Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0x25b9Aa7436d9C8F41a5f64e93fAd876A9ce5D3F3
Balance 0 ETH
Nonce 1
Code Size 15149 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

15149 bytes
0x6080604052600436106101fc575f3560e01c80638f2a0bb01161010c578063b1c5f4271161009f578063d547741f1161006e578063d547741f1461078d578063e38335e5146107b5578063f23a6e61146107d1578063f27a0c921461080d578063fe7cdae41461083757610203565b8063b1c5f427146106b1578063bc197c81146106ed578063c4d252f514610729578063d45c44351461075157610203565b80639d6bdfac116100db5780639d6bdfac14610617578063a217fddf14610633578063a2929a5b1461065d578063b08e51c01461068757610203565b80638f2a0bb0146105615780638f61f4f51461058957806391d14854146105b3578063973821a6146105ef57610203565b80632ab0f5291161018f57806336568abe1161015e57806336568abe1461045d578063584b153e1461048557806364d62353146104c15780637958004c146104e95780638065657f1461052557610203565b80632ab0f529146103a15780632f2f3be1146103dd5780632f2ff15d146103f957806331d507501461042157610203565b806313bc9f20116101cb57806313bc9f20146102b1578063150b7a02146102ed5780631c0554ba14610329578063248a9ca31461036557610203565b806301d5062a1461020757806301ffc9a71461022f57806307bd02651461026b578063134008d31461029557610203565b3661020357005b5f80fd5b348015610212575f80fd5b5061022d60048036038101906102289190612760565b61085f565b005b34801561023a575f80fd5b506102556004803603810190610250919061285f565b610934565b60405161026291906128a4565b60405180910390f35b348015610276575f80fd5b5061027f610945565b60405161028c91906128cc565b60405180910390f35b6102af60048036038101906102aa91906128e5565b610969565b005b3480156102bc575f80fd5b506102d760048036038101906102d2919061297b565b61098f565b6040516102e491906128a4565b60405180910390f35b3480156102f8575f80fd5b50610313600480360381019061030e9190612ade565b6109c7565b6040516103209190612b6d565b60405180910390f35b348015610334575f80fd5b5061034f600480360381019061034a9190612b86565b6109da565b60405161035c91906128a4565b60405180910390f35b348015610370575f80fd5b5061038b6004803603810190610386919061297b565b610a7a565b60405161039891906128cc565b60405180910390f35b3480156103ac575f80fd5b506103c760048036038101906103c2919061297b565b610a96565b6040516103d491906128a4565b60405180910390f35b6103f760048036038101906103f29190612bc4565b610acd565b005b348015610404575f80fd5b5061041f600480360381019061041a9190612c35565b610c2a565b005b34801561042c575f80fd5b506104476004803603810190610442919061297b565b610c4c565b60405161045491906128a4565b60405180910390f35b348015610468575f80fd5b50610483600480360381019061047e9190612c35565b610c84565b005b348015610490575f80fd5b506104ab60048036038101906104a6919061297b565b610cc3565b6040516104b891906128a4565b60405180910390f35b3480156104cc575f80fd5b506104e760048036038101906104e29190612c73565b610d2f565b005b3480156104f4575f80fd5b5061050f600480360381019061050a919061297b565b610df0565b60405161051c9190612d11565b60405180910390f35b348015610530575f80fd5b5061054b600480360381019061054691906128e5565b610e3c565b60405161055891906128cc565b60405180910390f35b34801561056c575f80fd5b5061058760048036038101906105829190612e29565b610e7a565b005b348015610594575f80fd5b5061059d611039565b6040516105aa91906128cc565b60405180910390f35b3480156105be575f80fd5b506105d960048036038101906105d49190612c35565b61105d565b6040516105e691906128a4565b60405180910390f35b3480156105fa575f80fd5b5061061560048036038101906106109190612b86565b6110c0565b005b610631600480360381019061062c9190612f12565b6113a9565b005b34801561063e575f80fd5b506106476116df565b60405161065491906128cc565b60405180910390f35b348015610668575f80fd5b506106716116e5565b60405161067e91906128cc565b60405180910390f35b348015610692575f80fd5b5061069b611709565b6040516106a891906128cc565b60405180910390f35b3480156106bc575f80fd5b506106d760048036038101906106d29190612fc2565b61172d565b6040516106e491906128cc565b60405180910390f35b3480156106f8575f80fd5b50610713600480360381019061070e9190613159565b611771565b6040516107209190612b6d565b60405180910390f35b348015610734575f80fd5b5061074f600480360381019061074a919061297b565b611785565b005b34801561075c575f80fd5b506107776004803603810190610772919061297b565b611854565b6040516107849190613233565b60405180910390f35b348015610798575f80fd5b506107b360048036038101906107ae9190612c35565b61186e565b005b6107cf60048036038101906107ca9190612fc2565b611890565b005b3480156107dc575f80fd5b506107f760048036038101906107f2919061324c565b6118ba565b6040516108049190612b6d565b60405180910390f35b348015610818575f80fd5b506108216118ce565b60405161082e9190613233565b60405180910390f35b348015610842575f80fd5b5061085d60048036038101906108589190612b86565b6118d7565b005b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc161088981611af8565b5f610898898989898989610e3c565b90506108a48184611b0c565b5f817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a6040516108df9695949392919061332a565b60405180910390a35f801b841461092957807f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d03878560405161092091906128cc565b60405180910390a25b505050505050505050565b5f61093e82611bd9565b9050919050565b7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b610971611c52565b61097f868686868686611c98565b610987611d52565b505050505050565b5f600260038111156109a4576109a3612c9e565b5b6109ad83610df0565b60038111156109bf576109be612c9e565b5b149050919050565b5f63150b7a0260e01b9050949350505050565b5f60045f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f805f8381526020019081526020015f20600101549050919050565b5f600380811115610aaa57610aa9612c9e565b5b610ab383610df0565b6003811115610ac557610ac4612c9e565b5b149050919050565b7f389e8c0e82c32d300e95b13fa579aabf6ac32df2485cb1f756e174c811676cb2610af781611af8565b610aff611c52565b5f610b0a8484611d5c565b9050610b1686826109da565b610b595785816040517f1b267067000000000000000000000000000000000000000000000000000000008152600401610b50929190613384565b60405180910390fd5b807bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168673ffffffffffffffffffffffffffffffffffffffff167f8b494001fc301b466fc368b40104ca4df15a8b1cc32f3fab144eb863256af113878787604051610bc3939291906133ab565b60405180910390a3610c198685858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f8201169050808301925050505050505087611de4565b5050610c23611d52565b5050505050565b610c3382610a7a565b610c3c81611af8565b610c468383611eaf565b50505050565b5f806003811115610c6057610c5f612c9e565b5b610c6983610df0565b6003811115610c7b57610c7a612c9e565b5b14159050919050565b81816040517f221a89e9000000000000000000000000000000000000000000000000000000008152600401610cba9291906133db565b60405180910390fd5b5f80610cce83610df0565b905060016003811115610ce457610ce3612c9e565b5b816003811115610cf757610cf6612c9e565b5b1480610d27575060026003811115610d1257610d11612c9e565b5b816003811115610d2557610d24612c9e565b5b145b915050919050565b5f610d38611f98565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610daa57806040517fe2850c59000000000000000000000000000000000000000000000000000000008152600401610da19190613402565b60405180910390fd5b7f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d560025483604051610ddd92919061341b565b60405180910390a1816002819055505050565b5f80610dfb83611854565b90505f8103610e0d575f915050610e37565b60018103610e1f576003915050610e37565b42811115610e31576001915050610e37565b60029150505b919050565b5f868686868686604051602001610e5896959493929190613442565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1610ea481611af8565b878790508a8a9050141580610ebf5750858590508a8a905014155b15610f0e578989905086869050898990506040517fffb03211000000000000000000000000000000000000000000000000000000008152600401610f059392919061349c565b60405180910390fd5b5f610f1f8b8b8b8b8b8b8b8b61172d565b9050610f2b8184611b0c565b5f5b8b8b9050811015610fe95780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610f6e57610f6d6134d1565b5b9050602002016020810190610f8391906134fe565b8d8d86818110610f9657610f956134d1565b5b905060200201358c8c87818110610fb057610faf6134d1565b5b9050602002810190610fc29190613535565b8c8b604051610fd69695949392919061332a565b60405180910390a3806001019050610f2d565b505f801b841461102c57807f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d03878560405161102391906128cc565b60405180910390a25b5050505050505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b5f805f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f6110c9611f98565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461113b57806040517fe2850c590000000000000000000000000000000000000000000000000000000081526004016111329190613402565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614806111a057503073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b806111c157505f8373ffffffffffffffffffffffffffffffffffffffff163b145b1561120357826040517fd08525e90000000000000000000000000000000000000000000000000000000081526004016111fa9190613402565b60405180910390fd5b60045f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f9054906101000a900460ff166113a457600160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f6101000a81548160ff021916908315150217905550817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168373ffffffffffffffffffffffffffffffffffffffff167f6fc4e73d7aa184267ad4580767022a65a19754e8950253003e41a13d09e12fb860405160405180910390a35b505050565b7f389e8c0e82c32d300e95b13fa579aabf6ac32df2485cb1f756e174c811676cb26113d381611af8565b6113db611c52565b84849050878790501415806113f65750828290508787905014155b15611445578686905083839050868690506040517fffb0321100000000000000000000000000000000000000000000000000000000815260040161143c9392919061349c565b60405180910390fd5b5f5b878790508110156116cd575f611480858584818110611469576114686134d1565b5b905060200281019061147b9190613535565b611d5c565b90505f898984818110611496576114956134d1565b5b90506020020160208101906114ab91906134fe565b905060045f8273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f9054906101000a900460ff166115875780826040517f1b26706700000000000000000000000000000000000000000000000000000000815260040161157e929190613384565b60405180910390fd5b817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168173ffffffffffffffffffffffffffffffffffffffff167f8b494001fc301b466fc368b40104ca4df15a8b1cc32f3fab144eb863256af1138a8a878181106115f2576115f16134d1565b5b9050602002013589898881811061160c5761160b6134d1565b5b905060200281019061161e9190613535565b60405161162d939291906133ab565b60405180910390a36116bf8187878681811061164c5761164b6134d1565b5b905060200281019061165e9190613535565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f820116905080830192505050505050508a8a878181106116b3576116b26134d1565b5b90506020020135611de4565b505050806001019050611447565b506116d6611d52565b50505050505050565b5f801b81565b7f389e8c0e82c32d300e95b13fa579aabf6ac32df2485cb1f756e174c811676cb281565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b5f888888888888888860405160200161174d989796959493929190613823565b60405160208183030381529060405280519060200120905098975050505050505050565b5f63bc197c8160e01b905095945050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f7836117af81611af8565b6117b882610cc3565b61180f57816117c76002611f9f565b6117d16001611f9f565b176040517f5ead8eb500000000000000000000000000000000000000000000000000000000815260040161180692919061388f565b60405180910390fd5b60015f8381526020019081526020015f205f9055817fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7060405160405180910390a25050565b5f60015f8381526020019081526020015f20549050919050565b61187782610a7a565b61188081611af8565b61188a8383611fc3565b50505050565b611898611c52565b6118a888888888888888886120ac565b6118b0611d52565b5050505050505050565b5f63f23a6e6160e01b905095945050505050565b5f600254905090565b5f6118e0611f98565b90503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461195257806040517fe2850c590000000000000000000000000000000000000000000000000000000081526004016119499190613402565b60405180910390fd5b60045f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f9054906101000a900460ff1615611af3575f60045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020015f205f6101000a81548160ff021916908315150217905550817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168373ffffffffffffffffffffffffffffffffffffffff167fd8cbe6041196ba003f736b4adf129a2bb32b119ca2f3f3d660c9657ce989b6ad60405160405180910390a35b505050565b611b0981611b04611f98565b612264565b50565b611b1582610c4c565b15611b615781611b245f611f9f565b6040517f5ead8eb5000000000000000000000000000000000000000000000000000000008152600401611b5892919061388f565b60405180910390fd5b5f611b6a6118ce565b905080821015611bb35781816040517f54336609000000000000000000000000000000000000000000000000000000008152600401611baa92919061341b565b60405180910390fd5b8142611bbf91906138e3565b60015f8581526020019081526020015f2081905550505050565b5f7f4e2312e0000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611c4b5750611c4a826122b5565b5b9050919050565b600260035403611c8e576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600381905550565b7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63611cc3815f61105d565b611cd957611cd881611cd3611f98565b612264565b5b5f611ce8888888888888610e3c565b9050611cf4818561232e565b611d00888888886123e1565b5f817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a604051611d379493929190613916565b60405180910390a3611d4881612462565b5050505050505050565b6001600381905550565b5f808383905003611d72575f60e01b9050611dde565b6004838390501015611dbd5782826040517f889b0465000000000000000000000000000000000000000000000000000000008152600401611db4929190613954565b60405180910390fd5b82825f90600492611dd09392919061397e565b90611ddb91906139ce565b90505b92915050565b606081471015611e2d5747826040517fcf479181000000000000000000000000000000000000000000000000000000008152600401611e2492919061341b565b60405180910390fd5b5f808573ffffffffffffffffffffffffffffffffffffffff168486604051611e559190613a7e565b5f6040518083038185875af1925050503d805f8114611e8f576040519150601f19603f3d011682016040523d82523d5f602084013e611e94565b606091505b5091509150611ea48683836124d0565b925050509392505050565b5f611eba838361105d565b611f8e5760015f808581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550611f2b611f98565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050611f92565b5f90505b92915050565b5f33905090565b5f816003811115611fb357611fb2612c9e565b5b60ff166001901b5f1b9050919050565b5f611fce838361105d565b156120a2575f805f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555061203f611f98565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a4600190506120a6565b5f90505b92915050565b7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e636120d7815f61105d565b6120ed576120ec816120e7611f98565b612264565b5b86869050898990501415806121085750848490508989905014155b15612157578888905085859050888890506040517fffb0321100000000000000000000000000000000000000000000000000000000815260040161214e9392919061349c565b60405180910390fd5b5f6121688a8a8a8a8a8a8a8a61172d565b9050612174818561232e565b5f5b8a8a905081101561224e575f8b8b83818110612195576121946134d1565b5b90506020020160208101906121aa91906134fe565b90505f8a8a848181106121c0576121bf6134d1565b5b905060200201359050365f8a8a868181106121de576121dd6134d1565b5b90506020028101906121f09190613535565b91509150612200848484846123e1565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58868686866040516122379493929190613916565b60405180910390a350505050806001019050612176565b5061225881612462565b50505050505050505050565b61226e828261105d565b6122b15780826040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526004016122a8929190613a94565b60405180910390fd5b5050565b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061232757506123268261255d565b5b9050919050565b6123378261098f565b61238357816123466002611f9f565b6040517f5ead8eb500000000000000000000000000000000000000000000000000000000815260040161237a92919061388f565b60405180910390fd5b5f801b811415801561239b575061239981610a96565b155b156123dd57806040517f90a9a6180000000000000000000000000000000000000000000000000000000081526004016123d491906128cc565b60405180910390fd5b5050565b5f808573ffffffffffffffffffffffffffffffffffffffff1685858560405161240b929190613adf565b5f6040518083038185875af1925050503d805f8114612445576040519150601f19603f3d011682016040523d82523d5f602084013e61244a565b606091505b509150915061245982826125c6565b50505050505050565b61246b8161098f565b6124b7578061247a6002611f9f565b6040517f5ead8eb50000000000000000000000000000000000000000000000000000000081526004016124ae92919061388f565b60405180910390fd5b6001805f8381526020019081526020015f208190555050565b6060826124e5576124e0826125ea565b612555565b5f825114801561250b57505f8473ffffffffffffffffffffffffffffffffffffffff163b145b1561254d57836040517f9996b3150000000000000000000000000000000000000000000000000000000081526004016125449190613402565b60405180910390fd5b819050612556565b5b9392505050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6060826125db576125d6826125ea565b6125e3565b8190506125e4565b5b92915050565b5f815111156125fc5780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6126688261263f565b9050919050565b6126788161265e565b8114612682575f80fd5b50565b5f813590506126938161266f565b92915050565b5f819050919050565b6126ab81612699565b81146126b5575f80fd5b50565b5f813590506126c6816126a2565b92915050565b5f80fd5b5f80fd5b5f80fd5b5f8083601f8401126126ed576126ec6126cc565b5b8235905067ffffffffffffffff81111561270a576127096126d0565b5b602083019150836001820283011115612726576127256126d4565b5b9250929050565b5f819050919050565b61273f8161272d565b8114612749575f80fd5b50565b5f8135905061275a81612736565b92915050565b5f805f805f805f60c0888a03121561277b5761277a612637565b5b5f6127888a828b01612685565b97505060206127998a828b016126b8565b965050604088013567ffffffffffffffff8111156127ba576127b961263b565b5b6127c68a828b016126d8565b955095505060606127d98a828b0161274c565b93505060806127ea8a828b0161274c565b92505060a06127fb8a828b016126b8565b91505092959891949750929550565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61283e8161280a565b8114612848575f80fd5b50565b5f8135905061285981612835565b92915050565b5f6020828403121561287457612873612637565b5b5f6128818482850161284b565b91505092915050565b5f8115159050919050565b61289e8161288a565b82525050565b5f6020820190506128b75f830184612895565b92915050565b6128c68161272d565b82525050565b5f6020820190506128df5f8301846128bd565b92915050565b5f805f805f8060a087890312156128ff576128fe612637565b5b5f61290c89828a01612685565b965050602061291d89828a016126b8565b955050604087013567ffffffffffffffff81111561293e5761293d61263b565b5b61294a89828a016126d8565b9450945050606061295d89828a0161274c565b925050608061296e89828a0161274c565b9150509295509295509295565b5f602082840312156129905761298f612637565b5b5f61299d8482850161274c565b91505092915050565b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6129f0826129aa565b810181811067ffffffffffffffff82111715612a0f57612a0e6129ba565b5b80604052505050565b5f612a2161262e565b9050612a2d82826129e7565b919050565b5f67ffffffffffffffff821115612a4c57612a4b6129ba565b5b612a55826129aa565b9050602081019050919050565b828183375f83830152505050565b5f612a82612a7d84612a32565b612a18565b905082815260208101848484011115612a9e57612a9d6129a6565b5b612aa9848285612a62565b509392505050565b5f82601f830112612ac557612ac46126cc565b5b8135612ad5848260208601612a70565b91505092915050565b5f805f8060808587031215612af657612af5612637565b5b5f612b0387828801612685565b9450506020612b1487828801612685565b9350506040612b25878288016126b8565b925050606085013567ffffffffffffffff811115612b4657612b4561263b565b5b612b5287828801612ab1565b91505092959194509250565b612b678161280a565b82525050565b5f602082019050612b805f830184612b5e565b92915050565b5f8060408385031215612b9c57612b9b612637565b5b5f612ba985828601612685565b9250506020612bba8582860161284b565b9150509250929050565b5f805f8060608587031215612bdc57612bdb612637565b5b5f612be987828801612685565b9450506020612bfa878288016126b8565b935050604085013567ffffffffffffffff811115612c1b57612c1a61263b565b5b612c27878288016126d8565b925092505092959194509250565b5f8060408385031215612c4b57612c4a612637565b5b5f612c588582860161274c565b9250506020612c6985828601612685565b9150509250929050565b5f60208284031215612c8857612c87612637565b5b5f612c95848285016126b8565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b60048110612cdc57612cdb612c9e565b5b50565b5f819050612cec82612ccb565b919050565b5f612cfb82612cdf565b9050919050565b612d0b81612cf1565b82525050565b5f602082019050612d245f830184612d02565b92915050565b5f8083601f840112612d3f57612d3e6126cc565b5b8235905067ffffffffffffffff811115612d5c57612d5b6126d0565b5b602083019150836020820283011115612d7857612d776126d4565b5b9250929050565b5f8083601f840112612d9457612d936126cc565b5b8235905067ffffffffffffffff811115612db157612db06126d0565b5b602083019150836020820283011115612dcd57612dcc6126d4565b5b9250929050565b5f8083601f840112612de957612de86126cc565b5b8235905067ffffffffffffffff811115612e0657612e056126d0565b5b602083019150836020820283011115612e2257612e216126d4565b5b9250929050565b5f805f805f805f805f60c08a8c031215612e4657612e45612637565b5b5f8a013567ffffffffffffffff811115612e6357612e6261263b565b5b612e6f8c828d01612d2a565b995099505060208a013567ffffffffffffffff811115612e9257612e9161263b565b5b612e9e8c828d01612d7f565b975097505060408a013567ffffffffffffffff811115612ec157612ec061263b565b5b612ecd8c828d01612dd4565b95509550506060612ee08c828d0161274c565b9350506080612ef18c828d0161274c565b92505060a0612f028c828d016126b8565b9150509295985092959850929598565b5f805f805f8060608789031215612f2c57612f2b612637565b5b5f87013567ffffffffffffffff811115612f4957612f4861263b565b5b612f5589828a01612d2a565b9650965050602087013567ffffffffffffffff811115612f7857612f7761263b565b5b612f8489828a01612d7f565b9450945050604087013567ffffffffffffffff811115612fa757612fa661263b565b5b612fb389828a01612dd4565b92509250509295509295509295565b5f805f805f805f8060a0898b031215612fde57612fdd612637565b5b5f89013567ffffffffffffffff811115612ffb57612ffa61263b565b5b6130078b828c01612d2a565b9850985050602089013567ffffffffffffffff81111561302a5761302961263b565b5b6130368b828c01612d7f565b9650965050604089013567ffffffffffffffff8111156130595761305861263b565b5b6130658b828c01612dd4565b945094505060606130788b828c0161274c565b92505060806130898b828c0161274c565b9150509295985092959890939650565b5f67ffffffffffffffff8211156130b3576130b26129ba565b5b602082029050602081019050919050565b5f6130d66130d184613099565b612a18565b905080838252602082019050602084028301858111156130f9576130f86126d4565b5b835b81811015613122578061310e88826126b8565b8452602084019350506020810190506130fb565b5050509392505050565b5f82601f8301126131405761313f6126cc565b5b81356131508482602086016130c4565b91505092915050565b5f805f805f60a0868803121561317257613171612637565b5b5f61317f88828901612685565b955050602061319088828901612685565b945050604086013567ffffffffffffffff8111156131b1576131b061263b565b5b6131bd8882890161312c565b935050606086013567ffffffffffffffff8111156131de576131dd61263b565b5b6131ea8882890161312c565b925050608086013567ffffffffffffffff81111561320b5761320a61263b565b5b61321788828901612ab1565b9150509295509295909350565b61322d81612699565b82525050565b5f6020820190506132465f830184613224565b92915050565b5f805f805f60a0868803121561326557613264612637565b5b5f61327288828901612685565b955050602061328388828901612685565b9450506040613294888289016126b8565b93505060606132a5888289016126b8565b925050608086013567ffffffffffffffff8111156132c6576132c561263b565b5b6132d288828901612ab1565b9150509295509295909350565b6132e88161265e565b82525050565b5f82825260208201905092915050565b5f61330983856132ee565b9350613316838584612a62565b61331f836129aa565b840190509392505050565b5f60a08201905061333d5f8301896132df565b61334a6020830188613224565b818103604083015261335d8186886132fe565b905061336c60608301856128bd565b6133796080830184613224565b979650505050505050565b5f6040820190506133975f8301856132df565b6133a46020830184612b5e565b9392505050565b5f6040820190506133be5f830186613224565b81810360208301526133d18184866132fe565b9050949350505050565b5f6040820190506133ee5f8301856128bd565b6133fb60208301846132df565b9392505050565b5f6020820190506134155f8301846132df565b92915050565b5f60408201905061342e5f830185613224565b61343b6020830184613224565b9392505050565b5f60a0820190506134555f8301896132df565b6134626020830188613224565b81810360408301526134758186886132fe565b905061348460608301856128bd565b61349160808301846128bd565b979650505050505050565b5f6060820190506134af5f830186613224565b6134bc6020830185613224565b6134c96040830184613224565b949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6020828403121561351357613512612637565b5b5f61352084828501612685565b91505092915050565b5f80fd5b5f80fd5b5f80fd5b5f808335600160200384360303811261355157613550613529565b5b80840192508235915067ffffffffffffffff8211156135735761357261352d565b5b60208301925060018202360383131561358f5761358e613531565b5b509250929050565b5f82825260208201905092915050565b5f819050919050565b6135b98161265e565b82525050565b5f6135ca83836135b0565b60208301905092915050565b5f6135e46020840184612685565b905092915050565b5f602082019050919050565b5f6136038385613597565b935061360e826135a7565b805f5b858110156136465761362382846135d6565b61362d88826135bf565b9750613638836135ec565b925050600181019050613611565b5085925050509392505050565b5f82825260208201905092915050565b5f80fd5b82818337505050565b5f61367b8385613653565b93507f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156136ae576136ad613663565b5b6020830292506136bf838584613667565b82840190509392505050565b5f82825260208201905092915050565b5f819050919050565b5f82825260208201905092915050565b5f6136ff83856136e4565b935061370c838584612a62565b613715836129aa565b840190509392505050565b5f61372c8484846136f4565b90509392505050565b5f80fd5b5f80fd5b5f80fd5b5f808335600160200384360303811261375d5761375c61373d565b5b83810192508235915060208301925067ffffffffffffffff82111561378557613784613735565b5b60018202360383131561379b5761379a613739565b5b509250929050565b5f602082019050919050565b5f6137ba83856136cb565b9350836020840285016137cc846136db565b805f5b878110156138115784840389526137e68284613741565b6137f1868284613720565b95506137fc846137a3565b935060208b019a5050506001810190506137cf565b50829750879450505050509392505050565b5f60a0820190508181035f83015261383c818a8c6135f8565b9050818103602083015261385181888a613670565b905081810360408301526138668186886137af565b905061387560608301856128bd565b61388260808301846128bd565b9998505050505050505050565b5f6040820190506138a25f8301856128bd565b6138af60208301846128bd565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6138ed82612699565b91506138f883612699565b92508282019050808211156139105761390f6138b6565b5b92915050565b5f6060820190506139295f8301876132df565b6139366020830186613224565b81810360408301526139498184866132fe565b905095945050505050565b5f6020820190508181035f83015261396d8184866132fe565b90509392505050565b5f80fd5b5f80fd5b5f808585111561399157613990613976565b5b838611156139a2576139a161397a565b5b6001850283019150848603905094509492505050565b5f82905092915050565b5f82821b905092915050565b5f6139d983836139b8565b826139e4813561280a565b92506004821015613a2457613a1f7fffffffff00000000000000000000000000000000000000000000000000000000836004036008026139c2565b831692505b505092915050565b5f81519050919050565b5f81905092915050565b8281835e5f83830152505050565b5f613a5882613a2c565b613a628185613a36565b9350613a72818560208601613a40565b80840191505092915050565b5f613a898284613a4e565b915081905092915050565b5f604082019050613aa75f8301856132df565b613ab460208301846128bd565b9392505050565b5f613ac68385613a36565b9350613ad3838584612a62565b82840190509392505050565b5f613aeb828486613abb565b9150819050939250505056fea264697066735822122052de93cf6676680f6d8a2bd2ce708c445041c0d21e46cc9de465ea8de8f2ef3564736f6c634300081a0033

Verified Source Code Full Match

Compiler: v0.8.26+commit.8a97fa7a EVM: cancun Optimization: No
EthenaTimelockController.sol 218 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import {TimelockController, Address} from "@openzeppelin/contracts/governance/TimelockController.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
/**
 * @title EthenaTimelockController
 * @dev A custom timelock contract extending OpenZeppelin's TimelockController.
 * - Allows bypassing the timelock for whitelisted functions.
 * - Functions can be whitelisted or removed from the whitelist by the admin.
 * - Emits events for whitelisting, removing from whitelist, and executing whitelisted functions.
 * - Overrides execute function to check for whitelisted functions.
 */

contract EthenaTimelockController is TimelockController, ReentrancyGuard {
    error NotWhitelisted(address target, bytes4 selector);
    error InvalidTarget(address target);
    error InvalidSelector(bytes data);
    error InvalidRoleGrant(address target, bytes32 role);
    error RenounceRoleNotAllowed(bytes32 role, address callerConfirmation);

    event FunctionWhitelisted(address indexed target, bytes4 indexed selector);
    event FunctionRemovedFromWhitelist(address indexed target, bytes4 indexed selector);
    event WhitelistedFunctionExecuted(address indexed target, bytes4 indexed selector, uint256 value, bytes data);

    // New role for whitelisted function execution
    bytes32 public constant WHITELISTED_EXECUTOR_ROLE = keccak256("WHITELISTED_EXECUTOR_ROLE");

    uint256 private constant SELECTOR_LENGTH = 4;

    /// @notice Mapping of whitelisted functions that can be executed without delay
    mapping(address target => mapping(bytes4 selector => bool allowed)) private _functionWhitelist;

    modifier onlyTimelock() {
        address sender = _msgSender();
        if (sender != address(this)) {
            revert TimelockUnauthorizedCaller(sender);
        }
        _;
    }

    /**
     * @dev Constructor for the CustomTimelock contract.
     * @param minDelay The minimum delay before an operation can be executed.
     * @param proposers The list of addresses that can propose operations.
     * @param executors The list of addresses that can execute operations.
     * @param whitelistedExecutors The list of addresses that can execute whitelisted operations.
     */
    constructor(
        uint256 minDelay,
        address[] memory proposers,
        address[] memory executors,
        address[] memory whitelistedExecutors
    ) TimelockController(minDelay, proposers, executors, address(0)) ReentrancyGuard() {
        for (uint256 i = 0; i < proposers.length; ++i) {
            if (proposers[i] == address(0)) {
                revert InvalidRoleGrant(proposers[i], PROPOSER_ROLE);
            }
        }
        // grant whitelisted executor role
        for (uint256 i = 0; i < whitelistedExecutors.length; ++i) {
            if (whitelistedExecutors[i] == address(0)) {
                revert InvalidRoleGrant(whitelistedExecutors[i], WHITELISTED_EXECUTOR_ROLE);
            }
            _grantRole(WHITELISTED_EXECUTOR_ROLE, whitelistedExecutors[i]);
        }
    }

    /**
     * @dev Adds a function selector to the whitelist for a specific address.
     * Can only be called via the timelock mechanism.
     * @param target The address of the contract.
     * @param selector The function selector to whitelist.
     */
    function addToWhitelist(address target, bytes4 selector) external onlyTimelock {
        if (target == address(0) || target == address(this) || target.code.length == 0) {
            revert InvalidTarget(target);
        }
        if (_functionWhitelist[target][selector]) {
            return;
        }
        _functionWhitelist[target][selector] = true;
        emit FunctionWhitelisted(target, selector);
    }

    /**
     * @dev Removes a function selector from the whitelist for a specific address.
     * Can only be called via the timelock mechanism.
     * @param target The address of the contract.
     * @param selector The function selector to remove from the whitelist.
     */
    function removeFromWhitelist(address target, bytes4 selector) external onlyTimelock {
        if (!_functionWhitelist[target][selector]) {
            return;
        }
        _functionWhitelist[target][selector] = false;
        emit FunctionRemovedFromWhitelist(target, selector);
    }

    /**
     * @dev Checks if a function selector is whitelisted for a specific address.
     * @param target The address of the contract.
     * @param selector The function selector to check.
     * @return True if the function selector is whitelisted, false otherwise.
     */
    function isWhitelisted(address target, bytes4 selector) public view returns (bool) {
        return _functionWhitelist[target][selector];
    }

    /**
     * @dev Executes a function, bypassing the timelock if it's whitelisted.
     * @param target The address of the contract to call.
     * @param value The amount of ETH to send along with the call.
     * @param data The calldata to send.
     * @param predecessor The operation that must be executed before this one.
     * @param salt A random value used to differentiate the operation from others.
     */
    function execute(address target, uint256 value, bytes calldata data, bytes32 predecessor, bytes32 salt)
        public
        payable
        override
        nonReentrant
    {
        // Guarded by onlyRoleOrOpenRole(EXECUTOR_ROLE)
        super.execute(target, value, data, predecessor, salt);
    }

    /**
     * @dev Executes a whitelisted function.
     * @param target The address of the contract to call.
     * @param value The amount of ETH to send along with the call.
     * @param data The calldata to send.
     */
    function executeWhitelisted(address target, uint256 value, bytes calldata data)
        public
        payable
        onlyRole(WHITELISTED_EXECUTOR_ROLE)
        nonReentrant
    {
        bytes4 selector = _extractSelector(data);
        if (!isWhitelisted(target, selector)) {
            revert NotWhitelisted(target, selector);
        }
        emit WhitelistedFunctionExecuted(target, selector, value, data);
        Address.functionCallWithValue(target, data, value);
    }

    /**
     * @dev Executes a batch of whitelisted functions.
     * @param targets The addresses of the contracts to call.
     * @param values The amounts of ETH to send along with the calls.
     * @param payloads The calldata to send.
     * @param predecessor The operation that must be executed before this one.
     * @param salt A random value used to differentiate the operation from others.
     */
    function executeBatch(
        address[] calldata targets,
        uint256[] calldata values,
        bytes[] calldata payloads,
        bytes32 predecessor,
        bytes32 salt
    ) public payable override nonReentrant {
        super.executeBatch(targets, values, payloads, predecessor, salt);
    }

    /**
     * @dev Executes a batch of whitelisted functions.
     * @param targets The addresses of the contracts to call.
     * @param values The amounts of ETH to send along with the calls.
     * @param payloads The calldata to send.
     */
    function executeWhitelistedBatch(address[] calldata targets, uint256[] calldata values, bytes[] calldata payloads)
        public
        payable
        onlyRole(WHITELISTED_EXECUTOR_ROLE)
        nonReentrant
    {
        if (targets.length != values.length || targets.length != payloads.length) {
            revert TimelockInvalidOperationLength(targets.length, payloads.length, values.length);
        }

        for (uint256 i = 0; i < targets.length; ++i) {
            bytes4 selector = _extractSelector(payloads[i]);
            address target = targets[i];
            if (!_functionWhitelist[target][selector]) {
                revert NotWhitelisted(target, selector);
            }
            emit WhitelistedFunctionExecuted(target, selector, values[i], payloads[i]);
            Address.functionCallWithValue(target, payloads[i], values[i]);
        }
    }

    /**
     * @dev Throws an error when trying to renounce a role.
     * @notice Roles cannot be renounced, only revoked thru timelock mechanism.
     * @param role The role to renounce.
     * @param callerConfirmation The address that is renouncing the role.
     */
    function renounceRole(bytes32 role, address callerConfirmation) public pure override {
        revert RenounceRoleNotAllowed(role, callerConfirmation);
    }

    /**
     * @dev Extracts the function selector from the calldata.
     * @notice Risk of selector collision mitigated by whitelisting being permissioned action and specific to target address.
     * @param data The calldata to extract the selector from.
     * @return selector The function selector.
     */
    function _extractSelector(bytes calldata data) internal pure returns (bytes4 selector) {
        if (data.length == 0) {
            selector = bytes4(0);
        } else if (data.length < SELECTOR_LENGTH) {
            revert InvalidSelector(data);
        } else {
            selector = bytes4(data[:SELECTOR_LENGTH]);
        }
    }
}
TimelockController.sol 472 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (governance/TimelockController.sol)

pragma solidity ^0.8.20;

import {AccessControl} from "../access/AccessControl.sol";
import {ERC721Holder} from "../token/ERC721/utils/ERC721Holder.sol";
import {ERC1155Holder} from "../token/ERC1155/utils/ERC1155Holder.sol";
import {Address} from "../utils/Address.sol";

/**
 * @dev Contract module which acts as a timelocked controller. When set as the
 * owner of an `Ownable` smart contract, it enforces a timelock on all
 * `onlyOwner` maintenance operations. This gives time for users of the
 * controlled contract to exit before a potentially dangerous maintenance
 * operation is applied.
 *
 * By default, this contract is self administered, meaning administration tasks
 * have to go through the timelock process. The proposer (resp executor) role
 * is in charge of proposing (resp executing) operations. A common use case is
 * to position this {TimelockController} as the owner of a smart contract, with
 * a multisig or a DAO as the sole proposer.
 */
contract TimelockController is AccessControl, ERC721Holder, ERC1155Holder {
    bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE");
    bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE");
    bytes32 public constant CANCELLER_ROLE = keccak256("CANCELLER_ROLE");
    uint256 internal constant _DONE_TIMESTAMP = uint256(1);

    mapping(bytes32 id => uint256) private _timestamps;
    uint256 private _minDelay;

    enum OperationState {
        Unset,
        Waiting,
        Ready,
        Done
    }

    /**
     * @dev Mismatch between the parameters length for an operation call.
     */
    error TimelockInvalidOperationLength(uint256 targets, uint256 payloads, uint256 values);

    /**
     * @dev The schedule operation doesn't meet the minimum delay.
     */
    error TimelockInsufficientDelay(uint256 delay, uint256 minDelay);

    /**
     * @dev The current state of an operation is not as required.
     * The `expectedStates` is a bitmap with the bits enabled for each OperationState enum position
     * counting from right to left.
     *
     * See {_encodeStateBitmap}.
     */
    error TimelockUnexpectedOperationState(bytes32 operationId, bytes32 expectedStates);

    /**
     * @dev The predecessor to an operation not yet done.
     */
    error TimelockUnexecutedPredecessor(bytes32 predecessorId);

    /**
     * @dev The caller account is not authorized.
     */
    error TimelockUnauthorizedCaller(address caller);

    /**
     * @dev Emitted when a call is scheduled as part of operation `id`.
     */
    event CallScheduled(
        bytes32 indexed id,
        uint256 indexed index,
        address target,
        uint256 value,
        bytes data,
        bytes32 predecessor,
        uint256 delay
    );

    /**
     * @dev Emitted when a call is performed as part of operation `id`.
     */
    event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);

    /**
     * @dev Emitted when new proposal is scheduled with non-zero salt.
     */
    event CallSalt(bytes32 indexed id, bytes32 salt);

    /**
     * @dev Emitted when operation `id` is cancelled.
     */
    event Cancelled(bytes32 indexed id);

    /**
     * @dev Emitted when the minimum delay for future operations is modified.
     */
    event MinDelayChange(uint256 oldDuration, uint256 newDuration);

    /**
     * @dev Initializes the contract with the following parameters:
     *
     * - `minDelay`: initial minimum delay in seconds for operations
     * - `proposers`: accounts to be granted proposer and canceller roles
     * - `executors`: accounts to be granted executor role
     * - `admin`: optional account to be granted admin role; disable with zero address
     *
     * IMPORTANT: The optional admin can aid with initial configuration of roles after deployment
     * without being subject to delay, but this role should be subsequently renounced in favor of
     * administration through timelocked proposals. Previous versions of this contract would assign
     * this admin to the deployer automatically and should be renounced as well.
     */
    constructor(uint256 minDelay, address[] memory proposers, address[] memory executors, address admin) {
        // self administration
        _grantRole(DEFAULT_ADMIN_ROLE, address(this));

        // optional admin
        if (admin != address(0)) {
            _grantRole(DEFAULT_ADMIN_ROLE, admin);
        }

        // register proposers and cancellers
        for (uint256 i = 0; i < proposers.length; ++i) {
            _grantRole(PROPOSER_ROLE, proposers[i]);
            _grantRole(CANCELLER_ROLE, proposers[i]);
        }

        // register executors
        for (uint256 i = 0; i < executors.length; ++i) {
            _grantRole(EXECUTOR_ROLE, executors[i]);
        }

        _minDelay = minDelay;
        emit MinDelayChange(0, minDelay);
    }

    /**
     * @dev Modifier to make a function callable only by a certain role. In
     * addition to checking the sender's role, `address(0)` 's role is also
     * considered. Granting a role to `address(0)` is equivalent to enabling
     * this role for everyone.
     */
    modifier onlyRoleOrOpenRole(bytes32 role) {
        if (!hasRole(role, address(0))) {
            _checkRole(role, _msgSender());
        }
        _;
    }

    /**
     * @dev Contract might receive/hold ETH as part of the maintenance process.
     */
    receive() external payable virtual {}

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(
        bytes4 interfaceId
    ) public view virtual override(AccessControl, ERC1155Holder) returns (bool) {
        return super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns whether an id corresponds to a registered operation. This
     * includes both Waiting, Ready, and Done operations.
     */
    function isOperation(bytes32 id) public view returns (bool) {
        return getOperationState(id) != OperationState.Unset;
    }

    /**
     * @dev Returns whether an operation is pending or not. Note that a "pending" operation may also be "ready".
     */
    function isOperationPending(bytes32 id) public view returns (bool) {
        OperationState state = getOperationState(id);
        return state == OperationState.Waiting || state == OperationState.Ready;
    }

    /**
     * @dev Returns whether an operation is ready for execution. Note that a "ready" operation is also "pending".
     */
    function isOperationReady(bytes32 id) public view returns (bool) {
        return getOperationState(id) == OperationState.Ready;
    }

    /**
     * @dev Returns whether an operation is done or not.
     */
    function isOperationDone(bytes32 id) public view returns (bool) {
        return getOperationState(id) == OperationState.Done;
    }

    /**
     * @dev Returns the timestamp at which an operation becomes ready (0 for
     * unset operations, 1 for done operations).
     */
    function getTimestamp(bytes32 id) public view virtual returns (uint256) {
        return _timestamps[id];
    }

    /**
     * @dev Returns operation state.
     */
    function getOperationState(bytes32 id) public view virtual returns (OperationState) {
        uint256 timestamp = getTimestamp(id);
        if (timestamp == 0) {
            return OperationState.Unset;
        } else if (timestamp == _DONE_TIMESTAMP) {
            return OperationState.Done;
        } else if (timestamp > block.timestamp) {
            return OperationState.Waiting;
        } else {
            return OperationState.Ready;
        }
    }

    /**
     * @dev Returns the minimum delay in seconds for an operation to become valid.
     *
     * This value can be changed by executing an operation that calls `updateDelay`.
     */
    function getMinDelay() public view virtual returns (uint256) {
        return _minDelay;
    }

    /**
     * @dev Returns the identifier of an operation containing a single
     * transaction.
     */
    function hashOperation(
        address target,
        uint256 value,
        bytes calldata data,
        bytes32 predecessor,
        bytes32 salt
    ) public pure virtual returns (bytes32) {
        return keccak256(abi.encode(target, value, data, predecessor, salt));
    }

    /**
     * @dev Returns the identifier of an operation containing a batch of
     * transactions.
     */
    function hashOperationBatch(
        address[] calldata targets,
        uint256[] calldata values,
        bytes[] calldata payloads,
        bytes32 predecessor,
        bytes32 salt
    ) public pure virtual returns (bytes32) {
        return keccak256(abi.encode(targets, values, payloads, predecessor, salt));
    }

    /**
     * @dev Schedule an operation containing a single transaction.
     *
     * Emits {CallSalt} if salt is nonzero, and {CallScheduled}.
     *
     * Requirements:
     *
     * - the caller must have the 'proposer' role.
     */
    function schedule(
        address target,
        uint256 value,
        bytes calldata data,
        bytes32 predecessor,
        bytes32 salt,
        uint256 delay
    ) public virtual onlyRole(PROPOSER_ROLE) {
        bytes32 id = hashOperation(target, value, data, predecessor, salt);
        _schedule(id, delay);
        emit CallScheduled(id, 0, target, value, data, predecessor, delay);
        if (salt != bytes32(0)) {
            emit CallSalt(id, salt);
        }
    }

    /**
     * @dev Schedule an operation containing a batch of transactions.
     *
     * Emits {CallSalt} if salt is nonzero, and one {CallScheduled} event per transaction in the batch.
     *
     * Requirements:
     *
     * - the caller must have the 'proposer' role.
     */
    function scheduleBatch(
        address[] calldata targets,
        uint256[] calldata values,
        bytes[] calldata payloads,
        bytes32 predecessor,
        bytes32 salt,
        uint256 delay
    ) public virtual onlyRole(PROPOSER_ROLE) {
        if (targets.length != values.length || targets.length != payloads.length) {
            revert TimelockInvalidOperationLength(targets.length, payloads.length, values.length);
        }

        bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);
        _schedule(id, delay);
        for (uint256 i = 0; i < targets.length; ++i) {
            emit CallScheduled(id, i, targets[i], values[i], payloads[i], predecessor, delay);
        }
        if (salt != bytes32(0)) {
            emit CallSalt(id, salt);
        }
    }

    /**
     * @dev Schedule an operation that is to become valid after a given delay.
     */
    function _schedule(bytes32 id, uint256 delay) private {
        if (isOperation(id)) {
            revert TimelockUnexpectedOperationState(id, _encodeStateBitmap(OperationState.Unset));
        }
        uint256 minDelay = getMinDelay();
        if (delay < minDelay) {
            revert TimelockInsufficientDelay(delay, minDelay);
        }
        _timestamps[id] = block.timestamp + delay;
    }

    /**
     * @dev Cancel an operation.
     *
     * Requirements:
     *
     * - the caller must have the 'canceller' role.
     */
    function cancel(bytes32 id) public virtual onlyRole(CANCELLER_ROLE) {
        if (!isOperationPending(id)) {
            revert TimelockUnexpectedOperationState(
                id,
                _encodeStateBitmap(OperationState.Waiting) | _encodeStateBitmap(OperationState.Ready)
            );
        }
        delete _timestamps[id];

        emit Cancelled(id);
    }

    /**
     * @dev Execute an (ready) operation containing a single transaction.
     *
     * Emits a {CallExecuted} event.
     *
     * Requirements:
     *
     * - the caller must have the 'executor' role.
     */
    // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,
    // thus any modifications to the operation during reentrancy should be caught.
    // slither-disable-next-line reentrancy-eth
    function execute(
        address target,
        uint256 value,
        bytes calldata payload,
        bytes32 predecessor,
        bytes32 salt
    ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
        bytes32 id = hashOperation(target, value, payload, predecessor, salt);

        _beforeCall(id, predecessor);
        _execute(target, value, payload);
        emit CallExecuted(id, 0, target, value, payload);
        _afterCall(id);
    }

    /**
     * @dev Execute an (ready) operation containing a batch of transactions.
     *
     * Emits one {CallExecuted} event per transaction in the batch.
     *
     * Requirements:
     *
     * - the caller must have the 'executor' role.
     */
    // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,
    // thus any modifications to the operation during reentrancy should be caught.
    // slither-disable-next-line reentrancy-eth
    function executeBatch(
        address[] calldata targets,
        uint256[] calldata values,
        bytes[] calldata payloads,
        bytes32 predecessor,
        bytes32 salt
    ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
        if (targets.length != values.length || targets.length != payloads.length) {
            revert TimelockInvalidOperationLength(targets.length, payloads.length, values.length);
        }

        bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);

        _beforeCall(id, predecessor);
        for (uint256 i = 0; i < targets.length; ++i) {
            address target = targets[i];
            uint256 value = values[i];
            bytes calldata payload = payloads[i];
            _execute(target, value, payload);
            emit CallExecuted(id, i, target, value, payload);
        }
        _afterCall(id);
    }

    /**
     * @dev Execute an operation's call.
     */
    function _execute(address target, uint256 value, bytes calldata data) internal virtual {
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        Address.verifyCallResult(success, returndata);
    }

    /**
     * @dev Checks before execution of an operation's calls.
     */
    function _beforeCall(bytes32 id, bytes32 predecessor) private view {
        if (!isOperationReady(id)) {
            revert TimelockUnexpectedOperationState(id, _encodeStateBitmap(OperationState.Ready));
        }
        if (predecessor != bytes32(0) && !isOperationDone(predecessor)) {
            revert TimelockUnexecutedPredecessor(predecessor);
        }
    }

    /**
     * @dev Checks after execution of an operation's calls.
     */
    function _afterCall(bytes32 id) private {
        if (!isOperationReady(id)) {
            revert TimelockUnexpectedOperationState(id, _encodeStateBitmap(OperationState.Ready));
        }
        _timestamps[id] = _DONE_TIMESTAMP;
    }

    /**
     * @dev Changes the minimum timelock duration for future operations.
     *
     * Emits a {MinDelayChange} event.
     *
     * Requirements:
     *
     * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing
     * an operation where the timelock is the target and the data is the ABI-encoded call to this function.
     */
    function updateDelay(uint256 newDelay) external virtual {
        address sender = _msgSender();
        if (sender != address(this)) {
            revert TimelockUnauthorizedCaller(sender);
        }
        emit MinDelayChange(_minDelay, newDelay);
        _minDelay = newDelay;
    }

    /**
     * @dev Encodes a `OperationState` into a `bytes32` representation where each bit enabled corresponds to
     * the underlying position in the `OperationState` enum. For example:
     *
     * 0x000...1000
     *   ^^^^^^----- ...
     *         ^---- Done
     *          ^--- Ready
     *           ^-- Waiting
     *            ^- Unset
     */
    function _encodeStateBitmap(OperationState operationState) internal pure returns (bytes32) {
        return bytes32(1 << uint8(operationState));
    }
}
ReentrancyGuard.sol 87 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
 * consider using {ReentrancyGuardTransient} instead.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        _status = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}
