Address Contract Partially Verified
Address
0xECaab68E0D903067eBb89a0fEfa6332ab93f7408
Balance
0.030000 ETH
Nonce
1
Code Size
16022 bytes
Creator
0x5C852791...6559 at tx 0x805ab0a3...94d89f
Indexed Transactions
0
Contract Bytecode
16022 bytes
0x6080604052600436106103545760003560e01c8063742af72b116101c6578063b88d4fde116100f7578063e8a3d48511610095578063f0cc3b851161006f578063f0cc3b85146109b7578063f2fde38b146109d7578063f449619e146109f7578063fadd308714610a1757600080fd5b8063e8a3d4851461096d578063e985e9c514610982578063f0c9dc60146109a257600080fd5b8063cef6d368116100d1578063cef6d368146108d7578063d547cfb714610916578063d955ec551461092b578063dc6b86271461094b57600080fd5b8063b88d4fde14610877578063be0d41b814610897578063c87b56dd146108b757600080fd5b806395d89b4111610164578063a22cb4651161013e578063a22cb465146107f7578063a2fb117514610817578063a4db625214610837578063b37217a41461085757600080fd5b806395d89b41146107a257806398fa734b146107b75780639e8c708e146107d757600080fd5b8063853828b6116101a0578063853828b61461072f5780638589ff45146107445780638da5cb5b1461076457806394985ddd1461078257600080fd5b8063742af72b146106c2578063834bb61b146106e25780638462151c1461070257600080fd5b80632d0335ab116102a057806342966c681161023e578063652489d411610218578063652489d41461064f578063661b1d2c1461066f57806370a082311461068d578063715018a6146106ad57600080fd5b806342966c68146105ef5780634f6ccce71461060f5780636352211e1461062f57600080fd5b80633408e4701161027a5780633408e470146105865780634129b2c91461059957806342619f66146105b957806342842e0e146105cf57600080fd5b80632d0335ab1461051a5780632f745c5914610550578063335477fc1461057057600080fd5b80630f7e59701161030d5780631df61141116102e75780631df61141146104a557806320379ee5146104c557806323b872dd146104da5780632ca40ed8146104fa57600080fd5b80630f7e597014610443578063109695231461047057806318160ddd1461049057600080fd5b806301ffc9a71461036057806306fdde0314610395578063081812fc146103b7578063095ea7b3146103ef5780630b75cef4146104115780630c53c51c1461043057600080fd5b3661035b57005b600080fd5b34801561036c57600080fd5b5061038061037b36600461388d565b610a2a565b60405190151581526020015b60405180910390f35b3480156103a157600080fd5b506103aa610a55565b60405161038c9190613b22565b3480156103c357600080fd5b506103d76103d236600461392d565b610ae7565b6040516001600160a01b03909116815260200161038c565b3480156103fb57600080fd5b5061040f61040a366004613745565b610b81565b005b34801561041d57600080fd5b506017545b60405190815260200161038c565b6103aa61043e3660046136c7565b610ca9565b34801561044f57600080fd5b506103aa604051806040016040528060018152602001603160f81b81525081565b34801561047c57600080fd5b5061040f61048b3660046138e4565b610e7b565b34801561049c57600080fd5b50600854610422565b3480156104b157600080fd5b5061040f6104c0366004613771565b610edb565b3480156104d157600080fd5b50600b54610422565b3480156104e657600080fd5b5061040f6104f5366004613591565b610fc5565b34801561050657600080fd5b5061038061051536600461353b565b610ffd565b34801561052657600080fd5b5061042261053536600461353b565b6001600160a01b03166000908152600c602052604090205490565b34801561055c57600080fd5b5061042261056b366004613745565b611008565b34801561057c57600080fd5b5061042260125481565b34801561059257600080fd5b5046610422565b3480156105a557600080fd5b506103d76105b436600461392d565b61109e565b3480156105c557600080fd5b5061042260165481565b3480156105db57600080fd5b5061040f6105ea366004613591565b6110ce565b3480156105fb57600080fd5b5061040f61060a36600461392d565b6110e9565b34801561061b57600080fd5b5061042261062a36600461392d565b61115d565b34801561063b57600080fd5b506103d761064a36600461392d565b6111f0565b34801561065b57600080fd5b5061040f61066a3660046138e4565b611267565b34801561067b57600080fd5b506010546001600160a01b03166103d7565b34801561069957600080fd5b506104226106a836600461353b565b6112c3565b3480156106b957600080fd5b5061040f61134a565b3480156106ce57600080fd5b5061040f6106dd36600461392d565b61139f565b3480156106ee57600080fd5b5061040f6106fd36600461392d565b6113ed565b34801561070e57600080fd5b5061072261071d36600461353b565b61143b565b60405161038c9190613aea565b34801561073b57600080fd5b5061040f6114fa565b34801561075057600080fd5b5061040f61075f3660046135d2565b611567565b34801561077057600080fd5b50600d546001600160a01b03166103d7565b34801561078e57600080fd5b5061040f61079d36600461386b565b6115d3565b3480156107ae57600080fd5b506103aa611651565b3480156107c357600080fd5b5061040f6107d236600461392d565b611660565b3480156107e357600080fd5b5061040f6107f236600461353b565b6116fe565b34801561080357600080fd5b5061040f610812366004613699565b61188d565b34801561082357600080fd5b506103d761083236600461392d565b61198f565b34801561084357600080fd5b5061038061085236600461392d565b6119b9565b34801561086357600080fd5b5061042261087236600461392d565b6119c4565b34801561088357600080fd5b5061040f61089236600461362d565b611c4a565b3480156108a357600080fd5b5061040f6108b2366004613831565b611c83565b3480156108c357600080fd5b506103aa6108d236600461392d565b611cdf565b3480156108e357600080fd5b506108f76108f236600461392d565b611d19565b604080516001600160a01b03909316835260208301919091520161038c565b34801561092257600080fd5b506103aa611d3a565b34801561093757600080fd5b5061040f61094636600461353b565b611d49565b34801561095757600080fd5b50610960611db4565b60405161038c9190613a9d565b34801561097957600080fd5b506103aa611e9d565b34801561098e57600080fd5b5061038061099d366004613558565b611ebd565b3480156109ae57600080fd5b506103aa611f8d565b3480156109c357600080fd5b506104226109d236600461392d565b61201b565b3480156109e357600080fd5b5061040f6109f236600461353b565b61202b565b348015610a0357600080fd5b5061040f610a1236600461392d565b6120e2565b61040f610a2536600461392d565b6122c2565b60006001600160e01b0319821663780e9d6360e01b1480610a4f5750610a4f82612499565b92915050565b606060008054610a6490613cf0565b80601f0160208091040260200160405190810160405280929190818152602001828054610a9090613cf0565b8015610add5780601f10610ab257610100808354040283529160200191610add565b820191906000526020600020905b815481529060010190602001808311610ac057829003601f168201915b5050505050905090565b6000818152600260205260408120546001600160a01b0316610b655760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b60648201526084015b60405180910390fd5b506000908152600460205260409020546001600160a01b031690565b6000610b8c826111f0565b9050806001600160a01b0316836001600160a01b03161415610bfa5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b6064820152608401610b5c565b806001600160a01b0316610c0c6124e9565b6001600160a01b03161480610c285750610c288161099d6124e9565b610c9a5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610b5c565b610ca483836124f8565b505050565b60408051606081810183526001600160a01b0388166000818152600c602090815290859020548452830152918101869052610ce78782878787612566565b610d3d5760405162461bcd60e51b815260206004820152602160248201527f5369676e657220616e64207369676e617475726520646f206e6f74206d6174636044820152600d60fb1b6064820152608401610b5c565b6001600160a01b0387166000908152600c60205260408120805491610d6183613d25565b91905055507f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b873388604051610d9993929190613a0d565b60405180910390a1600080306001600160a01b0316888a604051602001610dc19291906139a7565b60408051601f1981840301815290829052610ddb9161398b565b6000604051808303816000865af19150503d8060008114610e18576040519150601f19603f3d011682016040523d82523d6000602084013e610e1d565b606091505b509150915081610e6f5760405162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c000000006044820152606401610b5c565b98975050505050505050565b610e836124e9565b6001600160a01b0316610e9e600d546001600160a01b031690565b6001600160a01b031614610ec45760405162461bcd60e51b8152600401610b5c90613b87565b8051610ed79060119060208401906133b8565b5050565b610ee36124e9565b6001600160a01b0316610efe600d546001600160a01b031690565b6001600160a01b031614610f245760405162461bcd60e51b8152600401610b5c90613b87565b815181518114610f665760405162461bcd60e51b815260206004820152600d60248201526c082e4e4c2f2e640d8cadccee8d609b1b6044820152606401610b5c565b60005b81811015610fbf57610fad838281518110610f8657610f86613d96565b6020026020010151858381518110610fa057610fa0613d96565b6020026020010151612656565b80610fb781613d25565b915050610f69565b50505050565b610fd6610fd06124e9565b82612670565b610ff25760405162461bcd60e51b8152600401610b5c90613bbc565b610ca483838361273f565b6000610a4f826128ea565b6000611013836112c3565b82106110755760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610b5c565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b6000601782815481106110b3576110b3613d96565b6000918252602090912001546001600160a01b031692915050565b610ca483838360405180602001604052806000815250611c4a565b6010546001600160a01b03163314611151576111053382612670565b6111515760405162461bcd60e51b815260206004820152601e60248201527f4f776e657273686970206f7220617070726f76616c20726571756972656400006044820152606401610b5c565b61115a81612959565b50565b600061116860085490565b82106111cb5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610b5c565b600882815481106111de576111de613d96565b90600052602060002001549050919050565b6000818152600260205260408120546001600160a01b031680610a4f5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201526832b73a103a37b5b2b760b91b6064820152608401610b5c565b61126f6124e9565b6001600160a01b031661128a600d546001600160a01b031690565b6001600160a01b0316146112b05760405162461bcd60e51b8152600401610b5c90613b87565b8051610ed790600f9060208401906133b8565b60006001600160a01b03821661132e5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604482015269726f206164647265737360b01b6064820152608401610b5c565b506001600160a01b031660009081526003602052604090205490565b6113526124e9565b6001600160a01b031661136d600d546001600160a01b031690565b6001600160a01b0316146113935760405162461bcd60e51b8152600401610b5c90613b87565b61139d6000612a00565b565b6113a76124e9565b6001600160a01b03166113c2600d546001600160a01b031690565b6001600160a01b0316146113e85760405162461bcd60e51b8152600401610b5c90613b87565b601255565b6113f56124e9565b6001600160a01b0316611410600d546001600160a01b031690565b6001600160a01b0316146114365760405162461bcd60e51b8152600401610b5c90613b87565b601555565b60606000611448836112c3565b9050806114695760408051600080825260208201909252905b509392505050565b60008167ffffffffffffffff81111561148457611484613dac565b6040519080825280602002602001820160405280156114ad578160200160208202803683370190505b50905060005b82811015611461576114c58582611008565b8282815181106114d7576114d7613d96565b6020908102919091010152806114ec81613d25565b9150506114b3565b50919050565b6115026124e9565b6001600160a01b031661151d600d546001600160a01b031690565b6001600160a01b0316146115435760405162461bcd60e51b8152600401610b5c90613b87565b60405133904780156108fc02916000818181858888f1935050505061139d57600080fd5b82846001600160a01b0316611584600d546001600160a01b031690565b604080516001600160a01b0387811682526020820187905292909216917f096a55ec842afaa98cb78cb0352921e73c0d1caa9136309fa9c07f13f4a39a60910160405180910390a45050505050565b336001600160a01b037f000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb7952161461164b5760405162461bcd60e51b815260206004820152601f60248201527f4f6e6c7920565246436f6f7264696e61746f722063616e2066756c66696c6c006044820152606401610b5c565b60165550565b606060018054610a6490613cf0565b6116686124e9565b6001600160a01b0316611683600d546001600160a01b031690565b6001600160a01b0316146116a95760405162461bcd60e51b8152600401610b5c90613b87565b601654156116f95760405162461bcd60e51b815260206004820152601f60248201527f52616e646f6d206e756d62657220616c726561647920696e69746961746564006044820152606401610b5c565b601655565b6117066124e9565b6001600160a01b0316611721600d546001600160a01b031690565b6001600160a01b0316146117475760405162461bcd60e51b8152600401610b5c90613b87565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a082319060240160206040518083038186803b15801561178957600080fd5b505afa15801561179d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c19190613946565b9050600081116118085760405162461bcd60e51b81526020600482015260126024820152712737ba3434b733903a37903932b1b7bb32b960711b6044820152606401610b5c565b816001600160a01b031663a9059cbb611829600d546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401600060405180830381600087803b15801561187157600080fd5b505af1158015611885573d6000803e3d6000fd5b505050505050565b6118956124e9565b6001600160a01b0316826001600160a01b031614156118f65760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610b5c565b80600560006119036124e9565b6001600160a01b03908116825260208083019390935260409182016000908120918716808252919093529120805460ff1916921515929092179091556119476124e9565b6001600160a01b03167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611983911515815260200190565b60405180910390a35050565b6017818154811061199f57600080fd5b6000918252602090912001546001600160a01b0316905081565b6000610a4f82612a52565b60006119ce6124e9565b6001600160a01b03166119e9600d546001600160a01b031690565b6001600160a01b031614611a0f5760405162461bcd60e51b8152600401610b5c90613b87565b612710611a1b60085490565b1015611a5e5760405162461bcd60e51b815260206004820152601260248201527114d85b19481b5d5cdd08189948195b99195960721b6044820152606401610b5c565b60165415611aae5760405162461bcd60e51b815260206004820152601f60248201527f52616e646f6d206e756d62657220616c726561647920696e69746961746564006044820152606401610b5c565b678ac7230489e80000471015611b065760405162461bcd60e51b815260206004820152601b60248201527f6d696e203130204554482062616c616e636520726571756972656400000000006044820152606401610b5c565b6040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000001bc16d674ec80000907f000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca6001600160a01b0316906370a082319060240160206040518083038186803b158015611b8757600080fd5b505afa158015611b9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bbf9190613946565b1015611bff5760405162461bcd60e51b815260206004820152600f60248201526e4e6f7420656e6f756768204c494e4b60881b6044820152606401610b5c565b610a4f7faa77729d3466ca35ae8d28b3bbac7cc36a5031efdc430821c02bc31a238af4457f0000000000000000000000000000000000000000000000001bc16d674ec8000084612b07565b611c5b611c556124e9565b83612670565b611c775760405162461bcd60e51b8152600401610b5c90613bbc565b610fbf84848484612c9a565b611c8b6124e9565b6001600160a01b0316611ca6600d546001600160a01b031690565b6001600160a01b031614611ccc5760405162461bcd60e51b8152600401610b5c90613b87565b6014805460ff1916911515919091179055565b6060611ce9611d3a565b611cf283612ccd565b604051602001611d039291906139de565b6040516020818303038152906040529050919050565b600080611d2e600d546001600160a01b031690565b60125491509150915091565b6060600f8054610a6490613cf0565b611d516124e9565b6001600160a01b0316611d6c600d546001600160a01b031690565b6001600160a01b031614611d925760405162461bcd60e51b8152600401610b5c90613b87565b601080546001600160a01b0319166001600160a01b0392909216919091179055565b60175460609080611dd357505060408051600081526020810190915290565b60008167ffffffffffffffff811115611dee57611dee613dac565b604051908082528060200260200182016040528015611e17578160200160208202803683370190505b50905060005b82811015611e925760178181548110611e3857611e38613d96565b9060005260206000200160009054906101000a90046001600160a01b0316828281518110611e6857611e68613d96565b6001600160a01b039092166020928302919091019091015280611e8a81613d25565b915050611e1d565b5092915050565b5090565b6060604051806060016040528060228152602001613e3f60229139905090565b600e5460405163c455279160e01b81526001600160a01b03848116600483015260009281169190841690829063c45527919060240160206040518083038186803b158015611f0a57600080fd5b505afa158015611f1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4291906138c7565b6001600160a01b03161415611f5b576001915050610a4f565b6001600160a01b0380851660009081526005602090815260408083209387168352929052205460ff165b949350505050565b60118054611f9a90613cf0565b80601f0160208091040260200160405190810160405280929190818152602001828054611fc690613cf0565b80156120135780601f10611fe857610100808354040283529160200191612013565b820191906000526020600020905b815481529060010190602001808311611ff657829003601f168201915b505050505081565b600060155482610a4f9190613c8e565b6120336124e9565b6001600160a01b031661204e600d546001600160a01b031690565b6001600160a01b0316146120745760405162461bcd60e51b8152600401610b5c90613b87565b6001600160a01b0381166120d95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b5c565b61115a81612a00565b336120ec826111f0565b6001600160a01b0316146121355760405162461bcd60e51b815260206004820152601060248201526f13dddb995c9cda1a5c081b995959195960821b6044820152606401610b5c565b61213e81612a52565b61217c5760405162461bcd60e51b815260206004820152600f60248201526e2cb7ba903234b2103737ba103bb4b760891b6044820152606401610b5c565b612185336128ea565b156121d25760405162461bcd60e51b815260206004820152601860248201527f416c72656164792072656365697665642061207072697a6500000000000000006044820152606401610b5c565b601754600a1161221a5760405162461bcd60e51b8152602060048201526013602482015272141c9a5e99481b1a5b5a5d081c995858da1959606a1b6044820152606401610b5c565b601780546001810182556000919091527fc624b66cc0138b8fabc209247f72d758e1cf3343756d543badbf24212bed8c150180546001600160a01b031916339081179091556040518281527f79c99597ba23f96ba7d9b4729d81d5de16e368bfe8307fa890457fb7474ec98c9060200160405180910390a26040513390600090670de0b6b3a76400009082818181858883f19350505050158015610ed7573d6000803e3d6000fd5b60145460ff1661230b5760405162461bcd60e51b815260206004820152601460248201527314d85b19481b9bdd081cdd185c9d1959081e595d60621b6044820152606401610b5c565b60006015548261231b9190613c8e565b9050600061232860085490565b90508134101561236d5760405162461bcd60e51b815260206004820152601060248201526f2737ba1032b737bab3b41032ba3432b960811b6044820152606401610b5c565b61271061237a8285613c62565b11156123c85760405162461bcd60e51b815260206004820152601f60248201527f596f752063616e6e6f74206275792074686174206d616e7920746f6b656e73006044820152606401610b5c565b60005b838110156123fd576123dd3383612656565b816123e781613d25565b92505080806123f590613d25565b9150506123cb565b5034821015610ca457336108fc6124148434613cad565b6040518115909202916000818181858888f19350505050158015610fbf573d6000803e3d6000fd5b60003330141561249357600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b031691506124969050565b50335b90565b60006001600160e01b031982166380ac58cd60e01b14806124ca57506001600160e01b03198216635b5e139f60e01b145b80610a4f57506301ffc9a760e01b6001600160e01b0319831614610a4f565b60006124f361243c565b905090565b600081815260046020526040902080546001600160a01b0319166001600160a01b038416908117909155819061252d826111f0565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006001600160a01b0386166125cc5760405162461bcd60e51b815260206004820152602560248201527f4e61746976654d6574615472616e73616374696f6e3a20494e56414c49445f5360448201526424a3a722a960d91b6064820152608401610b5c565b60016125df6125da87612dcb565b612e48565b6040805160008152602081018083529290925260ff851690820152606081018690526080810185905260a0016020604051602081039080840390855afa15801561262d573d6000803e3d6000fd5b505050602060405103516001600160a01b0316866001600160a01b031614905095945050505050565b610ed7828260405180602001604052806000815250612e78565b6000818152600260205260408120546001600160a01b03166126e95760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610b5c565b60006126f4836111f0565b9050806001600160a01b0316846001600160a01b0316148061272f5750836001600160a01b031661272484610ae7565b6001600160a01b0316145b80611f855750611f858185611ebd565b826001600160a01b0316612752826111f0565b6001600160a01b0316146127ba5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201526839903737ba1037bbb760b91b6064820152608401610b5c565b6001600160a01b03821661281c5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610b5c565b612827838383612eab565b6128326000826124f8565b6001600160a01b038316600090815260036020526040812080546001929061285b908490613cad565b90915550506001600160a01b0382166000908152600360205260408120805460019290612889908490613c62565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60175460009081905b8082101561294f57836001600160a01b03166017838154811061291857612918613d96565b6000918252602090912001546001600160a01b0316141561293d575060019392505050565b8161294781613d25565b9250506128f3565b5060009392505050565b6000612964826111f0565b905061297281600084612eab565b61297d6000836124f8565b6001600160a01b03811660009081526003602052604081208054600192906129a6908490613cad565b909155505060008281526002602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b600d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008060165411612aa55760405162461bcd60e51b815260206004820152601860248201527f52616e646f6d206d75737420626520696e6974696174656400000000000000006044820152606401610b5c565b600061271083601654604051602001612ac8929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c612aeb9190613d40565b905060148111612afe5750600192915050565b50600092915050565b60007f000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca6001600160a01b0316634000aea07f000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb7952858786604051602001612b76929190918252602082015260400190565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401612ba393929190613a76565b602060405180830381600087803b158015612bbd57600080fd5b505af1158015612bd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bf5919061384e565b5060008481526013602081815260408084205481518084018a905280830188905230606082015260808082018390528351808303909101815260a090910190925281519183019190912093889052919052612c51906001612f63565b600086815260136020526040902055612c918582604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b95945050505050565b612ca584848461273f565b612cb184848484612fc9565b610fbf5760405162461bcd60e51b8152600401610b5c90613b35565b606081612cf15750506040805180820190915260018152600360fc1b602082015290565b8160005b8115612d1b5780612d0581613d25565b9150612d149050600a83613c7a565b9150612cf5565b60008167ffffffffffffffff811115612d3657612d36613dac565b6040519080825280601f01601f191660200182016040528015612d60576020820181803683370190505b5090505b8415611f8557612d75600183613cad565b9150612d82600a86613d40565b612d8d906030613c62565b60f81b818381518110612da257612da2613d96565b60200101906001600160f81b031916908160001a905350612dc4600a86613c7a565b9450612d64565b6000604051806080016040528060438152602001613dfc6043913980516020918201208351848301516040808701518051908601209051612e2b950193845260208401929092526001600160a01b03166040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b6000612e53600b5490565b60405161190160f01b6020820152602281019190915260428101839052606201612e2b565b612e8283836130da565b612e8f6000848484612fc9565b610ca45760405162461bcd60e51b8152600401610b5c90613b35565b6001600160a01b038316612f0657612f0181600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b612f29565b816001600160a01b0316836001600160a01b031614612f2957612f298382613228565b6001600160a01b038216612f4057610ca4816132c5565b826001600160a01b0316826001600160a01b031614610ca457610ca48282613374565b600080612f708385613c62565b905083811015612fc25760405162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006044820152606401610b5c565b9392505050565b60006001600160a01b0384163b156130d257836001600160a01b031663150b7a02612ff26124e9565b8786866040518563ffffffff1660e01b81526004016130149493929190613a39565b602060405180830381600087803b15801561302e57600080fd5b505af192505050801561305e575060408051601f3d908101601f1916820190925261305b918101906138aa565b60015b6130b8573d80801561308c576040519150601f19603f3d011682016040523d82523d6000602084013e613091565b606091505b5080516130b05760405162461bcd60e51b8152600401610b5c90613b35565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611f85565b506001611f85565b6001600160a01b0382166131305760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610b5c565b6000818152600260205260409020546001600160a01b0316156131955760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610b5c565b6131a160008383612eab565b6001600160a01b03821660009081526003602052604081208054600192906131ca908490613c62565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006001613235846112c3565b61323f9190613cad565b600083815260076020526040902054909150808214613292576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b6008546000906132d790600190613cad565b600083815260096020526040812054600880549394509092849081106132ff576132ff613d96565b90600052602060002001549050806008838154811061332057613320613d96565b600091825260208083209091019290925582815260099091526040808220849055858252812055600880548061335857613358613d80565b6001900381819060005260206000200160009055905550505050565b600061337f836112c3565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b8280546133c490613cf0565b90600052602060002090601f0160209004810192826133e6576000855561342c565b82601f106133ff57805160ff191683800117855561342c565b8280016001018555821561342c579182015b8281111561342c578251825591602001919060010190613411565b50611e999291505b80821115611e995760008155600101613434565b600067ffffffffffffffff83111561346257613462613dac565b613475601f8401601f1916602001613c0d565b905082815283838301111561348957600080fd5b828260208301376000602084830101529392505050565b600082601f8301126134b157600080fd5b813560206134c66134c183613c3e565b613c0d565b80838252828201915082860187848660051b89010111156134e657600080fd5b60005b8581101561350e5781356134fc81613dc2565b845292840192908401906001016134e9565b5090979650505050505050565b600082601f83011261352c57600080fd5b612fc283833560208501613448565b60006020828403121561354d57600080fd5b8135612fc281613dc2565b6000806040838503121561356b57600080fd5b823561357681613dc2565b9150602083013561358681613dc2565b809150509250929050565b6000806000606084860312156135a657600080fd5b83356135b181613dc2565b925060208401356135c181613dc2565b929592945050506040919091013590565b600080600080600060a086880312156135ea57600080fd5b85356135f581613dc2565b9450602086013561360581613dc2565b935060408601359250606086013561361c81613dc2565b949793965091946080013592915050565b6000806000806080858703121561364357600080fd5b843561364e81613dc2565b9350602085013561365e81613dc2565b925060408501359150606085013567ffffffffffffffff81111561368157600080fd5b61368d8782880161351b565b91505092959194509250565b600080604083850312156136ac57600080fd5b82356136b781613dc2565b9150602083013561358681613dd7565b600080600080600060a086880312156136df57600080fd5b85356136ea81613dc2565b9450602086013567ffffffffffffffff81111561370657600080fd5b6137128882890161351b565b9450506040860135925060608601359150608086013560ff8116811461373757600080fd5b809150509295509295909350565b6000806040838503121561375857600080fd5b823561376381613dc2565b946020939093013593505050565b6000806040838503121561378457600080fd5b823567ffffffffffffffff8082111561379c57600080fd5b818501915085601f8301126137b057600080fd5b813560206137c06134c183613c3e565b8083825282820191508286018a848660051b89010111156137e057600080fd5b600096505b848710156138035780358352600196909601959183019183016137e5565b509650508601359250508082111561381a57600080fd5b50613827858286016134a0565b9150509250929050565b60006020828403121561384357600080fd5b8135612fc281613dd7565b60006020828403121561386057600080fd5b8151612fc281613dd7565b6000806040838503121561387e57600080fd5b50508035926020909101359150565b60006020828403121561389f57600080fd5b8135612fc281613de5565b6000602082840312156138bc57600080fd5b8151612fc281613de5565b6000602082840312156138d957600080fd5b8151612fc281613dc2565b6000602082840312156138f657600080fd5b813567ffffffffffffffff81111561390d57600080fd5b8201601f8101841361391e57600080fd5b611f8584823560208401613448565b60006020828403121561393f57600080fd5b5035919050565b60006020828403121561395857600080fd5b5051919050565b60008151808452613977816020860160208601613cc4565b601f01601f19169290920160200192915050565b6000825161399d818460208701613cc4565b9190910192915050565b600083516139b9818460208801613cc4565b60609390931b6bffffffffffffffffffffffff19169190920190815260140192915050565b600083516139f0818460208801613cc4565b835190830190613a04818360208801613cc4565b01949350505050565b6001600160a01b03848116825283166020820152606060408201819052600090612c919083018461395f565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613a6c9083018461395f565b9695505050505050565b60018060a01b0384168152826020820152606060408201526000612c91606083018461395f565b6020808252825182820181905260009190848201906040850190845b81811015613ade5783516001600160a01b031683529284019291840191600101613ab9565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613ade57835183529284019291840191600101613b06565b602081526000612fc2602083018461395f565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b604051601f8201601f1916810167ffffffffffffffff81118282101715613c3657613c36613dac565b604052919050565b600067ffffffffffffffff821115613c5857613c58613dac565b5060051b60200190565b60008219821115613c7557613c75613d54565b500190565b600082613c8957613c89613d6a565b500490565b6000816000190483118215151615613ca857613ca8613d54565b500290565b600082821015613cbf57613cbf613d54565b500390565b60005b83811015613cdf578181015183820152602001613cc7565b83811115610fbf5750506000910152565b600181811c90821680613d0457607f821691505b602082108114156114f457634e487b7160e01b600052602260045260246000fd5b6000600019821415613d3957613d39613d54565b5060010190565b600082613d4f57613d4f613d6a565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461115a57600080fd5b801515811461115a57600080fd5b6001600160e01b03198116811461115a57600080fdfe4d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e61747572652968747470733a2f2f756e69716c792e696f2f6170692f6e66742d67656e657369732fa26469706673582212205adf4d24848f3e599a1110d0be7c407fa8f355a20311f48c1565b436f59758af64736f6c63430008060033
Verified Source Code Partial Match
Compiler: v0.8.6+commit.11564f7e
EVM: berlin
Optimization: Yes (200 runs)
UniqGenesis.sol 219 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;
import "./utils/ERC721/ERC721Claimable.sol";
import "./utils/VRF/VRFConsumerBase.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract UniqGenesis is ERC721Claimable, VRFConsumerBase {
// ----- EVENTS ----- //
event PrizeCollected(address indexed _winner, uint256 _tokenId);
// ----- VARIABLES ----- //
//Sale
uint256 internal constant _maxUniqly = 10000;
bool internal _saleStarted;
uint256 internal _tokenPrice;
//VRF + Prizes
bytes32 internal immutable keyHash;
uint256 internal immutable fee;
uint256 public randomResult;
address[] public winners;
// ----- CONSTRUCTOR ----- //
constructor(
string memory _bURI,
string memory _name,
string memory _symbol,
address _vrfCoordinator,
address _link,
bytes32 _keyHash,
uint256 _fee,
address _proxyRegistryAddress,
address _claimingContractAddress,
uint256 _tokenSalePrice,
uint256 _royaltyFee
)
ERC721Claimable(_name, _symbol, _bURI, _proxyRegistryAddress,_claimingContractAddress, _royaltyFee)
VRFConsumerBase(_vrfCoordinator, _link)
{
keyHash = _keyHash;
fee = _fee;
_tokenPrice = _tokenSalePrice;
}
// ----- VIEWS ----- //
function contractURI() public pure returns (string memory) {
return "https://uniqly.io/api/nft-genesis/";
}
function calculateEthPriceForExactUniqs(uint256 _number)
external
view
returns (uint256)
{
return _number * _tokenPrice;
}
function getAllWinners() external view returns (address[] memory) {
uint256 winnersCount = winners.length;
if (winnersCount == 0) {
return new address[](0);
} else {
address[] memory result = new address[](winnersCount);
uint256 index;
for (index = 0; index < winnersCount; index++) {
result[index] = winners[index];
}
return result;
}
}
function getWinner(uint256 _arrayKey) external view returns (address) {
return winners[_arrayKey];
}
function getWinnersCount() external view returns (uint256) {
return winners.length;
}
function checkWin(uint256 _tokenId) external view returns (bool) {
return _isWinner(_tokenId);
}
function isAlreadyRececeivedPrize(address _potWinner)
external
view
returns (bool)
{
return (_isAlreadyRececeivedPrize(_potWinner));
}
function _isAlreadyRececeivedPrize(address _potWinner)
internal
view
returns (bool)
{
uint256 i;
uint256 winnersCount = winners.length;
for (i = 0; i < winnersCount; i++) {
if (winners[i] == _potWinner) return true;
}
return false;
}
// ----- PUBLIC METHODS ----- //
//emits Transfer event
function mintUniqly(uint256 numUniqlies) external payable {
require(_saleStarted, "Sale not started yet");
uint256 requiredValue = numUniqlies * _tokenPrice;
uint256 mintIndex = totalSupply();
require(msg.value >= requiredValue, "Not enough ether");
require(
(numUniqlies + mintIndex) <= _maxUniqly,
"You cannot buy that many tokens"
);
for (uint256 i = 0; i < numUniqlies; i++) {
_safeMint(msg.sender, mintIndex);
mintIndex++;
}
// send back ETH if one overpay by accident
if (requiredValue < msg.value) {
payable(msg.sender).transfer(msg.value - requiredValue);
}
}
function collectPrize(uint256 _tokenId) external {
require(ownerOf(_tokenId) == msg.sender, "Ownership needed");
require(_isWinner(_tokenId), "You did not win");
require(
!_isAlreadyRececeivedPrize(msg.sender),
"Already received a prize"
);
require(winners.length < 10, "Prize limit reached");
winners.push(msg.sender);
emit PrizeCollected(msg.sender, _tokenId);
payable(msg.sender).transfer(1 ether);
}
receive() external payable {}
// ----- PRIVATE METHODS ----- //
function fulfillRandomness(bytes32, uint256 randomness) internal override {
randomResult = randomness;
}
function _isWinner(uint256 id) internal view returns (bool) {
require(randomResult > 0, "Random must be initiated");
uint256 result = (
uint256(keccak256(abi.encodePacked(id, randomResult)))
) % 10000;
if (result <= 20) return true;
return false;
}
// ----- OWNERS METHODS ----- //
function getRandomNumber(uint256 adminProvidedSeed)
external
onlyOwner
returns (bytes32)
{
require(totalSupply() >= _maxUniqly, "Sale must be ended");
require(randomResult == 0, "Random number already initiated");
require(address(this).balance >= 10 ether, "min 10 ETH balance required");
require(
LINK.balanceOf(address(this)) >= fee,
"Not enough LINK"
);
return requestRandomness(keyHash, fee, adminProvidedSeed);
}
function batchMintAsOwner(
uint[] memory _ids,
address[] memory _addresses
) external onlyOwner {
uint len = _ids.length;
require(len == _addresses.length, "Arrays length");
uint256 i = 0;
for (i = 0; i < len; i++) {
_safeMint(_addresses[i], _ids[i]);
}
}
function editSaleStatus(bool _isEnable) external onlyOwner{
_saleStarted = _isEnable;
}
function withdrawAll() external onlyOwner {
require(payable(msg.sender).send(address(this).balance));
}
function recoverERC20(address token) external onlyOwner {
uint256 val = IERC20(token).balanceOf(address(this));
require(val > 0, "Nothing to recover");
// use interface that not return value (USDT case)
Ierc20(token).transfer(owner(), val);
}
function setRandomResualAsAdmin(uint256 _newRandomResult) external onlyOwner{
require(randomResult == 0, "Random number already initiated");
randomResult = _newRandomResult;
}
function editTokenPrice(uint256 _newPrice) external onlyOwner{
_tokenPrice = _newPrice;
}
function editTokenUri(string memory _ttokenUri) external onlyOwner {
_token_uri = _ttokenUri;
}
}
interface Ierc20 {
function transfer(address, uint256) external;
}
VRFConsumerBase.sol 194 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./SafeMathChainlink.sol";
import "./LinkTokenInterface.sol";
import "./VRFRequestIDBase.sol";
/** ****************************************************************************
* @notice Interface for contracts using VRF randomness
* *****************************************************************************
* @dev PURPOSE
*
* @dev Reggie the Random Oracle (not his real job) wants to provide randomness
* @dev to Vera the verifier in such a way that Vera can be sure he's not
* @dev making his output up to suit himself. Reggie provides Vera a public key
* @dev to which he knows the secret key. Each time Vera provides a seed to
* @dev Reggie, he gives back a value which is computed completely
* @dev deterministically from the seed and the secret key.
*
* @dev Reggie provides a proof by which Vera can verify that the output was
* @dev correctly computed once Reggie tells it to her, but without that proof,
* @dev the output is indistinguishable to her from a uniform random sample
* @dev from the output space.
*
* @dev The purpose of this contract is to make it easy for unrelated contracts
* @dev to talk to Vera the verifier about the work Reggie is doing, to provide
* @dev simple access to a verifiable source of randomness.
* *****************************************************************************
* @dev USAGE
*
* @dev Calling contracts must inherit from VRFConsumerBase, and can
* @dev initialize VRFConsumerBase's attributes in their constructor as
* @dev shown:
*
* @dev contract VRFConsumer {
* @dev constuctor(<other arguments>, address _vrfCoordinator, address _link)
* @dev VRFConsumerBase(_vrfCoordinator, _link) public {
* @dev <initialization with other arguments goes here>
* @dev }
* @dev }
*
* @dev The oracle will have given you an ID for the VRF keypair they have
* @dev committed to (let's call it keyHash), and have told you the minimum LINK
* @dev price for VRF service. Make sure your contract has sufficient LINK, and
* @dev call requestRandomness(keyHash, fee, seed), where seed is the input you
* @dev want to generate randomness from.
*
* @dev Once the VRFCoordinator has received and validated the oracle's response
* @dev to your request, it will call your contract's fulfillRandomness method.
*
* @dev The randomness argument to fulfillRandomness is the actual random value
* @dev generated from your seed.
*
* @dev The requestId argument is generated from the keyHash and the seed by
* @dev makeRequestId(keyHash, seed). If your contract could have concurrent
* @dev requests open, you can use the requestId to track which seed is
* @dev associated with which randomness. See VRFRequestIDBase.sol for more
* @dev details. (See "SECURITY CONSIDERATIONS" for principles to keep in mind,
* @dev if your contract could have multiple requests in flight simultaneously.)
*
* @dev Colliding `requestId`s are cryptographically impossible as long as seeds
* @dev differ. (Which is critical to making unpredictable randomness! See the
* @dev next section.)
*
* *****************************************************************************
* @dev SECURITY CONSIDERATIONS
*
* @dev A method with the ability to call your fulfillRandomness method directly
* @dev could spoof a VRF response with any random value, so it's critical that
* @dev it cannot be directly called by anything other than this base contract
* @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method).
*
* @dev For your users to trust that your contract's random behavior is free
* @dev from malicious interference, it's best if you can write it so that all
* @dev behaviors implied by a VRF response are executed *during* your
* @dev fulfillRandomness method. If your contract must store the response (or
* @dev anything derived from it) and use it later, you must ensure that any
* @dev user-significant behavior which depends on that stored value cannot be
* @dev manipulated by a subsequent VRF request.
*
* @dev Similarly, both miners and the VRF oracle itself have some influence
* @dev over the order in which VRF responses appear on the blockchain, so if
* @dev your contract could have multiple VRF requests in flight simultaneously,
* @dev you must ensure that the order in which the VRF responses arrive cannot
* @dev be used to manipulate your contract's user-significant behavior.
*
* @dev Since the ultimate input to the VRF is mixed with the block hash of the
* @dev block in which the request is made, user-provided seeds have no impact
* @dev on its economic security properties. They are only included for API
* @dev compatability with previous versions of this contract.
*
* @dev Since the block hash of the block which contains the requestRandomness
* @dev call is mixed into the input to the VRF *last*, a sufficiently powerful
* @dev miner could, in principle, fork the blockchain to evict the block
* @dev containing the request, forcing the request to be included in a
* @dev different block with a different hash, and therefore a different input
* @dev to the VRF. However, such an attack would incur a substantial economic
* @dev cost. This cost scales with the number of blocks the VRF oracle waits
* @dev until it calls responds to a request.
*/
abstract contract VRFConsumerBase is VRFRequestIDBase {
using SafeMathChainlink for uint256;
/**
* @notice fulfillRandomness handles the VRF response. Your contract must
* @notice implement it. See "SECURITY CONSIDERATIONS" above for important
* @notice principles to keep in mind when implementing your fulfillRandomness
* @notice method.
*
* @dev VRFConsumerBase expects its subcontracts to have a method with this
* @dev signature, and will call it once it has verified the proof
* @dev associated with the randomness. (It is triggered via a call to
* @dev rawFulfillRandomness, below.)
*
* @param requestId The Id initially returned by requestRandomness
* @param randomness the VRF output
*/
function fulfillRandomness(bytes32 requestId, uint256 randomness)
internal virtual;
/**
* @notice requestRandomness initiates a request for VRF output given _seed
*
* @dev The fulfillRandomness method receives the output, once it's provided
* @dev by the Oracle, and verified by the vrfCoordinator.
*
* @dev The _keyHash must already be registered with the VRFCoordinator, and
* @dev the _fee must exceed the fee specified during registration of the
* @dev _keyHash.
*
* @dev The _seed parameter is vestigial, and is kept only for API
* @dev compatibility with older versions. It can't *hurt* to mix in some of
* @dev your own randomness, here, but it's not necessary because the VRF
* @dev oracle will mix the hash of the block containing your request into the
* @dev VRF seed it ultimately uses.
*
* @param _keyHash ID of public key against which randomness is generated
* @param _fee The amount of LINK to send with the request
* @param _seed seed mixed into the input of the VRF.
*
* @return requestId unique ID for this request
*
* @dev The returned requestId can be used to distinguish responses to
* @dev concurrent requests. It is passed as the first argument to
* @dev fulfillRandomness.
*/
function requestRandomness(bytes32 _keyHash, uint256 _fee, uint256 _seed)
internal returns (bytes32 requestId)
{
LINK.transferAndCall(vrfCoordinator, _fee, abi.encode(_keyHash, _seed));
// This is the seed passed to VRFCoordinator. The oracle will mix this with
// the hash of the block containing this request to obtain the seed/input
// which is finally passed to the VRF cryptographic machinery.
uint256 vRFSeed = makeVRFInputSeed(_keyHash, _seed, address(this), nonces[_keyHash]);
// nonces[_keyHash] must stay in sync with
// VRFCoordinator.nonces[_keyHash][this], which was incremented by the above
// successful LINK.transferAndCall (in VRFCoordinator.randomnessRequest).
// This provides protection against the user repeating their input seed,
// which would result in a predictable/duplicate output, if multiple such
// requests appeared in the same block.
nonces[_keyHash] = nonces[_keyHash].add(1);
return makeRequestId(_keyHash, vRFSeed);
}
LinkTokenInterface immutable internal LINK;
address immutable private vrfCoordinator;
// Nonces for each VRF key from which randomness has been requested.
//
// Must stay in sync with VRFCoordinator[_keyHash][this]
mapping(bytes32 /* keyHash */ => uint256 /* nonce */) private nonces;
/**
* @param _vrfCoordinator address of VRFCoordinator contract
* @param _link address of LINK token contract
*
* @dev https://docs.chain.link/docs/link-token-contracts
*/
constructor(address _vrfCoordinator, address _link) {
vrfCoordinator = _vrfCoordinator;
LINK = LinkTokenInterface(_link);
}
// rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF
// proof. rawFulfillRandomness then calls fulfillRandomness, after validating
// the origin of the call
function rawFulfillRandomness(bytes32 requestId, uint256 randomness) external {
require(msg.sender == vrfCoordinator, "Only VRFCoordinator can fulfill");
fulfillRandomness(requestId, randomness);
}
}
Address.sol 210 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - 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
* ====
*/
function isContract(address account) internal view 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.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) private pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
Context.sol 23 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
Strings.sol 66 lines
// SPDX-License-Identifier: MIT
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);
}
}
VRFRequestIDBase.sol 40 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract VRFRequestIDBase {
/**
* @notice returns the seed which is actually input to the VRF coordinator
*
* @dev To prevent repetition of VRF output due to repetition of the
* @dev user-supplied seed, that seed is combined in a hash with the
* @dev user-specific nonce, and the address of the consuming contract. The
* @dev risk of repetition is mostly mitigated by inclusion of a blockhash in
* @dev the final seed, but the nonce does protect against repetition in
* @dev requests which are included in a single block.
*
* @param _userSeed VRF seed input provided by user
* @param _requester Address of the requesting contract
* @param _nonce User-specific nonce at the time of the request
*/
function makeVRFInputSeed(bytes32 _keyHash, uint256 _userSeed,
address _requester, uint256 _nonce)
internal pure returns (uint256)
{
return uint256(keccak256(abi.encode(_keyHash, _userSeed, _requester, _nonce)));
}
/**
* @notice Returns the id for this request
* @param _keyHash The serviceAgreement ID to be used for this request
* @param _vRFInputSeed The seed to be passed directly to the VRF
* @return The id for this request
*
* @dev Note that _vRFInputSeed is not the seed passed by the consuming
* @dev contract, but the one generated by makeVRFInputSeed
*/
function makeRequestId(
bytes32 _keyHash, uint256 _vRFInputSeed) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(_keyHash, _vRFInputSeed));
}
}
Ownable.sol 71 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../utils/Context.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 Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_setOwner(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_setOwner(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
SafeMathChainlink.sol 108 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMathChainlink {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, "SafeMath: division by zero");
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, "SafeMath: modulo by zero");
return a % b;
}
}
ERC721Claimable.sol 156 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "../common/meta-transactions/ContentMixin.sol";
import "../common/meta-transactions/NativeMetaTransaction.sol";
contract OwnableDelegateProxy {}
contract ProxyRegistry {
mapping(address => OwnableDelegateProxy) public proxies;
}
abstract contract ERC721Claimable is
ContextMixin,
ERC721Enumerable,
NativeMetaTransaction,
Ownable
{
// ----- VARIABLES ----- //
address proxyRegistryAddress;
string internal _token_uri;
address internal _claimingAddress;
string public METADATA_PROVENANCE_HASH;
uint256 public ROYALTY_FEE;
// ----- EVENTS ----- //
event ReceivedRoyalties(
address indexed _royaltyRecipient,
address indexed _buyer,
uint256 indexed _tokenId,
address _tokenPaid,
uint256 _amount
);
// ----- CONSTRUCTOR ----- //
constructor(
string memory _name,
string memory _symbol,
string memory _uri,
address _proxyRegistryAddress,
address _claimingContractAddress,
uint256 _royaltyFee
) ERC721(_name, _symbol) {
proxyRegistryAddress = _proxyRegistryAddress;
_token_uri = _uri;
_initializeEIP712(_name);
_claimingAddress = _claimingContractAddress;
ROYALTY_FEE = _royaltyFee;
}
// ----- VIEWS ----- //
function baseTokenURI() public view virtual returns (string memory){
return _token_uri;
}
function tokenURI(uint256 _tokenId)
public
view
override
returns (string memory)
{
return
string(
abi.encodePacked(baseTokenURI(), Strings.toString(_tokenId))
);
}
function getClaimerAddress() external view returns (address) {
return _claimingAddress;
}
function royaltyInfo(uint256)
external
view
returns (address receiver, uint256 amount)
{
return (owner(), ROYALTY_FEE);
}
function isApprovedForAll(address owner, address operator)
public
view
override
returns (bool)
{
ProxyRegistry proxyRegistry = ProxyRegistry(proxyRegistryAddress);
if (address(proxyRegistry.proxies(owner)) == operator) {
return true;
}
return super.isApprovedForAll(owner, operator);
}
function _msgSender() internal view override returns (address sender) {
return ContextMixin.msgSender();
}
function tokensOfOwner(address _owner)
external
view
returns (uint256[] memory)
{
uint256 tokenCount = balanceOf(_owner);
if (tokenCount == 0) {
// Return an empty array
return new uint256[](0);
} else {
uint256[] memory result = new uint256[](tokenCount);
uint256 index;
for (index = 0; index < tokenCount; index++) {
result[index] = tokenOfOwnerByIndex(_owner, index);
}
return result;
}
}
// ----- PUBLIC METHODS ----- //
function burn(uint256 _tokenId) external {
if (msg.sender != _claimingAddress) {
require(
_isApprovedOrOwner(msg.sender, _tokenId),
"Ownership or approval required"
);
}
_burn(_tokenId);
}
function receivedRoyalties(
address,
address _buyer,
uint256 _tokenId,
address _tokenPaid,
uint256 _amount
) external {
emit ReceivedRoyalties(owner(), _buyer, _tokenId, _tokenPaid, _amount);
}
// ----- OWNERS METHODS ----- //
function editClaimingAdress(address _newAddress) external onlyOwner {
_claimingAddress = _newAddress;
}
function editRoyaltyFee(uint256 _newFee) external onlyOwner{
ROYALTY_FEE = _newFee;
}
function setProvenanceHash(string memory _hash) external onlyOwner {
METADATA_PROVENANCE_HASH = _hash;
}
}
LinkTokenInterface.sol 17 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface LinkTokenInterface {
function allowance(address owner, address spender) external view returns (uint256 remaining);
function approve(address spender, uint256 value) external returns (bool success);
function balanceOf(address owner) external view returns (uint256 balance);
function decimals() external view returns (uint8 decimalPlaces);
function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
function increaseApproval(address spender, uint256 subtractedValue) external;
function name() external view returns (string memory tokenName);
function symbol() external view returns (string memory tokenSymbol);
function totalSupply() external view returns (uint256 totalTokensIssued);
function transfer(address to, uint256 value) external returns (bool success);
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success);
function transferFrom(address from, address to, uint256 value) external returns (bool success);
}
IERC20.sol 81 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
ERC721.sol 411 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to owner address
mapping(uint256 => address) private _owners;
// Mapping owner address to token count
mapping(address => uint256) private _balances;
// Mapping from token ID to approved address
mapping(uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC721Metadata).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overriden in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
require(operator != _msgSender(), "ERC721: approve to caller");
_operatorApprovals[_msgSender()][operator] = approved;
emit ApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory _data
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* `_data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(
address from,
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(
address to,
uint256 tokenId,
bytes memory _data
) internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
// Clear approvals
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
// Clear approvals from the previous owner
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits a {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
/**
* @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
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver(to).onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual {}
}
IERC721.sol 142 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
ERC165.sol 28 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
IERC165.sol 24 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
IERC721Receiver.sol 26 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
EIP712Base.sol 77 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Initializable} from "./Initializable.sol";
contract EIP712Base is Initializable {
struct EIP712Domain {
string name;
string version;
address verifyingContract;
bytes32 salt;
}
string constant public ERC712_VERSION = "1";
bytes32 internal constant EIP712_DOMAIN_TYPEHASH = keccak256(
bytes(
"EIP712Domain(string name,string version,address verifyingContract,bytes32 salt)"
)
);
bytes32 internal domainSeperator;
// supposed to be called once while initializing.
// one of the contracts that inherits this contract follows proxy pattern
// so it is not possible to do this in a constructor
function _initializeEIP712(
string memory name
)
internal
initializer
{
_setDomainSeperator(name);
}
function _setDomainSeperator(string memory name) internal {
domainSeperator = keccak256(
abi.encode(
EIP712_DOMAIN_TYPEHASH,
keccak256(bytes(name)),
keccak256(bytes(ERC712_VERSION)),
address(this),
bytes32(getChainId())
)
);
}
function getDomainSeperator() public view returns (bytes32) {
return domainSeperator;
}
function getChainId() public view returns (uint256) {
uint256 id;
assembly {
id := chainid()
}
return id;
}
/**
* Accept message hash and returns hash message in EIP712 compatible form
* So that it can be used to recover signer from signature signed using EIP712 formatted data
* https://eips.ethereum.org/EIPS/eip-712
* "\\x19" makes the encoding deterministic
* "\\x01" is the version byte to make it compatible to EIP-191
*/
function toTypedMessageHash(bytes32 messageHash)
internal
view
returns (bytes32)
{
return
keccak256(
abi.encodePacked("\x19\x01", getDomainSeperator(), messageHash)
);
}
}
ContentMixin.sol 26 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
abstract contract ContextMixin {
function msgSender()
internal
view
returns (address payable sender)
{
if (msg.sender == address(this)) {
bytes memory array = msg.data;
uint256 index = msg.data.length;
assembly {
// Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
sender := and(
mload(add(array, index)),
0xffffffffffffffffffffffffffffffffffffffff
)
}
} else {
sender = payable(msg.sender);
}
return sender;
}
}
Initializable.sol 13 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Initializable {
bool inited = false;
modifier initializer() {
require(!inited, "already inited");
_;
inited = true;
}
}
IERC721Metadata.sol 26 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Metadata is IERC721 {
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
}
NativeMetaTransaction.sol 105 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./EIP712Base.sol";
contract NativeMetaTransaction is EIP712Base {
bytes32 private constant META_TRANSACTION_TYPEHASH =
keccak256(
bytes(
"MetaTransaction(uint256 nonce,address from,bytes functionSignature)"
)
);
event MetaTransactionExecuted(
address userAddress,
address payable relayerAddress,
bytes functionSignature
);
mapping(address => uint256) nonces;
/*
* Meta transaction structure.
* No point of including value field here as if user is doing value transfer then he has the funds to pay for gas
* He should call the desired function directly in that case.
*/
struct MetaTransaction {
uint256 nonce;
address from;
bytes functionSignature;
}
function executeMetaTransaction(
address userAddress,
bytes memory functionSignature,
bytes32 sigR,
bytes32 sigS,
uint8 sigV
) public payable returns (bytes memory) {
MetaTransaction memory metaTx = MetaTransaction({
nonce: nonces[userAddress],
from: userAddress,
functionSignature: functionSignature
});
require(
verify(userAddress, metaTx, sigR, sigS, sigV),
"Signer and signature do not match"
);
// increase nonce for user (to avoid re-use)
nonces[userAddress]++;
emit MetaTransactionExecuted(
userAddress,
payable(msg.sender),
functionSignature
);
// Append userAddress and relayer address at the end to extract it from calling context
(bool success, bytes memory returnData) = address(this).call(
abi.encodePacked(functionSignature, userAddress)
);
require(success, "Function call not successful");
return returnData;
}
function hashMetaTransaction(MetaTransaction memory metaTx)
internal
pure
returns (bytes32)
{
return
keccak256(
abi.encode(
META_TRANSACTION_TYPEHASH,
metaTx.nonce,
metaTx.from,
keccak256(metaTx.functionSignature)
)
);
}
function getNonce(address user) public view returns (uint256 nonce) {
nonce = nonces[user];
}
function verify(
address signer,
MetaTransaction memory metaTx,
bytes32 sigR,
bytes32 sigS,
uint8 sigV
) internal view returns (bool) {
require(signer != address(0), "NativeMetaTransaction: INVALID_SIGNER");
return
signer ==
ecrecover(
toTypedMessageHash(hashMetaTransaction(metaTx)),
sigV,
sigR,
sigS
);
}
}
ERC721Enumerable.sol 162 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../ERC721.sol";
import "./IERC721Enumerable.sol";
/**
* @dev This implements an optional extension of {ERC721} defined in the EIP that adds
* enumerability of all the token ids in the contract as well as all token ids owned by each
* account.
*/
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
// Mapping from owner to list of owned token IDs
mapping(address => mapping(uint256 => uint256)) private _ownedTokens;
// Mapping from token ID to index of the owner tokens list
mapping(uint256 => uint256) private _ownedTokensIndex;
// Array with all token ids, used for enumeration
uint256[] private _allTokens;
// Mapping from token id to position in the allTokens array
mapping(uint256 => uint256) private _allTokensIndex;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
return _ownedTokens[owner][index];
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _allTokens.length;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
return _allTokens[index];
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual override {
super._beforeTokenTransfer(from, to, tokenId);
if (from == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (from != to) {
_removeTokenFromOwnerEnumeration(from, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (to != from) {
_addTokenToOwnerEnumeration(to, tokenId);
}
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = ERC721.balanceOf(to);
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
uint256 tokenIndex = _ownedTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
delete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
// an 'if' statement (like in _removeTokenFromOwnerEnumeration)
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
// This also deletes the contents at the last position of the array
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
}
IERC721Enumerable.sol 28 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}
Read Contract
ERC712_VERSION 0x0f7e5970 → string
METADATA_PROVENANCE_HASH 0xf0c9dc60 → string
ROYALTY_FEE 0x335477fc → uint256
balanceOf 0x70a08231 → uint256
baseTokenURI 0xd547cfb7 → string
calculateEthPriceForExactUniqs 0xf0cc3b85 → uint256
checkWin 0xa4db6252 → bool
contractURI 0xe8a3d485 → string
getAllWinners 0xdc6b8627 → address[]
getApproved 0x081812fc → address
getChainId 0x3408e470 → uint256
getClaimerAddress 0x661b1d2c → address
getDomainSeperator 0x20379ee5 → bytes32
getNonce 0x2d0335ab → uint256
getWinner 0x4129b2c9 → address
getWinnersCount 0x0b75cef4 → uint256
isAlreadyRececeivedPrize 0x2ca40ed8 → bool
isApprovedForAll 0xe985e9c5 → bool
name 0x06fdde03 → string
owner 0x8da5cb5b → address
ownerOf 0x6352211e → address
randomResult 0x42619f66 → uint256
royaltyInfo 0xcef6d368 → address, uint256
supportsInterface 0x01ffc9a7 → bool
symbol 0x95d89b41 → string
tokenByIndex 0x4f6ccce7 → uint256
tokenOfOwnerByIndex 0x2f745c59 → uint256
tokenURI 0xc87b56dd → string
tokensOfOwner 0x8462151c → uint256[]
totalSupply 0x18160ddd → uint256
winners 0xa2fb1175 → address
Write Contract 24 functions
These functions modify contract state and require a wallet transaction to execute.
approve 0x095ea7b3
address to
uint256 tokenId
batchMintAsOwner 0x1df61141
uint256[] _ids
address[] _addresses
burn 0x42966c68
uint256 _tokenId
collectPrize 0xf449619e
uint256 _tokenId
editClaimingAdress 0xd955ec55
address _newAddress
editRoyaltyFee 0x742af72b
uint256 _newFee
editSaleStatus 0xbe0d41b8
bool _isEnable
editTokenPrice 0x834bb61b
uint256 _newPrice
editTokenUri 0x652489d4
string _ttokenUri
executeMetaTransaction 0x0c53c51c
address userAddress
bytes functionSignature
bytes32 sigR
bytes32 sigS
uint8 sigV
returns: bytes
getRandomNumber 0xb37217a4
uint256 adminProvidedSeed
returns: bytes32
mintUniqly 0xfadd3087
uint256 numUniqlies
rawFulfillRandomness 0x94985ddd
bytes32 requestId
uint256 randomness
receivedRoyalties 0x8589ff45
address
address _buyer
uint256 _tokenId
address _tokenPaid
uint256 _amount
recoverERC20 0x9e8c708e
address token
renounceOwnership 0x715018a6
No parameters
safeTransferFrom 0x42842e0e
address from
address to
uint256 tokenId
safeTransferFrom 0xb88d4fde
address from
address to
uint256 tokenId
bytes _data
setApprovalForAll 0xa22cb465
address operator
bool approved
setProvenanceHash 0x10969523
string _hash
setRandomResualAsAdmin 0x98fa734b
uint256 _newRandomResult
transferFrom 0x23b872dd
address from
address to
uint256 tokenId
transferOwnership 0xf2fde38b
address newOwner
withdrawAll 0x853828b6
No parameters
Recent Transactions
No transactions found for this address