Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0x615172e47c0C5A6dA8ea959632Ac0166f7a59eDc
Balance 0 ETH
Nonce 1
Code Size 13776 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

13776 bytes
0x60806040526004361061016a5760003560e01c80638da5cb5b116100cb578063d547741f1161007f578063f290aafa11610059578063f290aafa146103f9578063fc0c546a14610419578063fc3a7b981461044d57600080fd5b8063d547741f14610389578063e272ad3f146103a9578063e9ee1eaf146103c957600080fd5b80639dc7b023116100b05780639dc7b02314610336578063aad48d8014610356578063b23d54361461037657600080fd5b80638da5cb5b146102db57806391d148541461030657600080fd5b80634b0a8854116101225780636ccae054116101075780636ccae0541461027b57806370bab2c01461029b578063873ea755146102c857600080fd5b80634b0a88541461022e5780635b94db271461025b57600080fd5b80632f2ff15d116101535780632f2ff15d146101e45780633bd1adec14610206578063405e720a1461021b57600080fd5b806320f99c0a1461016f5780632421e155146101c0575b600080fd5b34801561017b57600080fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101cc57600080fd5b506101d660045481565b6040519081526020016101b7565b3480156101f057600080fd5b506102046101ff366004612848565b61046d565b005b34801561021257600080fd5b506102046104cc565b6102046102293660046128ba565b610528565b34801561023a57600080fd5b5061024e610249366004612962565b610679565b6040516101b791906129f5565b34801561026757600080fd5b50610204610276366004612962565b610713565b34801561028757600080fd5b50610204610296366004612a08565b6107d3565b3480156102a757600080fd5b506005546101969073ffffffffffffffffffffffffffffffffffffffff1681565b6102046102d6366004612b0d565b610871565b3480156102e757600080fd5b5060015473ffffffffffffffffffffffffffffffffffffffff16610196565b34801561031257600080fd5b50610326610321366004612848565b61097a565b60405190151581526020016101b7565b34801561034257600080fd5b50610204610351366004612ba9565b6109b5565b34801561036257600080fd5b50610204610371366004612be5565b610a5f565b610204610384366004612c2b565b610cd4565b34801561039557600080fd5b506102046103a4366004612848565b610dbc565b3480156103b557600080fd5b506102046103c4366004612d4b565b610e17565b3480156103d557600080fd5b506103266103e4366004612962565b60086020526000908152604090205460ff1681565b34801561040557600080fd5b5061024e610414366004612db7565b610fd1565b34801561042557600080fd5b506101967f00000000000000000000000083f20f44975d03b1b09e64809b757c47f942beea81565b34801561045957600080fd5b506101d6610468366004612dd0565b610fea565b60015473ffffffffffffffffffffffffffffffffffffffff1633146104be576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104c8828261108b565b5050565b60025473ffffffffffffffffffffffffffffffffffffffff16331461051d576040517f7c91ccdd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61052633611111565b565b600054600114610599576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e43590000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b60026000819055506000806106128760405180606001604052808d73ffffffffffffffffffffffffffffffffffffffff1681526020018c815260200189898080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505091525061118a565b9150915061062382602001516113e9565b610668888886868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525087925088915061148c9050565b505060016000555050505050505050565b6007602052600090815260409020805461069290612e05565b80601f01602080910402602001604051908101604052809291908181526020018280546106be90612e05565b801561070b5780601f106106e05761010080835404028352916020019161070b565b820191906000526020600020905b8154815290600101906020018083116106ee57829003601f168201915b505050505081565b60015473ffffffffffffffffffffffffffffffffffffffff163314610764576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290600090a250565b3360009081527f271b3e2292ab6fd3ff496cd98d6d375af02f11568a701741f48bba7789f13a7060205260409020547fc4c453d647953c0fd35db5a34ee76e60fb4abc3a8fb891a25936b70b38f292539060ff16610860576040517f962f633300000000000000000000000000000000000000000000000000000000815260048101829052602401610590565b61086b8484846117d1565b50505050565b6000546001146108dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e4359000000000000000000000000000000000000000000006044820152606401610590565b6002600081905550600080600080848060200190518101906108ff9190612e9d565b9350935093509350600060405180606001604052808673ffffffffffffffffffffffffffffffffffffffff168152602001858152602001838152509050606061094888836118c6565b8051602082015191945091925061095f9190611b49565b61096b85858385611bfd565b50506001600055505050505050565b600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915281205460ff165b9392505050565b600054600114610a21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f5245454e5452414e4359000000000000000000000000000000000000000000006044820152606401610590565b6002600090815580610a338484611e39565b91509150610a4981600001518260200151611b49565b610a54848484612141565b505060016000555050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610ab0576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000083f20f44975d03b1b09e64809b757c47f942beea73ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14610c5a576005546040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff91821660248201526000917f00000000000000000000000083f20f44975d03b1b09e64809b757c47f942beea169063dd62ed3e90604401602060405180830381865afa158015610b99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bbd9190612f02565b1115610c0957600554610c09907f00000000000000000000000083f20f44975d03b1b09e64809b757c47f942beea9073ffffffffffffffffffffffffffffffffffffffff1660006123fc565b8015610c5a57610c5a7f00000000000000000000000083f20f44975d03b1b09e64809b757c47f942beea837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6123fc565b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081179091556040519081527fe816c20840d998c8612f9b624b91687a80510eeb293cb09f7637379f6d73342d9060200160405180910390a15050565b6040517fd505accf000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018c90526064810185905260ff8416608482015260a4810183905260c4810182905273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000083f20f44975d03b1b09e64809b757c47f942beea169063d505accf9060e401600060405180830381600087803b158015610d8657600080fd5b505af1158015610d9a573d6000803e3d6000fd5b50505050610dae8c8c8c8c8c8c8c8c610528565b505050505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610e0d576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104c882826124cb565b60015473ffffffffffffffffffffffffffffffffffffffff163314610e68576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260005b81811015610fc957838382818110610e8657610e86612f1b565b9050602002016020810190610e9b9190612f4a565b60086000888885818110610eb157610eb1612f1b565b9050602002016020810190610ec69190612962565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790557f857309f1a328784e9fc9749624be5d32fd8e7afab58e7fe9a218dd613a37f15c868683818110610f4c57610f4c612f1b565b9050602002016020810190610f619190612962565b858584818110610f7357610f73612f1b565b9050602002016020810190610f889190612f4a565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835290151560208301520160405180910390a180610fc181612f94565b915050610e6c565b505050505050565b6006602052600090815260409020805461069290612e05565b6040517f666758ca000000000000000000000000000000000000000000000000000000008152600481018390526024810182905260009073ffffffffffffffffffffffffffffffffffffffff85169063666758ca90604401602060405180830381865afa15801561105f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110839190612f02565b949350505050565b600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b6001805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff000000000000000000000000000000000000000091821681179092556002805490911690556040517ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8790600090a250565b60408051606080820183526000808352602083015291810191909152815160609073ffffffffffffffffffffffffffffffffffffffff166111f7576040517f96bbcf1e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526008602052604090205460ff16611256576040517f5b0a758300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000083f20f44975d03b1b09e64809b757c47f942beea73ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1480156112b25750826020015134105b156112e9576040517f78f38f7600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60055473ffffffffffffffffffffffffffffffffffffffff16156113e2576005546040805160608101825273ffffffffffffffffffffffffffffffffffffffff878116825233602083015281830187905291517ff59ad990000000000000000000000000000000000000000000000000000000008152919092169163f59ad99091611377919060040161300b565b6000604051808303816000875af1158015611396573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526113dc91908101906130d9565b90925090505b9250929050565b80158061143f57507f00000000000000000000000083f20f44975d03b1b09e64809b757c47f942beea73ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee145b156114475750565b61148973ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000083f20f44975d03b1b09e64809b757c47f942beea1633308461254e565b50565b600554819073ffffffffffffffffffffffffffffffffffffffff161561158c576005546040805160808101825273ffffffffffffffffffffffffffffffffffffffff8881168252602082018890528183018790526060820186905291517f62811bf200000000000000000000000000000000000000000000000000000000815291909216916362811bf291611524919060040161313d565b6000604051808303816000875af1158015611543573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261158991908101906131dc565b90505b60007f00000000000000000000000083f20f44975d03b1b09e64809b757c47f942beea73ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146115e557346115f4565b60208201516115f49034613211565b905060008673ffffffffffffffffffffffffffffffffffffffff166374fa24a66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611643573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116679190612f02565b905060008773ffffffffffffffffffffffffffffffffffffffff1663ac0710cb848b87600001518860200151878a604001516040516020016116ac9493929190613228565b6040516020818303038152906040528b6040518563ffffffff1660e01b81526004016116da9392919061326d565b60206040518083038185885af11580156116f8573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061171d9190612f02565b9050818114611758576040517f7b7bbbe000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83516020808601516040805173ffffffffffffffffffffffffffffffffffffffff8d811682523394820194909452929093168284015260608201526080810184905290517fc74a00177d2c63e6eead5ea7936974ad9d0121f86140723b8909f8ec9662cc619181900360a00190a1505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff821661181e576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff84160161186a576118658282612639565b505050565b8273ffffffffffffffffffffffffffffffffffffffff163b6000036118bb576040517f1eb00b0600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118658383836126ae565b6040805160608181018352600080835260208301529181018290523360009081526008602052604090205460ff1661192a576040517f5b0a758300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b825173ffffffffffffffffffffffffffffffffffffffff1630148061199e57507f00000000000000000000000083f20f44975d03b1b09e64809b757c47f942beea73ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff16145b156119d5576040517f285c601600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60055473ffffffffffffffffffffffffffffffffffffffff16156113e2576005546040805160608101825233808252600090815260076020908152929020805473ffffffffffffffffffffffffffffffffffffffff9094169363cf36b9179383019190611a4190612e05565b80601f0160208091040260200160405190810160405280929190818152602001828054611a6d90612e05565b8015611aba5780601f10611a8f57610100808354040283529160200191611aba565b820191906000526020600020905b815481529060010190602001808311611a9d57829003601f168201915b50505050508152602001868152506040518263ffffffff1660e01b8152600401611ae49190613298565b6000604051808303816000875af1158015611b03573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526113dc919081019061330f565b80600003611b55575050565b7fffffffffffffffffffffffff11111111111111111111111111111111111111127f00000000000000000000000083f20f44975d03b1b09e64809b757c47f942beea73ffffffffffffffffffffffffffffffffffffffff1601611bbc576104c88282612639565b6104c873ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000083f20f44975d03b1b09e64809b757c47f942beea1683836126ae565b60055473ffffffffffffffffffffffffffffffffffffffff1615611dcf576005546040805160a0810182523380825260208083018890526000918252600790528281208054919473ffffffffffffffffffffffffffffffffffffffff169363dd19fe3893929083019190611c7090612e05565b80601f0160208091040260200160405190810160405280929190818152602001828054611c9c90612e05565b8015611ce95780601f10611cbe57610100808354040283529160200191611ce9565b820191906000526020600020905b815481529060010190602001808311611ccc57829003601f168201915b50505050508152602001868152602001858152506040518263ffffffff1660e01b8152600401611d199190613369565b6000604051808303816000875af1158015611d38573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611d7e9190810190613409565b805160008681526006602090815260409091208251939450611da6939092919091019061277d565b5060208082015133600090815260078352604090208151611dcc9391929091019061277d565b50505b80516020808301516040805133815273ffffffffffffffffffffffffffffffffffffffff909416928401929092528282015260608201859052517f9afd47907e25028cdaca89d193518c302bbb128617d5a992c5abd458155265939181900360800190a150505050565b60408051606081810183526000808352602083015291810182905273ffffffffffffffffffffffffffffffffffffffff841660009081526008602052604090205460ff16611eb3576040517f5b0a758300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082018252600085815260066020529182208054829190611ed790612e05565b80601f0160208091040260200160405190810160405280929190818152602001828054611f0390612e05565b8015611f505780601f10611f2557610100808354040283529160200191611f50565b820191906000526020600020905b815481529060010190602001808311611f3357829003601f168201915b50505050508152602001600760008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054611fa490612e05565b80601f0160208091040260200160405190810160405280929190818152602001828054611fd090612e05565b801561201d5780601f10611ff25761010080835404028352916020019161201d565b820191906000526020600020905b81548152906001019060200180831161200057829003601f168201915b50505050508152509050806000015151600003612066576040517fd3d38f6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60055460408051808201825273ffffffffffffffffffffffffffffffffffffffff88811682526020820185905291517f7afb99530000000000000000000000000000000000000000000000000000000081529190921691637afb9953916120d091906004016134de565b6000604051808303816000875af11580156120ef573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052612135919081019061330f565b90969095509350505050565b60408051808201825260008481526006602052918220805482919061216590612e05565b80601f016020809104026020016040519081016040528092919081815260200182805461219190612e05565b80156121de5780601f106121b3576101008083540402835291602001916121de565b820191906000526020600020905b8154815290600101906020018083116121c157829003601f168201915b50505050508152602001600760008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805461223290612e05565b80601f016020809104026020016040519081016040528092919081815260200182805461225e90612e05565b80156122ab5780601f10612280576101008083540402835291602001916122ab565b820191906000526020600020905b81548152906001019060200180831161228e57829003601f168201915b5050509190925250506005546040805160808101825273ffffffffffffffffffffffffffffffffffffffff8881168252602082018890528183018790526060820185905291517f1306ac3b000000000000000000000000000000000000000000000000000000008152939450911691631306ac3b9161232c91600401613519565b6000604051808303816000875af115801561234b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526123919190810190613409565b8051600085815260066020908152604090912082519394506123b9939092919091019061277d565b5060208082015173ffffffffffffffffffffffffffffffffffffffff86166000908152600783526040902081516123f59391929091019061277d565b5050505050565b60006040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508061086b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f415050524f56455f4641494c45440000000000000000000000000000000000006044820152606401610590565b600082815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551909184917f155aaafb6329a2098580462df33ec4b7441b19729b9601c5fc17ae1cf99a8a529190a35050565b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff841660248201528260448201526020600060648360008a5af13d15601f3d11600160005114161716915050806123f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152606401610590565b600080600080600085875af1905080611865576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4554485f5452414e534645525f4641494c4544000000000000000000000000006044820152606401610590565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508061086b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f5452414e534645525f4641494c454400000000000000000000000000000000006044820152606401610590565b82805461278990612e05565b90600052602060002090601f0160209004810192826127ab57600085556127f1565b82601f106127c457805160ff19168380011785556127f1565b828001600101855582156127f1579182015b828111156127f15782518255916020019190600101906127d6565b506127fd929150612801565b5090565b5b808211156127fd5760008155600101612802565b73ffffffffffffffffffffffffffffffffffffffff8116811461148957600080fd5b803561284381612816565b919050565b6000806040838503121561285b57600080fd5b82359150602083013561286d81612816565b809150509250929050565b60008083601f84011261288a57600080fd5b50813567ffffffffffffffff8111156128a257600080fd5b6020830191508360208285010111156113e257600080fd5b60008060008060008060008060c0898b0312156128d657600080fd5b88356128e181612816565b9750602089013596506040890135955060608901356128ff81612816565b9450608089013567ffffffffffffffff8082111561291c57600080fd5b6129288c838d01612878565b909650945060a08b013591508082111561294157600080fd5b5061294e8b828c01612878565b999c989b5096995094979396929594505050565b60006020828403121561297457600080fd5b81356109ae81612816565b60005b8381101561299a578181015183820152602001612982565b8381111561086b5750506000910152565b600081518084526129c381602086016020860161297f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006109ae60208301846129ab565b600080600060608486031215612a1d57600080fd5b8335612a2881612816565b92506020840135612a3881612816565b929592945050506040919091013590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612abf57612abf612a49565b604052919050565b600067ffffffffffffffff821115612ae157612ae1612a49565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60008060408385031215612b2057600080fd5b823563ffffffff81168114612b3457600080fd5b9150602083013567ffffffffffffffff811115612b5057600080fd5b8301601f81018513612b6157600080fd5b8035612b74612b6f82612ac7565b612a78565b818152866020838501011115612b8957600080fd5b816020840160208301376000602083830101528093505050509250929050565b60008060408385031215612bbc57600080fd5b8235612bc781612816565b946020939093013593505050565b8035801515811461284357600080fd5b60008060408385031215612bf857600080fd5b8235612c0381612816565b9150612c1160208401612bd5565b90509250929050565b803560ff8116811461284357600080fd5b6000806000806000806000806000806000806101408d8f031215612c4e57600080fd5b612c578d612838565b9b5060208d01359a5060408d01359950612c7360608e01612838565b985067ffffffffffffffff60808e01351115612c8e57600080fd5b612c9e8e60808f01358f01612878565b909850965067ffffffffffffffff60a08e01351115612cbc57600080fd5b612ccc8e60a08f01358f01612878565b909650945060c08d01359350612ce460e08e01612c1a565b92506101008d013591506101208d013590509295989b509295989b509295989b565b60008083601f840112612d1857600080fd5b50813567ffffffffffffffff811115612d3057600080fd5b6020830191508360208260051b85010111156113e257600080fd5b60008060008060408587031215612d6157600080fd5b843567ffffffffffffffff80821115612d7957600080fd5b612d8588838901612d06565b90965094506020870135915080821115612d9e57600080fd5b50612dab87828801612d06565b95989497509550505050565b600060208284031215612dc957600080fd5b5035919050565b600080600060608486031215612de557600080fd5b8335612df081612816565b95602085013595506040909401359392505050565b600181811c90821680612e1957607f821691505b602082108103612e52577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082601f830112612e6957600080fd5b8151612e77612b6f82612ac7565b818152846020838601011115612e8c57600080fd5b61108382602083016020870161297f565b60008060008060808587031215612eb357600080fd5b8451612ebe81612816565b809450506020850151925060408501519150606085015167ffffffffffffffff811115612eea57600080fd5b612ef687828801612e58565b91505092959194509250565b600060208284031215612f1457600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215612f5c57600080fd5b6109ae82612bd5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612fc557612fc5612f65565b5060010190565b73ffffffffffffffffffffffffffffffffffffffff815116825260208101516020830152600060408201516060604085015261108360608501826129ab565b60208152600073ffffffffffffffffffffffffffffffffffffffff8084511660208401528060208501511660408401525060408301516060808401526110836080840182612fcc565b60006060828403121561306657600080fd5b6040516060810167ffffffffffffffff828210818311171561308a5761308a612a49565b816040528293508451915061309e82612816565b8183526020850151602084015260408501519150808211156130bf57600080fd5b506130cc85828601612e58565b6040830152505092915050565b600080604083850312156130ec57600080fd5b825167ffffffffffffffff8082111561310457600080fd5b61311086838701613054565b9350602085015191508082111561312657600080fd5b5061313385828601612e58565b9150509250929050565b6020815273ffffffffffffffffffffffffffffffffffffffff8251166020820152600060208301516080604084015261317960a08401826129ab565b905060408401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808584030160608601526131b583836129ab565b92506060860151915080858403016080860152506131d38282612fcc565b95945050505050565b6000602082840312156131ee57600080fd5b815167ffffffffffffffff81111561320557600080fd5b61108384828501613054565b60008282101561322357613223612f65565b500390565b73ffffffffffffffffffffffffffffffffffffffff8516815283602082015282604082015260806060820152600061326360808301846129ab565b9695505050505050565b83815260606020820152600061328660608301856129ab565b828103604084015261326381856129ab565b6020815273ffffffffffffffffffffffffffffffffffffffff825116602082015260006020830151606060408401526132d460808401826129ab565b905060408401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160608501526131d38282612fcc565b6000806040838503121561332257600080fd5b825167ffffffffffffffff8082111561333a57600080fd5b61334686838701612e58565b9350602085015191508082111561335c57600080fd5b5061313385828601613054565b6020815273ffffffffffffffffffffffffffffffffffffffff8251166020820152602082015160408201526000604083015160a060608401526133af60c08401826129ab565b905060608401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808584030160808601526133eb83836129ab565b925060808601519150808584030160a0860152506131d38282612fcc565b60006020828403121561341b57600080fd5b815167ffffffffffffffff8082111561343357600080fd5b908301906040828603121561344757600080fd5b60405160408101818110838211171561346257613462612a49565b60405282518281111561347457600080fd5b61348087828601612e58565b82525060208301518281111561349557600080fd5b6134a187828601612e58565b60208301525095945050505050565b60008151604084526134c560408501826129ab565b9050602083015184820360208601526131d382826129ab565b6020815273ffffffffffffffffffffffffffffffffffffffff82511660208201526000602083015160408084015261108360608401826134b0565b6020815273ffffffffffffffffffffffffffffffffffffffff825116602082015260208201516040820152600060408301516080606084015261355f60a08401826129ab565b905060608401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160808501526131d382826134b056fea2646970667358221220557788e6752c1d7ecdbf7734bc4f5c467ab1082e81692db910832cbe2c77c8a164736f6c634300080d0033

Verified Source Code Partial Match

Compiler: v0.8.13+commit.abaa5c0e EVM: london Optimization: Yes (999999 runs)
Base.sol 337 lines
pragma solidity 0.8.13;

import {IMintableERC20} from "../interfaces/IMintableERC20.sol";
import {IConnector} from "../interfaces/IConnector.sol";
import "lib/solmate/src/utils/SafeTransferLib.sol";
import "../interfaces/IHook.sol";
import "../common/Errors.sol";
import "lib/solmate/src/utils/ReentrancyGuard.sol";
import "../interfaces/IBridge.sol";
import "../utils/RescueBase.sol";
import "../common/Constants.sol";

abstract contract Base is ReentrancyGuard, IBridge, RescueBase {
    address public immutable token;
    bytes32 public bridgeType;
    IHook public hook__;
    // message identifier => cache
    mapping(bytes32 => bytes) public identifierCache;

    // connector => cache
    mapping(address => bytes) public connectorCache;

    mapping(address => bool) public validConnectors;

    event ConnectorStatusUpdated(address connector, bool status);

    event HookUpdated(address newHook);

    event BridgingTokens(
        address connector,
        address sender,
        address receiver,
        uint256 amount,
        bytes32 messageId
    );
    event TokensBridged(
        address connecter,
        address receiver,
        uint256 amount,
        bytes32 messageId
    );

    constructor(address token_) AccessControl(msg.sender) {
        if (token_ != ETH_ADDRESS && token_.code.length == 0)
            revert InvalidTokenContract();
        token = token_;
        _grantRole(RESCUE_ROLE, msg.sender);
    }

    /**
     * @notice this function is used to update hook
     * @dev it can only be updated by owner
     * @dev should be carefully migrated as it can risk user funds
     * @param hook_ new hook address
     */
    function updateHook(
        address hook_,
        bool approve_
    ) external virtual onlyOwner {
        // remove the approval from the old hook
        if (token != ETH_ADDRESS) {
            if (ERC20(token).allowance(address(this), address(hook__)) > 0) {
                SafeTransferLib.safeApprove(ERC20(token), address(hook__), 0);
            }
            if (approve_) {
                SafeTransferLib.safeApprove(
                    ERC20(token),
                    hook_,
                    type(uint256).max
                );
            }
        }
        hook__ = IHook(hook_);

        emit HookUpdated(hook_);
    }

    function updateConnectorStatus(
        address[] calldata connectors,
        bool[] calldata statuses
    ) external onlyOwner {
        uint256 length = connectors.length;
        for (uint256 i; i < length; i++) {
            validConnectors[connectors[i]] = statuses[i];
            emit ConnectorStatusUpdated(connectors[i], statuses[i]);
        }
    }

    /**
     * @notice Executes pre-bridge operations before initiating a token bridge transfer.
     * @dev This internal function is called before initiating a token bridge transfer.
     * It validates the receiver address and the connector, and if a pre-hook contract is defined,
     * it executes the source pre-hook call.
     * @param connector_ The address of the connector responsible for the transfer.
     * @param transferInfo_ Information about the transfer.
     * @return transferInfo Information about the transfer after pre-bridge operations.
     * @return postHookData Data returned from the pre-hook call.
     * @dev Reverts with `ZeroAddressReceiver` if the receiver address is zero.
     * Reverts with `InvalidConnector` if the connector address is not valid.
     */
    function _beforeBridge(
        address connector_,
        TransferInfo memory transferInfo_
    )
        internal
        returns (TransferInfo memory transferInfo, bytes memory postHookData)
    {
        if (transferInfo_.receiver == address(0)) revert ZeroAddressReceiver();
        if (!validConnectors[connector_]) revert InvalidConnector();
        if (token == ETH_ADDRESS && msg.value < transferInfo_.amount)
            revert InsufficientMsgValue();

        if (address(hook__) != address(0)) {
            (transferInfo, postHookData) = hook__.srcPreHookCall(
                SrcPreHookCallParams(connector_, msg.sender, transferInfo_)
            );
        }
    }

    /**
     * @notice Executes post-bridge operations after completing a token bridge transfer.
     * @dev This internal function is called after completing a token bridge transfer.
     * It executes the source post-hook call if a hook contract is defined, calculates fees,
     * calls the outbound function of the connector, and emits an event for tokens withdrawn.
     * @param msgGasLimit_ The gas limit for the outbound call.
     * @param connector_ The address of the connector responsible for the transfer.
     * @param options_ Additional options for the outbound call.
     * @param postSrcHookData_ Data returned from the source post-hook call.
     * @param transferInfo_ Information about the transfer.
     * @dev Reverts with `MessageIdMisMatched` if the returned message ID does not match the expected message ID.
     */
    function _afterBridge(
        uint256 msgGasLimit_,
        address connector_,
        bytes memory options_,
        bytes memory postSrcHookData_,
        TransferInfo memory transferInfo_
    ) internal {
        TransferInfo memory transferInfo = transferInfo_;
        if (address(hook__) != address(0)) {
            transferInfo = hook__.srcPostHookCall(
                SrcPostHookCallParams(
                    connector_,
                    options_,
                    postSrcHookData_,
                    transferInfo_
                )
            );
        }

        uint256 fees = token == ETH_ADDRESS
            ? msg.value - transferInfo.amount
            : msg.value;

        bytes32 messageId = IConnector(connector_).getMessageId();
        bytes32 returnedMessageId = IConnector(connector_).outbound{
            value: fees
        }(
            msgGasLimit_,
            abi.encode(
                transferInfo.receiver,
                transferInfo.amount,
                messageId,
                transferInfo.data
            ),
            options_
        );
        if (returnedMessageId != messageId) revert MessageIdMisMatched();

        emit BridgingTokens(
            connector_,
            msg.sender,
            transferInfo.receiver,
            transferInfo.amount,
            messageId
        );
    }

    /**
     * @notice Executes pre-mint operations before minting tokens.
     * @dev This internal function is called before minting tokens.
     * It validates the caller as a valid connector, checks if the receiver is not this contract, the bridge contract,
     * or the token contract, and executes the destination pre-hook call if a hook contract is defined.
     * @param transferInfo_ Information about the transfer.
     * @return postHookData Data returned from the destination pre-hook call.
     * @return transferInfo Information about the transfer after pre-mint operations.
     * @dev Reverts with `InvalidConnector` if the caller is not a valid connector.
     * Reverts with `CannotTransferOrExecuteOnBridgeContracts` if the receiver is this contract, the bridge contract,
     * or the token contract.
     */
    function _beforeMint(
        uint32,
        TransferInfo memory transferInfo_
    )
        internal
        returns (bytes memory postHookData, TransferInfo memory transferInfo)
    {
        if (!validConnectors[msg.sender]) revert InvalidConnector();

        // no need of source check here, as if invalid caller, will revert with InvalidPoolId
        if (
            transferInfo_.receiver == address(this) ||
            // transferInfo_.receiver == address(bridge__) ||
            transferInfo_.receiver == token
        ) revert CannotTransferOrExecuteOnBridgeContracts();

        if (address(hook__) != address(0)) {
            (postHookData, transferInfo) = hook__.dstPreHookCall(
                DstPreHookCallParams(
                    msg.sender,
                    connectorCache[msg.sender],
                    transferInfo_
                )
            );
        }
    }

    /**
     * @notice Executes post-mint operations after minting tokens.
     * @dev This internal function is called after minting tokens.
     * It executes the destination post-hook call if a hook contract is defined and updates cache data.
     * @param messageId_ The unique identifier for the mint transaction.
     * @param postHookData_ Data returned from the destination pre-hook call.
     * @param transferInfo_ Information about the mint transaction.
     */
    function _afterMint(
        uint256,
        bytes32 messageId_,
        bytes memory postHookData_,
        TransferInfo memory transferInfo_
    ) internal {
        if (address(hook__) != address(0)) {
            CacheData memory cacheData = hook__.dstPostHookCall(
                DstPostHookCallParams(
                    msg.sender,
                    messageId_,
                    connectorCache[msg.sender],
                    postHookData_,
                    transferInfo_
                )
            );

            identifierCache[messageId_] = cacheData.identifierCache;
            connectorCache[msg.sender] = cacheData.connectorCache;
        }

        emit TokensBridged(
            msg.sender,
            transferInfo_.receiver,
            transferInfo_.amount,
            messageId_
        );
    }

    /**
     * @notice Executes pre-retry operations before retrying a failed transaction.
     * @dev This internal function is called before retrying a failed transaction.
     * It validates the connector, retrieves cache data for the given message ID,
     * and executes the pre-retry hook if defined.
     * @param connector_ The address of the connector responsible for the failed transaction.
     * @param messageId_ The unique identifier for the failed transaction.
     * @return postRetryHookData Data returned from the pre-retry hook call.
     * @return transferInfo Information about the transfer.
     * @dev Reverts with `InvalidConnector` if the connector is not valid.
     * Reverts with `NoPendingData` if there is no pending data for the given message ID.
     */
    function _beforeRetry(
        address connector_,
        bytes32 messageId_
    )
        internal
        returns (
            bytes memory postRetryHookData,
            TransferInfo memory transferInfo
        )
    {
        if (!validConnectors[connector_]) revert InvalidConnector();

        CacheData memory cacheData = CacheData(
            identifierCache[messageId_],
            connectorCache[connector_]
        );

        if (cacheData.identifierCache.length == 0) revert NoPendingData();
        (postRetryHookData, transferInfo) = hook__.preRetryHook(
            PreRetryHookCallParams(connector_, cacheData)
        );
    }

    /**
     * @notice Executes post-retry operations after retrying a failed transaction.
     * @dev This internal function is called after retrying a failed transaction.
     * It retrieves cache data for the given message ID, executes the post-retry hook if defined,
     * and updates cache data.
     * @param connector_ The address of the connector responsible for the failed transaction.
     * @param messageId_ The unique identifier for the failed transaction.
     * @param postRetryHookData Data returned from the pre-retry hook call.
     */
    function _afterRetry(
        address connector_,
        bytes32 messageId_,
        bytes memory postRetryHookData
    ) internal {
        CacheData memory cacheData = CacheData(
            identifierCache[messageId_],
            connectorCache[connector_]
        );

        (cacheData) = hook__.postRetryHook(
            PostRetryHookCallParams(
                connector_,
                messageId_,
                postRetryHookData,
                cacheData
            )
        );
        identifierCache[messageId_] = cacheData.identifierCache;
        connectorCache[connector_] = cacheData.connectorCache;
    }

    /**
     * @notice Retrieves the minimum fees required for a transaction from a connector.
     * @dev This function returns the minimum fees required for a transaction from the specified connector,
     * based on the provided message gas limit and payload size.
     * @param connector_ The address of the connector.
     * @param msgGasLimit_ The gas limit for the transaction.
     * @param payloadSize_ The size of the payload for the transaction.
     * @return totalFees The total minimum fees required for the transaction.
     */
    function getMinFees(
        address connector_,
        uint256 msgGasLimit_,
        uint256 payloadSize_
    ) external view returns (uint256 totalFees) {
        return IConnector(connector_).getMinFees(msgGasLimit_, payloadSize_);
    }
}
Vault.sol 158 lines
pragma solidity 0.8.13;

