Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0x9705a7113363A383c8A96689e20286AbE6612bb3
Balance 0 ETH
Nonce 1
Code Size 9694 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

9694 bytes
0x608060405234801561001057600080fd5b50600436106101cf5760003560e01c80636352211e116101045780638f17ae32116100a2578063bf7e214f11610071578063bf7e214f14610496578063c87b56dd146104b6578063e985e9c5146104c9578063fca3b5aa146104f757600080fd5b80638f17ae321461044857806395d89b4114610468578063a22cb46514610470578063b88d4fde1461048357600080fd5b806382295a2d116100de57806382295a2d146103ef5780638ad8d1d6146104025780638c73a042146104155780638da5cb5b1461042857600080fd5b80636352211e1461038657806370a08231146103bc5780637a9e5e4b146103dc57600080fd5b806323b872dd1161017157806341e42f301161014b57806341e42f301461033a57806342842e0e1461034d57806342966c681461036057806355f804b31461037357600080fd5b806323b872dd146102d55780632a55205a146102e85780633e4086e51461032757600080fd5b8063095ea7b3116101ad578063095ea7b31461026c57806313af403514610281578063197d3520146102945780631adbdf32146102a757600080fd5b806301ffc9a7146101d457806306fdde03146101fc578063081812fc14610211575b600080fd5b6101e76101e2366004611e0c565b61050a565b60405190151581526020015b60405180910390f35b61020461052a565b6040516101f39190611ea6565b61024761021f366004611eb9565b60046020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f3565b61027f61027a366004611ef4565b6105b8565b005b61027f61028f366004611f20565b6106ed565b61027f6102a2366004611f3d565b6107d8565b6102c76102b5366004611eb9565b600c6020526000908152604090205481565b6040519081526020016101f3565b61027f6102e3366004611f5f565b6108ba565b6102fb6102f6366004611f3d565b610b33565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152016101f3565b61027f610335366004611eb9565b610b76565b61027f610348366004611f20565b610bf5565b61027f61035b366004611f5f565b610cb6565b61027f61036e366004611eb9565b610e06565b61027f610381366004611fe9565b610ef0565b610247610394366004611eb9565b60036020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6102c76103ca366004611f20565b60026020526000908152604090205481565b61027f6103ea366004611f20565b610f76565b61027f6103fd36600461202b565b6110d3565b610204610410366004611eb9565b61116c565b61027f610423366004612077565b611185565b6008546102479073ffffffffffffffffffffffffffffffffffffffff1681565b6102c7610456366004611eb9565b600b6020526000908152604090205481565b61020461128e565b61027f61047e3660046120ba565b61129b565b61027f610491366004612122565b611332565b6009546102479073ffffffffffffffffffffffffffffffffffffffff1681565b6102046104c4366004611eb9565b611469565b6101e76104d7366004612220565b600560209081526000928352604080842090915290825290205460ff1681565b61027f610505366004611f20565b6114ce565b60006105158261158f565b80610524575061052482611670565b92915050565b600080546105379061224e565b80601f01602080910402602001604051908101604052809291908181526020018280546105639061224e565b80156105b05780601f10610585576101008083540402835291602001916105b0565b820191906000526020600020905b81548152906001019060200180831161059357829003601f168201915b505050505081565b60008181526003602052604090205473ffffffffffffffffffffffffffffffffffffffff163381148061061b575073ffffffffffffffffffffffffffffffffffffffff8116600090815260056020908152604080832033845290915290205460ff165b61066c5760405162461bcd60e51b815260206004820152600e60248201527f4e4f545f415554484f52495a454400000000000000000000000000000000000060448201526064015b60405180910390fd5b60008281526004602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff87811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b61071b336000357fffffffff0000000000000000000000000000000000000000000000000000000016611705565b6107675760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610663565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831690811790915560405133907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7690600090a350565b60008281526003602052604090205473ffffffffffffffffffffffffffffffffffffffff16331461084b5760405162461bcd60e51b815260206004820152600960248201527f4e4f545f4f574e455200000000000000000000000000000000000000000000006044820152606401610663565b6000828152600c602052604090205481116108a85760405162461bcd60e51b815260206004820152600b60248201527f43414e545f5245564552540000000000000000000000000000000000000000006044820152606401610663565b6000918252600c602052604090912055565b60008181526003602052604090205473ffffffffffffffffffffffffffffffffffffffff8481169116146109305760405162461bcd60e51b815260206004820152600a60248201527f57524f4e475f46524f4d000000000000000000000000000000000000000000006044820152606401610663565b73ffffffffffffffffffffffffffffffffffffffff82166109935760405162461bcd60e51b815260206004820152601160248201527f494e56414c49445f524543495049454e540000000000000000000000000000006044820152606401610663565b3373ffffffffffffffffffffffffffffffffffffffff841614806109da575060008181526004602052604090205473ffffffffffffffffffffffffffffffffffffffff1633145b80610a15575073ffffffffffffffffffffffffffffffffffffffff8316600090815260056020908152604080832033845290915290205460ff165b610a615760405162461bcd60e51b815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610663565b73ffffffffffffffffffffffffffffffffffffffff808416600081815260026020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019055938616808352848320805460010190558583526003825284832080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60075460065473ffffffffffffffffffffffffffffffffffffffff9091169060009061271090610b6390856122d1565b610b6d919061233d565b90509250929050565b610ba4336000357fffffffff0000000000000000000000000000000000000000000000000000000016611705565b610bf05760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610663565b600655565b610c23336000357fffffffff0000000000000000000000000000000000000000000000000000000016611705565b610c6f5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610663565b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610cc18383836108ba565b73ffffffffffffffffffffffffffffffffffffffff82163b1580610db557506040517f150b7a020000000000000000000000000000000000000000000000000000000080825233600483015273ffffffffffffffffffffffffffffffffffffffff858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015610d6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d919190612351565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b610e015760405162461bcd60e51b815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610663565b505050565b60008181526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1633811480610e5c575060008281526004602052604090205473ffffffffffffffffffffffffffffffffffffffff1633145b80610e97575073ffffffffffffffffffffffffffffffffffffffff8116600090815260056020908152604080832033845290915290205460ff165b610ee35760405162461bcd60e51b815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610663565b610eec82611816565b5050565b610f1e336000357fffffffff0000000000000000000000000000000000000000000000000000000016611705565b610f6a5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610663565b610e01600d8383611d24565b60085473ffffffffffffffffffffffffffffffffffffffff1633148061105957506009546040517fb70096130000000000000000000000000000000000000000000000000000000081523360048201523060248201526000357fffffffff0000000000000000000000000000000000000000000000000000000016604482015273ffffffffffffffffffffffffffffffffffffffff9091169063b700961390606401602060405180830381865afa158015611035573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611059919061236e565b61106257600080fd5b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831690811790915560405133907fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b7638998019890600090a350565b611101336000357fffffffff0000000000000000000000000000000000000000000000000000000016611705565b61114d5760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610663565b6000838152600a60205260409020611166908383611d24565b50505050565b600a60205260009081526040902080546105379061224e565b60085473ffffffffffffffffffffffffffffffffffffffff163314806111c25750600e5473ffffffffffffffffffffffffffffffffffffffff1633145b61120e5760405162461bcd60e51b815260206004820152600e60248201527f4e4f545f415554484f52495a45440000000000000000000000000000000000006044820152606401610663565b6000828152600b6020526040812054905b8281101561126457611252858284611239612710896122d1565b611243919061238b565b61124d919061238b565b611946565b8061125c816123a3565b91505061121f565b506000838152600b60205260408120805484929061128390849061238b565b909155505050505050565b600180546105379061224e565b33600081815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b61133d8484846108ba565b73ffffffffffffffffffffffffffffffffffffffff83163b158061141d57506040517f150b7a02000000000000000000000000000000000000000000000000000000008082529073ffffffffffffffffffffffffffffffffffffffff85169063150b7a02906113b69033908990889088906004016123dc565b6020604051808303816000875af11580156113d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f99190612351565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b6111665760405162461bcd60e51b815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610663565b606060006114796127108461233d565b6000818152600a60209081526040808320878452600c90925290912054919250600d916114a590611a8d565b6040516020016114b7939291906124f6565b604051602081830303815290604052915050919050565b6114fc336000357fffffffff0000000000000000000000000000000000000000000000000000000016611705565b6115485760405162461bcd60e51b815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152606401610663565b600e80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316148061162257507f80ac58cd000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b806105245750507fffffffff00000000000000000000000000000000000000000000000000000000167f5b5e139f000000000000000000000000000000000000000000000000000000001490565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614806105245750507fffffffff00000000000000000000000000000000000000000000000000000000167f2a55205a000000000000000000000000000000000000000000000000000000001490565b60095460009073ffffffffffffffffffffffffffffffffffffffff1680158015906117e957506040517fb700961300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527fffffffff000000000000000000000000000000000000000000000000000000008516604483015282169063b700961390606401602060405180830381865afa1580156117c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e9919061236e565b8061180e575060085473ffffffffffffffffffffffffffffffffffffffff8581169116145b949350505050565b60008181526003602052604090205473ffffffffffffffffffffffffffffffffffffffff16806118885760405162461bcd60e51b815260206004820152600a60248201527f4e4f545f4d494e544544000000000000000000000000000000000000000000006044820152606401610663565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260026020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190558583526003825280832080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811690915560049092528083208054909216909155518492907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b6119508282611bbf565b73ffffffffffffffffffffffffffffffffffffffff82163b1580611a4157506040517f150b7a0200000000000000000000000000000000000000000000000000000000808252336004830152600060248301819052604483018490526080606484015260848301529073ffffffffffffffffffffffffffffffffffffffff84169063150b7a029060a4016020604051808303816000875af11580156119f9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1d9190612351565b7fffffffff0000000000000000000000000000000000000000000000000000000016145b610eec5760405162461bcd60e51b815260206004820152601060248201527f554e534146455f524543495049454e54000000000000000000000000000000006044820152606401610663565b606081611acd57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611af75780611ae1816123a3565b9150611af09050600a8361233d565b9150611ad1565b60008167ffffffffffffffff811115611b1257611b126120f3565b6040519080825280601f01601f191660200182016040528015611b3c576020820181803683370190505b5090505b841561180e57611b5160018361254e565b9150611b5e600a86612565565b611b6990603061238b565b60f81b818381518110611b7e57611b7e612579565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611bb8600a8661233d565b9450611b40565b73ffffffffffffffffffffffffffffffffffffffff8216611c225760405162461bcd60e51b815260206004820152601160248201527f494e56414c49445f524543495049454e540000000000000000000000000000006044820152606401610663565b60008181526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1615611c945760405162461bcd60e51b815260206004820152600e60248201527f414c52454144595f4d494e5445440000000000000000000000000000000000006044820152606401610663565b73ffffffffffffffffffffffffffffffffffffffff8216600081815260026020908152604080832080546001019055848352600390915280822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b828054611d309061224e565b90600052602060002090601f016020900481019282611d525760008555611db6565b82601f10611d89578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00823516178555611db6565b82800160010185558215611db6579182015b82811115611db6578235825591602001919060010190611d9b565b50611dc2929150611dc6565b5090565b5b80821115611dc25760008155600101611dc7565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114611e0957600080fd5b50565b600060208284031215611e1e57600080fd5b8135611e2981611ddb565b9392505050565b60005b83811015611e4b578181015183820152602001611e33565b838111156111665750506000910152565b60008151808452611e74816020860160208601611e30565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611e296020830184611e5c565b600060208284031215611ecb57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff81168114611e0957600080fd5b60008060408385031215611f0757600080fd5b8235611f1281611ed2565b946020939093013593505050565b600060208284031215611f3257600080fd5b8135611e2981611ed2565b60008060408385031215611f5057600080fd5b50508035926020909101359150565b600080600060608486031215611f7457600080fd5b8335611f7f81611ed2565b92506020840135611f8f81611ed2565b929592945050506040919091013590565b60008083601f840112611fb257600080fd5b50813567ffffffffffffffff811115611fca57600080fd5b602083019150836020828501011115611fe257600080fd5b9250929050565b60008060208385031215611ffc57600080fd5b823567ffffffffffffffff81111561201357600080fd5b61201f85828601611fa0565b90969095509350505050565b60008060006040848603121561204057600080fd5b83359250602084013567ffffffffffffffff81111561205e57600080fd5b61206a86828701611fa0565b9497909650939450505050565b60008060006060848603121561208c57600080fd5b833561209781611ed2565b95602085013595506040909401359392505050565b8015158114611e0957600080fd5b600080604083850312156120cd57600080fd5b82356120d881611ed2565b915060208301356120e8816120ac565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000806080858703121561213857600080fd5b843561214381611ed2565b9350602085013561215381611ed2565b925060408501359150606085013567ffffffffffffffff8082111561217757600080fd5b818701915087601f83011261218b57600080fd5b81358181111561219d5761219d6120f3565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156121e3576121e36120f3565b816040528281528a60208487010111156121fc57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561223357600080fd5b823561223e81611ed2565b915060208301356120e881611ed2565b600181811c9082168061226257607f821691505b6020821081141561229c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612309576123096122a2565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261234c5761234c61230e565b500490565b60006020828403121561236357600080fd5b8151611e2981611ddb565b60006020828403121561238057600080fd5b8151611e29816120ac565b6000821982111561239e5761239e6122a2565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156123d5576123d56122a2565b5060010190565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152508360408301526080606083015261241b6080830184611e5c565b9695505050505050565b8054600090600181811c908083168061243f57607f831692505b602080841082141561247a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b81801561248e57600181146124bd576124ea565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008616895284890196506124ea565b60008881526020902060005b868110156124e25781548b8201529085019083016124c9565b505084890196505b50505050505092915050565b600061250b6125058387612425565b85612425565b7f2f0000000000000000000000000000000000000000000000000000000000000081528351612541816001840160208801611e30565b0160010195945050505050565b600082821015612560576125606122a2565b500390565b6000826125745761257461230e565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea2646970667358221220e7cf72724b9ab7b6720da8bf2c5ecf4d3546f880eb060908fac8bdda6329449f64736f6c634300080b0033

Verified Source Code Full Match

Compiler: v0.8.11+commit.d7f03943 EVM: london Optimization: Yes (10000 runs)
ERC2981V2.sol 27 lines
pragma solidity >=0.8.0;

/// @title Minimalist ERC2981 implementation.
/// @notice To be used within Quantum, as it was written for its needs.
/// @author exp.table
abstract contract ERC2981 {

    /// @dev one global fee for all royalties.
    uint256 internal _royaltyFee;
    /// @dev one global recipient for all royalties.
    address internal _royaltyRecipient;

    function royaltyInfo(uint256 tokenId, uint256 salePrice) public view virtual returns (
        address receiver,
        uint256 royaltyAmount
    ) {
        receiver = _royaltyRecipient;
        royaltyAmount = (salePrice * _royaltyFee) / 10000;
    }

    function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0x2a55205a; // ERC165 Interface ID for ERC2981
    }

}
QuantumKeyRing.sol 154 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;

import {ERC721 as ERC721S} from "@rari-capital/solmate/src/tokens/ERC721.sol";
import "@rari-capital/solmate/src/auth/Auth.sol";
import "@openzeppelin/contracts/utils/structs/BitMaps.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "./ERC2981V2.sol";

//                                                   
//                                                   
//                                  XXXXXXX          
//                               X XXXX XXXXXX       
//                             XXSXSXXXXXX XXXXX     
//                             XXXXX XX  XXXXXSXX    
//                           XXXX  XXXS SSXX XXXX    
//                           XXX XXXX     XXXXXX X   
//                          XXXXXXX X      XXX XXX  
//                          XXXXXXXX       XXXXXXX   
//                           SXX XXXXX    XXXSXXSX   
//                           XXXXXXXXX XXXXXXXXXX    
//                          SXXX X XX XXXXXX XXX  
//                       XXXXXX X XXX X X XSXX   
//                      SXXXXX X XXSXXXXS XX     
//                    XSXSX  XXXXXX            
//                   SXXX XXX XXXXX                  
//                 XXXXX SXXXXXX                     
//                SXXS  X XXXXX                      
//              XXXXXX X XSX X                       
//            XSXXX XX XXXXX                         
//          XXSXSSX XXXXXX                        
//        XSXXXSXXXXXXXXX                       
//        XXXXX XXXXXX   

/// @title The Quantum Key Ring. The keys do something.
/// @author exp.table
contract QuantumKeyRing is ERC721S, ERC2981, Auth {
    using Strings for uint256;
    using BitMaps for BitMaps.BitMap;

    /// >>>>>>>>>>>>>>>>>>>>>>>  STATE  <<<<<<<<<<<<<<<<<<<<<<<<<< ///

    mapping (uint256 => string) public keyCID;
    mapping (uint256 => uint256) public keySupply;
    mapping (uint256 => uint256) public tokenIdToSkinId;

    uint private constant _SEPARATOR = 10**4;
    string private _baseURI = "ipfs://";
    address private _minter;

    /// >>>>>>>>>>>>>>>>>>>>>  CONSTRUCTOR  <<<<<<<<<<<<<<<<<<<<<< ///

	/// @notice Deploys QuantumKeyRing
    /// @dev Initiates the Auth module with no authority and the sender as the owner
    /// @param owner The owner of the contract
    /// @param authority address of the deployed authority
    constructor(address owner, address authority) ERC721S("QuantumKeyRing", "QKR") Auth(owner, Authority(authority)) {
        _baseURI = "ipfs://";
    }

    /// >>>>>>>>>>>>>>>>>>>>>  RESTRICTED  <<<<<<<<<<<<<<<<<<<<<< ///

    /// @notice set address of the minter
    /// @param minter The address of the minter - should be QuantumKeyMaker
    function setMinter(address minter) public requiresAuth {
        _minter = minter;
    }

    /// @notice set the baseURI
    /// @param baseURI new base
    function setBaseURI(string calldata baseURI) public requiresAuth {
        _baseURI = baseURI;
    }

    /// @notice set the IPFS CID
    /// @param keyId The key id
    /// @param cid cid
    function setCID(uint256 keyId, string calldata cid) public requiresAuth {
        keyCID[keyId] = cid;
    }

    /// @notice sets the recipient of the royalties
    /// @param recipient address of the recipient
    function setRoyaltyRecipient(address recipient) public requiresAuth {
        _royaltyRecipient = recipient;
    }

    /// @notice sets the fee of royalties
    /// @dev The fee denominator is 10000 in BPS.
    /// @param fee fee
    /*
        Example

        This would set the fee at 5%
        ```
        keyRing.setRoyaltyFee(500)
        ```
    */
    function setRoyaltyFee(uint256 fee) public requiresAuth {
        _royaltyFee = fee;
    }

    /// >>>>>>>>>>>>>>>>>>>>>  VIEW  <<<<<<<<<<<<<<<<<<<<<< ///

    /// @notice Returns the URI of the token
    /// @param tokenId id of the token
    /// @return URI for the token ; expected to be ipfs://<cid>
    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        uint256 keyId = tokenId / _SEPARATOR;
        return string(abi.encodePacked(_baseURI, keyCID[keyId], "/" , tokenIdToSkinId[tokenId].toString()));
    }

    /// >>>>>>>>>>>>>>>>>>>>>  EXTERNAL  <<<<<<<<<<<<<<<<<<<<<< ///

    /// @notice Mints new keys
    /// @dev there is no check regarding limiting supply
    /// @param to recipient of newly minted tokens
    /// @param keyId id of the key
    /// @param amount amount to mint
    function make(address to, uint256 keyId, uint256 amount) public {
        require(msg.sender == owner || msg.sender == _minter, "NOT_AUTHORIZED");
        uint256 currSupply = keySupply[keyId];
        for(uint i; i < amount; i++) {
            _safeMint(to, (keyId * _SEPARATOR) +  currSupply + i);
        }
        keySupply[keyId] += amount;

    }

    /// @notice Burns key
    /// @dev Can be called by the owner or approved operator
    /// @param tokenId id of the tokens
    function burn(uint256 tokenId) public {
        address owner = ownerOf[tokenId];
        require(
            msg.sender == owner || msg.sender == getApproved[tokenId] || isApprovedForAll[owner][msg.sender],
            "NOT_AUTHORIZED"
        );
        _burn(tokenId);
    }

    /// @notice Applies a skin to a key
    /// @param tokenId id of the key
    /// @param skinId index of the skin
    function applySkin(uint256 tokenId, uint256 skinId) public {
        require(ownerOf[tokenId] == msg.sender, "NOT_OWNER");
        require(skinId > tokenIdToSkinId[tokenId], "CANT_REVERT");
        tokenIdToSkinId[tokenId] = skinId;
    }

    function supportsInterface(bytes4 interfaceId) public pure virtual override(ERC721S, ERC2981) returns (bool) {
        return ERC721S.supportsInterface(interfaceId) || ERC2981.supportsInterface(interfaceId);
    }
}
Auth.sol 64 lines
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Provides a flexible and updatable auth pattern which is completely separate from application logic.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Auth.sol)
/// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol)
abstract contract Auth {
    event OwnerUpdated(address indexed user, address indexed newOwner);

    event AuthorityUpdated(address indexed user, Authority indexed newAuthority);

    address public owner;

    Authority public authority;

    constructor(address _owner, Authority _authority) {
        owner = _owner;
        authority = _authority;

        emit OwnerUpdated(msg.sender, _owner);
        emit AuthorityUpdated(msg.sender, _authority);
    }

    modifier requiresAuth() {
        require(isAuthorized(msg.sender, msg.sig), "UNAUTHORIZED");

        _;
    }

    function isAuthorized(address user, bytes4 functionSig) internal view virtual returns (bool) {
        Authority auth = authority; // Memoizing authority saves us a warm SLOAD, around 100 gas.

        // Checking if the caller is the owner only after calling the authority saves gas in most cases, but be
        // aware that this makes protected functions uncallable even to the owner if the authority is out of order.
        return (address(auth) != address(0) && auth.canCall(user, address(this), functionSig)) || user == owner;
    }

    function setAuthority(Authority newAuthority) public virtual {
        // We check if the caller is the owner first because we want to ensure they can
        // always swap out the authority even if it's reverting or using up a lot of gas.
        require(msg.sender == owner || authority.canCall(msg.sender, address(this), msg.sig));

        authority = newAuthority;

        emit AuthorityUpdated(msg.sender, newAuthority);
    }

    function setOwner(address newOwner) public virtual requiresAuth {
        owner = newOwner;

        emit OwnerUpdated(msg.sender, newOwner);
    }
}

