Address: 0x217c5fae72adDE7a31175ee2294D14a5e8e4D61D
Balance (XRP): 0 XRP
Bytecode: 0x60806040526004361015610013575b610ba7565b61001e60003561015d565b806301ffc9a7146101585780630668d0bb146101535780630bb310de1461014e578063248a9ca3146101495780632f2ff15d146101445780633474a4a61461013f57806336568abe1461013a57806344004cc1146101355780634782f7791461013057806363acc14d1461012b5780638c17030f146101265780639010d07c1461012157806391d148541461011c5780639d043a6614610117578063a217fddf14610112578063a971e8421461010d578063bad4366114610108578063ca15c87314610103578063d547741f146100fe5763ed4c2ac70361000e57610b74565b610b40565b610b0b565b610aaf565b610a17565b6109e2565b61096f565b6108a4565b61086e565b6107e3565b610723565b6106a8565b610646565b6105d7565b6105a2565b610499565b610436565b61039a565b61034b565b6101ef565b60e01c90565b60405190565b600080fd5b600080fd5b600080fd5b63ffffffff60e01b1690565b61018d81610178565b0361019457565b600080fd5b905035906101a682610184565b565b906020828203126101c2576101bf91600001610199565b90565b61016e565b151590565b6101d5906101c7565b9052565b91906101ed906000602085019401906101cc565b565b3461021f5761021b61020a6102053660046101a8565b610bb1565b610212610163565b918291826101d9565b0390f35b610169565b60018060a01b031690565b61023890610224565b90565b6102448161022f565b0361024b57565b600080fd5b9050359061025d8261023b565b565b90565b61026b8161025f565b0361027257565b600080fd5b9050359061028482610262565b565b600080fd5b600080fd5b600080fd5b909182601f830112156102cf5781359167ffffffffffffffff83116102ca5760200192602083028401116102c557565b610290565b61028b565b610286565b91909160a081840312610340576102ee8360008301610250565b926102fc8160208401610277565b9261030a8260408501610250565b926103188360608301610277565b92608082013567ffffffffffffffff811161033b576103379201610295565b9091565b610173565b61016e565b60000190565b6103656103593660046102d4565b94939093929192610d21565b61036d610163565b8061037781610345565b0390f35b906020828203126103955761039291600001610250565b90565b61016e565b346103c8576103b26103ad36600461037b565b610f69565b6103ba610163565b806103c481610345565b0390f35b610169565b90565b6103d9816103cd565b036103e057565b600080fd5b905035906103f2826103d0565b565b9060208282031261040e5761040b916000016103e5565b90565b61016e565b61041c906103cd565b9052565b919061043490600060208501940190610413565b565b346104665761046261045161044c3660046103f4565b610fc7565b610459610163565b91829182610420565b0390f35b610169565b9190604083820312610494578061048861049192600086016103e5565b93602001610250565b90565b61016e565b346104c8576104b26104ac36600461046b565b90611012565b6104ba610163565b806104c481610345565b0390f35b610169565b60009103126104d857565b61016e565b6104e69061025f565b9052565b6104f39061022f565b9052565b67ffffffffffffffff1690565b61050d906104f7565b9052565b61051a906103cd565b9052565b9060a08061058a93610538600082015160008601906104dd565b61054a602082015160208601906104dd565b61055c604082015160408601906104ea565b61056e60608201516060860190610504565b61058060808201516080860190610504565b0151910190610511565b565b91906105a090600060c0850194019061051e565b565b346105d2576105b23660046104cd565b6105ce6105bd61122e565b6105c5610163565b9182918261058c565b0390f35b610169565b34610606576105f06105ea36600461046b565b906112f7565b6105f8610163565b8061060281610345565b0390f35b610169565b90916060828403126106415761063e6106278460008501610250565b936106358160208601610250565b93604001610277565b90565b61016e565b346106755761065f61065936600461060b565b91611396565b610667610163565b8061067181610345565b0390f35b610169565b91906040838203126106a357806106976106a09260008601610250565b93602001610277565b90565b61016e565b346106d7576106c16106bb36600461067a565b9061149c565b6106c9610163565b806106d381610345565b0390f35b610169565b60808183031261071e576106f38260008301610250565b9261071b6107048460208501610250565b936107128160408601610250565b936060016103e5565b90565b61016e565b346107555761073f6107363660046106dc565b9291909161158a565b610747610163565b8061075181610345565b0390f35b610169565b610763816104f7565b0361076a57565b600080fd5b9050359061077c8261075a565b565b909160c0828403126107de576107978360008401610277565b926107a58160208501610277565b926107b38260408301610250565b926107db6107c4846060850161076f565b936107d2816080860161076f565b9360a0016103e5565b90565b61016e565b34610818576108026107f636600461077e565b94939093929192611a34565b61080a610163565b8061081481610345565b0390f35b610169565b9190604083820312610846578061083a61084392600086016103e5565b93602001610277565b90565b61016e565b6108549061022f565b9052565b919061086c9060006020850194019061084b565b565b3461089f5761089b61088a61088436600461081d565b90611a64565b610892610163565b91829182610858565b0390f35b610169565b346108d5576108d16108c06108ba36600461046b565b90611aa4565b6108c8610163565b918291826101d9565b0390f35b610169565b600080fd5b908160c09103126108ed5790565b6108da565b908160e09103126109005790565b6108da565b9160608383031261096a5761091d8260008501610250565b92602081013567ffffffffffffffff8111610965578361093e9183016108df565b92604082013567ffffffffffffffff81116109605761095d92016108f2565b90565b610173565b610173565b61016e565b346109a05761099c61098b610985366004610905565b91611dc7565b610993610163565b91829182610420565b0390f35b610169565b90565b60001b90565b6109c26109bd6109c7926109a5565b6109a8565b6103cd565b90565b6109d460006109ae565b90565b6109df6109ca565b90565b34610a12576109f23660046104cd565b610a0e6109fd6109d7565b610a05610163565b91829182610420565b0390f35b610169565b34610a4757610a273660046104cd565b610a43610a32611e68565b610a3a610163565b91829182610858565b0390f35b610169565b91608083830312610aaa57610a6482600085016103e5565b9260208101359167ffffffffffffffff8311610aa557610a8984610aa2948401610295565b939094610a998160408601610250565b936060016103e5565b90565b610173565b61016e565b34610ae357610adf610ace610ac5366004610a4c565b93929092611fa4565b610ad6610163565b918291826101d9565b0390f35b610169565b610af19061025f565b9052565b9190610b0990600060208501940190610ae8565b565b34610b3b57610b37610b26610b213660046103f4565b61204c565b610b2e610163565b91829182610af5565b0390f35b610169565b34610b6f57610b59610b5336600461046b565b9061209c565b610b61610163565b80610b6b81610345565b0390f35b610169565b34610ba257610b8c610b873660046103f4565b6120d0565b610b94610163565b80610b9e81610345565b0390f35b610169565b600080fd5b600090565b610bb9610bac565b5080610bd4610bce635f05bb8960e11b610178565b91610178565b148015610bf8575b908115610be8575b5090565b610bf29150612115565b38610be4565b50610c02816120db565b610bdc565b60081c90565b60018060a01b031690565b610c24610c2991610c07565b610c0d565b90565b610c369054610c18565b90565b90565b610c50610c4b610c5592610224565b610c39565b610224565b90565b610c6190610c3c565b90565b610c6d90610c58565b90565b610c7990610c3c565b90565b610c8590610c70565b90565b600080fd5b601f801991011690565b634e487b7160e01b600052604160045260246000fd5b90610cb790610c8d565b810190811067ffffffffffffffff821117610cd157604052565b610c97565b60e01b90565b6000910312610ce757565b61016e565b916020610d0e929493610d076040820196600083019061084b565b0190610ae8565b565b610d18610163565b3d6000823e3d90fd5b93610d34939591958693909192936122b6565b610d4e610d49610d446005610c2c565b610c64565b610c7c565b632e73e0fd828492803b15610eae57610d7b60008094610d86610d6f610163565b97889687958694610cd6565b845260048401610cec565b03925af19081610e81575b5015600014610e7c576001610dde575b5b907ff32d98590495ee51bacb93809409a188e7ab8268b70b4c969d9da3a883c539f791610dd9610dd0610163565b92839283610cec565b0390a1565b610df8610df3610dee6005610c2c565b610c64565b610c7c565b6340c10f19828492803b15610e7757610e2560008094610e30610e19610163565b97889687958694610cd6565b845260048401610cec565b03925af18015610e7257610e45575b50610da1565b610e659060003d8111610e6b575b610e5d8183610cad565b810190610cdc565b38610e3f565b503d610e53565b610d10565b610c88565b610da2565b610ea19060003d8111610ea7575b610e998183610cad565b810190610cdc565b38610d91565b503d610e8f565b610c88565b7f70649ec320b507febad3e8ef750e5f580b9ae32f9f50d4c7b121332c8197153090565b610ef090610eeb610ee6610eb3565b61251a565b610f54565b565b610efb90610c3c565b90565b610f0790610ef2565b90565b90610f1b60018060a01b03916109a8565b9181191691161790565b610f2e90610ef2565b90565b90565b90610f49610f44610f5092610f25565b610f31565b8254610f0a565b9055565b610f60610f6791610efe565b6003610f34565b565b610f7290610ed7565b565b600090565b610f82906103cd565b90565b90610f8f90610f79565b600052602052604060002090565b60001c90565b90565b610fb2610fb791610f9d565b610fa3565b90565b610fc49054610fa6565b90565b6001610fe0610fe692610fd8610f74565b506000610f85565b01610fba565b90565b9061100491610fff610ffa82610fc7565b61251a565b611006565b565b906110109161252e565b565b9061101c91610fe9565b565b9061103161102a610163565b9283610cad565b565b61103d60c061101e565b90565b600090565b600090565b600090565b600090565b61105c611033565b90602080808080808761106d611040565b815201611078611040565b815201611083611045565b81520161108e61104a565b81520161109961104a565b8152016110a461104f565b81525050565b6110b2611054565b90565b90565b6110c46110c991610f9d565b6110b5565b90565b6110d690546110b8565b90565b906110e39061025f565b9052565b6110f36110f891610f9d565b610c0d565b90565b61110590546110e7565b90565b906111129061022f565b9052565b60a01c90565b67ffffffffffffffff1690565b61113561113a91611116565b61111c565b90565b6111479054611129565b90565b90611154906104f7565b9052565b61116461116991610f9d565b61111c565b90565b6111769054611158565b90565b90611183906103cd565b9052565b906112206112176004611198611033565b946111b16111a8600083016110cc565b600088016110d9565b6111c96111c0600183016110cc565b602088016110d9565b6111e16111d8600283016110fb565b60408801611108565b6111f96111f06002830161113d565b6060880161114a565b6112116112086003830161116c565b6080880161114a565b01610fba565b60a08401611179565b565b61122b90611187565b90565b6112366110aa565b506112416006611222565b90565b60209181520190565b60207f20726f6c657320666f722073656c660000000000000000000000000000000000917f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201520152565b6112a8602f604092611244565b6112b18161124d565b0190565b6112cb906020810190600081830391015261129b565b90565b156112d557565b6112dd610163565b62461bcd60e51b8152806112f3600482016112b5565b0390fd5b906113249161131f8261131961131361130e612558565b61022f565b9161022f565b146112ce565b612565565b565b7f5d8e12c39142ff96d79d04d15d1ba1269e4fe57bb9d26f43523628b34ba108ec90565b90611365929161136061135b611326565b61251a565b61137f565b565b61137090610c3c565b90565b61137c90611367565b90565b9161138c61139493611373565b9190916125c0565b565b906113a1929161134a565b565b906113bd916113b86113b3611326565b61251a565b61144a565b565b905090565b6113d0600080926113bf565b0190565b6113dd906113c4565b90565b67ffffffffffffffff81116113fe576113fa602091610c8d565b0190565b610c97565b90611415611410836113e0565b61101e565b918252565b606090565b3d60001461143c576114303d611403565b903d6000602084013e5b565b61144461141a565b9061143a565b60006114799281929061145b610163565b9081611466816113d4565b03925af161147261141f565b50156101c7565b61147f57565b6000631d42c86760e21b81528061149860048201610345565b0390fd5b906114a6916113a3565b565b60ff1690565b6114ba6114bf91610f9d565b6114a8565b90565b6114cc90546114ae565b90565b60081b90565b906114e8610100600160a81b03916114cf565b9181191691161790565b6114fb90610c70565b90565b90565b9061151661151161151d926114f2565b6114fe565b82546114d5565b9055565b7f4c02318d8c3aadc98ccf18aebbf3126f651e0c3f6a1de5ff8edcf6724a2ad5c290565b9061155160ff916109a8565b9181191691161790565b611564906101c7565b90565b90565b9061157f61157a6115869261155b565b611567565b8254611545565b9055565b92909261159760056114c2565b6115f5576115a96115e7946005611501565b6115bb6115b46109ca565b829061252e565b6115cd6115c6611521565b829061252e565b6115df6115d8611326565b829061252e565b91909161260b565b6115f36001600561156a565b565b600063f92ee8a960e01b81528061160e60048201610345565b0390fd5b90611630959493929161162b611626611521565b61251a565b6118fd565b565b61164661164161164b926104f7565b610c39565b61025f565b90565b61166261165d611667926109a5565b610c39565b61025f565b90565b61167460c061101e565b90565b611681905161025f565b90565b90611691600019916109a8565b9181191691161790565b6116af6116aa6116b49261025f565b610c39565b61025f565b90565b90565b906116cf6116ca6116d69261169b565b6116b7565b8254611684565b9055565b6116e4905161022f565b90565b906116fc6116f7611703926114f2565b6114fe565b8254610f0a565b9055565b61171190516104f7565b90565b60a01b90565b9061173067ffffffffffffffff60a01b91611714565b9181191691161790565b61174e611749611753926104f7565b610c39565b6104f7565b90565b90565b9061176e6117696117759261173a565b611756565b825461171a565b9055565b9061178c67ffffffffffffffff916109a8565b9181191691161790565b906117ab6117a66117b29261173a565b611756565b8254611779565b9055565b6117c090516103cd565b90565b6117cc90610f9d565b90565b906117e46117df6117eb92610f79565b6117c3565b8254611684565b9055565b9061188060a06004611886946118146000820161180e60008801611677565b906116ba565b61182d6001820161182760208801611677565b906116ba565b61184660028201611840604088016116da565b906116e7565b61185f6002820161185960608801611707565b90611759565b6118786003820161187260808801611707565b90611796565b0192016117b6565b906117cf565b565b90611892916117ef565b565b61189d906104f7565b9052565b91946118ea6118f4929897956118e060a0966118d66118fb9a6118cc60c08a019e60008b0190610ae8565b6020890190610ae8565b604087019061084b565b6060850190611894565b6080830190611894565b0190610413565b565b91939092948161191561190f886104f7565b916104f7565b108015611a19575b6119fc578261193561192f600061164e565b9161025f565b146119df57826119a16119da9461199a876119918a6119888d61197f8b936119768c9761196d61196361166a565b9b60008d016110d9565b60208b016110d9565b60408901611108565b6060870161114a565b6080850161114a565b60a08301611179565b6006611888565b9394959190917fabec13ca1773eed55d54d2f64593c33fa520ee45cac73a162f13928a2ebee233966119d1610163565b968796876118a1565b0390a1565b60006310ba94e960e31b8152806119f860048201610345565b0390fd5b60006310ba94e960e31b815280611a1560048201610345565b0390fd5b5081611a2d611a274261025f565b91611632565b111561191d565b90611a429594939291611612565b565b600090565b90611a5390610f79565b600052602052604060002090565b90565b90611a84611a7f611a8993611a77611a44565b506001611a49565b611a61565b61265b565b90565b90611a96906114f2565b600052602052604060002090565b611acb916000611ac0611ac693611ab9610bac565b5082610f85565b01611a8c565b6114c2565b90565b60018060a01b031690565b611ae5611aea91610f9d565b611ace565b90565b611af79054611ad9565b90565b611b0390610c70565b90565b90505190611b13826103d0565b565b90602082820312611b2f57611b2c91600001611b06565b90565b61016e565b50611b43906020810190610250565b90565b50611b55906020810190610199565b90565b611b6190610178565b9052565b50611b749060208101906103e5565b90565b600080fd5b600080fd5b600080fd5b9035600160200382360303811215611bc757016020813591019167ffffffffffffffff8211611bc2576001820236038313611bbd57565b611b7c565b611b77565b611b81565b60209181520190565b90826000939282370152565b9190611bfb81611bf481611c0095611bcc565b8095611bd5565b610c8d565b0190565b9035600160400382360303811215611c1a570190565b611b81565b9035600160200382360303811215611c6057016020813591019167ffffffffffffffff8211611c5b576001820236038313611c5657565b611b7c565b611b77565b611b81565b60209181520190565b9190611c8881611c8181611c8d95611c65565b8095611bd5565b610c8d565b0190565b50611ca090602081019061076f565b90565b90611ce1906020611cd9611ccf60408401611cc16000880188611c1f565b908683036000880152611c6e565b9482810190611c91565b910190610504565b90565b611d8e91611d80611d7560c08301611d0c611d026000870187611b34565b60008601906104ea565b611d26611d1c6020870187611b46565b6020860190611b58565b611d40611d366040870187611b65565b6040860190610511565b611d5a611d506060870187611b65565b6060860190610511565b611d676080860186611b86565b908583036080870152611be1565b9260a0810190611c04565b9060a0818403910152611ca3565b90565b939290611dbd604091611dc594611db0606089019260008a019061084b565b8782036020890152611ce4565b940190610413565b565b9150602090611dd4610f74565b50611de7611de26003611aed565b611afa565b611e13633808a90b949294611e1e611dff6004610fba565b611e07610163565b97889687958695610cd6565b855260048501611d91565b03915afa908115611e6357600091611e35575b5090565b611e56915060203d8111611e5c575b611e4e8183610cad565b810190611b15565b38611e31565b503d611e44565b610d10565b611e70611a44565b50611e7b6005610c2c565b90565b90611e88906114f2565b600052602052604060002090565b90611ea090610f79565b600052602052604060002090565b60601b90565b611ebd90611eae565b90565b611ec990611eb4565b90565b611ed8611edd9161022f565b611ec0565b9052565b90565b611ef0611ef5916103cd565b611ee1565b9052565b601481611f0c611f149360209695611ecc565b018092611ee4565b0190565b60200190565b5190565b67ffffffffffffffff8111611f3a5760208091020190565b610c97565b90929192611f54611f4f82611f22565b61101e565b9381855260208086019202830192818411611f9157915b838310611f785750505050565b60208091611f8684866103e5565b815201920191611f6b565b610290565b611fa1913691611f3f565b90565b9093929192611fb1610bac565b50611fd9611fd3611fce611fc760028790611e7e565b8590611e96565b6114c2565b156101c7565b9485611fe8575b505050505090565b61203d95509061201f6120389392959294612010612004610163565b93849260208401611ef9565b60208201810382520382610cad565b61203161202b82611f1e565b91611f18565b2093611f96565b612694565b3880808080611fe0565b600090565b61206b6120666120709261205e612047565b506001611a49565b611a61565b6126be565b90565b9061208e9161208961208482610fc7565b61251a565b612090565b565b9061209a91612565565b565b906120a691612073565b565b6120c1906120bc6120b7610eb3565b61251a565b6120c3565b565b6120ce9060046117cf565b565b6120d9906120a8565b565b6120e3610bac565b50806120f86120f26000610178565b91610178565b14908115612105575b5090565b61210f91506126de565b38612101565b61211d610bac565b50612127816126de565b908115612133575b5090565b61213d915061271e565b3861212f565b91602061216592949361215e60408201966000830190610ae8565b0190610ae8565b565b634e487b7160e01b600052601160045260246000fd5b61218c6121929193929361025f565b9261025f565b820391821161219d57565b612167565b600090565b6121b66121bc9193929361025f565b9261025f565b916121c883820261025f565b9281840414901517156121d757565b612167565b6121e59061164e565b9052565b60409061221361221a94969593966122096060840198600085019061084b565b6020830190610ae8565b01906121dc565b565b60409061224661224d949695939661223c6060840198600085019061084b565b6020830190610ae8565b0190610ae8565b565b61226361225e612268926109a5565b610c39565b610224565b90565b6122749061224f565b90565b61228090610c70565b90565b6040906122ad6122b494969593966122a36060840198600085019061084b565b60208301906121dc565b0190610ae8565b565b91939290926122f06122cb600260060161113d565b6122ea6122e46122de600360060161116c565b92611632565b91611632565b9061275e565b6124fd5761230160006006016110cc565b61231361230d8561025f565b9161025f565b106124d0578291612361916123426123739561233c600060060191612337836110cc565b61217d565b906116ba565b61234f6004600601610fba565b9190339161235b6121a2565b93612855565b61236e60016006016110cc565b6121a7565b918161239361238d61238860026006016110fb565b61022f565b9161022f565b036124a257806123ab6123a58561025f565b9161025f565b1061247f5750806123cd6123c76123c2600061226b565b61022f565b9161022f565b1460001461241257346123e86123e28461025f565b9161025f565b036123f25750505b565b61240e346000938493630f55e7df60e11b85526004850161221c565b0390fd5b9034612427612421600061164e565b9161025f565b1160001461245c57612439600061226b565b600090612458346000938493630f55e7df60e11b855260048501612283565b0390fd5b61246861247a92611373565b903361247330612277565b9192612928565b6123f0565b8261249e8391926000938493630f55e7df60e11b85526004850161221c565b0390fd5b826124b060026006016110fb565b6124cc600080938493630f55e7df60e11b8552600485016121e9565b0390fd5b826124de60006006016110cc565b6124f96000928392639e4c446160e01b845260048401612143565b0390fd5b6000630fe219dd60e21b81528061251660048201610345565b0390fd5b61252c90612526612558565b90612ae4565b565b9061255061254b61255593612544818590612b7d565b6001611a49565b611a61565b612c63565b50565b612560611a44565b503390565b9061258761258261258c9361257b818590612c9e565b6001611a49565b611a61565b612d37565b50565b61259890610c70565b90565b63ffffffff1690565b6125b86125b36125bd9261259b565b610cd6565b610178565b90565b916126046004926125f561260995936125dc63a9059cbb6125a4565b926125e5610163565b9687946020860190815201610cec565b60208201810382520383610cad565b612ee5565b565b90612621612626939261261c610eb3565b61252e565b612f52565b565b90565b61263761263c91610f9d565b61169b565b90565b61265361264e6126589261025f565b610c39565b610224565b90565b6126876126826126919361267d600061268c95612676611a44565b5001612628565b612fea565b61262b565b61263f565b610c70565b90565b6126ae6126ba92936126b4926126a8610bac565b5061303f565b926103cd565b916103cd565b1490565b6126d660006126db926126cf612047565b5001612628565b6130aa565b90565b6126e6610bac565b50806127016126fb635a05180f60e01b610178565b91610178565b1490811561270e575b5090565b61271891506130c2565b3861270a565b612726610bac565b508061274161273b634e821d3360e11b610178565b91610178565b1490811561274e575b5090565b61275891506120db565b3861274a565b612766610bac565b508161277b612775600061164e565b9161025f565b149081156127ae575b50908115612791575b5090565b90506127a66127a0429261025f565b9161025f565b10153861278d565b90506127c36127bd429261025f565b9161025f565b1038612784565b60209181520190565b600080fd5b9037565b9091826127e8916127ca565b9160018060fb1b03811161280b578291602061280792029384916127d8565b0190565b6127d3565b9061284161284c916128539698979560609561283460808701936000880190610413565b85830360208701526127dc565b96604083019061084b565b0190610413565b565b92938361287361286d61286860006109ae565b6103cd565b916103cd565b03612880575b5050505050565b61289861289285848689918693611fa4565b156101c7565b6128c857505050906128b96128be926128b46001936002611e7e565b611e96565b61156a565b3880808080612879565b846128f1918593949190916128db610163565b9586956304cb8cd560e31b875260048701612810565b0390fd5b60409061291f61292694969593966129156060840198600085019061084b565b602083019061084b565b0190610ae8565b565b612975939161296160049461297093946129456323b872dd6125a4565b93919091612951610163565b97889560208701908152016128f5565b60208201810382520383610cad565b612ee5565b565b90565b61298e61298961299392612977565b610c39565b61025f565b90565b905090565b60007f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000910152565b6129cf60178092612996565b6129d88161299b565b0190565b5190565b60005b8381106129f4575050906000910152565b8060209183015181850152016129e3565b612a2a612a2192602092612a18816129dc565b94858093612996565b938491016129e0565b0190565b60007f206973206d697373696e6720726f6c6520000000000000000000000000000000910152565b612a6260118092612996565b612a6b81612a2e565b0190565b612a89612a949392612a83612a8e936129c3565b90612a05565b612a56565b90612a05565b90565b90565b612ab9612ac2602093612ac793612ab0816129dc565b93848093611244565b958691016129e0565b610c8d565b0190565b612ae19160208201916000818403910152612a9a565b90565b90612af9612af3838390611aa4565b156101c7565b612b01575050565b612b7991612b57612b30612b20612b1a612b5c95613155565b9361262b565b612b2a602061297a565b90613378565b91612b48612b3c610163565b93849260208401612a6f565b60208201810382520382610cad565b612a97565b612b64610163565b91829162461bcd60e51b835260048301612acb565b0390fd5b612b91612b8b828490611aa4565b156101c7565b612b9a575b5050565b612bbc6001612bb76000612baf818690610f85565b018590611a8c565b61156a565b90612bc5612558565b90612c02612bfc612bf67f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d95610f79565b926114f2565b926114f2565b92612c0b610163565b80612c1581610345565b0390a43880612b96565b612c2890610c3c565b90565b612c3f612c3a612c4492610224565b610c39565b61025f565b90565b612c5b612c56612c609261025f565b6109a8565b6103cd565b90565b90612c96612c90612c8b612c866000612c9b96612c7e610bac565b500194612c1f565b612c2b565b612c47565b91612628565b613598565b90565b612ca9818390611aa4565b612cb2575b5050565b612cd46000612ccf6000612cc7818690610f85565b018590611a8c565b61156a565b90612cdd612558565b90612d1a612d14612d0e7ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b95610f79565b926114f2565b926114f2565b92612d23610163565b80612d2d81610345565b0390a43880612cae565b90612d6a612d64612d5f612d5a6000612d6f96612d52610bac565b500194612c1f565b612c2b565b612c47565b91612628565b61368e565b90565b67ffffffffffffffff8111612d9057612d8c602091610c8d565b0190565b610c97565b90612da7612da283612d72565b61101e565b918252565b60007f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564910152565b612dde6020612d95565b90612deb60208301612dac565b565b612df5612dd4565b90565b612e01816101c7565b03612e0857565b600080fd5b90505190612e1a82612df8565b565b90602082820312612e3657612e3391600001612e0d565b90565b61016e565b60207f6f74207375636365656400000000000000000000000000000000000000000000917f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008201520152565b612e96602a604092611244565b612e9f81612e3b565b0190565b612eb99060208101906000818303910152612e89565b90565b15612ec357565b612ecb610163565b62461bcd60e51b815280612ee160048201612ea3565b0390fd5b612f2f91612ef5612f049261258f565b90612efe612ded565b91613798565b612f0d81611f1e565b612f20612f1a600061164e565b9161025f565b14908115612f31575b50612ebc565b565b612f4c91506020612f4182611f1e565b818301019101612e1c565b38612f29565b90612f69612f62612f7093610efe565b6003610f34565b60046117cf565b565b634e487b7160e01b600052603260045260246000fd5b5490565b600052602060002090565b612fa081612f88565b821015612fbb57612fb2600191612f8c565b91020190600090565b612f72565b1c90565b612fd4906008612fd99302612fc0565b610fa3565b90565b90612fe79154612fc4565b90565b61300991600061300392612ffc610f74565b5001612f97565b90612fdc565b90565b6001613018910161025f565b90565b5190565b906130298261301b565b81101561303a576020809102010190565b612f72565b9190613049610f74565b50613054600061164e565b905b8161307161306b6130668761301b565b61025f565b9161025f565b10156130a35761309761309d9161309161308c87869061301f565b6117b6565b906137bb565b9161300c565b90613056565b9192505090565b60006130bf916130b8612047565b5001612f88565b90565b6130ca610bac565b50806130e56130df637965db0b60e01b610178565b91610178565b149081156130f2575b5090565b6130fc91506137fb565b386130ee565b606090565b90565b60ff1690565b61312461311f61312992613107565b610c39565b61310a565b90565b6131366014613110565b90565b61314d6131486131529261310a565b610c39565b61025f565b90565b61317261316d61318892613167613102565b50612c1f565b612c2b565b61318261317d61312c565b613139565b90613378565b90565b90565b6131a261319d6131a79261318b565b610c39565b61025f565b90565b6131b96131bf9193929361025f565b9261025f565b82018092116131ca57565b612167565b369037565b906131f96131e183611403565b926020806131ef86936113e0565b92019103906131cf565b565b600360fc1b90565b9061320d82611f1e565b81101561321f57600160209102010190565b612f72565b600f60fb1b90565b90565b61324361323e6132489261322c565b610c39565b61025f565b90565b6132549061025f565b60008114613263576001900390565b612167565b6f181899199a1a9b1b9c1cb0b131b232b360811b90565b613287613268565b90565b90565b6132a161329c6132a69261328a565b610c39565b61025f565b90565b60f81b90565b90565b6132c66132c16132cb926132af565b610c39565b61310a565b90565b6132ed906132e76132e16132f29461310a565b9161025f565b90612fc0565b61025f565b90565b60007f537472696e67733a20686578206c656e67746820696e73756666696369656e74910152565b61332960208092611244565b613332816132f5565b0190565b61334c906020810190600081830391015261331d565b90565b1561335657565b61335e610163565b62461bcd60e51b81528061337460048201613336565b0390fd5b9190613382613102565b5061341c61340c6133b86133b36133a3600261339e879161318e565b6121a7565b6133ad600261318e565b906131aa565b6131d4565b926133c16131fb565b6133da856133d460009360001a9361164e565b90613203565b536133e3613224565b6133fc856133f660019360001a9361322f565b90613203565b53613407600261318e565b6121a7565b613416600161322f565b906131aa565b925b8361343261342c600161322f565b9161025f565b11156134995761344061327f565b8161344b600f61328d565b16916010831015613494576134676134889261348e941a6132a9565b6134778591889060001a92613203565b5361348260046132b2565b906132ce565b9361324b565b9261341e565b612f72565b6134c19293506134bc906134b66134b0600061164e565b9161025f565b1461334f565b612a97565b90565b90565b600052602060002090565b5490565b6134df816134d2565b8210156134fa576134f16001916134c7565b91020190600090565b612f72565b1b90565b9190600861351f910291613519600019846134ff565b926134ff565b9181191691161790565b919061353f61353a61354793610f79565b6117c3565b908354613503565b9055565b908154916801000000000000000083101561357b5782613573916001613579950181556134d6565b90613529565b565b610c97565b9061358a90610f79565b600052602052604060002090565b6135a0610bac565b506135b56135af828490613821565b156101c7565b6000146135f8576135ee6135f3926135d96135d2600085016134c4565b829061354b565b60016135e760008501612f88565b9301613580565b6116ba565b600190565b5050600090565b634e487b7160e01b600052603160045260246000fd5b61362791613621610f74565b91613529565b565b613632816134d2565b801561365357600190039061365061364a83836134d6565b90613615565b55565b6135ff565b919061366e6136696136769361169b565b6116b7565b908354613503565b9055565b61368c91613686612047565b91613658565b565b613696610bac565b506136ad6136a8600183018490613580565b6110cc565b90816136c26136bc600061164e565b9161025f565b14156000146137905761374292600161373d92846136eb6000966136e58561322f565b9061217d565b6137086136f9888501612f88565b6137028661322f565b9061217d565b8061371b6137158461025f565b9161025f565b03613747575b5050506137376137328683016134c4565b613629565b01613580565b61367a565b600190565b6137889261377a613766613760613783948c8901612f97565b90612fdc565b9361377485918c8901612f97565b90613529565b91858501613580565b6116ba565b388080613721565b505050600090565b906137b892916137a661141a565b50906137b2600061164e565b9161390d565b90565b6137c3610f74565b50806137d76137d1846103cd565b916103cd565b106000146137ed57906137e991613967565b5b90565b6137f691613967565b6137ea565b613803610bac565b5061381d6138176301ffc9a760e01b610178565b91610178565b1490565b61383f91600161383a92613833610bac565b5001613580565b6110cc565b61385261384c600061164e565b9161025f565b141590565b61386090610c70565b90565b60207f722063616c6c0000000000000000000000000000000000000000000000000000917f416464726573733a20696e73756666696369656e742062616c616e636520666f60008201520152565b6138be6026604092611244565b6138c781613863565b0190565b6138e190602081019060008183039101526138b1565b90565b156138eb57565b6138f3610163565b62461bcd60e51b815280613909600482016138cb565b0390fd5b9160008091613964959361391f61141a565b5061394661392c30613857565b3161393f6139398561025f565b9161025f565b10156138e4565b8591602082019151925af19161395a61141f565b9092909192613a02565b90565b61396f610f74565b50600052602052604060002090565b60007f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000910152565b6139b3601d602092611244565b6139bc8161397e565b0190565b6139d690602081019060008183039101526139a6565b90565b156139e057565b6139e8610163565b62461bcd60e51b8152806139fe600482016139c0565b0390fd5b919290613a0d61141a565b50600014613a535750613a1f82611f1e565b613a32613a2c600061164e565b9161025f565b14613a3c575b5090565b613a48613a4d91613aa7565b6139d9565b38613a38565b8290613a5e82611f1e565b613a71613a6b600061164e565b9161025f565b11600014613a825750805190602001fd5b613aa390613a8e610163565b91829162461bcd60e51b835260048301612acb565b0390fd5b613aaf610bac565b503b613ac4613abe600061164e565b9161025f565b119056fea2646970667358221220c204633b23276edd95aa322dbea2171da8b640438f81199e08fb87ec1d64aa7f64736f6c634300081b0033
AccessControl.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ```solidity * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ```solidity * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `_msgSender()` is missing `role`. * Overriding this function changes the behavior of the {onlyRole} modifier. * * Format of the revert message is described in {_checkRole}. * * _Available since v4.6._ */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(account), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * May emit a {RoleGranted} event. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
AccessControlEnumerable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) pragma solidity ^0.8.0; import "./IAccessControlEnumerable.sol"; import "./AccessControl.sol"; import "../utils/structs/EnumerableSet.sol"; /** * @dev Extension of {AccessControl} that allows enumerating the members of each role. */ abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { using EnumerableSet for EnumerableSet.AddressSet; mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { return _roleMembers[role].at(index); } /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { return _roleMembers[role].length(); } /** * @dev Overload {_grantRole} to track enumerable memberships */ function _grantRole(bytes32 role, address account) internal virtual override { super._grantRole(role, account); _roleMembers[role].add(account); } /** * @dev Overload {_revokeRole} to track enumerable memberships */ function _revokeRole(bytes32 role, address account) internal virtual override { super._revokeRole(role, account); _roleMembers[role].remove(account); } }
IAccessControl.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
IAccessControlEnumerable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; /** * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. */ interface IAccessControlEnumerable is IAccessControl { /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) external view returns (address); /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) external view returns (uint256); }
Ownable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(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"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
IERC1967.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.0; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. * * _Available since v4.8.3._ */ interface IERC1967 { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
draft-IERC1822.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
ERC1967Upgrade.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeacon.sol"; import "../../interfaces/IERC1967.sol"; import "../../interfaces/draft-IERC1822.sol"; import "../../utils/Address.sol"; import "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ */ abstract contract ERC1967Upgrade is IERC1967 { // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { Address.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } } }
Proxy.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol) pragma solidity ^0.8.0; /** * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to * be specified by overriding the virtual {_implementation} function. * * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a * different contract through the {_delegate} function. * * The success and return data of the delegated call will be returned back to the caller of the proxy. */ abstract contract Proxy { /** * @dev Delegates the current call to `implementation`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _delegate(address implementation) internal virtual { assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /** * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function * and {_fallback} should delegate. */ function _implementation() internal view virtual returns (address); /** * @dev Delegates the current call to the address returned by `_implementation()`. * * This function does not return to its internal call site, it will return directly to the external caller. */ function _fallback() internal virtual { _beforeFallback(); _delegate(_implementation()); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other * function in the contract matches the call data. */ fallback() external payable virtual { _fallback(); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data * is empty. */ receive() external payable virtual { _fallback(); } /** * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback` * call, or as part of the Solidity `fallback` or `receive` functions. * * If overridden should call `super._beforeFallback()`. */ function _beforeFallback() internal virtual {} }
IBeacon.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
UpgradeableBeacon.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol) pragma solidity ^0.8.0; import "./IBeacon.sol"; import "../../access/Ownable.sol"; import "../../utils/Address.sol"; /** * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their * implementation contract, which is where they will delegate all function calls. * * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon. */ contract UpgradeableBeacon is IBeacon, Ownable { address private _implementation; /** * @dev Emitted when the implementation returned by the beacon is changed. */ event Upgraded(address indexed implementation); /** * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the * beacon. */ constructor(address implementation_) { _setImplementation(implementation_); } /** * @dev Returns the current implementation address. */ function implementation() public view virtual override returns (address) { return _implementation; } /** * @dev Upgrades the beacon to a new implementation. * * Emits an {Upgraded} event. * * Requirements: * * - msg.sender must be the owner of the contract. * - `newImplementation` must be a contract. */ function upgradeTo(address newImplementation) public virtual onlyOwner { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Sets the implementation contract address for this beacon * * Requirements: * * - `newImplementation` must be a contract. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "UpgradeableBeacon: implementation is not a contract"); _implementation = newImplementation; } }
IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
IERC20Permit.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
SafeERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
Address.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 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://consensys.net/diligence/blog/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.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
Context.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
Create2.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Create2.sol) pragma solidity ^0.8.0; /** * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer. * `CREATE2` can be used to compute in advance the address where a smart * contract will be deployed, which allows for interesting new mechanisms known * as 'counterfactual interactions'. * * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more * information. */ library Create2 { /** * @dev Deploys a contract using `CREATE2`. The address where the contract * will be deployed can be known in advance via {computeAddress}. * * The bytecode for a contract can be obtained from Solidity with * `type(contractName).creationCode`. * * Requirements: * * - `bytecode` must not be empty. * - `salt` must have not been used for `bytecode` already. * - the factory must have a balance of at least `amount`. * - if `amount` is non-zero, `bytecode` must have a `payable` constructor. */ function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) { require(address(this).balance >= amount, "Create2: insufficient balance"); require(bytecode.length != 0, "Create2: bytecode length is zero"); /// @solidity memory-safe-assembly assembly { addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt) } require(addr != address(0), "Create2: Failed on deploy"); } /** * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the * `bytecodeHash` or `salt` will result in a new destination address. */ function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) { return computeAddress(salt, bytecodeHash, address(this)); } /** * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}. */ function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) // Get free memory pointer // | | ↓ ptr ... ↓ ptr + 0x0B (start) ... ↓ ptr + 0x20 ... ↓ ptr + 0x40 ... | // |-------------------|---------------------------------------------------------------------------| // | bytecodeHash | CCCCCCCCCCCCC...CC | // | salt | BBBBBBBBBBBBB...BB | // | deployer | 000000...0000AAAAAAAAAAAAAAAAAAA...AA | // | 0xFF | FF | // |-------------------|---------------------------------------------------------------------------| // | memory | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC | // | keccak(start, 85) | ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ | mstore(add(ptr, 0x40), bytecodeHash) mstore(add(ptr, 0x20), salt) mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff mstore8(start, 0xff) addr := keccak256(start, 85) } } }
StorageSlot.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
Strings.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @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] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
MerkleProof.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.2) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Tree proofs. * * The tree and the proofs can be generated using our * https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. * You will find a quickstart guide in the readme. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the merkle tree could be reinterpreted as a leaf value. * OpenZeppelin's JavaScript library generates merkle trees that are safe * against this attack out of the box. */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Calldata version of {verify} * * _Available since v4.7._ */ function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Calldata version of {processProof} * * _Available since v4.7._ */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Calldata version of {multiProofVerify} * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false * respectively. * * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). * * _Available since v4.7._ */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 proofLen = proof.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { require(proofPos == proofLen, "MerkleProof: invalid multiproof"); unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Calldata version of {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 proofLen = proof.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { require(proofPos == proofLen, "MerkleProof: invalid multiproof"); unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } }
ERC165.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
IERC165.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) 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); }
Math.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
SignedMath.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
EnumerableSet.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. 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. * * ```solidity * 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. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ 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; if (lastIndex != toDeleteIndex) { 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) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // 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); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // 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)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // 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 in 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)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
Attestation.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.27; import { LibBytes } from "../../../utils/LibBytes.sol"; import { ACCEPT_IMPLICIT_REQUEST_MAGIC_PREFIX } from "./ISignalsImplicitMode.sol"; using LibBytes for bytes; /// @notice Attestation for a specific session /// @param approvedSigner Address of the approved signer /// @param identityType Identity type /// @param issuerHash Hash of the issuer /// @param audienceHash Hash of the audience /// @param applicationData Unspecified application data /// @param authData Auth data struct Attestation { address approvedSigner; bytes4 identityType; bytes32 issuerHash; bytes32 audienceHash; bytes applicationData; AuthData authData; } /// @notice Auth data for an attestation /// @param redirectUrl Authorization redirect URL /// @param issuedAt Timestamp of the attestation issuance struct AuthData { string redirectUrl; uint64 issuedAt; } /// @title LibAttestation /// @author Michael Standen /// @notice Library for attestation management library LibAttestation { /// @notice Hashes an attestation function toHash( Attestation memory attestation ) internal pure returns (bytes32) { return keccak256(toPacked(attestation)); } /// @notice Decodes an attestation from a packed bytes array /// @param encoded The packed bytes array /// @param pointer The pointer to the start of the attestation /// @return attestation The decoded attestation /// @return newPointer The new pointer to the end of the attestation function fromPacked( bytes calldata encoded, uint256 pointer ) internal pure returns (Attestation memory attestation, uint256 newPointer) { newPointer = pointer; (attestation.approvedSigner, newPointer) = encoded.readAddress(newPointer); (attestation.identityType, newPointer) = encoded.readBytes4(newPointer); (attestation.issuerHash, newPointer) = encoded.readBytes32(newPointer); (attestation.audienceHash, newPointer) = encoded.readBytes32(newPointer); // Application data (arbitrary bytes) uint256 dataSize; (dataSize, newPointer) = encoded.readUint24(newPointer); attestation.applicationData = encoded[newPointer:newPointer + dataSize]; newPointer += dataSize; // Auth data (attestation.authData, newPointer) = fromPackedAuthData(encoded, newPointer); return (attestation, newPointer); } /// @notice Decodes the auth data from a packed bytes /// @param encoded The packed bytes containing the auth data /// @param pointer The pointer to the start of the auth data within the encoded data /// @return authData The decoded auth data /// @return newPointer The pointer to the end of the auth data within the encoded data function fromPackedAuthData( bytes calldata encoded, uint256 pointer ) internal pure returns (AuthData memory authData, uint256 newPointer) { uint24 redirectUrlLength; (redirectUrlLength, pointer) = encoded.readUint24(pointer); authData.redirectUrl = string(encoded[pointer:pointer + redirectUrlLength]); pointer += redirectUrlLength; (authData.issuedAt, pointer) = encoded.readUint64(pointer); return (authData, pointer); } /// @notice Encodes an attestation into a packed bytes array /// @param attestation The attestation to encode /// @return encoded The packed bytes array function toPacked( Attestation memory attestation ) internal pure returns (bytes memory encoded) { return abi.encodePacked( attestation.approvedSigner, attestation.identityType, attestation.issuerHash, attestation.audienceHash, uint24(attestation.applicationData.length), attestation.applicationData, toPackAuthData(attestation.authData) ); } /// @notice Encodes the auth data into a packed bytes array /// @param authData The auth data to encode /// @return encoded The packed bytes array function toPackAuthData( AuthData memory authData ) internal pure returns (bytes memory encoded) { return abi.encodePacked(uint24(bytes(authData.redirectUrl).length), bytes(authData.redirectUrl), authData.issuedAt); } /// @notice Generates the implicit request magic return value /// @param attestation The attestation /// @param wallet The wallet /// @return magic The expected implicit request magic function generateImplicitRequestMagic(Attestation memory attestation, address wallet) internal pure returns (bytes32) { return keccak256( abi.encodePacked(ACCEPT_IMPLICIT_REQUEST_MAGIC_PREFIX, wallet, attestation.audienceHash, attestation.issuerHash) ); } }
ISignalsImplicitMode.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.27; import { Payload } from "../../../modules/Payload.sol"; import { Attestation } from "./Attestation.sol"; /// @dev Magic prefix for the implicit request bytes32 constant ACCEPT_IMPLICIT_REQUEST_MAGIC_PREFIX = keccak256(abi.encodePacked("acceptImplicitRequest")); /// @title ISignalsImplicitMode /// @author Agustin Aguilar, Michael Standen /// @notice Interface for the contracts that support implicit mode validation interface ISignalsImplicitMode { /// @notice Determines if an implicit request is valid /// @param wallet The wallet's address /// @param attestation The attestation data /// @param call The call to validate /// @return magic The hash of the implicit request if valid function acceptImplicitRequest( address wallet, Attestation calldata attestation, Payload.Call calldata call ) external view returns (bytes32 magic); }
Payload.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.27; import { LibBytes } from "../utils/LibBytes.sol"; using LibBytes for bytes; /// @title Payload /// @author Agustin Aguilar, Michael Standen, William Hua /// @notice Library for encoding and decoding payloads library Payload { /// @notice Error thrown when the kind is invalid error InvalidKind(uint8 kind); /// @dev keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)") bytes32 private constant EIP712_DOMAIN_TYPEHASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f; /// @dev keccak256("Sequence Wallet") bytes32 private constant EIP712_DOMAIN_NAME_SEQUENCE = 0x4aa45ca7ad825ceb1bf35643f0a58c295239df563b1b565c2485f96477c56318; /// @dev keccak256("3") bytes32 private constant EIP712_DOMAIN_VERSION_SEQUENCE = 0x2a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de; function domainSeparator(bool _noChainId, address _wallet) internal view returns (bytes32 _domainSeparator) { return keccak256( abi.encode( EIP712_DOMAIN_TYPEHASH, EIP712_DOMAIN_NAME_SEQUENCE, EIP712_DOMAIN_VERSION_SEQUENCE, _noChainId ? uint256(0) : uint256(block.chainid), _wallet ) ); } /// @dev keccak256("Call(address to,uint256 value,bytes data,uint256 gasLimit,bool delegateCall,bool onlyFallback,uint256 behaviorOnError)") bytes32 private constant CALL_TYPEHASH = 0x0603985259a953da1f65a522f589c17bd1d0117ec1d3abb7c0788aef251ef437; /// @dev keccak256("Calls(Call[] calls,uint256 space,uint256 nonce,address[] wallets)Call(address to,uint256 value,bytes data,uint256 gasLimit,bool delegateCall,bool onlyFallback,uint256 behaviorOnError)") bytes32 private constant CALLS_TYPEHASH = 0x11e1e4079a79a66e4ade50033cfe2678cdd5341d2dfe5ef9513edb1a0be147a2; /// @dev keccak256("Message(bytes message,address[] wallets)") bytes32 private constant MESSAGE_TYPEHASH = 0xe19a3b94fc3c7ece3f890d98a99bc422615537a08dea0603fa8425867d87d466; /// @dev keccak256("ConfigUpdate(bytes32 imageHash,address[] wallets)") bytes32 private constant CONFIG_UPDATE_TYPEHASH = 0x11fdeb7e8373a1aa96bfac8d0ea91526b2c5d15e5cee20e0543e780258f3e8e4; /// @notice Kind of transaction uint8 public constant KIND_TRANSACTIONS = 0x00; /// @notice Kind of digest uint8 public constant KIND_MESSAGE = 0x01; /// @notice Kind of config update uint8 public constant KIND_CONFIG_UPDATE = 0x02; /// @notice Kind of message uint8 public constant KIND_DIGEST = 0x03; /// @notice Behavior on error: ignore error uint8 public constant BEHAVIOR_IGNORE_ERROR = 0x00; /// @notice Behavior on error: revert on error uint8 public constant BEHAVIOR_REVERT_ON_ERROR = 0x01; /// @notice Behavior on error: abort on error uint8 public constant BEHAVIOR_ABORT_ON_ERROR = 0x02; /// @notice Payload call information /// @param to Address of the target contract /// @param value Value to send with the call /// @param data Data to send with the call /// @param gasLimit Gas limit for the call /// @param delegateCall If the call is a delegate call /// @param onlyFallback If the call should only be executed in an error scenario /// @param behaviorOnError Behavior on error struct Call { address to; uint256 value; bytes data; uint256 gasLimit; bool delegateCall; bool onlyFallback; uint256 behaviorOnError; } /// @notice Decoded payload /// @param kind Kind of payload /// @param noChainId If the chain ID should be omitted /// @param calls Array of calls (transaction kind) /// @param space Nonce space for the calls (transaction kind) /// @param nonce Nonce value for the calls (transaction kind) /// @param message Message to validate (message kind) /// @param imageHash Image hash to update to (config update kind) /// @param digest Digest to validate (digest kind) /// @param parentWallets Parent wallets struct Decoded { uint8 kind; bool noChainId; // Transaction kind Call[] calls; uint256 space; uint256 nonce; // Message kind // TODO: Maybe native 721 ? bytes message; // Config update kind bytes32 imageHash; // Digest kind for 1271 bytes32 digest; // Parent wallets address[] parentWallets; } function fromMessage( bytes memory message ) internal pure returns (Decoded memory _decoded) { _decoded.kind = KIND_MESSAGE; _decoded.message = message; } function fromConfigUpdate( bytes32 imageHash ) internal pure returns (Decoded memory _decoded) { _decoded.kind = KIND_CONFIG_UPDATE; _decoded.imageHash = imageHash; } function fromDigest( bytes32 digest ) internal pure returns (Decoded memory _decoded) { _decoded.kind = KIND_DIGEST; _decoded.digest = digest; } function fromPackedCalls( bytes calldata packed ) internal view returns (Decoded memory _decoded) { _decoded.kind = KIND_TRANSACTIONS; // Read the global flag (uint256 globalFlag, uint256 pointer) = packed.readFirstUint8(); // First bit determines if space is zero or not if (globalFlag & 0x01 == 0x01) { _decoded.space = 0; } else { (_decoded.space, pointer) = packed.readUint160(pointer); } // Next 3 bits determine the size of the nonce uint256 nonceSize = (globalFlag >> 1) & 0x07; if (nonceSize > 0) { // Read the nonce (_decoded.nonce, pointer) = packed.readUintX(pointer, nonceSize); } uint256 numCalls; // Bit 5 determines if the batch contains a single call if (globalFlag & 0x10 == 0x10) { numCalls = 1; } else { // Bit 6 determines if the number of calls uses 1 byte or 2 bytes if (globalFlag & 0x20 == 0x20) { (numCalls, pointer) = packed.readUint16(pointer); } else { (numCalls, pointer) = packed.readUint8(pointer); } } // Read the calls _decoded.calls = new Call[](numCalls); for (uint256 i = 0; i < numCalls; i++) { uint8 flags; (flags, pointer) = packed.readUint8(pointer); // First bit determines if this is a call to self // or a call to another address if (flags & 0x01 == 0x01) { // Call to self _decoded.calls[i].to = address(this); } else { // Call to another address (_decoded.calls[i].to, pointer) = packed.readAddress(pointer); } // Second bit determines if the call has value or not if (flags & 0x02 == 0x02) { (_decoded.calls[i].value, pointer) = packed.readUint256(pointer); } // Third bit determines if the call has data or not if (flags & 0x04 == 0x04) { // 3 bytes determine the size of the calldata uint256 calldataSize; (calldataSize, pointer) = packed.readUint24(pointer); _decoded.calls[i].data = packed[pointer:pointer + calldataSize]; pointer += calldataSize; } // Fourth bit determines if the call has a gas limit or not if (flags & 0x08 == 0x08) { (_decoded.calls[i].gasLimit, pointer) = packed.readUint256(pointer); } // Fifth bit determines if the call is a delegate call or not _decoded.calls[i].delegateCall = (flags & 0x10 == 0x10); // Sixth bit determines if the call is fallback only _decoded.calls[i].onlyFallback = (flags & 0x20 == 0x20); // Last 2 bits are directly mapped to the behavior on error _decoded.calls[i].behaviorOnError = (flags & 0xC0) >> 6; } } function hashCall( Call memory c ) internal pure returns (bytes32) { return keccak256( abi.encode( CALL_TYPEHASH, c.to, c.value, keccak256(c.data), c.gasLimit, c.delegateCall, c.onlyFallback, c.behaviorOnError ) ); } function hashCalls( Call[] memory calls ) internal pure returns (bytes32) { // In EIP712, an array is often hashed as the keccak256 of the concatenated // hashes of each item. So we hash each Call, pack them, and hash again. bytes32[] memory callHashes = new bytes32[](calls.length); for (uint256 i = 0; i < calls.length; i++) { callHashes[i] = hashCall(calls[i]); } return keccak256(abi.encodePacked(callHashes)); } function toEIP712( Decoded memory _decoded ) internal pure returns (bytes32) { bytes32 walletsHash = keccak256(abi.encodePacked(_decoded.parentWallets)); if (_decoded.kind == KIND_TRANSACTIONS) { bytes32 callsHash = hashCalls(_decoded.calls); // The top-level struct for Calls might be something like: // Calls(bytes32 callsHash,uint256 space,uint256 nonce,bytes32 walletsHash) return keccak256(abi.encode(CALLS_TYPEHASH, callsHash, _decoded.space, _decoded.nonce, walletsHash)); } else if (_decoded.kind == KIND_MESSAGE) { // If you define your top-level as: Message(bytes32 messageHash,bytes32 walletsHash) return keccak256(abi.encode(MESSAGE_TYPEHASH, keccak256(_decoded.message), walletsHash)); } else if (_decoded.kind == KIND_CONFIG_UPDATE) { // Top-level: ConfigUpdate(bytes32 imageHash,bytes32 walletsHash) return keccak256(abi.encode(CONFIG_UPDATE_TYPEHASH, _decoded.imageHash, walletsHash)); } else if (_decoded.kind == KIND_DIGEST) { // Top-level: Use MESSAGE_TYPEHASH but assume the digest is already the hashed message return keccak256(abi.encode(MESSAGE_TYPEHASH, _decoded.digest, walletsHash)); } else { // Unknown kind revert InvalidKind(_decoded.kind); } } function hash( Decoded memory _decoded ) internal view returns (bytes32) { bytes32 domain = domainSeparator(_decoded.noChainId, address(this)); bytes32 structHash = toEIP712(_decoded); return keccak256(abi.encodePacked("\x19\x01", domain, structHash)); } function hashFor(Decoded memory _decoded, address _wallet) internal view returns (bytes32) { bytes32 domain = domainSeparator(_decoded.noChainId, _wallet); bytes32 structHash = toEIP712(_decoded); return keccak256(abi.encodePacked("\x19\x01", domain, structHash)); } }
LibBytes.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.18; /// @title Library for reading data from bytes arrays /// @author Agustin Aguilar (aa@horizon.io), Michael Standen (mstan@horizon.io) /// @notice This library contains functions for reading data from bytes arrays. /// @dev These functions do not check if the input index is within the bounds of the data array. /// @dev Reading out of bounds may return dirty values. library LibBytes { function readFirstUint8( bytes calldata _data ) internal pure returns (uint8 a, uint256 newPointer) { assembly { let word := calldataload(_data.offset) a := shr(248, word) newPointer := 1 } } function readUint8(bytes calldata _data, uint256 _index) internal pure returns (uint8 a, uint256 newPointer) { assembly { let word := calldataload(add(_index, _data.offset)) a := shr(248, word) newPointer := add(_index, 1) } } function readUint16(bytes calldata _data, uint256 _index) internal pure returns (uint16 a, uint256 newPointer) { assembly { let word := calldataload(add(_index, _data.offset)) a := shr(240, word) newPointer := add(_index, 2) } } function readUint24(bytes calldata _data, uint256 _index) internal pure returns (uint24 a, uint256 newPointer) { assembly { let word := calldataload(add(_index, _data.offset)) a := shr(232, word) newPointer := add(_index, 3) } } function readUint64(bytes calldata _data, uint256 _index) internal pure returns (uint64 a, uint256 newPointer) { assembly { let word := calldataload(add(_index, _data.offset)) a := shr(192, word) newPointer := add(_index, 8) } } function readUint160(bytes calldata _data, uint256 _index) internal pure returns (uint160 a, uint256 newPointer) { assembly { let word := calldataload(add(_index, _data.offset)) a := shr(96, word) newPointer := add(_index, 20) } } function readUint256(bytes calldata _data, uint256 _index) internal pure returns (uint256 a, uint256 newPointer) { assembly { a := calldataload(add(_index, _data.offset)) newPointer := add(_index, 32) } } function readUintX( bytes calldata _data, uint256 _index, uint256 _length ) internal pure returns (uint256 a, uint256 newPointer) { assembly { let word := calldataload(add(_index, _data.offset)) let shift := sub(256, mul(_length, 8)) a := and(shr(shift, word), sub(shl(mul(8, _length), 1), 1)) newPointer := add(_index, _length) } } function readBytes4(bytes calldata _data, uint256 _pointer) internal pure returns (bytes4 a, uint256 newPointer) { assembly { let word := calldataload(add(_pointer, _data.offset)) a := and(word, 0xffffffff00000000000000000000000000000000000000000000000000000000) newPointer := add(_pointer, 4) } } function readBytes32(bytes calldata _data, uint256 _pointer) internal pure returns (bytes32 a, uint256 newPointer) { assembly { a := calldataload(add(_pointer, _data.offset)) newPointer := add(_pointer, 32) } } function readAddress(bytes calldata _data, uint256 _index) internal pure returns (address a, uint256 newPointer) { assembly { let word := calldataload(add(_index, _data.offset)) a := and(shr(96, word), 0xffffffffffffffffffffffffffffffffffffffff) newPointer := add(_index, 20) } } /// @dev ERC-2098 Compact Signature function readRSVCompact( bytes calldata _data, uint256 _index ) internal pure returns (bytes32 r, bytes32 s, uint8 v, uint256 newPointer) { uint256 yParityAndS; assembly { r := calldataload(add(_index, _data.offset)) yParityAndS := calldataload(add(_index, add(_data.offset, 32))) newPointer := add(_index, 64) } uint256 yParity = uint256(yParityAndS >> 255); s = bytes32(uint256(yParityAndS) & ((1 << 255) - 1)); v = uint8(yParity) + 27; } }
SignalsImplicitMode.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.13; import { IImplicitProjectValidation } from "../registry/IImplicitProjectValidation.sol"; import { ERC165, IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/ERC165.sol"; import { Attestation } from "sequence-v3/src/extensions/sessions/implicit/Attestation.sol"; import { ISignalsImplicitMode } from "sequence-v3/src/extensions/sessions/implicit/ISignalsImplicitMode.sol"; import { Payload } from "sequence-v3/src/modules/Payload.sol"; /// @title SignalsImplicitMode /// @author Michael Standen /// @notice Base contract for implicit mode validation by project abstract contract SignalsImplicitMode is ISignalsImplicitMode, ERC165 { IImplicitProjectValidation internal _validator; bytes32 internal _projectId; /// @notice Initialize implicit mode validation /// @param validator The IImplicitProjectValidation address /// @param projectId The project id function _initializeSignalsImplicitMode(address validator, bytes32 projectId) internal { _validator = IImplicitProjectValidation(validator); _projectId = projectId; } /// @inheritdoc ISignalsImplicitMode function acceptImplicitRequest( address wallet, Attestation calldata attestation, Payload.Call calldata call ) external view returns (bytes32) { _validateImplicitRequest(wallet, attestation, call); return _validator.validateAttestation(wallet, attestation, _projectId); } /// @notice Validates an implicit request /// @dev Optional hook for additional validation of the implicit requests /// @param wallet The wallet's address /// @param attestation The attestation data /// @param call The call to validate function _validateImplicitRequest( address wallet, Attestation calldata attestation, Payload.Call calldata call ) internal view virtual { } /// @inheritdoc IERC165 function supportsInterface( bytes4 interfaceId ) public view virtual override returns (bool) { return interfaceId == type(ISignalsImplicitMode).interfaceId || super.supportsInterface(interfaceId); } }
IImplicitProjectValidation.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.13; import { Attestation } from "sequence-v3/src/extensions/sessions/implicit/Attestation.sol"; /// @title IImplicitProjectValidation /// @author Michael Standen /// @notice Interface for contracts supporting validation of implicit sessions for projects interface IImplicitProjectValidation { /// @notice Invalid redirect url error error InvalidRedirectUrl(); /// @notice Check if a project has a code /// @param wallet The wallet address /// @param attestation The attestation /// @param projectId The project id /// @return magic The attestation magic bytes for the wallet address function validateAttestation( address wallet, Attestation calldata attestation, bytes32 projectId ) external view returns (bytes32); }
SequenceProxyFactory.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.19; import { ITransparentUpgradeableBeaconProxy, TransparentUpgradeableBeaconProxy } from "./TransparentUpgradeableBeaconProxy.sol"; import { Ownable } from "openzeppelin-contracts/contracts/access/Ownable.sol"; import { UpgradeableBeacon } from "openzeppelin-contracts/contracts/proxy/beacon/UpgradeableBeacon.sol"; import { Create2 } from "openzeppelin-contracts/contracts/utils/Create2.sol"; /** * An proxy factory that deploys upgradeable beacon proxies. * @dev The factory owner is able to upgrade the beacon implementation. * @dev Proxy deployers are able to override the beacon reference with their own. */ abstract contract SequenceProxyFactory is Ownable { UpgradeableBeacon public beacon; /** * Initialize a Sequence Proxy Factory. * @param implementation The initial beacon implementation. * @param factoryOwner The owner of the factory. */ function _initialize(address implementation, address factoryOwner) internal { beacon = new UpgradeableBeacon(implementation); Ownable._transferOwnership(factoryOwner); } /** * Deploys and initializes a new proxy instance. * @param _salt The deployment salt. * @param _proxyOwner The owner of the proxy. * @param _data The initialization data. * @return proxyAddress The address of the deployed proxy. */ function _createProxy( bytes32 _salt, address _proxyOwner, bytes memory _data ) internal returns (address proxyAddress) { bytes32 saltedHash = keccak256(abi.encodePacked(_salt, _proxyOwner, address(beacon), _data)); bytes memory bytecode = type(TransparentUpgradeableBeaconProxy).creationCode; proxyAddress = Create2.deploy(0, saltedHash, bytecode); ITransparentUpgradeableBeaconProxy(payable(proxyAddress)).initialize(_proxyOwner, address(beacon), _data); } /** * Computes the address of a proxy instance. * @param _salt The deployment salt. * @param _proxyOwner The owner of the proxy. * @return proxy The expected address of the deployed proxy. */ function _computeProxyAddress( bytes32 _salt, address _proxyOwner, bytes memory _data ) internal view returns (address) { bytes32 saltedHash = keccak256(abi.encodePacked(_salt, _proxyOwner, address(beacon), _data)); bytes32 bytecodeHash = keccak256(type(TransparentUpgradeableBeaconProxy).creationCode); return Create2.computeAddress(saltedHash, bytecodeHash); } /** * Upgrades the beacon implementation. * @param implementation The new beacon implementation. */ function upgradeBeacon( address implementation ) public onlyOwner { beacon.upgradeTo(implementation); } }
TransparentUpgradeableBeaconProxy.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.19; import { BeaconProxy, Proxy } from "./openzeppelin/BeaconProxy.sol"; import { ERC1967Proxy, TransparentUpgradeableProxy } from "./openzeppelin/TransparentUpgradeableProxy.sol"; interface ITransparentUpgradeableBeaconProxy { function initialize(address admin, address beacon, bytes memory data) external; } error InvalidInitialization(); /** * @dev As the underlying proxy implementation (TransparentUpgradeableProxy) allows the admin to call the implementation, * care must be taken to avoid proxy selector collisions. Implementation selectors must not conflict with the proxy selectors. * See https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing]. * The proxy selectors are: * - 0xcf7a1d77: initialize * - 0x3659cfe6: upgradeTo (from TransparentUpgradeableProxy) * - 0x4f1ef286: upgradeToAndCall (from TransparentUpgradeableProxy) * - 0x8f283970: changeAdmin (from TransparentUpgradeableProxy) * - 0xf851a440: admin (from TransparentUpgradeableProxy) * - 0x5c60da1b: implementation (from TransparentUpgradeableProxy) */ contract TransparentUpgradeableBeaconProxy is TransparentUpgradeableProxy, BeaconProxy { /** * Decode the initialization data from the msg.data and call the initialize function. */ function _dispatchInitialize() private returns (bytes memory) { _requireZeroValue(); (address admin, address beacon, bytes memory data) = abi.decode(msg.data[4:], (address, address, bytes)); initialize(admin, beacon, data); return ""; } function initialize(address admin, address beacon, bytes memory data) internal { if (_admin() != address(0)) { // Redundant call. This function can only be called when the admin is not set. revert InvalidInitialization(); } _changeAdmin(admin); _upgradeBeaconToAndCall(beacon, data, false); } /** * @dev If the admin is not set, the fallback function is used to initialize the proxy. * @dev If the admin is set, the fallback function is used to delegatecall the implementation. */ function _fallback() internal override(TransparentUpgradeableProxy, Proxy) { if (_getAdmin() == address(0)) { bytes memory ret; bytes4 selector = msg.sig; if (selector == ITransparentUpgradeableBeaconProxy.initialize.selector) { ret = _dispatchInitialize(); // solhint-disable-next-line no-inline-assembly assembly { return(add(ret, 0x20), mload(ret)) } } // When the admin is not set, the fallback function is used to initialize the proxy. revert InvalidInitialization(); } TransparentUpgradeableProxy._fallback(); } /** * Returns the current implementation address. * @dev This is the implementation address set by the admin, or the beacon implementation. */ function _implementation() internal view override(ERC1967Proxy, BeaconProxy) returns (address) { address implementation = ERC1967Proxy._implementation(); if (implementation != address(0)) { return implementation; } return BeaconProxy._implementation(); } }
BeaconProxy.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/beacon/BeaconProxy.sol) // Note: This implementation is an exact copy with the constructor removed, and pragma and imports updated. pragma solidity ^0.8.19; import "openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Upgrade.sol"; import "openzeppelin-contracts/contracts/proxy/Proxy.sol"; import "openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol"; /** * @dev This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}. * * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't * conflict with the storage layout of the implementation behind the proxy. * * _Available since v3.4._ */ contract BeaconProxy is Proxy, ERC1967Upgrade { /** * @dev Returns the current beacon address. */ function _beacon() internal view virtual returns (address) { return _getBeacon(); } /** * @dev Returns the current implementation address of the associated beacon. */ function _implementation() internal view virtual override returns (address) { return IBeacon(_getBeacon()).implementation(); } /** * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}. * * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. * * Requirements: * * - `beacon` must be a contract. * - The implementation returned by `beacon` must be a contract. */ function _setBeacon(address beacon, bytes memory data) internal virtual { _upgradeBeaconToAndCall(beacon, data, false); } }
ERC1967Proxy.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol) // Note: This implementation is an exact copy with the constructor removed, and pragma and imports updated. pragma solidity ^0.8.19; import "openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Upgrade.sol"; import "openzeppelin-contracts/contracts/proxy/Proxy.sol"; /** * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an * implementation address that can be changed. This address is stored in storage in the location specified by * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the * implementation behind the proxy. */ contract ERC1967Proxy is Proxy, ERC1967Upgrade { /** * @dev Returns the current implementation address. */ function _implementation() internal view virtual override returns (address impl) { return ERC1967Upgrade._getImplementation(); } }
TransparentUpgradeableProxy.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/transparent/TransparentUpgradeableProxy.sol) /// @notice This implementation is a copy of OpenZeppelin's with the following changes: /// - Pragma updated /// - Imports updated /// - Constructor removed /// - Allows admin to call implementation pragma solidity ^0.8.19; import "./ERC1967Proxy.sol"; /** * @dev Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy} * does not implement this interface directly, and some of its functions are implemented by an internal dispatch * mechanism. The compiler is unaware that these functions are implemented by {TransparentUpgradeableProxy} and will not * include them in the ABI so this interface must be used to interact with it. */ interface ITransparentUpgradeableProxy is IERC1967 { function admin() external view returns (address); function implementation() external view returns (address); function changeAdmin( address ) external; function upgradeTo( address ) external; function upgradeToAndCall(address, bytes memory) external payable; } /** * @dev This contract implements a proxy that is upgradeable by an admin. * * Unlike the original OpenZeppelin implementation, this contract does not prevent the admin from calling the implementation. * This potentially exposes the admin to a proxy selector attack. See * https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing]. * When using this contract, you must ensure that the implementation function selectors do not clash with the proxy selectors. * The proxy selectors are: * - 0x3659cfe6: upgradeTo * - 0x4f1ef286: upgradeToAndCall * - 0x8f283970: changeAdmin * - 0xf851a440: admin * - 0x5c60da1b: implementation * * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not * inherit from that interface, and instead the admin functions are implicitly implemented using a custom dispatch * mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to * fully implement transparency without decoding reverts caused by selector clashes between the proxy and the * implementation. * * WARNING: It is not recommended to extend this contract to add additional external functions. If you do so, the compiler * will not check that there are no selector conflicts, due to the note above. A selector clash between any new function * and the functions declared in {ITransparentUpgradeableProxy} will be resolved in favor of the new one. This could * render the admin operations inaccessible, which could prevent upgradeability. Transparency may also be compromised. */ contract TransparentUpgradeableProxy is ERC1967Proxy { /** * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin. * * CAUTION: This modifier is deprecated, as it could cause issues if the modified function has arguments, and the * implementation provides a function with the same selector. */ modifier ifAdmin() { if (msg.sender == _getAdmin()) { _; } else { _fallback(); } } /** * @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior */ function _fallback() internal virtual override { if (msg.sender == _getAdmin()) { bytes memory ret; bytes4 selector = msg.sig; if (selector == ITransparentUpgradeableProxy.upgradeTo.selector) { ret = _dispatchUpgradeTo(); } else if (selector == ITransparentUpgradeableProxy.upgradeToAndCall.selector) { ret = _dispatchUpgradeToAndCall(); } else if (selector == ITransparentUpgradeableProxy.changeAdmin.selector) { ret = _dispatchChangeAdmin(); } else if (selector == ITransparentUpgradeableProxy.admin.selector) { ret = _dispatchAdmin(); } else if (selector == ITransparentUpgradeableProxy.implementation.selector) { ret = _dispatchImplementation(); } else { // Call implementation return super._fallback(); } assembly { return(add(ret, 0x20), mload(ret)) } } else { super._fallback(); } } /** * @dev Returns the current admin. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function _dispatchAdmin() private returns (bytes memory) { _requireZeroValue(); address admin = _getAdmin(); return abi.encode(admin); } /** * @dev Returns the current implementation. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` */ function _dispatchImplementation() private returns (bytes memory) { _requireZeroValue(); address implementation = _implementation(); return abi.encode(implementation); } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _dispatchChangeAdmin() private returns (bytes memory) { _requireZeroValue(); address newAdmin = abi.decode(msg.data[4:], (address)); _changeAdmin(newAdmin); return ""; } /** * @dev Upgrade the implementation of the proxy. */ function _dispatchUpgradeTo() private returns (bytes memory) { _requireZeroValue(); address newImplementation = abi.decode(msg.data[4:], (address)); _upgradeToAndCall(newImplementation, bytes(""), false); return ""; } /** * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the * proxied contract. */ function _dispatchUpgradeToAndCall() private returns (bytes memory) { (address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes)); _upgradeToAndCall(newImplementation, data, true); return ""; } /** * @dev Returns the current admin. * * CAUTION: This function is deprecated. Use {ERC1967Upgrade-_getAdmin} instead. */ function _admin() internal view virtual returns (address) { return _getAdmin(); } /** * @dev To keep this contract fully transparent, all `ifAdmin` functions must be payable. This helper is here to * emulate some proxy functions being non-payable while still allowing value to pass through. */ function _requireZeroValue() internal { require(msg.value == 0); } }
IERC721Items.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.19; interface IERC721ItemsFunctions { /** * Mint tokens. * @param to Address to mint tokens to. * @param tokenId Token id to mint. */ function mint(address to, uint256 tokenId) external; /** * Mint a sequential token. * @param to Address to mint token to. * @param amount Amount of tokens to mint. */ function mintSequential(address to, uint256 amount) external; /** * Get the total supply of tokens. * @return totalSupply The total supply of tokens. */ function totalSupply() external view returns (uint256 totalSupply); } interface IERC721ItemsSignals { /** * Invalid initialization error. */ error InvalidInitialization(); } interface IERC721Items is IERC721ItemsFunctions, IERC721ItemsSignals { }
ERC721Sale.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.19; import { MerkleProofSingleUse } from "../../../common/MerkleProofSingleUse.sol"; import { SignalsImplicitModeControlled } from "../../../common/SignalsImplicitModeControlled.sol"; import { IERC20, SafeERC20, WithdrawControlled } from "../../../common/WithdrawControlled.sol"; import { IERC721ItemsFunctions } from "../../presets/items/IERC721Items.sol"; import { IERC721Sale, IERC721SaleFunctions } from "./IERC721Sale.sol"; /** * An ERC-721 token contract with primary sale mechanisms. */ contract ERC721Sale is IERC721Sale, WithdrawControlled, MerkleProofSingleUse, SignalsImplicitModeControlled { bytes32 internal constant MINT_ADMIN_ROLE = keccak256("MINT_ADMIN_ROLE"); bool private _initialized; address private _items; SaleDetails private _saleDetails; /** * Initialize the contract. * @param owner The owner of the contract * @param items The ERC-721 Items contract address * @param implicitModeValidator Implicit session validator address * @param implicitModeProjectId Implicit session project id * @dev This should be called immediately after deployment. */ function initialize( address owner, address items, address implicitModeValidator, bytes32 implicitModeProjectId ) public virtual { if (_initialized) { revert InvalidInitialization(); } _items = items; _grantRole(DEFAULT_ADMIN_ROLE, owner); _grantRole(MINT_ADMIN_ROLE, owner); _grantRole(WITHDRAW_ROLE, owner); _initializeImplicitMode(owner, implicitModeValidator, implicitModeProjectId); _initialized = true; } /** * Checks if the current block.timestamp is out of the give timestamp range. * @param _startTime Earliest acceptable timestamp (inclusive). * @param _endTime Latest acceptable timestamp (exclusive). * @dev A zero endTime value is always considered out of bounds. */ function _blockTimeOutOfBounds(uint256 _startTime, uint256 _endTime) private view returns (bool) { // 0 end time indicates inactive sale. return _endTime == 0 || block.timestamp < _startTime || block.timestamp >= _endTime; // solhint-disable-line not-rely-on-time } /** * Checks the sale is active, valid and takes payment. * @param _amount Amount of tokens to mint. * @param _expectedPaymentToken ERC20 token address to accept payment in. address(0) indicates ETH. * @param _maxTotal Maximum amount of payment tokens. * @param _proof Merkle proof for allowlist minting. */ function _validateMint( uint256 _amount, address _expectedPaymentToken, uint256 _maxTotal, bytes32[] calldata _proof ) private { // Active sale test if (_blockTimeOutOfBounds(_saleDetails.startTime, _saleDetails.endTime)) { revert SaleInactive(); } // Supply test if (_saleDetails.remainingSupply < _amount) { revert InsufficientSupply(_saleDetails.remainingSupply, _amount); } _saleDetails.remainingSupply -= _amount; // Check proof requireMerkleProof(_saleDetails.merkleRoot, _proof, msg.sender, ""); uint256 total = _saleDetails.cost * _amount; if (_expectedPaymentToken != _saleDetails.paymentToken) { // Caller expected different payment token revert InsufficientPayment(_saleDetails.paymentToken, total, 0); } if (_maxTotal < total) { // Caller expected to pay less revert InsufficientPayment(_expectedPaymentToken, total, _maxTotal); } if (_expectedPaymentToken == address(0)) { // Paid in ETH if (msg.value != total) { // We expect exact value match revert InsufficientPayment(_expectedPaymentToken, total, msg.value); } } else if (msg.value > 0) { // Paid in ERC20, but sent ETH revert InsufficientPayment(address(0), 0, msg.value); } else { // Paid in ERC20 SafeERC20.safeTransferFrom(IERC20(_expectedPaymentToken), msg.sender, address(this), total); } } // // Minting // /** * Mint tokens. * @param to Address to mint tokens to. * @param amount Amount of tokens to mint. * @param paymentToken ERC20 token address to accept payment in. address(0) indicates ETH. * @param maxTotal Maximum amount of payment tokens. * @param proof Merkle proof for allowlist minting. * @notice Sale must be active for all tokens. * @dev An empty proof is supplied when no proof is required. * @dev `paymentToken` must match the `paymentToken` in the sale details. */ function mint( address to, uint256 amount, address paymentToken, uint256 maxTotal, bytes32[] calldata proof ) public payable { _validateMint(amount, paymentToken, maxTotal, proof); try IERC721ItemsFunctions(_items).mintSequential(to, amount) { } catch { // On failure, support old minting method. IERC721ItemsFunctions(_items).mint(to, amount); } emit ItemsMinted(to, amount); } /** * Set the sale details. * @param remainingSupply The remaining number of tokens that can be minted by the items contract. 0 indicates unlimited supply. * @param cost The amount of payment tokens to accept for each token minted. * @param paymentToken The ERC20 token address to accept payment in. address(0) indicates ETH. * @param startTime The start time of the sale. Tokens cannot be minted before this time. * @param endTime The end time of the sale. Tokens cannot be minted after this time. * @param merkleRoot The merkle root for allowlist minting. * @dev A zero end time indicates an inactive sale. */ function setSaleDetails( uint256 remainingSupply, uint256 cost, address paymentToken, uint64 startTime, uint64 endTime, bytes32 merkleRoot ) public onlyRole(MINT_ADMIN_ROLE) { // solhint-disable-next-line not-rely-on-time if (endTime < startTime || endTime <= block.timestamp) { revert InvalidSaleDetails(); } if (remainingSupply == 0) { revert InvalidSaleDetails(); } _saleDetails = SaleDetails(remainingSupply, cost, paymentToken, startTime, endTime, merkleRoot); emit SaleDetailsUpdated(remainingSupply, cost, paymentToken, startTime, endTime, merkleRoot); } // // Views // function itemsContract() external view returns (address) { return address(_items); } /** * Get sale details. * @return Sale details. */ function saleDetails() external view returns (SaleDetails memory) { return _saleDetails; } /** * Check interface support. * @param interfaceId Interface id * @return True if supported */ function supportsInterface( bytes4 interfaceId ) public view virtual override(WithdrawControlled, SignalsImplicitModeControlled) returns (bool) { return interfaceId == type(IERC721SaleFunctions).interfaceId || WithdrawControlled.supportsInterface(interfaceId) || SignalsImplicitModeControlled.supportsInterface(interfaceId); } }
ERC721SaleFactory.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.19; import { SequenceProxyFactory } from "../../../../proxies/SequenceProxyFactory.sol"; import { ERC721Sale } from "./ERC721Sale.sol"; import { IERC721SaleFactory, IERC721SaleFactoryFunctions } from "./IERC721SaleFactory.sol"; /** * Deployer of ERC-721 Sale proxies. */ contract ERC721SaleFactory is IERC721SaleFactory, SequenceProxyFactory { /** * Creates an ERC-721 Sale Factory. * @param factoryOwner The owner of the ERC-721 Sale Factory */ constructor( address factoryOwner ) { ERC721Sale impl = new ERC721Sale(); SequenceProxyFactory._initialize(address(impl), factoryOwner); } /// @inheritdoc IERC721SaleFactoryFunctions function deploy( uint256 nonce, address proxyOwner, address tokenOwner, address items, address implicitModeValidator, bytes32 implicitModeProjectId ) external returns (address proxyAddr) { bytes32 salt = keccak256(abi.encode(nonce, tokenOwner, items, implicitModeValidator, implicitModeProjectId)); proxyAddr = _createProxy(salt, proxyOwner, ""); ERC721Sale(proxyAddr).initialize(tokenOwner, items, implicitModeValidator, implicitModeProjectId); emit ERC721SaleDeployed(proxyAddr); return proxyAddr; } /// @inheritdoc IERC721SaleFactoryFunctions function determineAddress( uint256 nonce, address proxyOwner, address tokenOwner, address items, address implicitModeValidator, bytes32 implicitModeProjectId ) external view returns (address proxyAddr) { bytes32 salt = keccak256(abi.encode(nonce, tokenOwner, items, implicitModeValidator, implicitModeProjectId)); return _computeProxyAddress(salt, proxyOwner, ""); } }
IERC721Sale.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.19; interface IERC721SaleFunctions { struct SaleDetails { uint256 remainingSupply; uint256 cost; address paymentToken; // ERC20 token address for payment. address(0) indicated payment in ETH. uint64 startTime; uint64 endTime; // 0 end time indicates sale inactive bytes32 merkleRoot; // Root of allowed addresses } /** * Mint tokens. * @param to Address to mint tokens to. * @param amount Amount of tokens to mint. * @param paymentToken ERC20 token address to accept payment in. address(0) indicates ETH. * @param maxTotal Maximum amount of payment tokens. * @param proof Merkle proof for allowlist minting. * @notice Sale must be active for all tokens. * @dev An empty proof is supplied when no proof is required. */ function mint( address to, uint256 amount, address paymentToken, uint256 maxTotal, bytes32[] memory proof ) external payable; /** * Set the sale details. * @param remainingSupply The maximum number of tokens that can be minted in this sale. * @param cost The amount of payment tokens to accept for each token minted. * @param paymentToken The ERC20 token address to accept payment in. address(0) indicates ETH. * @param startTime The start time of the sale. Tokens cannot be minted before this time. * @param endTime The end time of the sale. Tokens cannot be minted after this time. * @param merkleRoot The merkle root for allowlist minting. */ function setSaleDetails( uint256 remainingSupply, uint256 cost, address paymentToken, uint64 startTime, uint64 endTime, bytes32 merkleRoot ) external; /** * Get sale details. * @return Sale details. */ function saleDetails() external view returns (SaleDetails memory); } interface IERC721SaleSignals { event SaleDetailsUpdated( uint256 remainingSupply, uint256 cost, address paymentToken, uint64 startTime, uint64 endTime, bytes32 merkleRoot ); event ItemsMinted(address to, uint256 amount); /** * Contract already initialized. */ error InvalidInitialization(); /** * Sale details supplied are invalid. */ error InvalidSaleDetails(); /** * Sale is not active. */ error SaleInactive(); /** * Insufficient supply. * @param remainingSupply Remaining supply. * @param amount Amount to mint. */ error InsufficientSupply(uint256 remainingSupply, uint256 amount); /** * Insufficient tokens for payment. * @param currency Currency address. address(0) indicates ETH. * @param expected Expected amount of tokens. * @param actual Actual amount of tokens. */ error InsufficientPayment(address currency, uint256 expected, uint256 actual); } interface IERC721Sale is IERC721SaleFunctions, IERC721SaleSignals { }
IERC721SaleFactory.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.19; interface IERC721SaleFactoryFunctions { /** * Creates an ERC-721 Sale for given token contract * @param nonce Nonce for randomizing the deployment address. * @param proxyOwner The owner of the ERC-721 Sale proxy * @param tokenOwner The owner of the ERC-721 Sale implementation * @param items The ERC-721 Items contract address * @param implicitModeValidator The implicit mode validator address * @param implicitModeProjectId The implicit mode project id * @return proxyAddr The address of the ERC-721 Sale Proxy * @notice The deployed contract must be granted the MINTER_ROLE on the ERC-721 Items contract. */ function deploy( uint256 nonce, address proxyOwner, address tokenOwner, address items, address implicitModeValidator, bytes32 implicitModeProjectId ) external returns (address proxyAddr); /** * Computes the address of a proxy instance. * @param nonce Nonce for randomizing the deployment address. * @param proxyOwner The owner of the ERC-721 Sale proxy * @param tokenOwner The owner of the ERC-721 Sale implementation * @param items The ERC-721 Items contract address * @param implicitModeValidator The implicit mode validator address * @param implicitModeProjectId The implicit mode project id * @return proxyAddr The address of the ERC-721 Sale Proxy */ function determineAddress( uint256 nonce, address proxyOwner, address tokenOwner, address items, address implicitModeValidator, bytes32 implicitModeProjectId ) external returns (address proxyAddr); } interface IERC721SaleFactorySignals { /** * Event emitted when a new ERC-721 Sale proxy contract is deployed. * @param proxyAddr The address of the deployed proxy. */ event ERC721SaleDeployed(address proxyAddr); } interface IERC721SaleFactory is IERC721SaleFactoryFunctions, IERC721SaleFactorySignals { }
IMerkleProofSingleUse.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.19; interface IMerkleProofSingleUseFunctions { /** * Checks if the given merkle proof is valid. * @param root Merkle root. * @param proof Merkle proof. * @param addr Address to check. * @param salt Salt used to generate the merkle leaf. * @return True if the proof is valid and has not yet been used by {addr}. */ function checkMerkleProof( bytes32 root, bytes32[] calldata proof, address addr, bytes32 salt ) external view returns (bool); } interface IMerkleProofSingleUseSignals { /** * Thrown when the merkle proof is invalid or has already been used. * @param root Merkle root. * @param proof Merkle proof. * @param addr Address to check. * @param salt Salt used to generate the merkle leaf. */ error MerkleProofInvalid(bytes32 root, bytes32[] proof, address addr, bytes32 salt); } interface IMerkleProofSingleUse is IMerkleProofSingleUseFunctions, IMerkleProofSingleUseSignals { }
IWithdrawControlled.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.19; interface IWithdrawControlledFunctions { /** * Withdraws ERC20 tokens owned by this contract. * @param token The ERC20 token address. * @param to Address to withdraw to. * @param value Amount to withdraw. */ function withdrawERC20(address token, address to, uint256 value) external; /** * Withdraws ETH owned by this sale contract. * @param to Address to withdraw to. * @param value Amount to withdraw. */ function withdrawETH(address to, uint256 value) external; } interface IWithdrawControlledSignals { /** * Withdraw failed error. */ error WithdrawFailed(); } interface IWithdrawControlled is IWithdrawControlledFunctions, IWithdrawControlledSignals { }
MerkleProofSingleUse.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.19; import { IMerkleProofSingleUse } from "./IMerkleProofSingleUse.sol"; import { MerkleProof } from "openzeppelin-contracts/contracts/utils/cryptography/MerkleProof.sol"; /** * Require single use merkle proofs per address. */ abstract contract MerkleProofSingleUse is IMerkleProofSingleUse { // Stores proofs used by an address mapping(address => mapping(bytes32 => bool)) private _proofUsed; /** * Requires the given merkle proof to be valid. * @param root Merkle root. * @param proof Merkle proof. * @param addr Address to check. * @param salt Salt used to generate the merkle leaf. * @notice Fails when the proof is invalid or the proof has already been claimed by this address. * @dev This function reverts on failure. */ function requireMerkleProof(bytes32 root, bytes32[] calldata proof, address addr, bytes32 salt) internal { if (root != bytes32(0)) { if (!checkMerkleProof(root, proof, addr, salt)) { revert MerkleProofInvalid(root, proof, addr, salt); } _proofUsed[addr][root] = true; } } /** * Checks if the given merkle proof is valid. * @param root Merkle root. * @param proof Merkle proof. * @param addr Address to check. * @param salt Salt used to generate the merkle leaf. * @return True if the proof is valid and has not yet been used by {addr}. */ function checkMerkleProof( bytes32 root, bytes32[] calldata proof, address addr, bytes32 salt ) public view returns (bool) { return !_proofUsed[addr][root] && MerkleProof.verify(proof, root, keccak256(abi.encodePacked(addr, salt))); } }
SignalsImplicitModeControlled.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.19; import { AccessControlEnumerable } from "openzeppelin-contracts/contracts/access/AccessControlEnumerable.sol"; import { IERC165, IImplicitProjectValidation, SignalsImplicitMode } from "signals-implicit-mode/src/helper/SignalsImplicitMode.sol"; /** * An abstract contract that allows implicit session access for a given project. */ abstract contract SignalsImplicitModeControlled is AccessControlEnumerable, SignalsImplicitMode { bytes32 internal constant _IMPLICIT_MODE_ADMIN_ROLE = keccak256("IMPLICIT_MODE_ADMIN_ROLE"); function _initializeImplicitMode(address owner, address validator, bytes32 projectId) internal { _grantRole(_IMPLICIT_MODE_ADMIN_ROLE, owner); _initializeSignalsImplicitMode(validator, projectId); } /** * Updates the validator for implicit mode validation. * @param validator The validator address. * @notice Only callable by an address with the project admin role. */ function setImplicitModeValidator( address validator ) external onlyRole(_IMPLICIT_MODE_ADMIN_ROLE) { _validator = IImplicitProjectValidation(validator); } /** * Updates the settings for implicit mode validation. * @param projectId The project id. * @notice Only callable by an address with the project admin role. */ function setImplicitModeProjectId( bytes32 projectId ) external onlyRole(_IMPLICIT_MODE_ADMIN_ROLE) { _projectId = projectId; } /// @inheritdoc IERC165 function supportsInterface( bytes4 interfaceId ) public view virtual override(AccessControlEnumerable, SignalsImplicitMode) returns (bool) { return AccessControlEnumerable.supportsInterface(interfaceId) || SignalsImplicitMode.supportsInterface(interfaceId); } }
WithdrawControlled.sol
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.19; import { IWithdrawControlled } from "./IWithdrawControlled.sol"; import { AccessControlEnumerable, ERC165 } from "openzeppelin-contracts/contracts/access/AccessControlEnumerable.sol"; import { IERC20, SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; /** * An abstract contract that allows ETH and ERC20 tokens stored in the contract to be withdrawn. */ abstract contract WithdrawControlled is AccessControlEnumerable, IWithdrawControlled { bytes32 internal constant WITHDRAW_ROLE = keccak256("WITHDRAW_ROLE"); // // Withdraw // /** * Withdraws ERC20 tokens owned by this contract. * @param token The ERC20 token address. * @param to Address to withdraw to. * @param value Amount to withdraw. * @notice Only callable by an address with the withdraw role. */ function withdrawERC20(address token, address to, uint256 value) public onlyRole(WITHDRAW_ROLE) { SafeERC20.safeTransfer(IERC20(token), to, value); } /** * Withdraws ETH owned by this sale contract. * @param to Address to withdraw to. * @param value Amount to withdraw. * @notice Only callable by an address with the withdraw role. */ function withdrawETH(address to, uint256 value) public onlyRole(WITHDRAW_ROLE) { (bool success,) = to.call{ value: value }(""); if (!success) { revert WithdrawFailed(); } } /// @inheritdoc ERC165 function supportsInterface( bytes4 interfaceId ) public view virtual override(AccessControlEnumerable) returns (bool) { return interfaceId == type(IWithdrawControlled).interfaceId || AccessControlEnumerable.supportsInterface(interfaceId); } }
Gas Token: