diff --git a/src/abis/Flashloan.json b/src/abis/Flashloan.json index f0a936d..39f1179 100644 --- a/src/abis/Flashloan.json +++ b/src/abis/Flashloan.json @@ -182,72 +182,14 @@ { "components": [ { - "components": [ - { - "internalType": "uint8", - "name": "protocol", - "type": "uint8" - }, - { - "internalType": "uint16", - "name": "part", - "type": "uint16" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct IFlashloan.Swap[]", - "name": "swaps", - "type": "tuple[]" + "internalType": "uint8", + "name": "protocol", + "type": "uint8" }, { - "internalType": "address[]", - "name": "path", - "type": "address[]" - } - ], - "internalType": "struct IFlashloan.Hop[]", - "name": "hops", - "type": "tuple[]" - }, - { - "internalType": "uint16", - "name": "part", - "type": "uint16" - } - ], - "internalType": "struct IFlashloan.Route[]", - "name": "firstRoutes", - "type": "tuple[]" - }, - { - "components": [ - { - "components": [ - { - "components": [ - { - "internalType": "uint8", - "name": "protocol", - "type": "uint8" - }, - { - "internalType": "uint16", - "name": "part", - "type": "uint16" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "internalType": "struct IFlashloan.Swap[]", - "name": "swaps", - "type": "tuple[]" + "internalType": "bytes", + "name": "data", + "type": "bytes" }, { "internalType": "address[]", @@ -266,7 +208,7 @@ } ], "internalType": "struct IFlashloan.Route[]", - "name": "secondRoutes", + "name": "routes", "type": "tuple[]" } ], @@ -337,8 +279,8 @@ "type": "function" } ], - "bytecode": "0x608060405234801561001057600080fd5b5061001a33610023565b60018055610073565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b612b0980620000836000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b146100d0578063d5b99797146100bd578063eb2021c3146100bd578063f2fde38b146100f257600080fd5b806301e336671461008d578063715018a6146100a257806371b708d5146100aa5780637ed1f1dd146100bd575b600080fd5b6100a061009b366004611ec4565b610105565b005b6100a0610251565b6100a06100b8366004611f3b565b610287565b6100a06100cb366004611df5565b61063b565b6000546001600160a01b03166040516100e99190612687565b60405180910390f35b6100a0610100366004611d32565b61064f565b6000546001600160a01b031633146101385760405162461bcd60e51b815260040161012f90612772565b60405180910390fd5b6002600154141561015b5760405162461bcd60e51b815260040161012f906127f2565b60026001556040516370a0823160e01b815281906001600160a01b038516906370a082319061018e903090600401612687565b60206040518083038186803b1580156101a657600080fd5b505afa1580156101ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101de9190611f6f565b10156101fc5760405162461bcd60e51b815260040161012f90612762565b6102078383836106ab565b816001600160a01b03167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65826040516102409190612832565b60405180910390a250506001805550565b6000546001600160a01b0316331461027b5760405162461bcd60e51b815260040161012f90612772565b6102856000610706565b565b8060006102bf82604001516000815181106102b257634e487b7160e01b600052603260045260246000fd5b6020026020010151610756565b9050600082600001516001600160a01b0316634a248d2a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561030057600080fd5b505afa158015610314573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103389190611d50565b6001600160a01b0316826001600160a01b0316149050600083600001516001600160a01b031663d4b970466040518163ffffffff1660e01b815260040160206040518083038186803b15801561038d57600080fd5b505afa1580156103a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c59190611d50565b6001600160a01b0316836001600160a01b031614905081806103e45750805b6104005760405162461bcd60e51b815260040161012f906127c2565b60006040518060a00160405280336001600160a01b0316815260200187600001516001600160a01b031681526020018760200151815260200187604001518152602001876060015181525060405160200161045b9190612821565b6040516020818303038152906040529050600061049687604001516000815181106102b257634e487b7160e01b600052603260045260246000fd5b905086600001516001600160a01b031663d0a494e4826001600160a01b031689600001516001600160a01b0316634a248d2a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156104f257600080fd5b505afa158015610506573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061052a9190611d50565b6001600160a01b03161461053f576000610545565b88602001515b836001600160a01b03168a600001516001600160a01b0316634a248d2a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561058c57600080fd5b505afa1580156105a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c49190611d50565b6001600160a01b0316146105dc5789602001516105df565b60005b30866040518563ffffffff1660e01b81526004016106009493929190612893565b600060405180830381600087803b15801561061a57600080fd5b505af115801561062e573d6000803e3d6000fd5b5050505050505050505050565b61064885858585856107b8565b5050505050565b6000546001600160a01b031633146106795760405162461bcd60e51b815260040161012f90612772565b6001600160a01b03811661069f5760405162461bcd60e51b815260040161012f90612732565b6106a881610706565b50565b6107018363a9059cbb60e01b84846040516024016106ca929190612706565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610c83565b505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000816000015160008151811061077d57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516000815181106107a957634e487b7160e01b600052603260045260246000fd5b60200260200101519050919050565b60006107c682840184611f07565b905060006107f282606001516000815181106102b257634e487b7160e01b600052603260045260246000fd5b9050600061081e83608001516000815181106102b257634e487b7160e01b600052603260045260246000fd5b90508260400151826001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016108519190612687565b60206040518083038186803b15801561086957600080fd5b505afa15801561087d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a19190611f6f565b10156108bf5760405162461bcd60e51b815260040161012f90612742565b6108d183606001518460400151610d12565b6040516370a0823160e01b81526000906001600160a01b038316906370a0823190610900903090600401612687565b60206040518083038186803b15801561091857600080fd5b505afa15801561092c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109509190611f6f565b9050610960846080015182610d12565b7ffdc1bd83776f7aa310fcf2b1915ae1c6c16a4cfb48ebcea2bf15febd084c03de83846001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016109ae9190612687565b60206040518083038186803b1580156109c657600080fd5b505afa1580156109da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109fe9190611f6f565b604051610a0c929190612706565b60405180910390a160408085015190516370a0823160e01b81526001600160a01b038516906370a0823190610a45903090600401612687565b60206040518083038186803b158015610a5d57600080fd5b505afa158015610a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a959190611f6f565b1015610ab35760405162461bcd60e51b815260040161012f90612792565b6020840151604080860151905163a9059cbb60e01b81526001600160a01b0386169263a9059cbb92610ae792600401612706565b602060405180830381600087803b158015610b0157600080fd5b505af1158015610b15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b399190611ea6565b506040516370a0823160e01b81526000906001600160a01b038516906370a0823190610b69903090600401612687565b60206040518083038186803b158015610b8157600080fd5b505afa158015610b95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb99190611f6f565b855160405163a9059cbb60e01b81529192506001600160a01b0386169163a9059cbb91610bea918590600401612706565b602060405180830381600087803b158015610c0457600080fd5b505af1158015610c18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3c9190611ea6565b5084516040517f2b312ac7b7c9b2fc53c9398d48ed2df4c1d192a03cc090b47087b2936ba0a61f91610c6f918490612706565b60405180910390a150505050505050505050565b6000610cd8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610e1a9092919063ffffffff16565b8051909150156107015780806020019051810190610cf69190611ea6565b6107015760405162461bcd60e51b815260040161012f906127d2565b816000805b8251811015610d6b57828181518110610d4057634e487b7160e01b600052603260045260246000fd5b60200260200101516020015182610d579190612936565b915080610d6381612a2d565b915050610d17565b508061ffff1661271014610d915760405162461bcd60e51b815260040161012f90612802565b60005b8451811015610648576000610dd4868381518110610dc257634e487b7160e01b600052603260045260246000fd5b60200260200101516020015186610e33565b9050610e07868381518110610df957634e487b7160e01b600052603260045260246000fd5b602002602001015182610e50565b5080610e1281612a2d565b915050610d94565b6060610e298484600085610ead565b90505b9392505050565b6000612710610e4661ffff851684612986565b610e2c9190612972565b8060005b835151811015610ea757610e9384600001518281518110610e8557634e487b7160e01b600052603260045260246000fd5b602002602001015183610f66565b915080610e9f81612a2d565b915050610e54565b50505050565b606082471015610ecf5760405162461bcd60e51b815260040161012f90612752565b843b610eed5760405162461bcd60e51b815260040161012f906127b2565b600080866001600160a01b03168587604051610f09919061267b565b60006040518083038185875af1925050503d8060008114610f46576040519150601f19603f3d011682016040523d82523d6000602084013e610f4b565b606091505b5091509150610f5b828286611097565b979650505050505050565b815160009081805b8251811015610fc257828181518110610f9757634e487b7160e01b600052603260045260246000fd5b60200260200101516020015182610fae9190612936565b915080610fba81612a2d565b915050610f6e565b508061ffff1661271014610fe85760405162461bcd60e51b815260040161012f90612782565b6000805b86515181101561108d5760006110318860000151838151811061101f57634e487b7160e01b600052603260045260246000fd5b60200260200101516020015188610e33565b905061106d8860000151838151811061105a57634e487b7160e01b600052603260045260246000fd5b6020026020010151828a602001516110d0565b611077908461295f565b925050808061108590612a2d565b915050610fec565b5095945050505050565b606083156110a6575081610e2c565b8251156110b65782518084602001fd5b8160405162461bcd60e51b815260040161012f9190612721565b600083806000015160ff16600810156110fb5760405162461bcd60e51b815260040161012f906127e2565b845160ff1661111a5761111385604001518585611153565b915061114b565b6008856000015160ff16101561113957611113856040015185856112da565b611148856040015185856113e3565b91505b509392505050565b60008060008580602001905181019061116c9190611dbb565b9150915060008290506111a88560008151811061119957634e487b7160e01b600052603260045260246000fd5b6020026020010151828861164a565b806001600160a01b031663414bf389604051806101000160405280886000815181106111e457634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031681526020018860018151811061121b57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031681526020018562ffffff168152602001306001600160a01b031681526020014281526020018981526020016000815260200160006001600160a01b03168152506040518263ffffffff1660e01b81526004016112889190612812565b602060405180830381600087803b1580156112a257600080fd5b505af11580156112b6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5b9190611f6f565b600080848060200190518101906112f19190611d50565b90506113268360008151811061131757634e487b7160e01b600052603260045260246000fd5b6020026020010151828661164a565b6040516338ed173960e01b81526001600160a01b038216906338ed17399061135b908790600190889030904290600401612840565b600060405180830381600087803b15801561137557600080fd5b505af1158015611389573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113b19190810190611e72565b6001815181106113d157634e487b7160e01b600052603260045260246000fd5b60200260200101519150509392505050565b600080600080868060200190518101906113fd9190611d6e565b60408051600180825281830190925293965091945092506000919060208083019080368337019050509050838160008151811061144a57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b03168152505060008660008151811061148d57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316856001600160a01b0316634a248d2a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114d757600080fd5b505afa1580156114eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061150f9190611d50565b6001600160a01b031614611524576001611527565b60005b60ff16905061155f8760008151811061155057634e487b7160e01b600052603260045260246000fd5b6020026020010151858a61164a565b826001600160a01b031663f87dc1b78860008151811061158f57634e487b7160e01b600052603260045260246000fd5b6020026020010151896001815181106115b857634e487b7160e01b600052603260045260246000fd5b60200260200101518b600187876000426040518963ffffffff1660e01b81526004016115eb989796959493929190612695565b602060405180830381600087803b15801561160557600080fd5b505af1158015611619573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061163d9190611f6f565b9998505050505050505050565b60405163095ea7b360e01b81526001600160a01b0384169063095ea7b3906116789085908590600401612706565b602060405180830381600087803b15801561169257600080fd5b505af11580156116a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ca9190611ea6565b6107015760405162461bcd60e51b815260040161012f906127a2565b60006116f96116f4846128e9565b6128cd565b9050808382526020820190508285602086028201111561171857600080fd5b60005b85811015611744578161172e888261192e565b845250602092830192919091019060010161171b565b5050509392505050565b600061175c6116f4846128e9565b9050808382526020820190508285602086028201111561177b57600080fd5b60005b858110156117445781356001600160401b0381111561179c57600080fd5b8086016117a98982611bc4565b85525050602092830192919091019060010161177e565b60006117ce6116f4846128e9565b905080838252602082019050828560208602820111156117ed57600080fd5b60005b858110156117445781356001600160401b0381111561180e57600080fd5b80860161181b8982611c38565b8552505060209283019291909101906001016117f0565b60006118406116f4846128e9565b9050808382526020820190508285602086028201111561185f57600080fd5b60005b858110156117445781356001600160401b0381111561188057600080fd5b80860161188d8982611c89565b855250506020928301929190910190600101611862565b60006118b26116f4846128e9565b905080838252602082019050828560208602820111156118d157600080fd5b60005b8581101561174457816118e78882611d1c565b84525060209283019291909101906001016118d4565b600061190b6116f48461290c565b90508281526020810184848401111561192357600080fd5b61114b8482856129c9565b803561193981612a8a565b92915050565b805161193981612a8a565b600082601f83011261195b57600080fd5b813561196b8482602086016116e6565b949350505050565b600082601f83011261198457600080fd5b813561196b84826020860161174e565b600082601f8301126119a557600080fd5b813561196b8482602086016117c0565b600082601f8301126119c657600080fd5b813561196b848260208601611832565b600082601f8301126119e757600080fd5b815161196b8482602086016118a4565b805161193981612a9e565b60008083601f840112611a1457600080fd5b5081356001600160401b03811115611a2b57600080fd5b602083019150836001820283011115611a4357600080fd5b9250929050565b600082601f830112611a5b57600080fd5b813561196b8482602086016118fd565b803561193981612aa6565b600060a08284031215611a8857600080fd5b611a9260a06128cd565b90506000611aa0848461192e565b8252506020611ab18484830161192e565b6020830152506040611ac584828501611d11565b60408301525060608201356001600160401b03811115611ae457600080fd5b611af084828501611994565b60608301525060808201356001600160401b03811115611b0f57600080fd5b611b1b84828501611994565b60808301525092915050565b600060808284031215611b3957600080fd5b611b4360806128cd565b90506000611b51848461192e565b8252506020611b6284848301611d11565b60208301525060408201356001600160401b03811115611b8157600080fd5b611b8d84828501611994565b60408301525060608201356001600160401b03811115611bac57600080fd5b611bb884828501611994565b60608301525092915050565b600060408284031215611bd657600080fd5b611be060406128cd565b905081356001600160401b03811115611bf857600080fd5b611c04848285016119b5565b82525060208201356001600160401b03811115611c2057600080fd5b611c2c8482850161194a565b60208301525092915050565b600060408284031215611c4a57600080fd5b611c5460406128cd565b905081356001600160401b03811115611c6c57600080fd5b611c7884828501611973565b8252506020611c2c84848301611cfb565b600060608284031215611c9b57600080fd5b611ca560606128cd565b90506000611cb38484611d27565b8252506020611cc484848301611cfb565b60208301525060408201356001600160401b03811115611ce357600080fd5b611cef84828501611a4a565b60408301525092915050565b803561193981612aaf565b805161193981612ab9565b803561193981612ac4565b805161193981612ac4565b803561193981612aca565b600060208284031215611d4457600080fd5b600061196b848461192e565b600060208284031215611d6257600080fd5b600061196b848461193f565b600080600060608486031215611d8357600080fd5b6000611d8f868661193f565b9350506020611da08682870161193f565b9250506040611db18682870161193f565b9150509250925092565b60008060408385031215611dce57600080fd5b6000611dda858561193f565b9250506020611deb85828601611d06565b9150509250929050565b600080600080600060808688031215611e0d57600080fd5b6000611e19888861192e565b9550506020611e2a88828901611d11565b9450506040611e3b88828901611d11565b93505060608601356001600160401b03811115611e5757600080fd5b611e6388828901611a02565b92509250509295509295909350565b600060208284031215611e8457600080fd5b81516001600160401b03811115611e9a57600080fd5b61196b848285016119d6565b600060208284031215611eb857600080fd5b600061196b84846119f7565b600080600060608486031215611ed957600080fd5b6000611ee58686611a6b565b9350506020611ef68682870161192e565b9250506040611db186828701611d11565b600060208284031215611f1957600080fd5b81356001600160401b03811115611f2f57600080fd5b61196b84828501611a76565b600060208284031215611f4d57600080fd5b81356001600160401b03811115611f6357600080fd5b61196b84828501611b27565b600060208284031215611f8157600080fd5b600061196b8484611d1c565b6000611f998383611fc5565b505060200190565b6000610e2c83836125aa565b6000610e2c83836125dc565b6000610e2c8383612609565b611fce816129a5565b82525050565b6000611fde825190565b80845260209384019383018060005b838110156120125781516120018882611f8d565b975060208301925050600101611fed565b509495945050505050565b6000612027825190565b80845260209384019383018060005b8381101561201257815161204a8882611f8d565b975060208301925050600101612036565b6000612065825190565b8084526020840193508360208202850161207f8560200190565b8060005b858110156120b4578484038952815161209c8582611fa1565b94506020830160209a909a0199925050600101612083565b5091979650505050505050565b60006120cb825190565b808452602084019350836020820285016120e58560200190565b8060005b858110156120b457848403895281516121028582611fad565b94506020830160209a909a01999250506001016120e9565b6000612124825190565b8084526020840193508360208202850161213e8560200190565b8060005b858110156120b4578484038952815161215b8582611fb9565b94506020830160209a909a0199925050600101612142565b801515611fce565b6000612185825190565b80845260208401935061219c8185602086016129d5565b601f01601f19169290920192915050565b60006121b7825190565b6121c58185602086016129d5565b9290920192915050565b611fce816129c1565b602681526000602082017f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206181526564647265737360d01b602082015291505b5060400190565b601b81526000602082017f4661696c656420746f20626f72726f77206c6f616e20746f6b656e0000000000815291505b5060200190565b602681526000602082017f416464726573733a20696e73756666696369656e742062616c616e636520666f8152651c8818d85b1b60d21b60208201529150612217565b601081526000602082016f2737ba1032b737bab3b4103a37b5b2b760811b8152915061224e565b60208082527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65729101908152600061224e565b600f81526000602082016e29bbb0b8103830b93a1032b93937b960891b8152915061224e565b60208082527f4e6f7420656e6f75676820616d6f756e7420746f2072657475726e206c6f616e9101908152600061224e565b600f81526000602082016e30b8383937bb32903330b4b632b21760891b8152915061224e565b601d81526000602082017f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000008152915061224e565b601c81526000602082017f57726f6e6720666c6173686c6f616e20706f6f6c2061646472657373000000008152915061224e565b602a81526000602082017f5361666545524332303a204552433230206f7065726174696f6e20646964206e8152691bdd081cdd58d8d9595960b21b60208201529150612217565b600e81526000602082016d15dc9bdb99c81c1c9bdd1bd8dbdb60921b8152915061224e565b601f81526000602082017f5265656e7472616e637947756172643a207265656e7472616e742063616c6c008152915061224e565b601081526000602082016f2937baba32903830b93a1032b93937b960811b8152915061224e565b80516101008301906124b08482611fc5565b5060208201516124c36020850182611fc5565b5060408201516124d66040850182612661565b5060608201516124e96060850182611fc5565b5060808201516124fc608085018261266c565b5060a082015161250f60a085018261266c565b5060c082015161252260c085018261266c565b5060e0820151610ea760e0850182612648565b805160009060a08401906125498582611fc5565b50602083015161255c6020860182611fc5565b50604083015161256f604086018261266c565b506060830151848203606086015261258782826120c1565b915050608083015184820360808601526125a182826120c1565b95945050505050565b80516040808452600091908401906125c2828261211a565b915050602083015184820360208601526125a18282611fd4565b80516040808452600091908401906125f4828261205b565b915050602083015161114b6020860182612657565b8051600090606084019061261d8582612672565b5060208301516126306020860182612657565b50604083015184820360408601526125a1828261217b565b6001600160a01b038116611fce565b61ffff8116611fce565b62ffffff8116611fce565b80611fce565b60ff8116611fce565b6000610e2c82846121ad565b602081016119398284611fc5565b61010081016126a4828b611fc5565b6126b1602083018a611fc5565b6126be604083018961266c565b6126cb60608301886121cf565b81810360808301526126dd818761201d565b90506126ec60a083018661266c565b6126f960c0830185612173565b61163d60e083018461266c565b604081016127148285611fc5565b610e2c602083018461266c565b60208082528101610e2c818461217b565b60208082528101611939816121d8565b602080825281016119398161221e565b6020808252810161193981612255565b6020808252810161193981612298565b60208082528101611939816122bf565b60208082528101611939816122f1565b6020808252810161193981612317565b6020808252810161193981612349565b602080825281016119398161236f565b60208082528101611939816123a3565b60208082528101611939816123d7565b602080825281016119398161241e565b6020808252810161193981612443565b6020808252810161193981612477565b6101008101611939828461249e565b60208082528101610e2c8184612535565b60208101611939828461266c565b60a0810161284e828861266c565b61285b60208301876121cf565b818103604083015261286d818661201d565b905061287c6060830185611fc5565b612889608083018461266c565b9695505050505050565b608081016128a1828761266c565b6128ae602083018661266c565b6128bb6040830185611fc5565b8181036060830152612889818461217b565b60006128d860405190565b90506128e48282612a01565b919050565b60006001600160401b0382111561290257612902612a74565b5060209081020190565b60006001600160401b0382111561292557612925612a74565b601f19601f83011660200192915050565b600061ffff8216915061ffff831692508261ffff0382111561295a5761295a612a48565b500190565b6000821982111561295a5761295a612a48565b60008261298157612981612a5e565b500490565b60008160001904831182151516156129a0576129a0612a48565b500290565b60006001600160a01b038216611939565b6000611939826129a5565b600081611939565b82818337506000910152565b60005b838110156129f05781810151838201526020016129d8565b83811115610ea75750506000910152565b601f19601f83011681018181106001600160401b0382111715612a2657612a26612a74565b6040525050565b6000600019821415612a4157612a41612a48565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b612a93816129a5565b81146106a857600080fd5b801515612a93565b612a93816129b6565b61ffff8116612a93565b62ffffff8116612a93565b80612a93565b60ff8116612a9356fea264697066735822122098d67de68d552858f280a0c0bbc3c81644327953b32d892044e10ac9d9fe7bfa64736f6c63430008040033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b146100d0578063d5b99797146100bd578063eb2021c3146100bd578063f2fde38b146100f257600080fd5b806301e336671461008d578063715018a6146100a257806371b708d5146100aa5780637ed1f1dd146100bd575b600080fd5b6100a061009b366004611ec4565b610105565b005b6100a0610251565b6100a06100b8366004611f3b565b610287565b6100a06100cb366004611df5565b61063b565b6000546001600160a01b03166040516100e99190612687565b60405180910390f35b6100a0610100366004611d32565b61064f565b6000546001600160a01b031633146101385760405162461bcd60e51b815260040161012f90612772565b60405180910390fd5b6002600154141561015b5760405162461bcd60e51b815260040161012f906127f2565b60026001556040516370a0823160e01b815281906001600160a01b038516906370a082319061018e903090600401612687565b60206040518083038186803b1580156101a657600080fd5b505afa1580156101ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101de9190611f6f565b10156101fc5760405162461bcd60e51b815260040161012f90612762565b6102078383836106ab565b816001600160a01b03167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65826040516102409190612832565b60405180910390a250506001805550565b6000546001600160a01b0316331461027b5760405162461bcd60e51b815260040161012f90612772565b6102856000610706565b565b8060006102bf82604001516000815181106102b257634e487b7160e01b600052603260045260246000fd5b6020026020010151610756565b9050600082600001516001600160a01b0316634a248d2a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561030057600080fd5b505afa158015610314573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103389190611d50565b6001600160a01b0316826001600160a01b0316149050600083600001516001600160a01b031663d4b970466040518163ffffffff1660e01b815260040160206040518083038186803b15801561038d57600080fd5b505afa1580156103a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103c59190611d50565b6001600160a01b0316836001600160a01b031614905081806103e45750805b6104005760405162461bcd60e51b815260040161012f906127c2565b60006040518060a00160405280336001600160a01b0316815260200187600001516001600160a01b031681526020018760200151815260200187604001518152602001876060015181525060405160200161045b9190612821565b6040516020818303038152906040529050600061049687604001516000815181106102b257634e487b7160e01b600052603260045260246000fd5b905086600001516001600160a01b031663d0a494e4826001600160a01b031689600001516001600160a01b0316634a248d2a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156104f257600080fd5b505afa158015610506573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061052a9190611d50565b6001600160a01b03161461053f576000610545565b88602001515b836001600160a01b03168a600001516001600160a01b0316634a248d2a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561058c57600080fd5b505afa1580156105a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c49190611d50565b6001600160a01b0316146105dc5789602001516105df565b60005b30866040518563ffffffff1660e01b81526004016106009493929190612893565b600060405180830381600087803b15801561061a57600080fd5b505af115801561062e573d6000803e3d6000fd5b5050505050505050505050565b61064885858585856107b8565b5050505050565b6000546001600160a01b031633146106795760405162461bcd60e51b815260040161012f90612772565b6001600160a01b03811661069f5760405162461bcd60e51b815260040161012f90612732565b6106a881610706565b50565b6107018363a9059cbb60e01b84846040516024016106ca929190612706565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610c83565b505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000816000015160008151811061077d57634e487b7160e01b600052603260045260246000fd5b6020026020010151602001516000815181106107a957634e487b7160e01b600052603260045260246000fd5b60200260200101519050919050565b60006107c682840184611f07565b905060006107f282606001516000815181106102b257634e487b7160e01b600052603260045260246000fd5b9050600061081e83608001516000815181106102b257634e487b7160e01b600052603260045260246000fd5b90508260400151826001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016108519190612687565b60206040518083038186803b15801561086957600080fd5b505afa15801561087d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a19190611f6f565b10156108bf5760405162461bcd60e51b815260040161012f90612742565b6108d183606001518460400151610d12565b6040516370a0823160e01b81526000906001600160a01b038316906370a0823190610900903090600401612687565b60206040518083038186803b15801561091857600080fd5b505afa15801561092c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109509190611f6f565b9050610960846080015182610d12565b7ffdc1bd83776f7aa310fcf2b1915ae1c6c16a4cfb48ebcea2bf15febd084c03de83846001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016109ae9190612687565b60206040518083038186803b1580156109c657600080fd5b505afa1580156109da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109fe9190611f6f565b604051610a0c929190612706565b60405180910390a160408085015190516370a0823160e01b81526001600160a01b038516906370a0823190610a45903090600401612687565b60206040518083038186803b158015610a5d57600080fd5b505afa158015610a71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a959190611f6f565b1015610ab35760405162461bcd60e51b815260040161012f90612792565b6020840151604080860151905163a9059cbb60e01b81526001600160a01b0386169263a9059cbb92610ae792600401612706565b602060405180830381600087803b158015610b0157600080fd5b505af1158015610b15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b399190611ea6565b506040516370a0823160e01b81526000906001600160a01b038516906370a0823190610b69903090600401612687565b60206040518083038186803b158015610b8157600080fd5b505afa158015610b95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb99190611f6f565b855160405163a9059cbb60e01b81529192506001600160a01b0386169163a9059cbb91610bea918590600401612706565b602060405180830381600087803b158015610c0457600080fd5b505af1158015610c18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3c9190611ea6565b5084516040517f2b312ac7b7c9b2fc53c9398d48ed2df4c1d192a03cc090b47087b2936ba0a61f91610c6f918490612706565b60405180910390a150505050505050505050565b6000610cd8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610e1a9092919063ffffffff16565b8051909150156107015780806020019051810190610cf69190611ea6565b6107015760405162461bcd60e51b815260040161012f906127d2565b816000805b8251811015610d6b57828181518110610d4057634e487b7160e01b600052603260045260246000fd5b60200260200101516020015182610d579190612936565b915080610d6381612a2d565b915050610d17565b508061ffff1661271014610d915760405162461bcd60e51b815260040161012f90612802565b60005b8451811015610648576000610dd4868381518110610dc257634e487b7160e01b600052603260045260246000fd5b60200260200101516020015186610e33565b9050610e07868381518110610df957634e487b7160e01b600052603260045260246000fd5b602002602001015182610e50565b5080610e1281612a2d565b915050610d94565b6060610e298484600085610ead565b90505b9392505050565b6000612710610e4661ffff851684612986565b610e2c9190612972565b8060005b835151811015610ea757610e9384600001518281518110610e8557634e487b7160e01b600052603260045260246000fd5b602002602001015183610f66565b915080610e9f81612a2d565b915050610e54565b50505050565b606082471015610ecf5760405162461bcd60e51b815260040161012f90612752565b843b610eed5760405162461bcd60e51b815260040161012f906127b2565b600080866001600160a01b03168587604051610f09919061267b565b60006040518083038185875af1925050503d8060008114610f46576040519150601f19603f3d011682016040523d82523d6000602084013e610f4b565b606091505b5091509150610f5b828286611097565b979650505050505050565b815160009081805b8251811015610fc257828181518110610f9757634e487b7160e01b600052603260045260246000fd5b60200260200101516020015182610fae9190612936565b915080610fba81612a2d565b915050610f6e565b508061ffff1661271014610fe85760405162461bcd60e51b815260040161012f90612782565b6000805b86515181101561108d5760006110318860000151838151811061101f57634e487b7160e01b600052603260045260246000fd5b60200260200101516020015188610e33565b905061106d8860000151838151811061105a57634e487b7160e01b600052603260045260246000fd5b6020026020010151828a602001516110d0565b611077908461295f565b925050808061108590612a2d565b915050610fec565b5095945050505050565b606083156110a6575081610e2c565b8251156110b65782518084602001fd5b8160405162461bcd60e51b815260040161012f9190612721565b600083806000015160ff16600810156110fb5760405162461bcd60e51b815260040161012f906127e2565b845160ff1661111a5761111385604001518585611153565b915061114b565b6008856000015160ff16101561113957611113856040015185856112da565b611148856040015185856113e3565b91505b509392505050565b60008060008580602001905181019061116c9190611dbb565b9150915060008290506111a88560008151811061119957634e487b7160e01b600052603260045260246000fd5b6020026020010151828861164a565b806001600160a01b031663414bf389604051806101000160405280886000815181106111e457634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031681526020018860018151811061121b57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031681526020018562ffffff168152602001306001600160a01b031681526020014281526020018981526020016000815260200160006001600160a01b03168152506040518263ffffffff1660e01b81526004016112889190612812565b602060405180830381600087803b1580156112a257600080fd5b505af11580156112b6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5b9190611f6f565b600080848060200190518101906112f19190611d50565b90506113268360008151811061131757634e487b7160e01b600052603260045260246000fd5b6020026020010151828661164a565b6040516338ed173960e01b81526001600160a01b038216906338ed17399061135b908790600190889030904290600401612840565b600060405180830381600087803b15801561137557600080fd5b505af1158015611389573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113b19190810190611e72565b6001815181106113d157634e487b7160e01b600052603260045260246000fd5b60200260200101519150509392505050565b600080600080868060200190518101906113fd9190611d6e565b60408051600180825281830190925293965091945092506000919060208083019080368337019050509050838160008151811061144a57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b03168152505060008660008151811061148d57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316856001600160a01b0316634a248d2a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114d757600080fd5b505afa1580156114eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061150f9190611d50565b6001600160a01b031614611524576001611527565b60005b60ff16905061155f8760008151811061155057634e487b7160e01b600052603260045260246000fd5b6020026020010151858a61164a565b826001600160a01b031663f87dc1b78860008151811061158f57634e487b7160e01b600052603260045260246000fd5b6020026020010151896001815181106115b857634e487b7160e01b600052603260045260246000fd5b60200260200101518b600187876000426040518963ffffffff1660e01b81526004016115eb989796959493929190612695565b602060405180830381600087803b15801561160557600080fd5b505af1158015611619573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061163d9190611f6f565b9998505050505050505050565b60405163095ea7b360e01b81526001600160a01b0384169063095ea7b3906116789085908590600401612706565b602060405180830381600087803b15801561169257600080fd5b505af11580156116a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ca9190611ea6565b6107015760405162461bcd60e51b815260040161012f906127a2565b60006116f96116f4846128e9565b6128cd565b9050808382526020820190508285602086028201111561171857600080fd5b60005b85811015611744578161172e888261192e565b845250602092830192919091019060010161171b565b5050509392505050565b600061175c6116f4846128e9565b9050808382526020820190508285602086028201111561177b57600080fd5b60005b858110156117445781356001600160401b0381111561179c57600080fd5b8086016117a98982611bc4565b85525050602092830192919091019060010161177e565b60006117ce6116f4846128e9565b905080838252602082019050828560208602820111156117ed57600080fd5b60005b858110156117445781356001600160401b0381111561180e57600080fd5b80860161181b8982611c38565b8552505060209283019291909101906001016117f0565b60006118406116f4846128e9565b9050808382526020820190508285602086028201111561185f57600080fd5b60005b858110156117445781356001600160401b0381111561188057600080fd5b80860161188d8982611c89565b855250506020928301929190910190600101611862565b60006118b26116f4846128e9565b905080838252602082019050828560208602820111156118d157600080fd5b60005b8581101561174457816118e78882611d1c565b84525060209283019291909101906001016118d4565b600061190b6116f48461290c565b90508281526020810184848401111561192357600080fd5b61114b8482856129c9565b803561193981612a8a565b92915050565b805161193981612a8a565b600082601f83011261195b57600080fd5b813561196b8482602086016116e6565b949350505050565b600082601f83011261198457600080fd5b813561196b84826020860161174e565b600082601f8301126119a557600080fd5b813561196b8482602086016117c0565b600082601f8301126119c657600080fd5b813561196b848260208601611832565b600082601f8301126119e757600080fd5b815161196b8482602086016118a4565b805161193981612a9e565b60008083601f840112611a1457600080fd5b5081356001600160401b03811115611a2b57600080fd5b602083019150836001820283011115611a4357600080fd5b9250929050565b600082601f830112611a5b57600080fd5b813561196b8482602086016118fd565b803561193981612aa6565b600060a08284031215611a8857600080fd5b611a9260a06128cd565b90506000611aa0848461192e565b8252506020611ab18484830161192e565b6020830152506040611ac584828501611d11565b60408301525060608201356001600160401b03811115611ae457600080fd5b611af084828501611994565b60608301525060808201356001600160401b03811115611b0f57600080fd5b611b1b84828501611994565b60808301525092915050565b600060808284031215611b3957600080fd5b611b4360806128cd565b90506000611b51848461192e565b8252506020611b6284848301611d11565b60208301525060408201356001600160401b03811115611b8157600080fd5b611b8d84828501611994565b60408301525060608201356001600160401b03811115611bac57600080fd5b611bb884828501611994565b60608301525092915050565b600060408284031215611bd657600080fd5b611be060406128cd565b905081356001600160401b03811115611bf857600080fd5b611c04848285016119b5565b82525060208201356001600160401b03811115611c2057600080fd5b611c2c8482850161194a565b60208301525092915050565b600060408284031215611c4a57600080fd5b611c5460406128cd565b905081356001600160401b03811115611c6c57600080fd5b611c7884828501611973565b8252506020611c2c84848301611cfb565b600060608284031215611c9b57600080fd5b611ca560606128cd565b90506000611cb38484611d27565b8252506020611cc484848301611cfb565b60208301525060408201356001600160401b03811115611ce357600080fd5b611cef84828501611a4a565b60408301525092915050565b803561193981612aaf565b805161193981612ab9565b803561193981612ac4565b805161193981612ac4565b803561193981612aca565b600060208284031215611d4457600080fd5b600061196b848461192e565b600060208284031215611d6257600080fd5b600061196b848461193f565b600080600060608486031215611d8357600080fd5b6000611d8f868661193f565b9350506020611da08682870161193f565b9250506040611db18682870161193f565b9150509250925092565b60008060408385031215611dce57600080fd5b6000611dda858561193f565b9250506020611deb85828601611d06565b9150509250929050565b600080600080600060808688031215611e0d57600080fd5b6000611e19888861192e565b9550506020611e2a88828901611d11565b9450506040611e3b88828901611d11565b93505060608601356001600160401b03811115611e5757600080fd5b611e6388828901611a02565b92509250509295509295909350565b600060208284031215611e8457600080fd5b81516001600160401b03811115611e9a57600080fd5b61196b848285016119d6565b600060208284031215611eb857600080fd5b600061196b84846119f7565b600080600060608486031215611ed957600080fd5b6000611ee58686611a6b565b9350506020611ef68682870161192e565b9250506040611db186828701611d11565b600060208284031215611f1957600080fd5b81356001600160401b03811115611f2f57600080fd5b61196b84828501611a76565b600060208284031215611f4d57600080fd5b81356001600160401b03811115611f6357600080fd5b61196b84828501611b27565b600060208284031215611f8157600080fd5b600061196b8484611d1c565b6000611f998383611fc5565b505060200190565b6000610e2c83836125aa565b6000610e2c83836125dc565b6000610e2c8383612609565b611fce816129a5565b82525050565b6000611fde825190565b80845260209384019383018060005b838110156120125781516120018882611f8d565b975060208301925050600101611fed565b509495945050505050565b6000612027825190565b80845260209384019383018060005b8381101561201257815161204a8882611f8d565b975060208301925050600101612036565b6000612065825190565b8084526020840193508360208202850161207f8560200190565b8060005b858110156120b4578484038952815161209c8582611fa1565b94506020830160209a909a0199925050600101612083565b5091979650505050505050565b60006120cb825190565b808452602084019350836020820285016120e58560200190565b8060005b858110156120b457848403895281516121028582611fad565b94506020830160209a909a01999250506001016120e9565b6000612124825190565b8084526020840193508360208202850161213e8560200190565b8060005b858110156120b4578484038952815161215b8582611fb9565b94506020830160209a909a0199925050600101612142565b801515611fce565b6000612185825190565b80845260208401935061219c8185602086016129d5565b601f01601f19169290920192915050565b60006121b7825190565b6121c58185602086016129d5565b9290920192915050565b611fce816129c1565b602681526000602082017f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206181526564647265737360d01b602082015291505b5060400190565b601b81526000602082017f4661696c656420746f20626f72726f77206c6f616e20746f6b656e0000000000815291505b5060200190565b602681526000602082017f416464726573733a20696e73756666696369656e742062616c616e636520666f8152651c8818d85b1b60d21b60208201529150612217565b601081526000602082016f2737ba1032b737bab3b4103a37b5b2b760811b8152915061224e565b60208082527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65729101908152600061224e565b600f81526000602082016e29bbb0b8103830b93a1032b93937b960891b8152915061224e565b60208082527f4e6f7420656e6f75676820616d6f756e7420746f2072657475726e206c6f616e9101908152600061224e565b600f81526000602082016e30b8383937bb32903330b4b632b21760891b8152915061224e565b601d81526000602082017f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000008152915061224e565b601c81526000602082017f57726f6e6720666c6173686c6f616e20706f6f6c2061646472657373000000008152915061224e565b602a81526000602082017f5361666545524332303a204552433230206f7065726174696f6e20646964206e8152691bdd081cdd58d8d9595960b21b60208201529150612217565b600e81526000602082016d15dc9bdb99c81c1c9bdd1bd8dbdb60921b8152915061224e565b601f81526000602082017f5265656e7472616e637947756172643a207265656e7472616e742063616c6c008152915061224e565b601081526000602082016f2937baba32903830b93a1032b93937b960811b8152915061224e565b80516101008301906124b08482611fc5565b5060208201516124c36020850182611fc5565b5060408201516124d66040850182612661565b5060608201516124e96060850182611fc5565b5060808201516124fc608085018261266c565b5060a082015161250f60a085018261266c565b5060c082015161252260c085018261266c565b5060e0820151610ea760e0850182612648565b805160009060a08401906125498582611fc5565b50602083015161255c6020860182611fc5565b50604083015161256f604086018261266c565b506060830151848203606086015261258782826120c1565b915050608083015184820360808601526125a182826120c1565b95945050505050565b80516040808452600091908401906125c2828261211a565b915050602083015184820360208601526125a18282611fd4565b80516040808452600091908401906125f4828261205b565b915050602083015161114b6020860182612657565b8051600090606084019061261d8582612672565b5060208301516126306020860182612657565b50604083015184820360408601526125a1828261217b565b6001600160a01b038116611fce565b61ffff8116611fce565b62ffffff8116611fce565b80611fce565b60ff8116611fce565b6000610e2c82846121ad565b602081016119398284611fc5565b61010081016126a4828b611fc5565b6126b1602083018a611fc5565b6126be604083018961266c565b6126cb60608301886121cf565b81810360808301526126dd818761201d565b90506126ec60a083018661266c565b6126f960c0830185612173565b61163d60e083018461266c565b604081016127148285611fc5565b610e2c602083018461266c565b60208082528101610e2c818461217b565b60208082528101611939816121d8565b602080825281016119398161221e565b6020808252810161193981612255565b6020808252810161193981612298565b60208082528101611939816122bf565b60208082528101611939816122f1565b6020808252810161193981612317565b6020808252810161193981612349565b602080825281016119398161236f565b60208082528101611939816123a3565b60208082528101611939816123d7565b602080825281016119398161241e565b6020808252810161193981612443565b6020808252810161193981612477565b6101008101611939828461249e565b60208082528101610e2c8184612535565b60208101611939828461266c565b60a0810161284e828861266c565b61285b60208301876121cf565b818103604083015261286d818661201d565b905061287c6060830185611fc5565b612889608083018461266c565b9695505050505050565b608081016128a1828761266c565b6128ae602083018661266c565b6128bb6040830185611fc5565b8181036060830152612889818461217b565b60006128d860405190565b90506128e48282612a01565b919050565b60006001600160401b0382111561290257612902612a74565b5060209081020190565b60006001600160401b0382111561292557612925612a74565b601f19601f83011660200192915050565b600061ffff8216915061ffff831692508261ffff0382111561295a5761295a612a48565b500190565b6000821982111561295a5761295a612a48565b60008261298157612981612a5e565b500490565b60008160001904831182151516156129a0576129a0612a48565b500290565b60006001600160a01b038216611939565b6000611939826129a5565b600081611939565b82818337506000910152565b60005b838110156129f05781810151838201526020016129d8565b83811115610ea75750506000910152565b601f19601f83011681018181106001600160401b0382111715612a2657612a26612a74565b6040525050565b6000600019821415612a4157612a41612a48565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b612a93816129a5565b81146106a857600080fd5b801515612a93565b612a93816129b6565b61ffff8116612a93565b62ffffff8116612a93565b80612a93565b60ff8116612a9356fea264697066735822122098d67de68d552858f280a0c0bbc3c81644327953b32d892044e10ac9d9fe7bfa64736f6c63430008040033", + "bytecode": "0x608060405234801561001057600080fd5b5061001a33610023565b60018055610073565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b612675806100826000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b146100d0578063d5b99797146100bd578063eb2021c3146100bd578063f2fde38b146100f257600080fd5b806301e336671461008d5780630cdabeba146100a2578063715018a6146100b55780637ed1f1dd146100bd575b600080fd5b6100a061009b366004611b58565b610105565b005b6100a06100b0366004611bcf565b610251565b6100a06105ec565b6100a06100cb366004611a89565b610622565b6000546001600160a01b03166040516100e99190612226565b60405180910390f35b6100a06101003660046119c6565b610636565b6000546001600160a01b031633146101385760405162461bcd60e51b815260040161012f90612311565b60405180910390fd5b6002600154141561015b5760405162461bcd60e51b815260040161012f90612371565b60026001556040516370a0823160e01b815281906001600160a01b038516906370a082319061018e903090600401612226565b60206040518083038186803b1580156101a657600080fd5b505afa1580156101ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101de9190611c03565b10156101fc5760405162461bcd60e51b815260040161012f90612301565b610207838383610692565b816001600160a01b03167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b658260405161024091906123b1565b60405180910390a250506001805550565b806000610289826040015160008151811061027c57634e487b7160e01b600052603260045260246000fd5b60200260200101516106ed565b9050600082600001516001600160a01b0316634a248d2a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156102ca57600080fd5b505afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030291906119e4565b6001600160a01b0316826001600160a01b0316149050600083600001516001600160a01b031663d4b970466040518163ffffffff1660e01b815260040160206040518083038186803b15801561035757600080fd5b505afa15801561036b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061038f91906119e4565b6001600160a01b0316836001600160a01b031614905081806103ae5750805b6103ca5760405162461bcd60e51b815260040161012f90612351565b6040805160808101825233815286516001600160a01b03166020808301919091528781015182840152878301516060830152915160009261040c9291016123a0565b60405160208183030381529060405290506000610447876040015160008151811061027c57634e487b7160e01b600052603260045260246000fd5b905086600001516001600160a01b031663d0a494e4826001600160a01b031689600001516001600160a01b0316634a248d2a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156104a357600080fd5b505afa1580156104b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104db91906119e4565b6001600160a01b0316146104f05760006104f6565b88602001515b836001600160a01b03168a600001516001600160a01b0316634a248d2a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561053d57600080fd5b505afa158015610551573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061057591906119e4565b6001600160a01b03161461058d578960200151610590565b60005b30866040518563ffffffff1660e01b81526004016105b19493929190612412565b600060405180830381600087803b1580156105cb57600080fd5b505af11580156105df573d6000803e3d6000fd5b5050505050505050505050565b6000546001600160a01b031633146106165760405162461bcd60e51b815260040161012f90612311565b610620600061074f565b565b61062f858585858561079f565b5050505050565b6000546001600160a01b031633146106605760405162461bcd60e51b815260040161012f90612311565b6001600160a01b0381166106865760405162461bcd60e51b815260040161012f906122d1565b61068f8161074f565b50565b6106e88363a9059cbb60e01b84846040516024016106b19291906122a5565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610bad565b505050565b6000816000015160008151811061071457634e487b7160e01b600052603260045260246000fd5b60200260200101516040015160008151811061074057634e487b7160e01b600052603260045260246000fd5b60200260200101519050919050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006107ad82840184611b9b565b905060006107d9826060015160008151811061027c57634e487b7160e01b600052603260045260246000fd5b90508160400151816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161080c9190612226565b60206040518083038186803b15801561082457600080fd5b505afa158015610838573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085c9190611c03565b101561087a5760405162461bcd60e51b815260040161012f906122e1565b61088c82606001518360400151610c3c565b7ffdc1bd83776f7aa310fcf2b1915ae1c6c16a4cfb48ebcea2bf15febd084c03de81826001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016108da9190612226565b60206040518083038186803b1580156108f257600080fd5b505afa158015610906573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092a9190611c03565b6040516109389291906122a5565b60405180910390a160408083015190516370a0823160e01b81526001600160a01b038316906370a0823190610971903090600401612226565b60206040518083038186803b15801561098957600080fd5b505afa15801561099d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c19190611c03565b10156109df5760405162461bcd60e51b815260040161012f90612321565b6020820151604080840151905163a9059cbb60e01b81526001600160a01b0384169263a9059cbb92610a13926004016122a5565b602060405180830381600087803b158015610a2d57600080fd5b505af1158015610a41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a659190611b3a565b506040516370a0823160e01b81526000906001600160a01b038316906370a0823190610a95903090600401612226565b60206040518083038186803b158015610aad57600080fd5b505afa158015610ac1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae59190611c03565b835160405163a9059cbb60e01b81529192506001600160a01b0384169163a9059cbb91610b169185906004016122a5565b602060405180830381600087803b158015610b3057600080fd5b505af1158015610b44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b689190611b3a565b5082516040517f2b312ac7b7c9b2fc53c9398d48ed2df4c1d192a03cc090b47087b2936ba0a61f91610b9b9184906122a5565b60405180910390a15050505050505050565b6000610c02826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610d449092919063ffffffff16565b8051909150156106e85780806020019051810190610c209190611b3a565b6106e85760405162461bcd60e51b815260040161012f90612361565b816000805b8251811015610c9557828181518110610c6a57634e487b7160e01b600052603260045260246000fd5b60200260200101516020015182610c8191906124b5565b915080610c8d81612599565b915050610c41565b508061ffff1661271014610cbb5760405162461bcd60e51b815260040161012f90612381565b60005b845181101561062f576000610cfe868381518110610cec57634e487b7160e01b600052603260045260246000fd5b60200260200101516020015186610d5d565b9050610d31868381518110610d2357634e487b7160e01b600052603260045260246000fd5b602002602001015182610d7a565b5080610d3c81612599565b915050610cbe565b6060610d538484600085610dd7565b90505b9392505050565b6000612710610d7061ffff8516846124f2565b610d5691906124de565b8060005b835151811015610dd157610dbd84600001518281518110610daf57634e487b7160e01b600052603260045260246000fd5b602002602001015183610e90565b915080610dc981612599565b915050610d7e565b50505050565b606082471015610df95760405162461bcd60e51b815260040161012f906122f1565b843b610e175760405162461bcd60e51b815260040161012f90612341565b600080866001600160a01b03168587604051610e33919061221a565b60006040518083038185875af1925050503d8060008114610e70576040519150601f19603f3d011682016040523d82523d6000602084013e610e75565b606091505b5091509150610e85828286610ef2565b979650505050505050565b815160009060ff16610eb657610eaf8360200151838560400151610f2b565b9050610eec565b6008836000015160ff161015610ed957610eaf83602001518385604001516110b2565b610d5683602001518385604001516111bb565b92915050565b60608315610f01575081610d56565b825115610f115782518084602001fd5b8160405162461bcd60e51b815260040161012f91906122c0565b600080600085806020019051810190610f449190611a4f565b915091506000829050610f8085600081518110610f7157634e487b7160e01b600052603260045260246000fd5b60200260200101518288611422565b806001600160a01b031663414bf38960405180610100016040528088600081518110610fbc57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316815260200188600181518110610ff357634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031681526020018562ffffff168152602001306001600160a01b031681526020014281526020018981526020016000815260200160006001600160a01b03168152506040518263ffffffff1660e01b81526004016110609190612391565b602060405180830381600087803b15801561107a57600080fd5b505af115801561108e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e859190611c03565b600080848060200190518101906110c991906119e4565b90506110fe836000815181106110ef57634e487b7160e01b600052603260045260246000fd5b60200260200101518286611422565b6040516338ed173960e01b81526001600160a01b038216906338ed1739906111339087906001908890309042906004016123bf565b600060405180830381600087803b15801561114d57600080fd5b505af1158015611161573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111899190810190611b06565b6001815181106111a957634e487b7160e01b600052603260045260246000fd5b60200260200101519150509392505050565b600080600080868060200190518101906111d59190611a02565b60408051600180825281830190925293965091945092506000919060208083019080368337019050509050838160008151811061122257634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b03168152505060008660008151811061126557634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316856001600160a01b0316634a248d2a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156112af57600080fd5b505afa1580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e791906119e4565b6001600160a01b0316146112fc5760016112ff565b60005b60ff1690506113378760008151811061132857634e487b7160e01b600052603260045260246000fd5b6020026020010151858a611422565b826001600160a01b031663f87dc1b78860008151811061136757634e487b7160e01b600052603260045260246000fd5b60200260200101518960018151811061139057634e487b7160e01b600052603260045260246000fd5b60200260200101518b600187876000426040518963ffffffff1660e01b81526004016113c3989796959493929190612234565b602060405180830381600087803b1580156113dd57600080fd5b505af11580156113f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114159190611c03565b9998505050505050505050565b60405163095ea7b360e01b81526001600160a01b0384169063095ea7b39061145090859085906004016122a5565b602060405180830381600087803b15801561146a57600080fd5b505af115801561147e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a29190611b3a565b6106e85760405162461bcd60e51b815260040161012f90612331565b60006114d16114cc84612468565b61244c565b905080838252602082019050828560208602820111156114f057600080fd5b60005b8581101561151c5781611506888261169c565b84525060209283019291909101906001016114f3565b5050509392505050565b60006115346114cc84612468565b9050808382526020820190508285602086028201111561155357600080fd5b60005b8581101561151c5781356001600160401b0381111561157457600080fd5b80860161158189826118b5565b855250506020928301929190910190600101611556565b60006115a66114cc84612468565b905080838252602082019050828560208602820111156115c557600080fd5b60005b8581101561151c5781356001600160401b038111156115e657600080fd5b8086016115f38982611932565b8552505060209283019291909101906001016115c8565b60006116186114cc84612468565b9050808382526020820190508285602086028201111561163757600080fd5b60005b8581101561151c578161164d88826119b0565b845250602092830192919091019060010161163a565b60006116716114cc8461248b565b90508281526020810184848401111561168957600080fd5b611694848285612535565b509392505050565b8035610eec816125f6565b8051610eec816125f6565b600082601f8301126116c357600080fd5b81356116d38482602086016114be565b949350505050565b600082601f8301126116ec57600080fd5b81356116d3848260208601611526565b600082601f83011261170d57600080fd5b81356116d3848260208601611598565b600082601f83011261172e57600080fd5b81516116d384826020860161160a565b8051610eec8161260a565b60008083601f84011261175b57600080fd5b5081356001600160401b0381111561177257600080fd5b60208301915083600182028301111561178a57600080fd5b9250929050565b600082601f8301126117a257600080fd5b81356116d3848260208601611663565b8035610eec81612612565b6000608082840312156117cf57600080fd5b6117d9608061244c565b905060006117e7848461169c565b82525060206117f88484830161169c565b602083015250604061180c848285016119a5565b60408301525060608201356001600160401b0381111561182b57600080fd5b611837848285016116fc565b60608301525092915050565b60006060828403121561185557600080fd5b61185f606061244c565b9050600061186d848461169c565b825250602061187e848483016119a5565b60208301525060408201356001600160401b0381111561189d57600080fd5b6118a9848285016116fc565b60408301525092915050565b6000606082840312156118c757600080fd5b6118d1606061244c565b905060006118df84846119bb565b82525060208201356001600160401b038111156118fb57600080fd5b61190784828501611791565b60208301525060408201356001600160401b0381111561192657600080fd5b6118a9848285016116b2565b60006040828403121561194457600080fd5b61194e604061244c565b905081356001600160401b0381111561196657600080fd5b611972848285016116db565b82525060206119838484830161198f565b60208301525092915050565b8035610eec8161261b565b8051610eec81612625565b8035610eec81612630565b8051610eec81612630565b8035610eec81612636565b6000602082840312156119d857600080fd5b60006116d3848461169c565b6000602082840312156119f657600080fd5b60006116d384846116a7565b600080600060608486031215611a1757600080fd5b6000611a2386866116a7565b9350506020611a34868287016116a7565b9250506040611a45868287016116a7565b9150509250925092565b60008060408385031215611a6257600080fd5b6000611a6e85856116a7565b9250506020611a7f8582860161199a565b9150509250929050565b600080600080600060808688031215611aa157600080fd5b6000611aad888861169c565b9550506020611abe888289016119a5565b9450506040611acf888289016119a5565b93505060608601356001600160401b03811115611aeb57600080fd5b611af788828901611749565b92509250509295509295909350565b600060208284031215611b1857600080fd5b81516001600160401b03811115611b2e57600080fd5b6116d38482850161171d565b600060208284031215611b4c57600080fd5b60006116d3848461173e565b600080600060608486031215611b6d57600080fd5b6000611b7986866117b2565b9350506020611b8a8682870161169c565b9250506040611a45868287016119a5565b600060208284031215611bad57600080fd5b81356001600160401b03811115611bc357600080fd5b6116d3848285016117bd565b600060208284031215611be157600080fd5b81356001600160401b03811115611bf757600080fd5b6116d384828501611843565b600060208284031215611c1557600080fd5b60006116d384846119b0565b6000611c2d8383611c4d565b505060200190565b6000610d568383612174565b6000610d5683836121ba565b611c5681612511565b82525050565b6000611c66825190565b80845260209384019383018060005b83811015611c9a578151611c898882611c21565b975060208301925050600101611c75565b509495945050505050565b6000611caf825190565b80845260209384019383018060005b83811015611c9a578151611cd28882611c21565b975060208301925050600101611cbe565b6000611ced825190565b80845260208401935083602082028501611d078560200190565b8060005b85811015611d3c5784840389528151611d248582611c35565b94506020830160209a909a0199925050600101611d0b565b5091979650505050505050565b6000611d53825190565b80845260208401935083602082028501611d6d8560200190565b8060005b85811015611d3c5784840389528151611d8a8582611c41565b94506020830160209a909a0199925050600101611d71565b801515611c56565b6000611db4825190565b808452602084019350611dcb818560208601612541565b601f01601f19169290920192915050565b6000611de6825190565b611df4818560208601612541565b9290920192915050565b611c568161252d565b602681526000602082017f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206181526564647265737360d01b602082015291505b5060400190565b601b81526000602082017f4661696c656420746f20626f72726f77206c6f616e20746f6b656e0000000000815291505b5060200190565b602681526000602082017f416464726573733a20696e73756666696369656e742062616c616e636520666f8152651c8818d85b1b60d21b60208201529150611e46565b601081526000602082016f2737ba1032b737bab3b4103a37b5b2b760811b81529150611e7d565b60208082527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657291019081526000611e7d565b60208082527f4e6f7420656e6f75676820616d6f756e7420746f2072657475726e206c6f616e91019081526000611e7d565b600f81526000602082016e30b8383937bb32903330b4b632b21760891b81529150611e7d565b601d81526000602082017f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081529150611e7d565b601c81526000602082017f57726f6e6720666c6173686c6f616e20706f6f6c20616464726573730000000081529150611e7d565b602a81526000602082017f5361666545524332303a204552433230206f7065726174696f6e20646964206e8152691bdd081cdd58d8d9595960b21b60208201529150611e46565b601f81526000602082017f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081529150611e7d565b601081526000602082016f2937baba32903830b93a1032b93937b960811b81529150611e7d565b80516101008301906120948482611c4d565b5060208201516120a76020850182611c4d565b5060408201516120ba6040850182612200565b5060608201516120cd6060850182611c4d565b5060808201516120e0608085018261220b565b5060a08201516120f360a085018261220b565b5060c082015161210660c085018261220b565b5060e0820151610dd160e08501826121e7565b8051600090608084019061212d8582611c4d565b5060208301516121406020860182611c4d565b506040830151612153604086018261220b565b506060830151848203606086015261216b8282611d49565b95945050505050565b805160009060608401906121888582612211565b50602083015184820360208601526121a08282611daa565b9150506040830151848203604086015261216b8282611c5c565b80516040808452600091908401906121d28282611ce3565b915050602083015161169460208601826121f6565b6001600160a01b038116611c56565b61ffff8116611c56565b62ffffff8116611c56565b80611c56565b60ff8116611c56565b6000610d568284611ddc565b60208101610eec8284611c4d565b6101008101612243828b611c4d565b612250602083018a611c4d565b61225d604083018961220b565b61226a6060830188611dfe565b818103608083015261227c8187611ca5565b905061228b60a083018661220b565b61229860c0830185611da2565b61141560e083018461220b565b604081016122b38285611c4d565b610d56602083018461220b565b60208082528101610d568184611daa565b60208082528101610eec81611e07565b60208082528101610eec81611e4d565b60208082528101610eec81611e84565b60208082528101610eec81611ec7565b60208082528101610eec81611eee565b60208082528101610eec81611f20565b60208082528101610eec81611f52565b60208082528101610eec81611f78565b60208082528101610eec81611fac565b60208082528101610eec81611fe0565b60208082528101610eec81612027565b60208082528101610eec8161205b565b6101008101610eec8284612082565b60208082528101610d568184612119565b60208101610eec828461220b565b60a081016123cd828861220b565b6123da6020830187611dfe565b81810360408301526123ec8186611ca5565b90506123fb6060830185611c4d565b612408608083018461220b565b9695505050505050565b60808101612420828761220b565b61242d602083018661220b565b61243a6040830185611c4d565b81810360608301526124088184611daa565b600061245760405190565b9050612463828261256d565b919050565b60006001600160401b03821115612481576124816125e0565b5060209081020190565b60006001600160401b038211156124a4576124a46125e0565b601f19601f83011660200192915050565b600061ffff8216915061ffff831692508261ffff038211156124d9576124d96125b4565b500190565b6000826124ed576124ed6125ca565b500490565b600081600019048311821515161561250c5761250c6125b4565b500290565b60006001600160a01b038216610eec565b6000610eec82612511565b600081610eec565b82818337506000910152565b60005b8381101561255c578181015183820152602001612544565b83811115610dd15750506000910152565b601f19601f83011681018181106001600160401b0382111715612592576125926125e0565b6040525050565b60006000198214156125ad576125ad6125b4565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6125ff81612511565b811461068f57600080fd5b8015156125ff565b6125ff81612522565b61ffff81166125ff565b62ffffff81166125ff565b806125ff565b60ff81166125ff56fea2646970667358221220577209bda4157801a0372afaec48a9d34326d893455d840430ab6e99e7386af964736f6c63430008040033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b146100d0578063d5b99797146100bd578063eb2021c3146100bd578063f2fde38b146100f257600080fd5b806301e336671461008d5780630cdabeba146100a2578063715018a6146100b55780637ed1f1dd146100bd575b600080fd5b6100a061009b366004611b58565b610105565b005b6100a06100b0366004611bcf565b610251565b6100a06105ec565b6100a06100cb366004611a89565b610622565b6000546001600160a01b03166040516100e99190612226565b60405180910390f35b6100a06101003660046119c6565b610636565b6000546001600160a01b031633146101385760405162461bcd60e51b815260040161012f90612311565b60405180910390fd5b6002600154141561015b5760405162461bcd60e51b815260040161012f90612371565b60026001556040516370a0823160e01b815281906001600160a01b038516906370a082319061018e903090600401612226565b60206040518083038186803b1580156101a657600080fd5b505afa1580156101ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101de9190611c03565b10156101fc5760405162461bcd60e51b815260040161012f90612301565b610207838383610692565b816001600160a01b03167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b658260405161024091906123b1565b60405180910390a250506001805550565b806000610289826040015160008151811061027c57634e487b7160e01b600052603260045260246000fd5b60200260200101516106ed565b9050600082600001516001600160a01b0316634a248d2a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156102ca57600080fd5b505afa1580156102de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030291906119e4565b6001600160a01b0316826001600160a01b0316149050600083600001516001600160a01b031663d4b970466040518163ffffffff1660e01b815260040160206040518083038186803b15801561035757600080fd5b505afa15801561036b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061038f91906119e4565b6001600160a01b0316836001600160a01b031614905081806103ae5750805b6103ca5760405162461bcd60e51b815260040161012f90612351565b6040805160808101825233815286516001600160a01b03166020808301919091528781015182840152878301516060830152915160009261040c9291016123a0565b60405160208183030381529060405290506000610447876040015160008151811061027c57634e487b7160e01b600052603260045260246000fd5b905086600001516001600160a01b031663d0a494e4826001600160a01b031689600001516001600160a01b0316634a248d2a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156104a357600080fd5b505afa1580156104b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104db91906119e4565b6001600160a01b0316146104f05760006104f6565b88602001515b836001600160a01b03168a600001516001600160a01b0316634a248d2a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561053d57600080fd5b505afa158015610551573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061057591906119e4565b6001600160a01b03161461058d578960200151610590565b60005b30866040518563ffffffff1660e01b81526004016105b19493929190612412565b600060405180830381600087803b1580156105cb57600080fd5b505af11580156105df573d6000803e3d6000fd5b5050505050505050505050565b6000546001600160a01b031633146106165760405162461bcd60e51b815260040161012f90612311565b610620600061074f565b565b61062f858585858561079f565b5050505050565b6000546001600160a01b031633146106605760405162461bcd60e51b815260040161012f90612311565b6001600160a01b0381166106865760405162461bcd60e51b815260040161012f906122d1565b61068f8161074f565b50565b6106e88363a9059cbb60e01b84846040516024016106b19291906122a5565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610bad565b505050565b6000816000015160008151811061071457634e487b7160e01b600052603260045260246000fd5b60200260200101516040015160008151811061074057634e487b7160e01b600052603260045260246000fd5b60200260200101519050919050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006107ad82840184611b9b565b905060006107d9826060015160008151811061027c57634e487b7160e01b600052603260045260246000fd5b90508160400151816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161080c9190612226565b60206040518083038186803b15801561082457600080fd5b505afa158015610838573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085c9190611c03565b101561087a5760405162461bcd60e51b815260040161012f906122e1565b61088c82606001518360400151610c3c565b7ffdc1bd83776f7aa310fcf2b1915ae1c6c16a4cfb48ebcea2bf15febd084c03de81826001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016108da9190612226565b60206040518083038186803b1580156108f257600080fd5b505afa158015610906573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092a9190611c03565b6040516109389291906122a5565b60405180910390a160408083015190516370a0823160e01b81526001600160a01b038316906370a0823190610971903090600401612226565b60206040518083038186803b15801561098957600080fd5b505afa15801561099d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c19190611c03565b10156109df5760405162461bcd60e51b815260040161012f90612321565b6020820151604080840151905163a9059cbb60e01b81526001600160a01b0384169263a9059cbb92610a13926004016122a5565b602060405180830381600087803b158015610a2d57600080fd5b505af1158015610a41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a659190611b3a565b506040516370a0823160e01b81526000906001600160a01b038316906370a0823190610a95903090600401612226565b60206040518083038186803b158015610aad57600080fd5b505afa158015610ac1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae59190611c03565b835160405163a9059cbb60e01b81529192506001600160a01b0384169163a9059cbb91610b169185906004016122a5565b602060405180830381600087803b158015610b3057600080fd5b505af1158015610b44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b689190611b3a565b5082516040517f2b312ac7b7c9b2fc53c9398d48ed2df4c1d192a03cc090b47087b2936ba0a61f91610b9b9184906122a5565b60405180910390a15050505050505050565b6000610c02826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610d449092919063ffffffff16565b8051909150156106e85780806020019051810190610c209190611b3a565b6106e85760405162461bcd60e51b815260040161012f90612361565b816000805b8251811015610c9557828181518110610c6a57634e487b7160e01b600052603260045260246000fd5b60200260200101516020015182610c8191906124b5565b915080610c8d81612599565b915050610c41565b508061ffff1661271014610cbb5760405162461bcd60e51b815260040161012f90612381565b60005b845181101561062f576000610cfe868381518110610cec57634e487b7160e01b600052603260045260246000fd5b60200260200101516020015186610d5d565b9050610d31868381518110610d2357634e487b7160e01b600052603260045260246000fd5b602002602001015182610d7a565b5080610d3c81612599565b915050610cbe565b6060610d538484600085610dd7565b90505b9392505050565b6000612710610d7061ffff8516846124f2565b610d5691906124de565b8060005b835151811015610dd157610dbd84600001518281518110610daf57634e487b7160e01b600052603260045260246000fd5b602002602001015183610e90565b915080610dc981612599565b915050610d7e565b50505050565b606082471015610df95760405162461bcd60e51b815260040161012f906122f1565b843b610e175760405162461bcd60e51b815260040161012f90612341565b600080866001600160a01b03168587604051610e33919061221a565b60006040518083038185875af1925050503d8060008114610e70576040519150601f19603f3d011682016040523d82523d6000602084013e610e75565b606091505b5091509150610e85828286610ef2565b979650505050505050565b815160009060ff16610eb657610eaf8360200151838560400151610f2b565b9050610eec565b6008836000015160ff161015610ed957610eaf83602001518385604001516110b2565b610d5683602001518385604001516111bb565b92915050565b60608315610f01575081610d56565b825115610f115782518084602001fd5b8160405162461bcd60e51b815260040161012f91906122c0565b600080600085806020019051810190610f449190611a4f565b915091506000829050610f8085600081518110610f7157634e487b7160e01b600052603260045260246000fd5b60200260200101518288611422565b806001600160a01b031663414bf38960405180610100016040528088600081518110610fbc57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316815260200188600181518110610ff357634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031681526020018562ffffff168152602001306001600160a01b031681526020014281526020018981526020016000815260200160006001600160a01b03168152506040518263ffffffff1660e01b81526004016110609190612391565b602060405180830381600087803b15801561107a57600080fd5b505af115801561108e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e859190611c03565b600080848060200190518101906110c991906119e4565b90506110fe836000815181106110ef57634e487b7160e01b600052603260045260246000fd5b60200260200101518286611422565b6040516338ed173960e01b81526001600160a01b038216906338ed1739906111339087906001908890309042906004016123bf565b600060405180830381600087803b15801561114d57600080fd5b505af1158015611161573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111899190810190611b06565b6001815181106111a957634e487b7160e01b600052603260045260246000fd5b60200260200101519150509392505050565b600080600080868060200190518101906111d59190611a02565b60408051600180825281830190925293965091945092506000919060208083019080368337019050509050838160008151811061122257634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b03168152505060008660008151811061126557634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b0316856001600160a01b0316634a248d2a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156112af57600080fd5b505afa1580156112c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e791906119e4565b6001600160a01b0316146112fc5760016112ff565b60005b60ff1690506113378760008151811061132857634e487b7160e01b600052603260045260246000fd5b6020026020010151858a611422565b826001600160a01b031663f87dc1b78860008151811061136757634e487b7160e01b600052603260045260246000fd5b60200260200101518960018151811061139057634e487b7160e01b600052603260045260246000fd5b60200260200101518b600187876000426040518963ffffffff1660e01b81526004016113c3989796959493929190612234565b602060405180830381600087803b1580156113dd57600080fd5b505af11580156113f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114159190611c03565b9998505050505050505050565b60405163095ea7b360e01b81526001600160a01b0384169063095ea7b39061145090859085906004016122a5565b602060405180830381600087803b15801561146a57600080fd5b505af115801561147e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a29190611b3a565b6106e85760405162461bcd60e51b815260040161012f90612331565b60006114d16114cc84612468565b61244c565b905080838252602082019050828560208602820111156114f057600080fd5b60005b8581101561151c5781611506888261169c565b84525060209283019291909101906001016114f3565b5050509392505050565b60006115346114cc84612468565b9050808382526020820190508285602086028201111561155357600080fd5b60005b8581101561151c5781356001600160401b0381111561157457600080fd5b80860161158189826118b5565b855250506020928301929190910190600101611556565b60006115a66114cc84612468565b905080838252602082019050828560208602820111156115c557600080fd5b60005b8581101561151c5781356001600160401b038111156115e657600080fd5b8086016115f38982611932565b8552505060209283019291909101906001016115c8565b60006116186114cc84612468565b9050808382526020820190508285602086028201111561163757600080fd5b60005b8581101561151c578161164d88826119b0565b845250602092830192919091019060010161163a565b60006116716114cc8461248b565b90508281526020810184848401111561168957600080fd5b611694848285612535565b509392505050565b8035610eec816125f6565b8051610eec816125f6565b600082601f8301126116c357600080fd5b81356116d38482602086016114be565b949350505050565b600082601f8301126116ec57600080fd5b81356116d3848260208601611526565b600082601f83011261170d57600080fd5b81356116d3848260208601611598565b600082601f83011261172e57600080fd5b81516116d384826020860161160a565b8051610eec8161260a565b60008083601f84011261175b57600080fd5b5081356001600160401b0381111561177257600080fd5b60208301915083600182028301111561178a57600080fd5b9250929050565b600082601f8301126117a257600080fd5b81356116d3848260208601611663565b8035610eec81612612565b6000608082840312156117cf57600080fd5b6117d9608061244c565b905060006117e7848461169c565b82525060206117f88484830161169c565b602083015250604061180c848285016119a5565b60408301525060608201356001600160401b0381111561182b57600080fd5b611837848285016116fc565b60608301525092915050565b60006060828403121561185557600080fd5b61185f606061244c565b9050600061186d848461169c565b825250602061187e848483016119a5565b60208301525060408201356001600160401b0381111561189d57600080fd5b6118a9848285016116fc565b60408301525092915050565b6000606082840312156118c757600080fd5b6118d1606061244c565b905060006118df84846119bb565b82525060208201356001600160401b038111156118fb57600080fd5b61190784828501611791565b60208301525060408201356001600160401b0381111561192657600080fd5b6118a9848285016116b2565b60006040828403121561194457600080fd5b61194e604061244c565b905081356001600160401b0381111561196657600080fd5b611972848285016116db565b82525060206119838484830161198f565b60208301525092915050565b8035610eec8161261b565b8051610eec81612625565b8035610eec81612630565b8051610eec81612630565b8035610eec81612636565b6000602082840312156119d857600080fd5b60006116d3848461169c565b6000602082840312156119f657600080fd5b60006116d384846116a7565b600080600060608486031215611a1757600080fd5b6000611a2386866116a7565b9350506020611a34868287016116a7565b9250506040611a45868287016116a7565b9150509250925092565b60008060408385031215611a6257600080fd5b6000611a6e85856116a7565b9250506020611a7f8582860161199a565b9150509250929050565b600080600080600060808688031215611aa157600080fd5b6000611aad888861169c565b9550506020611abe888289016119a5565b9450506040611acf888289016119a5565b93505060608601356001600160401b03811115611aeb57600080fd5b611af788828901611749565b92509250509295509295909350565b600060208284031215611b1857600080fd5b81516001600160401b03811115611b2e57600080fd5b6116d38482850161171d565b600060208284031215611b4c57600080fd5b60006116d3848461173e565b600080600060608486031215611b6d57600080fd5b6000611b7986866117b2565b9350506020611b8a8682870161169c565b9250506040611a45868287016119a5565b600060208284031215611bad57600080fd5b81356001600160401b03811115611bc357600080fd5b6116d3848285016117bd565b600060208284031215611be157600080fd5b81356001600160401b03811115611bf757600080fd5b6116d384828501611843565b600060208284031215611c1557600080fd5b60006116d384846119b0565b6000611c2d8383611c4d565b505060200190565b6000610d568383612174565b6000610d5683836121ba565b611c5681612511565b82525050565b6000611c66825190565b80845260209384019383018060005b83811015611c9a578151611c898882611c21565b975060208301925050600101611c75565b509495945050505050565b6000611caf825190565b80845260209384019383018060005b83811015611c9a578151611cd28882611c21565b975060208301925050600101611cbe565b6000611ced825190565b80845260208401935083602082028501611d078560200190565b8060005b85811015611d3c5784840389528151611d248582611c35565b94506020830160209a909a0199925050600101611d0b565b5091979650505050505050565b6000611d53825190565b80845260208401935083602082028501611d6d8560200190565b8060005b85811015611d3c5784840389528151611d8a8582611c41565b94506020830160209a909a0199925050600101611d71565b801515611c56565b6000611db4825190565b808452602084019350611dcb818560208601612541565b601f01601f19169290920192915050565b6000611de6825190565b611df4818560208601612541565b9290920192915050565b611c568161252d565b602681526000602082017f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206181526564647265737360d01b602082015291505b5060400190565b601b81526000602082017f4661696c656420746f20626f72726f77206c6f616e20746f6b656e0000000000815291505b5060200190565b602681526000602082017f416464726573733a20696e73756666696369656e742062616c616e636520666f8152651c8818d85b1b60d21b60208201529150611e46565b601081526000602082016f2737ba1032b737bab3b4103a37b5b2b760811b81529150611e7d565b60208082527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657291019081526000611e7d565b60208082527f4e6f7420656e6f75676820616d6f756e7420746f2072657475726e206c6f616e91019081526000611e7d565b600f81526000602082016e30b8383937bb32903330b4b632b21760891b81529150611e7d565b601d81526000602082017f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081529150611e7d565b601c81526000602082017f57726f6e6720666c6173686c6f616e20706f6f6c20616464726573730000000081529150611e7d565b602a81526000602082017f5361666545524332303a204552433230206f7065726174696f6e20646964206e8152691bdd081cdd58d8d9595960b21b60208201529150611e46565b601f81526000602082017f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0081529150611e7d565b601081526000602082016f2937baba32903830b93a1032b93937b960811b81529150611e7d565b80516101008301906120948482611c4d565b5060208201516120a76020850182611c4d565b5060408201516120ba6040850182612200565b5060608201516120cd6060850182611c4d565b5060808201516120e0608085018261220b565b5060a08201516120f360a085018261220b565b5060c082015161210660c085018261220b565b5060e0820151610dd160e08501826121e7565b8051600090608084019061212d8582611c4d565b5060208301516121406020860182611c4d565b506040830151612153604086018261220b565b506060830151848203606086015261216b8282611d49565b95945050505050565b805160009060608401906121888582612211565b50602083015184820360208601526121a08282611daa565b9150506040830151848203604086015261216b8282611c5c565b80516040808452600091908401906121d28282611ce3565b915050602083015161169460208601826121f6565b6001600160a01b038116611c56565b61ffff8116611c56565b62ffffff8116611c56565b80611c56565b60ff8116611c56565b6000610d568284611ddc565b60208101610eec8284611c4d565b6101008101612243828b611c4d565b612250602083018a611c4d565b61225d604083018961220b565b61226a6060830188611dfe565b818103608083015261227c8187611ca5565b905061228b60a083018661220b565b61229860c0830185611da2565b61141560e083018461220b565b604081016122b38285611c4d565b610d56602083018461220b565b60208082528101610d568184611daa565b60208082528101610eec81611e07565b60208082528101610eec81611e4d565b60208082528101610eec81611e84565b60208082528101610eec81611ec7565b60208082528101610eec81611eee565b60208082528101610eec81611f20565b60208082528101610eec81611f52565b60208082528101610eec81611f78565b60208082528101610eec81611fac565b60208082528101610eec81611fe0565b60208082528101610eec81612027565b60208082528101610eec8161205b565b6101008101610eec8284612082565b60208082528101610d568184612119565b60208101610eec828461220b565b60a081016123cd828861220b565b6123da6020830187611dfe565b81810360408301526123ec8186611ca5565b90506123fb6060830185611c4d565b612408608083018461220b565b9695505050505050565b60808101612420828761220b565b61242d602083018661220b565b61243a6040830185611c4d565b81810360608301526124088184611daa565b600061245760405190565b9050612463828261256d565b919050565b60006001600160401b03821115612481576124816125e0565b5060209081020190565b60006001600160401b038211156124a4576124a46125e0565b601f19601f83011660200192915050565b600061ffff8216915061ffff831692508261ffff038211156124d9576124d96125b4565b500190565b6000826124ed576124ed6125ca565b500490565b600081600019048311821515161561250c5761250c6125b4565b500290565b60006001600160a01b038216610eec565b6000610eec82612511565b600081610eec565b82818337506000910152565b60005b8381101561255c578181015183820152602001612544565b83811115610dd15750506000910152565b601f19601f83011681018181106001600160401b0382111715612592576125926125e0565b6040525050565b60006000198214156125ad576125ad6125b4565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6125ff81612511565b811461068f57600080fd5b8015156125ff565b6125ff81612522565b61ffff81166125ff565b62ffffff81166125ff565b806125ff565b60ff81166125ff56fea2646970667358221220577209bda4157801a0372afaec48a9d34326d893455d840430ab6e99e7386af964736f6c63430008040033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/src/config.ts b/src/config.ts index c3c2baf..95c3402 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,12 +1,13 @@ import { ERC20Token } from "./constants/addresses"; +import { ITrade } from "./interfaces/trade"; +import { getBigNumber } from "./utils"; export const renderInterval = 1 * 1000; // interval of price check (ms) export const interval = 4 * 1000; -export const loanAmount = 10000; -export const diffAmount = 10; // Not enough amount to return loan +export const diffPercentage = 0.03; //export const chainId = 1;// Ethereum //export const chainId = 56;// Binance Smart Chain @@ -14,26 +15,12 @@ export const chainId = 137; // Polygon export const explorerURL = "https://polygonscan.com"; -/** - * Token pair the bot trading - * baseToken -> tradingToken -> baseToken (ex: DAI -> WETH -> DAI) - * profits are sent in baseToken if a transaction is successful. - */ - -export const baseTokens = [ - // ERC20Token.DAI, - // ERC20Token.WETH, - ERC20Token.USDC, - ERC20Token.USDT, - // ERC20Token.WMATIC, -]; - -export const tradingTokens = [ - ERC20Token.DAI, - ERC20Token.WETH, - ERC20Token.USDC, - ERC20Token.USDT, - ERC20Token.WMATIC, +export const tradingRoutes: ITrade[] = [ + { + path: [ERC20Token.USDC, ERC20Token.DAI, ERC20Token.USDC], + protocols: [2, 0], + amountIn: getBigNumber(20000, ERC20Token.USDC.decimals), + }, ]; /** @@ -48,18 +35,5 @@ export const flashloanAddress: string = * The bot can trade on UniswapV2 fork dexes(ex. SushiSwap) and UniswapV3 * For UniswapV2, you can trade between any token pair, but for UniswapV3, you have to check their pool fees and list them on src/price/uniswap/v3/fee.ts. */ -// protocols the bot will use -export const protocols = - "POLYGON_SUSHISWAP,POLYGON_QUICKSWAP,POLYGON_APESWAP,POLYGON_JETSWAP,POLYGON_WAULTSWAP,POLYGON_UNISWAP_V3"; export const gasLimit = 15000000; -export const gasPrice = 100; // gwei - -export const routeParts = [ - [10000], - [8000, 2000], - [5000, 4000, 1000], - [5000, 3000, 1000, 1000], - [3000, 2000, 2000, 2000, 1000], - [2000, 2000, 2000, 2000, 1000, 1000], -]; diff --git a/src/consoleUI/index.ts b/src/consoleUI/index.ts index bd74417..a9fdbef 100644 --- a/src/consoleUI/index.ts +++ b/src/consoleUI/index.ts @@ -1,46 +1,45 @@ import { Table } from "console-table-printer"; -import { baseTokens, tradingTokens } from "../config"; const readline = require("readline"); -export const initPriceTable = (p: Table, idx: number) => { - baseTokens.forEach(async (baseToken) => { - tradingTokens.forEach(async (tradingToken) => { - if (baseToken.address > tradingToken.address) { - p.addRow({ - index: idx, - - fromToken: (baseToken === tradingToken - ? "" - : baseToken.symbol - ).padEnd(6), - toToken: (baseToken === tradingToken - ? "" - : tradingToken.symbol - ).padEnd(6), - - fromAmount: "".padStart(7), - toAmount: "".padStart(7), - - difference: "".padStart(7), - percentage: "".padStart(5), - - time: "".padStart(6), - timestamp: "".padStart(24), - }); - - idx++; - } - }); - }); -}; - -export const renderTables = (p: Table, pp: Table) => { - // console.clear(); - readline.cursorTo(process.stdout, 0, 0); - - p.printTable(); - - if (pp.table.rows.length > 0) { - pp.printTable(); - } -}; +// export const initPriceTable = (p: Table, idx: number) => { +// baseTokens.forEach(async (baseToken) => { +// tradingTokens.forEach(async (tradingToken) => { +// if (baseToken.address > tradingToken.address) { +// p.addRow({ +// index: idx, + +// fromToken: (baseToken === tradingToken +// ? "" +// : baseToken.symbol +// ).padEnd(6), +// toToken: (baseToken === tradingToken +// ? "" +// : tradingToken.symbol +// ).padEnd(6), + +// fromAmount: "".padStart(7), +// toAmount: "".padStart(7), + +// difference: "".padStart(7), +// percentage: "".padStart(5), + +// time: "".padStart(6), +// timestamp: "".padStart(24), +// }); + +// idx++; +// } +// }); +// }); +// }; + +// export const renderTables = (p: Table, pp: Table) => { +// // console.clear(); +// readline.cursorTo(process.stdout, 0, 0); + +// p.printTable(); + +// if (pp.table.rows.length > 0) { +// pp.printTable(); +// } +// }; diff --git a/src/constants/addresses.ts b/src/constants/addresses.ts index c95c30e..dd730d4 100644 --- a/src/constants/addresses.ts +++ b/src/constants/addresses.ts @@ -132,7 +132,6 @@ type PoolMap = { [pair: string]: string }; export const dodoV2Pool: PoolMap = { WETH_USDC: "0x5333Eb1E32522F1893B7C9feA3c263807A02d561", WMATIC_USDC: "0x10Dd6d8A29D489BEDE472CC1b22dc695c144c5c7", - USDT_USDC: "0xA0020444b98f67B77a3d6dE6E66aF11c87da086e", }; type RouterMap = { [protocol: string]: string }; diff --git a/src/debug.ts b/src/debug.ts index 61d920e..bd97d66 100644 --- a/src/debug.ts +++ b/src/debug.ts @@ -1,64 +1,64 @@ -require("dotenv").config(); -import { ethers } from "ethers"; -import * as ABI from "./abis/Flashloan.json"; -import { IFlashloanRoute } from "./interfaces/main"; -import { findPool, findRouter, findToken } from "./utils"; +// require("dotenv").config(); +// import { ethers } from "ethers"; +// import * as ABI from "./abis/Flashloan.json"; +// import { IFlashloanRoute } from "./interfaces/main"; +// import { findPool, findRouter, findToken } from "./utils"; -if (process.env.ALCHEMY_POLYGON_RPC_URL === undefined) { - throw new Error("Please set ALCHEMY_POLYGON_RPC_URL environment variable."); -} +// if (process.env.ALCHEMY_POLYGON_RPC_URL === undefined) { +// throw new Error("Please set ALCHEMY_POLYGON_RPC_URL environment variable."); +// } -const maticProvider = new ethers.providers.JsonRpcProvider( - process.env.ALCHEMY_POLYGON_RPC_URL -); +// const maticProvider = new ethers.providers.JsonRpcProvider( +// process.env.ALCHEMY_POLYGON_RPC_URL +// ); -const inter = new ethers.utils.Interface(ABI.abi); +// const inter = new ethers.utils.Interface(ABI.abi); -const router = (route: IFlashloanRoute) => { - const protocols = route.hops.map((hop) => { - const tokenPair = `${findToken(hop.path[0])} → ${findToken(hop.path[1])}`; - return `${tokenPair}: ${hop.swaps}`; - }); - return protocols; -}; +// const router = (route: IFlashloanRoute) => { +// const protocols = route.hops.map((hop) => { +// const tokenPair = `${findToken(hop.path[0])} → ${findToken(hop.path[1])}`; +// return `${tokenPair}: ${hop.swaps}`; +// }); +// return protocols; +// }; -export const main = async () => { - var args = process.argv.slice(2); +// export const main = async () => { +// var args = process.argv.slice(2); - const tx = await maticProvider.getTransaction(args[0]); - console.log({ - hash: tx.hash, - from: tx.from, - to: tx.to, +// const tx = await maticProvider.getTransaction(args[0]); +// console.log({ +// hash: tx.hash, +// from: tx.from, +// to: tx.to, - gasPrice: tx.gasPrice?.toNumber(), - gasLimit: tx.gasLimit?.toNumber(), +// gasPrice: tx.gasPrice?.toNumber(), +// gasLimit: tx.gasLimit?.toNumber(), - nonce: tx.nonce, - blockNumber: tx.blockNumber, - }); +// nonce: tx.nonce, +// blockNumber: tx.blockNumber, +// }); - const decodedInput = inter.parseTransaction({ - data: tx.data, - value: tx.value, - }); - console.log({ - name: decodedInput.name, +// const decodedInput = inter.parseTransaction({ +// data: tx.data, +// value: tx.value, +// }); +// console.log({ +// name: decodedInput.name, - params: { - flashLoanPool: findPool(decodedInput.args.params.flashLoanPool), - loanAmount: decodedInput.args.params.loanAmount.toNumber(), - firstRoutes: decodedInput.args.params.firstRoutes.map( - (route: IFlashloanRoute) => JSON.stringify(router(route)) - ), - secondRoutes: decodedInput.args.params.secondRoutes.map( - (route: IFlashloanRoute) => JSON.stringify(router(route)) - ), - }, - }); -}; +// params: { +// flashLoanPool: findPool(decodedInput.args.params.flashLoanPool), +// loanAmount: decodedInput.args.params.loanAmount.toNumber(), +// firstRoutes: decodedInput.args.params.firstRoutes.map( +// (route: IFlashloanRoute) => JSON.stringify(router(route)) +// ), +// secondRoutes: decodedInput.args.params.secondRoutes.map( +// (route: IFlashloanRoute) => JSON.stringify(router(route)) +// ), +// }, +// }); +// }; -main().catch((error) => { - console.error(error); - process.exit(1); -}); +// main().catch((error) => { +// console.error(error); +// process.exit(1); +// }); diff --git a/src/expect.ts b/src/expect.ts index 5fe5246..f4423da 100644 --- a/src/expect.ts +++ b/src/expect.ts @@ -1,69 +1,19 @@ import { BigNumber, ethers } from "ethers"; -import { Hop, IFlashloanRoute, Swap } from "./interfaces/main"; import { getPriceOnUniV2 } from "./price/uniswap/v2/getPrice"; -import { getUniswapV3PoolFee } from "./price/uniswap/v3/fee"; import { getPriceOnUniV3 } from "./price/uniswap/v3/getPrice"; import { findRouterFromProtocol, getBigNumber } from "./utils"; -import { splitLoanAmount } from "./utils/split"; - -export const expectAmountOut = async ( - flashloanRoutes: IFlashloanRoute[], - totalAmountIn: BigNumber -) => { - let amountOut = getBigNumber(0); - for (const route of flashloanRoutes) { - const part = route.part; - const amountIn = splitLoanAmount(totalAmountIn, part); - const hopsAmountOut = await getHopsAmountOut(route.hops, amountIn); - if (hopsAmountOut) { - amountOut = amountOut.add(await getHopsAmountOut(route.hops, amountIn)); - } - } - return amountOut; -}; - -const getHopsAmountOut = async (hops: Hop[], initialAmount: BigNumber) => { - let amountIn = initialAmount; - for (const hop of hops) { - const swaps = hop.swaps; - const path = hop.path; - const swapsAmountOut = await getSwapsAmountOut(swaps, amountIn, path); - amountIn = swapsAmountOut ? swapsAmountOut : getBigNumber(0); - } - - return amountIn; -}; - -const getSwapsAmountOut = async ( - swaps: Swap[], - totalAmountIn: BigNumber, - path: string[] -) => { - let amountOut = getBigNumber(0); - for (const swap of swaps) { - const protocol = swap.protocol; - const part = swap.part; - const amountIn = splitLoanAmount(totalAmountIn, part); - const price = await expectPriceOnDex(protocol, amountIn, path[0], path[1]); - if (ethers.BigNumber.isBigNumber(price)) { - amountOut = amountOut.add(price); - } - } - return amountOut; -}; export const expectPriceOnDex = async ( protocol: number, amountIn: BigNumber, tokenIn: string, tokenOut: string -) => { +): Promise => { if (!amountIn || amountIn.eq(getBigNumber(0))) { return getBigNumber(0); } if (protocol === 0) { - const fee = getUniswapV3PoolFee([tokenIn, tokenOut]); - return await getPriceOnUniV3(tokenIn, tokenOut, amountIn, fee); + return await getPriceOnUniV3(tokenIn, tokenOut, amountIn); } else { const routerAddress = findRouterFromProtocol(protocol); return await getPriceOnUniV2(tokenIn, tokenOut, amountIn, routerAddress); diff --git a/src/findOpp.ts b/src/findOpp.ts new file mode 100644 index 0000000..37007e9 --- /dev/null +++ b/src/findOpp.ts @@ -0,0 +1,50 @@ +import { ITrade } from "./interfaces/trade"; +import { getPriceOnUniV2 } from "./price/uniswap/v2/getPrice"; +import { getPriceOnUniV3 } from "./price/uniswap/v3/getPrice"; +import { findRouterFromProtocol, getBigNumber } from "./utils"; +import * as log4js from "log4js"; + +const errReport = log4js.getLogger("error"); + +export const findOpp = async (trade: ITrade) => { + let amountOut = trade.amountIn; + for (const [i, protocol] of trade.protocols.entries()) { + switch (protocol) { + // uniswap v3 + case 0: + try { + amountOut = await getPriceOnUniV3( + trade.path[i].address, + trade.path[i + 1].address, + amountOut + ); + break; + } catch (e) { + logError(e); + amountOut = getBigNumber(0); + break; + } + // uniswap v2 + default: + try { + amountOut = await getPriceOnUniV2( + trade.path[i].address, + trade.path[i + 1].address, + amountOut, + findRouterFromProtocol(protocol) + ); + break; + } catch (e) { + logError(e); + amountOut = getBigNumber(0); + break; + } + } + } + + return amountOut; +}; + +const logError = (e: any) => { + errReport.warn("Failed to estimate price: ", e?.reason); +}; diff --git a/src/flashloan.ts b/src/flashloan.ts index 91788c4..6ee4184 100644 --- a/src/flashloan.ts +++ b/src/flashloan.ts @@ -1,9 +1,10 @@ import { ethers } from "ethers"; import * as FlashloanJson from "./abis/Flashloan.json"; -import { flashloanAddress, loanAmount, gasLimit, gasPrice } from "./config"; +import { flashloanAddress, gasLimit } from "./config"; import { IToken, dodoV2Pool } from "./constants/addresses"; -import { IFlashloanRoute, IParams } from "./interfaces/main"; -import { getBigNumber } from "./utils/index"; +import { IParams } from "./interfaces/main"; +import { ITrade } from "./interfaces/trade"; +import { passRoutes } from "./routes"; const maticProvider = new ethers.providers.JsonRpcProvider( process.env.ALCHEMY_POLYGON_RPC_URL @@ -38,22 +39,19 @@ const getLendingPool = (borrowingToken: IToken) => { return testedPools[borrowingToken.symbol][0]; }; -export const flashloan = async ( - tokenIn: IToken, - firstRoutes: IFlashloanRoute[], - secondRoutes: IFlashloanRoute[] -) => { +export const flashloan = async (trade: ITrade) => { let params: IParams; - + const tokenIn = trade.path[0]; + const gasPrice = await maticProvider.getGasPrice(); + const extraGas = ethers.utils.parseUnits("100", "gwei"); params = { flashLoanPool: getLendingPool(tokenIn), - loanAmount: getBigNumber(loanAmount, tokenIn.decimals), - firstRoutes: firstRoutes, - secondRoutes: secondRoutes, + loanAmount: trade.amountIn, + routes: passRoutes(trade), }; return Flashloan.connect(signer).dodoFlashLoan(params, { gasLimit: gasLimit, - gasPrice: ethers.utils.parseUnits(`${gasPrice}`, "gwei"), + gasPrice: gasPrice.add(extraGas), }); }; diff --git a/src/index.ts b/src/index.ts index 22e6e61..1b5c17a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,26 +1,21 @@ import { config as dotEnvConfig } from "dotenv"; dotEnvConfig(); -import { checkArbitrage } from "./price/1inch"; import { - baseTokens, interval, - tradingTokens, renderInterval, - loanAmount, - diffAmount, explorerURL, gasLimit, - gasPrice, + tradingRoutes, + diffPercentage, } from "./config"; import { flashloan } from "./flashloan"; -import { expectAmountOut } from "./expect"; -import { getBigNumber } from "./utils"; +import { checkIfProfitable, getBigNumber } from "./utils"; import { ethers } from "ethers"; -import { chalkDifference, chalkPercentage, chalkTime } from "./utils/chalk"; +// import { chalkDifference, chalkPercentage, chalkTime } from "./utils/chalk"; import { flashloanTable, priceTable } from "./consoleUI/table"; -import { initPriceTable, renderTables } from "./consoleUI"; -import { createRoutes } from "./price/1inch/route"; +// import { initPriceTable, renderTables } from "./consoleUI"; import * as log4js from "log4js"; +import { findOpp } from "./findOpp"; log4js.configure({ appenders: { @@ -37,167 +32,56 @@ const logger = log4js.getLogger("flashloan"); const errReport = log4js.getLogger("error"); export const main = async () => { - console.clear(); - let isFlashLoaning = false; - - const [maxX, _] = process.stdout.getWindowSize(); - - const p = priceTable(maxX); - const pp = flashloanTable(maxX); - - let idx = 0; - initPriceTable(p, idx); - - idx = 0; - renderTables(p, pp); - // const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)) - - setInterval(() => { - renderTables(p, pp); - }, renderInterval); - - baseTokens.forEach(async (baseToken) => { - tradingTokens.forEach(async (tradingToken) => { - // prevent swapping the same pair - if (baseToken.address > tradingToken.address) { - const i = idx; - - // await delay(interval / (baseTokens.length * tradingTokens.length) * i) - - const func = async () => { - const startTime = Date.now(); - - const updateRow = (text: any, options?: any) => { - text.time = chalkTime((Date.now() - startTime) / 1000).padStart(6); - text.timestamp = new Date().toISOString(); - - p.table.createColumnFromRow(text); - p.table.rows[i] = { - color: options?.color || p.table.rows[i].color, - separator: - options?.separator !== undefined - ? options?.separator - : p.table.rows[i].separator, - text: { ...p.table.rows[i].text, ...text }, - }; - }; - - const [isProfitable, firstProtocols, secondProtocols] = - await checkArbitrage(baseToken, tradingToken, updateRow); - - renderTables(p, pp); - - if (isProfitable && !isFlashLoaning) { - if (firstProtocols && secondProtocols) { - const firstRoutes = createRoutes(firstProtocols); - const secondRoutes = createRoutes(secondProtocols); - - const bnLoanAmount = getBigNumber(loanAmount, baseToken.decimals); - let bnExpectedAmountOut = getBigNumber(0); - // double check the price by qeurying dex contracts - try { - bnExpectedAmountOut = await expectAmountOut( - firstRoutes, - bnLoanAmount - ).then((firstAmountOut) => - expectAmountOut(secondRoutes, firstAmountOut) - ); - } catch (e) { - // skip flashloan when failed to estimate price - errReport.warn(e); - errReport.warn(1, JSON.stringify(firstProtocols)); - errReport.warn(2, JSON.stringify(secondProtocols)); - return; - } - // check if the expected amount is larger than the loan amount - const isOpportunity = bnLoanAmount - .add(getBigNumber(diffAmount, baseToken.decimals)) - .lt(bnExpectedAmountOut); - - if (isOpportunity) { - isFlashLoaning = true; - const stDifference = Number( - ethers.utils.formatUnits( - bnExpectedAmountOut.sub(bnLoanAmount), - baseToken.decimals - ) - ).toFixed(2); - const amount = Number( - ethers.utils.formatUnits( - bnExpectedAmountOut, - baseToken.decimals - ) - ).toFixed(2); - const difference = Number(stDifference); - const percentage = (difference / Number(loanAmount)) * 100; - - const startTime = Date.now(); - - try { - const tx = await flashloan( - baseToken, - firstRoutes, - secondRoutes - ); - - pp.addRow({ - baseToken: baseToken.symbol.padEnd(6), - tradingToken: tradingToken.symbol.padEnd(6), - - amount: (amount || "").padStart(7), - difference: (chalkDifference(difference) || "").padStart(6), - percentage: (chalkPercentage(percentage) || "").padStart(4), - - firstRoutes: firstProtocols.map((routes) => - routes.map((hops) => - hops - .map((swap) => swap.name.replace("POLYGON_", "")) - .join(" → ") - ) - ), - secondRoutes: secondProtocols.map((routes) => - routes.map((hops) => - hops - .map((swap) => swap.name.replace("POLYGON_", "")) - .join(" → ") - ) - ), - - txHash: tx.hash.padStart(66), - - time: chalkTime((Date.now() - startTime) / 1000).padStart( - 6 - ), - timestamp: new Date().toISOString(), - }); - renderTables(p, pp); - logger.info("flashloan executed", tx.hash); - logger.info(`Explorer URL: ${explorerURL}/tx/${tx.hash}`); - } catch (e) { - errReport.error(e); - errReport.error({ - gasLimit, - gasPrice, - loanAmount, - baseToken, - tradingToken, - }); - } finally { - isFlashLoaning = false; - } - } - } - } - }; - - func(); - - setInterval(func, interval); - - idx++; + tradingRoutes.forEach(async (trade) => { + const baseToken = trade.path[0]; + + const func = async () => { + const bnLoanAmount = trade.amountIn; + // estimate the token amount you get atfer swaps + let bnExpectedAmountOut = await findOpp(trade); + const isProfitable = checkIfProfitable( + bnLoanAmount, + diffPercentage, + bnExpectedAmountOut + ); + + if (isProfitable && !isFlashLoaning) { + isFlashLoaning = true; + try { + const tx = await flashloan(trade); + const stDifference = Number( + ethers.utils.formatUnits( + bnExpectedAmountOut.sub(bnLoanAmount), + baseToken.decimals + ) + ).toFixed(4); + const amount = Number( + ethers.utils.formatUnits(bnExpectedAmountOut, baseToken.decimals) + ).toFixed(4); + const loanAmount = Number( + ethers.utils.formatUnits(bnLoanAmount, baseToken.decimals) + ); + const difference = Number(stDifference); + const percentage = Number( + ((difference / loanAmount) * 100).toFixed(2) + ); + const path = trade.path.map((token) => { + return token.symbol; + }); + logger.info("path", path, "protocols", trade.protocols); + logger.info({ amount, difference, percentage }); + logger.info(`Explorer URL: ${explorerURL}/tx/${tx.hash}`); + } catch (e) { + errReport.error(e); + } finally { + isFlashLoaning = false; + } } - }); + }; + + func(); + setInterval(func, interval); }); }; diff --git a/src/interfaces/inch.ts b/src/interfaces/inch.ts deleted file mode 100644 index 33b424c..0000000 --- a/src/interfaces/inch.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface IProtocol { - name: string; - part: number; - fromTokenAddress: string; - toTokenAddress: string; -} diff --git a/src/interfaces/main.ts b/src/interfaces/main.ts index a6a22da..77efb7a 100644 --- a/src/interfaces/main.ts +++ b/src/interfaces/main.ts @@ -5,14 +5,9 @@ export interface IRoute { toTokenAddress: string; } -export interface Swap { +export interface Hop { protocol: number; - part: number; data: string; -} - -export interface Hop { - swaps: Swap[]; path: string[]; } @@ -24,6 +19,5 @@ export interface IFlashloanRoute { export interface IParams { flashLoanPool: string; loanAmount: BigNumber; - firstRoutes: IFlashloanRoute[]; - secondRoutes: IFlashloanRoute[]; + routes: IFlashloanRoute[]; } diff --git a/src/interfaces/trade.ts b/src/interfaces/trade.ts new file mode 100644 index 0000000..b1a9766 --- /dev/null +++ b/src/interfaces/trade.ts @@ -0,0 +1,8 @@ +import { BigNumber } from "ethers"; +import { IToken } from "../constants/addresses"; + +export interface ITrade { + path: IToken[]; + amountIn: BigNumber; + protocols: number[]; +} diff --git a/src/price/1inch/index.ts b/src/price/1inch/index.ts deleted file mode 100644 index 33fb26c..0000000 --- a/src/price/1inch/index.ts +++ /dev/null @@ -1,204 +0,0 @@ -import { config as dotEnvConfig } from "dotenv"; -dotEnvConfig(); -import { ethers } from "ethers"; -import { chainId, diffAmount, loanAmount } from "../../config"; -import { IRoute } from "../../interfaces/main"; -import { ERC20Token, IToken } from "../../constants/addresses"; -import { replaceTokenAddress } from "../../utils"; -import { IProtocol } from "../../interfaces/inch"; -import { sendRequest } from "../../utils/request"; -import { chalkDifference, chalkPercentage } from "../../utils/chalk"; -import { get1inchQuoteCallUrl } from "./url"; - -/** - * Will check if there's an arbitrage opportunity using the 1inch API - * @param fromToken token symbol you're swapping from - * @param toToken token symbol you're swapping to - * @param fromTokenDecimal number of decimal places of the token you're swapping from - * @returns - */ -export async function checkArbitrage( - fromToken: IToken, - toToken: IToken, - updateRow: Function -): Promise<[boolean, IProtocol[][][] | null, IProtocol[][][] | null, string?]> { - // Reset the row to default values. - updateRow( - { - log: ``, - }, - { - color: "white", - } - ); - - const fromTokenDecimal = fromToken.decimals; - - const amount = ethers.utils.parseUnits( - loanAmount.toString(), - fromTokenDecimal - ); - const amountDiff = ethers.utils.parseUnits( - (loanAmount + diffAmount).toString(), - fromTokenDecimal - ); - - const firstCallURL = get1inchQuoteCallUrl( - chainId, - fromToken.address, - toToken.address, - amount - ); - - updateRow({ - log: `Getting quote for ${fromToken.symbol} → ${toToken.symbol}…`, - }); - - const resultData1 = await sendRequest(firstCallURL); - if (!resultData1.data) { - updateRow( - { - fromToken: fromToken.symbol.padEnd(6), - toToken: toToken.symbol.padEnd(6), - - fromAmount: Number(ethers.utils.formatUnits(amount, fromTokenDecimal)) - .toFixed(2) - .padStart(7), - - log: `${resultData1.errorMessage}`, - }, - { - color: "red", - } - ); - - return [false, null, null]; - } - - const firstProtocols = resultData1.data.protocols; - const returnAmount = resultData1.data.toTokenAmount; - const secondCallURL = get1inchQuoteCallUrl( - chainId, - toToken.address, - fromToken.address, - returnAmount - ); - - updateRow({ - log: `Getting quote for ${toToken.symbol} → ${fromToken.symbol}…`, - }); - - const resultData2 = await sendRequest(secondCallURL); - if (!resultData2.data) { - updateRow( - { - fromToken: resultData1.data.fromToken.symbol.padEnd(6), - toToken: toToken.symbol.padEnd(6), - - fromAmount: Number( - ethers.utils.formatUnits( - resultData1.data.fromTokenAmount, - resultData1.data.fromToken.decimals - ) - ) - .toFixed(2) - .padStart(7), - - log: resultData2.errorMessage, - }, - { - color: "red", - } - ); - - return [false, null, null]; - } - const secondProtocols = resultData2.data.protocols; - - const isProfitable = amountDiff.lt( - ethers.BigNumber.from(resultData2.data.toTokenAmount) - ); - - const fromTokenAmount = Number( - ethers.utils.formatUnits( - resultData1.data.fromTokenAmount, - resultData1.data.fromToken.decimals - ) - ); - const toTokenAmount = Number( - ethers.utils.formatUnits( - resultData2.data.toTokenAmount, - resultData2.data.toToken.decimals - ) - ); - const difference = Number(toTokenAmount) - Number(fromTokenAmount); - const percentage = (difference / Number(fromTokenAmount)) * 100; - - updateRow( - { - fromToken: resultData1.data.fromToken.symbol.padEnd(6), - toToken: resultData1.data.toToken.symbol.padEnd(6), - - fromAmount: fromTokenAmount.toFixed(2).padStart(7), - toAmount: toTokenAmount.toFixed(2).padStart(7), - - difference: chalkDifference(difference).padStart(7), - percentage: chalkPercentage(percentage).padStart(5), - - log: "", - }, - { - color: isProfitable ?? "green", - } - ); - - // isProfitable && - // console.warn( - // _loanAmount, - // ethers.utils.formatUnits(resultData2.toTokenAmount, resultData2.toToken.decimals) - // ); - - return [ - isProfitable, - firstProtocols, - secondProtocols, - toTokenAmount.toFixed(2), - ]; -} - -const getProtocols = (protocols: IProtocol[][][]): IRoute[] => { - let route: IRoute[] = []; - const mainRoute = protocols[0]; - for (const onehop of mainRoute) { - const besthop = getMaxPart(onehop); - route.push({ - name: besthop.name, - toTokenAddress: besthop.toTokenAddress, - }); - } - return route; -}; - -const getMaxPart = (onehop: IProtocol[]): IProtocol => { - let maxPart = 0; - let key = 0; - onehop.forEach((protocol, index) => { - if (maxPart < protocol.part) { - maxPart = protocol.part; - key = index; - } - }); - return onehop[key]; -}; - -const getRoutes = (protocols: IProtocol[][][]): IRoute[] => { - let routes = getProtocols(protocols); - for (const route of routes) { - route.toTokenAddress = replaceTokenAddress( - route.toTokenAddress, - ERC20Token.MATIC.address, - ERC20Token.WMATIC.address - ); - } - return routes; -}; diff --git a/src/price/1inch/route.ts b/src/price/1inch/route.ts deleted file mode 100644 index cef0f33..0000000 --- a/src/price/1inch/route.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { ethers } from "ethers"; -import { ERC20Token, uniswapRouter } from "../../constants/addresses"; -import { IProtocol } from "../../interfaces/inch"; -import { Hop, IFlashloanRoute, Swap } from "../../interfaces/main"; -import { findRouterFromProtocol, replaceTokenAddress } from "../../utils"; -import { getRouteParts, toInt } from "../../utils/split"; -import { getUniswapV3PoolFee } from "../uniswap/v3/fee"; - -const protocolNameToNumber = (protocolName: string): number => { - let protocolNumber = 0; - for (const name of Object.keys(uniswapRouter)) { - if (name === protocolName) { - return protocolNumber; - } - protocolNumber++; - } - throw new Error(`Unknown protocol name: ${protocolName}`); -}; - -export const createRoutes = (routes: IProtocol[][][]): IFlashloanRoute[] => { - let flashloanRoutes: IFlashloanRoute[] = []; - let i = 0; - const routeParts = getRouteParts(routes.length); - for (const hops of routes) { - const part = routeParts[i]; - let route: IFlashloanRoute = { - part: part, - hops: toHops(hops), - }; - flashloanRoutes.push(route); - i++; - } - return flashloanRoutes; -}; - -const toHops = (results: IProtocol[][]) => { - let hops: Hop[] = []; - for (const result of results) { - const path = [result[0].fromTokenAddress, result[0].toTokenAddress].map( - (token) => { - return replaceTokenAddress( - token, - ERC20Token.MATIC.address, - ERC20Token.WMATIC.address - ); - } - ); - let hop: Hop = { - path: path, - swaps: toSwaps(result), - }; - hops.push(hop); - } - return hops; -}; - -const toSwaps = (results: IProtocol[]) => { - let swaps: Swap[] = []; - for (const result of results) { - const protocol = protocolNameToNumber(result.name); - swaps.push({ - protocol: protocol, - part: toInt(result.part), - data: getProtocolData( - protocol, - replaceTokenAddress( - result.fromTokenAddress, - ERC20Token.MATIC.address, - ERC20Token.WMATIC.address - ), - replaceTokenAddress( - result.toTokenAddress, - ERC20Token.MATIC.address, - ERC20Token.WMATIC.address - ) - ), - }); - } - return swaps; -}; - -const getProtocolData = ( - protocol: number, - fromToken: string, - toToken: string -) => { - if (protocol === 0) { - // uniswap V3 - return ethers.utils.defaultAbiCoder.encode( - ["address", "uint24"], - [ - findRouterFromProtocol(protocol), - getUniswapV3PoolFee([fromToken, toToken]), - ] - ); - } else { - // uniswap V2 - return ethers.utils.defaultAbiCoder.encode( - ["address"], - [findRouterFromProtocol(protocol)] - ); - } -}; diff --git a/src/price/1inch/url.ts b/src/price/1inch/url.ts deleted file mode 100644 index d954078..0000000 --- a/src/price/1inch/url.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { BigNumber } from "ethers"; -import { protocols } from "../../config"; - -/** - * Will get the 1inch API call URL for a trade - * @param chainId chain id of the network - * @param fromTokenAddress token address of the token you want to sell - * @param toTokenAddress token address of the token you want to buy - * @param amount amount of the token you want to sell - * @returns call URL for 1inch API - */ -export function get1inchQuoteCallUrl( - chainId: number, - fromTokenAddress: string, - toTokenAddress: string, - amount: BigNumber -): string { - const params = { - fromTokenAddress: fromTokenAddress, - toTokenAddress: toTokenAddress, - amount: amount.toString(), - protocols: protocols, - }; - const apiURL = "https://api.1inch.exchange/v4.0/"; - const searchString = new URLSearchParams(params); - const callURL = `${apiURL}${chainId}/quote?${searchString}`; - return callURL; -} diff --git a/src/price/uniswap/v3/getPrice.ts b/src/price/uniswap/v3/getPrice.ts index 34a9de5..88858b0 100644 --- a/src/price/uniswap/v3/getPrice.ts +++ b/src/price/uniswap/v3/getPrice.ts @@ -2,6 +2,7 @@ import { BigNumber, ethers } from "ethers"; import { abi as QuoterABI } from "@uniswap/v3-periphery/artifacts/contracts/lens/Quoter.sol/Quoter.json"; import { config as dotEnvConfig } from "dotenv"; import { getBigNumber } from "../../../utils"; +import { getUniswapV3PoolFee } from "./fee"; dotEnvConfig(); const maticProvider = new ethers.providers.JsonRpcProvider( @@ -20,15 +21,14 @@ const quoterContract = new ethers.Contract( * @param tokenIn address of token to convert from * @param tokenOut address of token to convert to * @param amountIn amount of token to convert from - * @param fee pool fee * @returns */ export const getPriceOnUniV3 = async ( tokenIn: string, tokenOut: string, - amountIn: BigNumber, - fee: number + amountIn: BigNumber ): Promise => { + const fee = getUniswapV3PoolFee([tokenIn, tokenOut]); const quotedAmountOut = await quoterContract.callStatic.quoteExactInputSingle( tokenIn, tokenOut, diff --git a/src/routes.ts b/src/routes.ts new file mode 100644 index 0000000..4d19c7b --- /dev/null +++ b/src/routes.ts @@ -0,0 +1,50 @@ +import { ethers } from "ethers"; +import { IToken } from "./constants/addresses"; +import { Hop, IFlashloanRoute } from "./interfaces/main"; +import { ITrade } from "./interfaces/trade"; +import { getUniswapV3PoolFee } from "./price/uniswap/v3/fee"; +import { findRouterFromProtocol } from "./utils"; + +const getDataBytesForProtocol = ( + tokenIn: IToken, + tokenOut: IToken, + protocol: number +) => { + switch (protocol) { + // uniswap V3 + case 0: + return ethers.utils.defaultAbiCoder.encode( + ["address", "uint24"], + [ + findRouterFromProtocol(0), + getUniswapV3PoolFee([tokenIn.address, tokenOut.address]), + ] + ); + // uniswap V2 + default: + return ethers.utils.defaultAbiCoder.encode( + ["address"], + [findRouterFromProtocol(protocol)] + ); + } +}; + +export const passRoutes = (trade: ITrade): IFlashloanRoute[] => { + let hops: Hop[] = []; + trade.protocols.forEach((protocol, i) => { + const tokenIn = trade.path[i]; + const tokenOut = trade.path[i + 1]; + const hop: Hop = { + protocol: protocol, + data: getDataBytesForProtocol(tokenIn, tokenOut, protocol), + path: [tokenIn.address, tokenOut.address], + }; + hops.push(hop); + }); + return [ + { + hops: hops, + part: 10000, + }, + ]; +}; diff --git a/src/utils/chalk.ts b/src/utils/chalk.ts index 997cbb3..194badc 100644 --- a/src/utils/chalk.ts +++ b/src/utils/chalk.ts @@ -1,16 +1,15 @@ import chalk = require("chalk"); -import { diffAmount } from "../config"; -export const chalkDifference = (difference: number) => { - const fixedDiff = difference.toFixed(1); - if (difference < 0) { - return chalk.red(fixedDiff); - } else if (difference < diffAmount) { - return chalk.yellow(fixedDiff); - } else { - return chalk.green(fixedDiff); - } -}; +// export const chalkDifference = (difference: number) => { +// const fixedDiff = difference.toFixed(1); +// if (difference < 0) { +// return chalk.red(fixedDiff); +// } else if (difference < diffAmount) { +// return chalk.yellow(fixedDiff); +// } else { +// return chalk.green(fixedDiff); +// } +// }; export const chalkPercentage = (percentage: number) => { const fixedDiff = percentage.toFixed(1); diff --git a/src/utils/index.ts b/src/utils/index.ts index 5c70184..89590f8 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,4 +1,4 @@ -import { ethers } from "ethers"; +import { BigNumber, ethers } from "ethers"; import { dodoV2Pool, ERC20Token, uniswapRouter } from "../constants/addresses"; export const getBigNumber = (amount: number, decimals = 18) => { @@ -61,3 +61,16 @@ export const findPool = (pool: string) => { export const findRouterFromProtocol = (protocol: number) => { return uniswapRouter[Object.keys(uniswapRouter)[protocol]]; }; + +export const checkIfProfitable = ( + loanAmount: BigNumber, + diffPercentage: number, + expectedAmountOut: BigNumber +) => { + const preventUnderflow = 1_000_000; + const isOpportunity = loanAmount + .mul((diffPercentage / 100 + 1) * preventUnderflow) + .div(preventUnderflow) + .lt(expectedAmountOut); + return isOpportunity; +}; diff --git a/src/utils/split.ts b/src/utils/split.ts index 87e3bb2..d59dc30 100644 --- a/src/utils/split.ts +++ b/src/utils/split.ts @@ -1,13 +1,4 @@ import { BigNumber } from "ethers"; -import { routeParts } from "../config"; - -export const getRouteParts = (length: number) => { - try { - return routeParts[length - 1]; - } catch { - throw new Error(`Route length ${length} is not supported`); - } -}; export const toInt = (float: number) => { return float * 100; diff --git a/test/uniswapPrice.test.ts b/test/uniswapPrice.test.ts index b247b19..ebe8076 100644 --- a/test/uniswapPrice.test.ts +++ b/test/uniswapPrice.test.ts @@ -1,20 +1,25 @@ import { findRouter, findRouterFromProtocol, getBigNumber } from "../src/utils"; -import { uniswapRouter } from "../src/constants/addresses"; +import { ERC20Token, uniswapRouter } from "../src/constants/addresses"; import { config as dotEnvConfig } from "dotenv"; dotEnvConfig(); import { expectPriceOnDex } from "../src/expect"; -import { baseTokens, tradingTokens } from "../src/config"; describe("Uniswap price check", () => { for (let i = 0; i < Object.keys(uniswapRouter).length; i++) { const routerAddress = findRouterFromProtocol(i); const routerName = findRouter(routerAddress); + const baseTokens = [ + ERC20Token.USDC, + ERC20Token.DAI, + ERC20Token.USDT, + ERC20Token.WETH, + ]; // skip jetswap if (i === 4) continue; describe(routerName, () => { baseTokens.forEach(async (baseToken) => { - tradingTokens.forEach(async (tradingToken) => { + baseTokens.forEach(async (tradingToken) => { if (baseToken.address > tradingToken.address) { test(`${baseToken.symbol} -> ${tradingToken.symbol}`, async () => { const price = await expectPriceOnDex( diff --git a/test/utils.test.ts b/test/utils.test.ts new file mode 100644 index 0000000..1404c5b --- /dev/null +++ b/test/utils.test.ts @@ -0,0 +1,24 @@ +import { ethers } from "ethers"; +import { checkIfProfitable, getBigNumber } from "../src/utils"; + +describe("Utils tests", () => { + test("getBigNumber", () => { + expect(getBigNumber(10, 6)).toStrictEqual( + ethers.BigNumber.from("10000000") + ); + }); + + describe("checkIfProfitable", () => { + test("6 decimals", () => { + expect( + checkIfProfitable(getBigNumber(10000, 6), 0.02, getBigNumber(10011, 6)) + ).toBe(true); + }); + + test("18 decimals", () => { + expect( + checkIfProfitable(getBigNumber(10000), 0.43, getBigNumber(10091)) + ).toBe(true); + }); + }); +});