/// @notice A generic interface for a contract which provides authorization data to an Auth instance.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Auth.sol)
/// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol)
interface Authority {
    function canCall(
        address user,
        address target,
        bytes4 functionSig
    ) external view returns (bool);
}
Strings.sol 67 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}
ERC721.sol 216 lines
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)
/// @dev Note that balanceOf does not revert if passed the zero address, in defiance of the ERC.
abstract contract ERC721 {
    /*///////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    event Approval(address indexed owner, address indexed spender, uint256 indexed id);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /*///////////////////////////////////////////////////////////////
                          METADATA STORAGE/LOGIC
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    function tokenURI(uint256 id) public view virtual returns (string memory);

    /*///////////////////////////////////////////////////////////////
                            ERC721 STORAGE                        
    //////////////////////////////////////////////////////////////*/

    mapping(address => uint256) public balanceOf;

    mapping(uint256 => address) public ownerOf;

    mapping(uint256 => address) public getApproved;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*///////////////////////////////////////////////////////////////
                              CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
    }

    /*///////////////////////////////////////////////////////////////
                              ERC721 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 id) public virtual {
        address owner = ownerOf[id];

        require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");

        getApproved[id] = spender;

        emit Approval(owner, spender, id);
    }

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function transferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        require(from == ownerOf[id], "WRONG_FROM");

        require(to != address(0), "INVALID_RECIPIENT");

        require(
            msg.sender == from || msg.sender == getApproved[id] || isApprovedForAll[from][msg.sender],
            "NOT_AUTHORIZED"
        );

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        unchecked {
            balanceOf[from]--;

            balanceOf[to]++;
        }

        ownerOf[id] = to;

        delete getApproved[id];

        emit Transfer(from, to, id);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        bytes memory data
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    /*///////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
            interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
    }

    /*///////////////////////////////////////////////////////////////
                       INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 id) internal virtual {
        require(to != address(0), "INVALID_RECIPIENT");

        require(ownerOf[id] == address(0), "ALREADY_MINTED");

        // Counter overflow is incredibly unrealistic.
        unchecked {
            balanceOf[to]++;
        }

        ownerOf[id] = to;

        emit Transfer(address(0), to, id);
    }

    function _burn(uint256 id) internal virtual {
        address owner = ownerOf[id];

        require(ownerOf[id] != address(0), "NOT_MINTED");

        // Ownership check above ensures no underflow.
        unchecked {
            balanceOf[owner]--;
        }

        delete ownerOf[id];

        delete getApproved[id];

        emit Transfer(owner, address(0), id);
    }

    /*///////////////////////////////////////////////////////////////
                       INTERNAL SAFE MINT LOGIC
    //////////////////////////////////////////////////////////////*/

    function _safeMint(address to, uint256 id) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _safeMint(
        address to,
        uint256 id,
        bytes memory data
    ) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }
}