import "./Base.sol";
import "../interfaces/IConnector.sol";
import "lib/solmate/src/tokens/ERC20.sol";

/**
 * @title SuperToken
 * @notice A contract which enables bridging a token to its sibling chains.
 * @dev This contract implements ISuperTokenOrVault to support message bridging through IMessageBridge compliant contracts.
 */
contract Vault is Base {
    using SafeTransferLib for ERC20;

    // /**
    //  * @notice constructor for creating a new SuperTokenVault.
    //  * @param token_ token contract address which is to be bridged.
    //  */

    constructor(address token_) Base(token_) {
        bridgeType = token_ == ETH_ADDRESS ? NATIVE_VAULT : ERC20_VAULT;
    }

    /**
     * @notice Bridges tokens between chains.
     * @dev This function allows bridging tokens between different chains.
     * @param receiver_ The address to receive the bridged tokens.
     * @param amount_ The amount of tokens to bridge.
     * @param msgGasLimit_ The gas limit for the execution of the bridging process.
     * @param connector_ The address of the connector contract responsible for the bridge.
     * @param execPayload_ The payload for executing the bridging process on the connector.
     * @param options_ Additional options for the bridging process.
     */
    function bridge(
        address receiver_,
        uint256 amount_,
        uint256 msgGasLimit_,
        address connector_,
        bytes calldata execPayload_,
        bytes calldata options_
    ) public payable nonReentrant {
        (
            TransferInfo memory transferInfo,
            bytes memory postHookData
        ) = _beforeBridge(
                connector_,
                TransferInfo(receiver_, amount_, execPayload_)
            );

        _receiveTokens(transferInfo.amount);

        _afterBridge(
            msgGasLimit_,
            connector_,
            options_,
            postHookData,
            transferInfo
        );
    }



    /**
     * @notice Bridges tokens between chains using permit.
     * @param receiver_  The address to receive the bridged tokens.
     * @param amount_  The amount of tokens to bridge.
     * @param msgGasLimit_  The gas limit for the execution of the bridging process.
     * @param connector_  The address of the connector contract responsible for the bridge.
     * @param execPayload_  The payload for executing the bridging process on the connector.
     * @param options_  Additional options for the bridging process.
     * @param deadline_  The deadline for the permit signature.
     * @param v_  The recovery id of the permit signature.
     * @param r_  The r value of the permit signature.
     * @param s_  The s value of the permit signature.
     */
    function bridgeWithPermit(
        address receiver_,
        uint256 amount_,
        uint256 msgGasLimit_,
        address connector_,
        bytes calldata execPayload_,
        bytes calldata options_,
        uint256 deadline_,
        uint8 v_,
        bytes32 r_,
        bytes32 s_
    ) external payable  {
        ERC20(token).permit(msg.sender, address(this), amount_, deadline_, v_, r_, s_);
        bridge(receiver_, amount_, msgGasLimit_, connector_, execPayload_, options_);
    }

    /**
     * @notice Receives inbound tokens from another chain.
     * @dev This function is used to receive tokens from another chain.
     * @param siblingChainSlug_ The identifier of the sibling chain.
     * @param payload_ The payload containing the inbound tokens.
     */
    function receiveInbound(
        uint32 siblingChainSlug_,
        bytes memory payload_
    ) external payable override nonReentrant {
        (
            address receiver,
            uint256 unlockAmount,
            bytes32 messageId,
            bytes memory extraData
        ) = abi.decode(payload_, (address, uint256, bytes32, bytes));

        TransferInfo memory transferInfo = TransferInfo(
            receiver,
            unlockAmount,
            extraData
        );

        bytes memory postHookData;
        (postHookData, transferInfo) = _beforeMint(
            siblingChainSlug_,
            transferInfo
        );

        _transferTokens(transferInfo.receiver, transferInfo.amount);

        _afterMint(unlockAmount, messageId, postHookData, transferInfo);
    }

    /**
     * @notice Retry a failed transaction.
     * @dev This function allows retrying a failed transaction sent through a connector.
     * @param connector_ The address of the connector contract responsible for the failed transaction.
     * @param messageId_ The unique identifier of the failed transaction.
     */
    function retry(
        address connector_,
        bytes32 messageId_
    ) external nonReentrant {
        (
            bytes memory postRetryHookData,
            TransferInfo memory transferInfo
        ) = _beforeRetry(connector_, messageId_);
        _transferTokens(transferInfo.receiver, transferInfo.amount);

        _afterRetry(connector_, messageId_, postRetryHookData);
    }

    function _transferTokens(address receiver_, uint256 amount_) internal {
        if (amount_ == 0) return;
        if (address(token) == ETH_ADDRESS) {
            SafeTransferLib.safeTransferETH(receiver_, amount_);
        } else {
            ERC20(token).safeTransfer(receiver_, amount_);
        }
    }

    function _receiveTokens(uint256 amount_) internal {
        if (amount_ == 0 || address(token) == ETH_ADDRESS) return;
        ERC20(token).safeTransferFrom(msg.sender, address(this), amount_);
    }
}
Errors.sol 27 lines
pragma solidity 0.8.13;