AccessControl.sol 209 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (access/AccessControl.sol)

pragma solidity ^0.8.20;

import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {ERC165} from "../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 account => bool) hasRole;
        bytes32 adminRole;
    }

    mapping(bytes32 role => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with an {AccessControlUnauthorizedAccount} error including the required role.
     */
    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 returns (bool) {
        return _roles[role].hasRole[account];
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
     * is missing `role`.
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert AccessControlUnauthorizedAccount(account, role);
        }
    }

    /**
     * @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 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 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 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 `callerConfirmation`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address callerConfirmation) public virtual {
        if (callerConfirmation != _msgSender()) {
            revert AccessControlBadConfirmation();
        }

        _revokeRole(role, callerConfirmation);
    }

    /**
     * @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 Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
        if (!hasRole(role, account)) {
            _roles[role].hasRole[account] = true;
            emit RoleGranted(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
        if (hasRole(role, account)) {
            _roles[role].hasRole[account] = false;
            emit RoleRevoked(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }
}
ERC721Holder.sol 24 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/utils/ERC721Holder.sol)

pragma solidity ^0.8.20;

import {IERC721Receiver} from "../IERC721Receiver.sol";

/**
 * @dev Implementation of the {IERC721Receiver} interface.
 *
 * Accepts all token transfers.
 * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or
 * {IERC721-setApprovalForAll}.
 */