/// @notice A generic interface for a contract which properly accepts ERC721 tokens.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC721.sol)
interface ERC721TokenReceiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 id,
        bytes calldata data
    ) external returns (bytes4);
}
BitMaps.sol 55 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/structs/BitMaps.sol)
pragma solidity ^0.8.0;

/**
 * @dev Library for managing uint256 to bool mapping in a compact and efficient way, providing the keys are sequential.
 * Largelly inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor].
 */
library BitMaps {
    struct BitMap {
        mapping(uint256 => uint256) _data;
    }

    /**
     * @dev Returns whether the bit at `index` is set.
     */
    function get(BitMap storage bitmap, uint256 index) internal view returns (bool) {
        uint256 bucket = index >> 8;
        uint256 mask = 1 << (index & 0xff);
        return bitmap._data[bucket] & mask != 0;
    }

    /**
     * @dev Sets the bit at `index` to the boolean `value`.
     */
    function setTo(
        BitMap storage bitmap,
        uint256 index,
        bool value
    ) internal {
        if (value) {
            set(bitmap, index);
        } else {
            unset(bitmap, index);
        }
    }

    /**
     * @dev Sets the bit at `index`.
     */
    function set(BitMap storage bitmap, uint256 index) internal {
        uint256 bucket = index >> 8;
        uint256 mask = 1 << (index & 0xff);
        bitmap._data[bucket] |= mask;
    }

    /**
     * @dev Unsets the bit at `index`.
     */
    function unset(BitMap storage bitmap, uint256 index) internal {
        uint256 bucket = index >> 8;
        uint256 mask = 1 << (index & 0xff);
        bitmap._data[bucket] &= ~mask;
    }
}

