Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0xC9677Cd8e9652F1b1aaDd3429769b0Ef8D7A0425
Balance 0 ETH
Nonce 1
Code Size 17875 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

17875 bytes
0x6080604052600436106103905760003560e01c80638da5cb5b116101dc578063cffec33811610102578063e72b29de116100a0578063f452472e1161006f578063f452472e14610af3578063f55df94e14610b13578063f91798b114610b33578063f98f51c114610b5357600080fd5b8063e72b29de14610a50578063e985e9c514610a6a578063efd0cbf914610ac0578063f2fde38b14610ad357600080fd5b8063d7959cf9116100dc578063d7959cf9146109f0578063dd0d1bbc14610a05578063e1fcd70714610a25578063e33b7de314610a3b57600080fd5b8063cffec3381461099a578063d5abeb01146109ba578063d6289983146109d057600080fd5b80639b5eceb91161017a578063ac9384b911610149578063ac9384b914610901578063b88d4fde14610917578063c87b56dd14610937578063ce7c2ac21461095757600080fd5b80639b5eceb91461088b5780639fbd756f146108a1578063a22cb465146108c1578063a3237827146108e157600080fd5b806396ea3a47116101b657806396ea3a47146107fc578063974610851461081c5780639852595c1461083257806399edbb4d1461087557600080fd5b80638da5cb5b1461079c57806395d89b41146107c75780639619c3bc146107dc57600080fd5b80633a98ef39116102c15780636c0360eb1161025f5780638462151c1161022e5780638462151c1461070f57806384a303d61461073c5780638b533ea41461075c5780638b83209b1461077c57600080fd5b80636c0360eb146106af57806370a08231146106c4578063715018a6146106e4578063812a4a41146106f957600080fd5b806348808c101161029b57806348808c101461062f5780634f6ccce71461064f5780635ad1c1b51461066f5780636352211e1461068f57600080fd5b80633a98ef39146105da57806342842e0e146105ef5780634530a8321461060f57600080fd5b8063191655871161032e57806325a8a88e1161030857806325a8a88e146105675780632f745c591461058757806334b1d403146105a757806334c2076b146105c757600080fd5b8063191655871461050857806323b872dd14610528578063242337fd1461054857600080fd5b8063081812fc1161036a578063081812fc14610464578063095ea7b3146104a957806312d71894146104c957806318160ddd146104e957600080fd5b806301ffc9a7146103eb57806302fe53051461042057806306fdde031461044257600080fd5b366103e6577f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be770336040805173ffffffffffffffffffffffffffffffffffffffff90921682523460208301520160405180910390a1005b600080fd5b3480156103f757600080fd5b5061040b610406366004613db3565b610b66565b60405190151581526020015b60405180910390f35b34801561042c57600080fd5b5061044061043b366004613eaa565b610bc2565b005b34801561044e57600080fd5b50610457610c45565b6040516104179190613f55565b34801561047057600080fd5b5061048461047f366004613f68565b610cd7565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610417565b3480156104b557600080fd5b506104406104c4366004613fa3565b610d7d565b3480156104d557600080fd5b506104406104e4366004613f68565b610ed6565b3480156104f557600080fd5b506002545b604051908152602001610417565b34801561051457600080fd5b50610440610523366004613fcf565b610f42565b34801561053457600080fd5b50610440610543366004613fec565b61117d565b34801561055457600080fd5b50600d5461040b90610100900460ff1681565b34801561057357600080fd5b50610440610582366004614042565b611204565b34801561059357600080fd5b506104fa6105a2366004613fa3565b61129c565b3480156105b357600080fd5b506104406105c2366004613f68565b6113b8565b6104406105d536600461405d565b611424565b3480156105e657600080fd5b506006546104fa565b3480156105fb57600080fd5b5061044061060a366004613fec565b611702565b34801561061b57600080fd5b5061044061062a366004613f68565b61171d565b34801561063b57600080fd5b5061048461064a3660046140ca565b611789565b34801561065b57600080fd5b506104fa61066a366004613f68565b61179c565b34801561067b57600080fd5b5061044061068a366004614042565b6117f9565b34801561069b57600080fd5b506104846106aa366004613f68565b611897565b3480156106bb57600080fd5b50610457611944565b3480156106d057600080fd5b506104fa6106df366004613fcf565b6119d2565b3480156106f057600080fd5b50610440611ad1565b34801561070557600080fd5b506104fa60155481565b34801561071b57600080fd5b5061072f61072a366004613fcf565b611b44565b604051610417919061412e565b34801561074857600080fd5b50610440610757366004614042565b611c3e565b34801561076857600080fd5b50610440610777366004613f68565b611cdd565b34801561078857600080fd5b50610484610797366004613f68565b611d49565b3480156107a857600080fd5b5060055473ffffffffffffffffffffffffffffffffffffffff16610484565b3480156107d357600080fd5b50610457611d86565b3480156107e857600080fd5b506104fa6107f7366004613fcf565b611d95565b34801561080857600080fd5b506104406108173660046141b7565b611dc8565b34801561082857600080fd5b506104fa60125481565b34801561083e57600080fd5b506104fa61084d366004613fcf565b73ffffffffffffffffffffffffffffffffffffffff1660009081526009602052604090205490565b34801561088157600080fd5b506104fa60115481565b34801561089757600080fd5b506104fa60145481565b3480156108ad57600080fd5b506104fa6108bc366004613fcf565b611f8d565b3480156108cd57600080fd5b506104406108dc366004614223565b611fc0565b3480156108ed57600080fd5b506104406108fc366004613f68565b6120bd565b34801561090d57600080fd5b506104fa60135481565b34801561092357600080fd5b50610440610932366004614258565b612129565b34801561094357600080fd5b50610457610952366004613f68565b6121b1565b34801561096357600080fd5b506104fa610972366004613fcf565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205490565b3480156109a657600080fd5b506104406109b5366004613f68565b61221d565b3480156109c657600080fd5b506104fa600c5481565b3480156109dc57600080fd5b506104406109eb366004613f68565b612289565b3480156109fc57600080fd5b506104576122f5565b348015610a1157600080fd5b506104fa610a20366004613fcf565b612311565b348015610a3157600080fd5b506104fa60165481565b348015610a4757600080fd5b506007546104fa565b348015610a5c57600080fd5b50600d5461040b9060ff1681565b348015610a7657600080fd5b5061040b610a853660046142c4565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260046020908152604080832093909416825291909152205460ff1690565b610440610ace366004613f68565b612344565b348015610adf57600080fd5b50610440610aee366004613fcf565b6125a0565b348015610aff57600080fd5b50610440610b0e366004613f68565b61269c565b348015610b1f57600080fd5b50610440610b2e366004613f68565b612708565b348015610b3f57600080fd5b50600d5461040b9062010000900460ff1681565b610440610b6136600461405d565b612774565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f780e9d63000000000000000000000000000000000000000000000000000000001480610bbc5750610bbc82612a3c565b92915050565b60055473ffffffffffffffffffffffffffffffffffffffff163314610c2e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b8051610c4190600b906020840190613cf5565b5050565b606060008054610c54906142fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610c80906142fd565b8015610ccd5780601f10610ca257610100808354040283529160200191610ccd565b820191906000526020600020905b815481529060010190602001808311610cb057829003601f168201915b5050505050905090565b6000610ce282612b1f565b610d545760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e00000000000000000000000000000000000000006064820152608401610c25565b5060009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b6000610d8882611897565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610e2c5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f72000000000000000000000000000000000000000000000000000000000000006064820152608401610c25565b3373ffffffffffffffffffffffffffffffffffffffff82161480610e555750610e558133610a85565b610ec75760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610c25565b610ed18383612b83565b505050565b60055473ffffffffffffffffffffffffffffffffffffffff163314610f3d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c25565b600e55565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260086020526040902054610fda5760405162461bcd60e51b815260206004820152602660248201527f5061796d656e7453706c69747465723a206163636f756e7420686173206e6f2060448201527f73686172657300000000000000000000000000000000000000000000000000006064820152608401610c25565b600060075447610fea9190614380565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260096020908152604080832054600654600890935290832054939450919261102e9085614398565b6110389190614404565b6110429190614418565b9050806110b75760405162461bcd60e51b815260206004820152602b60248201527f5061796d656e7453706c69747465723a206163636f756e74206973206e6f742060448201527f647565207061796d656e740000000000000000000000000000000000000000006064820152608401610c25565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600960205260409020546110e8908290614380565b73ffffffffffffffffffffffffffffffffffffffff841660009081526009602052604090205560075461111c908290614380565b6007556111298382612c23565b6040805173ffffffffffffffffffffffffffffffffffffffff85168152602081018390527fdf20fd1e76bc69d672e4814fafb2c449bba3a5369d8359adf9e05e6fde87b056910160405180910390a1505050565b6111873382612d49565b6111f95760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610c25565b610ed1838383612e85565b60055473ffffffffffffffffffffffffffffffffffffffff16331461126b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c25565b600d80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b60006112a7836119d2565b82106112f55760405162461bcd60e51b815260206004820152601660248201527f455243373231456e756d3a206f776e657220696f6f62000000000000000000006044820152606401610c25565b6000805b60025481101561136f57600281815481106113165761131661442f565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff8681169116141561135f5783821415611353579150610bbc9050565b61135c8261445e565b91505b6113688161445e565b90506112f9565b5060405162461bcd60e51b815260206004820152601660248201527f455243373231456e756d3a206f776e657220696f6f62000000000000000000006044820152606401610c25565b60055473ffffffffffffffffffffffffffffffffffffffff16331461141f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c25565b601555565b600061142f60025490565b90503361143c8484611789565b73ffffffffffffffffffffffffffffffffffffffff161461149f5760405162461bcd60e51b815260206004820152601160248201527f5369676e617475726520496e76616c69640000000000000000000000000000006044820152606401610c25565b600d5460ff166114f15760405162461bcd60e51b815260206004820152601560248201527f4f472073616c65206973206e6f742061637469766500000000000000000000006044820152606401610c25565b600084116115415760405162461bcd60e51b815260206004820152601060248201527f4d696e74206d6f7265207468616e2030000000000000000000000000000000006044820152606401610c25565b6011548411156115935760405162461bcd60e51b815260206004820152600960248201527f4d696e74206c65737300000000000000000000000000000000000000000000006044820152606401610c25565b600c546115a08583614380565b11156115ee5760405162461bcd60e51b815260206004820152600960248201527f4d696e74206c65737300000000000000000000000000000000000000000000006044820152606401610c25565b83600e546115fc9190614398565b34101561164b5760405162461bcd60e51b815260206004820152601260248201527f45544820696e7075742069732077726f6e6700000000000000000000000000006044820152606401610c25565b8361165533611f8d565b10156116a35760405162461bcd60e51b815260206004820152601360248201527f596f75206d696e74656420746f6f206d616e79000000000000000000000000006044820152606401610c25565b3233146116af57600080fd5b60005b848110156116ed576116dd336116c88385614380565b60405180602001604052806000815250613054565b6116e68161445e565b90506116b2565b50600090506116fc33856130dd565b50505050565b610ed183838360405180602001604052806000815250612129565b60055473ffffffffffffffffffffffffffffffffffffffff1633146117845760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c25565b601055565b6000611795838361311b565b9392505050565b60006117a760025490565b82106117f55760405162461bcd60e51b815260206004820152601760248201527f455243373231456e756d3a20676c6f62616c20696f6f620000000000000000006044820152606401610c25565b5090565b60055473ffffffffffffffffffffffffffffffffffffffff1633146118605760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c25565b600d8054911515610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909216919091179055565b600080600283815481106118ad576118ad61442f565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905080610bbc5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e00000000000000000000000000000000000000000000006064820152608401610c25565b600b8054611951906142fd565b80601f016020809104026020016040519081016040528092919081815260200182805461197d906142fd565b80156119ca5780601f1061199f576101008083540402835291602001916119ca565b820191906000526020600020905b8154815290600101906020018083116119ad57829003601f168201915b505050505081565b600073ffffffffffffffffffffffffffffffffffffffff8216611a5d5760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f2061646472657373000000000000000000000000000000000000000000006064820152608401610c25565b600254600090815b81811015611ac85760028181548110611a8057611a8061442f565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff86811691161415611ab857611ab58361445e565b92505b611ac18161445e565b9050611a65565b50909392505050565b60055473ffffffffffffffffffffffffffffffffffffffff163314611b385760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c25565b611b426000613133565b565b6060611b4f826119d2565b600010611b9e5760405162461bcd60e51b815260206004820152601660248201527f455243373231456e756d3a206f776e657220696f6f62000000000000000000006044820152606401610c25565b6000611ba9836119d2565b905060008167ffffffffffffffff811115611bc657611bc6613dd0565b604051908082528060200260200182016040528015611bef578160200160208202803683370190505b50905060005b82811015611c3657611c07858261129c565b828281518110611c1957611c1961442f565b602090810291909101015280611c2e8161445e565b915050611bf5565b509392505050565b60055473ffffffffffffffffffffffffffffffffffffffff163314611ca55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c25565b600d805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055565b60055473ffffffffffffffffffffffffffffffffffffffff163314611d445760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c25565b601655565b6000600a8281548110611d5e57611d5e61442f565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1692915050565b606060018054610c54906142fd565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260186020526040812054601554610bbc9190614418565b60055473ffffffffffffffffffffffffffffffffffffffff163314611e2f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c25565b828114611e3b57600080fd5b600080611e4760025490565b905060005b85811015611e8a57868682818110611e6657611e6661442f565b9050602002013583611e789190614380565b9250611e838161445e565b9050611e4c565b50600c54611e988383614380565b1115611ee65760405162461bcd60e51b815260206004820152600860248201527f546f6f206d616e790000000000000000000000000000000000000000000000006044820152606401610c25565b6000915060005b83811015611f845760005b878783818110611f0a57611f0a61442f565b90506020020135811015611f7357611f63868684818110611f2d57611f2d61442f565b9050602002016020810190611f429190613fcf565b84611f4c8161445e565b955060405180602001604052806000815250613054565b611f6c8161445e565b9050611ef8565b50611f7d8161445e565b9050611eed565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260176020526040812054601454610bbc9190614418565b73ffffffffffffffffffffffffffffffffffffffff82163314156120265760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610c25565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168085529083529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b60055473ffffffffffffffffffffffffffffffffffffffff1633146121245760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c25565b601455565b6121333383612d49565b6121a55760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610c25565b6116fc848484846131aa565b6060600c548211156121c257600080fd5b60006121cc613233565b905060008151116121ec5760405180602001604052806000815250611795565b806121f684613242565b604051602001612207929190614497565b6040516020818303038152906040529392505050565b60055473ffffffffffffffffffffffffffffffffffffffff1633146122845760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c25565b601155565b60055473ffffffffffffffffffffffffffffffffffffffff1633146122f05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c25565b601255565b6040518060600160405280602e8152602001614570602e913981565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260196020526040812054601654610bbc9190614418565b600061234f60025490565b600d5490915062010000900460ff166123aa5760405162461bcd60e51b815260206004820152601960248201527f5075626c69632073616c65206973206e6f7420616374697665000000000000006044820152606401610c25565b600082116123fa5760405162461bcd60e51b815260206004820152601060248201527f4d696e74206d6f7265207468616e2030000000000000000000000000000000006044820152606401610c25565b60135482111561244c5760405162461bcd60e51b815260206004820152600960248201527f4d696e74206c65737300000000000000000000000000000000000000000000006044820152606401610c25565b600c546124598383614380565b11156124a75760405162461bcd60e51b815260206004820152600960248201527f4d696e74206c65737300000000000000000000000000000000000000000000006044820152606401610c25565b816010546124b59190614398565b3410156125045760405162461bcd60e51b815260206004820152601260248201527f45544820696e7075742069732077726f6e6700000000000000000000000000006044820152606401610c25565b8161250e33612311565b101561255c5760405162461bcd60e51b815260206004820152601360248201527f596f75206d696e74656420746f6f206d616e79000000000000000000000000006044820152606401610c25565b32331461256857600080fd5b60005b8281101561259157612581336116c88385614380565b61258a8161445e565b905061256b565b5060009050610c413383613374565b60055473ffffffffffffffffffffffffffffffffffffffff1633146126075760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c25565b73ffffffffffffffffffffffffffffffffffffffff81166126905760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610c25565b61269981613133565b50565b60055473ffffffffffffffffffffffffffffffffffffffff1633146127035760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c25565b601355565b60055473ffffffffffffffffffffffffffffffffffffffff16331461276f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c25565b600f55565b600061277f60025490565b90503361278c8484611789565b73ffffffffffffffffffffffffffffffffffffffff16146127ef5760405162461bcd60e51b815260206004820152601160248201527f5369676e617475726520496e76616c69640000000000000000000000000000006044820152606401610c25565b600d54610100900460ff166128465760405162461bcd60e51b815260206004820152601c60248201527f416c6c6f776c6973742073616c65206973206e6f7420616374697665000000006044820152606401610c25565b600084116128965760405162461bcd60e51b815260206004820152601060248201527f4d696e74206d6f7265207468616e2030000000000000000000000000000000006044820152606401610c25565b6012548411156128e85760405162461bcd60e51b815260206004820152600960248201527f4d696e74206c65737300000000000000000000000000000000000000000000006044820152606401610c25565b600c546128f58583614380565b11156129435760405162461bcd60e51b815260206004820152600960248201527f4d696e74206c65737300000000000000000000000000000000000000000000006044820152606401610c25565b83600e546129519190614398565b3410156129a05760405162461bcd60e51b815260206004820152601260248201527f45544820696e7075742069732077726f6e6700000000000000000000000000006044820152606401610c25565b836129aa33611d95565b10156129f85760405162461bcd60e51b815260206004820152601360248201527f596f75206d696e74656420746f6f206d616e79000000000000000000000000006044820152606401610c25565b323314612a0457600080fd5b60005b84811015612a2d57612a1d336116c88385614380565b612a268161445e565b9050612a07565b50600090506116fc33856133a9565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd000000000000000000000000000000000000000000000000000000001480612acf57507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b80610bbc57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610bbc565b60025460009082108015610bbc5750600073ffffffffffffffffffffffffffffffffffffffff1660028381548110612b5957612b5961442f565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16141592915050565b600081815260036020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081179091558190612bdd82611897565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b80471015612c735760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610c25565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114612ccd576040519150601f19603f3d011682016040523d82523d6000602084013e612cd2565b606091505b5050905080610ed15760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610c25565b6000612d5482612b1f565b612dc65760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e00000000000000000000000000000000000000006064820152608401610c25565b6000612dd183611897565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612e4057508373ffffffffffffffffffffffffffffffffffffffff16612e2884610cd7565b73ffffffffffffffffffffffffffffffffffffffff16145b80612e7d575073ffffffffffffffffffffffffffffffffffffffff80821660009081526004602090815260408083209388168352929052205460ff165b949350505050565b8273ffffffffffffffffffffffffffffffffffffffff16612ea582611897565b73ffffffffffffffffffffffffffffffffffffffff1614612f2e5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201527f73206e6f74206f776e00000000000000000000000000000000000000000000006064820152608401610c25565b73ffffffffffffffffffffffffffffffffffffffff8216612fb65760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610c25565b612fc1600082612b83565b8160028281548110612fd557612fd561442f565b6000918252602082200180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff938416179055604051839285811692908716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9190a4505050565b61305e83836133de565b61306b6000848484613538565b610ed15760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610c25565b73ffffffffffffffffffffffffffffffffffffffff821660009081526017602052604081208054839290613112908490614380565b90915550505050565b6000806131278461370e565b9050612e7d8184613771565b6005805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6131b5848484612e85565b6131c184848484613538565b6116fc5760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610c25565b6060600b8054610c54906142fd565b60608161328257505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b81156132ac57806132968161445e565b91506132a59050600a83614404565b9150613286565b60008167ffffffffffffffff8111156132c7576132c7613dd0565b6040519080825280601f01601f1916602001820160405280156132f1576020820181803683370190505b5090505b8415612e7d57613306600183614418565b9150613313600a866144c6565b61331e906030614380565b60f81b8183815181106133335761333361442f565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061336d600a86614404565b94506132f5565b73ffffffffffffffffffffffffffffffffffffffff821660009081526019602052604081208054839290613112908490614380565b73ffffffffffffffffffffffffffffffffffffffff821660009081526018602052604081208054839290613112908490614380565b73ffffffffffffffffffffffffffffffffffffffff82166134415760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610c25565b61344a81612b1f565b156134975760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610c25565b6002805460018101825560009182527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff85169081179091556040518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600073ffffffffffffffffffffffffffffffffffffffff84163b15613703576040517f150b7a0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063150b7a02906135af9033908990889088906004016144da565b6020604051808303816000875af1925050508015613608575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261360591810190614523565b60015b6136b8573d808015613636576040519150601f19603f3d011682016040523d82523d6000602084013e61363b565b606091505b5080516136b05760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610c25565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a0200000000000000000000000000000000000000000000000000000000149050612e7d565b506001949350505050565b6000610bbc7f28bcf37b3cf2bc5fb85e4153569e33942b67dedd3a52f5007e880261d298bb9c8380519060200120604051602001613756929190918252602082015260400190565b6040516020818303038152906040528051906020012061378d565b600080600061378085856137f6565b91509150611c3681613866565b6000610bbc61379a613a57565b836040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008082516041141561382d5760208301516040840151606085015160001a61382187828585613b8b565b9450945050505061385f565b825160401415613857576020830151604084015161384c868383613ca3565b93509350505061385f565b506000905060025b9250929050565b600081600481111561387a5761387a614540565b14156138835750565b600181600481111561389757613897614540565b14156138e55760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610c25565b60028160048111156138f9576138f9614540565b14156139475760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610c25565b600381600481111561395b5761395b614540565b14156139cf5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610c25565b60048160048111156139e3576139e3614540565b14156126995760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c60448201527f75650000000000000000000000000000000000000000000000000000000000006064820152608401610c25565b60003073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c9677cd8e9652f1b1aadd3429769b0ef8d7a042516148015613abd57507f000000000000000000000000000000000000000000000000000000000000000146145b15613ae757507f08b9503505765b51ccb887966358f1d5e71c0d1efe7af1e507e3545a9d0962eb90565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527fdf2d8ac372798e7ea3e723777b699a7ac5e9638f8f4fc7a2332f3930f646b8fa828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613bc25750600090506003613c9a565b8460ff16601b14158015613bda57508460ff16601c14155b15613beb5750600090506004613c9a565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015613c3f573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116613c9357600060019250925050613c9a565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831681613cd960ff86901c601b614380565b9050613ce787828885613b8b565b935093505050935093915050565b828054613d01906142fd565b90600052602060002090601f016020900481019282613d235760008555613d69565b82601f10613d3c57805160ff1916838001178555613d69565b82800160010185558215613d69579182015b82811115613d69578251825591602001919060010190613d4e565b506117f59291505b808211156117f55760008155600101613d71565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461269957600080fd5b600060208284031215613dc557600080fd5b813561179581613d85565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112613e1057600080fd5b813567ffffffffffffffff80821115613e2b57613e2b613dd0565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715613e7157613e71613dd0565b81604052838152866020858801011115613e8a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060208284031215613ebc57600080fd5b813567ffffffffffffffff811115613ed357600080fd5b612e7d84828501613dff565b60005b83811015613efa578181015183820152602001613ee2565b838111156116fc5750506000910152565b60008151808452613f23816020860160208601613edf565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006117956020830184613f0b565b600060208284031215613f7a57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461269957600080fd5b60008060408385031215613fb657600080fd5b8235613fc181613f81565b946020939093013593505050565b600060208284031215613fe157600080fd5b813561179581613f81565b60008060006060848603121561400157600080fd5b833561400c81613f81565b9250602084013561401c81613f81565b929592945050506040919091013590565b8035801515811461403d57600080fd5b919050565b60006020828403121561405457600080fd5b6117958261402d565b60008060006060848603121561407257600080fd5b83359250602084013567ffffffffffffffff8082111561409157600080fd5b61409d87838801613dff565b935060408601359150808211156140b357600080fd5b506140c086828701613dff565b9150509250925092565b600080604083850312156140dd57600080fd5b823567ffffffffffffffff808211156140f557600080fd5b61410186838701613dff565b9350602085013591508082111561411757600080fd5b5061412485828601613dff565b9150509250929050565b6020808252825182820181905260009190848201906040850190845b818110156141665783518352928401929184019160010161414a565b50909695505050505050565b60008083601f84011261418457600080fd5b50813567ffffffffffffffff81111561419c57600080fd5b6020830191508360208260051b850101111561385f57600080fd5b600080600080604085870312156141cd57600080fd5b843567ffffffffffffffff808211156141e557600080fd5b6141f188838901614172565b9096509450602087013591508082111561420a57600080fd5b5061421787828801614172565b95989497509550505050565b6000806040838503121561423657600080fd5b823561424181613f81565b915061424f6020840161402d565b90509250929050565b6000806000806080858703121561426e57600080fd5b843561427981613f81565b9350602085013561428981613f81565b925060408501359150606085013567ffffffffffffffff8111156142ac57600080fd5b6142b887828801613dff565b91505092959194509250565b600080604083850312156142d757600080fd5b82356142e281613f81565b915060208301356142f281613f81565b809150509250929050565b600181811c9082168061431157607f821691505b6020821081141561434b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561439357614393614351565b500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156143d0576143d0614351565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614413576144136143d5565b500490565b60008282101561442a5761442a614351565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561449057614490614351565b5060010190565b600083516144a9818460208801613edf565b8351908301906144bd818360208801613edf565b01949350505050565b6000826144d5576144d56143d5565b500690565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526145196080830184613f0b565b9695505050505050565b60006020828403121561453557600080fd5b815161179581613d85565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfe516d5671484671536777396b4b4c445a66636a4773355747673164747251567a616758326b4c674d665932596658a26469706673582212205b108cd996ac70ff6968a61506de080ef22453ffd736219fc52e98814282839164736f6c634300080b0033

Verified Source Code Partial Match

Compiler: v0.8.11+commit.d7f03943 EVM: london Optimization: Yes (20000 runs)
ECDSA.sol 230 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

import "./Strings.sol";

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        } else if (error == RecoverError.InvalidSignatureV) {
            revert("ECDSA: invalid signature 'v' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        // Check the signature length
        // - case 65: r,s,v signature (standard)
        // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else if (signature.length == 64) {
            bytes32 r;
            bytes32 vs;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                vs := mload(add(signature, 0x40))
            }
            return tryRecover(hash, r, vs);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }
        if (v != 27 && v != 28) {
            return (address(0), RecoverError.InvalidSignatureV);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}
EIP712.sol 104 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol)

pragma solidity ^0.8.0;

import "./ECDSA.sol";

/**
 * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.
 *
 * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,
 * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding
 * they need in their contracts using a combination of `abi.encode` and `keccak256`.
 *
 * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
 * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
 * ({_hashTypedDataV4}).
 *
 * The implementation of the domain separator was designed to be as efficient as possible while still properly updating
 * the chain id to protect against replay attacks on an eventual fork of the chain.
 *
 * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
 * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
 *
 * _Available since v3.4._
 */
abstract contract EIP712 {
    /* solhint-disable var-name-mixedcase */
    // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to
    // invalidate the cached domain separator if the chain id changes.
    bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
    uint256 private immutable _CACHED_CHAIN_ID;
    address private immutable _CACHED_THIS;

    bytes32 private immutable _HASHED_NAME;
    bytes32 private immutable _HASHED_VERSION;
    bytes32 private immutable _TYPE_HASH;

    /* solhint-enable var-name-mixedcase */

    /**
     * @dev Initializes the domain separator and parameter caches.
     *
     * The meaning of `name` and `version` is specified in
     * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:
     *
     * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
     * - `version`: the current major version of the signing domain.
     *
     * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
     * contract upgrade].
     */
    constructor(string memory name, string memory version) {
        bytes32 hashedName = keccak256(bytes(name));
        bytes32 hashedVersion = keccak256(bytes(version));
        bytes32 typeHash = keccak256(
            "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
        );
        _HASHED_NAME = hashedName;
        _HASHED_VERSION = hashedVersion;
        _CACHED_CHAIN_ID = block.chainid;
        _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
        _CACHED_THIS = address(this);
        _TYPE_HASH = typeHash;
    }

    /**
     * @dev Returns the domain separator for the current chain.
     */
    function _domainSeparatorV4() internal view returns (bytes32) {
        if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {
            return _CACHED_DOMAIN_SEPARATOR;
        } else {
            return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
        }
    }

    function _buildDomainSeparator(
        bytes32 typeHash,
        bytes32 nameHash,
        bytes32 versionHash
    ) private view returns (bytes32) {
        return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
    }

    /**
     * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
     * function returns the hash of the fully encoded EIP712 message for this domain.
     *
     * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
     *
     * ```solidity
     * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
     *     keccak256("Mail(address to,string contents)"),
     *     mailTo,
     *     keccak256(bytes(mailContents))
     * )));
     * address signer = ECDSA.recover(digest, signature);
     * ```
     */
    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
        return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
    }
}
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;
    }
}
ERC721.sol 199 lines
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.10;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./IERC721Metadata.sol";
import "./Address.sol";
import "./Context.sol";
import "./ERC165.sol";

abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    string private _name;
    string private _symbol;
    address[] internal _owners;
    mapping(uint256 => address) private _tokenApprovals;
    mapping(address => mapping(address => bool)) private _operatorApprovals;     
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }     
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            super.supportsInterface(interfaceId);
    }
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");
        uint count = 0;
        uint length = _owners.length;
        for( uint i = 0; i < length; ++i ){
          if( owner == _owners[i] ){
            ++count;
          }
        }
        delete length;
        return count;
    }
    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;
    }
    function name() public view virtual override returns (string memory) {
        return _name;
    }
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }
    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);
    }
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }
    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);
    }
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[owner][operator];
    }
    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);
    }
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }
    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);
    }     
    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");
    }
	function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return tokenId < _owners.length && _owners[tokenId] != address(0);
    }
	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));
    }
	function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }
	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"
        );
    }
	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);
        _owners.push(to);

        emit Transfer(address(0), to, tokenId);
    }
	function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId);

        _beforeTokenTransfer(owner, address(0), tokenId);

        // Clear approvals
        _approve(address(0), tokenId);
        _owners[tokenId] = address(0);

        emit Transfer(owner, address(0), tokenId);
    }
	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);
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);
    }
	function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
    }
	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.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;
        }
    }
	function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}
}
Address.sol 216 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);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal 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;
    }
}
ERC721A.sol 38 lines
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.10;
import "./ERC721.sol";
import "./IERC721Enumerable.sol";
abstract contract ERC721A is ERC721, IERC721Enumerable {
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
        return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
    }
    function tokenOfOwnerByIndex(address owner, uint256 index) public view override returns (uint256 tokenId) {
        require(index < ERC721.balanceOf(owner), "ERC721Enum: owner ioob");
        uint count;
        for( uint i; i < _owners.length; ++i ){
            if( owner == _owners[i] ){
                if( count == index )
                    return i;
                else
                    ++count;
            }
        }
        require(false, "ERC721Enum: owner ioob");
    }
    function tokensOfOwner(address owner) public view returns (uint256[] memory) {
        require(0 < ERC721.balanceOf(owner), "ERC721Enum: owner ioob");
        uint256 tokenCount = balanceOf(owner);
        uint256[] memory tokenIds = new uint256[](tokenCount);
        for (uint256 i = 0; i < tokenCount; i++) {
            tokenIds[i] = tokenOfOwnerByIndex(owner, i);
        }
        return tokenIds;
    }
    function totalSupply() public view virtual override returns (uint256) {
        return _owners.length;
    }
    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
        require(index < ERC721A.totalSupply(), "ERC721Enum: global ioob");
        return index;
    }
}
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);
}
IERC721.sol 142 lines
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./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;
}
Ownable.sol 70 lines
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./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);
    }
}
Payment.sol 132 lines
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./Address.sol";
import "./Context.sol";
import "./SafeMath.sol";

/**
 * @title PaymentSplitter
 * @dev This contract allows to split Ether payments among a group of accounts. The sender does not need to be aware
 * that the Ether will be split in this way, since it is handled transparently by the contract.
 *
 * The split can be in equal parts or in any other arbitrary proportion. The way this is specified is by assigning each
 * account to a number of shares. Of all the Ether that this contract receives, each account will then be able to claim
 * an amount proportional to the percentage of total shares they were assigned.
 *
 * `PaymentSplitter` follows a _pull payment_ model. This means that payments are not automatically forwarded to the
 * accounts but kept in this contract, and the actual transfer is triggered as a separate step by calling the {release}
 * function.
 */
contract Payment is Context {
    event PayeeAdded(address account, uint256 shares);
    event PaymentReleased(address to, uint256 amount);
    event PaymentReceived(address from, uint256 amount);

    uint256 private _totalShares;
    uint256 private _totalReleased;

    mapping(address => uint256) private _shares;
    mapping(address => uint256) private _released;
    address[] private _payees;

    /**
     * @dev Creates an instance of `PaymentSplitter` where each account in `payees` is assigned the number of shares at
     * the matching position in the `shares` array.
     *
     * All addresses in `payees` must be non-zero. Both arrays must have the same non-zero length, and there must be no
     * duplicates in `payees`.
     */
    constructor(address[] memory payees, uint256[] memory shares_) payable {
        require(payees.length == shares_.length, "PaymentSplitter: payees and shares length mismatch");
        require(payees.length > 0, "PaymentSplitter: no payees");

        for (uint256 i = 0; i < payees.length; i++) {
            _addPayee(payees[i], shares_[i]);
        }
    }

    /**
     * @dev The Ether received will be logged with {PaymentReceived} events. Note that these events are not fully
     * reliable: it's possible for a contract to receive Ether without triggering this function. This only affects the
     * reliability of the events, and not the actual splitting of Ether.
     *
     * To learn more about this see the Solidity documentation for
     * https://solidity.readthedocs.io/en/latest/contracts.html#fallback-function[fallback
     * functions].
     */
    receive() external payable virtual {
        emit PaymentReceived(_msgSender(), msg.value);
    }

    /**
     * @dev Getter for the total shares held by payees.
     */
    function totalShares() public view returns (uint256) {
        return _totalShares;
    }

    /**
     * @dev Getter for the total amount of Ether already released.
     */
    function totalReleased() public view returns (uint256) {
        return _totalReleased;
    }

    /**
     * @dev Getter for the amount of shares held by an account.
     */
    function shares(address account) public view returns (uint256) {
        return _shares[account];
    }

    /**
     * @dev Getter for the amount of Ether already released to a payee.
     */
    function released(address account) public view returns (uint256) {
        return _released[account];
    }

    /**
     * @dev Getter for the address of the payee number `index`.
     */
    function payee(uint256 index) public view returns (address) {
        return _payees[index];
    }

    /**
     * @dev Triggers a transfer to `account` of the amount of Ether they are owed, according to their percentage of the
     * total shares and their previous withdrawals.
     */
    function release(address payable account) public virtual {
        require(_shares[account] > 0, "PaymentSplitter: account has no shares");

        uint256 totalReceived = address(this).balance + _totalReleased;
        uint256 payment = (totalReceived * _shares[account]) / _totalShares - _released[account];

        require(payment != 0, "PaymentSplitter: account is not due payment");

        _released[account] = _released[account] + payment;
        _totalReleased = _totalReleased + payment;

        Address.sendValue(account, payment);
        emit PaymentReleased(account, payment);
    }

    /**
     * @dev Add a new payee to the contract.
     * @param account The address of the payee to add.
     * @param shares_ The number of shares owned by the payee.
     */
    function _addPayee(address account, uint256 shares_) private {
        require(account != address(0), "PaymentSplitter: account is the zero address");
        require(shares_ > 0, "PaymentSplitter: shares are 0");
        require(_shares[account] == 0, "PaymentSplitter: account already has shares");

        _payees.push(account);
        _shares[account] = shares_;
        _totalShares = _totalShares + shares_;
        emit PayeeAdded(account, shares_);
    }
}
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);
    }
}
SafeMath.sol 226 lines
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // 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-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @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) {
        return a + b;
    }

    /**
     * @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) {
        return a - b;
    }

    /**
     * @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) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting 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) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message 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,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * 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,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}
Elemental.sol 231 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.2;

import "./ERC721A.sol";
import "./Ownable.sol";
import "./ECDSA.sol";
import "./EIP712.sol";
import "./Payment.sol";

contract ELEMENTAL is ERC721A,  EIP712, Ownable, Payment {
    using Strings for uint256;
    string public baseURI;

    //starting ipfs hash to be changed using chainlink VRF (https://ipfs.io/ipfs/QmVqHFqSgw9kKLDZfcjGs5WGg1dtrQVzagX2kLgMfY2YfX/)
	string public constant ipfs = "QmVqHFqSgw9kKLDZfcjGs5WGg1dtrQVzagX2kLgMfY2YfX";

    //signature
    string private constant SINGING_DOMAIN = "ELEMENTAL";
    string private constant SIGNATURE_VERSION = "1";

    //settings
  	uint256 public maxSupply = 2022;
	bool public OGStatus = false;
	bool public allowlistStatus = false;
	bool public publicStatus = false;
	uint256 private priceOG = 0.2 ether;
	uint256 private priceAllowlist = 0.2 ether;
	uint256 private pricePublic = 0.3 ether;
	uint256 public maxMintPerTxOG = 2;
	uint256 public maxMintPerTxAllowlist = 1;
	uint256 public maxMintPerTxPublic = 3;
    uint256 public maxMintPerWalletOG = 2;
	uint256 public maxMintPerWalletAllowlist = 1;
    uint256 public maxMintPerWalletPublic = 3;

    //mappings
     mapping(address => uint256) private mintCountMapOG;
     mapping(address => uint256) private mintCountMapAllowlist;
	 mapping(address => uint256) private mintCountMapPublic;
     mapping(address => uint256) private allowedMintCountMapOG;
     mapping(address => uint256) private allowedMintCountMapAllowlist;
     mapping(address => uint256) private allowedMintCountMapPublic;

    //shares
	address[] private addressList = [
		0xb1270a3D1F50440B32d62D088Aa30556Dcc8F950,
		0x41Fb9227c703086B2d908E177A692EdCD3d7DE2C,
		0xEcc03efB7C0A7BD09A5cC7e954Ac42E8f949A0B5
	];
	uint[] private shareList = [70,
								25,
								5];

    constructor(
        	string memory _name,
	string memory _symbol,
	string memory _initBaseURI
    ) 
    ERC721(_name, _symbol) 
    EIP712(SINGING_DOMAIN, SIGNATURE_VERSION) 
    Payment(addressList, shareList) {
          setURI(_initBaseURI); 
    }


 	function mintOG(uint256 _tokenAmount, string memory name, bytes memory signature) public payable {
  	uint256 s = totalSupply();
        require(check(name, signature) == msg.sender, "Signature Invalid"); //server side signature
        require(OGStatus,"OG sale is not active");
        require(_tokenAmount > 0, "Mint more than 0" );
	    require(_tokenAmount <= maxMintPerTxOG, "Mint less");
	    require( s + _tokenAmount <= maxSupply, "Mint less");
	    require(msg.value >= priceOG * _tokenAmount, "ETH input is wrong");
        require(allowedMintCountOG(msg.sender) >= _tokenAmount,"You minted too many");
		require(tx.origin == msg.sender);
       for (uint256 i = 0; i < _tokenAmount; ++i) {
       _safeMint(msg.sender, s + i, "");
       	}
        delete s;
        updateMintCountOG(msg.sender, _tokenAmount);
    }

    function mintAllowlist(uint256 _tokenAmount, string memory name, bytes memory signature) public payable {
  	uint256 s = totalSupply();
        require(check(name, signature) == msg.sender, "Signature Invalid"); //server side signature
        require(allowlistStatus,"Allowlist sale is not active");
        require(_tokenAmount > 0, "Mint more than 0" );
	    require(_tokenAmount <= maxMintPerTxAllowlist, "Mint less");
	    require( s + _tokenAmount <= maxSupply, "Mint less");
	    require(msg.value >= priceOG * _tokenAmount, "ETH input is wrong");
        require(allowedMintCountAllowlist(msg.sender) >= _tokenAmount,"You minted too many");
      	require(tx.origin == msg.sender);
	   for (uint256 i = 0; i < _tokenAmount; ++i) {
       _safeMint(msg.sender, s + i, "");
       	}
        delete s;
        updateMintCountAllowlist(msg.sender, _tokenAmount);
    }

    function mintPublic(uint256 _tokenAmount) public payable {
  	uint256 s = totalSupply();
        require(publicStatus,"Public sale is not active");
        require(_tokenAmount > 0, "Mint more than 0" );
	    require(_tokenAmount <= maxMintPerTxPublic, "Mint less");
	    require( s + _tokenAmount <= maxSupply, "Mint less");
	    require(msg.value >= pricePublic * _tokenAmount, "ETH input is wrong");
        require(allowedMintCountPublic(msg.sender) >= _tokenAmount,"You minted too many");
     	require(tx.origin == msg.sender);
	   for (uint256 i = 0; i < _tokenAmount; ++i) {
             _safeMint(msg.sender, s + i, "");
       	}
        delete s;
	    updateMintCountPublic(msg.sender, _tokenAmount);
    }

    	// admin minting
	function gift(uint[] calldata gifts, address[] calldata recipient) external onlyOwner{
	require(gifts.length == recipient.length);
		uint g = 0;
		uint256 s = totalSupply();
			for(uint i = 0; i < gifts.length; ++i){
			g += gifts[i];
		}
	require( s + g <= maxSupply, "Too many" );
		delete g;
			for(uint i = 0; i < recipient.length; ++i){
			for(uint j = 0; j < gifts[i]; ++j){
		_safeMint( recipient[i], s++, "" );
			}
		}
		delete s;	
	}

    function check(string memory name, bytes memory signature) public view returns (address) {
        return _verify( name, signature);
    }

    function _verify(string memory name, bytes memory signature) internal view returns (address) {
        bytes32 digest = _hash(name);
        return ECDSA.recover(digest, signature);
    }

    function _hash(string memory name) internal view returns (bytes32) {
        return _hashTypedDataV4(keccak256(abi.encode(
            keccak256("Web3Struct(string name)"),
            keccak256(bytes(name))
        )));
        }

	//allow list + max per wallet counters
    function allowedMintCountOG(address minter) public view returns (uint256) {
    	return maxMintPerWalletOG - mintCountMapOG[minter];
     }
	function allowedMintCountAllowlist(address minter) public view returns (uint256) {
    	return maxMintPerWalletAllowlist - mintCountMapAllowlist[minter];
     }
	function allowedMintCountPublic(address minter) public view returns (uint256) {
    	return maxMintPerWalletPublic - mintCountMapPublic[minter];
     }
	function updateMintCountOG(address minter, uint256 count) private {
    	mintCountMapOG[minter] += count;
     }
	function updateMintCountAllowlist(address minter, uint256 count) private {
    	mintCountMapAllowlist[minter] += count;
     }
	function updateMintCountPublic(address minter, uint256 count) private {
    	mintCountMapPublic[minter] += count;
     }

	//read metadata
	function _baseURI() internal view virtual returns (string memory) {
		return baseURI;
	}
	function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
		require(tokenId <= maxSupply);
		string memory currentBaseURI = _baseURI();
			return bytes(currentBaseURI).length > 0	? string(abi.encodePacked(currentBaseURI, tokenId.toString())) : "";
	}


    //price switch

	function setPriceOG(uint256 _newPrice) public onlyOwner {
		priceOG = _newPrice;
	}
	function setPriceAllowlist(uint256 _newPrice) public onlyOwner {
		priceAllowlist = _newPrice;
	}
	function setPricePublic(uint256 _newPrice) public onlyOwner {
		pricePublic = _newPrice;
	}

	//max switch
	function setMaxPerTxAllowlist(uint256 _newMaxMintAmount) public onlyOwner {
		maxMintPerTxAllowlist = _newMaxMintAmount;
	}
	function setMaxPerTxOG(uint256 _newMaxMintAmount) public onlyOwner {
		maxMintPerTxOG = _newMaxMintAmount;
	}
	function setMaxPerTxPublic(uint256 _newMaxMintAmount) public onlyOwner {
		maxMintPerTxPublic = _newMaxMintAmount;
	}

    //max switch
	function setMaxPerWalletOG(uint256 _newMaxMintAmount) public onlyOwner {
	maxMintPerWalletOG = _newMaxMintAmount;
	}
	function setMaxPerWalletAllowlist(uint256 _newMaxMintAmount) public onlyOwner {
	maxMintPerWalletAllowlist = _newMaxMintAmount;
	}
	function setMaxPerWalletPublic(uint256 _newMaxMintAmount) public onlyOwner {
	maxMintPerWalletPublic = _newMaxMintAmount;
	}

    //onoff switch
	function setOG(bool _wlstatus) public onlyOwner {
		OGStatus = _wlstatus;
	}
	function setAllowlist(bool _wlstatus) public onlyOwner {
		allowlistStatus = _wlstatus;
	}
	function setP(bool _pstatus) public onlyOwner {
		publicStatus = _pstatus;
	}

	//write metadata
	function setURI(string memory _newBaseURI) public onlyOwner {
		baseURI = _newBaseURI;
	}

}
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);
}
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);
}
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

OGStatus 0xe72b29de → bool
allowedMintCountAllowlist 0x9619c3bc → uint256
allowedMintCountOG 0x9fbd756f → uint256
allowedMintCountPublic 0xdd0d1bbc → uint256
allowlistStatus 0x242337fd → bool
balanceOf 0x70a08231 → uint256
baseURI 0x6c0360eb → string
check 0x48808c10 → address
getApproved 0x081812fc → address
ipfs 0xd7959cf9 → string
isApprovedForAll 0xe985e9c5 → bool
maxMintPerTxAllowlist 0x97461085 → uint256
maxMintPerTxOG 0x99edbb4d → uint256
maxMintPerTxPublic 0xac9384b9 → uint256
maxMintPerWalletAllowlist 0x812a4a41 → uint256
maxMintPerWalletOG 0x9b5eceb9 → uint256
maxMintPerWalletPublic 0xe1fcd707 → uint256
maxSupply 0xd5abeb01 → uint256
name 0x06fdde03 → string
owner 0x8da5cb5b → address
ownerOf 0x6352211e → address
payee 0x8b83209b → address
publicStatus 0xf91798b1 → bool
released 0x9852595c → uint256
shares 0xce7c2ac2 → uint256
supportsInterface 0x01ffc9a7 → bool
symbol 0x95d89b41 → string
tokenByIndex 0x4f6ccce7 → uint256
tokenOfOwnerByIndex 0x2f745c59 → uint256
tokenURI 0xc87b56dd → string
tokensOfOwner 0x8462151c → uint256[]
totalReleased 0xe33b7de3 → uint256
totalShares 0x3a98ef39 → uint256
totalSupply 0x18160ddd → uint256

Write Contract 25 functions

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

approve 0x095ea7b3
address to
uint256 tokenId
gift 0x96ea3a47
uint256[] gifts
address[] recipient
mintAllowlist 0xf98f51c1
uint256 _tokenAmount
string name
bytes signature
mintOG 0x34c2076b
uint256 _tokenAmount
string name
bytes signature
mintPublic 0xefd0cbf9
uint256 _tokenAmount
release 0x19165587
address account
renounceOwnership 0x715018a6
No parameters
safeTransferFrom 0x42842e0e
address from
address to
uint256 tokenId
safeTransferFrom 0xb88d4fde
address from
address to
uint256 tokenId
bytes _data
setAllowlist 0x5ad1c1b5
bool _wlstatus
setApprovalForAll 0xa22cb465
address operator
bool approved
setMaxPerTxAllowlist 0xd6289983
uint256 _newMaxMintAmount
setMaxPerTxOG 0xcffec338
uint256 _newMaxMintAmount
setMaxPerTxPublic 0xf452472e
uint256 _newMaxMintAmount
setMaxPerWalletAllowlist 0x34b1d403
uint256 _newMaxMintAmount
setMaxPerWalletOG 0xa3237827
uint256 _newMaxMintAmount
setMaxPerWalletPublic 0x8b533ea4
uint256 _newMaxMintAmount
setOG 0x25a8a88e
bool _wlstatus
setP 0x84a303d6
bool _pstatus
setPriceAllowlist 0xf55df94e
uint256 _newPrice
setPriceOG 0x12d71894
uint256 _newPrice
setPricePublic 0x4530a832
uint256 _newPrice
setURI 0x02fe5305
string _newBaseURI
transferFrom 0x23b872dd
address from
address to
uint256 tokenId
transferOwnership 0xf2fde38b
address newOwner

Recent Transactions

No transactions found for this address