error SiblingNotSupported();
error NotAuthorized();
error NotBridge();
error NotSocket();
error ConnectorUnavailable();
error InvalidPoolId();
error CannotTransferOrExecuteOnBridgeContracts();
error NoPendingData();
error MessageIdMisMatched();
error NotMessageBridge();
error InvalidSiblingChainSlug();
error InvalidTokenContract();
error InvalidExchangeRateContract();
error InvalidConnector();
error InvalidConnectorPoolId();
error ZeroAddressReceiver();
error ZeroAddress();
error ZeroAmount();
error DebtRatioTooHigh();
error NotEnoughAssets();
error VaultShutdown();
error InsufficientFunds();
error PermitDeadlineExpired();
error InvalidSigner();
error InsufficientMsgValue();
Ownable.sol 80 lines
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.13;

/**
 * @title Ownable
 * @dev The Ownable contract provides a simple way to manage ownership of a contract
 * and allows for ownership to be transferred to a nominated address.
 */
abstract contract Ownable {
    address private _owner;
    address private _nominee;

    event OwnerNominated(address indexed nominee);
    event OwnerClaimed(address indexed claimer);

    error OnlyOwner();
    error OnlyNominee();

    /**
     * @dev Sets the contract's owner to the address that is passed to the constructor.
     */
    constructor(address owner_) {
        _claimOwner(owner_);
    }

    /**
     * @dev Modifier that restricts access to only the contract's owner.
     * Throws an error if the caller is not the owner.
     */
    modifier onlyOwner() {
        if (msg.sender != _owner) revert OnlyOwner();
        _;
    }

    /**
     * @dev Returns the current owner of the contract.
     */
    function owner() external view returns (address) {
        return _owner;
    }

    /**
     * @dev Returns the current nominee for ownership of the contract.
     */
    function nominee() external view returns (address) {
        return _nominee;
    }

    /**
     * @dev Allows the current owner to nominate a new owner for the contract.
     * Throws an error if the caller is not the owner.
     * Emits an `OwnerNominated` event with the address of the nominee.
     */
    function nominateOwner(address nominee_) external {
        if (msg.sender != _owner) revert OnlyOwner();
        _nominee = nominee_;
        emit OwnerNominated(_nominee);
    }

    /**
     * @dev Allows the nominated owner to claim ownership of the contract.
     * Throws an error if the caller is not the nominee.
     * Sets the nominated owner as the new owner of the contract.
     * Emits an `OwnerClaimed` event with the address of the new owner.
     */
    function claimOwner() external {
        if (msg.sender != _nominee) revert OnlyNominee();
        _claimOwner(msg.sender);
    }

    /**
     * @dev Internal function that sets the owner of the contract to the specified address
     * and sets the nominee to address(0).
     */
    function _claimOwner(address claimer_) internal {
        _owner = claimer_;
        _nominee = address(0);
        emit OwnerClaimed(claimer_);
    }
}
Structs.sol 65 lines
pragma solidity 0.8.13;