Read Contract

authority 0xbf7e214f → address
balanceOf 0x70a08231 → uint256
getApproved 0x081812fc → address
isApprovedForAll 0xe985e9c5 → bool
keyCID 0x8ad8d1d6 → string
keySupply 0x8f17ae32 → uint256
name 0x06fdde03 → string
owner 0x8da5cb5b → address
ownerOf 0x6352211e → address
royaltyInfo 0x2a55205a → address, uint256
supportsInterface 0x01ffc9a7 → bool
symbol 0x95d89b41 → string
tokenIdToSkinId 0x1adbdf32 → uint256
tokenURI 0xc87b56dd → string

Write Contract 15 functions

These functions modify contract state and require a wallet transaction to execute.

applySkin 0x197d3520
uint256 tokenId
uint256 skinId
approve 0x095ea7b3
address spender
uint256 id
burn 0x42966c68
uint256 tokenId
make 0x8c73a042
address to
uint256 keyId
uint256 amount
safeTransferFrom 0x42842e0e
address from
address to
uint256 id
safeTransferFrom 0xb88d4fde
address from
address to
uint256 id
bytes data
setApprovalForAll 0xa22cb465
address operator
bool approved
setAuthority 0x7a9e5e4b
address newAuthority
setBaseURI 0x55f804b3
string baseURI
setCID 0x82295a2d
uint256 keyId
string cid
setMinter 0xfca3b5aa
address minter
setOwner 0x13af4035
address newOwner
setRoyaltyFee 0x3e4086e5
uint256 fee
setRoyaltyRecipient 0x41e42f30
address recipient
transferFrom 0x23b872dd
address from
address to
uint256 id

Recent Transactions

No transactions found for this address