Address Contract Verified
Address
0xFF031cc2563988Bc4afA29E2cD7Bcc2d389900a5
Balance
0 ETH
Nonce
1
Code Size
14771 bytes
Creator
0x4ed740A2...2aAa at tx 0x5d2e1926...16c8dc
Indexed Transactions
0
Contract Bytecode
14771 bytes
0x60806040526004361061014f5760003560e01c80637f5a22f9116100b6578063bce53d241161006f578063bce53d2414610402578063d7fc2da414610422578063d8b964e614610442578063d904371e14610472578063e30c397814610492578063f2fde38b146104b057600080fd5b80637f5a22f9146103185780638da5cb5b146103385780639178bd70146103565780639ccef96f14610376578063a3c573eb146103b5578063a7931169146103d557600080fd5b80633f07fe0d116101085780633f07fe0d1461026a5780634e36b11c1461028a578063536f4cfe146102ae578063715018a6146102ce57806378e3214f146102e357806379ba50971461030357600080fd5b80630babd8641461015b57806311c4b77214610198578063227c5412146101ba5780632344e655146101fa5780632c9e34211461021a5780633bbd64bc1461023a57600080fd5b3661015657005b600080fd5b34801561016757600080fd5b5060025461017b906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101a457600080fd5b506101b86101b33660046127a9565b6104d0565b005b3480156101c657600080fd5b506101ea6101d53660046127e0565b60046020526000908152604090205460ff1681565b604051901515815260200161018f565b34801561020657600080fd5b506101b861021536600461285f565b6104e6565b34801561022657600080fd5b506101b86102353660046128fd565b6107fb565b34801561024657600080fd5b506101ea6102553660046129c4565b60086020526000908152604090205460ff1681565b34801561027657600080fd5b506101b86102853660046129e1565b61098e565b34801561029657600080fd5b506102a060075481565b60405190815260200161018f565b3480156102ba57600080fd5b506101b86102c9366004612a86565b610c0c565b3480156102da57600080fd5b506101b8610c47565b3480156102ef57600080fd5b506101b86102fe366004612a9f565b610c5b565b34801561030f57600080fd5b506101b8610c6e565b34801561032457600080fd5b506101ea6103333660046129c4565b610ced565b34801561034457600080fd5b506000546001600160a01b031661017b565b34801561036257600080fd5b506101b8610371366004612acb565b610d0b565b34801561038257600080fd5b50610396610391366004612d99565b610d9e565b604080516001600160a01b03909316835260208301919091520161018f565b3480156103c157600080fd5b5060065461017b906001600160a01b031681565b3480156103e157600080fd5b506102a06103f0366004612a86565b60096020526000908152604090205481565b34801561040e57600080fd5b5061039661041d366004612e91565b610dda565b34801561042e57600080fd5b506101b861043d3660046129c4565b610e16565b34801561044e57600080fd5b506101ea61045d3660046129c4565b60036020526000908152604090205460ff1681565b34801561047e57600080fd5b506101b861048d366004612eea565b610e27565b34801561049e57600080fd5b506001546001600160a01b031661017b565b3480156104bc57600080fd5b506101b86104cb3660046129c4565b610f73565b6104d8610fe4565b6104e2828261103e565b5050565b6104ee61109b565b6006546001600160a01b03163314610519576040516303d6041760e41b815260040160405180910390fd5b60008061052883850185612f6f565b915091508051825161053a9190612fde565b60000361055a576040516312cd5ab760e11b815260040160405180910390fd5b6000610569888b8b8a8a6110f4565b905061057d816040015182600001516111ee565b6101408301526101208201526007548351156106a6576000848060200190518101906105a9919061305a565b60208101516001600160a01b0316608085015290506001825a11156106645730639ccef96f845a6105da91906131f0565b86516040808901516101408a015191516001600160e01b031960e087901b16815261060b9392908990600401613245565b604080518083038160008887f193505050508015610646575060408051601f3d908101601f1916820190925261064391810190613361565b60015b15610664576001600160a01b03909116602086015260608501525060005b80156106a3576106988e8560e00151866000015185600001518860400151876020015188606001518b61016001518d611237565b5050505050506107e7565b50505b825115610794576000838060200190518101906106c3919061338f565b60808401519091506001600160a01b03166106ec576080808201516001600160a01b0316908401525b815a1115610792573063bce53d24835a61070691906131f0565b83866020015187606001516040518563ffffffff1660e01b815260040161072f9392919061344a565b604080518083038160008887f19350505050801561076a575060408051601f3d908101601f1916820190925261076791810190613361565b60015b15610792576001600160a01b0391821660a086015260c0850152608080830151909116908401525b505b8160c00151826060015111156107ca576107ca826020015183608001518460c0015185606001516107c591906131f0565b6112d1565b6107d88261012001516113d8565b6107e28c836113f9565b505050505b6107f16001600555565b5050505050505050565b61080361109b565b3360009081526008602052604090205460ff166108335760405163f5b06b4160e01b815260040160405180910390fd5b6001600160a01b03851661084657600080fd5b60006108558a8a8a88886110f4565b6001600160a01b0387166080820181905260e082015182516040808501516101608601519151959650600095610895958e9390918b908b906020016134bb565b60408051601f19818403018152918152815160209283012060008f8152600990935291205490915081146108dc57604051635603eb5160e11b815260040160405180910390fd5b6108f38260000151836080015184604001516112d1565b600960008d81526020019081526020016000206000905581608001516001600160a01b031682600001516001600160a01b03168d7f7097a92401cb3cede25c9b17516e7ac039f9b02ac27d72e269b2aad16a4ca8f585604001518660e0015187610100015188610160015160405161096e949392919061352a565b60405180910390a450506109826001600555565b50505050505050505050565b61099661109b565b3360009081526008602052604090205460ff166109c65760405163f5b06b4160e01b815260040160405180910390fd5b60008390036109e8576040516312cd5ab760e11b815260040160405180910390fd5b60006109f78a8a8a8a8a6110f4565b90506000610a0785870187613559565b6020808201516001600160a01b03166080850181905260e0850151855184516040808901516101608a01519151979850600097610a539795969495939491939192918d918d91016134bb565b60405160208183030381529060405280519060200120905080600960008f81526020019081526020016000205414610a9e57604051635603eb5160e11b815260040160405180910390fd5b610ab0836040015184600001516111ee565b610140850181905261012085019190915283516040850151610ad29285611481565b60608501526001600160a01b031660208401528315610ba7576007546000610afc8688018861358d565b9050815a1115610ba4573063bce53d24835a610b1891906131f0565b83886020015189606001516040518563ffffffff1660e01b8152600401610b419392919061344a565b604080518083038160008887f193505050508015610b7c575060408051601f3d908101601f19168201909252610b7991810190613361565b60015b15610ba4576001600160a01b0391821660a088015260c0870152608080830151909116908601525b50505b8260c0015183606001511115610bd857610bd8836020015184608001518560c0015186606001516107c591906131f0565b610be68361012001516113d8565b60008d815260096020526040812055610bff8d846113f9565b5050506109826001600555565b610c14610fe4565b600781905560405181907ff47543a7cab136b12cca0a2ecd728c9d1943f57b923b98db48725d2b76dd4da990600090a250565b610c4f610fe4565b610c59600061154a565b565b610c63610fe4565b6104e28233836112d1565b60015433906001600160a01b03168114610ce15760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b610cea8161154a565b50565b6000610cf7610fe4565b610d0082611563565b50600190505b919050565b610d13610fe4565b6001600160a01b038216610d3a5760405163538ba4f960e01b815260040160405180910390fd5b6001600160a01b038216600081815260086020908152604091829020805460ff19168515159081179091558251938452908301527fd963701e30b9d04e85bfbf92c227f5d0b832d24c25598c3fbeeae8761d6ded9591015b60405180910390a15050565b600080333014610dc157604051632ee47ea160e11b815260040160405180910390fd5b610dcd86868686611481565b9097909650945050505050565b600080333014610dfd57604051632ee47ea160e11b815260040160405180910390fd5b84519150610e0c8385876115dc565b9050935093915050565b610e1e610fe4565b610cea81611771565b610e2f610fe4565b6000829003610e5157604051630239912560e01b815260040160405180910390fd5b60005b82811015610f6d57610e95848483818110610e7157610e716135c1565b9050602002016020810190610e8691906129c4565b6001600160a01b03163b151590565b610eb2576040516308ebd80360e11b815260040160405180910390fd5b8160036000868685818110610ec957610ec96135c1565b9050602002016020810190610ede91906129c4565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055811515848483818110610f1b57610f1b6135c1565b9050602002016020810190610f3091906129c4565b6001600160a01b03167f1f478f1e5aee36a892d86e821aba410dc0934cb0ebd0241dd75370833884545360405160405180910390a3600101610e54565b50505050565b610f7b610fe4565b600180546001600160a01b0383166001600160a01b03199091168117909155610fac6000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6000546001600160a01b03163314610c595760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610cd8565b6001600160e01b03198216600081815260046020908152604091829020805460ff19168515159081179091558251938452908301527fc4a5aadd92b2d0e7efaf25f9d44b0e6fca6c44da8e09fc3250cc12ef954cb60e9101610d92565b6002600554036110ed5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610cd8565b6002600555565b61117c60405180610180016040528060006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160006001600160a01b0316815260200160006001600160a01b031681526020016000815260200160008152602001600081526020016000815260200160008152602001606081525090565b6001600160a01b03851680825260408083018690526020808401929092526060830186905260e08301889052466101008401528051601f850183900483028101830190915283815290849084908190840183828082843760009201919091525050505061016082015295945050505050565b60008060006111fd84306117e3565b905084811015611220576040516319af26f360e31b815260040160405180910390fd5b47925061122d85826131f0565b9150509250929050565b60008888888888878760405160200161125697969594939291906135d7565b60408051601f19818403018152828252805160209182012060008e8152600990925291902081905591508a907fd457b25e0e458857e38c937f68af3100c40afd88fc5522c5820440d07b44351f906112bd908c908c908c908c908c908c908c908c9061364d565b60405180910390a250505050505050505050565b6112da83611877565b156112ee576112e982826118b0565b505050565b46632b6653dc8114801561131e575073a614f803b6fd780986a42c78ec9c7f77e6ded13c6001600160a01b038516145b156113c457604080516001600160a01b038581166024830152604480830186905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291519186169161137a91906136b9565b6000604051808303816000865af19150503d80600081146113b7576040519150601f19603f3d011682016040523d82523d6000602084013e6113bc565b606091505b505050610f6d565b610f6d6001600160a01b03851684846119c9565b80471015610cea57604051630cfbd6ed60e01b815260040160405180910390fd5b8060a001516001600160a01b031681608001516001600160a01b0316837f593e4dbcb8f7312fc3bdd77e2095da131a6e1993f37752d12576d04e1f7253b484600001518560200151866040015187606001518860c001518960e001518a61010001518b61016001516040516114759897969594939291906136d5565b60405180910390a45050565b805160006001600160a01b03808316908716036114b4576040516001624cdd6d60e11b0319815260040160405180910390fd5b60006114c48460000151306117e3565b90506114d1878786611a2c565b806114e08560000151306117e3565b6114ea91906131f0565b91508360600151821015611511576040516319af26f360e31b815260040160405180910390fd5b60008561151e89306117e3565b61152891906131f0565b9050801561153f5761153f888660400151836112d1565b505094509492505050565b600180546001600160a01b0319169055610cea81611ca5565b60006001600160a01b0382163b61158d576040516308ebd80360e11b815260040160405180910390fd5b600680546001600160a01b0319166001600160a01b0384169081179091556040517f53b7c37d01415b2804281f4684b0722e0b01fbd375bf502609f465e17ab4441e90600090a2506001919050565b60006115e883306117e3565b604083015160a08401519192509060238211156116055785828201525b83516116119082611cf5565b600061161c86611877565b1561168b5784600001516001600160a01b0316878360405161163e91906136b9565b60006040518083038185875af1925050503d806000811461167b576040519150601f19603f3d011682016040523d82523d6000602084013e611680565b606091505b505080915050611734565b86156116ab5760208501516116ab906001600160a01b0388169089611dfe565b84600001516001600160a01b03168560600151836040516116cc91906136b9565b60006040518083038185875af1925050503d8060008114611709576040519150601f19603f3d011682016040523d82523d6000602084013e61170e565b606091505b50909150508615611734576020850151611734906001600160a01b038816906000611eab565b8061175257604051637588692960e01b815260040160405180910390fd5b61175c86306117e3565b61176690856131f0565b979650505050505050565b6001600160a01b0381163b611799576040516308ebd80360e11b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0383169081179091556040517f556b8b8772c1552cbcc67f9bb7c7fd60934af593e54ec7aa4e8b2683632675f890600090a250565b60006117ee83611877565b1561180457506001600160a01b03811631611871565b6040516370a0823160e01b81526001600160a01b0383811660048301528416906370a0823190602401602060405180830381865afa15801561184a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061186e919061371f565b90505b92915050565b60006001600160a01b038216158061187157506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1492915050565b804710156119005760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610cd8565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461194d576040519150601f19603f3d011682016040523d82523d6000602084013e611952565b606091505b50509050806112e95760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610cd8565b6040516001600160a01b0383166024820152604481018290526112e990849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611fc0565b6080810151516000819003611a5457604051630239912560e01b815260040160405180910390fd5b6000806000611a6886858760800151612095565b608088015192955090935091506000611a8089611877565b905060005b86811015610982578415611b7d5780600003611b0e5783611ad65784838281518110611ab357611ab36135c1565b6020026020010151606001818151611acb91906131f0565b915081815250611b08565b84838281518110611ae957611ae96135c1565b6020026020010151606001818151611b019190612fde565b9150818152505b50611b7d565b83611b495785838281518110611b2657611b266135c1565b6020026020010151606001818151611b3e91906131f0565b915081815250611b7b565b85838281518110611b5c57611b5c6135c1565b6020026020010151606001818151611b749190612fde565b9150818152505b505b81611bda57611bda838281518110611b9757611b976135c1565b602002602001015160400151848381518110611bb557611bb56135c1565b6020026020010151606001518c6001600160a01b0316611dfe9092919063ffffffff16565b611c5c838281518110611bef57611bef6135c1565b60200260200101516000015183858481518110611c0e57611c0e6135c1565b6020026020010151602001518d878681518110611c2d57611c2d6135c1565b602002602001015160600151888781518110611c4b57611c4b6135c1565b602002602001015160800151612175565b81611c9d57611c9d838281518110611c7657611c766135c1565b60200260200101516040015160008c6001600160a01b0316611eab9092919063ffffffff16565b600101611a85565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6002546001600160a01b039081169083168114801590611d2e57506001600160a01b03831660009081526003602052604090205460ff16155b15611d4c5760405163369370d960e01b815260040160405180910390fd5b6000611d5783612207565b6001600160e01b0319811660009081526004602052604090205490915060ff1615611d9557604051630d1a468960e01b815260040160405180910390fd5b816001600160a01b0316846001600160a01b031603610f6d576001600160e01b03198116632e1a7d4d60e01b14801590611de057506001600160e01b03198116630d0e30db60e41b14155b15610f6d57604051630d1a468960e01b815260040160405180910390fd5b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301526000919085169063dd62ed3e90604401602060405180830381865afa158015611e4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e72919061371f565b9050610f6d8463095ea7b360e01b85611e8b8686612fde565b6040516001600160a01b03909216602483015260448201526064016119f5565b801580611f255750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611eff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f23919061371f565b155b611f905760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610cd8565b6040516001600160a01b0383166024820152604481018290526112e990849063095ea7b360e01b906064016119f5565b6000612015826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166122229092919063ffffffff16565b90508051600014806120365750808060200190518101906120369190613738565b6112e95760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610cd8565b6000808080805b868110156120d7578581815181106120b6576120b66135c1565b602002602001015160600151826120cd9190612fde565b915060010161209c565b50868111156121235760009150816120ef88836131f0565b90506120fb8782613755565b94506121078786613777565b61211190826131f0565b61211b9086612fde565b93505061216b565b8681101561216b5760019150600061213b82896131f0565b90506121478782613755565b94506121538786613777565b61215d90826131f0565b6121679086612fde565b9350505b5093509350939050565b6000600487600581111561218b5761218b613203565b036121a35761219c85848885612239565b90506121e0565b60058760058111156121b7576121b7613203565b036121c75761219c84848461237c565b6040516318f9c3a760e11b815260040160405180910390fd5b806121fe57604051636ff55bbf60e01b815260040160405180910390fd5b50505050505050565b6000815160000361221a57506000919050565b506020015190565b6060612231848460008561261a565b949350505050565b600080600083806020019051810190612252919061378e565b8151919350915060005b8181101561229a576000848281518110612278576122786135c1565b6020026020010151905060238111156122915788818501525b5060010161225c565b506122a58883611cf5565b851561231157876001600160a01b031687836040516122c491906136b9565b60006040518083038185875af1925050503d8060008114612301576040519150601f19603f3d011682016040523d82523d6000602084013e612306565b606091505b505080945050612371565b876001600160a01b03168260405161232991906136b9565b6000604051808303816000865af19150503d8060008114612366576040519150601f19603f3d011682016040523d82523d6000602084013e61236b565b606091505b50909450505b505050949350505050565b60008082806020019051810190612393919061383f565b905060005b81518110156126115780156123f1576123ce8282815181106123bc576123bc6135c1565b602002602001015160200151306117e3565b94508181815181106123e2576123e26135c1565b60200260200101516020015195505b6000828281518110612405576124056135c1565b60200260200101516080015190506000838381518110612427576124276135c1565b602002602001015160000151905060238111156124445786818301525b61246b848481518110612459576124596135c1565b60200260200101516040015183611cf5565b61247488611877565b156124fc5783838151811061248b5761248b6135c1565b6020026020010151604001516001600160a01b031687836040516124af91906136b9565b60006040518083038185875af1925050503d80600081146124ec576040519150601f19603f3d011682016040523d82523d6000602084013e6124f1565b606091505b5050809550506125fb565b821561253d5761253d848481518110612517576125176135c1565b602002602001015160600151888a6001600160a01b0316611dfe9092919063ffffffff16565b83838151811061254f5761254f6135c1565b6020026020010151604001516001600160a01b03168260405161257291906136b9565b6000604051808303816000865af19150503d80600081146125af576040519150601f19603f3d011682016040523d82523d6000602084013e6125b4565b606091505b509095505082156125fb576125fb8484815181106125d4576125d46135c1565b60200260200101516060015160008a6001600160a01b0316611eab9092919063ffffffff16565b84612607575050612611565b5050600101612398565b50509392505050565b60608247101561267b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610cd8565b600080866001600160a01b0316858760405161269791906136b9565b60006040518083038185875af1925050503d80600081146126d4576040519150601f19603f3d011682016040523d82523d6000602084013e6126d9565b606091505b5091509150611766878383876060831561275457825160000361274d576001600160a01b0385163b61274d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610cd8565b5081612231565b61223183838151156127695781518083602001fd5b8060405162461bcd60e51b8152600401610cd8919061396a565b80356001600160e01b031981168114610d0657600080fd5b8015158114610cea57600080fd5b600080604083850312156127bc57600080fd5b6127c583612783565b915060208301356127d58161279b565b809150509250929050565b6000602082840312156127f257600080fd5b6127fb82612783565b9392505050565b6001600160a01b0381168114610cea57600080fd5b60008083601f84011261282957600080fd5b5081356001600160401b0381111561284057600080fd5b60208301915083602082850101111561285857600080fd5b9250929050565b60008060008060008060008060c0898b03121561287b57600080fd5b88359750602089013561288d81612802565b9650604089013595506060890135945060808901356001600160401b03808211156128b757600080fd5b6128c38c838d01612817565b909650945060a08b01359150808211156128dc57600080fd5b506128e98b828c01612817565b999c989b5096995094979396929594505050565b6000806000806000806000806000806101008b8d03121561291d57600080fd5b8a35995060208b0135985060408b013561293681612802565b975060608b0135965060808b013561294d81612802565b955060a08b013561295d81612802565b945060c08b01356001600160401b038082111561297957600080fd5b6129858e838f01612817565b909650945060e08d013591508082111561299e57600080fd5b506129ab8d828e01612817565b915080935050809150509295989b9194979a5092959850565b6000602082840312156129d657600080fd5b81356127fb81612802565b60008060008060008060008060008060e08b8d031215612a0057600080fd5b8a35995060208b0135985060408b0135612a1981612802565b975060608b0135965060808b01356001600160401b0380821115612a3c57600080fd5b612a488e838f01612817565b909850965060a08d0135915080821115612a6157600080fd5b612a6d8e838f01612817565b909650945060c08d013591508082111561299e57600080fd5b600060208284031215612a9857600080fd5b5035919050565b60008060408385031215612ab257600080fd5b8235612abd81612802565b946020939093013593505050565b60008060408385031215612ade57600080fd5b82356127c581612802565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612b2157612b21612ae9565b60405290565b60405160c081016001600160401b0381118282101715612b2157612b21612ae9565b604051601f8201601f191681016001600160401b0381118282101715612b7157612b71612ae9565b604052919050565b60006001600160401b03821115612b9257612b92612ae9565b5060051b60200190565b60068110610cea57600080fd5b60006001600160401b03821115612bc257612bc2612ae9565b50601f01601f191660200190565b600082601f830112612be157600080fd5b8135612bf4612bef82612ba9565b612b49565b818152846020838601011115612c0957600080fd5b816020850160208301376000918101602001919091529392505050565b600060a08284031215612c3857600080fd5b612c40612aff565b90508135612c4d81612802565b8152602082810135612c5e81612802565b828201526040830135612c7081612802565b6040830152606083810135818401526080808501356001600160401b0380821115612c9a57600080fd5b818701915087601f830112612cae57600080fd5b8135612cbc612bef82612b79565b81815260059190911b8301860190868101908a831115612cdb57600080fd5b8785015b83811015612d8557803585811115612cf75760008081fd5b860160a0818e03601f19011215612d0e5760008081fd5b612d16612aff565b8a820135612d2381612b9c565b81526040820135612d3381612802565b818c0152818a0135612d4481612802565b6040820152818901358a82015260a082013587811115612d645760008081fd5b612d728f8d83860101612bd0565b828b015250845250918801918801612cdf565b506080890152509598975050505050505050565b60008060008060808587031215612daf57600080fd5b8435612dba81612802565b9350602085013592506040850135915060608501356001600160401b03811115612de357600080fd5b612def87828801612c26565b91505092959194509250565b600060c08284031215612e0d57600080fd5b612e15612b27565b90508135612e2281612802565b81526020820135612e3281612802565b8060208301525060408201356040820152606082013560608201526080820135612e5b81612802565b608082015260a08201356001600160401b03811115612e7957600080fd5b612e8584828501612bd0565b60a08301525092915050565b600080600060608486031215612ea657600080fd5b83356001600160401b03811115612ebc57600080fd5b612ec886828701612dfb565b9350506020840135612ed981612802565b929592945050506040919091013590565b600080600060408486031215612eff57600080fd5b83356001600160401b0380821115612f1657600080fd5b818601915086601f830112612f2a57600080fd5b813581811115612f3957600080fd5b8760208260051b8501011115612f4e57600080fd5b60209283019550935050840135612f648161279b565b809150509250925092565b60008060408385031215612f8257600080fd5b82356001600160401b0380821115612f9957600080fd5b612fa586838701612bd0565b93506020850135915080821115612fbb57600080fd5b5061122d85828601612bd0565b634e487b7160e01b600052601160045260246000fd5b8082018082111561187157611871612fc8565b60005b8381101561300c578181015183820152602001612ff4565b50506000910152565b600082601f83011261302657600080fd5b8151613034612bef82612ba9565b81815284602083860101111561304957600080fd5b612231826020830160208701612ff1565b6000602080838503121561306d57600080fd5b82516001600160401b038082111561308457600080fd5b9084019060a0828703121561309857600080fd5b6130a0612aff565b82516130ab81612802565b8152828401516130ba81612802565b8185015260408301516130cc81612802565b604082015260608381015190820152608080840151838111156130ee57600080fd5b80850194505087601f85011261310357600080fd5b8351613111612bef82612b79565b81815260059190911b8501860190868101908a83111561313057600080fd5b8787015b838110156131dc5780518781111561314c5760008081fd5b880160a0818e03601f190112156131635760008081fd5b61316b612aff565b8a82015161317881612b9c565b8152604082015161318881612802565b818c0152606082015161319a81612802565b604082015281870151606082015260a0820151898111156131bb5760008081fd5b6131c98f8d83860101613015565b8289015250845250918801918801613134565b506080850152509198975050505050505050565b8181038181111561187157611871612fc8565b634e487b7160e01b600052602160045260246000fd5b60008151808452613231816020860160208601612ff1565b601f01601f19169290920160200192915050565b6000608060018060a01b03808816845260208781860152604087604087015260606080606088015261012087018489511660808901528389015160a086821660a08b01528660408c01511660c08b015260608b015160e08b015260808b0151915060a06101008b01528282518085526101409450848c019150848160051b8d0101945087840193506000805b82811015613349578d870361013f19018452855180516006811061330357634e487b7160e01b84526021600452602484fd5b8852808b01518c168b890152898101518c168a89015288810151898901528c01518c880186905261333686890182613219565b97505094890194928901926001016132d1565b50505050505080965050505050505095945050505050565b6000806040838503121561337457600080fd5b825161337f81612802565b6020939093015192949293505050565b6000602082840312156133a157600080fd5b81516001600160401b03808211156133b857600080fd5b9083019060c082860312156133cc57600080fd5b6133d4612b27565b82516133df81612802565b815260208301516133ef81612802565b806020830152506040830151604082015260608301516060820152608083015161341881612802565b608082015260a08301518281111561342f57600080fd5b61343b87828601613015565b60a08301525095945050505050565b60608152600060018060a01b03808651166060840152806020870151166080840152604086015160a0840152606086015160c08401528060808701511660e084015260a086015160c06101008501526134a7610120850182613219565b959091166020840152505060400152919050565b88815260006bffffffffffffffffffffffff19808a60601b166020840152808960601b166034840152876048840152808760601b16606884015250845161350981607c850160208901612ff1565b82018385607c83013760009301607c01928352509098975050505050505050565b84815283602082015282604082015260806060820152600061354f6080830184613219565b9695505050505050565b60006020828403121561356b57600080fd5b81356001600160401b0381111561358157600080fd5b61223184828501612c26565b60006020828403121561359f57600080fd5b81356001600160401b038111156135b557600080fd5b61223184828501612dfb565b634e487b7160e01b600052603260045260246000fd5b87815260006bffffffffffffffffffffffff19808960601b166020840152808860601b166034840152866048840152808660601b16606884015250835161362581607c850160208801612ff1565b83519083019061363c81607c840160208801612ff1565b01607c019998505050505050505050565b8881526001600160a01b0388811660208301528781166040830152606082018790528516608082015260a0810184905261010060c0820181905260009061369683820186613219565b905082810360e08401526136aa8185613219565b9b9a5050505050505050505050565b600082516136cb818460208701612ff1565b9190910192915050565b600061010060018060a01b03808c168452808b166020850152508860408401528760608401528660808401528560a08401528460c08401528060e08401526136aa81840185613219565b60006020828403121561373157600080fd5b5051919050565b60006020828403121561374a57600080fd5b81516127fb8161279b565b60008261377257634e487b7160e01b600052601260045260246000fd5b500490565b808202811582820484141761187157611871612fc8565b600080604083850312156137a157600080fd5b82516001600160401b03808211156137b857600080fd5b818501915085601f8301126137cc57600080fd5b815160206137dc612bef83612b79565b82815260059290921b840181019181810190898411156137fb57600080fd5b948201945b8386101561381957855182529482019490820190613800565b9188015191965090935050508082111561383257600080fd5b5061122d85828601613015565b6000602080838503121561385257600080fd5b82516001600160401b038082111561386957600080fd5b818501915085601f83011261387d57600080fd5b815161388b612bef82612b79565b81815260059190911b830184019084810190888311156138aa57600080fd5b8585015b8381101561395d578051858111156138c65760008081fd5b860160a0818c03601f19018113156138de5760008081fd5b6138e6612aff565b8983015181526040808401516138fb81612802565b828c015260608481015161390e81612802565b808385015250608091508185015161392581612802565b9083015291830151918883111561393c5760008081fd5b61394a8e8c85870101613015565b90820152855250509186019186016138ae565b5098975050505050505050565b6020815260006127fb602083018461321956fea26469706673582212200945cd72fa8444fcfa9ab4968d0693ae88f4c28bc5dc5f7d0b5fbd779a89f67564736f6c63430008190033
Verified Source Code Full Match
Compiler: v0.8.25+commit.b61c2a91
EVM: london
Optimization: Yes (200 runs)
IButterReceiver.sol 14 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IButterReceiver {
//_srcToken received token (wtoken or erc20 token)
function onReceived(
bytes32 _orderId,
address _srcToken,
uint256 _amount,
uint256 _fromChain,
bytes calldata _from,
bytes calldata _payload
) external;
}
Ownable.sol 83 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
Ownable2Step.sol 57 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)
pragma solidity ^0.8.0;
import "./Ownable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2Step is Ownable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() public virtual {
address sender = _msgSender();
require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
_transferOwnership(sender);
}
}
ReentrancyGuard.sol 77 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @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 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;
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
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// 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;
}
}
IERC20Permit.sol 60 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
IERC20.sol 78 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
SafeERC20.sol 143 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
Address.sol 244 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
Context.sol 24 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
SwapCall.sol 329 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.25;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "../lib/Errors.sol";
abstract contract SwapCall {
using SafeERC20 for IERC20;
using Address for address;
address internal constant ZERO_ADDRESS = address(0);
address internal constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
address public wToken;
// uint256 internal nativeBalanceBeforeExec;
// uint256 internal initInputTokenBalance;
mapping(address => bool) public approved;
mapping(bytes4 => bool) public funcBlackList;
event EditFuncBlackList(bytes4 _func, bool flag);
event SetWrappedToken(address indexed _wToken);
enum DexType {
AGG,
UNIV2,
UNIV3,
CURVE,
FILL,
MIX
}
struct CallbackParam {
address target;
address approveTo;
uint256 offset;
uint256 extraNativeAmount;
address receiver;
bytes data;
}
struct SwapParam {
address dstToken;
address receiver;
address leftReceiver;
uint256 minAmount;
SwapData[] swaps;
}
struct SwapData {
DexType dexType;
address callTo;
address approveTo;
uint256 fromAmount;
bytes callData;
}
constructor(address _wToken) payable {
_setWToken(_wToken);
//| a9059cbb | transfer(address,uint256)
funcBlackList[bytes4(0xa9059cbb)] = true;
//| 095ea7b3 | approve(address,uint256) |
funcBlackList[bytes4(0x095ea7b3)] = true;
//| 23b872dd | transferFrom(address,address,uint256) |
funcBlackList[bytes4(0x23b872dd)] = true;
//| 39509351 | increaseAllowance(address,uint256)
funcBlackList[bytes4(0x39509351)] = true;
//| a22cb465 | setApprovalForAll(address,bool) |
funcBlackList[bytes4(0xa22cb465)] = true;
//| 42842e0e | safeTransferFrom(address,address,uint256) |
funcBlackList[bytes4(0x42842e0e)] = true;
//| b88d4fde | safeTransferFrom(address,address,uint256,bytes) |
funcBlackList[bytes4(0xb88d4fde)] = true;
//| 9bd9bbc6 | send(address,uint256,bytes) |
funcBlackList[bytes4(0x9bd9bbc6)] = true;
//| fe9d9303 | burn(uint256,bytes) |
funcBlackList[bytes4(0xfe9d9303)] = true;
//| 959b8c3f | authorizeOperator
funcBlackList[bytes4(0x959b8c3f)] = true;
//| f242432a | safeTransferFrom(address,address,uint256,uint256,bytes) |
funcBlackList[bytes4(0xf242432a)] = true;
//| 2eb2c2d6 | safeBatchTransferFrom(address,address,uint256[],uint256[],bytes) |
funcBlackList[bytes4(0x2eb2c2d6)] = true;
}
function _editFuncBlackList(bytes4 _func, bool _flag) internal {
funcBlackList[_func] = _flag;
emit EditFuncBlackList(_func, _flag);
}
function _setWToken(address _wToken) internal {
if (!_wToken.isContract()) revert Errors.NOT_CONTRACT();
wToken = _wToken;
emit SetWrappedToken(_wToken);
}
function _afterCheck(uint256 nativeBalanceBeforeExec) internal view {
if (address(this).balance < nativeBalanceBeforeExec) revert Errors.NATIVE_VALUE_OVERSPEND();
}
function _swap(
address _token,
uint256 _amount,
uint256 _initBalance,
SwapParam memory swapParam
) internal returns (address _dstToken, uint256 _dstAmount) {
_dstToken = swapParam.dstToken;
if (_token == _dstToken) revert Errors.SWAP_SAME_TOKEN();
uint256 finalTokenAmount = _getBalance(swapParam.dstToken, address(this));
_doSwap(_token, _amount, swapParam);
_dstAmount = _getBalance(swapParam.dstToken, address(this)) - finalTokenAmount;
if (_dstAmount < swapParam.minAmount) revert Errors.RECEIVE_LOW();
uint256 left = _getBalance(_token, address(this)) - _initBalance;
if (left != 0) {
_transfer(_token, swapParam.leftReceiver, left);
}
}
function _callBack(
uint256 _amount,
address _token,
CallbackParam memory callParam
) internal returns (uint256 _callAmount) {
_callAmount = _getBalance(_token, address(this));
uint256 offset = callParam.offset;
bytes memory callPayload = callParam.data;
if (offset > 35) {
//32 length + 4 funcSig
assembly {
mstore(add(callPayload, offset), _amount)
}
}
_checkApprove(callParam.target, callPayload);
bool _result;
if (_isNative(_token)) {
(_result, ) = callParam.target.call{value: _amount}(callPayload);
} else {
if (_amount != 0) IERC20(_token).safeIncreaseAllowance(callParam.approveTo, _amount);
// this contract not save money make sure send value can cover this
(_result, ) = callParam.target.call{value: callParam.extraNativeAmount}(callPayload);
if (_amount != 0) IERC20(_token).safeApprove(callParam.approveTo, 0);
}
if (!_result) revert Errors.CALL_BACK_FAIL();
_callAmount = _callAmount - _getBalance(_token, address(this));
}
function _checkApprove(address _callTo, bytes memory _calldata) private view {
address wTokenAddr = wToken;
if (_callTo != wTokenAddr && (!approved[_callTo])) revert Errors.NO_APPROVE();
bytes4 sig = _getFirst4Bytes(_calldata);
if (funcBlackList[sig]) revert Errors.CALL_FUNC_BLACK_LIST();
if (_callTo == wTokenAddr) {
if (sig != bytes4(0x2e1a7d4d) && sig != bytes4(0xd0e30db0)) revert Errors.CALL_FUNC_BLACK_LIST();
}
}
function _doSwap(address _token, uint256 _amount, SwapParam memory swapParam) internal {
uint256 len = swapParam.swaps.length;
if (len == 0) revert Errors.EMPTY();
(uint256 amountAdjust, uint256 firstAdjust, bool isUp) = _rebuildSwaps(_amount, len, swapParam.swaps);
SwapData[] memory _swaps = swapParam.swaps;
bool isNative = _isNative(_token);
for (uint i = 0; i < len; ) {
if (firstAdjust != 0) {
if (i == 0) {
isUp ? _swaps[i].fromAmount += firstAdjust : _swaps[i].fromAmount -= firstAdjust;
} else {
isUp ? _swaps[i].fromAmount += amountAdjust : _swaps[i].fromAmount -= amountAdjust;
}
}
if (!isNative) {
IERC20(_token).safeIncreaseAllowance(_swaps[i].approveTo, _swaps[i].fromAmount);
}
_execute(_swaps[i].dexType, isNative, _swaps[i].callTo, _token, _swaps[i].fromAmount, _swaps[i].callData);
if (!isNative) {
IERC20(_token).safeApprove(_swaps[i].approveTo, 0);
}
unchecked {
i++;
}
}
}
function _rebuildSwaps(
uint256 _amount,
uint256 _len,
SwapData[] memory _swaps
) private pure returns (uint256 amountAdjust, uint256 firstAdjust, bool isUp) {
uint256 total = 0;
for (uint256 i = 0; i < _len; i++) {
total += _swaps[i].fromAmount;
}
if (total > _amount) {
isUp = false;
uint256 margin = total - _amount;
amountAdjust = margin / _len;
firstAdjust = amountAdjust + (margin - amountAdjust * _len);
} else if (total < _amount) {
isUp = true;
uint256 margin = _amount - total;
amountAdjust = margin / _len;
firstAdjust = amountAdjust + (margin - amountAdjust * _len);
}
}
function _execute(
DexType _dexType,
bool _native,
address _router,
address _srcToken,
uint256 _amount,
bytes memory _swapData
) internal {
bool _result;
if (_dexType == DexType.FILL) {
(_result) = _makeAggFill(_router, _amount, _native, _swapData);
} else if (_dexType == DexType.MIX) {
(_result) = _makeMixSwap(_srcToken, _amount, _swapData);
} else {
revert Errors.UNSUPPORT_DEX_TYPE();
}
if (!_result) revert Errors.SWAP_FAIL();
}
struct MixSwap {
uint256 offset;
address srcToken;
address callTo;
address approveTo;
bytes callData;
}
function _makeMixSwap(address _srcToken, uint256 _amount, bytes memory _swapData) internal returns (bool _result) {
MixSwap[] memory mixSwaps = abi.decode(_swapData, (MixSwap[]));
for (uint256 i = 0; i < mixSwaps.length; i++) {
if (i != 0) {
_amount = _getBalance(mixSwaps[i].srcToken, address(this));
_srcToken = mixSwaps[i].srcToken;
}
bytes memory callData = mixSwaps[i].callData;
uint256 offset = mixSwaps[i].offset;
if (offset > 35) {
//32 length + 4 funcSig
assembly {
mstore(add(callData, offset), _amount)
}
}
_checkApprove(mixSwaps[i].callTo, callData);
if (_isNative(_srcToken)) {
(_result, ) = mixSwaps[i].callTo.call{value: _amount}(callData);
} else {
if (i != 0) {
IERC20(_srcToken).safeIncreaseAllowance(mixSwaps[i].approveTo, _amount);
}
(_result, ) = mixSwaps[i].callTo.call(callData);
if (i != 0) {
IERC20(_srcToken).safeApprove(mixSwaps[i].approveTo, 0);
}
}
if (!_result) {
break;
}
}
}
function _makeAggFill(
address _router,
uint256 _amount,
bool native,
bytes memory _swapData
) internal returns (bool _result) {
(uint256[] memory offsets, bytes memory callData) = abi.decode(_swapData, (uint256[], bytes));
uint256 len = offsets.length;
for (uint i = 0; i < len; i++) {
uint256 offset = offsets[i];
if (offset > 35) {
//32 length + 4 funcSig
assembly {
mstore(add(callData, offset), _amount)
}
}
}
_checkApprove(_router, callData);
if (native) {
(_result, ) = _router.call{value: _amount}(callData);
} else {
(_result, ) = _router.call(callData);
}
}
function _isNative(address token) internal pure returns (bool) {
return (token == ZERO_ADDRESS || token == NATIVE_ADDRESS);
}
function _getBalance(address _token, address _account) internal view returns (uint256) {
if (_isNative(_token)) {
return _account.balance;
} else {
return IERC20(_token).balanceOf(_account);
}
}
function _transfer(address _token, address _to, uint256 _amount) internal {
if (_isNative(_token)) {
Address.sendValue(payable(_to), _amount);
} else {
uint256 _chainId = block.chainid;
if (_chainId == 728126428 && _token == 0xa614f803B6FD780986A42c78Ec9c7f77e6DeD13C) {
// Tron USDT
_token.call(abi.encodeWithSelector(0xa9059cbb, _to, _amount));
} else {
IERC20(_token).safeTransfer(_to, _amount);
}
}
}
function _getFirst4Bytes(bytes memory data) internal pure returns (bytes4 outBytes4) {
if (data.length == 0) {
return 0x0;
}
assembly {
outBytes4 := mload(add(data, 32))
}
}
}
Errors.sol 24 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;
library Errors {
error NOT_CONTRACT();
error SWAP_FAIL();
error CALL_BACK_FAIL();
error ZERO_IN();
error FEE_MISMATCH();
error FEE_LOWER();
error ZERO_ADDRESS();
error RECEIVE_LOW();
error CALL_AMOUNT_INVALID();
error BRIDGE_ONLY();
error DATA_EMPTY();
error NO_APPROVE();
error NATIVE_VALUE_OVERSPEND();
error EMPTY();
error UNSUPPORT_DEX_TYPE();
error SWAP_SAME_TOKEN();
error CANNOT_ADJUST();
error SELF_ONLY();
error CALL_FUNC_BLACK_LIST();
}
Receiver.sol 387 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.25;
import "@openzeppelin/contracts/access/Ownable2Step.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@butternetwork/bridge/contracts/interface/IButterReceiver.sol";
import "./abstract/SwapCall.sol";
contract Receiver is Ownable2Step, SwapCall, ReentrancyGuard, IButterReceiver {
using SafeERC20 for IERC20;
using Address for address;
address public bridgeAddress;
uint256 public gasForReFund = 80000;
mapping(address => bool) public keepers;
mapping(bytes32 => bytes32) public storedFailedSwap;
error ONLY_KEEPER();
error INVALID_EXEC_PARAM();
// use to solve deep stack
struct SwapTemp {
address srcToken;
address swapToken;
uint256 srcAmount;
uint256 swapAmount;
address receiver;
address target;
uint256 callAmount;
uint256 fromChain;
uint256 toChain;
uint256 nativeBalance;
uint256 inputBalance;
bytes from;
}
event RemoteSwapAndCall(
bytes32 indexed orderId,
address indexed receiver,
address indexed target,
address originToken,
address swapToken,
uint256 originAmount,
uint256 swapAmount,
uint256 callAmount,
uint256 fromChain,
uint256 toChain,
bytes from
);
event SwapRescueFunds(
bytes32 indexed orderId,
address indexed token,
address indexed receiver,
uint256 amount,
uint256 fromChain,
uint256 toChain,
bytes from
);
event Approve(address indexed executor, bool indexed flag);
event SetBridgeAddress(address indexed _bridgeAddress);
event SetGasForReFund(uint256 indexed _gasForReFund);
event UpdateKeepers(address _keeper, bool _flag);
constructor(address _owner, address _wToken, address _bridgeAddress) payable SwapCall(_wToken) {
if (_owner == address(0)) revert Errors.ZERO_ADDRESS();
_setBridgeAddress(_bridgeAddress);
_transferOwnership(_owner);
}
function setAuthorization(address[] calldata _executors, bool _flag) external onlyOwner {
if (_executors.length == 0) revert Errors.EMPTY();
for (uint i = 0; i < _executors.length; i++) {
if (!_executors[i].isContract()) revert Errors.NOT_CONTRACT();
approved[_executors[i]] = _flag;
emit Approve(_executors[i], _flag);
}
}
function updateKeepers(address _keeper, bool _flag) external onlyOwner {
if (_keeper == address(0)) revert Errors.ZERO_ADDRESS();
keepers[_keeper] = _flag;
emit UpdateKeepers(_keeper, _flag);
}
function setBridgeAddress(address _bridgeAddress) public onlyOwner returns (bool) {
_setBridgeAddress(_bridgeAddress);
return true;
}
function setGasForReFund(uint256 _gasForReFund) external onlyOwner {
gasForReFund = _gasForReFund;
emit SetGasForReFund(_gasForReFund);
}
function setWToken(address _wToken) external onlyOwner {
_setWToken(_wToken);
}
function editFuncBlackList(bytes4 _func, bool _flag) external onlyOwner {
_editFuncBlackList(_func, _flag);
}
// _srcToken must erc20 Token or wToken
function onReceived(
bytes32 _orderId,
address _srcToken,
uint256 _amount,
uint256 _fromChain,
bytes calldata _from,
bytes calldata _swapAndCall
) external override nonReentrant {
if (msg.sender != bridgeAddress) revert Errors.BRIDGE_ONLY();
(bytes memory _swapData, bytes memory _callbackData) = abi.decode(_swapAndCall, (bytes, bytes));
if ((_swapData.length + _callbackData.length) == 0) revert Errors.DATA_EMPTY();
SwapTemp memory swapTemp = _assignment(_fromChain, _srcToken, _amount, _from);
(swapTemp.nativeBalance, swapTemp.inputBalance) = _checkBalance(swapTemp.srcAmount, swapTemp.srcToken);
uint256 minExecGas = gasForReFund;
if (_swapData.length > 0) {
SwapParam memory swap = abi.decode(_swapData, (SwapParam));
swapTemp.receiver = swap.receiver;
bool needStore = true;
if (gasleft() > minExecGas) {
try
this.remoteSwap{gas: (gasleft() - minExecGas)}(
swapTemp.srcToken,
swapTemp.srcAmount,
swapTemp.inputBalance,
swap
)
returns (address dstToken, uint256 dstAmount) {
swapTemp.swapToken = dstToken;
swapTemp.swapAmount = dstAmount;
needStore = false;
} catch {}
}
if (needStore) {
_store(
_orderId,
swapTemp.fromChain,
swapTemp.srcToken,
swap.dstToken,
swapTemp.srcAmount,
swap.receiver,
swap.minAmount,
swapTemp.from,
_callbackData
);
return;
}
}
if (_callbackData.length > 0) {
CallbackParam memory callParam = abi.decode(_callbackData, (CallbackParam));
if (swapTemp.receiver == address(0)) {
swapTemp.receiver = callParam.receiver;
}
if (gasleft() > minExecGas) {
try
this.remoteCall{gas: (gasleft() - minExecGas)}(callParam, swapTemp.swapToken, swapTemp.swapAmount)
returns (address target, uint256 callAmount) {
swapTemp.target = target;
swapTemp.callAmount = callAmount;
swapTemp.receiver = callParam.receiver;
} catch {}
}
}
if (swapTemp.swapAmount > swapTemp.callAmount) {
_transfer(swapTemp.swapToken, swapTemp.receiver, (swapTemp.swapAmount - swapTemp.callAmount));
}
_afterCheck(swapTemp.nativeBalance);
_emitRemoteSwapAndCall(_orderId, swapTemp);
}
function swapRescueFunds(
bytes32 _orderId,
uint256 _fromChain,
address _srcToken,
uint256 _amount,
address _dscToken,
address _receiver,
bytes calldata _from,
bytes calldata _callbackData
) external nonReentrant {
if (!keepers[msg.sender]) revert ONLY_KEEPER();
require(_receiver != address(0));
SwapTemp memory swapTemp = _assignment(_fromChain, _srcToken, _amount, _from);
swapTemp.receiver = _receiver;
bytes32 hash = keccak256(
abi.encodePacked(
swapTemp.fromChain,
swapTemp.srcToken,
_dscToken,
swapTemp.srcAmount,
swapTemp.receiver,
swapTemp.from,
_callbackData
)
);
if (storedFailedSwap[_orderId] != hash) revert INVALID_EXEC_PARAM();
_transfer(swapTemp.srcToken, swapTemp.receiver, swapTemp.srcAmount);
delete storedFailedSwap[_orderId];
emit SwapRescueFunds(
_orderId,
swapTemp.srcToken,
swapTemp.receiver,
swapTemp.srcAmount,
swapTemp.fromChain,
swapTemp.toChain,
swapTemp.from
);
}
function execSwap(
bytes32 _orderId,
uint256 _fromChain,
address _srcToken,
uint256 _amount,
bytes calldata _from,
bytes calldata _swapData,
bytes calldata _callbackData
) external nonReentrant {
if (!keepers[msg.sender]) revert ONLY_KEEPER();
if (_swapData.length == 0) revert Errors.DATA_EMPTY();
SwapTemp memory swapTemp = _assignment(_fromChain, _srcToken, _amount, _from);
SwapParam memory swap = abi.decode(_swapData, (SwapParam));
swapTemp.receiver = swap.receiver;
bytes32 hash = keccak256(
abi.encodePacked(
swapTemp.fromChain,
swapTemp.srcToken,
swap.dstToken,
swapTemp.srcAmount,
swapTemp.receiver,
swapTemp.from,
_callbackData
)
);
if (storedFailedSwap[_orderId] != hash) revert INVALID_EXEC_PARAM();
(swapTemp.nativeBalance, swapTemp.inputBalance) = _checkBalance(swapTemp.srcAmount, swapTemp.srcToken);
(swapTemp.swapToken, swapTemp.swapAmount) = _swap(
swapTemp.srcToken,
swapTemp.srcAmount,
swapTemp.inputBalance,
swap
);
if (_callbackData.length > 0) {
uint256 minExecGas = gasForReFund;
CallbackParam memory callParam = abi.decode(_callbackData, (CallbackParam));
if (gasleft() > minExecGas) {
try
this.remoteCall{gas: (gasleft() - minExecGas)}(callParam, swapTemp.swapToken, swapTemp.swapAmount)
returns (address target, uint256 callAmount) {
swapTemp.target = target;
swapTemp.callAmount = callAmount;
swapTemp.receiver = callParam.receiver;
} catch {}
}
}
if (swapTemp.swapAmount > swapTemp.callAmount) {
_transfer(swapTemp.swapToken, swapTemp.receiver, (swapTemp.swapAmount - swapTemp.callAmount));
}
_afterCheck(swapTemp.nativeBalance);
delete storedFailedSwap[_orderId];
_emitRemoteSwapAndCall(_orderId, swapTemp);
}
function _assignment(
uint256 _fromChain,
address _srcToken,
uint256 _amount,
bytes calldata _from
) private view returns (SwapTemp memory swapTemp) {
swapTemp.srcToken = _srcToken;
swapTemp.srcAmount = _amount;
swapTemp.swapToken = _srcToken;
swapTemp.swapAmount = _amount;
swapTemp.fromChain = _fromChain;
swapTemp.toChain = block.chainid;
swapTemp.from = _from;
}
function _emitRemoteSwapAndCall(bytes32 _orderId, SwapTemp memory swapTemp) private {
emit RemoteSwapAndCall(
_orderId,
swapTemp.receiver,
swapTemp.target,
swapTemp.srcToken,
swapTemp.swapToken,
swapTemp.srcAmount,
swapTemp.swapAmount,
swapTemp.callAmount,
swapTemp.fromChain,
swapTemp.toChain,
swapTemp.from
);
}
function _checkBalance(
uint256 _amount,
address _srcToken
) private view returns (uint256 nativeBalance, uint256 inputBalance) {
uint256 balance = _getBalance(_srcToken, address(this));
if (balance < _amount) revert Errors.RECEIVE_LOW();
nativeBalance = address(this).balance;
inputBalance = balance - _amount;
}
function remoteSwap(
address _srcToken,
uint256 _amount,
uint256 _initBalance,
SwapParam memory swapParam
) external returns (address dstToken, uint256 dstAmount) {
if (msg.sender != address(this)) revert Errors.SELF_ONLY();
(dstToken, dstAmount) = _swap(_srcToken, _amount, _initBalance, swapParam);
}
function remoteCall(
CallbackParam memory _callbackParam,
address _callToken,
uint256 _amount
) external returns (address target, uint256 callAmount) {
if (msg.sender != address(this)) revert Errors.SELF_ONLY();
target = _callbackParam.target;
callAmount = _callBack(_amount, _callToken, _callbackParam);
}
event SwapFailed(
bytes32 indexed _orderId,
uint256 _fromChain,
address _srcToken,
address _dscToken,
uint256 _amount,
address _receiver,
uint256 _minReceived,
bytes _from,
bytes _callData
);
function _store(
bytes32 _orderId,
uint256 _fromChain,
address _srcToken,
address _dstToken,
uint256 _amount,
address _receiver,
uint256 _minReceived,
bytes memory _from,
bytes memory _callbackData
) private {
bytes32 hash = keccak256(
abi.encodePacked(_fromChain, _srcToken, _dstToken, _amount, _receiver, _from, _callbackData)
);
storedFailedSwap[_orderId] = hash;
emit SwapFailed(_orderId, _fromChain, _srcToken, _dstToken, _amount, _receiver, _minReceived, _from, _callbackData);
}
function _setBridgeAddress(address _bridgeAddress) internal returns (bool) {
if (!_bridgeAddress.isContract()) revert Errors.NOT_CONTRACT();
bridgeAddress = _bridgeAddress;
emit SetBridgeAddress(_bridgeAddress);
return true;
}
function rescueFunds(address _token, uint256 _amount) external onlyOwner {
_transfer(_token, msg.sender, _amount);
}
receive() external payable {}
}
Read Contract
approved 0xd8b964e6 → bool
bridgeAddress 0xa3c573eb → address
funcBlackList 0x227c5412 → bool
gasForReFund 0x4e36b11c → uint256
keepers 0x3bbd64bc → bool
owner 0x8da5cb5b → address
pendingOwner 0xe30c3978 → address
storedFailedSwap 0xa7931169 → bytes32
wToken 0x0babd864 → address
Write Contract 15 functions
These functions modify contract state and require a wallet transaction to execute.
acceptOwnership 0x79ba5097
No parameters
editFuncBlackList 0x11c4b772
bytes4 _func
bool _flag
execSwap 0x3f07fe0d
bytes32 _orderId
uint256 _fromChain
address _srcToken
uint256 _amount
bytes _from
bytes _swapData
bytes _callbackData
onReceived 0x2344e655
bytes32 _orderId
address _srcToken
uint256 _amount
uint256 _fromChain
bytes _from
bytes _swapAndCall
remoteCall 0x74da61de
tuple _callbackParam
address _callToken
uint256 _amount
returns: address, uint256
remoteSwap 0xea4e58ec
address _srcToken
uint256 _amount
uint256 _initBalance
tuple swapParam
returns: address, uint256
renounceOwnership 0x715018a6
No parameters
rescueFunds 0x78e3214f
address _token
uint256 _amount
setAuthorization 0xd904371e
address[] _executors
bool _flag
setBridgeAddress 0x7f5a22f9
address _bridgeAddress
returns: bool
setGasForReFund 0x536f4cfe
uint256 _gasForReFund
setWToken 0xd7fc2da4
address _wToken
swapRescueFunds 0x2c9e3421
bytes32 _orderId
uint256 _fromChain
address _srcToken
uint256 _amount
address _dscToken
address _receiver
bytes _from
bytes _callbackData
transferOwnership 0xf2fde38b
address newOwner
updateKeepers 0x9178bd70
address _keeper
bool _flag
Token Balances (3)
View Transfers →Recent Transactions
No transactions found for this address