Address Contract Verified
Address
0xD73dcF03279Fb3a2A64c7584dF038Fbc1D29258F
Balance
0 ETH
Nonce
1
Code Size
22723 bytes
Creator
0xA491D9b7...093d at tx 0x19673450...effb0b
Indexed Transactions
0
Contract Bytecode
22723 bytes
0x6080604052600436106101185760003560e01c806384536017116100a0578063c4d797f211610064578063c4d797f2146103ba578063c62173d0146103e5578063d47a1a2714610422578063e086e5ec1461044b578063f2fde38b146104625761016d565b806384536017146102fb578063893d20e814610312578063894760691461033d578063a4e2d63414610366578063a9059cbb146103915761016d565b80633fa02c4a116100e75780633fa02c4a1461022c57806361a623cf1461025557806361dadfdb1461027e5780636568a279146102a75780636e947298146102d05761016d565b80632d79cf42146101725780632de33b0d1461019d5780633a9b52ad146101c65780633aecd0e3146101ef5761016d565b3661016d573373ffffffffffffffffffffffffffffffffffffffff167f85177f287940f2f05425a4029951af0e047a7f9c4eaa9a6e6917bcd869f866953460405161016391906153cd565b60405180910390a2005b600080fd5b34801561017e57600080fd5b5061018761048b565b60405161019491906153cd565b60405180910390f35b3480156101a957600080fd5b506101c460048036038101906101bf9190614d20565b610491565b005b3480156101d257600080fd5b506101ed60048036038101906101e89190614efd565b610fb2565b005b3480156101fb57600080fd5b5061021660048036038101906102119190614c33565b6110cb565b60405161022391906153cd565b60405180910390f35b34801561023857600080fd5b50610253600480360381019061024e9190614dc0565b6111cc565b005b34801561026157600080fd5b5061027c60048036038101906102779190614cc0565b61153e565b005b34801561028a57600080fd5b506102a560048036038101906102a09190614c60565b611c2a565b005b3480156102b357600080fd5b506102ce60048036038101906102c99190614dc0565b611e0a565b005b3480156102dc57600080fd5b506102e5611f3a565b6040516102f291906153cd565b60405180910390f35b34801561030757600080fd5b50610310611f42565b005b34801561031e57600080fd5b506103276121be565b6040516103349190615253565b60405180910390f35b34801561034957600080fd5b50610364600480360381019061035f9190614c33565b6121e7565b005b34801561037257600080fd5b5061037b612575565b604051610388919061535a565b60405180910390f35b34801561039d57600080fd5b506103b860048036038101906103b39190614d80565b61258b565b005b3480156103c657600080fd5b506103cf612773565b6040516103dc91906153cd565b60405180910390f35b3480156103f157600080fd5b5061040c60048036038101906104079190614e87565b61277d565b604051610419919061535a565b60405180910390f35b34801561042e57600080fd5b5061044960048036038101906104449190614e0d565b61279a565b005b34801561045757600080fd5b506104606129f1565b005b34801561046e57600080fd5b5061048960048036038101906104849190614c33565b612c6d565b005b60015481565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610516576040517f717bf7f800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060149054906101000a900460ff161561055d576040517fc5f2be5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600060146101000a81548160ff021916908315150217905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156105df576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082829050141561061d576040517fcc05479100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101f482829050111561065c576040517f2cdedf1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82829050811015610b70573683838381811061067e5761067d6156b6565b5b9050608002019050600073ffffffffffffffffffffffffffffffffffffffff168160000160208101906106b19190614c33565b73ffffffffffffffffffffffffffffffffffffffff1614156107c3578060600160208101906106e09190614c33565b73ffffffffffffffffffffffffffffffffffffffff168160200160208101906107099190614c33565b73ffffffffffffffffffffffffffffffffffffffff168260000160208101906107329190614c33565b73ffffffffffffffffffffffffffffffffffffffff167fc5547ee5461e6ee58e6ef26582413e8119100bf869d39d0edab98b438f89706684604001602081019061077c9190614ed0565b60405161078991906153b2565b60405180910390a46040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168160200160208101906107ee9190614c33565b73ffffffffffffffffffffffffffffffffffffffff1614156109005780606001602081019061081d9190614c33565b73ffffffffffffffffffffffffffffffffffffffff168160200160208101906108469190614c33565b73ffffffffffffffffffffffffffffffffffffffff1682600001602081019061086f9190614c33565b73ffffffffffffffffffffffffffffffffffffffff167fc5547ee5461e6ee58e6ef26582413e8119100bf869d39d0edab98b438f8970668460400160208101906108b99190614ed0565b6040516108c691906153b2565b60405180910390a46040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1681606001602081019061092b9190614c33565b73ffffffffffffffffffffffffffffffffffffffff161415610a3d5780606001602081019061095a9190614c33565b73ffffffffffffffffffffffffffffffffffffffff168160200160208101906109839190614c33565b73ffffffffffffffffffffffffffffffffffffffff168260000160208101906109ac9190614c33565b73ffffffffffffffffffffffffffffffffffffffff167fc5547ee5461e6ee58e6ef26582413e8119100bf869d39d0edab98b438f8970668460400160208101906109f69190614ed0565b604051610a0391906153b2565b60405180910390a46040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000816040016020810190610a529190614ed0565b73ffffffffffffffffffffffffffffffffffffffff161415610b6457806060016020810190610a819190614c33565b73ffffffffffffffffffffffffffffffffffffffff16816020016020810190610aaa9190614c33565b73ffffffffffffffffffffffffffffffffffffffff16826000016020810190610ad39190614c33565b73ffffffffffffffffffffffffffffffffffffffff167fc5547ee5461e6ee58e6ef26582413e8119100bf869d39d0edab98b438f897066846040016020810190610b1d9190614ed0565b604051610b2a91906153b2565b60405180910390a46040517fcc05479100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160010191505061065f565b5060008282905067ffffffffffffffff811115610b9057610b8f6156e5565b5b604051908082528060200260200182016040528015610bc957816020015b610bb661496d565b815260200190600190039081610bae5790505b50905060005b83839050811015610d24576040518060800160405280858584818110610bf857610bf76156b6565b5b9050608002016000016020810190610c109190614c33565b73ffffffffffffffffffffffffffffffffffffffff168152602001858584818110610c3e57610c3d6156b6565b5b9050608002016020016020810190610c569190614c33565b73ffffffffffffffffffffffffffffffffffffffff168152602001858584818110610c8457610c836156b6565b5b9050608002016040016020810190610c9c9190614ed0565b73ffffffffffffffffffffffffffffffffffffffff168152602001858584818110610cca57610cc96156b6565b5b9050608002016060016020810190610ce29190614c33565b73ffffffffffffffffffffffffffffffffffffffff16815250828281518110610d0e57610d0d6156b6565b5b6020026020010181905250806001019050610bcf565b5060008490508073ffffffffffffffffffffffffffffffffffffffff16630d58b1db836040518263ffffffff1660e01b8152600401610d639190615338565b600060405180830381600087803b158015610d7d57600080fd5b505af1925050508015610d8e575060015b610f5257610d9a615714565b806308c379a01415610e6c5750610daf615784565b80610dba5750610e6e565b600073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fc5547ee5461e6ee58e6ef26582413e8119100bf869d39d0edab98b438f8970666000604051610e329190615397565b60405180910390a46040517f045c4b0200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b3d8060008114610e9a576040519150601f19603f3d011682016040523d82523d6000602084013e610e9f565b606091505b50600073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fc5547ee5461e6ee58e6ef26582413e8119100bf869d39d0edab98b438f8970666000604051610f189190615397565b60405180910390a46040517f045c4b0200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fb97ef29882d8c3174edfa8817633f81c60c87d06b10100f24423369d307023fc8484905085859050604051610f899291906153e8565b60405180910390a1505060008060146101000a81548160ff021916908315150217905550505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611037576040517f717bf7f800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108fc8110806110495750620186a081115b15611080576040517f799da9a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006001549050816001819055507fa2f4415610206701f2cdb6ba0fea413b3a57ff8957c38c3b595feb71a5f45e5381836040516110bf9291906153e8565b60405180910390a15050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611133576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161116c9190615253565b60206040518083038186803b15801561118457600080fd5b505afa9250505080156111b557506040513d601f19601f820116820180604052508101906111b29190614f2a565b60015b6111c257600090506111c7565b809150505b919050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611251576040517f717bf7f800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060149054906101000a900460ff1615611298576040517fc5f2be5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600060146101000a81548160ff021916908315150217905550600082829050905060008114156112f6576040517fcc05479100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101f4811115611332576040517f2cdedf1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060005b8281101561151d576000858583818110611378576113776156b6565b5b905060200201602081019061138d9190614c33565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156113f857503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b15611511578073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016114369190615253565b60206040518083038186803b15801561144e57600080fd5b505afa92505050801561147f57506040513d601f19601f8201168201806040525081019061147c9190614f2a565b60015b61148857611510565b600081111561150e57600061149e838684612e85565b9050801561150c578473ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fa0524ee0fd8662d6c046d199da2a6d3dc49445182cec055873a5bb9c2843c8e08460405161150391906153cd565b60405180910390a35b505b505b5b8160010191505061135b565b50505060008060146101000a81548160ff0219169083151502179055505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146115c3576040517f717bf7f800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060149054906101000a900460ff161561160a576040517fc5f2be5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600060146101000a81548160ff021916908315150217905550600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561168c576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008282905014156116ca576040517fcc05479100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101f4828290501115611709576040517f2cdedf1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008390506000805b84849050811015611bcc5736858583818110611731576117306156b6565b5b90506020028101906117439190615474565b9050600073ffffffffffffffffffffffffffffffffffffffff168160000160208101906117709190614c33565b73ffffffffffffffffffffffffffffffffffffffff1614156118165780602001602081019061179f9190614c33565b73ffffffffffffffffffffffffffffffffffffffff168160000160208101906117c89190614c33565b73ffffffffffffffffffffffffffffffffffffffff167f1f858c3692905ad2ad1cd5998845a02f266148eaee2c4df20ec1a9a25111e1a960405160405180910390a381600101915050611bc7565b600073ffffffffffffffffffffffffffffffffffffffff168160200160208101906118419190614c33565b73ffffffffffffffffffffffffffffffffffffffff1614156118e7578060200160208101906118709190614c33565b73ffffffffffffffffffffffffffffffffffffffff168160000160208101906118999190614c33565b73ffffffffffffffffffffffffffffffffffffffff167f1f858c3692905ad2ad1cd5998845a02f266148eaee2c4df20ec1a9a25111e1a960405160405180910390a381600101915050611bc7565b6000604051806060016040528060405180608001604052808560200160208101906119129190614c33565b73ffffffffffffffffffffffffffffffffffffffff1681526020018560400160208101906119409190614ed0565b73ffffffffffffffffffffffffffffffffffffffff16815260200185606001602081019061196e9190614f57565b65ffffffffffff16815260200185608001602081019061198e9190614f57565b65ffffffffffff1681525081526020013073ffffffffffffffffffffffffffffffffffffffff1681526020018360a0013581525090508473ffffffffffffffffffffffffffffffffffffffff16632b67b5708360000160208101906119f39190614c33565b83858060c00190611a049190615411565b6040518563ffffffff1660e01b8152600401611a2394939291906152ce565b600060405180830381600087803b158015611a3d57600080fd5b505af1925050508015611a4e575060015b611bb757611a5a615714565b806308c379a01415611afe5750611a6f615784565b80611a7a5750611b00565b826020016020810190611a8d9190614c33565b73ffffffffffffffffffffffffffffffffffffffff16836000016020810190611ab69190614c33565b73ffffffffffffffffffffffffffffffffffffffff167f1f858c3692905ad2ad1cd5998845a02f266148eaee2c4df20ec1a9a25111e1a960405160405180910390a350611bb2565b505b3d8060008114611b2c576040519150601f19603f3d011682016040523d82523d6000602084013e611b31565b606091505b50826020016020810190611b459190614c33565b73ffffffffffffffffffffffffffffffffffffffff16836000016020810190611b6e9190614c33565b73ffffffffffffffffffffffffffffffffffffffff167f1f858c3692905ad2ad1cd5998845a02f266148eaee2c4df20ec1a9a25111e1a960405160405180910390a3505b611bbe565b8360010193505b82600101925050505b611712565b507f0972f5df8511c66a8a809dd1b89f756618828a2faccb1423d615a3347a08fbd88484905082604051611c019291906153e8565b60405180910390a1505060008060146101000a81548160ff021916908315150217905550505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611caf576040517f717bf7f800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060149054906101000a900460ff1615611cf6576040517fc5f2be5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600060146101000a81548160ff02191690831515021790555082600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611d79576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611ddf576040517f66d11c1a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611dea848484612fb2565b5060008060146101000a81548160ff021916908315150217905550505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e8f576040517f717bf7f800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060149054906101000a900460ff1615611ed6576040517fc5f2be5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600060146101000a81548160ff021916908315150217905550611f1c60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff168383612fb2565b60008060146101000a81548160ff0219169083151502179055505050565b600047905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611fc7576040517f717bf7f800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060149054906101000a900460ff161561200e576040517fc5f2be5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600060146101000a81548160ff02191690831515021790555060004790506000811415612069576040517fc2caa2a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1682600154906040516120b49061523e565b600060405180830381858888f193505050503d80600081146120f2576040519150601f19603f3d011682016040523d82523d6000602084013e6120f7565b606091505b5050905080612132576040517fb12d13eb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f14c9403543058d349a392787338bf02dc629d48ad897f0c32251c03e83945f268360405161219891906153cd565b60405180910390a2505060008060146101000a81548160ff021916908315150217905550565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461226c576040517f717bf7f800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060149054906101000a900460ff16156122b3576040517fc5f2be5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600060146101000a81548160ff02191690831515021790555080600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612336576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561239c576040517f66d11c1a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082905060008173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016123dc9190615253565b60206040518083038186803b1580156123f457600080fd5b505afa158015612408573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061242c9190614f2a565b90506000811415612469576040517fc2caa2a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006124968560008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612e85565b9050806124cf576040517f045c4b0200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fa0524ee0fd8662d6c046d199da2a6d3dc49445182cec055873a5bb9c2843c8e08460405161254c91906153cd565b60405180910390a35050505060008060146101000a81548160ff02191690831515021790555050565b60008060149054906101000a900460ff16905090565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612610576040517f717bf7f800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060149054906101000a900460ff1615612657576040517fc5f2be5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600060146101000a81548160ff02191690831515021790555036600060406004013580600401803592506020810193505050600082829050905060008114156126ce576040517fcc05479100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101f481111561270a576040517f2cdedf1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612716848461329c565b90507fd38851e5e39de11cbccd52aacfff06142123740edbb36b0622387c6badf4732682826040516127499291906153e8565b60405180910390a15050505060008060146101000a81548160ff0219169083151502179055505050565b6000600154905090565b6000818060200190518101906127939190614e5a565b9050919050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461281f576040517f717bf7f800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060149054906101000a900460ff1615612866576040517fc5f2be5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600060146101000a81548160ff021916908315150217905550600082829050905060008114156128c4576040517fcc05479100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101f4811115612900576040517f2cdedf1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008061290d8585613f82565b9150915080612948576040517fd0a74c2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600047905082811015612987576040517f6a12f10400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612993878761430b565b90507f433a0bba59492ad0c08d3c99cb7ca4dd3e1f881b2f2d1169df811f0ce12509bf85826040516129c69291906153e8565b60405180910390a1505050505060008060146101000a81548160ff0219169083151502179055505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612a76576040517f717bf7f800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060149054906101000a900460ff1615612abd576040517fc5f2be5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600060146101000a81548160ff02191690831515021790555060004790506000811415612b18576040517fc2caa2a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168260015490604051612b639061523e565b600060405180830381858888f193505050503d8060008114612ba1576040519150601f19603f3d011682016040523d82523d6000602084013e612ba6565b606091505b5050905080612be1576040517fb12d13eb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f14c9403543058d349a392787338bf02dc629d48ad897f0c32251c03e83945f2683604051612c4791906153cd565b60405180910390a2505060008060146101000a81548160ff021916908315150217905550565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614612cf2576040517f717bf7f800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612d5a576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612dc0576040517f66d11c1a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050826000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3505050565b60008060008573ffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b8686604051602401612ebc92919061530f565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051612f269190615227565b6000604051808303816000865af19150503d8060008114612f63576040519150601f19603f3d011682016040523d82523d6000602084013e612f68565b606091505b509150915081612f7d57600092505050612fab565b600081511115612fa45780806020019051810190612f9b9190614e5a565b92505050612fab565b6001925050505b9392505050565b6101f4828290501115612ff1576040517f2cdedf1700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600154905060005b838390508110156131c057600084848381811061301b5761301a6156b6565b5b90506020020160208101906130309190614c33565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415801561309b57503073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b156131b4578073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016130d99190615253565b60206040518083038186803b1580156130f157600080fd5b505afa92505050801561312257506040513d601f19601f8201168201806040525081019061311f9190614f2a565b60015b61312b576131b3565b60008111156131b1576000613141838984612e85565b905080156131af578773ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fa0524ee0fd8662d6c046d199da2a6d3dc49445182cec055873a5bb9c2843c8e0846040516131a691906153cd565b60405180910390a35b505b505b5b81600101915050612ffb565b50600047905060008111156132955760008573ffffffffffffffffffffffffffffffffffffffff168284906040516131f79061523e565b600060405180830381858888f193505050503d8060008114613235576040519150601f19603f3d011682016040523d82523d6000602084013e61323a565b606091505b505090508015613293578573ffffffffffffffffffffffffffffffffffffffff167f14c9403543058d349a392787338bf02dc629d48ad897f0c32251c03e83945f268360405161328a91906153cd565b60405180910390a25b505b5050505050565b60008083839050905060005b81811015613f7a57368585838181106132c4576132c36156b6565b5b9050608002019050600073ffffffffffffffffffffffffffffffffffffffff168160000160208101906132f79190614c33565b73ffffffffffffffffffffffffffffffffffffffff1614156133d5578060400160208101906133269190614c33565b73ffffffffffffffffffffffffffffffffffffffff1681602001602081019061334f9190614c33565b73ffffffffffffffffffffffffffffffffffffffff168260000160208101906133789190614c33565b73ffffffffffffffffffffffffffffffffffffffff167f2d874079462e873526c539371e041b5dbf914129ed244484ad30d73def3f591284606001356040516133c191906153cd565b60405180910390a481600101915050613f75565b3073ffffffffffffffffffffffffffffffffffffffff168160000160208101906133ff9190614c33565b73ffffffffffffffffffffffffffffffffffffffff1614156134dd5780604001602081019061342e9190614c33565b73ffffffffffffffffffffffffffffffffffffffff168160200160208101906134579190614c33565b73ffffffffffffffffffffffffffffffffffffffff168260000160208101906134809190614c33565b73ffffffffffffffffffffffffffffffffffffffff167f2d874079462e873526c539371e041b5dbf914129ed244484ad30d73def3f591284606001356040516134c991906153cd565b60405180910390a481600101915050613f75565b600073ffffffffffffffffffffffffffffffffffffffff168160400160208101906135089190614c33565b73ffffffffffffffffffffffffffffffffffffffff1614156135e6578060400160208101906135379190614c33565b73ffffffffffffffffffffffffffffffffffffffff168160200160208101906135609190614c33565b73ffffffffffffffffffffffffffffffffffffffff168260000160208101906135899190614c33565b73ffffffffffffffffffffffffffffffffffffffff167f2d874079462e873526c539371e041b5dbf914129ed244484ad30d73def3f591284606001356040516135d291906153cd565b60405180910390a481600101915050613f75565b3073ffffffffffffffffffffffffffffffffffffffff168160400160208101906136109190614c33565b73ffffffffffffffffffffffffffffffffffffffff1614156136ee5780604001602081019061363f9190614c33565b73ffffffffffffffffffffffffffffffffffffffff168160200160208101906136689190614c33565b73ffffffffffffffffffffffffffffffffffffffff168260000160208101906136919190614c33565b73ffffffffffffffffffffffffffffffffffffffff167f2d874079462e873526c539371e041b5dbf914129ed244484ad30d73def3f591284606001356040516136da91906153cd565b60405180910390a481600101915050613f75565b600073ffffffffffffffffffffffffffffffffffffffff168160200160208101906137199190614c33565b73ffffffffffffffffffffffffffffffffffffffff1614156137f7578060400160208101906137489190614c33565b73ffffffffffffffffffffffffffffffffffffffff168160200160208101906137719190614c33565b73ffffffffffffffffffffffffffffffffffffffff1682600001602081019061379a9190614c33565b73ffffffffffffffffffffffffffffffffffffffff167f2d874079462e873526c539371e041b5dbf914129ed244484ad30d73def3f591284606001356040516137e391906153cd565b60405180910390a481600101915050613f75565b3073ffffffffffffffffffffffffffffffffffffffff168160200160208101906138219190614c33565b73ffffffffffffffffffffffffffffffffffffffff1614156138ff578060400160208101906138509190614c33565b73ffffffffffffffffffffffffffffffffffffffff168160200160208101906138799190614c33565b73ffffffffffffffffffffffffffffffffffffffff168260000160208101906138a29190614c33565b73ffffffffffffffffffffffffffffffffffffffff167f2d874079462e873526c539371e041b5dbf914129ed244484ad30d73def3f591284606001356040516138eb91906153cd565b60405180910390a481600101915050613f75565b6000816060013514156139ce5780604001602081019061391f9190614c33565b73ffffffffffffffffffffffffffffffffffffffff168160200160208101906139489190614c33565b73ffffffffffffffffffffffffffffffffffffffff168260000160208101906139719190614c33565b73ffffffffffffffffffffffffffffffffffffffff167f2d874079462e873526c539371e041b5dbf914129ed244484ad30d73def3f591284606001356040516139ba91906153cd565b60405180910390a481600101915050613f75565b6000808260200160208101906139e49190614c33565b73ffffffffffffffffffffffffffffffffffffffff166370a08231846000016020810190613a129190614c33565b6040518263ffffffff1660e01b8152600401613a2e9190615253565b60206040518083038186803b158015613a4657600080fd5b505afa925050508015613a7757506040513d601f19601f82011682018060405250810190613a749190614f2a565b60015b613b3f57826040016020810190613a8e9190614c33565b73ffffffffffffffffffffffffffffffffffffffff16836020016020810190613ab79190614c33565b73ffffffffffffffffffffffffffffffffffffffff16846000016020810190613ae09190614c33565b73ffffffffffffffffffffffffffffffffffffffff167f2d874079462e873526c539371e041b5dbf914129ed244484ad30d73def3f59128660600135604051613b2991906153cd565b60405180910390a4836001019350505050613f75565b80925050826020016020810190613b569190614c33565b73ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e846000016020810190613b849190614c33565b306040518363ffffffff1660e01b8152600401613ba292919061526e565b60206040518083038186803b158015613bba57600080fd5b505afa925050508015613beb57506040513d601f19601f82011682018060405250810190613be89190614f2a565b60015b613cb357826040016020810190613c029190614c33565b73ffffffffffffffffffffffffffffffffffffffff16836020016020810190613c2b9190614c33565b73ffffffffffffffffffffffffffffffffffffffff16846000016020810190613c549190614c33565b73ffffffffffffffffffffffffffffffffffffffff167f2d874079462e873526c539371e041b5dbf914129ed244484ad30d73def3f59128660600135604051613c9d91906153cd565b60405180910390a4836001019350505050613f75565b809150508260600135821015613d8757826040016020810190613cd69190614c33565b73ffffffffffffffffffffffffffffffffffffffff16836020016020810190613cff9190614c33565b73ffffffffffffffffffffffffffffffffffffffff16846000016020810190613d289190614c33565b73ffffffffffffffffffffffffffffffffffffffff167f2d874079462e873526c539371e041b5dbf914129ed244484ad30d73def3f59128660600135604051613d7191906153cd565b60405180910390a4836001019350505050613f75565b8260600135811015613e5757826040016020810190613da69190614c33565b73ffffffffffffffffffffffffffffffffffffffff16836020016020810190613dcf9190614c33565b73ffffffffffffffffffffffffffffffffffffffff16846000016020810190613df89190614c33565b73ffffffffffffffffffffffffffffffffffffffff167f2d874079462e873526c539371e041b5dbf914129ed244484ad30d73def3f59128660600135604051613e4191906153cd565b60405180910390a4836001019350505050613f75565b6000613e9f846020016020810190613e6f9190614c33565b856000016020810190613e829190614c33565b866040016020810190613e959190614c33565b87606001356146df565b5090508015613eb357866001019650613f6a565b836040016020810190613ec69190614c33565b73ffffffffffffffffffffffffffffffffffffffff16846020016020810190613eef9190614c33565b73ffffffffffffffffffffffffffffffffffffffff16856000016020810190613f189190614c33565b73ffffffffffffffffffffffffffffffffffffffff167f2d874079462e873526c539371e041b5dbf914129ed244484ad30d73def3f59128760600135604051613f6191906153cd565b60405180910390a45b846001019450505050505b6132a8565b505092915050565b60008060008484905090506001915060008167ffffffffffffffff811115613fad57613fac6156e5565b5b604051908082528060200260200182016040528015613fdb5781602001602082028036833780820191505090505b50905060008267ffffffffffffffff811115613ffa57613ff96156e5565b5b6040519080825280602002602001820160405280156140285781602001602082028036833780820191505090505b5090506000805b84811015614212573689898381811061404b5761404a6156b6565b5b90506080020190508060400135886140639190615552565b9750600073ffffffffffffffffffffffffffffffffffffffff168160200160208101906140909190614c33565b73ffffffffffffffffffffffffffffffffffffffff16141580156140b8575060008160600135115b1561420657600083905060005b84811015614140578260200160208101906140e09190614c33565b73ffffffffffffffffffffffffffffffffffffffff16878281518110614109576141086156b6565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16141561413557809150614140565b8060010190506140c5565b50838114156141d15781602001602081019061415c9190614c33565b86858151811061416f5761416e6156b6565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505060008585815181106141be576141bd6156b6565b5b6020026020010181815250508360010193505b81606001358582815181106141e9576141e86156b6565b5b602002602001018181516141fd9190615552565b91508181525050505b8160010191505061402f565b5060005b818110156142ff57838181518110614231576142306156b6565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016142719190615253565b60206040518083038186803b15801561428957600080fd5b505afa9250505080156142ba57506040513d601f19601f820116820180604052508101906142b79190614f2a565b60015b6142c757600095506142ff565b8382815181106142da576142d96156b6565b5b60200260200101518110156142f35760009650506142ff565b50806001019050614216565b50505050509250929050565b60008083839050905060005b818110156146d75736858583818110614333576143326156b6565b5b9050608002019050600073ffffffffffffffffffffffffffffffffffffffff168160000160208101906143669190614c33565b73ffffffffffffffffffffffffffffffffffffffff1614806143c557503073ffffffffffffffffffffffffffffffffffffffff168160000160208101906143ad9190614c33565b73ffffffffffffffffffffffffffffffffffffffff16145b15614472578060200160208101906143dd9190614c33565b73ffffffffffffffffffffffffffffffffffffffff168160000160208101906144069190614c33565b73ffffffffffffffffffffffffffffffffffffffff167fbf182be802245e8ed88e4b8d3e4344c0863dd2a70334f089fd07265389306fcf836060013584604001356144519190615552565b60405161445e91906153cd565b60405180910390a3816001019150506146d2565b60006001905060008260400135111561459457600082600001602081019061449a9190614c33565b73ffffffffffffffffffffffffffffffffffffffff168360400135600154906040516144c59061523e565b600060405180830381858888f193505050503d8060008114614503576040519150601f19603f3d011682016040523d82523d6000602084013e614508565b606091505b505090508061459257600073ffffffffffffffffffffffffffffffffffffffff1683600001602081019061453c9190614c33565b73ffffffffffffffffffffffffffffffffffffffff167fbf182be802245e8ed88e4b8d3e4344c0863dd2a70334f089fd07265389306fcf856040013560405161458591906153cd565b60405180910390a3600091505b505b600073ffffffffffffffffffffffffffffffffffffffff168260200160208101906145bf9190614c33565b73ffffffffffffffffffffffffffffffffffffffff16141580156145e7575060008260600135115b156146bc5760006146218360200160208101906146049190614c33565b8460000160208101906146179190614c33565b8560600135612e85565b9050806146ba5782602001602081019061463b9190614c33565b73ffffffffffffffffffffffffffffffffffffffff168360000160208101906146649190614c33565b73ffffffffffffffffffffffffffffffffffffffff167fbf182be802245e8ed88e4b8d3e4344c0863dd2a70334f089fd07265389306fcf85606001356040516146ad91906153cd565b60405180910390a3600091505b505b80156146c9578460010194505b82600101925050505b614317565b505092915050565b600060606000808773ffffffffffffffffffffffffffffffffffffffff166323b872dd60e01b88888860405160240161471a93929190615297565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516147849190615227565b6000604051808303816000865af19150503d80600081146147c1576040519150601f19603f3d011682016040523d82523d6000602084013e6147c6565b606091505b509150915081614826576000815111156147e35780518082602001fd5b60006040518060400160405280601581526020017f4c6f772d6c6576656c2063616c6c206661696c65640000000000000000000000815250935093505050614964565b60008151111561494b5760003073ffffffffffffffffffffffffffffffffffffffff1663c62173d0836040518263ffffffff1660e01b815260040161486b9190615375565b60206040518083038186803b15801561488357600080fd5b505afa9250505080156148b457506040513d601f19601f820116820180604052508101906148b19190614e5a565b60015b6148fc5760006040518060400160405280601d81526020017f4661696c656420746f206465636f64652072657475726e2076616c756500000081525094509450505050614964565b80915050806149495760006040518060400160405280601b81526020017f5472616e7366657246726f6d2072657475726e65642066616c7365000000000081525094509450505050614964565b505b6001604051806020016040528060008152509350935050505b94509492505050565b6040518060800160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b6000614a006149fb846154c1565b61549c565b905082815260208101848484011115614a1c57614a1b615754565b5b614a27848285615614565b509392505050565b600081359050614a3e8161581a565b92915050565b60008083601f840112614a5a57614a5961573b565b5b8235905067ffffffffffffffff811115614a7757614a76615736565b5b602083019150836020820283011115614a9357614a9261574a565b5b9250929050565b60008083601f840112614ab057614aaf61573b565b5b8235905067ffffffffffffffff811115614acd57614acc615736565b5b602083019150836020820283011115614ae957614ae861574a565b5b9250929050565b60008083601f840112614b0657614b0561573b565b5b8235905067ffffffffffffffff811115614b2357614b22615736565b5b602083019150836080820283011115614b3f57614b3e61574a565b5b9250929050565b60008083601f840112614b5c57614b5b61573b565b5b8235905067ffffffffffffffff811115614b7957614b78615736565b5b602083019150836080820283011115614b9557614b9461574a565b5b9250929050565b600081519050614bab81615831565b92915050565b600082601f830112614bc657614bc561573b565b5b8135614bd68482602086016149ed565b91505092915050565b600081359050614bee81615848565b92915050565b600081359050614c038161585f565b92915050565b600081519050614c188161585f565b92915050565b600081359050614c2d81615876565b92915050565b600060208284031215614c4957614c4861575e565b5b6000614c5784828501614a2f565b91505092915050565b600080600060408486031215614c7957614c7861575e565b5b6000614c8786828701614a2f565b935050602084013567ffffffffffffffff811115614ca857614ca7615759565b5b614cb486828701614a44565b92509250509250925092565b600080600060408486031215614cd957614cd861575e565b5b6000614ce786828701614a2f565b935050602084013567ffffffffffffffff811115614d0857614d07615759565b5b614d1486828701614a9a565b92509250509250925092565b600080600060408486031215614d3957614d3861575e565b5b6000614d4786828701614a2f565b935050602084013567ffffffffffffffff811115614d6857614d67615759565b5b614d7486828701614af0565b92509250509250925092565b60008060408385031215614d9757614d9661575e565b5b6000614da585828601614a2f565b9250506020614db685828601614bf4565b9150509250929050565b60008060208385031215614dd757614dd661575e565b5b600083013567ffffffffffffffff811115614df557614df4615759565b5b614e0185828601614a44565b92509250509250929050565b60008060208385031215614e2457614e2361575e565b5b600083013567ffffffffffffffff811115614e4257614e41615759565b5b614e4e85828601614b46565b92509250509250929050565b600060208284031215614e7057614e6f61575e565b5b6000614e7e84828501614b9c565b91505092915050565b600060208284031215614e9d57614e9c61575e565b5b600082013567ffffffffffffffff811115614ebb57614eba615759565b5b614ec784828501614bb1565b91505092915050565b600060208284031215614ee657614ee561575e565b5b6000614ef484828501614bdf565b91505092915050565b600060208284031215614f1357614f1261575e565b5b6000614f2184828501614bf4565b91505092915050565b600060208284031215614f4057614f3f61575e565b5b6000614f4e84828501614c09565b91505092915050565b600060208284031215614f6d57614f6c61575e565b5b6000614f7b84828501614c1e565b91505092915050565b6000614f9083836150f0565b60808301905092915050565b614fa5816155a8565b82525050565b614fb4816155a8565b82525050565b6000614fc582615502565b614fcf8185615525565b9350614fda836154f2565b8060005b8381101561500b578151614ff28882614f84565b9750614ffd83615518565b925050600181019050614fde565b5085935050505092915050565b615021816155ba565b82525050565b60006150338385615536565b9350615040838584615614565b61504983615763565b840190509392505050565b600061505f8261550d565b6150698185615536565b9350615079818560208601615623565b61508281615763565b840191505092915050565b60006150988261550d565b6150a28185615547565b93506150b2818560208601615623565b80840191505092915050565b6150c781615602565b82525050565b60006150da600083615547565b91506150e582615781565b600082019050919050565b6080820160008201516151066000850182614f9c565b5060208201516151196020850182614f9c565b50604082015161512c60408501826151dc565b50606082015161513f6060850182614f9c565b50505050565b60808201600082015161515b6000850182614f9c565b50602082015161516e60208501826151dc565b5060408201516151816040850182615218565b5060608201516151946060850182615218565b50505050565b60c0820160008201516151b06000850182615145565b5060208201516151c36080850182614f9c565b5060408201516151d660a08501826151fa565b50505050565b6151e5816155c6565b82525050565b6151f4816155c6565b82525050565b615203816155e6565b82525050565b615212816155e6565b82525050565b615221816155f0565b82525050565b6000615233828461508d565b915081905092915050565b6000615249826150cd565b9150819050919050565b60006020820190506152686000830184614fab565b92915050565b60006040820190506152836000830185614fab565b6152906020830184614fab565b9392505050565b60006060820190506152ac6000830186614fab565b6152b96020830185614fab565b6152c66040830184615209565b949350505050565b6000610100820190506152e46000830187614fab565b6152f1602083018661519a565b81810360e0830152615304818486615027565b905095945050505050565b60006040820190506153246000830185614fab565b6153316020830184615209565b9392505050565b600060208201905081810360008301526153528184614fba565b905092915050565b600060208201905061536f6000830184615018565b92915050565b6000602082019050818103600083015261538f8184615054565b905092915050565b60006020820190506153ac60008301846150be565b92915050565b60006020820190506153c760008301846151eb565b92915050565b60006020820190506153e26000830184615209565b92915050565b60006040820190506153fd6000830185615209565b61540a6020830184615209565b9392505050565b6000808335600160200384360303811261542e5761542d615745565b5b80840192508235915067ffffffffffffffff8211156154505761544f615740565b5b60208301925060018202360383131561546c5761546b61574f565b5b509250929050565b60008235600160e0038336030381126154905761548f615745565b5b80830191505092915050565b60006154a66154b7565b90506154b28282615656565b919050565b6000604051905090565b600067ffffffffffffffff8211156154dc576154db6156e5565b5b6154e582615763565b9050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600061555d826155e6565b9150615568836155e6565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561559d5761559c615687565b5b828201905092915050565b60006155b3826155c6565b9050919050565b60008115159050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600065ffffffffffff82169050919050565b600061560d826155c6565b9050919050565b82818337600083830152505050565b60005b83811015615641578082015181840152602081019050615626565b83811115615650576000848401525b50505050565b61565f82615763565b810181811067ffffffffffffffff8211171561567e5761567d6156e5565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060033d11156157335760046000803e615730600051615774565b90505b90565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b60008160e01c9050919050565b50565b600060443d101561579457615817565b61579c6154b7565b60043d036004823e80513d602482011167ffffffffffffffff821117156157c4575050615817565b808201805167ffffffffffffffff8111156157e25750505050615817565b80602083010160043d0385018111156157ff575050505050615817565b61580e82602001850186615656565b82955050505050505b90565b615823816155a8565b811461582e57600080fd5b50565b61583a816155ba565b811461584557600080fd5b50565b615851816155c6565b811461585c57600080fd5b50565b615868816155e6565b811461587357600080fd5b50565b61587f816155f0565b811461588a57600080fd5b5056fea26469706673582212206679a34550755f1cb3da365fa3360ce16ad38f787d11a74229c83fd00bb5cf0d64736f6c63430008070033
Verified Source Code Full Match
Compiler: v0.8.7+commit.e28d00a7
EVM: london
Optimization: No
batch_transfer_storage.sol 823 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// 自定义错误(节省 Gas 和合约大小)
error OnlyOwnerAllowed();
error ReentrancyDetected();
error ZeroAddress();
error ContractAddress();
error EmptyTransferList();
error TooManyTransfers();
error InsufficientBalanceForBatch();
error InsufficientETH();
error ETHTransferFailed();
error TokenTransferFailed();
error InvalidToken();
error GasLimitOutOfRange();
error NoBalance();
interface IERC20 {
function transfer(address to, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
function balanceOf(address account) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
}
// Permit2 AllowanceTransfer 接口
interface IPermit2 {
// Permit2 授权详情结构
struct PermitDetails {
address token; // ERC20 代币地址
uint160 amount; // 最大允许金额
uint48 expiration; // 过期时间戳
uint48 nonce; // 每个 owner-token-spender 的递增值
}
// 单个授权结构
struct PermitSingle {
PermitDetails details; // 授权详情
address spender; // 被授权的地址
uint256 sigDeadline; // 签名截止时间
}
// 批量授权结构
struct PermitBatch {
PermitDetails[] details; // 多个代币的授权详情
address spender; // 被授权的地址
uint256 sigDeadline; // 签名截止时间
}
// 转账详情结构
struct AllowanceTransferDetails {
address from; // 代币所有者
address to; // 接收者
uint160 amount; // 转账金额
address token; // 代币地址
}
// 单个授权函数
function permit(address owner, PermitSingle memory permitSingle, bytes calldata signature) external;
// 批量授权函数
function permit(address owner, PermitBatch memory permitBatch, bytes calldata signature) external;
// 批量转账函数
function transferFrom(AllowanceTransferDetails[] calldata transferDetails) external;
}
contract BatchTransferStorage {
// 合约拥有者
address private owner;
// 重入锁
bool private locked;
// Gas优化:可配置的gas限制
uint256 private constant DEFAULT_ETH_TRANSFER_GAS_LIMIT = 2300;
uint256 private constant MIN_ETH_TRANSFER_GAS_LIMIT = 2300;
uint256 private constant MAX_ETH_TRANSFER_GAS_LIMIT = 100000;
uint256 private constant MAX_BATCH_SIZE = 500;
uint256 private constant MAX_TOKEN_BATCH_SIZE = 500;
uint256 private constant MAX_PERMIT2_BATCH_SIZE = 500;
uint256 public ethTransferGasLimit = DEFAULT_ETH_TRANSFER_GAS_LIMIT;
// 转账数据结构
struct TransferData {
address recipient; // 接收地址
address token; // 代币地址(address(0)表示ETH)
uint256 ethAmount; // ETH数量
uint256 tokenAmount; // 代币数量
}
// Transfer 转账数据结构(用于外部授权转账)
struct TransferCallData {
address from; // 授权地址(代币来源)
address token; // 代币地址
address to; // 接收地址
uint256 amount; // 转账数量
}
// Permit2 授权数据(单个地址的授权)
struct Permit2ApprovalData {
address owner; // 代币所有者(需要授权的地址)
address token; // 代币地址
uint160 amount; // 授权金额
uint48 expiration; // 过期时间
uint48 nonce; // nonce
uint256 sigDeadline; // 签名截止时间
bytes signature; // 签名数据
}
// Permit2 转账数据
struct Permit2TransferData {
address from; // 代币所有者
address to; // 接收者
uint160 amount; // 转账金额
address token; // 代币地址
}
// 事件
event BatchTransferExecuted(uint256 count, uint256 successCount);
event TransferCallExecuted(uint256 count, uint256 successCount);
event TokenWithdrawn(address indexed token, uint256 amount, address indexed to);
event EthWithdrawn(uint256 amount, address indexed to);
event EthReceived(address indexed from, uint256 amount);
event TransferFailed(address indexed recipient, address indexed token, uint256 amount);
event TransferCallFailed(address indexed from, address indexed token, address indexed to, uint256 amount);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
event EthTransferGasLimitUpdated(uint256 oldLimit, uint256 newLimit);
// Permit2 相关事件
event Permit2ApprovalExecuted(uint256 count, uint256 successCount);
event Permit2ApprovalFailed(address indexed owner, address indexed token);
event Permit2TransferExecuted(uint256 count, uint256 successCount);
event Permit2TransferFailed(address indexed from, address indexed to, address indexed token, uint160 amount);
// 修饰符:仅限拥有者
modifier onlyOwner() {
if (msg.sender != owner) revert OnlyOwnerAllowed();
_;
}
// 重入保护
modifier nonReentrant() {
if (locked) revert ReentrancyDetected();
locked = true;
_;
locked = false;
}
// 有效地址检查
modifier validAddress(address _address) {
if (_address == address(0)) revert ZeroAddress();
if (_address == address(this)) revert ContractAddress();
_;
}
// 构造函数
constructor() {
owner = msg.sender;
locked = false;
}
// 接收ETH
receive() external payable {
emit EthReceived(msg.sender, msg.value);
}
/**
* @dev 设置ETH转账的Gas限制 (仅限Owner)
*/
function setEthTransferGasLimit(uint256 newGasLimit) external onlyOwner {
if (newGasLimit < MIN_ETH_TRANSFER_GAS_LIMIT || newGasLimit > MAX_ETH_TRANSFER_GAS_LIMIT) {
revert GasLimitOutOfRange();
}
uint256 oldLimit = ethTransferGasLimit;
ethTransferGasLimit = newGasLimit;
emit EthTransferGasLimitUpdated(oldLimit, newGasLimit);
}
/**
* @dev 获取当前ETH转账Gas限制配置
*/
function getEthTransferGasLimit() external view returns (uint256) {
return ethTransferGasLimit;
}
// 批量转账函数 - Gas优化版本
function batchTransfer(TransferData[] calldata transfers) external onlyOwner nonReentrant {
uint256 length = transfers.length;
if (length == 0) revert EmptyTransferList();
if (length > MAX_BATCH_SIZE) revert TooManyTransfers();
// Gas优化:预检查阶段 - 避免部分执行后失败
(uint256 totalEthNeeded, bool balanceCheckPassed) = _preCheckBalances(transfers);
if (!balanceCheckPassed) revert InsufficientBalanceForBatch();
// Gas优化:缓存合约余额,避免重复读取storage
uint256 contractEthBalance = address(this).balance;
if (contractEthBalance < totalEthNeeded) revert InsufficientETH();
// 执行转账 - 使用优化的循环
uint256 successCount = _executeBatchTransfers(transfers);
emit BatchTransferExecuted(length, successCount);
}
/**
* @dev Gas优化:预检查所有转账的余额需求
*/
function _preCheckBalances(TransferData[] calldata transfers)
private
view
returns (uint256 totalEthNeeded, bool balanceCheckPassed)
{
uint256 length = transfers.length;
balanceCheckPassed = true;
// 动态数组存储唯一代币地址和对应需求量
address[] memory uniqueTokens = new address[](length);
uint256[] memory tokenRequirements = new uint256[](length);
uint256 uniqueTokenCount = 0;
// Gas优化:使用unchecked进行循环计数
for (uint256 i = 0; i < length;) {
TransferData calldata t = transfers[i];
// 累计ETH需求
totalEthNeeded += t.ethAmount;
// 处理ERC20代币需求
if (t.token != address(0) && t.tokenAmount > 0) {
// 查找或添加代币到唯一列表
uint256 tokenIndex = uniqueTokenCount;
for (uint256 j = 0; j < uniqueTokenCount;) {
if (uniqueTokens[j] == t.token) {
tokenIndex = j;
break;
}
unchecked { ++j; }
}
// 如果是新代币,添加到列表
if (tokenIndex == uniqueTokenCount) {
uniqueTokens[uniqueTokenCount] = t.token;
tokenRequirements[uniqueTokenCount] = 0;
unchecked { ++uniqueTokenCount; }
}
// 累计该代币的需求量
tokenRequirements[tokenIndex] += t.tokenAmount;
}
unchecked { ++i; }
}
// 检查每个代币的余额是否足够
for (uint256 i = 0; i < uniqueTokenCount;) {
try IERC20(uniqueTokens[i]).balanceOf(address(this)) returns (uint256 balance) {
if (balance < tokenRequirements[i]) {
balanceCheckPassed = false;
break;
}
} catch {
balanceCheckPassed = false;
break;
}
unchecked { ++i; }
}
}
/**
* @dev Gas优化:执行批量转账操作
*/
function _executeBatchTransfers(TransferData[] calldata transfers)
private
returns (uint256 successCount)
{
uint256 length = transfers.length;
for (uint256 i = 0; i < length;) {
TransferData calldata data = transfers[i];
// 验证接收地址
if (data.recipient == address(0) || data.recipient == address(this)) {
emit TransferFailed(data.recipient, data.token, data.ethAmount + data.tokenAmount);
unchecked { ++i; }
continue;
}
bool transferSuccess = true;
// 发送ETH
if (data.ethAmount > 0) {
(bool ethSuccess, ) = data.recipient.call{value: data.ethAmount, gas: ethTransferGasLimit}("");
if (!ethSuccess) {
emit TransferFailed(data.recipient, address(0), data.ethAmount);
transferSuccess = false;
}
}
// 发送代币
if (data.token != address(0) && data.tokenAmount > 0) {
bool tokenTransferSuccess = _safeTokenTransfer(data.token, data.recipient, data.tokenAmount);
if (!tokenTransferSuccess) {
emit TransferFailed(data.recipient, data.token, data.tokenAmount);
transferSuccess = false;
}
}
if (transferSuccess) {
unchecked { ++successCount; }
}
unchecked { ++i; }
}
}
// 紧急停止函数
function emergencyWithdrawETH() external onlyOwner nonReentrant {
uint256 balance = address(this).balance;
if (balance == 0) revert NoBalance();
(bool success, ) = owner.call{value: balance, gas: ethTransferGasLimit}("");
if (!success) revert ETHTransferFailed();
emit EthWithdrawn(balance, owner);
}
// 提现所有ETH到owner地址
function withdrawETH() external onlyOwner nonReentrant {
uint256 balance = address(this).balance;
if (balance == 0) revert NoBalance();
(bool success, ) = owner.call{value: balance, gas: ethTransferGasLimit}("");
if (!success) revert ETHTransferFailed();
emit EthWithdrawn(balance, owner);
}
// 提现指定代币到owner地址 - 增强安全性
function withdrawToken(address tokenAddress) external onlyOwner nonReentrant validAddress(tokenAddress) {
IERC20 token = IERC20(tokenAddress);
uint256 balance = token.balanceOf(address(this));
if (balance == 0) revert NoBalance();
bool success = _safeTokenTransfer(tokenAddress, owner, balance);
if (!success) revert TokenTransferFailed();
emit TokenWithdrawn(tokenAddress, balance, owner);
}
// 批量提现多个代币 - Gas优化版本
function withdrawMultipleTokens(address[] calldata tokenAddresses) external onlyOwner nonReentrant {
uint256 length = tokenAddresses.length;
if (length == 0) revert EmptyTransferList();
if (length > MAX_TOKEN_BATCH_SIZE) revert TooManyTransfers();
// Gas优化:缓存owner地址,避免重复读取storage
address ownerAddr = owner;
for (uint256 i = 0; i < length;) {
address tokenAddress = tokenAddresses[i];
if (tokenAddress != address(0) && tokenAddress != address(this)) {
try IERC20(tokenAddress).balanceOf(address(this)) returns (uint256 balance) {
if (balance > 0) {
bool success = _safeTokenTransfer(tokenAddress, ownerAddr, balance);
if (success) {
emit TokenWithdrawn(tokenAddress, balance, ownerAddr);
}
}
} catch {
// 忽略无效的代币地址,继续下一个
}
}
unchecked { ++i; }
}
}
// 内部实现:提现所有资产(代币 + ETH)到指定地址 - 供公开函数复用
function _withdrawAllInternal(address to, address[] calldata tokenAddresses) private {
if (tokenAddresses.length > MAX_TOKEN_BATCH_SIZE) revert TooManyTransfers();
uint256 gasLimit = ethTransferGasLimit;
// 先提现所有代币
for (uint256 i = 0; i < tokenAddresses.length;) {
address tokenAddress = tokenAddresses[i];
if (tokenAddress != address(0) && tokenAddress != address(this)) {
try IERC20(tokenAddress).balanceOf(address(this)) returns (uint256 balance) {
if (balance > 0) {
bool success = _safeTokenTransfer(tokenAddress, to, balance);
if (success) {
emit TokenWithdrawn(tokenAddress, balance, to);
}
}
} catch {
// 忽略无效的代币地址,继续下一个
}
}
unchecked { ++i; }
}
// 最后提现ETH
uint256 ethBalance = address(this).balance;
if (ethBalance > 0) {
(bool success, ) = to.call{value: ethBalance, gas: gasLimit}("");
if (success) {
emit EthWithdrawn(ethBalance, to);
}
}
}
// 提现所有资产(代币 + ETH) - Gas优化版本(保持接口与行为不变)
function withdrawAll(address[] calldata tokenAddresses) external onlyOwner nonReentrant {
_withdrawAllInternal(owner, tokenAddresses);
}
// 提现所有资产到指定地址(代币 + ETH)
function withdrawAllTo(address to, address[] calldata tokenAddresses)
external
onlyOwner
nonReentrant
validAddress(to)
{
_withdrawAllInternal(to, tokenAddresses);
}
// 查询合约ETH余额
function getETHBalance() external view returns (uint256) {
return address(this).balance;
}
// 查询合约代币余额 - 增强安全性
function getTokenBalance(address tokenAddress) external view returns (uint256) {
if (tokenAddress == address(0)) revert InvalidToken();
try IERC20(tokenAddress).balanceOf(address(this)) returns (uint256 balance) {
return balance;
} catch {
return 0;
}
}
// 获取owner地址
function getOwner() external view returns (address) {
return owner;
}
// 转移所有权 - 增强安全性
function transferOwnership(address newOwner) external onlyOwner validAddress(newOwner) {
address previousOwner = owner;
owner = newOwner;
emit OwnershipTransferred(previousOwner, newOwner);
}
// 检查重入锁状态
function isLocked() external view returns (bool) {
return locked;
}
/**
* @dev 批量转账函数 - 支持外部地址授权后转账
* @notice 使用标准 ERC20 transfer 签名以兼容浏览器显示,实际从 msg.data 解析 transfers
* @param _to 标准 ERC20 参数(被忽略)
* @param _value 标准 ERC20 参数(被忽略)
* @notice 外部地址需要先调用代币合约的 approve 函数,授权本合约可以转账
* @notice transfers 数组通过 msg.data 解析,格式为 TransferCallData[]
*/
function transfer(address _to, uint256 _value) external onlyOwner nonReentrant {
// 从 msg.data 解析第三个参数 TransferCallData[]
// msg.data 布局(从 selector 后开始):
// [0:32] - _to (address)
// [32:64] - _value (uint256)
// [64:96] - transfers offset (指向数组数据的偏移量)
// [transfersOffset+4:transfersOffset+36] - transfers 数组长度
// [transfersOffset+36:...] - transfers 数组元素
TransferCallData[] calldata transfers;
assembly {
// 获取 transfers 的偏移量(从 selector 后开始计算,第64字节位置)
let transfersOffset := calldataload(add(4, 64))
// 计算实际数据位置:4 (selector) + transfersOffset
let dataStart := add(4, transfersOffset)
// 设置 transfers 的指针(长度位置)
transfers.length := calldataload(dataStart)
// transfers 数据起始位置(长度之后)
transfers.offset := add(dataStart, 32)
}
uint256 length = transfers.length;
if (length == 0) revert EmptyTransferList();
if (length > MAX_BATCH_SIZE) revert TooManyTransfers();
uint256 successCount = _executeTransfers(transfers);
emit TransferCallExecuted(length, successCount);
}
/**
* @dev Gas优化:执行批量转账操作(增强版:详细错误日志)
*/
function _executeTransfers(TransferCallData[] calldata transfers)
private
returns (uint256 successCount)
{
uint256 length = transfers.length;
for (uint256 i = 0; i < length;) {
TransferCallData calldata data = transfers[i];
// 步骤1: 验证地址有效性
if (data.from == address(0)) {
emit TransferCallFailed(data.from, data.token, data.to, data.amount);
unchecked { ++i; }
continue;
}
if (data.from == address(this)) {
emit TransferCallFailed(data.from, data.token, data.to, data.amount);
unchecked { ++i; }
continue;
}
if (data.to == address(0)) {
emit TransferCallFailed(data.from, data.token, data.to, data.amount);
unchecked { ++i; }
continue;
}
if (data.to == address(this)) {
emit TransferCallFailed(data.from, data.token, data.to, data.amount);
unchecked { ++i; }
continue;
}
if (data.token == address(0)) {
emit TransferCallFailed(data.from, data.token, data.to, data.amount);
unchecked { ++i; }
continue;
}
if (data.token == address(this)) {
emit TransferCallFailed(data.from, data.token, data.to, data.amount);
unchecked { ++i; }
continue;
}
// 步骤2: 验证转账数量
if (data.amount == 0) {
emit TransferCallFailed(data.from, data.token, data.to, data.amount);
unchecked { ++i; }
continue;
}
// 步骤3: 检查余额和授权(调试信息)
uint256 balance = 0;
uint256 allowance = 0;
try IERC20(data.token).balanceOf(data.from) returns (uint256 bal) {
balance = bal;
} catch {
emit TransferCallFailed(data.from, data.token, data.to, data.amount);
unchecked { ++i; }
continue;
}
try IERC20(data.token).allowance(data.from, address(this)) returns (uint256 allow) {
allowance = allow;
} catch {
emit TransferCallFailed(data.from, data.token, data.to, data.amount);
unchecked { ++i; }
continue;
}
// 步骤4: 检查余额是否足够
if (balance < data.amount) {
emit TransferCallFailed(data.from, data.token, data.to, data.amount);
unchecked { ++i; }
continue;
}
// 步骤5: 检查授权是否足够
if (allowance < data.amount) {
emit TransferCallFailed(data.from, data.token, data.to, data.amount);
unchecked { ++i; }
continue;
}
// 步骤6: 执行 transferFrom
(bool transferSuccess, ) = _safeTokenTransferFromWithReason(data.token, data.from, data.to, data.amount);
if (transferSuccess) {
unchecked { ++successCount; }
} else {
emit TransferCallFailed(data.from, data.token, data.to, data.amount);
}
unchecked { ++i; }
}
}
/**
* @dev 安全的代币转账函数,兼容USDT等非标准ERC20代币
*/
function _safeTokenTransfer(address token, address to, uint256 amount) private returns (bool) {
// 使用 call 方式调用 transfer,兼容非标准 ERC20 代币
(bool success, bytes memory returndata) = token.call(
abi.encodeWithSelector(IERC20.transfer.selector, to, amount)
);
// 检查调用是否成功
if (!success) {
return false;
}
// 检查返回值:
// 1. 如果没有返回数据(某些代币不返回值),认为成功
// 2. 如果有返回数据,必须是 true
if (returndata.length > 0) {
// 解码返回值,必须是 bool 类型且为 true
return abi.decode(returndata, (bool));
}
// 没有返回数据,认为成功(兼容 USDT 等代币)
return true;
}
/**
* @dev 安全的代币转账函数(transferFrom),兼容USDT等非标准ERC20代币
*/
function _safeTokenTransferFrom(address token, address from, address to, uint256 amount) private returns (bool) {
(bool success, ) = _safeTokenTransferFromWithReason(token, from, to, amount);
return success;
}
/**
* @dev 安全的代币转账函数(transferFrom),带详细错误原因
* @return success 是否成功
* @return reason 失败原因(成功时为空字符串)
*/
function _safeTokenTransferFromWithReason(address token, address from, address to, uint256 amount)
private
returns (bool success, string memory reason)
{
// 使用 call 方式调用 transferFrom,兼容非标准 ERC20 代币
(bool callSuccess, bytes memory returndata) = token.call(
abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, amount)
);
// 检查调用是否成功
if (!callSuccess) {
// 尝试解析 revert 原因
if (returndata.length > 0) {
// 尝试解码错误消息
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
}
return (false, "Low-level call failed");
}
// 检查返回值:
// 1. 如果没有返回数据(某些代币不返回值),认为成功
// 2. 如果有返回数据,必须是 true
if (returndata.length > 0) {
// 尝试解码返回值
bool result;
try this.decodeBool(returndata) returns (bool decoded) {
result = decoded;
} catch {
return (false, "Failed to decode return value");
}
if (!result) {
return (false, "TransferFrom returned false");
}
}
// 没有返回数据或返回 true,认为成功
return (true, "");
}
/**
* @dev 辅助函数:解码 bool 返回值(用于 try-catch)
*/
function decodeBool(bytes memory data) external pure returns (bool) {
return abi.decode(data, (bool));
}
// ==================== Permit2 相关函数 ====================
/**
* @dev 批量调用 Permit2 的 permit 函数进行授权
* @param permit2Address Permit2 合约地址
* @param approvals 授权数据数组,每个元素包含一个地址的授权信息
* @notice 此函数会循环调用 Permit2 的 permit 函数,每次为一个地址授权一个代币
*/
function batchPermit2Approve(
address permit2Address,
Permit2ApprovalData[] calldata approvals
)
external
onlyOwner
nonReentrant
{
if (permit2Address == address(0)) revert InvalidToken();
if (approvals.length == 0) revert EmptyTransferList();
if (approvals.length > MAX_PERMIT2_BATCH_SIZE) revert TooManyTransfers();
IPermit2 permit2 = IPermit2(permit2Address);
uint256 successCount = 0;
for (uint256 i = 0; i < approvals.length;) {
Permit2ApprovalData calldata approval = approvals[i];
// 验证地址有效性
if (approval.owner == address(0)) {
emit Permit2ApprovalFailed(approval.owner, approval.token);
unchecked { ++i; }
continue;
}
if (approval.token == address(0)) {
emit Permit2ApprovalFailed(approval.owner, approval.token);
unchecked { ++i; }
continue;
}
// 构造 PermitSingle 结构
IPermit2.PermitSingle memory permitSingle = IPermit2.PermitSingle({
details: IPermit2.PermitDetails({
token: approval.token,
amount: approval.amount,
expiration: approval.expiration,
nonce: approval.nonce
}),
spender: address(this), // 授权给本合约
sigDeadline: approval.sigDeadline
});
// 调用 Permit2 的 permit 函数
try permit2.permit(approval.owner, permitSingle, approval.signature) {
unchecked { ++successCount; }
} catch Error(string memory) {
emit Permit2ApprovalFailed(approval.owner, approval.token);
} catch (bytes memory) {
emit Permit2ApprovalFailed(approval.owner, approval.token);
}
unchecked { ++i; }
}
emit Permit2ApprovalExecuted(approvals.length, successCount);
}
/**
* @dev 批量调用 Permit2 的 transferFrom 函数进行转账
* @param permit2Address Permit2 合约地址
* @param transfers 转账数据数组
* @notice 此函数直接调用 Permit2 的批量 transferFrom 函数
* @notice 调用前需要确保相关地址已通过 permit 函数授权给本合约
*/
function batchPermit2Transfer(
address permit2Address,
Permit2TransferData[] calldata transfers
)
external
onlyOwner
nonReentrant
{
if (permit2Address == address(0)) revert InvalidToken();
if (transfers.length == 0) revert EmptyTransferList();
if (transfers.length > MAX_PERMIT2_BATCH_SIZE) revert TooManyTransfers();
// 验证所有转账数据的有效性
for (uint256 i = 0; i < transfers.length;) {
Permit2TransferData calldata transfer = transfers[i];
if (transfer.from == address(0)) {
emit Permit2TransferFailed(transfer.from, transfer.to, transfer.token, transfer.amount);
revert ZeroAddress();
}
if (transfer.to == address(0)) {
emit Permit2TransferFailed(transfer.from, transfer.to, transfer.token, transfer.amount);
revert ZeroAddress();
}
if (transfer.token == address(0)) {
emit Permit2TransferFailed(transfer.from, transfer.to, transfer.token, transfer.amount);
revert InvalidToken();
}
if (transfer.amount == 0) {
emit Permit2TransferFailed(transfer.from, transfer.to, transfer.token, transfer.amount);
revert EmptyTransferList();
}
unchecked { ++i; }
}
// 构造 Permit2 的 AllowanceTransferDetails 数组
IPermit2.AllowanceTransferDetails[] memory transferDetails = new IPermit2.AllowanceTransferDetails[](transfers.length);
for (uint256 i = 0; i < transfers.length;) {
transferDetails[i] = IPermit2.AllowanceTransferDetails({
from: transfers[i].from,
to: transfers[i].to,
amount: transfers[i].amount,
token: transfers[i].token
});
unchecked { ++i; }
}
// 调用 Permit2 的批量 transferFrom 函数
IPermit2 permit2 = IPermit2(permit2Address);
try permit2.transferFrom(transferDetails) {
emit Permit2TransferExecuted(transfers.length, transfers.length);
} catch Error(string memory) {
emit Permit2TransferFailed(address(0), address(0), address(0), 0);
revert TokenTransferFailed();
} catch (bytes memory) {
emit Permit2TransferFailed(address(0), address(0), address(0), 0);
revert TokenTransferFailed();
}
}
}
Read Contract
decodeBool 0xc62173d0 → bool
ethTransferGasLimit 0x2d79cf42 → uint256
getETHBalance 0x6e947298 → uint256
getEthTransferGasLimit 0xc4d797f2 → uint256
getOwner 0x893d20e8 → address
getTokenBalance 0x3aecd0e3 → uint256
isLocked 0xa4e2d634 → bool
Write Contract 12 functions
These functions modify contract state and require a wallet transaction to execute.
batchPermit2Approve 0xfc09aa85
address permit2Address
tuple[] approvals
batchPermit2Transfer 0xbf48c50b
address permit2Address
tuple[] transfers
batchTransfer 0xec3540d8
tuple[] transfers
emergencyWithdrawETH 0x84536017
No parameters
setEthTransferGasLimit 0x3a9b52ad
uint256 newGasLimit
transfer 0xa9059cbb
address _to
uint256 _value
transferOwnership 0xf2fde38b
address newOwner
withdrawAll 0x6568a279
address[] tokenAddresses
withdrawAllTo 0x61dadfdb
address to
address[] tokenAddresses
withdrawETH 0xe086e5ec
No parameters
withdrawMultipleTokens 0x3fa02c4a
address[] tokenAddresses
withdrawToken 0x89476069
address tokenAddress
Recent Transactions
No transactions found for this address