struct UpdateLimitParams {
    bool isMint;
    address connector;
    uint256 maxLimit;
    uint256 ratePerSecond;
}

struct SrcPreHookCallParams {
    address connector;
    address msgSender;
    TransferInfo transferInfo;
}

struct SrcPostHookCallParams {
    address connector;
    bytes options;
    bytes postSrcHookData;
    TransferInfo transferInfo;
}

struct DstPreHookCallParams {
    address connector;
    bytes connectorCache;
    TransferInfo transferInfo;
}

struct DstPostHookCallParams {
    address connector;
    bytes32 messageId;
    bytes connectorCache;
    bytes postHookData;
    TransferInfo transferInfo;
}

struct PreRetryHookCallParams {
    address connector;
    CacheData cacheData;
}

struct PostRetryHookCallParams {
    address connector;
    bytes32 messageId;
    bytes postRetryHookData;
    CacheData cacheData;
}

struct TransferInfo {
    address receiver;
    uint256 amount;
    bytes data;
}

struct CacheData {
    bytes identifierCache;
    bytes connectorCache;
}

struct LimitParams {
    uint256 lastUpdateTimestamp;
    uint256 ratePerSecond;
    uint256 maxLimit;
    uint256 lastUpdateLimit;
}
Constants.sol 20 lines
pragma solidity 0.8.13;

address constant ETH_ADDRESS = address(
    0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE
);

bytes32 constant NORMAL_CONTROLLER = keccak256("NORMAL_CONTROLLER");
bytes32 constant FIAT_TOKEN_CONTROLLER = keccak256("FIAT_TOKEN_CONTROLLER");

bytes32 constant LIMIT_HOOK = keccak256("LIMIT_HOOK");
bytes32 constant LIMIT_EXECUTION_HOOK = keccak256("LIMIT_EXECUTION_HOOK");
bytes32 constant LIMIT_EXECUTION_YIELD_HOOK = keccak256(
    "LIMIT_EXECUTION_YIELD_HOOK"
);
bytes32 constant LIMIT_EXECUTION_YIELD_TOKEN_HOOK = keccak256(
    "LIMIT_EXECUTION_YIELD_TOKEN_HOOK"
);

bytes32 constant ERC20_VAULT = keccak256("ERC20_VAULT");
bytes32 constant NATIVE_VAULT = keccak256("NATIVE_VAULT");
IHook.sol 71 lines
pragma solidity ^0.8.3;
import "../common/Structs.sol";

interface IHook {
    /**
     * @notice Executes pre-hook call for source underlyingAsset.
     * @dev This function is used to execute a pre-hook call for the source underlyingAsset before initiating a transfer.
     * @param params_ Parameters for the pre-hook call.
     * @return transferInfo Information about the transfer.
     * @return postSrcHookData returned from the pre-hook call.
     */
    function srcPreHookCall(
        SrcPreHookCallParams calldata params_
    )
        external
        returns (
            TransferInfo memory transferInfo,
            bytes memory postSrcHookData
        );