abstract contract ERC721Holder is IERC721Receiver {
    /**
     * @dev See {IERC721Receiver-onERC721Received}.
     *
     * Always returns `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) {
        return this.onERC721Received.selector;
    }
}
ERC1155Holder.sol 42 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/utils/ERC1155Holder.sol)

pragma solidity ^0.8.20;

import {IERC165, ERC165} from "../../../utils/introspection/ERC165.sol";
import {IERC1155Receiver} from "../IERC1155Receiver.sol";

/**
 * @dev Simple implementation of `IERC1155Receiver` that will allow a contract to hold ERC-1155 tokens.
 *
 * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be
 * stuck.
 */
abstract contract ERC1155Holder is ERC165, IERC1155Receiver {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);
    }

    function onERC1155Received(
        address,
        address,
        uint256,
        uint256,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC1155Received.selector;
    }

    function onERC1155BatchReceived(
        address,
        address,
        uint256[] memory,
        uint256[] memory,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC1155BatchReceived.selector;
    }
}
Address.sol 150 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.0) (utils/Address.sol)

pragma solidity ^0.8.20;

import {Errors} from "./Errors.sol";

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @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.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert Errors.InsufficientBalance(address(this).balance, amount);
        }

        (bool success, bytes memory returndata) = recipient.call{value: amount}("");
        if (!success) {
            _revert(returndata);
        }
    }

    /**
     * @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 or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {Errors.FailedCall} error.
     *
     * 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.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @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`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert Errors.InsufficientBalance(address(this).balance, value);
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
     * of an unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {Errors.FailedCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

    /**
     * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.
     */
    function _revert(bytes memory returndata) 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
            assembly ("memory-safe") {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert Errors.FailedCall();
        }
    }
}
IAccessControl.sol 98 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (access/IAccessControl.sol)

