Address Contract Partially Verified
Address
0x0AE114F24A68fa1EF8181cC44fa4c60321605A69
Balance
0 ETH
Nonce
1
Code Size
21280 bytes
Creator
0x8e312711...Fc67 at tx 0x60955b84...b7b9e8
Indexed Transactions
0
Contract Bytecode
21280 bytes
0x60806040526004361061023b5760003560e01c806370a082311161012e578063b88d4fde116100ab578063e80893af1161006f578063e80893af1461085a578063e985e9c514610883578063eb8d2444146108c0578063f2fde38b146108eb578063f47c84c5146109145761023b565b8063b88d4fde14610779578063c4e37095146107a2578063c87b56dd146107cb578063cfafe1ef14610808578063d031370b146108315761023b565b80638462151c116100f25780638462151c146106a15780638da5cb5b146106de57806395d89b4114610709578063a0712d6814610734578063a22cb465146107505761023b565b806370a08231146105d0578063711897421461060d5780637146bd0814610636578063715018a614610661578063781b02cc146106785761023b565b80632f745c59116101bc5780634ebe2e1a116101805780634ebe2e1a146104c55780634f6ccce71461050257806355f804b31461053f5780636352211e146105685780636373a6b1146105a55761023b565b80632f745c59146103f45780633ccfd60b146104315780633fa40f941461044857806342842e0e146104715780634b369a611461049a5761023b565b806311e776fe1161020357806311e776fe1461033757806318160ddd1461036057806318b200711461038b5780631a5e2a36146103b457806323b872dd146103cb5761023b565b806301ffc9a71461024057806306fdde031461027d578063081812fc146102a8578063095ea7b3146102e5578063109695231461030e575b600080fd5b34801561024c57600080fd5b5061026760048036038101906102629190613d87565b61093f565b60405161027491906149fc565b60405180910390f35b34801561028957600080fd5b506102926109b9565b60405161029f9190614a17565b60405180910390f35b3480156102b457600080fd5b506102cf60048036038101906102ca9190613e1a565b610a4b565b6040516102dc9190614973565b60405180910390f35b3480156102f157600080fd5b5061030c60048036038101906103079190613ce1565b610ad0565b005b34801561031a57600080fd5b5061033560048036038101906103309190613dd9565b610be8565b005b34801561034357600080fd5b5061035e60048036038101906103599190613e1a565b610c7e565b005b34801561036c57600080fd5b50610375610d04565b6040516103829190614db4565b60405180910390f35b34801561039757600080fd5b506103b260048036038101906103ad9190613e1a565b610d11565b005b3480156103c057600080fd5b506103c9610d97565b005b3480156103d757600080fd5b506103f260048036038101906103ed9190613bdb565b610ea5565b005b34801561040057600080fd5b5061041b60048036038101906104169190613ce1565b610f05565b6040516104289190614db4565b60405180910390f35b34801561043d57600080fd5b50610446610faa565b005b34801561045457600080fd5b5061046f600480360381019061046a9190613d1d565b611360565b005b34801561047d57600080fd5b5061049860048036038101906104939190613bdb565b611585565b005b3480156104a657600080fd5b506104af6115a5565b6040516104bc9190614db4565b60405180910390f35b3480156104d157600080fd5b506104ec60048036038101906104e79190613e1a565b6115ab565b6040516104f99190614d99565b60405180910390f35b34801561050e57600080fd5b5061052960048036038101906105249190613e1a565b61162a565b6040516105369190614db4565b60405180910390f35b34801561054b57600080fd5b5061056660048036038101906105619190613dd9565b6116c1565b005b34801561057457600080fd5b5061058f600480360381019061058a9190613e1a565b611757565b60405161059c9190614973565b60405180910390f35b3480156105b157600080fd5b506105ba611809565b6040516105c79190614a17565b60405180910390f35b3480156105dc57600080fd5b506105f760048036038101906105f29190613b76565b611897565b6040516106049190614db4565b60405180910390f35b34801561061957600080fd5b50610634600480360381019061062f9190613e1a565b61194f565b005b34801561064257600080fd5b5061064b6119d5565b6040516106589190614db4565b60405180910390f35b34801561066d57600080fd5b506106766119db565b005b34801561068457600080fd5b5061069f600480360381019061069a9190613b76565b611b18565b005b3480156106ad57600080fd5b506106c860048036038101906106c39190613b76565b611bd8565b6040516106d591906149da565b60405180910390f35b3480156106ea57600080fd5b506106f3611cd2565b6040516107009190614973565b60405180910390f35b34801561071557600080fd5b5061071e611cfc565b60405161072b9190614a17565b60405180910390f35b61074e60048036038101906107499190613e1a565b611d8e565b005b34801561075c57600080fd5b5061077760048036038101906107729190613ca5565b611f9f565b005b34801561078557600080fd5b506107a0600480360381019061079b9190613c2a565b612120565b005b3480156107ae57600080fd5b506107c960048036038101906107c49190613d5e565b612182565b005b3480156107d757600080fd5b506107f260048036038101906107ed9190613e1a565b61221b565b6040516107ff9190614a17565b60405180910390f35b34801561081457600080fd5b5061082f600480360381019061082a9190613b76565b6122c2565b005b34801561083d57600080fd5b5061085860048036038101906108539190613e1a565b612382565b005b34801561086657600080fd5b50610881600480360381019061087c9190613b76565b6124c6565b005b34801561088f57600080fd5b506108aa60048036038101906108a59190613b9f565b612586565b6040516108b791906149fc565b60405180910390f35b3480156108cc57600080fd5b506108d561261a565b6040516108e291906149fc565b60405180910390f35b3480156108f757600080fd5b50610912600480360381019061090d9190613b76565b61262d565b005b34801561092057600080fd5b506109296127d9565b6040516109369190614db4565b60405180910390f35b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806109b257506109b1826127df565b5b9050919050565b6060600080546109c890615115565b80601f01602080910402602001604051908101604052809291908181526020018280546109f490615115565b8015610a415780601f10610a1657610100808354040283529160200191610a41565b820191906000526020600020905b815481529060010190602001808311610a2457829003601f168201915b5050505050905090565b6000610a56826128c1565b610a95576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a8c90614c99565b60405180910390fd5b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610adb82611757565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610b4c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b4390614d39565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610b6b61292d565b73ffffffffffffffffffffffffffffffffffffffff161480610b9a5750610b9981610b9461292d565b612586565b5b610bd9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bd090614b99565b60405180910390fd5b610be38383612935565b505050565b610bf061292d565b73ffffffffffffffffffffffffffffffffffffffff16610c0e611cd2565b73ffffffffffffffffffffffffffffffffffffffff1614610c64576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c5b90614cb9565b60405180910390fd5b80600c9080519060200190610c7a9291906138f1565b5050565b610c8661292d565b73ffffffffffffffffffffffffffffffffffffffff16610ca4611cd2565b73ffffffffffffffffffffffffffffffffffffffff1614610cfa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cf190614cb9565b60405180910390fd5b80600e8190555050565b6000600880549050905090565b610d1961292d565b73ffffffffffffffffffffffffffffffffffffffff16610d37611cd2565b73ffffffffffffffffffffffffffffffffffffffff1614610d8d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d8490614cb9565b60405180910390fd5b80600f8190555050565b610d9f61292d565b73ffffffffffffffffffffffffffffffffffffffff16610dbd611cd2565b73ffffffffffffffffffffffffffffffffffffffff1614610e13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e0a90614cb9565b60405180910390fd5b60004711610e56576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e4d90614d19565b60405180910390fd5b60004790503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610ea1573d6000803e3d6000fd5b5050565b610eb6610eb061292d565b826129ee565b610ef5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eec90614d59565b60405180910390fd5b610f00838383612acc565b505050565b6000610f1083611897565b8210610f51576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f4890614a39565b60405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b610fb261292d565b73ffffffffffffffffffffffffffffffffffffffff16610fd0611cd2565b73ffffffffffffffffffffffffffffffffffffffff1614611026576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161101d90614cb9565b60405180910390fd5b60004711611069576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161106090614d19565b60405180910390fd5b600047905060006110976064611089603285612d2890919063ffffffff16565b612d3e90919063ffffffff16565b905060006110c260646110b4601986612d2890919063ffffffff16565b612d3e90919063ffffffff16565b905060006110ed60646110df601987612d2890919063ffffffff16565b612d3e90919063ffffffff16565b90506000601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16846040516111379061495e565b60006040518083038185875af1925050503d8060008114611174576040519150601f19603f3d011682016040523d82523d6000602084013e611179565b606091505b50509050806111bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111b490614b79565b60405180910390fd5b601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16836040516112039061495e565b60006040518083038185875af1925050503d8060008114611240576040519150601f19603f3d011682016040523d82523d6000602084013e611245565b606091505b5050809150508061128b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128290614bb9565b60405180910390fd5b601460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16826040516112d19061495e565b60006040518083038185875af1925050503d806000811461130e576040519150601f19603f3d011682016040523d82523d6000602084013e611313565b606091505b50508091505080611359576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161135090614c19565b60405180910390fd5b5050505050565b61136861292d565b73ffffffffffffffffffffffffffffffffffffffff16611386611cd2565b73ffffffffffffffffffffffffffffffffffffffff16146113dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113d390614cb9565b60405180910390fd5b600e546113fa82516113ec610d04565b612d5490919063ffffffff16565b111561143b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161143290614c59565b60405180910390fd5b6000429050600080600090505b835181101561157f5761146c600161145e610d04565b612d5490919063ffffffff16565b9150600e54821161156c576114c18482815181106114b3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002602001015183612d6a565b604051806020016040528084815250600b6000848152602001908152602001600020600082015181600001559050507f2d03118aa776f7008445f6ca8490a6782ede2db364d741513555ba656ab1879f8285838151811061154b577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101518560405161156393929190614dcf565b60405180910390a15b808061157790615147565b915050611448565b50505050565b6115a083838360405180602001604052806000815250612120565b505050565b600f5481565b6115b3613977565b6115bc826128c1565b6115fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115f290614b59565b60405180910390fd5b600b60008381526020019081526020016000206040518060200160405290816000820154815250509050919050565b6000611634610d04565b8210611675576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161166c90614d79565b60405180910390fd5b600882815481106116af577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001549050919050565b6116c961292d565b73ffffffffffffffffffffffffffffffffffffffff166116e7611cd2565b73ffffffffffffffffffffffffffffffffffffffff161461173d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161173490614cb9565b60405180910390fd5b80601190805190602001906117539291906138f1565b5050565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611800576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117f790614bf9565b60405180910390fd5b80915050919050565b600c805461181690615115565b80601f016020809104026020016040519081016040528092919081815260200182805461184290615115565b801561188f5780601f106118645761010080835404028352916020019161188f565b820191906000526020600020905b81548152906001019060200180831161187257829003601f168201915b505050505081565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611908576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118ff90614bd9565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b61195761292d565b73ffffffffffffffffffffffffffffffffffffffff16611975611cd2565b73ffffffffffffffffffffffffffffffffffffffff16146119cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119c290614cb9565b60405180910390fd5b80600d8190555050565b600d5481565b6119e361292d565b73ffffffffffffffffffffffffffffffffffffffff16611a01611cd2565b73ffffffffffffffffffffffffffffffffffffffff1614611a57576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a4e90614cb9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b611b2061292d565b73ffffffffffffffffffffffffffffffffffffffff16611b3e611cd2565b73ffffffffffffffffffffffffffffffffffffffff1614611b94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b8b90614cb9565b60405180910390fd5b80601460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60606000611be583611897565b905060008167ffffffffffffffff811115611c29577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051908082528060200260200182016040528015611c575781602001602082028036833780820191505090505b50905060005b82811015611cc757611c6f8582610f05565b828281518110611ca8577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020026020010181815250508080611cbf90615147565b915050611c5d565b508092505050919050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060018054611d0b90615115565b80601f0160208091040260200160405190810160405280929190818152602001828054611d3790615115565b8015611d845780601f10611d5957610100808354040283529160200191611d84565b820191906000526020600020905b815481529060010190602001808311611d6757829003601f168201915b5050505050905090565b601060009054906101000a900460ff16611ddd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dd490614af9565b60405180910390fd5b600d54811115611e22576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e1990614b39565b60405180910390fd5b600e54611e3f82611e31610d04565b612d5490919063ffffffff16565b1115611e80576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e7790614c59565b60405180910390fd5b34611e9682600f54612d2890919063ffffffff16565b1115611ed7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ece90614c39565b60405180910390fd5b6000429050600080600190505b838111611f9957611f066001611ef8610d04565b612d5490919063ffffffff16565b9150600e548211611f8657611f1b3383612d6a565b604051806020016040528084815250600b6000848152602001908152602001600020600082015181600001559050507f2d03118aa776f7008445f6ca8490a6782ede2db364d741513555ba656ab1879f823385604051611f7d93929190614dcf565b60405180910390a15b8080611f9190615147565b915050611ee4565b50505050565b611fa761292d565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612015576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161200c90614ad9565b60405180910390fd5b806005600061202261292d565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff166120cf61292d565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161211491906149fc565b60405180910390a35050565b61213161212b61292d565b836129ee565b612170576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161216790614d59565b60405180910390fd5b61217c84848484612d88565b50505050565b61218a61292d565b73ffffffffffffffffffffffffffffffffffffffff166121a8611cd2565b73ffffffffffffffffffffffffffffffffffffffff16146121fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121f590614cb9565b60405180910390fd5b80601060006101000a81548160ff02191690831515021790555050565b6060612226826128c1565b612265576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161225c90614cf9565b60405180910390fd5b600061226f612de4565b9050600081511161228f57604051806020016040528060008152506122ba565b8061229984612e76565b6040516020016122aa92919061493a565b6040516020818303038152906040525b915050919050565b6122ca61292d565b73ffffffffffffffffffffffffffffffffffffffff166122e8611cd2565b73ffffffffffffffffffffffffffffffffffffffff161461233e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161233590614cb9565b60405180910390fd5b80601260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b61238a61292d565b73ffffffffffffffffffffffffffffffffffffffff166123a8611cd2565b73ffffffffffffffffffffffffffffffffffffffff16146123fe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123f590614cb9565b60405180910390fd5b6000804290506000600190505b8381116124c05761242d600161241f610d04565b612d5490919063ffffffff16565b9250600e5483116124ad576124423384612d6a565b604051806020016040528083815250600b6000858152602001908152602001600020600082015181600001559050507f2d03118aa776f7008445f6ca8490a6782ede2db364d741513555ba656ab1879f8333846040516124a493929190614dcf565b60405180910390a15b80806124b890615147565b91505061240b565b50505050565b6124ce61292d565b73ffffffffffffffffffffffffffffffffffffffff166124ec611cd2565b73ffffffffffffffffffffffffffffffffffffffff1614612542576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161253990614cb9565b60405180910390fd5b80601360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b601060009054906101000a900460ff1681565b61263561292d565b73ffffffffffffffffffffffffffffffffffffffff16612653611cd2565b73ffffffffffffffffffffffffffffffffffffffff16146126a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126a090614cb9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612719576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161271090614a79565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600e5481565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806128aa57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806128ba57506128b982613023565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff166129a883611757565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60006129f9826128c1565b612a38576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a2f90614b19565b60405180910390fd5b6000612a4383611757565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612ab257508373ffffffffffffffffffffffffffffffffffffffff16612a9a84610a4b565b73ffffffffffffffffffffffffffffffffffffffff16145b80612ac35750612ac28185612586565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16612aec82611757565b73ffffffffffffffffffffffffffffffffffffffff1614612b42576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b3990614cd9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612bb2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ba990614ab9565b60405180910390fd5b612bbd83838361308d565b612bc8600082612935565b6001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612c18919061502b565b925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612c6f9190614f4a565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b60008183612d369190614fd1565b905092915050565b60008183612d4c9190614fa0565b905092915050565b60008183612d629190614f4a565b905092915050565b612d848282604051806020016040528060008152506131a1565b5050565b612d93848484612acc565b612d9f848484846131fc565b612dde576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dd590614a59565b60405180910390fd5b50505050565b606060118054612df390615115565b80601f0160208091040260200160405190810160405280929190818152602001828054612e1f90615115565b8015612e6c5780601f10612e4157610100808354040283529160200191612e6c565b820191906000526020600020905b815481529060010190602001808311612e4f57829003601f168201915b5050505050905090565b60606000821415612ebe576040518060400160405280600181526020017f3000000000000000000000000000000000000000000000000000000000000000815250905061301e565b600082905060005b60008214612ef0578080612ed990615147565b915050600a82612ee99190614fa0565b9150612ec6565b60008167ffffffffffffffff811115612f32577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015612f645781602001600182028036833780820191505090505b5090505b6000851461301757600182612f7d919061502b565b9150600a85612f8c9190615190565b6030612f989190614f4a565b60f81b818381518110612fd4577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a856130109190614fa0565b9450612f68565b8093505050505b919050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b613098838383613393565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156130db576130d681613398565b61311a565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146131195761311883826133e1565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561315d576131588161354e565b61319c565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461319b5761319a8282613691565b5b5b505050565b6131ab8383613710565b6131b860008484846131fc565b6131f7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131ee90614a59565b60405180910390fd5b505050565b600061321d8473ffffffffffffffffffffffffffffffffffffffff166138de565b15613386578373ffffffffffffffffffffffffffffffffffffffff1663150b7a0261324661292d565b8786866040518563ffffffff1660e01b8152600401613268949392919061498e565b602060405180830381600087803b15801561328257600080fd5b505af19250505080156132b357506040513d601f19601f820116820180604052508101906132b09190613db0565b60015b613336573d80600081146132e3576040519150601f19603f3d011682016040523d82523d6000602084013e6132e8565b606091505b5060008151141561332e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161332590614a59565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161491505061338b565b600190505b949350505050565b505050565b6008805490506009600083815260200190815260200160002081905550600881908060018154018082558091505060019003906000526020600020016000909190919091505550565b600060016133ee84611897565b6133f8919061502b565b90506000600760008481526020019081526020016000205490508181146134dd576000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816007600083815260200190815260200160002081905550505b6007600084815260200190815260200160002060009055600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b60006001600880549050613562919061502b565b90506000600960008481526020019081526020016000205490506000600883815481106135b8577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020015490508060088381548110613600577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020018190555081600960008381526020019081526020016000208190555060096000858152602001908152602001600020600090556008805480613675577f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6001900381819060005260206000200160009055905550505050565b600061369c83611897565b905081600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806007600084815260200190815260200160002081905550505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613780576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161377790614c79565b60405180910390fd5b613789816128c1565b156137c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016137c090614a99565b60405180910390fd5b6137d56000838361308d565b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546138259190614f4a565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b600080823b905060008111915050919050565b8280546138fd90615115565b90600052602060002090601f01602090048101928261391f5760008555613966565b82601f1061393857805160ff1916838001178555613966565b82800160010185558215613966579182015b8281111561396557825182559160200191906001019061394a565b5b509050613973919061398a565b5090565b6040518060200160405280600081525090565b5b808211156139a357600081600090555060010161398b565b5090565b60006139ba6139b584614e37565b614e06565b905080838252602082019050828560208602820111156139d957600080fd5b60005b85811015613a0957816139ef8882613a8f565b8452602084019350602083019250506001810190506139dc565b5050509392505050565b6000613a26613a2184614e63565b614e06565b905082815260208101848484011115613a3e57600080fd5b613a498482856150d3565b509392505050565b6000613a64613a5f84614e93565b614e06565b905082815260208101848484011115613a7c57600080fd5b613a878482856150d3565b509392505050565b600081359050613a9e8161528e565b92915050565b600082601f830112613ab557600080fd5b8135613ac58482602086016139a7565b91505092915050565b600081359050613add816152a5565b92915050565b600081359050613af2816152bc565b92915050565b600081519050613b07816152bc565b92915050565b600082601f830112613b1e57600080fd5b8135613b2e848260208601613a13565b91505092915050565b600082601f830112613b4857600080fd5b8135613b58848260208601613a51565b91505092915050565b600081359050613b70816152d3565b92915050565b600060208284031215613b8857600080fd5b6000613b9684828501613a8f565b91505092915050565b60008060408385031215613bb257600080fd5b6000613bc085828601613a8f565b9250506020613bd185828601613a8f565b9150509250929050565b600080600060608486031215613bf057600080fd5b6000613bfe86828701613a8f565b9350506020613c0f86828701613a8f565b9250506040613c2086828701613b61565b9150509250925092565b60008060008060808587031215613c4057600080fd5b6000613c4e87828801613a8f565b9450506020613c5f87828801613a8f565b9350506040613c7087828801613b61565b925050606085013567ffffffffffffffff811115613c8d57600080fd5b613c9987828801613b0d565b91505092959194509250565b60008060408385031215613cb857600080fd5b6000613cc685828601613a8f565b9250506020613cd785828601613ace565b9150509250929050565b60008060408385031215613cf457600080fd5b6000613d0285828601613a8f565b9250506020613d1385828601613b61565b9150509250929050565b600060208284031215613d2f57600080fd5b600082013567ffffffffffffffff811115613d4957600080fd5b613d5584828501613aa4565b91505092915050565b600060208284031215613d7057600080fd5b6000613d7e84828501613ace565b91505092915050565b600060208284031215613d9957600080fd5b6000613da784828501613ae3565b91505092915050565b600060208284031215613dc257600080fd5b6000613dd084828501613af8565b91505092915050565b600060208284031215613deb57600080fd5b600082013567ffffffffffffffff811115613e0557600080fd5b613e1184828501613b37565b91505092915050565b600060208284031215613e2c57600080fd5b6000613e3a84828501613b61565b91505092915050565b6000613e4f838361491c565b60208301905092915050565b613e648161505f565b82525050565b6000613e7582614ed3565b613e7f8185614f01565b9350613e8a83614ec3565b8060005b83811015613ebb578151613ea28882613e43565b9750613ead83614ef4565b925050600181019050613e8e565b5085935050505092915050565b613ed181615071565b82525050565b6000613ee282614ede565b613eec8185614f12565b9350613efc8185602086016150e2565b613f058161527d565b840191505092915050565b6000613f1b82614ee9565b613f258185614f2e565b9350613f358185602086016150e2565b613f3e8161527d565b840191505092915050565b6000613f5482614ee9565b613f5e8185614f3f565b9350613f6e8185602086016150e2565b80840191505092915050565b6000613f87602b83614f2e565b91507f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008301527f74206f6620626f756e64730000000000000000000000000000000000000000006020830152604082019050919050565b6000613fed603283614f2e565b91507f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008301527f63656976657220696d706c656d656e74657200000000000000000000000000006020830152604082019050919050565b6000614053602683614f2e565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006140b9601c83614f2e565b91507f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006000830152602082019050919050565b60006140f9602483614f2e565b91507f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008301527f72657373000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061415f601983614f2e565b91507f4552433732313a20617070726f766520746f2063616c6c6572000000000000006000830152602082019050919050565b600061419f601f83614f2e565b91507f4d696e74206973206e6f7420617661696c61626c65207269676874206e6f77006000830152602082019050919050565b60006141df602c83614f2e565b91507f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008301527f697374656e7420746f6b656e00000000000000000000000000000000000000006020830152604082019050919050565b6000614245602183614f2e565b91507f43616e206f6e6c79206d696e7420323020746f6b656e7320617420612074696d60008301527f65000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006142ab601483614f2e565b91507f546f6b656e20776173206e6f74206d696e7465640000000000000000000000006000830152602082019050919050565b60006142eb602183614f2e565b91507f63726561746f724164647265737331205769746864726177616c206661696c6560008301527f64000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614351603883614f2e565b91507f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008301527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006020830152604082019050919050565b60006143b7602183614f2e565b91507f63726561746f724164647265737332205769746864726177616c206661696c6560008301527f64000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061441d602a83614f2e565b91507f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008301527f726f2061646472657373000000000000000000000000000000000000000000006020830152604082019050919050565b6000614483602983614f2e565b91507f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008301527f656e7420746f6b656e00000000000000000000000000000000000000000000006020830152604082019050919050565b60006144e9602183614f2e565b91507f63726561746f724164647265737333205769746864726177616c206661696c6560008301527f64000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061454f601983614f2e565b91507f56616c75652073656e74206973206e6f7420636f7272656374000000000000006000830152602082019050919050565b600061458f602083614f2e565b91507f507572636861736520776f756c6420657863656564206d617820737570706c796000830152602082019050919050565b60006145cf602083614f2e565b91507f4552433732313a206d696e7420746f20746865207a65726f20616464726573736000830152602082019050919050565b600061460f602c83614f2e565b91507f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008301527f697374656e7420746f6b656e00000000000000000000000000000000000000006020830152604082019050919050565b6000614675602083614f2e565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006146b5602983614f2e565b91507f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960008301527f73206e6f74206f776e00000000000000000000000000000000000000000000006020830152604082019050919050565b600061471b602f83614f2e565b91507f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008301527f6e6578697374656e7420746f6b656e00000000000000000000000000000000006020830152604082019050919050565b6000614781601683614f2e565b91507f4e6f2062616c616e636520746f207769746864726177000000000000000000006000830152602082019050919050565b60006147c1602183614f2e565b91507f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008301527f72000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614827600083614f23565b9150600082019050919050565b6000614841603183614f2e565b91507f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008301527f776e6572206e6f7220617070726f7665640000000000000000000000000000006020830152604082019050919050565b60006148a7602c83614f2e565b91507f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008301527f7574206f6620626f756e647300000000000000000000000000000000000000006020830152604082019050919050565b602082016000820151614916600085018261491c565b50505050565b614925816150c9565b82525050565b614934816150c9565b82525050565b60006149468285613f49565b91506149528284613f49565b91508190509392505050565b60006149698261481a565b9150819050919050565b60006020820190506149886000830184613e5b565b92915050565b60006080820190506149a36000830187613e5b565b6149b06020830186613e5b565b6149bd604083018561492b565b81810360608301526149cf8184613ed7565b905095945050505050565b600060208201905081810360008301526149f48184613e6a565b905092915050565b6000602082019050614a116000830184613ec8565b92915050565b60006020820190508181036000830152614a318184613f10565b905092915050565b60006020820190508181036000830152614a5281613f7a565b9050919050565b60006020820190508181036000830152614a7281613fe0565b9050919050565b60006020820190508181036000830152614a9281614046565b9050919050565b60006020820190508181036000830152614ab2816140ac565b9050919050565b60006020820190508181036000830152614ad2816140ec565b9050919050565b60006020820190508181036000830152614af281614152565b9050919050565b60006020820190508181036000830152614b1281614192565b9050919050565b60006020820190508181036000830152614b32816141d2565b9050919050565b60006020820190508181036000830152614b5281614238565b9050919050565b60006020820190508181036000830152614b728161429e565b9050919050565b60006020820190508181036000830152614b92816142de565b9050919050565b60006020820190508181036000830152614bb281614344565b9050919050565b60006020820190508181036000830152614bd2816143aa565b9050919050565b60006020820190508181036000830152614bf281614410565b9050919050565b60006020820190508181036000830152614c1281614476565b9050919050565b60006020820190508181036000830152614c32816144dc565b9050919050565b60006020820190508181036000830152614c5281614542565b9050919050565b60006020820190508181036000830152614c7281614582565b9050919050565b60006020820190508181036000830152614c92816145c2565b9050919050565b60006020820190508181036000830152614cb281614602565b9050919050565b60006020820190508181036000830152614cd281614668565b9050919050565b60006020820190508181036000830152614cf2816146a8565b9050919050565b60006020820190508181036000830152614d128161470e565b9050919050565b60006020820190508181036000830152614d3281614774565b9050919050565b60006020820190508181036000830152614d52816147b4565b9050919050565b60006020820190508181036000830152614d7281614834565b9050919050565b60006020820190508181036000830152614d928161489a565b9050919050565b6000602082019050614dae6000830184614900565b92915050565b6000602082019050614dc9600083018461492b565b92915050565b6000606082019050614de4600083018661492b565b614df16020830185613e5b565b614dfe604083018461492b565b949350505050565b6000604051905081810181811067ffffffffffffffff82111715614e2d57614e2c61524e565b5b8060405250919050565b600067ffffffffffffffff821115614e5257614e5161524e565b5b602082029050602081019050919050565b600067ffffffffffffffff821115614e7e57614e7d61524e565b5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff821115614eae57614ead61524e565b5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000614f55826150c9565b9150614f60836150c9565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115614f9557614f946151c1565b5b828201905092915050565b6000614fab826150c9565b9150614fb6836150c9565b925082614fc657614fc56151f0565b5b828204905092915050565b6000614fdc826150c9565b9150614fe7836150c9565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156150205761501f6151c1565b5b828202905092915050565b6000615036826150c9565b9150615041836150c9565b925082821015615054576150536151c1565b5b828203905092915050565b600061506a826150a9565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b82818337600083830152505050565b60005b838110156151005780820151818401526020810190506150e5565b8381111561510f576000848401525b50505050565b6000600282049050600182168061512d57607f821691505b602082108114156151415761514061521f565b5b50919050565b6000615152826150c9565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415615185576151846151c1565b5b600182019050919050565b600061519b826150c9565b91506151a6836150c9565b9250826151b6576151b56151f0565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b6152978161505f565b81146152a257600080fd5b50565b6152ae81615071565b81146152b957600080fd5b50565b6152c58161507d565b81146152d057600080fd5b50565b6152dc816150c9565b81146152e757600080fd5b5056fea26469706673582212204ad8fb990b8d1813e4bed6bae310a18f5551f9aa0ff2ba935538ffba86be99fe64736f6c63430008000033
Verified Source Code Partial Match
Compiler: v0.8.0+commit.c7dfd78e
EVM: istanbul
Optimization: No
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 376 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./IERC721Metadata.sol";
import "./Address.sol";
import "./Context.sol";
import "./Strings.sol";
import "./ERC165.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
// Token name
string private _name;
// Token symbol
string private _symbol;
// Mapping from token ID to owner address
mapping (uint256 => address) private _owners;
// Mapping owner address to token count
mapping (address => uint256) private _balances;
// Mapping from token ID to approved address
mapping (uint256 => address) private _tokenApprovals;
// Mapping from owner to operator approvals
mapping (address => mapping (address => bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor (string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return interfaceId == type(IERC721).interfaceId
|| interfaceId == type(IERC721Metadata).interfaceId
|| super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/
function balanceOf(address owner) public view virtual override returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/
function ownerOf(uint256 tokenId) public view virtual override returns (address) {
address owner = _owners[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory baseURI = _baseURI();
return bytes(baseURI).length > 0
? string(abi.encodePacked(baseURI, tokenId.toString()))
: '';
}
/**
* @dev Base URI for computing {tokenURI}. Empty by default, can be overriden
* in child contracts.
*/
function _baseURI() internal view virtual returns (string memory) {
return "";
}
/**
* @dev See {IERC721-approve}.
*/
function approve(address to, uint256 tokenId) public virtual override {
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/
function getApproved(uint256 tokenId) public view virtual override returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/
function setApprovalForAll(address operator, bool approved) public virtual override {
require(operator != _msgSender(), "ERC721: approve to caller");
_operatorApprovals[_msgSender()][operator] = approved;
emit ApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/
function transferFrom(address from, address to, uint256 tokenId) public virtual override {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransfer(from, to, tokenId, _data);
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* `_data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted (`_mint`),
* and stop existing when they are burned (`_burn`).
*/
function _exists(uint256 tokenId) internal view virtual returns (bool) {
return _owners[tokenId] != address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function _safeMint(address to, uint256 tokenId) internal virtual {
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {
_mint(to, tokenId);
require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/
function _burn(uint256 tokenId) internal virtual {
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId);
// Clear approvals
_approve(address(0), tokenId);
_balances[owner] -= 1;
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/
function _transfer(address from, address to, uint256 tokenId) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
// Clear approvals from the previous owner
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits a {Approval} event.
*/
function _approve(address to, uint256 tokenId) internal virtual {
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
private returns (bool)
{
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver(to).onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
// solhint-disable-next-line no-inline-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual { }
}
Address.sol 189 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;
// solhint-disable-next-line no-inline-assembly
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");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(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");
// solhint-disable-next-line avoid-low-level-calls
(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");
// solhint-disable-next-line avoid-low-level-calls
(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");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
Context.sol 24 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) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
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 129 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 68 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 () {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), 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 {
emit OwnershipTransferred(_owner, address(0));
_owner = 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");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
Strings.sol 67 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant alphabet = "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] = alphabet[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
SafeMath.sol 218 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. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* 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;
}
}
}
EnumerableMap.sol 224 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./EnumerableSet.sol";
/**
* @dev Library for managing an enumerable variant of Solidity's
* https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]
* type.
*
* Maps have the following properties:
*
* - Entries are added, removed, and checked for existence in constant time
* (O(1)).
* - Entries are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableMap for EnumerableMap.UintToAddressMap;
*
* // Declare a set state variable
* EnumerableMap.UintToAddressMap private myMap;
* }
* ```
*
* As of v3.0.0, only maps of type `uint256 -> address` (`UintToAddressMap`) are
* supported.
*/
library EnumerableMap {
using EnumerableSet for EnumerableSet.Bytes32Set;
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Map type with
// bytes32 keys and values.
// The Map implementation uses private functions, and user-facing
// implementations (such as Uint256ToAddressMap) are just wrappers around
// the underlying Map.
// This means that we can only create new EnumerableMaps for types that fit
// in bytes32.
struct Map {
// Storage of keys
EnumerableSet.Bytes32Set _keys;
mapping (bytes32 => bytes32) _values;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function _set(Map storage map, bytes32 key, bytes32 value) private returns (bool) {
map._values[key] = value;
return map._keys.add(key);
}
/**
* @dev Removes a key-value pair from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function _remove(Map storage map, bytes32 key) private returns (bool) {
delete map._values[key];
return map._keys.remove(key);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function _contains(Map storage map, bytes32 key) private view returns (bool) {
return map._keys.contains(key);
}
/**
* @dev Returns the number of key-value pairs in the map. O(1).
*/
function _length(Map storage map) private view returns (uint256) {
return map._keys.length();
}
/**
* @dev Returns the key-value pair stored at position `index` in the map. O(1).
*
* Note that there are no guarantees on the ordering of entries inside the
* array, and it may change when more entries are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Map storage map, uint256 index) private view returns (bytes32, bytes32) {
bytes32 key = map._keys.at(index);
return (key, map._values[key]);
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function _tryGet(Map storage map, bytes32 key) private view returns (bool, bytes32) {
bytes32 value = map._values[key];
if (value == bytes32(0)) {
return (_contains(map, key), bytes32(0));
} else {
return (true, value);
}
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function _get(Map storage map, bytes32 key) private view returns (bytes32) {
bytes32 value = map._values[key];
require(value != 0 || _contains(map, key), "EnumerableMap: nonexistent key");
return value;
}
/**
* @dev Same as {_get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {_tryGet}.
*/
function _get(Map storage map, bytes32 key, string memory errorMessage) private view returns (bytes32) {
bytes32 value = map._values[key];
require(value != 0 || _contains(map, key), errorMessage);
return value;
}
// UintToAddressMap
struct UintToAddressMap {
Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {
return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
return _remove(map._inner, bytes32(key));
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
return _contains(map._inner, bytes32(key));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(UintToAddressMap storage map) internal view returns (uint256) {
return _length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the set. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
(bytes32 key, bytes32 value) = _at(map._inner, index);
return (uint256(key), address(uint160(uint256(value))));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*
* _Available since v3.4._
*/
function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
(bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));
return (success, address(uint160(uint256(value))));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
return address(uint160(uint256(_get(map._inner, bytes32(key)))));
}
/**
* @dev Same as {get}, with a custom error message when `key` is not in the map.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryGet}.
*/
function get(UintToAddressMap storage map, uint256 key, string memory errorMessage) internal view returns (address) {
return address(uint160(uint256(_get(map._inner, bytes32(key), errorMessage))));
}
}
EnumerableSet.sol 297 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping (bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) { // Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
// When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.
bytes32 lastvalue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastvalue;
// Update the index for the moved value
set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
require(set._values.length > index, "EnumerableSet: index out of bounds");
return set._values[index];
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
}
IERC721Metadata.sol 27 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 21 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);
}
ERC721Enumerable.sol 159 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./ERC721.sol";
import "./IERC721Enumerable.sol";
/**
* @dev This implements an optional extension of {ERC721} defined in the EIP that adds
* enumerability of all the token ids in the contract as well as all token ids owned by each
* account.
*/
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
// Mapping from owner to list of owned token IDs
mapping(address => mapping(uint256 => uint256)) private _ownedTokens;
// Mapping from token ID to index of the owner tokens list
mapping(uint256 => uint256) private _ownedTokensIndex;
// Array with all token ids, used for enumeration
uint256[] private _allTokens;
// Mapping from token id to position in the allTokens array
mapping(uint256 => uint256) private _allTokensIndex;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
return interfaceId == type(IERC721Enumerable).interfaceId
|| super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
return _ownedTokens[owner][index];
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _allTokens.length;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/
function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
return _allTokens[index];
}
/**
* @dev Hook that is called before any token transfer. This includes minting
* and burning.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, ``from``'s `tokenId` will be burned.
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override {
super._beforeTokenTransfer(from, to, tokenId);
if (from == address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} else if (from != to) {
_removeTokenFromOwnerEnumeration(from, tokenId);
}
if (to == address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} else if (to != from) {
_addTokenToOwnerEnumeration(to, tokenId);
}
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
uint256 length = ERC721.balanceOf(to);
_ownedTokens[to][length] = tokenId;
_ownedTokensIndex[tokenId] = length;
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
uint256 tokenIndex = _ownedTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
delete _ownedTokensIndex[tokenId];
delete _ownedTokens[from][lastTokenIndex];
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _allTokens.length - 1;
uint256 tokenIndex = _allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
// an 'if' statement (like in _removeTokenFromOwnerEnumeration)
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
// This also deletes the contents at the last position of the array
delete _allTokensIndex[tokenId];
_allTokens.pop();
}
}
IERC721Enumerable.sol 29 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);
}
ComedyMonstersClub.sol 237 lines
//Contract based on https://docs.openzeppelin.com/contracts/3.x/erc721
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./ERC721.sol";
import "./Ownable.sol";
import "./SafeMath.sol";
import "./EnumerableMap.sol";
import "./ERC721Enumerable.sol";
contract ComedyMonstersClub is ERC721Enumerable, Ownable {
using SafeMath for uint256;
// Token detail
struct ComedyMonsterDetail {
uint256 creation;
}
// Events
event TokenMinted(uint256 tokenId, address owner, uint256 creation);
// Token Detail
mapping(uint256 => ComedyMonsterDetail) private _comedyMonsterDetails;
// Provenance number
string public PROVENANCE = "";
// Max amount of token to purchase per account each time
uint public MAX_PURCHASE = 20;
// Maximum amount of tokens to supply.
uint256 public MAX_TOKENS = 10100;
// Current price.
uint256 public CURRENT_PRICE = 100000000000000000;
// Define if sale is active
bool public saleIsActive = true;
// Base URI
string private baseURI;
address private creatorAddress1 = 0xFB76016964A33277a168c950d0010b508CbA9bAc;
address private creatorAddress2 = 0xeBD0414164018B2172fb06933Be974263DBc0B83;
address private creatorAddress3 = 0x0dC3EDF769F34962bbDA01eBEf4F700287f51e9d;
/**
* Contract constructor
*/
constructor(string memory name, string memory symbol, string memory _baseUri, uint256 _maxTokens) ERC721(name, symbol) {
setBaseURI(_baseUri);
MAX_TOKENS = _maxTokens;
}
/*
* Set provenance once it's calculated
*/
function setProvenanceHash(string memory _provenanceHash) public onlyOwner {
PROVENANCE = _provenanceHash;
}
/*
* Set max tokens
*/
function setMaxTokens(uint256 _maxTokens) public onlyOwner {
MAX_TOKENS = _maxTokens;
}
/*
* Set max purchase
*/
function setMaxPurchase(uint256 _maxPurchase) public onlyOwner {
MAX_PURCHASE = _maxPurchase;
}
/*
* Pause sale if active, make active if paused
*/
function setSaleState(bool _newState) public onlyOwner {
saleIsActive = _newState;
}
/**
* Set the current token price
*/
function setCurrentPrice(uint256 _currentPrice) public onlyOwner {
CURRENT_PRICE = _currentPrice;
}
/**
* Get the token detail
*/
function getComedyMonsterDetail(uint256 _tokenId) public view returns(ComedyMonsterDetail memory detail) {
require(_exists(_tokenId), "Token was not minted");
return _comedyMonsterDetails[_tokenId];
}
/**
* @dev Changes the base URI if we want to move things in the future (Callable by owner only)
*/
function setBaseURI(string memory BaseURI) public onlyOwner {
baseURI = BaseURI;
}
/**
* @dev Base URI for computing {tokenURI}. Empty by default, can be overriden
* in child contracts.
*/
function _baseURI() internal view virtual override returns (string memory) {
return baseURI;
}
/**
* Set creatorAddress1 address
*/
function setCreatorAddress1(address _creatorAddress1) public onlyOwner {
creatorAddress1 = _creatorAddress1;
}
/**
* Set creatorAddress2 address
*/
function setCreatorAddress2(address _creatorAddress2) public onlyOwner {
creatorAddress2 = _creatorAddress2;
}
/**
* Set creatorAddress3 address
*/
function setCreatorAddress3(address _creatorAddress3) public onlyOwner {
creatorAddress3 = _creatorAddress3;
}
/**
* Withdraw
*/
function withdraw() public onlyOwner {
require(address(this).balance > 0, "No balance to withdraw");
uint balance = address(this).balance;
uint creatorShare1 = balance.mul(50).div(100);
uint creatorShare2 = balance.mul(25).div(100);
uint creatorShare3 = balance.mul(25).div(100);
(bool success, ) = creatorAddress1.call{value: creatorShare1}("");
require(success, "creatorAddress1 Withdrawal failed");
(success, ) = creatorAddress2.call{value: creatorShare2}("");
require(success, "creatorAddress2 Withdrawal failed");
(success, ) = creatorAddress3.call{value: creatorShare3}("");
require(success, "creatorAddress3 Withdrawal failed");
}
/**
* Withdraw
*/
function withdrawAlt() public onlyOwner {
require(address(this).balance > 0, "No balance to withdraw");
uint balance = address(this).balance;
payable(msg.sender).transfer(balance);
}
/**
* Reserve tokens
*/
function reserveTokens(uint256 qty) public onlyOwner {
uint tokenId;
uint256 creation = block.timestamp;
for (uint i = 1; i <= qty; i++) {
tokenId = totalSupply().add(1);
if (tokenId <= MAX_TOKENS) {
_safeMint(msg.sender, tokenId);
_comedyMonsterDetails[tokenId] = ComedyMonsterDetail(creation);
emit TokenMinted(tokenId, msg.sender, creation);
}
}
}
/**
* Mint token for owners.
*/
function mintTokens(address[] memory _owners) public onlyOwner {
require(totalSupply().add(_owners.length) <= MAX_TOKENS, "Purchase would exceed max supply");
uint256 creation = block.timestamp;
uint256 tokenId;
for (uint i = 0; i < _owners.length; i++) {
tokenId = totalSupply().add(1);
if (tokenId <= MAX_TOKENS) {
_safeMint(_owners[i], tokenId);
_comedyMonsterDetails[tokenId] = ComedyMonsterDetail(creation);
emit TokenMinted(tokenId, _owners[i], creation);
}
}
}
/**
* Mint tokens
*/
function mint(uint qty) public payable {
require(saleIsActive, "Mint is not available right now");
require(qty <= MAX_PURCHASE, "Can only mint 20 tokens at a time");
require(totalSupply().add(qty) <= MAX_TOKENS, "Purchase would exceed max supply");
require(CURRENT_PRICE.mul(qty) <= msg.value, "Value sent is not correct");
uint256 creation = block.timestamp;
uint tokenId;
for(uint i = 1; i <= qty; i++) {
tokenId = totalSupply().add(1);
if (tokenId <= MAX_TOKENS) {
_safeMint(msg.sender, tokenId);
_comedyMonsterDetails[tokenId] = ComedyMonsterDetail(creation);
emit TokenMinted(tokenId, msg.sender, creation);
}
}
}
/**
* Get tokens owner
*/
function tokensOfOwner(address _owner) external view returns(uint256[] memory) {
uint tokenCount = balanceOf(_owner);
uint256[] memory tokensId = new uint256[](tokenCount);
for(uint i = 0; i < tokenCount; i++){
tokensId[i] = tokenOfOwnerByIndex(_owner, i);
}
return tokensId;
}
}
Read Contract
CURRENT_PRICE 0x4b369a61 → uint256
MAX_PURCHASE 0x7146bd08 → uint256
MAX_TOKENS 0xf47c84c5 → uint256
PROVENANCE 0x6373a6b1 → string
balanceOf 0x70a08231 → uint256
getApproved 0x081812fc → address
getComedyMonsterDetail 0x4ebe2e1a → tuple
isApprovedForAll 0xe985e9c5 → bool
name 0x06fdde03 → string
owner 0x8da5cb5b → address
ownerOf 0x6352211e → address
saleIsActive 0xeb8d2444 → bool
supportsInterface 0x01ffc9a7 → bool
symbol 0x95d89b41 → string
tokenByIndex 0x4f6ccce7 → uint256
tokenOfOwnerByIndex 0x2f745c59 → uint256
tokenURI 0xc87b56dd → string
tokensOfOwner 0x8462151c → uint256[]
totalSupply 0x18160ddd → uint256
Write Contract 21 functions
These functions modify contract state and require a wallet transaction to execute.
approve 0x095ea7b3
address to
uint256 tokenId
mint 0xa0712d68
uint256 qty
mintTokens 0x3fa40f94
address[] _owners
renounceOwnership 0x715018a6
No parameters
reserveTokens 0xd031370b
uint256 qty
safeTransferFrom 0x42842e0e
address from
address to
uint256 tokenId
safeTransferFrom 0xb88d4fde
address from
address to
uint256 tokenId
bytes _data
setApprovalForAll 0xa22cb465
address operator
bool approved
setBaseURI 0x55f804b3
string BaseURI
setCreatorAddress1 0xcfafe1ef
address _creatorAddress1
setCreatorAddress2 0xe80893af
address _creatorAddress2
setCreatorAddress3 0x781b02cc
address _creatorAddress3
setCurrentPrice 0x18b20071
uint256 _currentPrice
setMaxPurchase 0x71189742
uint256 _maxPurchase
setMaxTokens 0x11e776fe
uint256 _maxTokens
setProvenanceHash 0x10969523
string _provenanceHash
setSaleState 0xc4e37095
bool _newState
transferFrom 0x23b872dd
address from
address to
uint256 tokenId
transferOwnership 0xf2fde38b
address newOwner
withdraw 0x3ccfd60b
No parameters
withdrawAlt 0x1a5e2a36
No parameters
Recent Transactions
No transactions found for this address