    function srcPostHookCall(
        SrcPostHookCallParams calldata params_
    ) external returns (TransferInfo memory transferInfo);

    /**
     * @notice Executes pre-hook call for destination underlyingAsset.
     * @dev This function is used to execute a pre-hook call for the destination underlyingAsset before initiating a transfer.
     * @param params_ Parameters for the pre-hook call.
     */
    function dstPreHookCall(
        DstPreHookCallParams calldata params_
    )
        external
        returns (bytes memory postHookData, TransferInfo memory transferInfo);

    /**
     * @notice Executes post-hook call for destination underlyingAsset.
     * @dev This function is used to execute a post-hook call for the destination underlyingAsset after completing a transfer.
     * @param params_ Parameters for the post-hook call.
     * @return cacheData Cached data for the post-hook call.
     */
    function dstPostHookCall(
        DstPostHookCallParams calldata params_
    ) external returns (CacheData memory cacheData);

    /**
     * @notice Executes a pre-retry hook for a failed transaction.
     * @dev This function is used to execute a pre-retry hook for a failed transaction.
     * @param params_ Parameters for the pre-retry hook.
     * @return postRetryHookData Data from the post-retry hook.
     * @return transferInfo Information about the transfer.
     */
    function preRetryHook(
        PreRetryHookCallParams calldata params_
    )
        external
        returns (
            bytes memory postRetryHookData,
            TransferInfo memory transferInfo
        );

    /**
     * @notice Executes a post-retry hook for a failed transaction.
     * @dev This function is used to execute a post-retry hook for a failed transaction.
     * @param params_ Parameters for the post-retry hook.
     * @return cacheData Cached data for the post-retry hook.
     */
    function postRetryHook(
        PostRetryHookCallParams calldata params_
    ) external returns (CacheData memory cacheData);
}
RescueBase.sol 28 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;
import {RescueFundsLib} from "../libraries/RescueFundsLib.sol";
import {AccessControl} from "./AccessControl.sol";

/**
 * @title Base contract for super token and vault
 * @notice It contains relevant execution payload storages.
 * @dev This contract implements Socket's IPlug to enable message bridging and IMessageBridge
 * to support any type of message bridge.
 */
abstract contract RescueBase is AccessControl {
    bytes32 constant RESCUE_ROLE = keccak256("RESCUE_ROLE");

    /**
     * @notice Rescues funds from the contract if they are locked by mistake.
     * @param token_ The address of the token contract.
     * @param rescueTo_ The address where rescued tokens need to be sent.
     * @param amount_ The amount of tokens to be rescued.
     */
    function rescueFunds(
        address token_,
        address rescueTo_,
        uint256 amount_
    ) external onlyRole(RESCUE_ROLE) {
        RescueFundsLib.rescueFunds(token_, rescueTo_, amount_);
    }
}
IBridge.sol 19 lines
pragma solidity ^0.8.3;

interface IBridge {
    function bridge(
        address receiver_,
        uint256 amount_,
        uint256 msgGasLimit_,
        address connector_,
        bytes calldata execPayload_,
        bytes calldata options_
    ) external payable;

    function receiveInbound(
        uint32 siblingChainSlug_,
        bytes memory payload_
    ) external payable;

    function retry(address connector_, bytes32 messageId_) external;
}
ERC20.sol 206 lines
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 amount);

    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /*//////////////////////////////////////////////////////////////
                            METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    uint8 public immutable decimals;

    /*//////////////////////////////////////////////////////////////
                              ERC20 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;

    mapping(address => mapping(address => uint256)) public allowance;

    /*//////////////////////////////////////////////////////////////
                            EIP-2612 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 internal immutable INITIAL_CHAIN_ID;

    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

    mapping(address => uint256) public nonces;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals
    ) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;

        INITIAL_CHAIN_ID = block.chainid;
        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
    }

    /*//////////////////////////////////////////////////////////////
                               ERC20 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 amount) public virtual returns (bool) {
        allowance[msg.sender][spender] = amount;

        emit Approval(msg.sender, spender, amount);

        return true;
    }

    function transfer(address to, uint256 amount) public virtual returns (bool) {
        balanceOf[msg.sender] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(msg.sender, to, amount);

        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual returns (bool) {
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

        balanceOf[from] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);

        return true;
    }

    /*//////////////////////////////////////////////////////////////
                             EIP-2612 LOGIC
    //////////////////////////////////////////////////////////////*/

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        // Unchecked because the only math done is incrementing
        // the owner's nonce which cannot realistically overflow.
        unchecked {
            address recoveredAddress = ecrecover(
                keccak256(
                    abi.encodePacked(
                        "\x19\x01",
                        DOMAIN_SEPARATOR(),
                        keccak256(
                            abi.encode(
                                keccak256(
                                    "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
                                ),
                                owner,
                                spender,
                                value,
                                nonces[owner]++,
                                deadline
                            )
                        )
                    )
                ),
                v,
                r,
                s
            );

            require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
    }

    function computeDomainSeparator() internal view virtual returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                    keccak256(bytes(name)),
                    keccak256("1"),
                    block.chainid,
                    address(this)
                )
            );
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 amount) internal virtual {
        totalSupply += amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(address(0), to, amount);
    }

    function _burn(address from, uint256 amount) internal virtual {
        balanceOf[from] -= amount;

        // Cannot underflow because a user's balance
        // will never be larger than the total supply.
        unchecked {
            totalSupply -= amount;
        }

        emit Transfer(from, address(0), amount);
    }
}
AccessControl.sol 125 lines
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.13;

import "./Ownable.sol";

/**
 * @title AccessControl
 * @dev This abstract contract implements access control mechanism based on roles.
 * Each role can have one or more addresses associated with it, which are granted
 * permission to execute functions with the onlyRole modifier.
 */