pragma solidity ^0.8.20;

/**
 * @dev External interface of AccessControl declared to support ERC-165 detection.
 */
interface IAccessControl {
    /**
     * @dev The `account` is missing a role.
     */
    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);

    /**
     * @dev The caller of a function is not the expected one.
     *
     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
     */
    error AccessControlBadConfirmation();

    /**
     * @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 to signal this.
     */
    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. This account bears the admin role (for the granted role).
     * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.
     */
    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 `callerConfirmation`.
     */
    function renounceRole(bytes32 role, address callerConfirmation) external;
}
Context.sol 28 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @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;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}
ERC165.sol 27 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC-165 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);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}
IERC721Receiver.sol 28 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.20;

/**
 * @title ERC-721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC-721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be
     * reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}
IERC1155Receiver.sol 59 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../../utils/introspection/IERC165.sol";

/**
 * @dev Interface that must be implemented by smart contracts in order to receive
 * ERC-1155 token transfers.
 */
interface IERC1155Receiver is IERC165 {
    /**
     * @dev Handles the receipt of a single ERC-1155 token type. This function is
     * called at the end of a `safeTransferFrom` after the balance has been updated.
     *
     * NOTE: To accept the transfer, this must return
     * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
     * (i.e. 0xf23a6e61, or its own function selector).
     *
     * @param operator The address which initiated the transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param id The ID of the token being transferred
     * @param value The amount of tokens being transferred
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
     */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external returns (bytes4);

