Address Contract Verified
Address
0x61E3D1C26802DF805e9Fc22Dc26342e29eCFe860
Balance
0 ETH
Nonce
1
Code Size
19624 bytes
Creator
0xbFe2f826...C3c8 at tx 0x13ecf47d...40132c
Indexed Transactions
0
Contract Bytecode
19624 bytes
0x6080604052600436106102305760003560e01c80637d9128441161012e578063c87b56dd116100ab578063efd0cbf91161006f578063efd0cbf914610869578063f2fde38b14610885578063f3fef3a3146108ae578063f5aa406d146108d7578063fc1a1c361461090057610230565b8063c87b56dd14610770578063c95d83c6146107ad578063cfe1908d146107d6578063d5abeb0114610801578063e985e9c51461082c57610230565b8063a6d612f9116100f2578063a6d612f9146106bb578063a945bf80146106d7578063b88d4fde14610702578063bc63f02e1461072b578063c62752551461074757610230565b80637d912844146105d45780637e9845f5146106115780638da5cb5b1461063c57806395d89b4114610667578063a22cb4651461069257610230565b806342842e0e116101bc5780636352211e116101805780636352211e146104dd57806366cc5f0d1461051a5780636f8b44b01461054557806370a082311461056e578063717d57d3146105ab57610230565b806342842e0e146103fa5780634f6ccce71461042357806355f804b3146104605780635a67de0714610489578063603f4d52146104b257610230565b8063095ea7b311610203578063095ea7b31461030357806318160ddd1461032c57806323b872dd146103575780632f745c59146103805780633a602b4d146103bd57610230565b806301ffc9a71461023557806302c366bc1461027257806306fdde031461029b578063081812fc146102c6575b600080fd5b34801561024157600080fd5b5061025c6004803603810190610257919061367a565b61092b565b60405161026991906136c2565b60405180910390f35b34801561027e57600080fd5b5061029960048036038101906102949190613713565b610acd565b005b3480156102a757600080fd5b506102b0610b54565b6040516102bd91906137d0565b60405180910390f35b3480156102d257600080fd5b506102ed60048036038101906102e89190613713565b610be2565b6040516102fa9190613833565b60405180910390f35b34801561030f57600080fd5b5061032a6004803603810190610325919061387a565b610c15565b005b34801561033857600080fd5b50610341610dec565b60405161034e91906138c9565b60405180910390f35b34801561036357600080fd5b5061037e600480360381019061037991906138e4565b610dfb565b005b34801561038c57600080fd5b506103a760048036038101906103a2919061387a565b610fdd565b6040516103b491906138c9565b60405180910390f35b3480156103c957600080fd5b506103e460048036038101906103df9190613937565b6110c8565b6040516103f191906138c9565b60405180910390f35b34801561040657600080fd5b50610421600480360381019061041c91906138e4565b6110e0565b005b34801561042f57600080fd5b5061044a60048036038101906104459190613713565b6112c2565b60405161045791906138c9565b60405180910390f35b34801561046c57600080fd5b5061048760048036038101906104829190613a99565b611323565b005b34801561049557600080fd5b506104b060048036038101906104ab9190613b07565b6113ac565b005b3480156104be57600080fd5b506104c7611456565b6040516104d49190613bab565b60405180910390f35b3480156104e957600080fd5b5061050460048036038101906104ff9190613713565b611469565b6040516105119190613833565b60405180910390f35b34801561052657600080fd5b5061052f6114c7565b60405161053c91906138c9565b60405180910390f35b34801561055157600080fd5b5061056c60048036038101906105679190613713565b6114cd565b005b34801561057a57600080fd5b5061059560048036038101906105909190613937565b6115e7565b6040516105a291906138c9565b60405180910390f35b3480156105b757600080fd5b506105d260048036038101906105cd9190613713565b6115f9565b005b3480156105e057600080fd5b506105fb60048036038101906105f69190613cc4565b611680565b60405161060891906138c9565b60405180910390f35b34801561061d57600080fd5b506106266117df565b60405161063391906138c9565b60405180910390f35b34801561064857600080fd5b506106516117f5565b60405161065e9190613833565b60405180910390f35b34801561067357600080fd5b5061067c61181f565b60405161068991906137d0565b60405180910390f35b34801561069e57600080fd5b506106b960048036038101906106b49190613d5f565b6118ad565b005b6106d560048036038101906106d09190613d9f565b611a20565b005b3480156106e357600080fd5b506106ec611c6e565b6040516106f991906138c9565b60405180910390f35b34801561070e57600080fd5b5061072960048036038101906107249190613e9c565b611c74565b005b61074560048036038101906107409190613f1f565b611e59565b005b34801561075357600080fd5b5061076e60048036038101906107699190613713565b611faf565b005b34801561077c57600080fd5b5061079760048036038101906107929190613713565b612036565b6040516107a491906137d0565b60405180910390f35b3480156107b957600080fd5b506107d460048036038101906107cf9190613713565b6120db565b005b3480156107e257600080fd5b506107eb612162565b6040516107f891906138c9565b60405180910390f35b34801561080d57600080fd5b50610816612168565b60405161082391906138c9565b60405180910390f35b34801561083857600080fd5b50610853600480360381019061084e9190613f5f565b61216e565b60405161086091906136c2565b60405180910390f35b610883600480360381019061087e9190613713565b612182565b005b34801561089157600080fd5b506108ac60048036038101906108a79190613937565b612406565b005b3480156108ba57600080fd5b506108d560048036038101906108d0919061387a565b612549565b005b3480156108e357600080fd5b506108fe60048036038101906108f99190613f9f565b612709565b005b34801561090c57600080fd5b50610915612792565b60405161092291906138c9565b60405180910390f35b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806109f657507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610a5e57507f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610ac657507f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60003390508073ffffffffffffffffffffffffffffffffffffffff16610af16117f5565b73ffffffffffffffffffffffffffffffffffffffff1614610b4957806040517f55932a1b000000000000000000000000000000000000000000000000000000008152600401610b409190613833565b60405180910390fd5b81600d819055505050565b60018054610b6190613ffb565b80601f0160208091040260200160405190810160405280929190818152602001828054610b8d90613ffb565b8015610bda5780601f10610baf57610100808354040283529160200191610bda565b820191906000526020600020905b815481529060010190602001808311610bbd57829003601f168201915b505050505081565b60036020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b80610c1f81612798565b610c6057806040517f1cf4d9a4000000000000000000000000000000000000000000000000000000008152600401610c5791906138c9565b60405180910390fd5b60003390506000610c70846127b7565b90508073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603610ce257846040517ff2b21e1c000000000000000000000000000000000000000000000000000000008152600401610cd99190613833565b60405180910390fd5b6000610cef82848761287d565b905080610d37578183866040517f19f48dff000000000000000000000000000000000000000000000000000000008152600401610d2e9392919061402c565b60405180910390fd5b856003600087815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550848673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050505050565b6000610df6612936565b905090565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115610fcb573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610e6d57610e68848484612945565b610fd7565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401610eb6929190614063565b602060405180830381865afa158015610ed3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef791906140a1565b8015610f8957506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401610f47929190614063565b602060405180830381865afa158015610f64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8891906140a1565b5b610fca57336040517fede71dcc000000000000000000000000000000000000000000000000000000008152600401610fc19190613833565b60405180910390fd5b5b610fd6848484612945565b5b50505050565b6000610fe883612ae5565b821061102d5782826040517f374f8b4f0000000000000000000000000000000000000000000000000000000081526004016110249291906140ce565b60405180910390fd5b600080600190505b6000548110156110bf5761104881612798565b80156110875750611058816127b7565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16145b156110ac5781840361109d5780925050506110c2565b81806110a890614126565b9250505b80806110b790614126565b915050611035565b50505b92915050565b60106020528060005260406000206000915090505481565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156112b0573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036111525761114d848484612c42565b6112bc565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b815260040161119b929190614063565b602060405180830381865afa1580156111b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111dc91906140a1565b801561126e57506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b815260040161122c929190614063565b602060405180830381865afa158015611249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061126d91906140a1565b5b6112af57336040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016112a69190613833565b60405180910390fd5b5b6112bb848484612c42565b5b50505050565b60006112cc6117df565b821061130f57816040517f125c19b000000000000000000000000000000000000000000000000000000000815260040161130691906138c9565b60405180910390fd5b60018261131c919061416e565b9050919050565b60003390508073ffffffffffffffffffffffffffffffffffffffff166113476117f5565b73ffffffffffffffffffffffffffffffffffffffff161461139f57806040517f55932a1b0000000000000000000000000000000000000000000000000000000081526004016113969190613833565b60405180910390fd5b6113a882612c62565b5050565b60003390508073ffffffffffffffffffffffffffffffffffffffff166113d06117f5565b73ffffffffffffffffffffffffffffffffffffffff161461142857806040517f55932a1b00000000000000000000000000000000000000000000000000000000815260040161141f9190613833565b60405180910390fd5b81600f60006101000a81548160ff0219169083600281111561144d5761144c613b34565b5b02179055505050565b600f60009054906101000a900460ff1681565b60008161147581612798565b6114b657806040517f1cf4d9a40000000000000000000000000000000000000000000000000000000081526004016114ad91906138c9565b60405180910390fd5b6114bf836127b7565b915050919050565b600c5481565b60003390508073ffffffffffffffffffffffffffffffffffffffff166114f16117f5565b73ffffffffffffffffffffffffffffffffffffffff161461154957806040517f55932a1b0000000000000000000000000000000000000000000000000000000081526004016115409190613833565b60405180910390fd5b6000611553610dec565b9050808311611597576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161158e90614214565b60405180910390fd5b600e5483106115db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115d2906142a6565b60405180910390fd5b82600e81905550505050565b60006115f282612ae5565b9050919050565b60003390508073ffffffffffffffffffffffffffffffffffffffff1661161d6117f5565b73ffffffffffffffffffffffffffffffffffffffff161461167557806040517f55932a1b00000000000000000000000000000000000000000000000000000000815260040161166c9190613833565b60405180910390fd5b81600a819055505050565b60008060001b600754036116c0576040517f93dff14200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81600860008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541061174357836040517f6acdb09500000000000000000000000000000000000000000000000000000000815260040161173a9190613833565b60405180910390fd5b61174d8484612c75565b61178e57836040517f186a628d0000000000000000000000000000000000000000000000000000000081526004016117859190613833565b60405180910390fd5b6000600860008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205483039050809150509392505050565b600060016000546117f091906142c6565b905090565b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6002805461182c90613ffb565b80601f016020809104026020016040519081016040528092919081815260200182805461185890613ffb565b80156118a55780601f1061187a576101008083540402835291602001916118a5565b820191906000526020600020905b81548152906001019060200180831161188857829003601f168201915b505050505081565b60003390508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160361192257826040517ff2b21e1c0000000000000000000000000000000000000000000000000000000081526004016119199190613833565b60405180910390fd5b81600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3184604051611a1391906136c2565b60405180910390a3505050565b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614611a8e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a8590614346565b60405180910390fd5b6001806002811115611aa357611aa2613b34565b5b600f60009054906101000a900460ff166002811115611ac557611ac4613b34565b5b14611b05576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611afc906143b2565b60405180910390fd5b3383600c548481811115611b5057836040517f186a628d000000000000000000000000000000000000000000000000000000008152600401611b479190613833565b60405180910390fd5b6000611b5d858585611680565b905081811015611ba457846040517f186a628d000000000000000000000000000000000000000000000000000000008152600401611b9b9190613833565b60405180910390fd5b6000611bae610dec565b9050600e548882611bbf919061416e565b1115611c00576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bf79061441e565b60405180910390fd5b600a5488611c0e919061443e565b3414611c4f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c46906144cc565b60405180910390fd5b611c593389612cb8565b611c633389612e73565b505050505050505050565b600b5481565b8360006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115611e45573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ce757611ce285858585612ec4565b611e52565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401611d30929190614063565b602060405180830381865afa158015611d4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7191906140a1565b8015611e0357506daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401611dc1929190614063565b602060405180830381865afa158015611dde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e0291906140a1565b5b611e4457336040517fede71dcc000000000000000000000000000000000000000000000000000000008152600401611e3b9190613833565b60405180910390fd5b5b611e5185858585612ec4565b5b5050505050565b60003390508073ffffffffffffffffffffffffffffffffffffffff16611e7d6117f5565b73ffffffffffffffffffffffffffffffffffffffff1614611ed557806040517f55932a1b000000000000000000000000000000000000000000000000000000008152600401611ecc9190613833565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff1614611f43576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f3a90614346565b60405180910390fd5b6000611f4d610dec565b9050600e548482611f5e919061416e565b1115611f9f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f969061441e565b60405180910390fd5b611fa98385612cb8565b50505050565b60003390508073ffffffffffffffffffffffffffffffffffffffff16611fd36117f5565b73ffffffffffffffffffffffffffffffffffffffff161461202b57806040517f55932a1b0000000000000000000000000000000000000000000000000000000081526004016120229190613833565b60405180910390fd5b81600b819055505050565b60608161204281612798565b61208357806040517f1cf4d9a400000000000000000000000000000000000000000000000000000000815260040161207a91906138c9565b60405180910390fd5b60006006805461209290613ffb565b9050116120a7576120a283612f22565b6120d3565b60066120b284612f22565b6040516020016120c39291906145c0565b6040516020818303038152906040525b915050919050565b60003390508073ffffffffffffffffffffffffffffffffffffffff166120ff6117f5565b73ffffffffffffffffffffffffffffffffffffffff161461215757806040517f55932a1b00000000000000000000000000000000000000000000000000000000815260040161214e9190613833565b60405180910390fd5b81600c819055505050565b600d5481565b600e5481565b600061217a8383613082565b905092915050565b3373ffffffffffffffffffffffffffffffffffffffff163273ffffffffffffffffffffffffffffffffffffffff16146121f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121e790614346565b60405180910390fd5b600280600281111561220557612204613b34565b5b600f60009054906101000a900460ff16600281111561222757612226613b34565b5b14612267576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161225e906143b2565b60405180910390fd5b6000612271610dec565b9050600d5483601060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546122c1919061416e565b1115612302576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122f990614630565b60405180910390fd5b600e548382612311919061416e565b1115612352576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123499061441e565b60405180910390fd5b600b5483612360919061443e565b34146123a1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612398906144cc565b60405180910390fd5b6123ab3384612cb8565b82601060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546123fa919061416e565b92505081905550505050565b60003390508073ffffffffffffffffffffffffffffffffffffffff1661242a6117f5565b73ffffffffffffffffffffffffffffffffffffffff161461248257806040517f55932a1b0000000000000000000000000000000000000000000000000000000081526004016124799190613833565b60405180910390fd5b6000600960009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905082600960006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3505050565b60003390508073ffffffffffffffffffffffffffffffffffffffff1661256d6117f5565b73ffffffffffffffffffffffffffffffffffffffff16146125c557806040517f55932a1b0000000000000000000000000000000000000000000000000000000081526004016125bc9190613833565b60405180910390fd5b60004790506000811161260d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126049061469c565b60405180910390fd5b80831115612650576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161264790614708565b60405180910390fd5b600084905060008173ffffffffffffffffffffffffffffffffffffffff168560405161267b90614759565b60006040518083038185875af1925050503d80600081146126b8576040519150601f19603f3d011682016040523d82523d6000602084013e6126bd565b606091505b5050905080612701576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126f8906147ba565b60405180910390fd5b505050505050565b60003390508073ffffffffffffffffffffffffffffffffffffffff1661272d6117f5565b73ffffffffffffffffffffffffffffffffffffffff161461278557806040517f55932a1b00000000000000000000000000000000000000000000000000000000815260040161277c9190613833565b60405180910390fd5b61278e82613116565b5050565b600a5481565b60008082036127aa57600090506127b2565b600054821090505b919050565b60008082905060006005600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612873578180612835906147da565b9250506005600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506127f6565b8092505050919050565b6000808473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061291857506003600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b8061292957506129288585613082565b5b9050809150509392505050565b60006129406117df565b905090565b8061294f81612798565b61299057806040517f1cf4d9a400000000000000000000000000000000000000000000000000000000815260040161298791906138c9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036129f6576040517f14242cb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60003390506000612a06846127b7565b90508073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614612a7c578086856040517fe02b28e7000000000000000000000000000000000000000000000000000000008152600401612a739392919061402c565b60405180910390fd5b6000612a8982848761287d565b905080612ad1578183866040517f19f48dff000000000000000000000000000000000000000000000000000000008152600401612ac89392919061402c565b60405180910390fd5b612adc828787613120565b50505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612b235760009050612c3d565b60008080600190505b600054811015612c3657612b3f81612798565b15612c2557600073ffffffffffffffffffffffffffffffffffffffff166005600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612be2576005600082815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505b8173ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603612c24578280612c2090614126565b9350505b5b80612c2f90614126565b9050612b2c565b5081925050505b919050565b612c5d83838360405180602001604052806000815250611c74565b505050565b8060069081612c71919061499a565b5050565b60008083604051602001612c899190614ab4565b604051602081830303815290604052805190602001209050600754612cae8483613408565b1491505092915050565b60008054905060008282612ccc919061416e565b90506000600182612cdd91906142c6565b9050846005600085815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082811115612d8c57846005600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b81600081905550612daf600086856040518060200160405280600081525061345e565b612df057846040517f015be56a000000000000000000000000000000000000000000000000000000008152600401612de79190613833565b60405180910390fd5b60008390505b82811015612e6b57808673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a480612e6490614126565b9050612df6565b505050505050565b80600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505050565b612ecf848484610dfb565b612edb8484848461345e565b612f1c57826040517f015be56a000000000000000000000000000000000000000000000000000000008152600401612f139190613833565b60405180910390fd5b50505050565b606060008203612f69576040518060400160405280600181526020017f3000000000000000000000000000000000000000000000000000000000000000815250905061307d565b600082905060005b60008214612f9b578080612f8490614126565b915050600a82612f949190614afe565b9150612f71565b60008167ffffffffffffffff811115612fb757612fb661396e565b5b6040519080825280601f01601f191660200182016040528015612fe95781602001600182028036833780820191505090505b5090505b600085146130765760018261300291906142c6565b9150600a856130119190614b2f565b603061301d919061416e565b60f81b81838151811061303357613032614b60565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a8561306f9190614afe565b9450612fed565b8093505050505b919050565b6000600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b8060078190555050565b60006003600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600060018211613184576001613192565b60018261319191906142c6565b5b905060006001836131a3919061416e565b9050600083831080156131bb57506131ba83612798565b5b80156132265750600073ffffffffffffffffffffffffffffffffffffffff166005600085815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b9050600061323383612798565b801561329e5750600073ffffffffffffffffffffffffffffffffffffffff166005600085815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b905081156132f957866005600086815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b801561335257866005600085815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b856005600087815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550848673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a450505050505050565b60008082905060005b84518110156134535761343e8286838151811061343157613430614b60565b5b60200260200101516135cc565b9150808061344b90614126565b915050613411565b508091505092915050565b600080843b905060008111156135be578473ffffffffffffffffffffffffffffffffffffffff1663150b7a02338887876040518563ffffffff1660e01b81526004016134ad9493929190614be4565b6020604051808303816000875af19250505080156134e957506040513d601f19601f820116820180604052508101906134e69190614c45565b60015b61356d573d8060008114613519576040519150601f19603f3d011682016040523d82523d6000602084013e61351e565b606091505b50600081510361356557856040517f015be56a00000000000000000000000000000000000000000000000000000000815260040161355c9190613833565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614925050506135c4565b60019150505b949350505050565b60008183106135e4576135df82846135f7565b6135ef565b6135ee83836135f7565b5b905092915050565b600082600052816020526040600020905092915050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61365781613622565b811461366257600080fd5b50565b6000813590506136748161364e565b92915050565b6000602082840312156136905761368f613618565b5b600061369e84828501613665565b91505092915050565b60008115159050919050565b6136bc816136a7565b82525050565b60006020820190506136d760008301846136b3565b92915050565b6000819050919050565b6136f0816136dd565b81146136fb57600080fd5b50565b60008135905061370d816136e7565b92915050565b60006020828403121561372957613728613618565b5b6000613737848285016136fe565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561377a57808201518184015260208101905061375f565b60008484015250505050565b6000601f19601f8301169050919050565b60006137a282613740565b6137ac818561374b565b93506137bc81856020860161375c565b6137c581613786565b840191505092915050565b600060208201905081810360008301526137ea8184613797565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061381d826137f2565b9050919050565b61382d81613812565b82525050565b60006020820190506138486000830184613824565b92915050565b61385781613812565b811461386257600080fd5b50565b6000813590506138748161384e565b92915050565b6000806040838503121561389157613890613618565b5b600061389f85828601613865565b92505060206138b0858286016136fe565b9150509250929050565b6138c3816136dd565b82525050565b60006020820190506138de60008301846138ba565b92915050565b6000806000606084860312156138fd576138fc613618565b5b600061390b86828701613865565b935050602061391c86828701613865565b925050604061392d868287016136fe565b9150509250925092565b60006020828403121561394d5761394c613618565b5b600061395b84828501613865565b91505092915050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6139a682613786565b810181811067ffffffffffffffff821117156139c5576139c461396e565b5b80604052505050565b60006139d861360e565b90506139e4828261399d565b919050565b600067ffffffffffffffff821115613a0457613a0361396e565b5b613a0d82613786565b9050602081019050919050565b82818337600083830152505050565b6000613a3c613a37846139e9565b6139ce565b905082815260208101848484011115613a5857613a57613969565b5b613a63848285613a1a565b509392505050565b600082601f830112613a8057613a7f613964565b5b8135613a90848260208601613a29565b91505092915050565b600060208284031215613aaf57613aae613618565b5b600082013567ffffffffffffffff811115613acd57613acc61361d565b5b613ad984828501613a6b565b91505092915050565b60038110613aef57600080fd5b50565b600081359050613b0181613ae2565b92915050565b600060208284031215613b1d57613b1c613618565b5b6000613b2b84828501613af2565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60038110613b7457613b73613b34565b5b50565b6000819050613b8582613b63565b919050565b6000613b9582613b77565b9050919050565b613ba581613b8a565b82525050565b6000602082019050613bc06000830184613b9c565b92915050565b600067ffffffffffffffff821115613be157613be061396e565b5b602082029050602081019050919050565b600080fd5b6000819050919050565b613c0a81613bf7565b8114613c1557600080fd5b50565b600081359050613c2781613c01565b92915050565b6000613c40613c3b84613bc6565b6139ce565b90508083825260208201905060208402830185811115613c6357613c62613bf2565b5b835b81811015613c8c5780613c788882613c18565b845260208401935050602081019050613c65565b5050509392505050565b600082601f830112613cab57613caa613964565b5b8135613cbb848260208601613c2d565b91505092915050565b600080600060608486031215613cdd57613cdc613618565b5b6000613ceb86828701613865565b935050602084013567ffffffffffffffff811115613d0c57613d0b61361d565b5b613d1886828701613c96565b9250506040613d29868287016136fe565b9150509250925092565b613d3c816136a7565b8114613d4757600080fd5b50565b600081359050613d5981613d33565b92915050565b60008060408385031215613d7657613d75613618565b5b6000613d8485828601613865565b9250506020613d9585828601613d4a565b9150509250929050565b60008060408385031215613db657613db5613618565b5b600083013567ffffffffffffffff811115613dd457613dd361361d565b5b613de085828601613c96565b9250506020613df1858286016136fe565b9150509250929050565b600067ffffffffffffffff821115613e1657613e1561396e565b5b613e1f82613786565b9050602081019050919050565b6000613e3f613e3a84613dfb565b6139ce565b905082815260208101848484011115613e5b57613e5a613969565b5b613e66848285613a1a565b509392505050565b600082601f830112613e8357613e82613964565b5b8135613e93848260208601613e2c565b91505092915050565b60008060008060808587031215613eb657613eb5613618565b5b6000613ec487828801613865565b9450506020613ed587828801613865565b9350506040613ee6878288016136fe565b925050606085013567ffffffffffffffff811115613f0757613f0661361d565b5b613f1387828801613e6e565b91505092959194509250565b60008060408385031215613f3657613f35613618565b5b6000613f44858286016136fe565b9250506020613f5585828601613865565b9150509250929050565b60008060408385031215613f7657613f75613618565b5b6000613f8485828601613865565b9250506020613f9585828601613865565b9150509250929050565b600060208284031215613fb557613fb4613618565b5b6000613fc384828501613c18565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061401357607f821691505b60208210810361402657614025613fcc565b5b50919050565b60006060820190506140416000830186613824565b61404e6020830185613824565b61405b60408301846138ba565b949350505050565b60006040820190506140786000830185613824565b6140856020830184613824565b9392505050565b60008151905061409b81613d33565b92915050565b6000602082840312156140b7576140b6613618565b5b60006140c58482850161408c565b91505092915050565b60006040820190506140e36000830185613824565b6140f060208301846138ba565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614131826136dd565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614163576141626140f7565b5b600182019050919050565b6000614179826136dd565b9150614184836136dd565b925082820190508082111561419c5761419b6140f7565b5b92915050565b7f4d617820737570706c792073686f756c6420626520677265617465722074686160008201527f6e2063757272656e7420737570706c7900000000000000000000000000000000602082015250565b60006141fe60308361374b565b9150614209826141a2565b604082019050919050565b6000602082019050818103600083015261422d816141f1565b9050919050565b7f4d617820737570706c792073686f756c6420626520677265617465722074686160008201527f6e2070726576696f7573206d617820737570706c790000000000000000000000602082015250565b600061429060358361374b565b915061429b82614234565b604082019050919050565b600060208201905081810360008301526142bf81614283565b9050919050565b60006142d1826136dd565b91506142dc836136dd565b92508282039050818111156142f4576142f36140f7565b5b92915050565b7f4e6f20736d61727420636f6e7472616374732061726520616c6c6f7765640000600082015250565b6000614330601e8361374b565b915061433b826142fa565b602082019050919050565b6000602082019050818103600083015261435f81614323565b9050919050565b7f53616c65206e6f74206163746976650000000000000000000000000000000000600082015250565b600061439c600f8361374b565b91506143a782614366565b602082019050919050565b600060208201905081810360008301526143cb8161438f565b9050919050565b7f4578636565647320737570706c79000000000000000000000000000000000000600082015250565b6000614408600e8361374b565b9150614413826143d2565b602082019050919050565b60006020820190508181036000830152614437816143fb565b9050919050565b6000614449826136dd565b9150614454836136dd565b9250828202614462816136dd565b91508282048414831517614479576144786140f7565b5b5092915050565b7f45746865722073656e74206973206e6f7420636f727265637400000000000000600082015250565b60006144b660198361374b565b91506144c182614480565b602082019050919050565b600060208201905081810360008301526144e5816144a9565b9050919050565b600081905092915050565b60008190508160005260206000209050919050565b6000815461451981613ffb565b61452381866144ec565b9450600182166000811461453e576001811461455357614586565b60ff1983168652811515820286019350614586565b61455c856144f7565b60005b8381101561457e5781548189015260018201915060208101905061455f565b838801955050505b50505092915050565b600061459a82613740565b6145a481856144ec565b93506145b481856020860161375c565b80840191505092915050565b60006145cc828561450c565b91506145d8828461458f565b91508190509392505050565b7f45786365656473206d696e74207065722077616c6c6574000000000000000000600082015250565b600061461a60178361374b565b9150614625826145e4565b602082019050919050565b600060208201905081810360008301526146498161460d565b9050919050565b7f4e6f2062616c616e636520746f20776974686472617700000000000000000000600082015250565b600061468660168361374b565b915061469182614650565b602082019050919050565b600060208201905081810360008301526146b581614679565b9050919050565b7f416d6f756e74206973206e6f742076616c696400000000000000000000000000600082015250565b60006146f260138361374b565b91506146fd826146bc565b602082019050919050565b60006020820190508181036000830152614721816146e5565b9050919050565b600081905092915050565b50565b6000614743600083614728565b915061474e82614733565b600082019050919050565b600061476482614736565b9150819050919050565b7f5472616e73616374696f6e206661696c65640000000000000000000000000000600082015250565b60006147a460128361374b565b91506147af8261476e565b602082019050919050565b600060208201905081810360008301526147d381614797565b9050919050565b60006147e5826136dd565b9150600082036147f8576147f76140f7565b5b600182039050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026148507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614813565b61485a8683614813565b95508019841693508086168417925050509392505050565b6000819050919050565b600061489761489261488d846136dd565b614872565b6136dd565b9050919050565b6000819050919050565b6148b18361487c565b6148c56148bd8261489e565b848454614820565b825550505050565b600090565b6148da6148cd565b6148e58184846148a8565b505050565b5b81811015614909576148fe6000826148d2565b6001810190506148eb565b5050565b601f82111561494e5761491f816144f7565b61492884614803565b81016020851015614937578190505b61494b61494385614803565b8301826148ea565b50505b505050565b600082821c905092915050565b600061497160001984600802614953565b1980831691505092915050565b600061498a8383614960565b9150826002028217905092915050565b6149a382613740565b67ffffffffffffffff8111156149bc576149bb61396e565b5b6149c68254613ffb565b6149d182828561490d565b600060209050601f831160018114614a0457600084156149f2578287015190505b6149fc858261497e565b865550614a64565b601f198416614a12866144f7565b60005b82811015614a3a57848901518255600182019150602085019450602081019050614a15565b86831015614a575784890151614a53601f891682614960565b8355505b6001600288020188555050505b505050505050565b60008160601b9050919050565b6000614a8482614a6c565b9050919050565b6000614a9682614a79565b9050919050565b614aae614aa982613812565b614a8b565b82525050565b6000614ac08284614a9d565b60148201915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000614b09826136dd565b9150614b14836136dd565b925082614b2457614b23614acf565b5b828204905092915050565b6000614b3a826136dd565b9150614b45836136dd565b925082614b5557614b54614acf565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050919050565b600082825260208201905092915050565b6000614bb682614b8f565b614bc08185614b9a565b9350614bd081856020860161375c565b614bd981613786565b840191505092915050565b6000608082019050614bf96000830187613824565b614c066020830186613824565b614c1360408301856138ba565b8181036060830152614c258184614bab565b905095945050505050565b600081519050614c3f8161364e565b92915050565b600060208284031215614c5b57614c5a613618565b5b6000614c6984828501614c30565b9150509291505056fea2646970667358221220f421f832a83304ef944ee0444694434aa2fe84d630e552f4a840794ae955487b64736f6c63430008110033
Verified Source Code Full Match
Compiler: v0.8.17+commit.8df45f5f
EVM: london
Optimization: No
IERC173.sol 21 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
/**
* @dev Required interface of an ERC173 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-173[EIP].
*/
interface IERC173 /* is IERC165 */ {
/// @dev This emits when ownership of a contract changes.
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/// @notice Get the address of the owner
/// @return The address of the owner.
function owner() view external returns(address);
/// @notice Set the address of the new owner of the contract
/// @dev Set _newOwner to address(0) to renounce any ownership.
/// @param _newOwner The address of the new owner of the contract
function transferOwnership(address _newOwner) external;
}
IERC721Enumerable.sol 29 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
/// @dev See https://eips.ethereum.org/EIPS/eip-721
/// Note: the ERC-165 identifier for this interface is 0x780e9d63.
interface IERC721Enumerable /* is IERC721 */ {
/// @notice Count NFTs tracked by this contract
/// @return A count of valid NFTs tracked by this contract, where each one of
/// them has an assigned and queryable owner not equal to the zero address
function totalSupply() external view returns ( uint256 );
/// @notice Enumerate valid NFTs
/// @dev Throws if `index_` >= `totalSupply()`.
/// @param index_ A counter less than `totalSupply()`
/// @return The token identifier for the `index_`th NFT,
/// (sort order not specified)
function tokenByIndex( uint256 index_ ) external view returns ( uint256 );
/// @notice Enumerate NFTs assigned to an owner
/// @dev Throws if `index_` >= `balanceOf(owner_)` or if
/// `owner_` is the zero address, representing invalid NFTs.
/// @param owner_ An address where we are interested in NFTs owned by them
/// @param index_ A counter less than `balanceOf(owner_)`
/// @return The token identifier for the `index_`th NFT assigned to `owner_`,
/// (sort order not specified)
function tokenOfOwnerByIndex( address owner_, uint256 index_ ) external view returns ( uint256 );
}
IERC721Receiver.sol 20 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02.
interface IERC721Receiver {
/// @notice Handle the receipt of an NFT
/// @dev The ERC721 smart contract calls this function on the recipient
/// after a `transfer`. This function MAY throw to revert and reject the
/// transfer. Return of other than the magic value MUST result in the
/// transaction being reverted.
/// Note: the contract address is always the message sender.
/// @param operator_ The address which called `safeTransferFrom` function
/// @param from_ The address which previously owned the token
/// @param tokenId_ The NFT identifier which is being transferred
/// @param data_ Additional data with no specified format
/// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
/// unless throwing
function onERC721Received( address operator_, address from_, uint256 tokenId_, bytes calldata data_ ) external returns( bytes4 );
}
Reg_ERC721Batch.sol 613 lines
// SPDX-License-Identifier: MIT
/**
* Author: Lambdalf the White
*/
pragma solidity 0.8.17;
import "./interfaces/IERC721Errors.sol";
import "./interfaces/IERC165.sol";
import "./interfaces/IERC721.sol";
import "./interfaces/IERC721Enumerable.sol";
import "./interfaces/IERC721Metadata.sol";
import "./interfaces/IERC721Receiver.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
* This contract features:
* ~ Very Cheap batch minting
* ~ Token tracker support
*
* Note: This implementation imposes a very expensive `balanceOf()` and `ownerOf()`.
* It is not recommended to interract with those from another contract.
*/
abstract contract Reg_ERC721Batch is
IERC721Errors,
IERC165,
IERC721,
IERC721Metadata,
IERC721Enumerable
{
uint256 private _nextId = 1;
string public name;
string public symbol;
// Mapping from token ID to approved address
mapping(uint256 => address) public getApproved;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
// List of owner addresses
mapping(uint256 => address) private _owners;
// Token Base URI
string private _baseURI;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
function __init_ERC721Metadata(
string memory name_,
string memory symbol_,
string memory baseURI_
) internal {
name = name_;
symbol = symbol_;
_baseURI = baseURI_;
}
// **************************************
// ***** MODIFIER *****
// **************************************
/**
* @dev Ensures the token exist.
* A token exists if it has been minted and is not owned by the null address.
*
* @param tokenId_ : identifier of the NFT being referenced
*/
modifier exists(uint256 tokenId_) {
if (!_exists(tokenId_)) {
revert IERC721_NONEXISTANT_TOKEN(tokenId_);
}
_;
}
// **************************************
// **************************************
// ***** INTERNAL *****
// **************************************
/**
* @dev Internal function returning the number of tokens in `tokenOwner_`'s account.
*/
function _balanceOf(address tokenOwner_)
internal
view
virtual
returns (uint256)
{
if (tokenOwner_ == address(0)) {
return 0;
}
uint256 _count_ = 0;
address _currentTokenOwner_;
for (uint256 i = 1; i < _nextId; ++i) {
if (_exists(i)) {
if (_owners[i] != address(0)) {
_currentTokenOwner_ = _owners[i];
}
if (tokenOwner_ == _currentTokenOwner_) {
_count_++;
}
}
}
return _count_;
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from_ address representing the previous owner of the given token ID
* @param to_ target address that will receive the tokens
* @param tokenId_ uint256 ID of the token to be transferred
* @param data_ bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(
address from_,
address to_,
uint256 tokenId_,
bytes memory data_
) internal virtual returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
//
// IMPORTANT
// It is unsafe to assume that an address not flagged by this method
// is an externally-owned account (EOA) and not a contract.
//
// Among others, the following types of addresses will not be flagged:
//
// - an externally-owned account
// - a contract in construction
// - an address where a contract will be created
// - an address where a contract lived, but was destroyed
uint256 _size_;
assembly {
_size_ := extcodesize(to_)
}
// If address is a contract, check that it is aware of how to handle ERC721 tokens
if (_size_ > 0) {
try
IERC721Receiver(to_).onERC721Received(
msg.sender,
from_,
tokenId_,
data_
)
returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert IERC721_NON_ERC721_RECEIVER(to_);
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Internal function returning whether a token exists.
* A token exists if it has been minted and is not owned by the null address.
*
* @param tokenId_ uint256 ID of the token to verify
*
* @return bool whether the token exists
*/
function _exists(uint256 tokenId_) internal view virtual returns (bool) {
if (tokenId_ == 0) {
return false;
}
return tokenId_ < _nextId;
}
/**
* @dev Internal function returning whether `operator_` is allowed
* to manage tokens on behalf of `tokenOwner_`.
*
* @param tokenOwner_ address that owns tokens
* @param operator_ address that tries to manage tokens
*
* @return bool whether `operator_` is allowed to handle the token
*/
function _isApprovedForAll(address tokenOwner_, address operator_)
internal
view
virtual
returns (bool)
{
return _operatorApprovals[tokenOwner_][operator_];
}
/**
* @dev Internal function returning whether `operator_` is allowed to handle `tokenId_`
*
* Note: To avoid multiple checks for the same data, it is assumed that existence of `tokeId_`
* has been verified prior via {_exists}
* If it hasn't been verified, this function might panic
*
* @param operator_ address that tries to handle the token
* @param tokenId_ uint256 ID of the token to be handled
*
* @return bool whether `operator_` is allowed to handle the token
*/
function _isApprovedOrOwner(
address tokenOwner_,
address operator_,
uint256 tokenId_
) internal view virtual returns (bool) {
bool _isApproved_ = operator_ == tokenOwner_ ||
operator_ == getApproved[tokenId_] ||
_isApprovedForAll(tokenOwner_, operator_);
return _isApproved_;
}
/**
* @dev Mints `qty_` tokens and transfers them to `to_`.
*
* This internal function can be used to perform token minting.
*
* Emits one or more {Transfer} event.
*/
function _mint(address to_, uint256 qty_) internal virtual {
uint256 _firstToken_ = _nextId;
uint256 _nextStart_ = _firstToken_ + qty_;
uint256 _lastToken_ = _nextStart_ - 1;
_owners[_firstToken_] = to_;
if (_lastToken_ > _firstToken_) {
_owners[_lastToken_] = to_;
}
_nextId = _nextStart_;
if (!_checkOnERC721Received(address(0), to_, _firstToken_, "")) {
revert IERC721_NON_ERC721_RECEIVER(to_);
}
for (uint256 i = _firstToken_; i < _nextStart_; ++i) {
emit Transfer(address(0), to_, i);
}
}
/**
* @dev Internal function returning the owner of the `tokenId_` token.
*
* @param tokenId_ uint256 ID of the token to verify
*
* @return address the address of the token owner
*/
function _ownerOf(uint256 tokenId_)
internal
view
virtual
returns (address)
{
uint256 _tokenId_ = tokenId_;
address _tokenOwner_ = _owners[_tokenId_];
while (_tokenOwner_ == address(0)) {
_tokenId_--;
_tokenOwner_ = _owners[_tokenId_];
}
return _tokenOwner_;
}
/**
* @dev Internal function used to set the base URI of the collection.
*/
function _setBaseURI(string memory baseURI_) internal virtual {
_baseURI = baseURI_;
}
/**
* @dev Internal function returning the total supply.
*/
function _totalSupply() internal view virtual returns (uint256) {
return supplyMinted();
}
/**
* @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 Transfers `tokenId_` from `from_` to `to_`.
*
* This internal function can be used to implement alternative mechanisms to perform
* token transfer, such as signature-based, or token burning.
*
* Emits a {Transfer} event.
*/
function _transfer(
address from_,
address to_,
uint256 tokenId_
) internal virtual {
getApproved[tokenId_] = address(0);
uint256 _previousId_ = tokenId_ > 1 ? tokenId_ - 1 : 1;
uint256 _nextId_ = tokenId_ + 1;
bool _previousShouldUpdate_ = _previousId_ < tokenId_ &&
_exists(_previousId_) &&
_owners[_previousId_] == address(0);
bool _nextShouldUpdate_ = _exists(_nextId_) &&
_owners[_nextId_] == address(0);
if (_previousShouldUpdate_) {
_owners[_previousId_] = from_;
}
if (_nextShouldUpdate_) {
_owners[_nextId_] = from_;
}
_owners[tokenId_] = to_;
emit Transfer(from_, to_, tokenId_);
}
// **************************************
// **************************************
// ***** PUBLIC *****
// **************************************
/**
* @dev See {IERC721-approve}.
*/
function approve(address to_, uint256 tokenId_)
public
virtual
exists(tokenId_)
{
address _operator_ = msg.sender;
address _tokenOwner_ = _ownerOf(tokenId_);
if (to_ == _tokenOwner_) {
revert IERC721_INVALID_APPROVAL(to_);
}
bool _isApproved_ = _isApprovedOrOwner(
_tokenOwner_,
_operator_,
tokenId_
);
if (!_isApproved_) {
revert IERC721_CALLER_NOT_APPROVED(
_tokenOwner_,
_operator_,
tokenId_
);
}
getApproved[tokenId_] = to_;
emit Approval(_tokenOwner_, to_, tokenId_);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*
* Note: We can ignore `from_` as we can compare everything to the actual token owner,
* but we cannot remove this parameter to stay in conformity with IERC721
*/
function safeTransferFrom(
address from_,
address to_,
uint256 tokenId_
) public virtual override {
safeTransferFrom(from_, to_, tokenId_, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*
* Note: We can ignore `from_` as we can compare everything to the actual token owner,
* but we cannot remove this parameter to stay in conformity with IERC721
*/
function safeTransferFrom(
address from_,
address to_,
uint256 tokenId_,
bytes memory data_
) public virtual override {
transferFrom(from_, to_, tokenId_);
if (!_checkOnERC721Received(from_, to_, tokenId_, data_)) {
revert IERC721_NON_ERC721_RECEIVER(to_);
}
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator_, bool approved_)
public
virtual
override
{
address _account_ = msg.sender;
if (operator_ == _account_) {
revert IERC721_INVALID_APPROVAL(operator_);
}
_operatorApprovals[_account_][operator_] = approved_;
emit ApprovalForAll(_account_, operator_, approved_);
}
/**
* @dev See {IERC721-transferFrom}.
*
* Note: We can ignore `from_` as we can compare everything to the actual token owner,
* but we cannot remove this parameter to stay in conformity with IERC721
*/
function transferFrom(
address from_,
address to_,
uint256 tokenId_
) public virtual exists(tokenId_) {
if (to_ == address(0)) {
revert IERC721_INVALID_TRANSFER();
}
address _operator_ = msg.sender;
address _tokenOwner_ = _ownerOf(tokenId_);
if (from_ != _tokenOwner_) {
revert IERC721_INVALID_TRANSFER_FROM(_tokenOwner_, from_, tokenId_);
}
bool _isApproved_ = _isApprovedOrOwner(
_tokenOwner_,
_operator_,
tokenId_
);
if (!_isApproved_) {
revert IERC721_CALLER_NOT_APPROVED(
_tokenOwner_,
_operator_,
tokenId_
);
}
_transfer(_tokenOwner_, to_, tokenId_);
}
// **************************************
// **************************************
// ***** VIEW *****
// **************************************
/**
* @dev Returns the number of tokens in `tokenOwner_`'s account.
*/
function balanceOf(address tokenOwner_)
public
view
virtual
returns (uint256)
{
return _balanceOf(tokenOwner_);
}
/**
* @dev Returns if the `operator_` is allowed to manage all of the assets of `tokenOwner_`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address tokenOwner_, address operator_)
public
view
virtual
returns (bool)
{
return _isApprovedForAll(tokenOwner_, operator_);
}
/**
* @dev Returns the owner of the `tokenId_` token.
*
* Requirements:
*
* - `tokenId_` must exist.
*/
function ownerOf(uint256 tokenId_)
public
view
virtual
exists(tokenId_)
returns (address)
{
return _ownerOf(tokenId_);
}
/**
* @dev Returns the total number of tokens minted
*
* @return uint256 the number of tokens that have been minted so far
*/
function supplyMinted() public view virtual returns (uint256) {
return _nextId - 1;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId_)
public
view
virtual
override
returns (bool)
{
return
interfaceId_ == type(IERC721Enumerable).interfaceId ||
interfaceId_ == type(IERC721Metadata).interfaceId ||
interfaceId_ == type(IERC721).interfaceId ||
interfaceId_ == type(IERC165).interfaceId;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index_)
public
view
virtual
override
returns (uint256)
{
if (index_ >= supplyMinted()) {
revert IERC721Enumerable_INDEX_OUT_OF_BOUNDS(index_);
}
return index_ + 1;
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/
function tokenOfOwnerByIndex(address tokenOwner_, uint256 index_)
public
view
virtual
override
returns (uint256 tokenId)
{
if (index_ >= _balanceOf(tokenOwner_)) {
revert IERC721Enumerable_OWNER_INDEX_OUT_OF_BOUNDS(
tokenOwner_,
index_
);
}
uint256 _count_ = 0;
for (uint256 i = 1; i < _nextId; i++) {
if (_exists(i) && tokenOwner_ == _ownerOf(i)) {
if (index_ == _count_) {
return i;
}
_count_++;
}
}
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId_)
public
view
virtual
override
exists(tokenId_)
returns (string memory)
{
return
bytes(_baseURI).length > 0
? string(abi.encodePacked(_baseURI, _toString(tokenId_)))
: _toString(tokenId_);
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply();
}
// **************************************
}
OperatorFilterer.sol 60 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {IOperatorFilterRegistry} from "./IOperatorFilterRegistry.sol";
abstract contract OperatorFilterer {
error OperatorNotAllowed(address operator);
IOperatorFilterRegistry constant operatorFilterRegistry =
IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E);
constructor(address subscriptionOrRegistrantToCopy, bool subscribe) {
// If an inheriting token contract is deployed to a network without the registry deployed, the modifier
// will not revert, but the contract will need to be registered with the registry once it is deployed in
// order for the modifier to filter addresses.
if (address(operatorFilterRegistry).code.length > 0) {
if (subscribe) {
operatorFilterRegistry.registerAndSubscribe(
address(this),
subscriptionOrRegistrantToCopy
);
} else {
if (subscriptionOrRegistrantToCopy != address(0)) {
operatorFilterRegistry.registerAndCopyEntries(
address(this),
subscriptionOrRegistrantToCopy
);
} else {
operatorFilterRegistry.register(address(this));
}
}
}
}
modifier onlyAllowedOperator(address from) virtual {
// Check registry code length to facilitate testing in environments without a deployed registry.
if (address(operatorFilterRegistry).code.length > 0) {
// Allow spending tokens from addresses with balance
// Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred
// from an EOA.
if (from == msg.sender) {
_;
return;
}
if (
!(operatorFilterRegistry.isOperatorAllowed(
address(this),
msg.sender
) &&
operatorFilterRegistry.isOperatorAllowed(
address(this),
from
))
) {
revert OperatorNotAllowed(msg.sender);
}
}
_;
}
}
Whitelist_Merkle.sol 136 lines
// SPDX-License-Identifier: MIT
/**
* Author: Lambdalf the White
* Edit : Squeebo
*/
pragma solidity 0.8.17;
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
abstract contract Whitelist_Merkle {
// Errors
/**
* @dev Thrown when trying to query the whitelist while it's not set
*/
error Whitelist_NOT_SET();
/**
* @dev Thrown when `account` has consumed their alloted access and tries to query more
*
* @param account : address trying to access the whitelist
*/
error Whitelist_CONSUMED(address account);
/**
* @dev Thrown when `account` does not have enough alloted access to fulfil their query
*
* @param account : address trying to access the whitelist
*/
error Whitelist_FORBIDDEN(address account);
bytes32 private _root;
mapping(address => uint256) private _consumed;
/**
* @dev Ensures that `account_` has `qty_` alloted access on the whitelist.
*
* @param account_ : the address to validate access
* @param proof_ : the Merkle proof to validate whitelist allocation
* @param alloted_ : the max amount of whitelist spots allocated
* @param qty_ : the amount of whitelist access requested
*/
modifier isWhitelisted(
address account_,
bytes32[] memory proof_,
uint256 alloted_,
uint256 qty_
) {
if (qty_ > alloted_) {
revert Whitelist_FORBIDDEN(account_);
}
uint256 _allowed_ = checkWhitelistAllowance(account_, proof_, alloted_);
if (_allowed_ < qty_) {
revert Whitelist_FORBIDDEN(account_);
}
_;
}
/**
* @dev Internal function setting the pass to protect the whitelist.
*
* @param root_ : the Merkle root to hold the whitelist
*/
function _setWhitelist(bytes32 root_) internal virtual {
_root = root_;
}
/**
* @dev Returns the amount that `account_` is allowed to access from the whitelist.
*
* @param account_ : the address to validate access
* @param proof_ : the Merkle proof to validate whitelist allocation
*
* @return uint256 : the total amount of whitelist allocation remaining for `account_`
*
* Requirements:
*
* - `_root` must be set.
*/
function checkWhitelistAllowance(
address account_,
bytes32[] memory proof_,
uint256 alloted_
) public view returns (uint256) {
if (_root == 0) {
revert Whitelist_NOT_SET();
}
if (_consumed[account_] >= alloted_) {
revert Whitelist_CONSUMED(account_);
}
if (!_computeProof(account_, proof_)) {
revert Whitelist_FORBIDDEN(account_);
}
uint256 _res_;
unchecked {
_res_ = alloted_ - _consumed[account_];
}
return _res_;
}
/**
* @dev Processes the Merkle proof to determine if `account_` is whitelisted.
*
* @param account_ : the address to validate access
* @param proof_ : the Merkle proof to validate whitelist allocation
*
* @return bool : whether `account_` is whitelisted or not
*/
function _computeProof(address account_, bytes32[] memory proof_)
private
view
returns (bool)
{
bytes32 leaf = keccak256(abi.encodePacked(account_));
return MerkleProof.processProof(proof_, leaf) == _root;
}
/**
* @dev Consumes `amount_` whitelist access passes from `account_`.
*
* @param account_ : the address to consume access from
*
* Note: Before calling this function, eligibility should be checked through {Whitelistable-checkWhitelistAllowance}.
*/
function _consumeWhitelist(address account_, uint256 qty_) internal {
unchecked {
_consumed[account_] += qty_;
}
}
}
IERC165.sol 13 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
interface IERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceID The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// @return `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
IERC721Errors.sol 61 lines
// SPDX-License-Identifier: MIT
/**
* Author: Lambdalf the White
*/
pragma solidity 0.8.17;
interface IERC721Errors {
/**
* @dev Thrown when `operator` has not been approved to manage `tokenId` on behalf of `tokenOwner`.
*
* @param tokenOwner : address owning the token
* @param operator : address trying to manage the token
* @param tokenId : identifier of the NFT being referenced
*/
error IERC721_CALLER_NOT_APPROVED( address tokenOwner, address operator, uint256 tokenId );
/**
* @dev Thrown when `operator` tries to approve themselves for managing a token they own.
*
* @param operator : address that is trying to approve themselves
*/
error IERC721_INVALID_APPROVAL( address operator );
/**
* @dev Thrown when a token is being transferred to the zero address.
*/
error IERC721_INVALID_TRANSFER();
/**
* @dev Thrown when a token is being transferred from an address that doesn't own it.
*
* @param tokenOwner : address owning the token
* @param from : address that the NFT is being transferred from
* @param tokenId : identifier of the NFT being referenced
*/
error IERC721_INVALID_TRANSFER_FROM( address tokenOwner, address from, uint256 tokenId );
/**
* @dev Thrown when the requested token doesn't exist.
*
* @param tokenId : identifier of the NFT being referenced
*/
error IERC721_NONEXISTANT_TOKEN( uint256 tokenId );
/**
* @dev Thrown when a token is being safely transferred to a contract unable to handle it.
*
* @param receiver : address unable to receive the token
*/
error IERC721_NON_ERC721_RECEIVER( address receiver );
/**
* @dev Thrown when trying to get the token at an index that doesn't exist.
*
* @param index : the inexistant index
*/
error IERC721Enumerable_INDEX_OUT_OF_BOUNDS( uint256 index );
/**
* @dev Thrown when trying to get the token owned by `tokenOwner` at an index that doesn't exist.
*
* @param tokenOwner : address owning the token
* @param index : the inexistant index
*/
error IERC721Enumerable_OWNER_INDEX_OUT_OF_BOUNDS( address tokenOwner, uint256 index );
}
IERC721Metadata.sol 20 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
/// @dev See https://eips.ethereum.org/EIPS/eip-721
/// Note: the ERC-165 identifier for this interface is 0x5b5e139f.
interface IERC721Metadata /* is IERC721 */ {
/// @notice A descriptive name for a collection of NFTs in this contract
function name() external view returns ( string memory _name );
/// @notice An abbreviated name for NFTs in this contract
function symbol() external view returns ( string memory _symbol );
/// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
/// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
/// 3986. The URI may point to a JSON file that conforms to the "ERC721
/// Metadata JSON Schema".
function tokenURI( uint256 _tokenId ) external view returns ( string memory );
}
IOperatorFilterRegistry.sol 93 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IOperatorFilterRegistry {
function isOperatorAllowed(address registrant, address operator)
external
view
returns (bool);
function register(address registrant) external;
function registerAndSubscribe(address registrant, address subscription)
external;
function registerAndCopyEntries(
address registrant,
address registrantToCopy
) external;
function updateOperator(
address registrant,
address operator,
bool filtered
) external;
function updateOperators(
address registrant,
address[] calldata operators,
bool filtered
) external;
function updateCodeHash(
address registrant,
bytes32 codehash,
bool filtered
) external;
function updateCodeHashes(
address registrant,
bytes32[] calldata codeHashes,
bool filtered
) external;
function subscribe(address registrant, address registrantToSubscribe)
external;
function unsubscribe(address registrant, bool copyExistingEntries) external;
function subscriptionOf(address addr) external returns (address registrant);
function subscribers(address registrant)
external
returns (address[] memory);
function subscriberAt(address registrant, uint256 index)
external
returns (address);
function copyEntriesOf(address registrant, address registrantToCopy)
external;
function isOperatorFiltered(address registrant, address operator)
external
returns (bool);
function isCodeHashOfFiltered(address registrant, address operatorWithCode)
external
returns (bool);
function isCodeHashFiltered(address registrant, bytes32 codeHash)
external
returns (bool);
function filteredOperators(address addr)
external
returns (address[] memory);
function filteredCodeHashes(address addr)
external
returns (bytes32[] memory);
function filteredOperatorAt(address registrant, uint256 index)
external
returns (address);
function filteredCodeHashAt(address registrant, uint256 index)
external
returns (bytes32);
function isRegistered(address addr) external returns (bool);
function codeHashOf(address addr) external returns (bytes32);
}
MerkleProof.sol 223 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)
pragma solidity ^0.8.0;
/**
* @dev These functions deal with verification of Merkle Tree proofs.
*
* The tree and the proofs can be generated using our
* https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
* You will find a quickstart guide in the readme.
*
* WARNING: You should avoid using leaf values that are 64 bytes long prior to
* hashing, or use a hash function other than keccak256 for hashing leaves.
* This is because the concatenation of a sorted pair of internal nodes in
* the merkle tree could be reinterpreted as a leaf value.
* OpenZeppelin's JavaScript library generates merkle trees that are safe
* against this attack out of the box.
*/
library MerkleProof {
/**
* @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
* defined by `root`. For this, a `proof` must be provided, containing
* sibling hashes on the branch from the leaf to the root of the tree. Each
* pair of leaves and each pair of pre-images are assumed to be sorted.
*/
function verify(
bytes32[] memory proof,
bytes32 root,
bytes32 leaf
) internal pure returns (bool) {
return processProof(proof, leaf) == root;
}
/**
* @dev Calldata version of {verify}
*
* _Available since v4.7._
*/
function verifyCalldata(
bytes32[] calldata proof,
bytes32 root,
bytes32 leaf
) internal pure returns (bool) {
return processProofCalldata(proof, leaf) == root;
}
/**
* @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
* from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
* hash matches the root of the tree. When processing the proof, the pairs
* of leafs & pre-images are assumed to be sorted.
*
* _Available since v4.4._
*/
function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Calldata version of {processProof}
*
* _Available since v4.7._
*/
function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
/**
* @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by
* `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
*
* CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
*
* _Available since v4.7._
*/
function multiProofVerify(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProof(proof, proofFlags, leaves) == root;
}
/**
* @dev Calldata version of {multiProofVerify}
*
* CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
*
* _Available since v4.7._
*/
function multiProofVerifyCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProofCalldata(proof, proofFlags, leaves) == root;
}
/**
* @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
* proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
* leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
* respectively.
*
* CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
* is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
* tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
*
* _Available since v4.7._
*/
function processMultiProof(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the merkle tree.
uint256 leavesLen = leaves.length;
uint256 totalHashes = proofFlags.length;
// Check proof validity.
require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value for the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
return hashes[totalHashes - 1];
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
/**
* @dev Calldata version of {processMultiProof}.
*
* CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
*
* _Available since v4.7._
*/
function processMultiProofCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
// This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by
// consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
// `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
// the merkle tree.
uint256 leavesLen = leaves.length;
uint256 totalHashes = proofFlags.length;
// Check proof validity.
require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");
// The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
// `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
// At each step, we compute the next hash using two values:
// - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
// get the next hash.
// - depending on the flag, either another value for the "main queue" (merging branches) or an element from the
// `proof` array.
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
return hashes[totalHashes - 1];
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
}
function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}
DefaultOperatorFilterer.sol 10 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {OperatorFilterer} from "./OperatorFilterer.sol";
abstract contract DefaultOperatorFilterer is OperatorFilterer {
address constant DEFAULT_SUBSCRIPTION = address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6);
constructor() OperatorFilterer(DEFAULT_SUBSCRIPTION, true) {}
}
ERC173.sol 81 lines
// SPDX-License-Identifier: MIT
/**
* Author: Lambdalf the White
*/
pragma solidity 0.8.17;
import "../interfaces/IERC173.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract ERC173 is IERC173 {
// Errors
/**
* @dev Thrown when `operator` is not the contract owner.
*
* @param operator : address trying to use a function reserved to contract owner without authorization
*/
error IERC173_NOT_OWNER( address operator );
// The owner of the contract
address private _owner;
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
address _sender_ = msg.sender;
if ( owner() != _sender_ ) {
revert IERC173_NOT_OWNER( _sender_ );
}
_;
}
/**
* @dev Sets the contract owner.
*
* Note: This function needs to be called in the contract constructor to initialize the contract owner,
* if it is not, then parts of the contract might be non functional
*
* @param owner_ : address that owns the contract
*/
function _setOwner( address owner_ ) internal {
_owner = owner_;
}
/**
* @dev Returns the address of the current contract owner.
*
* @return address : the current contract owner
*/
function owner() public view virtual returns ( address ) {
return _owner;
}
/**
* @dev Transfers ownership of the contract to `newOwner_`.
*
* @param newOwner_ : address of the new contract owner
*
* Requirements:
*
* - Caller must be the contract owner.
*/
function transferOwnership( address newOwner_ ) public virtual onlyOwner {
address _oldOwner_ = _owner;
_owner = newOwner_;
emit OwnershipTransferred( _oldOwner_, newOwner_ );
}
}
IERC721.sol 102 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)
pragma solidity 0.8.17;
/// @title ERC-721 Non-Fungible Token Standard
/// @dev See https://eips.ethereum.org/EIPS/eip-721
/// Note: the ERC-165 identifier for this interface is 0x80ac58cd.
interface IERC721 /* is IERC165 */ {
/// @dev This emits when ownership of any NFT changes by any mechanism.
/// This event emits when NFTs are created (`from` == 0) and destroyed
/// (`to` == 0). Exception: during contract creation, any number of NFTs
/// may be created and assigned without emitting Transfer. At the time of
/// any transfer, the approved address for that NFT (if any) is reset to none.
event Transfer( address indexed from_, address indexed to_, uint256 indexed tokenId_ );
/// @dev This emits when the approved address for an NFT is changed or
/// reaffirmed. The zero address indicates there is no approved address.
/// When a Transfer event emits, this also indicates that the approved
/// address for that NFT (if any) is reset to none.
event Approval( address indexed owner_, address indexed approved_, uint256 indexed tokenId_ );
/// @dev This emits when an operator is enabled or disabled for an owner.
/// The operator can manage all NFTs of the owner.
event ApprovalForAll( address indexed owner_, address indexed operator_, bool approved_ );
/// @notice Count all NFTs assigned to an owner
/// @dev NFTs assigned to the zero address are considered invalid, and this
/// function throws for queries about the zero address.
/// @param owner_ An address for whom to query the balance
/// @return The number of NFTs owned by `owner_`, possibly zero
function balanceOf( address owner_ ) external view returns ( uint256 );
/// @notice Find the owner of an NFT
/// @dev NFTs assigned to zero address are considered invalid, and queries
/// about them do throw.
/// @param tokenId_ The identifier for an NFT
/// @return The address of the owner of the NFT
function ownerOf( uint256 tokenId_ ) external view returns ( address );
/// @notice Transfers the ownership of an NFT from one address to another address
/// @dev Throws unless `msg.sender` is the current owner, an authorized
/// operator, or the approved address for this NFT. Throws if `from_` is
/// not the current owner. Throws if `to_` is the zero address. Throws if
/// `tokenId_` is not a valid NFT. When transfer is complete, this function
/// checks if `to_` is a smart contract (code size > 0). If so, it calls
/// `onERC721Received` on `to_` and throws if the return value is not
/// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
/// @param from_ The current owner of the NFT
/// @param to_ The new owner
/// @param tokenId_ The NFT to transfer
/// @param data_ Additional data with no specified format, sent in call to `to_`
function safeTransferFrom( address from_, address to_, uint256 tokenId_, bytes calldata data_ ) external;
/// @notice Transfers the ownership of an NFT from one address to another address
/// @dev This works identically to the other function with an extra data parameter,
/// except this function just sets data to "".
/// @param from_ The current owner of the NFT
/// @param to_ The new owner
/// @param tokenId_ The NFT to transfer
function safeTransferFrom( address from_, address to_, uint256 tokenId_ ) external;
/// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
/// TO CONFIRM THAT `to_` IS CAPABLE OF RECEIVING NFTS OR ELSE
/// THEY MAY BE PERMANENTLY LOST
/// @dev Throws unless `msg.sender` is the current owner, an authorized
/// operator, or the approved address for this NFT. Throws if `from_` is
/// not the current owner. Throws if `to_` is the zero address. Throws if
/// `tokenId_` is not a valid NFT.
/// @param from_ The current owner of the NFT
/// @param to_ The new owner
/// @param tokenId_ The NFT to transfer
function transferFrom( address from_, address to_, uint256 tokenId_ ) external;
/// @notice Change or reaffirm the approved address for an NFT
/// @dev The zero address indicates there is no approved address.
/// Throws unless `msg.sender` is the current NFT owner, or an authorized
/// operator of the current owner.
/// @param approved_ The new approved NFT controller
/// @param tokenId_ The NFT to approve
function approve( address approved_, uint256 tokenId_ ) external;
/// @notice Enable or disable approval for a third party ("operator") to manage
/// all of `msg.sender`'s assets
/// @dev Emits the ApprovalForAll event. The contract MUST allow
/// multiple operators per owner.
/// @param operator_ Address to add to the set of authorized operators
/// @param approved_ True if the operator is approved, false to revoke approval
function setApprovalForAll( address operator_, bool approved_ ) external;
/// @notice Get the approved address for a single NFT
/// @dev Throws if `tokenId_` is not a valid NFT.
/// @param tokenId_ The NFT to find the approved address for
/// @return The approved address for this NFT, or the zero address if there is none
function getApproved( uint256 tokenId_ ) external view returns ( address );
/// @notice Query if an address is an authorized operator for another address
/// @param owner_ The address that owns the NFTs
/// @param operator_ The address that acts on behalf of the owner
/// @return True if `operator_` is an approved operator for `owner_`, false otherwise
function isApprovedForAll( address owner_, address operator_ ) external view returns ( bool );
}
SavageNation.sol 242 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;
// Contract by @AsteriaLabs
import "./Reg_ERC721Batch.sol";
import "./utils/Whitelist_Merkle.sol";
import "./utils/ERC173.sol";
import "./interfaces/DefaultOperatorFilterer.sol";
/// @title Savage Nation
/// @author Goku <@Suleman132446>
contract SavageNation is
Reg_ERC721Batch,
Whitelist_Merkle,
ERC173,
DefaultOperatorFilterer
{
using MerkleProof for bytes32[];
uint256 public whitelistPrice = 0.039 ether;
uint256 public publicPrice = 0.059 ether;
uint256 public maxPerWhitelist = 2;
uint256 public maxPerPublic = 2;
uint256 public maxSupply = 10000;
/**
@dev An enum representing the sale state
*/
enum Sale {
PAUSED,
PRIVATE,
PUBLIC
}
Sale public saleState = Sale.PAUSED;
// Mapping of nft minted by a wallet in public
mapping(address => uint256) public mintedPerWallet;
// Modifier to allow only owner
// Modifier to check the sale state
modifier isSaleState(Sale sale_) {
require(saleState == sale_, "Sale not active");
_;
}
// Modifier to block the other contracts
modifier blockContracts() {
require(tx.origin == msg.sender, "No smart contracts are allowed");
_;
}
constructor(
string memory name_,
string memory symbol_,
string memory baseURI_
) {
__init_ERC721Metadata(name_, symbol_, baseURI_);
_setOwner(msg.sender);
}
/**
* @dev tranfer the funds from contract
*
* @param to_ : the address of the wallet to transfer the funds
*/
function withdraw(address to_, uint amount_) public onlyOwner {
uint256 _balance_ = address(this).balance;
require(_balance_ > 0, "No balance to withdraw");
require(amount_ <= _balance_, "Amount is not valid");
address _recipient_ = payable(to_);
(bool _success_, ) = _recipient_.call{value: amount_}("");
require(_success_, "Transaction failed");
}
/**
* @dev set the whiltelist price
*
* @param price_ : the price of whitelist mint
*/
function setWhitelistPrice(uint256 price_) external onlyOwner {
whitelistPrice = price_;
}
/**
* @dev set the public mint price
*
* @param price_ : the price of public mint
*/
function setPublicPrice(uint256 price_) external onlyOwner {
publicPrice = price_;
}
/**
* @dev set the mints per wallet in whitelist
*
* @param mints_ : the amount of for whitelist mint
*/
function setMintsPerWhitelist(uint256 mints_) external onlyOwner {
maxPerWhitelist = mints_;
}
/**
* @dev set the mints per wallet in public
*
* @param mints_ : the amount of for public mint
*/
function setMintsPerPublic(uint256 mints_) external onlyOwner {
maxPerPublic = mints_;
}
/**
* @dev set the max supply for collection
*
* @param supply_ : the amount for supply
*/
function setMaxSupply(uint256 supply_) external onlyOwner {
uint _currentSupply_ = totalSupply();
require(
supply_ > _currentSupply_,
"Max supply should be greater than current supply"
);
require(
supply_ < maxSupply,
"Max supply should be greater than previous max supply"
);
maxSupply = supply_;
}
/**
* @dev set the merkle root for whitelist
*
* @param root_ : the merkle for whitelist
*/
function setWhitelistRoot(bytes32 root_) external onlyOwner {
_setWhitelist(root_);
}
/**
* @dev set the base uri for collection
*
* @param baseURI_ : the base uri for collection
*/
function setBaseURI(string memory baseURI_) external onlyOwner {
_setBaseURI(baseURI_);
}
/**
* @dev set the sale state
*
* @param sale_ : the new sale state
*/
function setSaleState(Sale sale_) external onlyOwner {
saleState = sale_;
}
/**
* @dev mint the token in whitelist sale
*
* @param proof_ : the proof for verificaton
* @param qty_ : the quantity of mint
*/
function mintWhitelist(bytes32[] memory proof_, uint256 qty_)
external
payable
blockContracts
isSaleState(Sale.PRIVATE)
isWhitelisted(msg.sender, proof_, maxPerWhitelist, qty_)
{
uint _supply_ = totalSupply();
require(_supply_ + qty_ <= maxSupply, "Exceeds supply");
require(
msg.value == qty_ * whitelistPrice,
"Ether sent is not correct"
);
_mint(msg.sender, qty_);
_consumeWhitelist(msg.sender, qty_);
}
/**
* @dev mint the token for airdrop
*
* @param qty_ : the quantity of mint
* @param to_: the address to send to
*/
function airdrop( uint256 qty_ , address to_) onlyOwner
external
payable
blockContracts
{
uint _supply_ = totalSupply();
require(_supply_ + qty_ <= maxSupply, "Exceeds supply");
_mint(to_, qty_);
}
/**
* @dev mint the token in public sale
*
* @param qty_ : the quantity of mint
*/
function mintPublic(uint256 qty_)
external
payable
blockContracts
isSaleState(Sale.PUBLIC)
{
uint _supply_ = totalSupply();
require(
mintedPerWallet[msg.sender] + qty_ <= maxPerPublic,
"Exceeds mint per wallet"
);
require(_supply_ + qty_ <= maxSupply, "Exceeds supply");
require(msg.value == qty_ * publicPrice, "Ether sent is not correct");
_mint(msg.sender, qty_);
mintedPerWallet[msg.sender] += qty_;
}
function transferFrom(
address from,
address to,
uint256 tokenId
) public override onlyAllowedOperator(from) {
super.transferFrom(from, to, tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public override onlyAllowedOperator(from) {
super.safeTransferFrom(from, to, tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory data
) public override onlyAllowedOperator(from) {
super.safeTransferFrom(from, to, tokenId, data);
}
}
Read Contract
balanceOf 0x70a08231 → uint256
checkWhitelistAllowance 0x7d912844 → uint256
getApproved 0x081812fc → address
isApprovedForAll 0xe985e9c5 → bool
maxPerPublic 0xcfe1908d → uint256
maxPerWhitelist 0x66cc5f0d → uint256
maxSupply 0xd5abeb01 → uint256
mintedPerWallet 0x3a602b4d → uint256
name 0x06fdde03 → string
owner 0x8da5cb5b → address
ownerOf 0x6352211e → address
publicPrice 0xa945bf80 → uint256
saleState 0x603f4d52 → uint8
supplyMinted 0x7e9845f5 → uint256
supportsInterface 0x01ffc9a7 → bool
symbol 0x95d89b41 → string
tokenByIndex 0x4f6ccce7 → uint256
tokenOfOwnerByIndex 0x2f745c59 → uint256
tokenURI 0xc87b56dd → string
totalSupply 0x18160ddd → uint256
whitelistPrice 0xfc1a1c36 → uint256
Write Contract 18 functions
These functions modify contract state and require a wallet transaction to execute.
airdrop 0xbc63f02e
uint256 qty_
address to_
approve 0x095ea7b3
address to_
uint256 tokenId_
mintPublic 0xefd0cbf9
uint256 qty_
mintWhitelist 0xa6d612f9
bytes32[] proof_
uint256 qty_
safeTransferFrom 0x42842e0e
address from
address to
uint256 tokenId
safeTransferFrom 0xb88d4fde
address from
address to
uint256 tokenId
bytes data
setApprovalForAll 0xa22cb465
address operator_
bool approved_
setBaseURI 0x55f804b3
string baseURI_
setMaxSupply 0x6f8b44b0
uint256 supply_
setMintsPerPublic 0x02c366bc
uint256 mints_
setMintsPerWhitelist 0xc95d83c6
uint256 mints_
setPublicPrice 0xc6275255
uint256 price_
setSaleState 0x5a67de07
uint8 sale_
setWhitelistPrice 0x717d57d3
uint256 price_
setWhitelistRoot 0xf5aa406d
bytes32 root_
transferFrom 0x23b872dd
address from
address to
uint256 tokenId
transferOwnership 0xf2fde38b
address newOwner_
withdraw 0xf3fef3a3
address to_
uint256 amount_
Recent Transactions
No transactions found for this address