abstract contract AccessControl is Ownable {
    /**
     * @dev A mapping of roles to a mapping of addresses to boolean values indicating whether or not they have the role.
     */
    mapping(bytes32 => mapping(address => bool)) private _permits;

    /**
     * @dev Emitted when a role is granted to an address.
     */
    event RoleGranted(bytes32 indexed role, address indexed grantee);

    /**
     * @dev Emitted when a role is revoked from an address.
     */
    event RoleRevoked(bytes32 indexed role, address indexed revokee);

    /**
     * @dev Error message thrown when an address does not have permission to execute a function with onlyRole modifier.
     */
    error NoPermit(bytes32 role);

    /**
     * @dev Constructor that sets the owner of the contract.
     */
    constructor(address owner_) Ownable(owner_) {}

    /**
     * @dev Modifier that restricts access to addresses having roles
     * Throws an error if the caller do not have permit
     */
    modifier onlyRole(bytes32 role) {
        if (!_permits[role][msg.sender]) revert NoPermit(role);
        _;
    }

    /**
     * @dev Checks and reverts if an address do not have a specific role.
     * @param role_ The role to check.
     * @param address_ The address to check.
     */
    function _checkRole(bytes32 role_, address address_) internal virtual {
        if (!_hasRole(role_, address_)) revert NoPermit(role_);
    }

    /**
     * @dev Grants a role to a given address.
     * @param role_ The role to grant.
     * @param grantee_ The address to grant the role to.
     * Emits a RoleGranted event.
     * Can only be called by the owner of the contract.
     */
    function grantRole(
        bytes32 role_,
        address grantee_
    ) external virtual onlyOwner {
        _grantRole(role_, grantee_);
    }

    /**
     * @dev Revokes a role from a given address.
     * @param role_ The role to revoke.
     * @param revokee_ The address to revoke the role from.
     * Emits a RoleRevoked event.
     * Can only be called by the owner of the contract.
     */
    function revokeRole(
        bytes32 role_,
        address revokee_
    ) external virtual onlyOwner {
        _revokeRole(role_, revokee_);
    }

    /**
     * @dev Internal function to grant a role to a given address.
     * @param role_ The role to grant.
     * @param grantee_ The address to grant the role to.
     * Emits a RoleGranted event.
     */
    function _grantRole(bytes32 role_, address grantee_) internal {
        _permits[role_][grantee_] = true;
        emit RoleGranted(role_, grantee_);
    }

    /**
     * @dev Internal function to revoke a role from a given address.
     * @param role_ The role to revoke.
     * @param revokee_ The address to revoke the role from.
     * Emits a RoleRevoked event.
     */
    function _revokeRole(bytes32 role_, address revokee_) internal {
        _permits[role_][revokee_] = false;
        emit RoleRevoked(role_, revokee_);
    }

    /**
     * @dev Checks whether an address has a specific role.
     * @param role_ The role to check.
     * @param address_ The address to check.
     * @return A boolean value indicating whether or not the address has the role.
     */
    function hasRole(
        bytes32 role_,
        address address_
    ) external view returns (bool) {
        return _hasRole(role_, address_);
    }

    function _hasRole(
        bytes32 role_,
        address address_
    ) internal view returns (bool) {
        return _permits[role_][address_];
    }
}
IConnector.sol 18 lines
pragma solidity ^0.8.13;

interface IConnector {
    function outbound(
        uint256 msgGasLimit_,
        bytes memory payload_,
        bytes memory options_
    ) external payable returns (bytes32 messageId_);

    function siblingChainSlug() external view returns (uint32);

    function getMinFees(
        uint256 msgGasLimit_,
        uint256 payloadSize_
    ) external view returns (uint256 totalFees);

    function getMessageId() external view returns (bytes32);
}
RescueFundsLib.sol 46 lines
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.13;

import "lib/solmate/src/utils/SafeTransferLib.sol";
import "lib/solmate/src/tokens/ERC20.sol";

error ZeroAddress();

/**
 * @title RescueFundsLib
 * @dev A library that provides a function to rescue funds from a contract.
 */

library RescueFundsLib {
    /**
     * @dev The address used to identify ETH.
     */
    address public constant ETH_ADDRESS =
        address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);

    /**
     * @dev thrown when the given token address don't have any code
     */
    error InvalidTokenAddress();

    /**
     * @dev Rescues funds from a contract.
     * @param token_ The address of the token contract.
     * @param rescueTo_ The address of the user.
     * @param amount_ The amount of tokens to be rescued.
     */
    function rescueFunds(
        address token_,
        address rescueTo_,
        uint256 amount_
    ) internal {
        if (rescueTo_ == address(0)) revert ZeroAddress();

        if (token_ == ETH_ADDRESS) {
            SafeTransferLib.safeTransferETH(rescueTo_, amount_);
        } else {
            if (token_.code.length == 0) revert InvalidTokenAddress();
            SafeTransferLib.safeTransfer(ERC20(token_), rescueTo_, amount_);
        }
    }
}
IMintableERC20.sol 7 lines
pragma solidity 0.8.13;

interface IMintableERC20 {
    function mint(address receiver_, uint256 amount_) external;

    function burn(address burner_, uint256 amount_) external;
}
ReentrancyGuard.sol 19 lines
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Gas optimized reentrancy protection for smart contracts.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ReentrancyGuard.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol)
abstract contract ReentrancyGuard {
    uint256 private locked = 1;

    modifier nonReentrant() virtual {
        require(locked == 1, "REENTRANCY");

        locked = 2;

        _;

        locked = 1;
    }
}
SafeTransferLib.sol 128 lines
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

import {ERC20} from "../tokens/ERC20.sol";

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
    /*//////////////////////////////////////////////////////////////
                             ETH OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferETH(address to, uint256 amount) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Transfer the ETH and store if it succeeded or not.
            success := call(gas(), to, amount, 0, 0, 0, 0)
        }

        require(success, "ETH_TRANSFER_FAILED");
    }

    /*//////////////////////////////////////////////////////////////
                            ERC20 OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferFrom(
        ERC20 token,
        address from,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument.
            mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
            )
        }

        require(success, "TRANSFER_FROM_FAILED");
    }

    function safeTransfer(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "TRANSFER_FAILED");
    }

    function safeApprove(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "APPROVE_FAILED");
    }
}

Read Contract

bridgeType 0x2421e155 → bytes32
connectorCache 0x4b0a8854 → bytes
getMinFees 0xfc3a7b98 → uint256
hasRole 0x91d14854 → bool
hook__ 0x70bab2c0 → address
identifierCache 0xf290aafa → bytes
nominee 0x20f99c0a → address
owner 0x8da5cb5b → address
token 0xfc0c546a → address
validConnectors 0xe9ee1eaf → bool

Write Contract 11 functions

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

bridge 0x405e720a
address receiver_
uint256 amount_
uint256 msgGasLimit_
address connector_
bytes execPayload_
bytes options_
bridgeWithPermit 0xb23d5436
address receiver_
uint256 amount_
uint256 msgGasLimit_
address connector_
bytes execPayload_
bytes options_
uint256 deadline_
uint8 v_
bytes32 r_
bytes32 s_
claimOwner 0x3bd1adec
No parameters
grantRole 0x2f2ff15d
bytes32 role_
address grantee_
nominateOwner 0x5b94db27
address nominee_
receiveInbound 0x873ea755
uint32 siblingChainSlug_
bytes payload_
rescueFunds 0x6ccae054
address token_
address rescueTo_
uint256 amount_
retry 0x9dc7b023
address connector_
bytes32 messageId_
revokeRole 0xd547741f
bytes32 role_
address revokee_
updateConnectorStatus 0xe272ad3f
address[] connectors
bool[] statuses
updateHook 0xaad48d80
address hook_
bool approve_

Recent Transactions

No transactions found for this address