    /**
     * @dev Handles the receipt of a multiple ERC-1155 token types. This function
     * is called at the end of a `safeBatchTransferFrom` after the balances have
     * been updated.
     *
     * NOTE: To accept the transfer(s), this must return
     * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
     * (i.e. 0xbc197c81, or its own function selector).
     *
     * @param operator The address which initiated the batch transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param ids An array containing ids of each token being transferred (order and length must match values array)
     * @param values An array containing amounts of each token being transferred (order and length must match ids array)
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
     */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external returns (bytes4);
}
Errors.sol 34 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)

pragma solidity ^0.8.20;

/**
 * @dev Collection of common custom errors used in multiple contracts
 *
 * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
 * It is recommended to avoid relying on the error API for critical functionality.
 *
 * _Available since v5.1._
 */
library Errors {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error InsufficientBalance(uint256 balance, uint256 needed);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedCall();

    /**
     * @dev The deployment failed.
     */
    error FailedDeployment();

    /**
     * @dev A necessary precompile is missing.
     */
    error MissingPrecompile(address);
}
IERC165.sol 25 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * 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[ERC 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);
}

Read Contract

CANCELLER_ROLE 0xb08e51c0 → bytes32
DEFAULT_ADMIN_ROLE 0xa217fddf → bytes32
EXECUTOR_ROLE 0x07bd0265 → bytes32
PROPOSER_ROLE 0x8f61f4f5 → bytes32
WHITELISTED_EXECUTOR_ROLE 0xa2929a5b → bytes32
getMinDelay 0xf27a0c92 → uint256
getOperationState 0x7958004c → uint8
getRoleAdmin 0x248a9ca3 → bytes32
getTimestamp 0xd45c4435 → uint256
hasRole 0x91d14854 → bool
hashOperation 0x8065657f → bytes32
hashOperationBatch 0xb1c5f427 → bytes32
isOperation 0x31d50750 → bool
isOperationDone 0x2ab0f529 → bool
isOperationPending 0x584b153e → bool
isOperationReady 0x13bc9f20 → bool
isWhitelisted 0x1c0554ba → bool
renounceRole 0x36568abe
supportsInterface 0x01ffc9a7 → bool

Write Contract 15 functions

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

addToWhitelist 0x973821a6
address target
bytes4 selector
cancel 0xc4d252f5
bytes32 id
execute 0x134008d3
address target
uint256 value
bytes data
bytes32 predecessor
bytes32 salt
executeBatch 0xe38335e5
address[] targets
uint256[] values
bytes[] payloads
bytes32 predecessor
bytes32 salt
executeWhitelisted 0x2f2f3be1
address target
uint256 value
bytes data
executeWhitelistedBatch 0x9d6bdfac
address[] targets
uint256[] values
bytes[] payloads
grantRole 0x2f2ff15d
bytes32 role
address account
onERC1155BatchReceived 0xbc197c81
address
address
uint256[]
uint256[]
bytes
returns: bytes4
onERC1155Received 0xf23a6e61
address
address
uint256
uint256
bytes
returns: bytes4
onERC721Received 0x150b7a02
address
address
uint256
bytes
returns: bytes4
removeFromWhitelist 0xfe7cdae4
address target
bytes4 selector
revokeRole 0xd547741f
bytes32 role
address account
schedule 0x01d5062a
address target
uint256 value
bytes data
bytes32 predecessor
bytes32 salt
uint256 delay
scheduleBatch 0x8f2a0bb0
address[] targets
uint256[] values
bytes[] payloads
bytes32 predecessor
bytes32 salt
uint256 delay
updateDelay 0x64d62353
uint256 newDelay

Recent Transactions

No transactions found for this address