diff --git a/Cargo.lock b/Cargo.lock index c23352acee..9596fd87fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7776,6 +7776,7 @@ version = "0.1.0" dependencies = [ "alloy-contract", "alloy-eips", + "alloy-network", "alloy-primitives", "alloy-provider", "alloy-rpc-types", @@ -7793,6 +7794,7 @@ dependencies = [ "derive_more 1.0.0", "eth-domain-types", "ethrpc", + "futures", "gas-price-estimation", "hex-literal", "http-client", diff --git a/contracts/artifacts/Solver.json b/contracts/artifacts/Solver.json index 94ba3bd7da..1a0068b09a 100644 --- a/contracts/artifacts/Solver.json +++ b/contracts/artifacts/Solver.json @@ -22,11 +22,6 @@ "name": "sellAmount", "type": "uint256" }, - { - "internalType": "address", - "name": "nativeToken", - "type": "address" - }, { "internalType": "address", "name": "spardose", @@ -101,8 +96,8 @@ "type": "function" } ], - "bytecode": "0x6080604052348015600e575f5ffd5b506109c58061001c5f395ff3fe608060405234801561000f575f5ffd5b506004361061003f575f3560e01c80631d47e7f4146100435780632582edb41461006d5780633bbb2e1d14610082575b5f5ffd5b610056610051366004610702565b610095565b6040516100649291906107c6565b60405180910390f35b61008061007b366004610813565b610229565b005b610080610090366004610888565b61031e565b5f606033301461012b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b5f8573ffffffffffffffffffffffffffffffffffffffff165f6040515f6040518083038185875af1925050503d805f8114610181576040519150601f19603f3d011682016040523d82523d5f602084013e610186565b606091505b505090505061019687878a61048d565b6101a1888585610557565b91506101ae87878a61048d565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722c80548060200260200160405190810160405280929190818152602001828054801561021757602002820191905f5260205f20905b815481526020019060010190808311610203575b50505050509050965096945050505050565b5f5a6040517f542eb77d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152878116602483015260448201879052858116606483015284811660848301529192509088169063542eb77d9060a4015f604051808303815f87803b1580156102b4575f5ffd5b505af11580156102c6573d5f5f3e3d5ffd5b505050505a6102d59082610901565b6102e19061116c61091a565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b5f828254610310919061091a565b909155505050505050505050565b5f5a90507f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722c73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff861614610407576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa1580156103de573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610402919061092d565b610420565b8373ffffffffffffffffffffffffffffffffffffffff16315b81546001810183555f9283526020909220909101558115610487575a6104469082610901565b6104529061116c61091a565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b5f828254610481919061091a565b90915550505b50505050565b5f5b828110156104875730633bbb2e1d8585848181106104af576104af610944565b90506020020160208101906104c49190610971565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff918216600482015290851660248201525f60448201526064015f604051808303815f87803b158015610535575f5ffd5b505af1158015610547573d5f5f3e3d5ffd5b50506001909201915061048f9050565b5f5f5a90506105b284848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505073ffffffffffffffffffffffffffffffffffffffff8916929150506105f3565b507f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b545a6105e09083610901565b6105ea9190610901565b95945050505050565b6060610600835f84610607565b9392505050565b60605f8473ffffffffffffffffffffffffffffffffffffffff168484604051610630919061098c565b5f6040518083038185875af1925050503d805f811461066a576040519150601f19603f3d011682016040523d82523d5f602084013e61066f565b606091505b50925090508061068157815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146106aa575f5ffd5b50565b80356106b881610689565b919050565b5f5f83601f8401126106cd575f5ffd5b50813567ffffffffffffffff8111156106e4575f5ffd5b6020830191508360208285010111156106fb575f5ffd5b9250929050565b5f5f5f5f5f5f60808789031215610717575f5ffd5b863561072281610689565b9550602087013567ffffffffffffffff81111561073d575f5ffd5b8701601f8101891361074d575f5ffd5b803567ffffffffffffffff811115610763575f5ffd5b8960208260051b8401011115610777575f5ffd5b6020919091019550935061078d604088016106ad565b9250606087013567ffffffffffffffff8111156107a8575f5ffd5b6107b489828a016106bd565b979a9699509497509295939492505050565b5f60408201848352604060208401528084518083526060850191506020860192505f5b818110156108075783518352602093840193909201916001016107e9565b50909695505050505050565b5f5f5f5f5f5f60c08789031215610828575f5ffd5b863561083381610689565b9550602087013561084381610689565b9450604087013561085381610689565b935060608701359250608087013561086a81610689565b915060a087013561087a81610689565b809150509295509295509295565b5f5f5f6060848603121561089a575f5ffd5b83356108a581610689565b925060208401356108b581610689565b9150604084013580151581146108c9575f5ffd5b809150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b81810381811115610914576109146108d4565b92915050565b80820180821115610914576109146108d4565b5f6020828403121561093d575f5ffd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215610981575f5ffd5b813561060081610689565b5f82515f5b818110156109ab5760208186018101518583015201610991565b505f92019182525091905056fea164736f6c634300081e000a", - "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061003f575f3560e01c80631d47e7f4146100435780632582edb41461006d5780633bbb2e1d14610082575b5f5ffd5b610056610051366004610702565b610095565b6040516100649291906107c6565b60405180910390f35b61008061007b366004610813565b610229565b005b610080610090366004610888565b61031e565b5f606033301461012b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b5f8573ffffffffffffffffffffffffffffffffffffffff165f6040515f6040518083038185875af1925050503d805f8114610181576040519150601f19603f3d011682016040523d82523d5f602084013e610186565b606091505b505090505061019687878a61048d565b6101a1888585610557565b91506101ae87878a61048d565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722c80548060200260200160405190810160405280929190818152602001828054801561021757602002820191905f5260205f20905b815481526020019060010190808311610203575b50505050509050965096945050505050565b5f5a6040517f542eb77d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152878116602483015260448201879052858116606483015284811660848301529192509088169063542eb77d9060a4015f604051808303815f87803b1580156102b4575f5ffd5b505af11580156102c6573d5f5f3e3d5ffd5b505050505a6102d59082610901565b6102e19061116c61091a565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b5f828254610310919061091a565b909155505050505050505050565b5f5a90507f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722c73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff861614610407576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa1580156103de573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610402919061092d565b610420565b8373ffffffffffffffffffffffffffffffffffffffff16315b81546001810183555f9283526020909220909101558115610487575a6104469082610901565b6104529061116c61091a565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b5f828254610481919061091a565b90915550505b50505050565b5f5b828110156104875730633bbb2e1d8585848181106104af576104af610944565b90506020020160208101906104c49190610971565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff918216600482015290851660248201525f60448201526064015f604051808303815f87803b158015610535575f5ffd5b505af1158015610547573d5f5f3e3d5ffd5b50506001909201915061048f9050565b5f5f5a90506105b284848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505073ffffffffffffffffffffffffffffffffffffffff8916929150506105f3565b507f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b545a6105e09083610901565b6105ea9190610901565b95945050505050565b6060610600835f84610607565b9392505050565b60605f8473ffffffffffffffffffffffffffffffffffffffff168484604051610630919061098c565b5f6040518083038185875af1925050503d805f811461066a576040519150601f19603f3d011682016040523d82523d5f602084013e61066f565b606091505b50925090508061068157815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146106aa575f5ffd5b50565b80356106b881610689565b919050565b5f5f83601f8401126106cd575f5ffd5b50813567ffffffffffffffff8111156106e4575f5ffd5b6020830191508360208285010111156106fb575f5ffd5b9250929050565b5f5f5f5f5f5f60808789031215610717575f5ffd5b863561072281610689565b9550602087013567ffffffffffffffff81111561073d575f5ffd5b8701601f8101891361074d575f5ffd5b803567ffffffffffffffff811115610763575f5ffd5b8960208260051b8401011115610777575f5ffd5b6020919091019550935061078d604088016106ad565b9250606087013567ffffffffffffffff8111156107a8575f5ffd5b6107b489828a016106bd565b979a9699509497509295939492505050565b5f60408201848352604060208401528084518083526060850191506020860192505f5b818110156108075783518352602093840193909201916001016107e9565b50909695505050505050565b5f5f5f5f5f5f60c08789031215610828575f5ffd5b863561083381610689565b9550602087013561084381610689565b9450604087013561085381610689565b935060608701359250608087013561086a81610689565b915060a087013561087a81610689565b809150509295509295509295565b5f5f5f6060848603121561089a575f5ffd5b83356108a581610689565b925060208401356108b581610689565b9150604084013580151581146108c9575f5ffd5b809150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b81810381811115610914576109146108d4565b92915050565b80820180821115610914576109146108d4565b5f6020828403121561093d575f5ffd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215610981575f5ffd5b813561060081610689565b5f82515f5b818110156109ab5760208186018101518583015201610991565b505f92019182525091905056fea164736f6c634300081e000a", + "bytecode": "0x6080604052348015600e575f5ffd5b506109ab8061001c5f395ff3fe608060405234801561000f575f5ffd5b506004361061003f575f3560e01c80631d47e7f4146100435780632ff111f51461006d5780633bbb2e1d14610082575b5f5ffd5b6100566100513660046106f9565b610095565b6040516100649291906107bd565b60405180910390f35b61008061007b36600461080a565b610229565b005b61008061009036600461086e565b610315565b5f606033301461012b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b5f8573ffffffffffffffffffffffffffffffffffffffff165f6040515f6040518083038185875af1925050503d805f8114610181576040519150601f19603f3d011682016040523d82523d5f602084013e610186565b606091505b505090505061019687878a610484565b6101a188858561054e565b91506101ae87878a610484565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722c80548060200260200160405190810160405280929190818152602001828054801561021757602002820191905f5260205f20905b815481526020019060010190808311610203575b50505050509050965096945050505050565b5f5a6040517f5bbe8b3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152868116602483015260448201869052848116606483015291925090871690635bbe8b3f906084015f604051808303815f87803b1580156102ac575f5ffd5b505af11580156102be573d5f5f3e3d5ffd5b505050505a6102cd90826108e7565b6102d99061116c610900565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b5f8282546103089190610900565b9091555050505050505050565b5f5a90507f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722c73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff8616146103fe576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa1580156103d5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103f99190610913565b610417565b8373ffffffffffffffffffffffffffffffffffffffff16315b81546001810183555f928352602090922090910155811561047e575a61043d90826108e7565b6104499061116c610900565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b5f8282546104789190610900565b90915550505b50505050565b5f5b8281101561047e5730633bbb2e1d8585848181106104a6576104a661092a565b90506020020160208101906104bb9190610957565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff918216600482015290851660248201525f60448201526064015f604051808303815f87803b15801561052c575f5ffd5b505af115801561053e573d5f5f3e3d5ffd5b5050600190920191506104869050565b5f5f5a90506105a984848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505073ffffffffffffffffffffffffffffffffffffffff8916929150506105ea565b507f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b545a6105d790836108e7565b6105e191906108e7565b95945050505050565b60606105f7835f846105fe565b9392505050565b60605f8473ffffffffffffffffffffffffffffffffffffffff1684846040516106279190610972565b5f6040518083038185875af1925050503d805f8114610661576040519150601f19603f3d011682016040523d82523d5f602084013e610666565b606091505b50925090508061067857815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146106a1575f5ffd5b50565b80356106af81610680565b919050565b5f5f83601f8401126106c4575f5ffd5b50813567ffffffffffffffff8111156106db575f5ffd5b6020830191508360208285010111156106f2575f5ffd5b9250929050565b5f5f5f5f5f5f6080878903121561070e575f5ffd5b863561071981610680565b9550602087013567ffffffffffffffff811115610734575f5ffd5b8701601f81018913610744575f5ffd5b803567ffffffffffffffff81111561075a575f5ffd5b8960208260051b840101111561076e575f5ffd5b60209190910195509350610784604088016106a4565b9250606087013567ffffffffffffffff81111561079f575f5ffd5b6107ab89828a016106b4565b979a9699509497509295939492505050565b5f60408201848352604060208401528084518083526060850191506020860192505f5b818110156107fe5783518352602093840193909201916001016107e0565b50909695505050505050565b5f5f5f5f5f60a0868803121561081e575f5ffd5b853561082981610680565b9450602086013561083981610680565b9350604086013561084981610680565b925060608601359150608086013561086081610680565b809150509295509295909350565b5f5f5f60608486031215610880575f5ffd5b833561088b81610680565b9250602084013561089b81610680565b9150604084013580151581146108af575f5ffd5b809150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b818103818111156108fa576108fa6108ba565b92915050565b808201808211156108fa576108fa6108ba565b5f60208284031215610923575f5ffd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215610967575f5ffd5b81356105f781610680565b5f82515f5b818110156109915760208186018101518583015201610977565b505f92019182525091905056fea164736f6c634300081e000a", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061003f575f3560e01c80631d47e7f4146100435780632ff111f51461006d5780633bbb2e1d14610082575b5f5ffd5b6100566100513660046106f9565b610095565b6040516100649291906107bd565b60405180910390f35b61008061007b36600461080a565b610229565b005b61008061009036600461086e565b610315565b5f606033301461012b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b5f8573ffffffffffffffffffffffffffffffffffffffff165f6040515f6040518083038185875af1925050503d805f8114610181576040519150601f19603f3d011682016040523d82523d5f602084013e610186565b606091505b505090505061019687878a610484565b6101a188858561054e565b91506101ae87878a610484565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722c80548060200260200160405190810160405280929190818152602001828054801561021757602002820191905f5260205f20905b815481526020019060010190808311610203575b50505050509050965096945050505050565b5f5a6040517f5bbe8b3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152868116602483015260448201869052848116606483015291925090871690635bbe8b3f906084015f604051808303815f87803b1580156102ac575f5ffd5b505af11580156102be573d5f5f3e3d5ffd5b505050505a6102cd90826108e7565b6102d99061116c610900565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b5f8282546103089190610900565b9091555050505050505050565b5f5a90507f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722c73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff8616146103fe576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa1580156103d5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103f99190610913565b610417565b8373ffffffffffffffffffffffffffffffffffffffff16315b81546001810183555f928352602090922090910155811561047e575a61043d90826108e7565b6104499061116c610900565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b5f8282546104789190610900565b90915550505b50505050565b5f5b8281101561047e5730633bbb2e1d8585848181106104a6576104a661092a565b90506020020160208101906104bb9190610957565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff918216600482015290851660248201525f60448201526064015f604051808303815f87803b15801561052c575f5ffd5b505af115801561053e573d5f5f3e3d5ffd5b5050600190920191506104869050565b5f5f5a90506105a984848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505073ffffffffffffffffffffffffffffffffffffffff8916929150506105ea565b507f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b545a6105d790836108e7565b6105e191906108e7565b95945050505050565b60606105f7835f846105fe565b9392505050565b60605f8473ffffffffffffffffffffffffffffffffffffffff1684846040516106279190610972565b5f6040518083038185875af1925050503d805f8114610661576040519150601f19603f3d011682016040523d82523d5f602084013e610666565b606091505b50925090508061067857815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146106a1575f5ffd5b50565b80356106af81610680565b919050565b5f5f83601f8401126106c4575f5ffd5b50813567ffffffffffffffff8111156106db575f5ffd5b6020830191508360208285010111156106f2575f5ffd5b9250929050565b5f5f5f5f5f5f6080878903121561070e575f5ffd5b863561071981610680565b9550602087013567ffffffffffffffff811115610734575f5ffd5b8701601f81018913610744575f5ffd5b803567ffffffffffffffff81111561075a575f5ffd5b8960208260051b840101111561076e575f5ffd5b60209190910195509350610784604088016106a4565b9250606087013567ffffffffffffffff81111561079f575f5ffd5b6107ab89828a016106b4565b979a9699509497509295939492505050565b5f60408201848352604060208401528084518083526060850191506020860192505f5b818110156107fe5783518352602093840193909201916001016107e0565b50909695505050505050565b5f5f5f5f5f60a0868803121561081e575f5ffd5b853561082981610680565b9450602086013561083981610680565b9350604086013561084981610680565b925060608601359150608086013561086081610680565b809150509295509295909350565b5f5f5f60608486031215610880575f5ffd5b833561088b81610680565b9250602084013561089b81610680565b9150604084013580151581146108af575f5ffd5b809150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b818103818111156108fa576108fa6108ba565b92915050565b808201808211156108fa576108fa6108ba565b5f60208284031215610923575f5ffd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215610967575f5ffd5b81356105f781610680565b5f82515f5b818110156109915760208186018101518583015201610977565b505f92019182525091905056fea164736f6c634300081e000a", "devdoc": { "methods": {} }, diff --git a/contracts/artifacts/Trader.json b/contracts/artifacts/Trader.json index 2bb2245e43..7a9cb937ef 100644 --- a/contracts/artifacts/Trader.json +++ b/contracts/artifacts/Trader.json @@ -21,11 +21,6 @@ "name": "sellAmount", "type": "uint256" }, - { - "internalType": "address", - "name": "nativeToken", - "type": "address" - }, { "internalType": "address", "name": "spardose", @@ -89,8 +84,8 @@ "type": "receive" } ], - "bytecode": "0x6080604052348015600e575f5ffd5b50610d008061001c5f395ff3fe608060405260043610610037575f3560e01c80631626ba7e1461008d578063542eb77d14610104578063eb5625d9146101255761003e565b3661003e57005b5f6100835f368080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525062010000939250506101449050565b9050805160208201f35b348015610098575f5ffd5b506100cf6100a7366004610b01565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010f575f5ffd5b5061012361011e366004610b9c565b6101c2565b005b348015610130575f5ffd5b5061012361013f366004610c00565b610916565b60605f8373ffffffffffffffffffffffffffffffffffffffff168360405161016c9190610c3e565b5f60405180830381855af49150503d805f81146101a4576040519150601f19603f3d011682016040523d82523d5f602084013e6101a9565b606091505b5092509050806101bb57815160208301fd5b5092915050565b7f02565dba7d68dcbed629110024b7b5e785bfc1a484602045eea513de8a2dcf99805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082161790915560ff16156102a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e6365000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036103e4576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa158015610340573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103649190610c6a565b9050838110156103e2575f6103798286610c81565b90508047106103e0578373ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004015f604051808303818588803b1580156103c8575f5ffd5b505af11580156103da573d5f5f3e3d5ffd5b50505050505b505b505b5f8573ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561042e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104529190610cb9565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff80831660248301529192505f9187169063dd62ed3e90604401602060405180830381865afa1580156104c7573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104eb9190610c6a565b905084811015610748576040517feb5625d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8088166004830152831660248201525f6044820152309063eb5625d9906064015f604051808303815f87803b158015610567575f5ffd5b505af1925050508015610578575060015b506040517feb5625d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8088166004830152831660248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6044820152309063eb5625d9906064015f604051808303815f87803b15801561060b575f5ffd5b505af192505050801561061c575060015b506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff83811660248301525f919088169063dd62ed3e90604401602060405180830381865afa158015610690573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106b49190610c6a565b905085811015610746576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f74726164657220646964206e6f7420676976652074686520726571756972656460448201527f20617070726f76616c7300000000000000000000000000000000000000000000606482015260840161029a565b505b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8816906370a0823190602401602060405180830381865afa1580156107b2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107d69190610c6a565b90508581101561090c5773ffffffffffffffffffffffffffffffffffffffff841663494666b688610807848a610c81565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff909216600483015260248201526044015f604051808303815f87803b15801561086f575f5ffd5b505af1925050508015610880575060015b61090c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f74726164657220646f6573206e6f74206861766520656e6f7567682073656c6c60448201527f20746f6b656e0000000000000000000000000000000000000000000000000000606482015260840161029a565b5050505050505050565b61093773ffffffffffffffffffffffffffffffffffffffff8416838361093c565b505050565b6040805173ffffffffffffffffffffffffffffffffffffffff848116602483015260448083018590528351808403909101815260649092019092526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052905f906109ce90861683610a46565b90506109d981610a5a565b610a3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f5361666545524332303a20617070726f76616c206661696c6564000000000000604482015260640161029a565b5050505050565b6060610a53835f84610a7f565b9392505050565b5f81515f1480610a79575081806020019051810190610a799190610cd4565b92915050565b60605f8473ffffffffffffffffffffffffffffffffffffffff168484604051610aa89190610c3e565b5f6040518083038185875af1925050503d805f8114610ae2576040519150601f19603f3d011682016040523d82523d5f602084013e610ae7565b606091505b509250905080610af957815160208301fd5b509392505050565b5f5f5f60408486031215610b13575f5ffd5b83359250602084013567ffffffffffffffff811115610b30575f5ffd5b8401601f81018613610b40575f5ffd5b803567ffffffffffffffff811115610b56575f5ffd5b866020828401011115610b67575f5ffd5b939660209190910195509293505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610b99575f5ffd5b50565b5f5f5f5f5f60a08688031215610bb0575f5ffd5b8535610bbb81610b78565b94506020860135610bcb81610b78565b9350604086013592506060860135610be281610b78565b91506080860135610bf281610b78565b809150509295509295909350565b5f5f5f60608486031215610c12575f5ffd5b8335610c1d81610b78565b92506020840135610c2d81610b78565b929592945050506040919091013590565b5f82515f5b81811015610c5d5760208186018101518583015201610c43565b505f920191825250919050565b5f60208284031215610c7a575f5ffd5b5051919050565b81810381811115610a79577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60208284031215610cc9575f5ffd5b8151610a5381610b78565b5f60208284031215610ce4575f5ffd5b81518015158114610a53575f5ffdfea164736f6c634300081e000a", - "deployedBytecode": "0x608060405260043610610037575f3560e01c80631626ba7e1461008d578063542eb77d14610104578063eb5625d9146101255761003e565b3661003e57005b5f6100835f368080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525062010000939250506101449050565b9050805160208201f35b348015610098575f5ffd5b506100cf6100a7366004610b01565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010f575f5ffd5b5061012361011e366004610b9c565b6101c2565b005b348015610130575f5ffd5b5061012361013f366004610c00565b610916565b60605f8373ffffffffffffffffffffffffffffffffffffffff168360405161016c9190610c3e565b5f60405180830381855af49150503d805f81146101a4576040519150601f19603f3d011682016040523d82523d5f602084013e6101a9565b606091505b5092509050806101bb57815160208301fd5b5092915050565b7f02565dba7d68dcbed629110024b7b5e785bfc1a484602045eea513de8a2dcf99805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082161790915560ff16156102a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e6365000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036103e4576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa158015610340573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103649190610c6a565b9050838110156103e2575f6103798286610c81565b90508047106103e0578373ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004015f604051808303818588803b1580156103c8575f5ffd5b505af11580156103da573d5f5f3e3d5ffd5b50505050505b505b505b5f8573ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561042e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104529190610cb9565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff80831660248301529192505f9187169063dd62ed3e90604401602060405180830381865afa1580156104c7573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104eb9190610c6a565b905084811015610748576040517feb5625d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8088166004830152831660248201525f6044820152309063eb5625d9906064015f604051808303815f87803b158015610567575f5ffd5b505af1925050508015610578575060015b506040517feb5625d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8088166004830152831660248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6044820152309063eb5625d9906064015f604051808303815f87803b15801561060b575f5ffd5b505af192505050801561061c575060015b506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff83811660248301525f919088169063dd62ed3e90604401602060405180830381865afa158015610690573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106b49190610c6a565b905085811015610746576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f74726164657220646964206e6f7420676976652074686520726571756972656460448201527f20617070726f76616c7300000000000000000000000000000000000000000000606482015260840161029a565b505b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8816906370a0823190602401602060405180830381865afa1580156107b2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107d69190610c6a565b90508581101561090c5773ffffffffffffffffffffffffffffffffffffffff841663494666b688610807848a610c81565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff909216600483015260248201526044015f604051808303815f87803b15801561086f575f5ffd5b505af1925050508015610880575060015b61090c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f74726164657220646f6573206e6f74206861766520656e6f7567682073656c6c60448201527f20746f6b656e0000000000000000000000000000000000000000000000000000606482015260840161029a565b5050505050505050565b61093773ffffffffffffffffffffffffffffffffffffffff8416838361093c565b505050565b6040805173ffffffffffffffffffffffffffffffffffffffff848116602483015260448083018590528351808403909101815260649092019092526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052905f906109ce90861683610a46565b90506109d981610a5a565b610a3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f5361666545524332303a20617070726f76616c206661696c6564000000000000604482015260640161029a565b5050505050565b6060610a53835f84610a7f565b9392505050565b5f81515f1480610a79575081806020019051810190610a799190610cd4565b92915050565b60605f8473ffffffffffffffffffffffffffffffffffffffff168484604051610aa89190610c3e565b5f6040518083038185875af1925050503d805f8114610ae2576040519150601f19603f3d011682016040523d82523d5f602084013e610ae7565b606091505b509250905080610af957815160208301fd5b509392505050565b5f5f5f60408486031215610b13575f5ffd5b83359250602084013567ffffffffffffffff811115610b30575f5ffd5b8401601f81018613610b40575f5ffd5b803567ffffffffffffffff811115610b56575f5ffd5b866020828401011115610b67575f5ffd5b939660209190910195509293505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610b99575f5ffd5b50565b5f5f5f5f5f60a08688031215610bb0575f5ffd5b8535610bbb81610b78565b94506020860135610bcb81610b78565b9350604086013592506060860135610be281610b78565b91506080860135610bf281610b78565b809150509295509295909350565b5f5f5f60608486031215610c12575f5ffd5b8335610c1d81610b78565b92506020840135610c2d81610b78565b929592945050506040919091013590565b5f82515f5b81811015610c5d5760208186018101518583015201610c43565b505f920191825250919050565b5f60208284031215610c7a575f5ffd5b5051919050565b81810381811115610a79577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60208284031215610cc9575f5ffd5b8151610a5381610b78565b5f60208284031215610ce4575f5ffd5b81518015158114610a53575f5ffdfea164736f6c634300081e000a", + "bytecode": "0x6080604052348015600e575f5ffd5b50610baa8061001c5f395ff3fe608060405260043610610037575f3560e01c80631626ba7e1461008d5780635bbe8b3f14610104578063eb5625d9146101255761003e565b3661003e57005b5f6100835f368080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525062010000939250506101449050565b9050805160208201f35b348015610098575f5ffd5b506100cf6100a73660046109bf565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010f575f5ffd5b5061012361011e366004610a5a565b6101c2565b005b348015610130575f5ffd5b5061012361013f366004610aaa565b6107d4565b60605f8373ffffffffffffffffffffffffffffffffffffffff168360405161016c9190610ae8565b5f60405180830381855af49150503d805f81146101a4576040519150601f19603f3d011682016040523d82523d5f602084013e6101a9565b606091505b5092509050806101bb57815160208301fd5b5092915050565b7f02565dba7d68dcbed629110024b7b5e785bfc1a484602045eea513de8a2dcf99805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082161790915560ff16156102a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e6365000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b5f8473ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102ed573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103119190610b14565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff80831660248301529192505f9186169063dd62ed3e90604401602060405180830381865afa158015610386573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103aa9190610b2f565b905083811015610607576040517feb5625d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152831660248201525f6044820152309063eb5625d9906064015f604051808303815f87803b158015610426575f5ffd5b505af1925050508015610437575060015b506040517feb5625d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152831660248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6044820152309063eb5625d9906064015f604051808303815f87803b1580156104ca575f5ffd5b505af19250505080156104db575060015b506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff83811660248301525f919087169063dd62ed3e90604401602060405180830381865afa15801561054f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105739190610b2f565b905084811015610605576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f74726164657220646964206e6f7420676976652074686520726571756972656460448201527f20617070726f76616c7300000000000000000000000000000000000000000000606482015260840161029a565b505b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa158015610671573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106959190610b2f565b9050848110156107cb5773ffffffffffffffffffffffffffffffffffffffff841663494666b6876106c68489610b46565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff909216600483015260248201526044015f604051808303815f87803b15801561072e575f5ffd5b505af192505050801561073f575060015b6107cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f74726164657220646f6573206e6f74206861766520656e6f7567682073656c6c60448201527f20746f6b656e0000000000000000000000000000000000000000000000000000606482015260840161029a565b50505050505050565b6107f573ffffffffffffffffffffffffffffffffffffffff841683836107fa565b505050565b6040805173ffffffffffffffffffffffffffffffffffffffff848116602483015260448083018590528351808403909101815260649092019092526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052905f9061088c90861683610904565b905061089781610918565b6108fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f5361666545524332303a20617070726f76616c206661696c6564000000000000604482015260640161029a565b5050505050565b6060610911835f8461093d565b9392505050565b5f81515f14806109375750818060200190518101906109379190610b7e565b92915050565b60605f8473ffffffffffffffffffffffffffffffffffffffff1684846040516109669190610ae8565b5f6040518083038185875af1925050503d805f81146109a0576040519150601f19603f3d011682016040523d82523d5f602084013e6109a5565b606091505b5092509050806109b757815160208301fd5b509392505050565b5f5f5f604084860312156109d1575f5ffd5b83359250602084013567ffffffffffffffff8111156109ee575f5ffd5b8401601f810186136109fe575f5ffd5b803567ffffffffffffffff811115610a14575f5ffd5b866020828401011115610a25575f5ffd5b939660209190910195509293505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610a57575f5ffd5b50565b5f5f5f5f60808587031215610a6d575f5ffd5b8435610a7881610a36565b93506020850135610a8881610a36565b9250604085013591506060850135610a9f81610a36565b939692955090935050565b5f5f5f60608486031215610abc575f5ffd5b8335610ac781610a36565b92506020840135610ad781610a36565b929592945050506040919091013590565b5f82515f5b81811015610b075760208186018101518583015201610aed565b505f920191825250919050565b5f60208284031215610b24575f5ffd5b815161091181610a36565b5f60208284031215610b3f575f5ffd5b5051919050565b81810381811115610937577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60208284031215610b8e575f5ffd5b81518015158114610911575f5ffdfea164736f6c634300081e000a", + "deployedBytecode": "0x608060405260043610610037575f3560e01c80631626ba7e1461008d5780635bbe8b3f14610104578063eb5625d9146101255761003e565b3661003e57005b5f6100835f368080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525062010000939250506101449050565b9050805160208201f35b348015610098575f5ffd5b506100cf6100a73660046109bf565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010f575f5ffd5b5061012361011e366004610a5a565b6101c2565b005b348015610130575f5ffd5b5061012361013f366004610aaa565b6107d4565b60605f8373ffffffffffffffffffffffffffffffffffffffff168360405161016c9190610ae8565b5f60405180830381855af49150503d805f81146101a4576040519150601f19603f3d011682016040523d82523d5f602084013e6101a9565b606091505b5092509050806101bb57815160208301fd5b5092915050565b7f02565dba7d68dcbed629110024b7b5e785bfc1a484602045eea513de8a2dcf99805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082161790915560ff16156102a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e6365000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b5f8473ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102ed573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103119190610b14565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff80831660248301529192505f9186169063dd62ed3e90604401602060405180830381865afa158015610386573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103aa9190610b2f565b905083811015610607576040517feb5625d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152831660248201525f6044820152309063eb5625d9906064015f604051808303815f87803b158015610426575f5ffd5b505af1925050508015610437575060015b506040517feb5625d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152831660248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6044820152309063eb5625d9906064015f604051808303815f87803b1580156104ca575f5ffd5b505af19250505080156104db575060015b506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff83811660248301525f919087169063dd62ed3e90604401602060405180830381865afa15801561054f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105739190610b2f565b905084811015610605576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f74726164657220646964206e6f7420676976652074686520726571756972656460448201527f20617070726f76616c7300000000000000000000000000000000000000000000606482015260840161029a565b505b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa158015610671573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106959190610b2f565b9050848110156107cb5773ffffffffffffffffffffffffffffffffffffffff841663494666b6876106c68489610b46565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff909216600483015260248201526044015f604051808303815f87803b15801561072e575f5ffd5b505af192505050801561073f575060015b6107cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f74726164657220646f6573206e6f74206861766520656e6f7567682073656c6c60448201527f20746f6b656e0000000000000000000000000000000000000000000000000000606482015260840161029a565b50505050505050565b6107f573ffffffffffffffffffffffffffffffffffffffff841683836107fa565b505050565b6040805173ffffffffffffffffffffffffffffffffffffffff848116602483015260448083018590528351808403909101815260649092019092526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052905f9061088c90861683610904565b905061089781610918565b6108fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f5361666545524332303a20617070726f76616c206661696c6564000000000000604482015260640161029a565b5050505050565b6060610911835f8461093d565b9392505050565b5f81515f14806109375750818060200190518101906109379190610b7e565b92915050565b60605f8473ffffffffffffffffffffffffffffffffffffffff1684846040516109669190610ae8565b5f6040518083038185875af1925050503d805f81146109a0576040519150601f19603f3d011682016040523d82523d5f602084013e6109a5565b606091505b5092509050806109b757815160208301fd5b509392505050565b5f5f5f604084860312156109d1575f5ffd5b83359250602084013567ffffffffffffffff8111156109ee575f5ffd5b8401601f810186136109fe575f5ffd5b803567ffffffffffffffff811115610a14575f5ffd5b866020828401011115610a25575f5ffd5b939660209190910195509293505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610a57575f5ffd5b50565b5f5f5f5f60808587031215610a6d575f5ffd5b8435610a7881610a36565b93506020850135610a8881610a36565b9250604085013591506060850135610a9f81610a36565b939692955090935050565b5f5f5f60608486031215610abc575f5ffd5b8335610ac781610a36565b92506020840135610ad781610a36565b929592945050506040919091013590565b5f82515f5b81811015610b075760208186018101518583015201610aed565b505f920191825250919050565b5f60208284031215610b24575f5ffd5b815161091181610a36565b5f60208284031215610b3f575f5ffd5b5051919050565b81810381811115610937577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60208284031215610b8e575f5ffd5b81518015158114610911575f5ffdfea164736f6c634300081e000a", "devdoc": { "methods": {} }, diff --git a/contracts/generated/contracts-generated/solver/src/lib.rs b/contracts/generated/contracts-generated/solver/src/lib.rs index cd27b738be..fbfe9aad21 100644 --- a/contracts/generated/contracts-generated/solver/src/lib.rs +++ b/contracts/generated/contracts-generated/solver/src/lib.rs @@ -11,7 +11,7 @@ Generated by the following Solidity interface... ```solidity interface Solver { - function ensureTradePreconditions(address trader, address settlementContract, address sellToken, uint256 sellAmount, address nativeToken, address spardose) external; + function ensureTradePreconditions(address trader, address settlementContract, address sellToken, uint256 sellAmount, address spardose) external; function storeBalance(address token, address owner, bool countGas) external; function swap(address settlementContract, address[] memory tokens, address payable receiver, bytes memory settlementCall) external returns (uint256 gasUsed, uint256[] memory queriedBalances); } @@ -44,11 +44,6 @@ interface Solver { "type": "uint256", "internalType": "uint256" }, - { - "name": "nativeToken", - "type": "address", - "internalType": "address" - }, { "name": "spardose", "type": "address", @@ -134,27 +129,27 @@ pub mod Solver { /// The creation / init bytecode of the contract. /// /// ```text - ///0x6080604052348015600e575f5ffd5b506109c58061001c5f395ff3fe608060405234801561000f575f5ffd5b506004361061003f575f3560e01c80631d47e7f4146100435780632582edb41461006d5780633bbb2e1d14610082575b5f5ffd5b610056610051366004610702565b610095565b6040516100649291906107c6565b60405180910390f35b61008061007b366004610813565b610229565b005b610080610090366004610888565b61031e565b5f606033301461012b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b5f8573ffffffffffffffffffffffffffffffffffffffff165f6040515f6040518083038185875af1925050503d805f8114610181576040519150601f19603f3d011682016040523d82523d5f602084013e610186565b606091505b505090505061019687878a61048d565b6101a1888585610557565b91506101ae87878a61048d565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722c80548060200260200160405190810160405280929190818152602001828054801561021757602002820191905f5260205f20905b815481526020019060010190808311610203575b50505050509050965096945050505050565b5f5a6040517f542eb77d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152878116602483015260448201879052858116606483015284811660848301529192509088169063542eb77d9060a4015f604051808303815f87803b1580156102b4575f5ffd5b505af11580156102c6573d5f5f3e3d5ffd5b505050505a6102d59082610901565b6102e19061116c61091a565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b5f828254610310919061091a565b909155505050505050505050565b5f5a90507f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722c73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff861614610407576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa1580156103de573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610402919061092d565b610420565b8373ffffffffffffffffffffffffffffffffffffffff16315b81546001810183555f9283526020909220909101558115610487575a6104469082610901565b6104529061116c61091a565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b5f828254610481919061091a565b90915550505b50505050565b5f5b828110156104875730633bbb2e1d8585848181106104af576104af610944565b90506020020160208101906104c49190610971565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff918216600482015290851660248201525f60448201526064015f604051808303815f87803b158015610535575f5ffd5b505af1158015610547573d5f5f3e3d5ffd5b50506001909201915061048f9050565b5f5f5a90506105b284848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505073ffffffffffffffffffffffffffffffffffffffff8916929150506105f3565b507f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b545a6105e09083610901565b6105ea9190610901565b95945050505050565b6060610600835f84610607565b9392505050565b60605f8473ffffffffffffffffffffffffffffffffffffffff168484604051610630919061098c565b5f6040518083038185875af1925050503d805f811461066a576040519150601f19603f3d011682016040523d82523d5f602084013e61066f565b606091505b50925090508061068157815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146106aa575f5ffd5b50565b80356106b881610689565b919050565b5f5f83601f8401126106cd575f5ffd5b50813567ffffffffffffffff8111156106e4575f5ffd5b6020830191508360208285010111156106fb575f5ffd5b9250929050565b5f5f5f5f5f5f60808789031215610717575f5ffd5b863561072281610689565b9550602087013567ffffffffffffffff81111561073d575f5ffd5b8701601f8101891361074d575f5ffd5b803567ffffffffffffffff811115610763575f5ffd5b8960208260051b8401011115610777575f5ffd5b6020919091019550935061078d604088016106ad565b9250606087013567ffffffffffffffff8111156107a8575f5ffd5b6107b489828a016106bd565b979a9699509497509295939492505050565b5f60408201848352604060208401528084518083526060850191506020860192505f5b818110156108075783518352602093840193909201916001016107e9565b50909695505050505050565b5f5f5f5f5f5f60c08789031215610828575f5ffd5b863561083381610689565b9550602087013561084381610689565b9450604087013561085381610689565b935060608701359250608087013561086a81610689565b915060a087013561087a81610689565b809150509295509295509295565b5f5f5f6060848603121561089a575f5ffd5b83356108a581610689565b925060208401356108b581610689565b9150604084013580151581146108c9575f5ffd5b809150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b81810381811115610914576109146108d4565b92915050565b80820180821115610914576109146108d4565b5f6020828403121561093d575f5ffd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215610981575f5ffd5b813561060081610689565b5f82515f5b818110156109ab5760208186018101518583015201610991565b505f92019182525091905056fea164736f6c634300081e000a + ///0x6080604052348015600e575f5ffd5b506109ab8061001c5f395ff3fe608060405234801561000f575f5ffd5b506004361061003f575f3560e01c80631d47e7f4146100435780632ff111f51461006d5780633bbb2e1d14610082575b5f5ffd5b6100566100513660046106f9565b610095565b6040516100649291906107bd565b60405180910390f35b61008061007b36600461080a565b610229565b005b61008061009036600461086e565b610315565b5f606033301461012b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b5f8573ffffffffffffffffffffffffffffffffffffffff165f6040515f6040518083038185875af1925050503d805f8114610181576040519150601f19603f3d011682016040523d82523d5f602084013e610186565b606091505b505090505061019687878a610484565b6101a188858561054e565b91506101ae87878a610484565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722c80548060200260200160405190810160405280929190818152602001828054801561021757602002820191905f5260205f20905b815481526020019060010190808311610203575b50505050509050965096945050505050565b5f5a6040517f5bbe8b3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152868116602483015260448201869052848116606483015291925090871690635bbe8b3f906084015f604051808303815f87803b1580156102ac575f5ffd5b505af11580156102be573d5f5f3e3d5ffd5b505050505a6102cd90826108e7565b6102d99061116c610900565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b5f8282546103089190610900565b9091555050505050505050565b5f5a90507f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722c73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff8616146103fe576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa1580156103d5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103f99190610913565b610417565b8373ffffffffffffffffffffffffffffffffffffffff16315b81546001810183555f928352602090922090910155811561047e575a61043d90826108e7565b6104499061116c610900565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b5f8282546104789190610900565b90915550505b50505050565b5f5b8281101561047e5730633bbb2e1d8585848181106104a6576104a661092a565b90506020020160208101906104bb9190610957565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff918216600482015290851660248201525f60448201526064015f604051808303815f87803b15801561052c575f5ffd5b505af115801561053e573d5f5f3e3d5ffd5b5050600190920191506104869050565b5f5f5a90506105a984848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505073ffffffffffffffffffffffffffffffffffffffff8916929150506105ea565b507f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b545a6105d790836108e7565b6105e191906108e7565b95945050505050565b60606105f7835f846105fe565b9392505050565b60605f8473ffffffffffffffffffffffffffffffffffffffff1684846040516106279190610972565b5f6040518083038185875af1925050503d805f8114610661576040519150601f19603f3d011682016040523d82523d5f602084013e610666565b606091505b50925090508061067857815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146106a1575f5ffd5b50565b80356106af81610680565b919050565b5f5f83601f8401126106c4575f5ffd5b50813567ffffffffffffffff8111156106db575f5ffd5b6020830191508360208285010111156106f2575f5ffd5b9250929050565b5f5f5f5f5f5f6080878903121561070e575f5ffd5b863561071981610680565b9550602087013567ffffffffffffffff811115610734575f5ffd5b8701601f81018913610744575f5ffd5b803567ffffffffffffffff81111561075a575f5ffd5b8960208260051b840101111561076e575f5ffd5b60209190910195509350610784604088016106a4565b9250606087013567ffffffffffffffff81111561079f575f5ffd5b6107ab89828a016106b4565b979a9699509497509295939492505050565b5f60408201848352604060208401528084518083526060850191506020860192505f5b818110156107fe5783518352602093840193909201916001016107e0565b50909695505050505050565b5f5f5f5f5f60a0868803121561081e575f5ffd5b853561082981610680565b9450602086013561083981610680565b9350604086013561084981610680565b925060608601359150608086013561086081610680565b809150509295509295909350565b5f5f5f60608486031215610880575f5ffd5b833561088b81610680565b9250602084013561089b81610680565b9150604084013580151581146108af575f5ffd5b809150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b818103818111156108fa576108fa6108ba565b92915050565b808201808211156108fa576108fa6108ba565b5f60208284031215610923575f5ffd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215610967575f5ffd5b81356105f781610680565b5f82515f5b818110156109915760208186018101518583015201610977565b505f92019182525091905056fea164736f6c634300081e000a /// ``` #[rustfmt::skip] #[allow(clippy::all)] pub static BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( - b"`\x80`@R4\x80\x15`\x0EW__\xFD[Pa\t\xC5\x80a\0\x1C_9_\xF3\xFE`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0?W_5`\xE0\x1C\x80c\x1DG\xE7\xF4\x14a\0CW\x80c%\x82\xED\xB4\x14a\0mW\x80c;\xBB.\x1D\x14a\0\x82W[__\xFD[a\0Va\0Q6`\x04a\x07\x02V[a\0\x95V[`@Qa\0d\x92\x91\x90a\x07\xC6V[`@Q\x80\x91\x03\x90\xF3[a\0\x80a\0{6`\x04a\x08\x13V[a\x02)V[\0[a\0\x80a\0\x906`\x04a\x08\x88V[a\x03\x1EV[_``30\x14a\x01+W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`8`$\x82\x01R\x7Fonly simulation logic is allowed`D\x82\x01R\x7F to call 'swap' function\0\0\0\0\0\0\0\0`d\x82\x01R`\x84\x01`@Q\x80\x91\x03\x90\xFD[_\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16_`@Q_`@Q\x80\x83\x03\x81\x85\x87Z\xF1\x92PPP=\x80_\x81\x14a\x01\x81W`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\x01\x86V[``\x91P[PP\x90PPa\x01\x96\x87\x87\x8Aa\x04\x8DV[a\x01\xA1\x88\x85\x85a\x05WV[\x91Pa\x01\xAE\x87\x87\x8Aa\x04\x8DV[\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r,\x80T\x80` \x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80T\x80\x15a\x02\x17W` \x02\x82\x01\x91\x90_R` _ \x90[\x81T\x81R` \x01\x90`\x01\x01\x90\x80\x83\x11a\x02\x03W[PPPPP\x90P\x96P\x96\x94PPPPPV[_Z`@Q\x7FT.\xB7}\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x88\x81\x16`\x04\x83\x01R\x87\x81\x16`$\x83\x01R`D\x82\x01\x87\x90R\x85\x81\x16`d\x83\x01R\x84\x81\x16`\x84\x83\x01R\x91\x92P\x90\x88\x16\x90cT.\xB7}\x90`\xA4\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x02\xB4W__\xFD[PZ\xF1\x15\x80\x15a\x02\xC6W=__>=_\xFD[PPPPZa\x02\xD5\x90\x82a\t\x01V[a\x02\xE1\x90a\x11la\t\x1AV[\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r+_\x82\x82Ta\x03\x10\x91\x90a\t\x1AV[\x90\x91UPPPPPPPPPV[_Z\x90P\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r,s\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEEs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x86\x16\x14a\x04\x07W`@Q\x7Fp\xA0\x821\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x85\x81\x16`\x04\x83\x01R\x86\x16\x90cp\xA0\x821\x90`$\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x03\xDEW=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x04\x02\x91\x90a\t-V[a\x04 V[\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x161[\x81T`\x01\x81\x01\x83U_\x92\x83R` \x90\x92 \x90\x91\x01U\x81\x15a\x04\x87WZa\x04F\x90\x82a\t\x01V[a\x04R\x90a\x11la\t\x1AV[\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r+_\x82\x82Ta\x04\x81\x91\x90a\t\x1AV[\x90\x91UPP[PPPPV[_[\x82\x81\x10\x15a\x04\x87W0c;\xBB.\x1D\x85\x85\x84\x81\x81\x10a\x04\xAFWa\x04\xAFa\tDV[\x90P` \x02\x01` \x81\x01\x90a\x04\xC4\x91\x90a\tqV[`@Q\x7F\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\xE0\x84\x90\x1B\x16\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x91\x82\x16`\x04\x82\x01R\x90\x85\x16`$\x82\x01R_`D\x82\x01R`d\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x055W__\xFD[PZ\xF1\x15\x80\x15a\x05GW=__>=_\xFD[PP`\x01\x90\x92\x01\x91Pa\x04\x8F\x90PV[__Z\x90Pa\x05\xB2\x84\x84\x80\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x93\x92\x91\x90\x81\x81R` \x01\x83\x83\x80\x82\x847_\x92\x01\x91\x90\x91RPPs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x89\x16\x92\x91PPa\x05\xF3V[P\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r+TZa\x05\xE0\x90\x83a\t\x01V[a\x05\xEA\x91\x90a\t\x01V[\x95\x94PPPPPV[``a\x06\0\x83_\x84a\x06\x07V[\x93\x92PPPV[``_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84\x84`@Qa\x060\x91\x90a\t\x8CV[_`@Q\x80\x83\x03\x81\x85\x87Z\xF1\x92PPP=\x80_\x81\x14a\x06jW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\x06oV[``\x91P[P\x92P\x90P\x80a\x06\x81W\x81Q` \x83\x01\xFD[P\x93\x92PPPV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16\x81\x14a\x06\xAAW__\xFD[PV[\x805a\x06\xB8\x81a\x06\x89V[\x91\x90PV[__\x83`\x1F\x84\x01\x12a\x06\xCDW__\xFD[P\x815g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x06\xE4W__\xFD[` \x83\x01\x91P\x83` \x82\x85\x01\x01\x11\x15a\x06\xFBW__\xFD[\x92P\x92\x90PV[______`\x80\x87\x89\x03\x12\x15a\x07\x17W__\xFD[\x865a\x07\"\x81a\x06\x89V[\x95P` \x87\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x07=W__\xFD[\x87\x01`\x1F\x81\x01\x89\x13a\x07MW__\xFD[\x805g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x07cW__\xFD[\x89` \x82`\x05\x1B\x84\x01\x01\x11\x15a\x07wW__\xFD[` \x91\x90\x91\x01\x95P\x93Pa\x07\x8D`@\x88\x01a\x06\xADV[\x92P``\x87\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x07\xA8W__\xFD[a\x07\xB4\x89\x82\x8A\x01a\x06\xBDV[\x97\x9A\x96\x99P\x94\x97P\x92\x95\x93\x94\x92PPPV[_`@\x82\x01\x84\x83R`@` \x84\x01R\x80\x84Q\x80\x83R``\x85\x01\x91P` \x86\x01\x92P_[\x81\x81\x10\x15a\x08\x07W\x83Q\x83R` \x93\x84\x01\x93\x90\x92\x01\x91`\x01\x01a\x07\xE9V[P\x90\x96\x95PPPPPPV[______`\xC0\x87\x89\x03\x12\x15a\x08(W__\xFD[\x865a\x083\x81a\x06\x89V[\x95P` \x87\x015a\x08C\x81a\x06\x89V[\x94P`@\x87\x015a\x08S\x81a\x06\x89V[\x93P``\x87\x015\x92P`\x80\x87\x015a\x08j\x81a\x06\x89V[\x91P`\xA0\x87\x015a\x08z\x81a\x06\x89V[\x80\x91PP\x92\x95P\x92\x95P\x92\x95V[___``\x84\x86\x03\x12\x15a\x08\x9AW__\xFD[\x835a\x08\xA5\x81a\x06\x89V[\x92P` \x84\x015a\x08\xB5\x81a\x06\x89V[\x91P`@\x84\x015\x80\x15\x15\x81\x14a\x08\xC9W__\xFD[\x80\x91PP\x92P\x92P\x92V[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[\x81\x81\x03\x81\x81\x11\x15a\t\x14Wa\t\x14a\x08\xD4V[\x92\x91PPV[\x80\x82\x01\x80\x82\x11\x15a\t\x14Wa\t\x14a\x08\xD4V[_` \x82\x84\x03\x12\x15a\t=W__\xFD[PQ\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[_` \x82\x84\x03\x12\x15a\t\x81W__\xFD[\x815a\x06\0\x81a\x06\x89V[_\x82Q_[\x81\x81\x10\x15a\t\xABW` \x81\x86\x01\x81\x01Q\x85\x83\x01R\x01a\t\x91V[P_\x92\x01\x91\x82RP\x91\x90PV\xFE\xA1dsolcC\0\x08\x1E\0\n", + b"`\x80`@R4\x80\x15`\x0EW__\xFD[Pa\t\xAB\x80a\0\x1C_9_\xF3\xFE`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0?W_5`\xE0\x1C\x80c\x1DG\xE7\xF4\x14a\0CW\x80c/\xF1\x11\xF5\x14a\0mW\x80c;\xBB.\x1D\x14a\0\x82W[__\xFD[a\0Va\0Q6`\x04a\x06\xF9V[a\0\x95V[`@Qa\0d\x92\x91\x90a\x07\xBDV[`@Q\x80\x91\x03\x90\xF3[a\0\x80a\0{6`\x04a\x08\nV[a\x02)V[\0[a\0\x80a\0\x906`\x04a\x08nV[a\x03\x15V[_``30\x14a\x01+W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`8`$\x82\x01R\x7Fonly simulation logic is allowed`D\x82\x01R\x7F to call 'swap' function\0\0\0\0\0\0\0\0`d\x82\x01R`\x84\x01`@Q\x80\x91\x03\x90\xFD[_\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16_`@Q_`@Q\x80\x83\x03\x81\x85\x87Z\xF1\x92PPP=\x80_\x81\x14a\x01\x81W`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\x01\x86V[``\x91P[PP\x90PPa\x01\x96\x87\x87\x8Aa\x04\x84V[a\x01\xA1\x88\x85\x85a\x05NV[\x91Pa\x01\xAE\x87\x87\x8Aa\x04\x84V[\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r,\x80T\x80` \x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80T\x80\x15a\x02\x17W` \x02\x82\x01\x91\x90_R` _ \x90[\x81T\x81R` \x01\x90`\x01\x01\x90\x80\x83\x11a\x02\x03W[PPPPP\x90P\x96P\x96\x94PPPPPV[_Z`@Q\x7F[\xBE\x8B?\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x87\x81\x16`\x04\x83\x01R\x86\x81\x16`$\x83\x01R`D\x82\x01\x86\x90R\x84\x81\x16`d\x83\x01R\x91\x92P\x90\x87\x16\x90c[\xBE\x8B?\x90`\x84\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x02\xACW__\xFD[PZ\xF1\x15\x80\x15a\x02\xBEW=__>=_\xFD[PPPPZa\x02\xCD\x90\x82a\x08\xE7V[a\x02\xD9\x90a\x11la\t\0V[\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r+_\x82\x82Ta\x03\x08\x91\x90a\t\0V[\x90\x91UPPPPPPPPV[_Z\x90P\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r,s\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEEs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x86\x16\x14a\x03\xFEW`@Q\x7Fp\xA0\x821\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x85\x81\x16`\x04\x83\x01R\x86\x16\x90cp\xA0\x821\x90`$\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x03\xD5W=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x03\xF9\x91\x90a\t\x13V[a\x04\x17V[\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x161[\x81T`\x01\x81\x01\x83U_\x92\x83R` \x90\x92 \x90\x91\x01U\x81\x15a\x04~WZa\x04=\x90\x82a\x08\xE7V[a\x04I\x90a\x11la\t\0V[\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r+_\x82\x82Ta\x04x\x91\x90a\t\0V[\x90\x91UPP[PPPPV[_[\x82\x81\x10\x15a\x04~W0c;\xBB.\x1D\x85\x85\x84\x81\x81\x10a\x04\xA6Wa\x04\xA6a\t*V[\x90P` \x02\x01` \x81\x01\x90a\x04\xBB\x91\x90a\tWV[`@Q\x7F\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\xE0\x84\x90\x1B\x16\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x91\x82\x16`\x04\x82\x01R\x90\x85\x16`$\x82\x01R_`D\x82\x01R`d\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x05,W__\xFD[PZ\xF1\x15\x80\x15a\x05>W=__>=_\xFD[PP`\x01\x90\x92\x01\x91Pa\x04\x86\x90PV[__Z\x90Pa\x05\xA9\x84\x84\x80\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x93\x92\x91\x90\x81\x81R` \x01\x83\x83\x80\x82\x847_\x92\x01\x91\x90\x91RPPs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x89\x16\x92\x91PPa\x05\xEAV[P\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r+TZa\x05\xD7\x90\x83a\x08\xE7V[a\x05\xE1\x91\x90a\x08\xE7V[\x95\x94PPPPPV[``a\x05\xF7\x83_\x84a\x05\xFEV[\x93\x92PPPV[``_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84\x84`@Qa\x06'\x91\x90a\trV[_`@Q\x80\x83\x03\x81\x85\x87Z\xF1\x92PPP=\x80_\x81\x14a\x06aW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\x06fV[``\x91P[P\x92P\x90P\x80a\x06xW\x81Q` \x83\x01\xFD[P\x93\x92PPPV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16\x81\x14a\x06\xA1W__\xFD[PV[\x805a\x06\xAF\x81a\x06\x80V[\x91\x90PV[__\x83`\x1F\x84\x01\x12a\x06\xC4W__\xFD[P\x815g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x06\xDBW__\xFD[` \x83\x01\x91P\x83` \x82\x85\x01\x01\x11\x15a\x06\xF2W__\xFD[\x92P\x92\x90PV[______`\x80\x87\x89\x03\x12\x15a\x07\x0EW__\xFD[\x865a\x07\x19\x81a\x06\x80V[\x95P` \x87\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x074W__\xFD[\x87\x01`\x1F\x81\x01\x89\x13a\x07DW__\xFD[\x805g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x07ZW__\xFD[\x89` \x82`\x05\x1B\x84\x01\x01\x11\x15a\x07nW__\xFD[` \x91\x90\x91\x01\x95P\x93Pa\x07\x84`@\x88\x01a\x06\xA4V[\x92P``\x87\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x07\x9FW__\xFD[a\x07\xAB\x89\x82\x8A\x01a\x06\xB4V[\x97\x9A\x96\x99P\x94\x97P\x92\x95\x93\x94\x92PPPV[_`@\x82\x01\x84\x83R`@` \x84\x01R\x80\x84Q\x80\x83R``\x85\x01\x91P` \x86\x01\x92P_[\x81\x81\x10\x15a\x07\xFEW\x83Q\x83R` \x93\x84\x01\x93\x90\x92\x01\x91`\x01\x01a\x07\xE0V[P\x90\x96\x95PPPPPPV[_____`\xA0\x86\x88\x03\x12\x15a\x08\x1EW__\xFD[\x855a\x08)\x81a\x06\x80V[\x94P` \x86\x015a\x089\x81a\x06\x80V[\x93P`@\x86\x015a\x08I\x81a\x06\x80V[\x92P``\x86\x015\x91P`\x80\x86\x015a\x08`\x81a\x06\x80V[\x80\x91PP\x92\x95P\x92\x95\x90\x93PV[___``\x84\x86\x03\x12\x15a\x08\x80W__\xFD[\x835a\x08\x8B\x81a\x06\x80V[\x92P` \x84\x015a\x08\x9B\x81a\x06\x80V[\x91P`@\x84\x015\x80\x15\x15\x81\x14a\x08\xAFW__\xFD[\x80\x91PP\x92P\x92P\x92V[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[\x81\x81\x03\x81\x81\x11\x15a\x08\xFAWa\x08\xFAa\x08\xBAV[\x92\x91PPV[\x80\x82\x01\x80\x82\x11\x15a\x08\xFAWa\x08\xFAa\x08\xBAV[_` \x82\x84\x03\x12\x15a\t#W__\xFD[PQ\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[_` \x82\x84\x03\x12\x15a\tgW__\xFD[\x815a\x05\xF7\x81a\x06\x80V[_\x82Q_[\x81\x81\x10\x15a\t\x91W` \x81\x86\x01\x81\x01Q\x85\x83\x01R\x01a\twV[P_\x92\x01\x91\x82RP\x91\x90PV\xFE\xA1dsolcC\0\x08\x1E\0\n", ); /// The runtime bytecode of the contract, as deployed on the network. /// /// ```text - ///0x608060405234801561000f575f5ffd5b506004361061003f575f3560e01c80631d47e7f4146100435780632582edb41461006d5780633bbb2e1d14610082575b5f5ffd5b610056610051366004610702565b610095565b6040516100649291906107c6565b60405180910390f35b61008061007b366004610813565b610229565b005b610080610090366004610888565b61031e565b5f606033301461012b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b5f8573ffffffffffffffffffffffffffffffffffffffff165f6040515f6040518083038185875af1925050503d805f8114610181576040519150601f19603f3d011682016040523d82523d5f602084013e610186565b606091505b505090505061019687878a61048d565b6101a1888585610557565b91506101ae87878a61048d565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722c80548060200260200160405190810160405280929190818152602001828054801561021757602002820191905f5260205f20905b815481526020019060010190808311610203575b50505050509050965096945050505050565b5f5a6040517f542eb77d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152878116602483015260448201879052858116606483015284811660848301529192509088169063542eb77d9060a4015f604051808303815f87803b1580156102b4575f5ffd5b505af11580156102c6573d5f5f3e3d5ffd5b505050505a6102d59082610901565b6102e19061116c61091a565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b5f828254610310919061091a565b909155505050505050505050565b5f5a90507f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722c73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff861614610407576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa1580156103de573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610402919061092d565b610420565b8373ffffffffffffffffffffffffffffffffffffffff16315b81546001810183555f9283526020909220909101558115610487575a6104469082610901565b6104529061116c61091a565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b5f828254610481919061091a565b90915550505b50505050565b5f5b828110156104875730633bbb2e1d8585848181106104af576104af610944565b90506020020160208101906104c49190610971565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff918216600482015290851660248201525f60448201526064015f604051808303815f87803b158015610535575f5ffd5b505af1158015610547573d5f5f3e3d5ffd5b50506001909201915061048f9050565b5f5f5a90506105b284848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505073ffffffffffffffffffffffffffffffffffffffff8916929150506105f3565b507f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b545a6105e09083610901565b6105ea9190610901565b95945050505050565b6060610600835f84610607565b9392505050565b60605f8473ffffffffffffffffffffffffffffffffffffffff168484604051610630919061098c565b5f6040518083038185875af1925050503d805f811461066a576040519150601f19603f3d011682016040523d82523d5f602084013e61066f565b606091505b50925090508061068157815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146106aa575f5ffd5b50565b80356106b881610689565b919050565b5f5f83601f8401126106cd575f5ffd5b50813567ffffffffffffffff8111156106e4575f5ffd5b6020830191508360208285010111156106fb575f5ffd5b9250929050565b5f5f5f5f5f5f60808789031215610717575f5ffd5b863561072281610689565b9550602087013567ffffffffffffffff81111561073d575f5ffd5b8701601f8101891361074d575f5ffd5b803567ffffffffffffffff811115610763575f5ffd5b8960208260051b8401011115610777575f5ffd5b6020919091019550935061078d604088016106ad565b9250606087013567ffffffffffffffff8111156107a8575f5ffd5b6107b489828a016106bd565b979a9699509497509295939492505050565b5f60408201848352604060208401528084518083526060850191506020860192505f5b818110156108075783518352602093840193909201916001016107e9565b50909695505050505050565b5f5f5f5f5f5f60c08789031215610828575f5ffd5b863561083381610689565b9550602087013561084381610689565b9450604087013561085381610689565b935060608701359250608087013561086a81610689565b915060a087013561087a81610689565b809150509295509295509295565b5f5f5f6060848603121561089a575f5ffd5b83356108a581610689565b925060208401356108b581610689565b9150604084013580151581146108c9575f5ffd5b809150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b81810381811115610914576109146108d4565b92915050565b80820180821115610914576109146108d4565b5f6020828403121561093d575f5ffd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215610981575f5ffd5b813561060081610689565b5f82515f5b818110156109ab5760208186018101518583015201610991565b505f92019182525091905056fea164736f6c634300081e000a + ///0x608060405234801561000f575f5ffd5b506004361061003f575f3560e01c80631d47e7f4146100435780632ff111f51461006d5780633bbb2e1d14610082575b5f5ffd5b6100566100513660046106f9565b610095565b6040516100649291906107bd565b60405180910390f35b61008061007b36600461080a565b610229565b005b61008061009036600461086e565b610315565b5f606033301461012b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b5f8573ffffffffffffffffffffffffffffffffffffffff165f6040515f6040518083038185875af1925050503d805f8114610181576040519150601f19603f3d011682016040523d82523d5f602084013e610186565b606091505b505090505061019687878a610484565b6101a188858561054e565b91506101ae87878a610484565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722c80548060200260200160405190810160405280929190818152602001828054801561021757602002820191905f5260205f20905b815481526020019060010190808311610203575b50505050509050965096945050505050565b5f5a6040517f5bbe8b3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152868116602483015260448201869052848116606483015291925090871690635bbe8b3f906084015f604051808303815f87803b1580156102ac575f5ffd5b505af11580156102be573d5f5f3e3d5ffd5b505050505a6102cd90826108e7565b6102d99061116c610900565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b5f8282546103089190610900565b9091555050505050505050565b5f5a90507f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722c73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff8616146103fe576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa1580156103d5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103f99190610913565b610417565b8373ffffffffffffffffffffffffffffffffffffffff16315b81546001810183555f928352602090922090910155811561047e575a61043d90826108e7565b6104499061116c610900565b7f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b5f8282546104789190610900565b90915550505b50505050565b5f5b8281101561047e5730633bbb2e1d8585848181106104a6576104a661092a565b90506020020160208101906104bb9190610957565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff918216600482015290851660248201525f60448201526064015f604051808303815f87803b15801561052c575f5ffd5b505af115801561053e573d5f5f3e3d5ffd5b5050600190920191506104869050565b5f5f5a90506105a984848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505073ffffffffffffffffffffffffffffffffffffffff8916929150506105ea565b507f14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff18c9a173a722b545a6105d790836108e7565b6105e191906108e7565b95945050505050565b60606105f7835f846105fe565b9392505050565b60605f8473ffffffffffffffffffffffffffffffffffffffff1684846040516106279190610972565b5f6040518083038185875af1925050503d805f8114610661576040519150601f19603f3d011682016040523d82523d5f602084013e610666565b606091505b50925090508061067857815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146106a1575f5ffd5b50565b80356106af81610680565b919050565b5f5f83601f8401126106c4575f5ffd5b50813567ffffffffffffffff8111156106db575f5ffd5b6020830191508360208285010111156106f2575f5ffd5b9250929050565b5f5f5f5f5f5f6080878903121561070e575f5ffd5b863561071981610680565b9550602087013567ffffffffffffffff811115610734575f5ffd5b8701601f81018913610744575f5ffd5b803567ffffffffffffffff81111561075a575f5ffd5b8960208260051b840101111561076e575f5ffd5b60209190910195509350610784604088016106a4565b9250606087013567ffffffffffffffff81111561079f575f5ffd5b6107ab89828a016106b4565b979a9699509497509295939492505050565b5f60408201848352604060208401528084518083526060850191506020860192505f5b818110156107fe5783518352602093840193909201916001016107e0565b50909695505050505050565b5f5f5f5f5f60a0868803121561081e575f5ffd5b853561082981610680565b9450602086013561083981610680565b9350604086013561084981610680565b925060608601359150608086013561086081610680565b809150509295509295909350565b5f5f5f60608486031215610880575f5ffd5b833561088b81610680565b9250602084013561089b81610680565b9150604084013580151581146108af575f5ffd5b809150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b818103818111156108fa576108fa6108ba565b92915050565b808201808211156108fa576108fa6108ba565b5f60208284031215610923575f5ffd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60208284031215610967575f5ffd5b81356105f781610680565b5f82515f5b818110156109915760208186018101518583015201610977565b505f92019182525091905056fea164736f6c634300081e000a /// ``` #[rustfmt::skip] #[allow(clippy::all)] pub static DEPLOYED_BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( - b"`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0?W_5`\xE0\x1C\x80c\x1DG\xE7\xF4\x14a\0CW\x80c%\x82\xED\xB4\x14a\0mW\x80c;\xBB.\x1D\x14a\0\x82W[__\xFD[a\0Va\0Q6`\x04a\x07\x02V[a\0\x95V[`@Qa\0d\x92\x91\x90a\x07\xC6V[`@Q\x80\x91\x03\x90\xF3[a\0\x80a\0{6`\x04a\x08\x13V[a\x02)V[\0[a\0\x80a\0\x906`\x04a\x08\x88V[a\x03\x1EV[_``30\x14a\x01+W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`8`$\x82\x01R\x7Fonly simulation logic is allowed`D\x82\x01R\x7F to call 'swap' function\0\0\0\0\0\0\0\0`d\x82\x01R`\x84\x01`@Q\x80\x91\x03\x90\xFD[_\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16_`@Q_`@Q\x80\x83\x03\x81\x85\x87Z\xF1\x92PPP=\x80_\x81\x14a\x01\x81W`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\x01\x86V[``\x91P[PP\x90PPa\x01\x96\x87\x87\x8Aa\x04\x8DV[a\x01\xA1\x88\x85\x85a\x05WV[\x91Pa\x01\xAE\x87\x87\x8Aa\x04\x8DV[\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r,\x80T\x80` \x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80T\x80\x15a\x02\x17W` \x02\x82\x01\x91\x90_R` _ \x90[\x81T\x81R` \x01\x90`\x01\x01\x90\x80\x83\x11a\x02\x03W[PPPPP\x90P\x96P\x96\x94PPPPPV[_Z`@Q\x7FT.\xB7}\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x88\x81\x16`\x04\x83\x01R\x87\x81\x16`$\x83\x01R`D\x82\x01\x87\x90R\x85\x81\x16`d\x83\x01R\x84\x81\x16`\x84\x83\x01R\x91\x92P\x90\x88\x16\x90cT.\xB7}\x90`\xA4\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x02\xB4W__\xFD[PZ\xF1\x15\x80\x15a\x02\xC6W=__>=_\xFD[PPPPZa\x02\xD5\x90\x82a\t\x01V[a\x02\xE1\x90a\x11la\t\x1AV[\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r+_\x82\x82Ta\x03\x10\x91\x90a\t\x1AV[\x90\x91UPPPPPPPPPV[_Z\x90P\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r,s\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEEs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x86\x16\x14a\x04\x07W`@Q\x7Fp\xA0\x821\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x85\x81\x16`\x04\x83\x01R\x86\x16\x90cp\xA0\x821\x90`$\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x03\xDEW=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x04\x02\x91\x90a\t-V[a\x04 V[\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x161[\x81T`\x01\x81\x01\x83U_\x92\x83R` \x90\x92 \x90\x91\x01U\x81\x15a\x04\x87WZa\x04F\x90\x82a\t\x01V[a\x04R\x90a\x11la\t\x1AV[\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r+_\x82\x82Ta\x04\x81\x91\x90a\t\x1AV[\x90\x91UPP[PPPPV[_[\x82\x81\x10\x15a\x04\x87W0c;\xBB.\x1D\x85\x85\x84\x81\x81\x10a\x04\xAFWa\x04\xAFa\tDV[\x90P` \x02\x01` \x81\x01\x90a\x04\xC4\x91\x90a\tqV[`@Q\x7F\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\xE0\x84\x90\x1B\x16\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x91\x82\x16`\x04\x82\x01R\x90\x85\x16`$\x82\x01R_`D\x82\x01R`d\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x055W__\xFD[PZ\xF1\x15\x80\x15a\x05GW=__>=_\xFD[PP`\x01\x90\x92\x01\x91Pa\x04\x8F\x90PV[__Z\x90Pa\x05\xB2\x84\x84\x80\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x93\x92\x91\x90\x81\x81R` \x01\x83\x83\x80\x82\x847_\x92\x01\x91\x90\x91RPPs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x89\x16\x92\x91PPa\x05\xF3V[P\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r+TZa\x05\xE0\x90\x83a\t\x01V[a\x05\xEA\x91\x90a\t\x01V[\x95\x94PPPPPV[``a\x06\0\x83_\x84a\x06\x07V[\x93\x92PPPV[``_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84\x84`@Qa\x060\x91\x90a\t\x8CV[_`@Q\x80\x83\x03\x81\x85\x87Z\xF1\x92PPP=\x80_\x81\x14a\x06jW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\x06oV[``\x91P[P\x92P\x90P\x80a\x06\x81W\x81Q` \x83\x01\xFD[P\x93\x92PPPV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16\x81\x14a\x06\xAAW__\xFD[PV[\x805a\x06\xB8\x81a\x06\x89V[\x91\x90PV[__\x83`\x1F\x84\x01\x12a\x06\xCDW__\xFD[P\x815g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x06\xE4W__\xFD[` \x83\x01\x91P\x83` \x82\x85\x01\x01\x11\x15a\x06\xFBW__\xFD[\x92P\x92\x90PV[______`\x80\x87\x89\x03\x12\x15a\x07\x17W__\xFD[\x865a\x07\"\x81a\x06\x89V[\x95P` \x87\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x07=W__\xFD[\x87\x01`\x1F\x81\x01\x89\x13a\x07MW__\xFD[\x805g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x07cW__\xFD[\x89` \x82`\x05\x1B\x84\x01\x01\x11\x15a\x07wW__\xFD[` \x91\x90\x91\x01\x95P\x93Pa\x07\x8D`@\x88\x01a\x06\xADV[\x92P``\x87\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x07\xA8W__\xFD[a\x07\xB4\x89\x82\x8A\x01a\x06\xBDV[\x97\x9A\x96\x99P\x94\x97P\x92\x95\x93\x94\x92PPPV[_`@\x82\x01\x84\x83R`@` \x84\x01R\x80\x84Q\x80\x83R``\x85\x01\x91P` \x86\x01\x92P_[\x81\x81\x10\x15a\x08\x07W\x83Q\x83R` \x93\x84\x01\x93\x90\x92\x01\x91`\x01\x01a\x07\xE9V[P\x90\x96\x95PPPPPPV[______`\xC0\x87\x89\x03\x12\x15a\x08(W__\xFD[\x865a\x083\x81a\x06\x89V[\x95P` \x87\x015a\x08C\x81a\x06\x89V[\x94P`@\x87\x015a\x08S\x81a\x06\x89V[\x93P``\x87\x015\x92P`\x80\x87\x015a\x08j\x81a\x06\x89V[\x91P`\xA0\x87\x015a\x08z\x81a\x06\x89V[\x80\x91PP\x92\x95P\x92\x95P\x92\x95V[___``\x84\x86\x03\x12\x15a\x08\x9AW__\xFD[\x835a\x08\xA5\x81a\x06\x89V[\x92P` \x84\x015a\x08\xB5\x81a\x06\x89V[\x91P`@\x84\x015\x80\x15\x15\x81\x14a\x08\xC9W__\xFD[\x80\x91PP\x92P\x92P\x92V[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[\x81\x81\x03\x81\x81\x11\x15a\t\x14Wa\t\x14a\x08\xD4V[\x92\x91PPV[\x80\x82\x01\x80\x82\x11\x15a\t\x14Wa\t\x14a\x08\xD4V[_` \x82\x84\x03\x12\x15a\t=W__\xFD[PQ\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[_` \x82\x84\x03\x12\x15a\t\x81W__\xFD[\x815a\x06\0\x81a\x06\x89V[_\x82Q_[\x81\x81\x10\x15a\t\xABW` \x81\x86\x01\x81\x01Q\x85\x83\x01R\x01a\t\x91V[P_\x92\x01\x91\x82RP\x91\x90PV\xFE\xA1dsolcC\0\x08\x1E\0\n", + b"`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0?W_5`\xE0\x1C\x80c\x1DG\xE7\xF4\x14a\0CW\x80c/\xF1\x11\xF5\x14a\0mW\x80c;\xBB.\x1D\x14a\0\x82W[__\xFD[a\0Va\0Q6`\x04a\x06\xF9V[a\0\x95V[`@Qa\0d\x92\x91\x90a\x07\xBDV[`@Q\x80\x91\x03\x90\xF3[a\0\x80a\0{6`\x04a\x08\nV[a\x02)V[\0[a\0\x80a\0\x906`\x04a\x08nV[a\x03\x15V[_``30\x14a\x01+W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`8`$\x82\x01R\x7Fonly simulation logic is allowed`D\x82\x01R\x7F to call 'swap' function\0\0\0\0\0\0\0\0`d\x82\x01R`\x84\x01`@Q\x80\x91\x03\x90\xFD[_\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16_`@Q_`@Q\x80\x83\x03\x81\x85\x87Z\xF1\x92PPP=\x80_\x81\x14a\x01\x81W`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\x01\x86V[``\x91P[PP\x90PPa\x01\x96\x87\x87\x8Aa\x04\x84V[a\x01\xA1\x88\x85\x85a\x05NV[\x91Pa\x01\xAE\x87\x87\x8Aa\x04\x84V[\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r,\x80T\x80` \x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80T\x80\x15a\x02\x17W` \x02\x82\x01\x91\x90_R` _ \x90[\x81T\x81R` \x01\x90`\x01\x01\x90\x80\x83\x11a\x02\x03W[PPPPP\x90P\x96P\x96\x94PPPPPV[_Z`@Q\x7F[\xBE\x8B?\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x87\x81\x16`\x04\x83\x01R\x86\x81\x16`$\x83\x01R`D\x82\x01\x86\x90R\x84\x81\x16`d\x83\x01R\x91\x92P\x90\x87\x16\x90c[\xBE\x8B?\x90`\x84\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x02\xACW__\xFD[PZ\xF1\x15\x80\x15a\x02\xBEW=__>=_\xFD[PPPPZa\x02\xCD\x90\x82a\x08\xE7V[a\x02\xD9\x90a\x11la\t\0V[\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r+_\x82\x82Ta\x03\x08\x91\x90a\t\0V[\x90\x91UPPPPPPPPV[_Z\x90P\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r,s\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEEs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x86\x16\x14a\x03\xFEW`@Q\x7Fp\xA0\x821\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x85\x81\x16`\x04\x83\x01R\x86\x16\x90cp\xA0\x821\x90`$\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x03\xD5W=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x03\xF9\x91\x90a\t\x13V[a\x04\x17V[\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x161[\x81T`\x01\x81\x01\x83U_\x92\x83R` \x90\x92 \x90\x91\x01U\x81\x15a\x04~WZa\x04=\x90\x82a\x08\xE7V[a\x04I\x90a\x11la\t\0V[\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r+_\x82\x82Ta\x04x\x91\x90a\t\0V[\x90\x91UPP[PPPPV[_[\x82\x81\x10\x15a\x04~W0c;\xBB.\x1D\x85\x85\x84\x81\x81\x10a\x04\xA6Wa\x04\xA6a\t*V[\x90P` \x02\x01` \x81\x01\x90a\x04\xBB\x91\x90a\tWV[`@Q\x7F\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\xE0\x84\x90\x1B\x16\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x91\x82\x16`\x04\x82\x01R\x90\x85\x16`$\x82\x01R_`D\x82\x01R`d\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x05,W__\xFD[PZ\xF1\x15\x80\x15a\x05>W=__>=_\xFD[PP`\x01\x90\x92\x01\x91Pa\x04\x86\x90PV[__Z\x90Pa\x05\xA9\x84\x84\x80\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x93\x92\x91\x90\x81\x81R` \x01\x83\x83\x80\x82\x847_\x92\x01\x91\x90\x91RPPs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x89\x16\x92\x91PPa\x05\xEAV[P\x7F\x14\xF5\xB2\xC1\x85\xFC\x03\xC7\\x}\x1F\x0E\x10\xEA\x13|\xC6\xD25\xA0\x04tH\xEF\xF1\x8C\x9A\x17:r+TZa\x05\xD7\x90\x83a\x08\xE7V[a\x05\xE1\x91\x90a\x08\xE7V[\x95\x94PPPPPV[``a\x05\xF7\x83_\x84a\x05\xFEV[\x93\x92PPPV[``_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84\x84`@Qa\x06'\x91\x90a\trV[_`@Q\x80\x83\x03\x81\x85\x87Z\xF1\x92PPP=\x80_\x81\x14a\x06aW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\x06fV[``\x91P[P\x92P\x90P\x80a\x06xW\x81Q` \x83\x01\xFD[P\x93\x92PPPV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16\x81\x14a\x06\xA1W__\xFD[PV[\x805a\x06\xAF\x81a\x06\x80V[\x91\x90PV[__\x83`\x1F\x84\x01\x12a\x06\xC4W__\xFD[P\x815g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x06\xDBW__\xFD[` \x83\x01\x91P\x83` \x82\x85\x01\x01\x11\x15a\x06\xF2W__\xFD[\x92P\x92\x90PV[______`\x80\x87\x89\x03\x12\x15a\x07\x0EW__\xFD[\x865a\x07\x19\x81a\x06\x80V[\x95P` \x87\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x074W__\xFD[\x87\x01`\x1F\x81\x01\x89\x13a\x07DW__\xFD[\x805g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x07ZW__\xFD[\x89` \x82`\x05\x1B\x84\x01\x01\x11\x15a\x07nW__\xFD[` \x91\x90\x91\x01\x95P\x93Pa\x07\x84`@\x88\x01a\x06\xA4V[\x92P``\x87\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x07\x9FW__\xFD[a\x07\xAB\x89\x82\x8A\x01a\x06\xB4V[\x97\x9A\x96\x99P\x94\x97P\x92\x95\x93\x94\x92PPPV[_`@\x82\x01\x84\x83R`@` \x84\x01R\x80\x84Q\x80\x83R``\x85\x01\x91P` \x86\x01\x92P_[\x81\x81\x10\x15a\x07\xFEW\x83Q\x83R` \x93\x84\x01\x93\x90\x92\x01\x91`\x01\x01a\x07\xE0V[P\x90\x96\x95PPPPPPV[_____`\xA0\x86\x88\x03\x12\x15a\x08\x1EW__\xFD[\x855a\x08)\x81a\x06\x80V[\x94P` \x86\x015a\x089\x81a\x06\x80V[\x93P`@\x86\x015a\x08I\x81a\x06\x80V[\x92P``\x86\x015\x91P`\x80\x86\x015a\x08`\x81a\x06\x80V[\x80\x91PP\x92\x95P\x92\x95\x90\x93PV[___``\x84\x86\x03\x12\x15a\x08\x80W__\xFD[\x835a\x08\x8B\x81a\x06\x80V[\x92P` \x84\x015a\x08\x9B\x81a\x06\x80V[\x91P`@\x84\x015\x80\x15\x15\x81\x14a\x08\xAFW__\xFD[\x80\x91PP\x92P\x92P\x92V[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[\x81\x81\x03\x81\x81\x11\x15a\x08\xFAWa\x08\xFAa\x08\xBAV[\x92\x91PPV[\x80\x82\x01\x80\x82\x11\x15a\x08\xFAWa\x08\xFAa\x08\xBAV[_` \x82\x84\x03\x12\x15a\t#W__\xFD[PQ\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`2`\x04R`$_\xFD[_` \x82\x84\x03\x12\x15a\tgW__\xFD[\x815a\x05\xF7\x81a\x06\x80V[_\x82Q_[\x81\x81\x10\x15a\t\x91W` \x81\x86\x01\x81\x01Q\x85\x83\x01R\x01a\twV[P_\x92\x01\x91\x82RP\x91\x90PV\xFE\xA1dsolcC\0\x08\x1E\0\n", ); #[derive(Default, Debug, PartialEq, Eq, Hash)] - /**Function with signature `ensureTradePreconditions(address,address,address,uint256,address,address)` and selector `0x2582edb4`. + /**Function with signature `ensureTradePreconditions(address,address,address,uint256,address)` and selector `0x2ff111f5`. ```solidity - function ensureTradePreconditions(address trader, address settlementContract, address sellToken, uint256 sellAmount, address nativeToken, address spardose) external; + function ensureTradePreconditions(address trader, address settlementContract, address sellToken, uint256 sellAmount, address spardose) external; ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] @@ -168,12 +163,10 @@ pub mod Solver { #[allow(missing_docs)] pub sellAmount: alloy_sol_types::private::primitives::aliases::U256, #[allow(missing_docs)] - pub nativeToken: alloy_sol_types::private::Address, - #[allow(missing_docs)] pub spardose: alloy_sol_types::private::Address, } ///Container type for the return parameters of the - /// [`ensureTradePreconditions(address,address,address,uint256,address, + /// [`ensureTradePreconditions(address,address,address,uint256, /// address)`](ensureTradePreconditionsCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] @@ -195,7 +188,6 @@ pub mod Solver { alloy_sol_types::sol_data::Address, alloy_sol_types::sol_data::Uint<256>, alloy_sol_types::sol_data::Address, - alloy_sol_types::sol_data::Address, ); #[doc(hidden)] type UnderlyingRustTuple<'a> = ( @@ -204,7 +196,6 @@ pub mod Solver { alloy_sol_types::private::Address, alloy_sol_types::private::primitives::aliases::U256, alloy_sol_types::private::Address, - alloy_sol_types::private::Address, ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] @@ -224,7 +215,6 @@ pub mod Solver { value.settlementContract, value.sellToken, value.sellAmount, - value.nativeToken, value.spardose, ) } @@ -238,8 +228,7 @@ pub mod Solver { settlementContract: tuple.1, sellToken: tuple.2, sellAmount: tuple.3, - nativeToken: tuple.4, - spardose: tuple.5, + spardose: tuple.4, } } } @@ -290,16 +279,15 @@ pub mod Solver { alloy_sol_types::sol_data::Address, alloy_sol_types::sol_data::Uint<256>, alloy_sol_types::sol_data::Address, - alloy_sol_types::sol_data::Address, ); type Return = ensureTradePreconditionsReturn; type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; type ReturnTuple<'a> = (); type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SELECTOR: [u8; 4] = [37u8, 130u8, 237u8, 180u8]; + const SELECTOR: [u8; 4] = [47u8, 241u8, 17u8, 245u8]; const SIGNATURE: &'static str = - "ensureTradePreconditions(address,address,address,uint256,address,address)"; + "ensureTradePreconditions(address,address,address,uint256,address)"; #[inline] fn new<'a>( @@ -323,9 +311,6 @@ pub mod Solver { as alloy_sol_types::SolType>::tokenize( &self.sellAmount, ), - ::tokenize( - &self.nativeToken, - ), ::tokenize( &self.spardose, ), @@ -736,7 +721,7 @@ pub mod Solver { /// Prefer using `SolInterface` methods instead. pub const SELECTORS: &'static [[u8; 4usize]] = &[ [29u8, 71u8, 231u8, 244u8], - [37u8, 130u8, 237u8, 180u8], + [47u8, 241u8, 17u8, 245u8], [59u8, 187u8, 46u8, 29u8], ]; /// The signatures in the same order as `SELECTORS`. @@ -1083,7 +1068,6 @@ pub mod Solver { settlementContract: alloy_sol_types::private::Address, sellToken: alloy_sol_types::private::Address, sellAmount: alloy_sol_types::private::primitives::aliases::U256, - nativeToken: alloy_sol_types::private::Address, spardose: alloy_sol_types::private::Address, ) -> alloy_contract::SolCallBuilder<&P, ensureTradePreconditionsCall, N> { self.call_builder(&ensureTradePreconditionsCall { @@ -1091,7 +1075,6 @@ pub mod Solver { settlementContract, sellToken, sellAmount, - nativeToken, spardose, }) } diff --git a/contracts/generated/contracts-generated/trader/src/lib.rs b/contracts/generated/contracts-generated/trader/src/lib.rs index 9583bc614e..8fb9497e99 100644 --- a/contracts/generated/contracts-generated/trader/src/lib.rs +++ b/contracts/generated/contracts-generated/trader/src/lib.rs @@ -15,7 +15,7 @@ interface Trader { receive() external payable; - function ensureTradePreconditions(address settlementContract, address sellToken, uint256 sellAmount, address nativeToken, address spardose) external; + function ensureTradePreconditions(address settlementContract, address sellToken, uint256 sellAmount, address spardose) external; function isValidSignature(bytes32, bytes memory) external pure returns (bytes4); function safeApprove(address token, address vaultRelayer, uint256 amount) external; } @@ -51,11 +51,6 @@ interface Trader { "type": "uint256", "internalType": "uint256" }, - { - "name": "nativeToken", - "type": "address", - "internalType": "address" - }, { "name": "spardose", "type": "address", @@ -126,27 +121,27 @@ pub mod Trader { /// The creation / init bytecode of the contract. /// /// ```text - ///0x6080604052348015600e575f5ffd5b50610d008061001c5f395ff3fe608060405260043610610037575f3560e01c80631626ba7e1461008d578063542eb77d14610104578063eb5625d9146101255761003e565b3661003e57005b5f6100835f368080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525062010000939250506101449050565b9050805160208201f35b348015610098575f5ffd5b506100cf6100a7366004610b01565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010f575f5ffd5b5061012361011e366004610b9c565b6101c2565b005b348015610130575f5ffd5b5061012361013f366004610c00565b610916565b60605f8373ffffffffffffffffffffffffffffffffffffffff168360405161016c9190610c3e565b5f60405180830381855af49150503d805f81146101a4576040519150601f19603f3d011682016040523d82523d5f602084013e6101a9565b606091505b5092509050806101bb57815160208301fd5b5092915050565b7f02565dba7d68dcbed629110024b7b5e785bfc1a484602045eea513de8a2dcf99805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082161790915560ff16156102a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e6365000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036103e4576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa158015610340573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103649190610c6a565b9050838110156103e2575f6103798286610c81565b90508047106103e0578373ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004015f604051808303818588803b1580156103c8575f5ffd5b505af11580156103da573d5f5f3e3d5ffd5b50505050505b505b505b5f8573ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561042e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104529190610cb9565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff80831660248301529192505f9187169063dd62ed3e90604401602060405180830381865afa1580156104c7573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104eb9190610c6a565b905084811015610748576040517feb5625d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8088166004830152831660248201525f6044820152309063eb5625d9906064015f604051808303815f87803b158015610567575f5ffd5b505af1925050508015610578575060015b506040517feb5625d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8088166004830152831660248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6044820152309063eb5625d9906064015f604051808303815f87803b15801561060b575f5ffd5b505af192505050801561061c575060015b506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff83811660248301525f919088169063dd62ed3e90604401602060405180830381865afa158015610690573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106b49190610c6a565b905085811015610746576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f74726164657220646964206e6f7420676976652074686520726571756972656460448201527f20617070726f76616c7300000000000000000000000000000000000000000000606482015260840161029a565b505b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8816906370a0823190602401602060405180830381865afa1580156107b2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107d69190610c6a565b90508581101561090c5773ffffffffffffffffffffffffffffffffffffffff841663494666b688610807848a610c81565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff909216600483015260248201526044015f604051808303815f87803b15801561086f575f5ffd5b505af1925050508015610880575060015b61090c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f74726164657220646f6573206e6f74206861766520656e6f7567682073656c6c60448201527f20746f6b656e0000000000000000000000000000000000000000000000000000606482015260840161029a565b5050505050505050565b61093773ffffffffffffffffffffffffffffffffffffffff8416838361093c565b505050565b6040805173ffffffffffffffffffffffffffffffffffffffff848116602483015260448083018590528351808403909101815260649092019092526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052905f906109ce90861683610a46565b90506109d981610a5a565b610a3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f5361666545524332303a20617070726f76616c206661696c6564000000000000604482015260640161029a565b5050505050565b6060610a53835f84610a7f565b9392505050565b5f81515f1480610a79575081806020019051810190610a799190610cd4565b92915050565b60605f8473ffffffffffffffffffffffffffffffffffffffff168484604051610aa89190610c3e565b5f6040518083038185875af1925050503d805f8114610ae2576040519150601f19603f3d011682016040523d82523d5f602084013e610ae7565b606091505b509250905080610af957815160208301fd5b509392505050565b5f5f5f60408486031215610b13575f5ffd5b83359250602084013567ffffffffffffffff811115610b30575f5ffd5b8401601f81018613610b40575f5ffd5b803567ffffffffffffffff811115610b56575f5ffd5b866020828401011115610b67575f5ffd5b939660209190910195509293505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610b99575f5ffd5b50565b5f5f5f5f5f60a08688031215610bb0575f5ffd5b8535610bbb81610b78565b94506020860135610bcb81610b78565b9350604086013592506060860135610be281610b78565b91506080860135610bf281610b78565b809150509295509295909350565b5f5f5f60608486031215610c12575f5ffd5b8335610c1d81610b78565b92506020840135610c2d81610b78565b929592945050506040919091013590565b5f82515f5b81811015610c5d5760208186018101518583015201610c43565b505f920191825250919050565b5f60208284031215610c7a575f5ffd5b5051919050565b81810381811115610a79577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60208284031215610cc9575f5ffd5b8151610a5381610b78565b5f60208284031215610ce4575f5ffd5b81518015158114610a53575f5ffdfea164736f6c634300081e000a + ///0x6080604052348015600e575f5ffd5b50610baa8061001c5f395ff3fe608060405260043610610037575f3560e01c80631626ba7e1461008d5780635bbe8b3f14610104578063eb5625d9146101255761003e565b3661003e57005b5f6100835f368080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525062010000939250506101449050565b9050805160208201f35b348015610098575f5ffd5b506100cf6100a73660046109bf565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010f575f5ffd5b5061012361011e366004610a5a565b6101c2565b005b348015610130575f5ffd5b5061012361013f366004610aaa565b6107d4565b60605f8373ffffffffffffffffffffffffffffffffffffffff168360405161016c9190610ae8565b5f60405180830381855af49150503d805f81146101a4576040519150601f19603f3d011682016040523d82523d5f602084013e6101a9565b606091505b5092509050806101bb57815160208301fd5b5092915050565b7f02565dba7d68dcbed629110024b7b5e785bfc1a484602045eea513de8a2dcf99805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082161790915560ff16156102a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e6365000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b5f8473ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102ed573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103119190610b14565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff80831660248301529192505f9186169063dd62ed3e90604401602060405180830381865afa158015610386573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103aa9190610b2f565b905083811015610607576040517feb5625d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152831660248201525f6044820152309063eb5625d9906064015f604051808303815f87803b158015610426575f5ffd5b505af1925050508015610437575060015b506040517feb5625d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152831660248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6044820152309063eb5625d9906064015f604051808303815f87803b1580156104ca575f5ffd5b505af19250505080156104db575060015b506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff83811660248301525f919087169063dd62ed3e90604401602060405180830381865afa15801561054f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105739190610b2f565b905084811015610605576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f74726164657220646964206e6f7420676976652074686520726571756972656460448201527f20617070726f76616c7300000000000000000000000000000000000000000000606482015260840161029a565b505b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa158015610671573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106959190610b2f565b9050848110156107cb5773ffffffffffffffffffffffffffffffffffffffff841663494666b6876106c68489610b46565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff909216600483015260248201526044015f604051808303815f87803b15801561072e575f5ffd5b505af192505050801561073f575060015b6107cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f74726164657220646f6573206e6f74206861766520656e6f7567682073656c6c60448201527f20746f6b656e0000000000000000000000000000000000000000000000000000606482015260840161029a565b50505050505050565b6107f573ffffffffffffffffffffffffffffffffffffffff841683836107fa565b505050565b6040805173ffffffffffffffffffffffffffffffffffffffff848116602483015260448083018590528351808403909101815260649092019092526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052905f9061088c90861683610904565b905061089781610918565b6108fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f5361666545524332303a20617070726f76616c206661696c6564000000000000604482015260640161029a565b5050505050565b6060610911835f8461093d565b9392505050565b5f81515f14806109375750818060200190518101906109379190610b7e565b92915050565b60605f8473ffffffffffffffffffffffffffffffffffffffff1684846040516109669190610ae8565b5f6040518083038185875af1925050503d805f81146109a0576040519150601f19603f3d011682016040523d82523d5f602084013e6109a5565b606091505b5092509050806109b757815160208301fd5b509392505050565b5f5f5f604084860312156109d1575f5ffd5b83359250602084013567ffffffffffffffff8111156109ee575f5ffd5b8401601f810186136109fe575f5ffd5b803567ffffffffffffffff811115610a14575f5ffd5b866020828401011115610a25575f5ffd5b939660209190910195509293505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610a57575f5ffd5b50565b5f5f5f5f60808587031215610a6d575f5ffd5b8435610a7881610a36565b93506020850135610a8881610a36565b9250604085013591506060850135610a9f81610a36565b939692955090935050565b5f5f5f60608486031215610abc575f5ffd5b8335610ac781610a36565b92506020840135610ad781610a36565b929592945050506040919091013590565b5f82515f5b81811015610b075760208186018101518583015201610aed565b505f920191825250919050565b5f60208284031215610b24575f5ffd5b815161091181610a36565b5f60208284031215610b3f575f5ffd5b5051919050565b81810381811115610937577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60208284031215610b8e575f5ffd5b81518015158114610911575f5ffdfea164736f6c634300081e000a /// ``` #[rustfmt::skip] #[allow(clippy::all)] pub static BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( - b"`\x80`@R4\x80\x15`\x0EW__\xFD[Pa\r\0\x80a\0\x1C_9_\xF3\xFE`\x80`@R`\x046\x10a\x007W_5`\xE0\x1C\x80c\x16&\xBA~\x14a\0\x8DW\x80cT.\xB7}\x14a\x01\x04W\x80c\xEBV%\xD9\x14a\x01%Wa\0>V[6a\0>W\0[_a\0\x83_6\x80\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x93\x92\x91\x90\x81\x81R` \x01\x83\x83\x80\x82\x847_\x92\x01\x91\x90\x91RPb\x01\0\0\x93\x92PPa\x01D\x90PV[\x90P\x80Q` \x82\x01\xF3[4\x80\x15a\0\x98W__\xFD[Pa\0\xCFa\0\xA76`\x04a\x0B\x01V[\x7F\x16&\xBA~\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x93\x92PPPV[`@Q\x7F\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x90\x91\x16\x81R` \x01`@Q\x80\x91\x03\x90\xF3[4\x80\x15a\x01\x0FW__\xFD[Pa\x01#a\x01\x1E6`\x04a\x0B\x9CV[a\x01\xC2V[\0[4\x80\x15a\x010W__\xFD[Pa\x01#a\x01?6`\x04a\x0C\0V[a\t\x16V[``_\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83`@Qa\x01l\x91\x90a\x0C>V[_`@Q\x80\x83\x03\x81\x85Z\xF4\x91PP=\x80_\x81\x14a\x01\xA4W`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\x01\xA9V[``\x91P[P\x92P\x90P\x80a\x01\xBBW\x81Q` \x83\x01\xFD[P\x92\x91PPV[\x7F\x02V]\xBA}h\xDC\xBE\xD6)\x11\0$\xB7\xB5\xE7\x85\xBF\xC1\xA4\x84` E\xEE\xA5\x13\xDE\x8A-\xCF\x99\x80T`\x01\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\x82\x16\x17\x90\x91U`\xFF\x16\x15a\x02\xA3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`#`$\x82\x01R\x7FprepareSwap can only be called o`D\x82\x01R\x7Fnce\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`d\x82\x01R`\x84\x01[`@Q\x80\x91\x03\x90\xFD[\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x03\xE4W`@Q\x7Fp\xA0\x821\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R0`\x04\x82\x01R_\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x86\x16\x90cp\xA0\x821\x90`$\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x03@W=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x03d\x91\x90a\x0CjV[\x90P\x83\x81\x10\x15a\x03\xE2W_a\x03y\x82\x86a\x0C\x81V[\x90P\x80G\x10a\x03\xE0W\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16c\xD0\xE3\r\xB0\x82`@Q\x82c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01_`@Q\x80\x83\x03\x81\x85\x88\x80;\x15\x80\x15a\x03\xC8W__\xFD[PZ\xF1\x15\x80\x15a\x03\xDAW=__>=_\xFD[PPPPP[P[P[_\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16c\x9BU,\xC2`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x04.W=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x04R\x91\x90a\x0C\xB9V[`@Q\x7F\xDDb\xED>\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R0`\x04\x82\x01Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x83\x16`$\x83\x01R\x91\x92P_\x91\x87\x16\x90c\xDDb\xED>\x90`D\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x04\xC7W=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x04\xEB\x91\x90a\x0CjV[\x90P\x84\x81\x10\x15a\x07HW`@Q\x7F\xEBV%\xD9\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x88\x16`\x04\x83\x01R\x83\x16`$\x82\x01R_`D\x82\x01R0\x90c\xEBV%\xD9\x90`d\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x05gW__\xFD[PZ\xF1\x92PPP\x80\x15a\x05xWP`\x01[P`@Q\x7F\xEBV%\xD9\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x88\x16`\x04\x83\x01R\x83\x16`$\x82\x01R\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF`D\x82\x01R0\x90c\xEBV%\xD9\x90`d\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x06\x0BW__\xFD[PZ\xF1\x92PPP\x80\x15a\x06\x1CWP`\x01[P`@Q\x7F\xDDb\xED>\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R0`\x04\x82\x01Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x81\x16`$\x83\x01R_\x91\x90\x88\x16\x90c\xDDb\xED>\x90`D\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x06\x90W=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x06\xB4\x91\x90a\x0CjV[\x90P\x85\x81\x10\x15a\x07FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`*`$\x82\x01R\x7Ftrader did not give the required`D\x82\x01R\x7F approvals\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`d\x82\x01R`\x84\x01a\x02\x9AV[P[`@Q\x7Fp\xA0\x821\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R0`\x04\x82\x01R_\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x88\x16\x90cp\xA0\x821\x90`$\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x07\xB2W=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x07\xD6\x91\x90a\x0CjV[\x90P\x85\x81\x10\x15a\t\x0CWs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x16cIFf\xB6\x88a\x08\x07\x84\x8Aa\x0C\x81V[`@Q\x7F\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\xE0\x85\x90\x1B\x16\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x92\x16`\x04\x83\x01R`$\x82\x01R`D\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x08oW__\xFD[PZ\xF1\x92PPP\x80\x15a\x08\x80WP`\x01[a\t\x0CW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`&`$\x82\x01R\x7Ftrader does not have enough sell`D\x82\x01R\x7F token\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`d\x82\x01R`\x84\x01a\x02\x9AV[PPPPPPPPV[a\t7s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x16\x83\x83a\tV[_`@Q\x80\x83\x03\x81\x85\x87Z\xF1\x92PPP=\x80_\x81\x14a\n\xE2W`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\n\xE7V[``\x91P[P\x92P\x90P\x80a\n\xF9W\x81Q` \x83\x01\xFD[P\x93\x92PPPV[___`@\x84\x86\x03\x12\x15a\x0B\x13W__\xFD[\x835\x92P` \x84\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0B0W__\xFD[\x84\x01`\x1F\x81\x01\x86\x13a\x0B@W__\xFD[\x805g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0BVW__\xFD[\x86` \x82\x84\x01\x01\x11\x15a\x0BgW__\xFD[\x93\x96` \x91\x90\x91\x01\x95P\x92\x93PPPV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16\x81\x14a\x0B\x99W__\xFD[PV[_____`\xA0\x86\x88\x03\x12\x15a\x0B\xB0W__\xFD[\x855a\x0B\xBB\x81a\x0BxV[\x94P` \x86\x015a\x0B\xCB\x81a\x0BxV[\x93P`@\x86\x015\x92P``\x86\x015a\x0B\xE2\x81a\x0BxV[\x91P`\x80\x86\x015a\x0B\xF2\x81a\x0BxV[\x80\x91PP\x92\x95P\x92\x95\x90\x93PV[___``\x84\x86\x03\x12\x15a\x0C\x12W__\xFD[\x835a\x0C\x1D\x81a\x0BxV[\x92P` \x84\x015a\x0C-\x81a\x0BxV[\x92\x95\x92\x94PPP`@\x91\x90\x91\x015\x90V[_\x82Q_[\x81\x81\x10\x15a\x0C]W` \x81\x86\x01\x81\x01Q\x85\x83\x01R\x01a\x0CCV[P_\x92\x01\x91\x82RP\x91\x90PV[_` \x82\x84\x03\x12\x15a\x0CzW__\xFD[PQ\x91\x90PV[\x81\x81\x03\x81\x81\x11\x15a\nyW\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_` \x82\x84\x03\x12\x15a\x0C\xC9W__\xFD[\x81Qa\nS\x81a\x0BxV[_` \x82\x84\x03\x12\x15a\x0C\xE4W__\xFD[\x81Q\x80\x15\x15\x81\x14a\nSW__\xFD\xFE\xA1dsolcC\0\x08\x1E\0\n", + b"`\x80`@R4\x80\x15`\x0EW__\xFD[Pa\x0B\xAA\x80a\0\x1C_9_\xF3\xFE`\x80`@R`\x046\x10a\x007W_5`\xE0\x1C\x80c\x16&\xBA~\x14a\0\x8DW\x80c[\xBE\x8B?\x14a\x01\x04W\x80c\xEBV%\xD9\x14a\x01%Wa\0>V[6a\0>W\0[_a\0\x83_6\x80\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x93\x92\x91\x90\x81\x81R` \x01\x83\x83\x80\x82\x847_\x92\x01\x91\x90\x91RPb\x01\0\0\x93\x92PPa\x01D\x90PV[\x90P\x80Q` \x82\x01\xF3[4\x80\x15a\0\x98W__\xFD[Pa\0\xCFa\0\xA76`\x04a\t\xBFV[\x7F\x16&\xBA~\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x93\x92PPPV[`@Q\x7F\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x90\x91\x16\x81R` \x01`@Q\x80\x91\x03\x90\xF3[4\x80\x15a\x01\x0FW__\xFD[Pa\x01#a\x01\x1E6`\x04a\nZV[a\x01\xC2V[\0[4\x80\x15a\x010W__\xFD[Pa\x01#a\x01?6`\x04a\n\xAAV[a\x07\xD4V[``_\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83`@Qa\x01l\x91\x90a\n\xE8V[_`@Q\x80\x83\x03\x81\x85Z\xF4\x91PP=\x80_\x81\x14a\x01\xA4W`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\x01\xA9V[``\x91P[P\x92P\x90P\x80a\x01\xBBW\x81Q` \x83\x01\xFD[P\x92\x91PPV[\x7F\x02V]\xBA}h\xDC\xBE\xD6)\x11\0$\xB7\xB5\xE7\x85\xBF\xC1\xA4\x84` E\xEE\xA5\x13\xDE\x8A-\xCF\x99\x80T`\x01\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\x82\x16\x17\x90\x91U`\xFF\x16\x15a\x02\xA3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`#`$\x82\x01R\x7FprepareSwap can only be called o`D\x82\x01R\x7Fnce\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`d\x82\x01R`\x84\x01[`@Q\x80\x91\x03\x90\xFD[_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16c\x9BU,\xC2`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x02\xEDW=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x03\x11\x91\x90a\x0B\x14V[`@Q\x7F\xDDb\xED>\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R0`\x04\x82\x01Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x83\x16`$\x83\x01R\x91\x92P_\x91\x86\x16\x90c\xDDb\xED>\x90`D\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x03\x86W=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x03\xAA\x91\x90a\x0B/V[\x90P\x83\x81\x10\x15a\x06\x07W`@Q\x7F\xEBV%\xD9\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x87\x16`\x04\x83\x01R\x83\x16`$\x82\x01R_`D\x82\x01R0\x90c\xEBV%\xD9\x90`d\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x04&W__\xFD[PZ\xF1\x92PPP\x80\x15a\x047WP`\x01[P`@Q\x7F\xEBV%\xD9\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x87\x16`\x04\x83\x01R\x83\x16`$\x82\x01R\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF`D\x82\x01R0\x90c\xEBV%\xD9\x90`d\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x04\xCAW__\xFD[PZ\xF1\x92PPP\x80\x15a\x04\xDBWP`\x01[P`@Q\x7F\xDDb\xED>\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R0`\x04\x82\x01Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x81\x16`$\x83\x01R_\x91\x90\x87\x16\x90c\xDDb\xED>\x90`D\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x05OW=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x05s\x91\x90a\x0B/V[\x90P\x84\x81\x10\x15a\x06\x05W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`*`$\x82\x01R\x7Ftrader did not give the required`D\x82\x01R\x7F approvals\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`d\x82\x01R`\x84\x01a\x02\x9AV[P[`@Q\x7Fp\xA0\x821\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R0`\x04\x82\x01R_\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x87\x16\x90cp\xA0\x821\x90`$\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x06qW=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x06\x95\x91\x90a\x0B/V[\x90P\x84\x81\x10\x15a\x07\xCBWs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x16cIFf\xB6\x87a\x06\xC6\x84\x89a\x0BFV[`@Q\x7F\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\xE0\x85\x90\x1B\x16\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x92\x16`\x04\x83\x01R`$\x82\x01R`D\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x07.W__\xFD[PZ\xF1\x92PPP\x80\x15a\x07?WP`\x01[a\x07\xCBW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`&`$\x82\x01R\x7Ftrader does not have enough sell`D\x82\x01R\x7F token\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`d\x82\x01R`\x84\x01a\x02\x9AV[PPPPPPPV[a\x07\xF5s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x16\x83\x83a\x07\xFAV[PPPV[`@\x80Qs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x81\x16`$\x83\x01R`D\x80\x83\x01\x85\x90R\x83Q\x80\x84\x03\x90\x91\x01\x81R`d\x90\x92\x01\x90\x92R` \x81\x01\x80Q{\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x7F\t^\xA7\xB3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x17\x90R\x90_\x90a\x08\x8C\x90\x86\x16\x83a\t\x04V[\x90Pa\x08\x97\x81a\t\x18V[a\x08\xFDW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x1A`$\x82\x01R\x7FSafeERC20: approval failed\0\0\0\0\0\0`D\x82\x01R`d\x01a\x02\x9AV[PPPPPV[``a\t\x11\x83_\x84a\t=V[\x93\x92PPPV[_\x81Q_\x14\x80a\t7WP\x81\x80` \x01\x90Q\x81\x01\x90a\t7\x91\x90a\x0B~V[\x92\x91PPV[``_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84\x84`@Qa\tf\x91\x90a\n\xE8V[_`@Q\x80\x83\x03\x81\x85\x87Z\xF1\x92PPP=\x80_\x81\x14a\t\xA0W`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\t\xA5V[``\x91P[P\x92P\x90P\x80a\t\xB7W\x81Q` \x83\x01\xFD[P\x93\x92PPPV[___`@\x84\x86\x03\x12\x15a\t\xD1W__\xFD[\x835\x92P` \x84\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\t\xEEW__\xFD[\x84\x01`\x1F\x81\x01\x86\x13a\t\xFEW__\xFD[\x805g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\n\x14W__\xFD[\x86` \x82\x84\x01\x01\x11\x15a\n%W__\xFD[\x93\x96` \x91\x90\x91\x01\x95P\x92\x93PPPV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16\x81\x14a\nWW__\xFD[PV[____`\x80\x85\x87\x03\x12\x15a\nmW__\xFD[\x845a\nx\x81a\n6V[\x93P` \x85\x015a\n\x88\x81a\n6V[\x92P`@\x85\x015\x91P``\x85\x015a\n\x9F\x81a\n6V[\x93\x96\x92\x95P\x90\x93PPV[___``\x84\x86\x03\x12\x15a\n\xBCW__\xFD[\x835a\n\xC7\x81a\n6V[\x92P` \x84\x015a\n\xD7\x81a\n6V[\x92\x95\x92\x94PPP`@\x91\x90\x91\x015\x90V[_\x82Q_[\x81\x81\x10\x15a\x0B\x07W` \x81\x86\x01\x81\x01Q\x85\x83\x01R\x01a\n\xEDV[P_\x92\x01\x91\x82RP\x91\x90PV[_` \x82\x84\x03\x12\x15a\x0B$W__\xFD[\x81Qa\t\x11\x81a\n6V[_` \x82\x84\x03\x12\x15a\x0B?W__\xFD[PQ\x91\x90PV[\x81\x81\x03\x81\x81\x11\x15a\t7W\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_` \x82\x84\x03\x12\x15a\x0B\x8EW__\xFD[\x81Q\x80\x15\x15\x81\x14a\t\x11W__\xFD\xFE\xA1dsolcC\0\x08\x1E\0\n", ); /// The runtime bytecode of the contract, as deployed on the network. /// /// ```text - ///0x608060405260043610610037575f3560e01c80631626ba7e1461008d578063542eb77d14610104578063eb5625d9146101255761003e565b3661003e57005b5f6100835f368080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525062010000939250506101449050565b9050805160208201f35b348015610098575f5ffd5b506100cf6100a7366004610b01565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010f575f5ffd5b5061012361011e366004610b9c565b6101c2565b005b348015610130575f5ffd5b5061012361013f366004610c00565b610916565b60605f8373ffffffffffffffffffffffffffffffffffffffff168360405161016c9190610c3e565b5f60405180830381855af49150503d805f81146101a4576040519150601f19603f3d011682016040523d82523d5f602084013e6101a9565b606091505b5092509050806101bb57815160208301fd5b5092915050565b7f02565dba7d68dcbed629110024b7b5e785bfc1a484602045eea513de8a2dcf99805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082161790915560ff16156102a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e6365000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16036103e4576040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa158015610340573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103649190610c6a565b9050838110156103e2575f6103798286610c81565b90508047106103e0578373ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004015f604051808303818588803b1580156103c8575f5ffd5b505af11580156103da573d5f5f3e3d5ffd5b50505050505b505b505b5f8573ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561042e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104529190610cb9565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff80831660248301529192505f9187169063dd62ed3e90604401602060405180830381865afa1580156104c7573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104eb9190610c6a565b905084811015610748576040517feb5625d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8088166004830152831660248201525f6044820152309063eb5625d9906064015f604051808303815f87803b158015610567575f5ffd5b505af1925050508015610578575060015b506040517feb5625d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8088166004830152831660248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6044820152309063eb5625d9906064015f604051808303815f87803b15801561060b575f5ffd5b505af192505050801561061c575060015b506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff83811660248301525f919088169063dd62ed3e90604401602060405180830381865afa158015610690573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106b49190610c6a565b905085811015610746576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f74726164657220646964206e6f7420676976652074686520726571756972656460448201527f20617070726f76616c7300000000000000000000000000000000000000000000606482015260840161029a565b505b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8816906370a0823190602401602060405180830381865afa1580156107b2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107d69190610c6a565b90508581101561090c5773ffffffffffffffffffffffffffffffffffffffff841663494666b688610807848a610c81565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff909216600483015260248201526044015f604051808303815f87803b15801561086f575f5ffd5b505af1925050508015610880575060015b61090c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f74726164657220646f6573206e6f74206861766520656e6f7567682073656c6c60448201527f20746f6b656e0000000000000000000000000000000000000000000000000000606482015260840161029a565b5050505050505050565b61093773ffffffffffffffffffffffffffffffffffffffff8416838361093c565b505050565b6040805173ffffffffffffffffffffffffffffffffffffffff848116602483015260448083018590528351808403909101815260649092019092526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052905f906109ce90861683610a46565b90506109d981610a5a565b610a3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f5361666545524332303a20617070726f76616c206661696c6564000000000000604482015260640161029a565b5050505050565b6060610a53835f84610a7f565b9392505050565b5f81515f1480610a79575081806020019051810190610a799190610cd4565b92915050565b60605f8473ffffffffffffffffffffffffffffffffffffffff168484604051610aa89190610c3e565b5f6040518083038185875af1925050503d805f8114610ae2576040519150601f19603f3d011682016040523d82523d5f602084013e610ae7565b606091505b509250905080610af957815160208301fd5b509392505050565b5f5f5f60408486031215610b13575f5ffd5b83359250602084013567ffffffffffffffff811115610b30575f5ffd5b8401601f81018613610b40575f5ffd5b803567ffffffffffffffff811115610b56575f5ffd5b866020828401011115610b67575f5ffd5b939660209190910195509293505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610b99575f5ffd5b50565b5f5f5f5f5f60a08688031215610bb0575f5ffd5b8535610bbb81610b78565b94506020860135610bcb81610b78565b9350604086013592506060860135610be281610b78565b91506080860135610bf281610b78565b809150509295509295909350565b5f5f5f60608486031215610c12575f5ffd5b8335610c1d81610b78565b92506020840135610c2d81610b78565b929592945050506040919091013590565b5f82515f5b81811015610c5d5760208186018101518583015201610c43565b505f920191825250919050565b5f60208284031215610c7a575f5ffd5b5051919050565b81810381811115610a79577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60208284031215610cc9575f5ffd5b8151610a5381610b78565b5f60208284031215610ce4575f5ffd5b81518015158114610a53575f5ffdfea164736f6c634300081e000a + ///0x608060405260043610610037575f3560e01c80631626ba7e1461008d5780635bbe8b3f14610104578063eb5625d9146101255761003e565b3661003e57005b5f6100835f368080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525062010000939250506101449050565b9050805160208201f35b348015610098575f5ffd5b506100cf6100a73660046109bf565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010f575f5ffd5b5061012361011e366004610a5a565b6101c2565b005b348015610130575f5ffd5b5061012361013f366004610aaa565b6107d4565b60605f8373ffffffffffffffffffffffffffffffffffffffff168360405161016c9190610ae8565b5f60405180830381855af49150503d805f81146101a4576040519150601f19603f3d011682016040523d82523d5f602084013e6101a9565b606091505b5092509050806101bb57815160208301fd5b5092915050565b7f02565dba7d68dcbed629110024b7b5e785bfc1a484602045eea513de8a2dcf99805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082161790915560ff16156102a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e6365000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b5f8473ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102ed573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103119190610b14565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff80831660248301529192505f9186169063dd62ed3e90604401602060405180830381865afa158015610386573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103aa9190610b2f565b905083811015610607576040517feb5625d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152831660248201525f6044820152309063eb5625d9906064015f604051808303815f87803b158015610426575f5ffd5b505af1925050508015610437575060015b506040517feb5625d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152831660248201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6044820152309063eb5625d9906064015f604051808303815f87803b1580156104ca575f5ffd5b505af19250505080156104db575060015b506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff83811660248301525f919087169063dd62ed3e90604401602060405180830381865afa15801561054f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105739190610b2f565b905084811015610605576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f74726164657220646964206e6f7420676976652074686520726571756972656460448201527f20617070726f76616c7300000000000000000000000000000000000000000000606482015260840161029a565b505b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa158015610671573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106959190610b2f565b9050848110156107cb5773ffffffffffffffffffffffffffffffffffffffff841663494666b6876106c68489610b46565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff909216600483015260248201526044015f604051808303815f87803b15801561072e575f5ffd5b505af192505050801561073f575060015b6107cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f74726164657220646f6573206e6f74206861766520656e6f7567682073656c6c60448201527f20746f6b656e0000000000000000000000000000000000000000000000000000606482015260840161029a565b50505050505050565b6107f573ffffffffffffffffffffffffffffffffffffffff841683836107fa565b505050565b6040805173ffffffffffffffffffffffffffffffffffffffff848116602483015260448083018590528351808403909101815260649092019092526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052905f9061088c90861683610904565b905061089781610918565b6108fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f5361666545524332303a20617070726f76616c206661696c6564000000000000604482015260640161029a565b5050505050565b6060610911835f8461093d565b9392505050565b5f81515f14806109375750818060200190518101906109379190610b7e565b92915050565b60605f8473ffffffffffffffffffffffffffffffffffffffff1684846040516109669190610ae8565b5f6040518083038185875af1925050503d805f81146109a0576040519150601f19603f3d011682016040523d82523d5f602084013e6109a5565b606091505b5092509050806109b757815160208301fd5b509392505050565b5f5f5f604084860312156109d1575f5ffd5b83359250602084013567ffffffffffffffff8111156109ee575f5ffd5b8401601f810186136109fe575f5ffd5b803567ffffffffffffffff811115610a14575f5ffd5b866020828401011115610a25575f5ffd5b939660209190910195509293505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610a57575f5ffd5b50565b5f5f5f5f60808587031215610a6d575f5ffd5b8435610a7881610a36565b93506020850135610a8881610a36565b9250604085013591506060850135610a9f81610a36565b939692955090935050565b5f5f5f60608486031215610abc575f5ffd5b8335610ac781610a36565b92506020840135610ad781610a36565b929592945050506040919091013590565b5f82515f5b81811015610b075760208186018101518583015201610aed565b505f920191825250919050565b5f60208284031215610b24575f5ffd5b815161091181610a36565b5f60208284031215610b3f575f5ffd5b5051919050565b81810381811115610937577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f60208284031215610b8e575f5ffd5b81518015158114610911575f5ffdfea164736f6c634300081e000a /// ``` #[rustfmt::skip] #[allow(clippy::all)] pub static DEPLOYED_BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( - b"`\x80`@R`\x046\x10a\x007W_5`\xE0\x1C\x80c\x16&\xBA~\x14a\0\x8DW\x80cT.\xB7}\x14a\x01\x04W\x80c\xEBV%\xD9\x14a\x01%Wa\0>V[6a\0>W\0[_a\0\x83_6\x80\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x93\x92\x91\x90\x81\x81R` \x01\x83\x83\x80\x82\x847_\x92\x01\x91\x90\x91RPb\x01\0\0\x93\x92PPa\x01D\x90PV[\x90P\x80Q` \x82\x01\xF3[4\x80\x15a\0\x98W__\xFD[Pa\0\xCFa\0\xA76`\x04a\x0B\x01V[\x7F\x16&\xBA~\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x93\x92PPPV[`@Q\x7F\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x90\x91\x16\x81R` \x01`@Q\x80\x91\x03\x90\xF3[4\x80\x15a\x01\x0FW__\xFD[Pa\x01#a\x01\x1E6`\x04a\x0B\x9CV[a\x01\xC2V[\0[4\x80\x15a\x010W__\xFD[Pa\x01#a\x01?6`\x04a\x0C\0V[a\t\x16V[``_\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83`@Qa\x01l\x91\x90a\x0C>V[_`@Q\x80\x83\x03\x81\x85Z\xF4\x91PP=\x80_\x81\x14a\x01\xA4W`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\x01\xA9V[``\x91P[P\x92P\x90P\x80a\x01\xBBW\x81Q` \x83\x01\xFD[P\x92\x91PPV[\x7F\x02V]\xBA}h\xDC\xBE\xD6)\x11\0$\xB7\xB5\xE7\x85\xBF\xC1\xA4\x84` E\xEE\xA5\x13\xDE\x8A-\xCF\x99\x80T`\x01\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\x82\x16\x17\x90\x91U`\xFF\x16\x15a\x02\xA3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`#`$\x82\x01R\x7FprepareSwap can only be called o`D\x82\x01R\x7Fnce\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`d\x82\x01R`\x84\x01[`@Q\x80\x91\x03\x90\xFD[\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x03\xE4W`@Q\x7Fp\xA0\x821\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R0`\x04\x82\x01R_\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x86\x16\x90cp\xA0\x821\x90`$\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x03@W=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x03d\x91\x90a\x0CjV[\x90P\x83\x81\x10\x15a\x03\xE2W_a\x03y\x82\x86a\x0C\x81V[\x90P\x80G\x10a\x03\xE0W\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16c\xD0\xE3\r\xB0\x82`@Q\x82c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01_`@Q\x80\x83\x03\x81\x85\x88\x80;\x15\x80\x15a\x03\xC8W__\xFD[PZ\xF1\x15\x80\x15a\x03\xDAW=__>=_\xFD[PPPPP[P[P[_\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16c\x9BU,\xC2`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x04.W=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x04R\x91\x90a\x0C\xB9V[`@Q\x7F\xDDb\xED>\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R0`\x04\x82\x01Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x83\x16`$\x83\x01R\x91\x92P_\x91\x87\x16\x90c\xDDb\xED>\x90`D\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x04\xC7W=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x04\xEB\x91\x90a\x0CjV[\x90P\x84\x81\x10\x15a\x07HW`@Q\x7F\xEBV%\xD9\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x88\x16`\x04\x83\x01R\x83\x16`$\x82\x01R_`D\x82\x01R0\x90c\xEBV%\xD9\x90`d\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x05gW__\xFD[PZ\xF1\x92PPP\x80\x15a\x05xWP`\x01[P`@Q\x7F\xEBV%\xD9\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x88\x16`\x04\x83\x01R\x83\x16`$\x82\x01R\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF`D\x82\x01R0\x90c\xEBV%\xD9\x90`d\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x06\x0BW__\xFD[PZ\xF1\x92PPP\x80\x15a\x06\x1CWP`\x01[P`@Q\x7F\xDDb\xED>\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R0`\x04\x82\x01Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x81\x16`$\x83\x01R_\x91\x90\x88\x16\x90c\xDDb\xED>\x90`D\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x06\x90W=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x06\xB4\x91\x90a\x0CjV[\x90P\x85\x81\x10\x15a\x07FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`*`$\x82\x01R\x7Ftrader did not give the required`D\x82\x01R\x7F approvals\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`d\x82\x01R`\x84\x01a\x02\x9AV[P[`@Q\x7Fp\xA0\x821\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R0`\x04\x82\x01R_\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x88\x16\x90cp\xA0\x821\x90`$\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x07\xB2W=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x07\xD6\x91\x90a\x0CjV[\x90P\x85\x81\x10\x15a\t\x0CWs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x16cIFf\xB6\x88a\x08\x07\x84\x8Aa\x0C\x81V[`@Q\x7F\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\xE0\x85\x90\x1B\x16\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x92\x16`\x04\x83\x01R`$\x82\x01R`D\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x08oW__\xFD[PZ\xF1\x92PPP\x80\x15a\x08\x80WP`\x01[a\t\x0CW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`&`$\x82\x01R\x7Ftrader does not have enough sell`D\x82\x01R\x7F token\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`d\x82\x01R`\x84\x01a\x02\x9AV[PPPPPPPPV[a\t7s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x16\x83\x83a\tV[_`@Q\x80\x83\x03\x81\x85\x87Z\xF1\x92PPP=\x80_\x81\x14a\n\xE2W`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\n\xE7V[``\x91P[P\x92P\x90P\x80a\n\xF9W\x81Q` \x83\x01\xFD[P\x93\x92PPPV[___`@\x84\x86\x03\x12\x15a\x0B\x13W__\xFD[\x835\x92P` \x84\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0B0W__\xFD[\x84\x01`\x1F\x81\x01\x86\x13a\x0B@W__\xFD[\x805g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0BVW__\xFD[\x86` \x82\x84\x01\x01\x11\x15a\x0BgW__\xFD[\x93\x96` \x91\x90\x91\x01\x95P\x92\x93PPPV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16\x81\x14a\x0B\x99W__\xFD[PV[_____`\xA0\x86\x88\x03\x12\x15a\x0B\xB0W__\xFD[\x855a\x0B\xBB\x81a\x0BxV[\x94P` \x86\x015a\x0B\xCB\x81a\x0BxV[\x93P`@\x86\x015\x92P``\x86\x015a\x0B\xE2\x81a\x0BxV[\x91P`\x80\x86\x015a\x0B\xF2\x81a\x0BxV[\x80\x91PP\x92\x95P\x92\x95\x90\x93PV[___``\x84\x86\x03\x12\x15a\x0C\x12W__\xFD[\x835a\x0C\x1D\x81a\x0BxV[\x92P` \x84\x015a\x0C-\x81a\x0BxV[\x92\x95\x92\x94PPP`@\x91\x90\x91\x015\x90V[_\x82Q_[\x81\x81\x10\x15a\x0C]W` \x81\x86\x01\x81\x01Q\x85\x83\x01R\x01a\x0CCV[P_\x92\x01\x91\x82RP\x91\x90PV[_` \x82\x84\x03\x12\x15a\x0CzW__\xFD[PQ\x91\x90PV[\x81\x81\x03\x81\x81\x11\x15a\nyW\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_` \x82\x84\x03\x12\x15a\x0C\xC9W__\xFD[\x81Qa\nS\x81a\x0BxV[_` \x82\x84\x03\x12\x15a\x0C\xE4W__\xFD[\x81Q\x80\x15\x15\x81\x14a\nSW__\xFD\xFE\xA1dsolcC\0\x08\x1E\0\n", + b"`\x80`@R`\x046\x10a\x007W_5`\xE0\x1C\x80c\x16&\xBA~\x14a\0\x8DW\x80c[\xBE\x8B?\x14a\x01\x04W\x80c\xEBV%\xD9\x14a\x01%Wa\0>V[6a\0>W\0[_a\0\x83_6\x80\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x93\x92\x91\x90\x81\x81R` \x01\x83\x83\x80\x82\x847_\x92\x01\x91\x90\x91RPb\x01\0\0\x93\x92PPa\x01D\x90PV[\x90P\x80Q` \x82\x01\xF3[4\x80\x15a\0\x98W__\xFD[Pa\0\xCFa\0\xA76`\x04a\t\xBFV[\x7F\x16&\xBA~\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x93\x92PPPV[`@Q\x7F\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x90\x91\x16\x81R` \x01`@Q\x80\x91\x03\x90\xF3[4\x80\x15a\x01\x0FW__\xFD[Pa\x01#a\x01\x1E6`\x04a\nZV[a\x01\xC2V[\0[4\x80\x15a\x010W__\xFD[Pa\x01#a\x01?6`\x04a\n\xAAV[a\x07\xD4V[``_\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83`@Qa\x01l\x91\x90a\n\xE8V[_`@Q\x80\x83\x03\x81\x85Z\xF4\x91PP=\x80_\x81\x14a\x01\xA4W`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\x01\xA9V[``\x91P[P\x92P\x90P\x80a\x01\xBBW\x81Q` \x83\x01\xFD[P\x92\x91PPV[\x7F\x02V]\xBA}h\xDC\xBE\xD6)\x11\0$\xB7\xB5\xE7\x85\xBF\xC1\xA4\x84` E\xEE\xA5\x13\xDE\x8A-\xCF\x99\x80T`\x01\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\x82\x16\x17\x90\x91U`\xFF\x16\x15a\x02\xA3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`#`$\x82\x01R\x7FprepareSwap can only be called o`D\x82\x01R\x7Fnce\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`d\x82\x01R`\x84\x01[`@Q\x80\x91\x03\x90\xFD[_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16c\x9BU,\xC2`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x02\xEDW=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x03\x11\x91\x90a\x0B\x14V[`@Q\x7F\xDDb\xED>\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R0`\x04\x82\x01Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x83\x16`$\x83\x01R\x91\x92P_\x91\x86\x16\x90c\xDDb\xED>\x90`D\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x03\x86W=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x03\xAA\x91\x90a\x0B/V[\x90P\x83\x81\x10\x15a\x06\x07W`@Q\x7F\xEBV%\xD9\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x87\x16`\x04\x83\x01R\x83\x16`$\x82\x01R_`D\x82\x01R0\x90c\xEBV%\xD9\x90`d\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x04&W__\xFD[PZ\xF1\x92PPP\x80\x15a\x047WP`\x01[P`@Q\x7F\xEBV%\xD9\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x80\x87\x16`\x04\x83\x01R\x83\x16`$\x82\x01R\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF`D\x82\x01R0\x90c\xEBV%\xD9\x90`d\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x04\xCAW__\xFD[PZ\xF1\x92PPP\x80\x15a\x04\xDBWP`\x01[P`@Q\x7F\xDDb\xED>\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R0`\x04\x82\x01Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x81\x16`$\x83\x01R_\x91\x90\x87\x16\x90c\xDDb\xED>\x90`D\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x05OW=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x05s\x91\x90a\x0B/V[\x90P\x84\x81\x10\x15a\x06\x05W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`*`$\x82\x01R\x7Ftrader did not give the required`D\x82\x01R\x7F approvals\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`d\x82\x01R`\x84\x01a\x02\x9AV[P[`@Q\x7Fp\xA0\x821\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R0`\x04\x82\x01R_\x90s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x87\x16\x90cp\xA0\x821\x90`$\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x06qW=__>=_\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x06\x95\x91\x90a\x0B/V[\x90P\x84\x81\x10\x15a\x07\xCBWs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x16cIFf\xB6\x87a\x06\xC6\x84\x89a\x0BFV[`@Q\x7F\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\xE0\x85\x90\x1B\x16\x81Rs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x90\x92\x16`\x04\x83\x01R`$\x82\x01R`D\x01_`@Q\x80\x83\x03\x81_\x87\x80;\x15\x80\x15a\x07.W__\xFD[PZ\xF1\x92PPP\x80\x15a\x07?WP`\x01[a\x07\xCBW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`&`$\x82\x01R\x7Ftrader does not have enough sell`D\x82\x01R\x7F token\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`d\x82\x01R`\x84\x01a\x02\x9AV[PPPPPPPV[a\x07\xF5s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x16\x83\x83a\x07\xFAV[PPPV[`@\x80Qs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x84\x81\x16`$\x83\x01R`D\x80\x83\x01\x85\x90R\x83Q\x80\x84\x03\x90\x91\x01\x81R`d\x90\x92\x01\x90\x92R` \x81\x01\x80Q{\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x7F\t^\xA7\xB3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x17\x90R\x90_\x90a\x08\x8C\x90\x86\x16\x83a\t\x04V[\x90Pa\x08\x97\x81a\t\x18V[a\x08\xFDW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R` `\x04\x82\x01R`\x1A`$\x82\x01R\x7FSafeERC20: approval failed\0\0\0\0\0\0`D\x82\x01R`d\x01a\x02\x9AV[PPPPPV[``a\t\x11\x83_\x84a\t=V[\x93\x92PPPV[_\x81Q_\x14\x80a\t7WP\x81\x80` \x01\x90Q\x81\x01\x90a\t7\x91\x90a\x0B~V[\x92\x91PPV[``_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84\x84`@Qa\tf\x91\x90a\n\xE8V[_`@Q\x80\x83\x03\x81\x85\x87Z\xF1\x92PPP=\x80_\x81\x14a\t\xA0W`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\t\xA5V[``\x91P[P\x92P\x90P\x80a\t\xB7W\x81Q` \x83\x01\xFD[P\x93\x92PPPV[___`@\x84\x86\x03\x12\x15a\t\xD1W__\xFD[\x835\x92P` \x84\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\t\xEEW__\xFD[\x84\x01`\x1F\x81\x01\x86\x13a\t\xFEW__\xFD[\x805g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\n\x14W__\xFD[\x86` \x82\x84\x01\x01\x11\x15a\n%W__\xFD[\x93\x96` \x91\x90\x91\x01\x95P\x92\x93PPPV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x16\x81\x14a\nWW__\xFD[PV[____`\x80\x85\x87\x03\x12\x15a\nmW__\xFD[\x845a\nx\x81a\n6V[\x93P` \x85\x015a\n\x88\x81a\n6V[\x92P`@\x85\x015\x91P``\x85\x015a\n\x9F\x81a\n6V[\x93\x96\x92\x95P\x90\x93PPV[___``\x84\x86\x03\x12\x15a\n\xBCW__\xFD[\x835a\n\xC7\x81a\n6V[\x92P` \x84\x015a\n\xD7\x81a\n6V[\x92\x95\x92\x94PPP`@\x91\x90\x91\x015\x90V[_\x82Q_[\x81\x81\x10\x15a\x0B\x07W` \x81\x86\x01\x81\x01Q\x85\x83\x01R\x01a\n\xEDV[P_\x92\x01\x91\x82RP\x91\x90PV[_` \x82\x84\x03\x12\x15a\x0B$W__\xFD[\x81Qa\t\x11\x81a\n6V[_` \x82\x84\x03\x12\x15a\x0B?W__\xFD[PQ\x91\x90PV[\x81\x81\x03\x81\x81\x11\x15a\t7W\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_` \x82\x84\x03\x12\x15a\x0B\x8EW__\xFD[\x81Q\x80\x15\x15\x81\x14a\t\x11W__\xFD\xFE\xA1dsolcC\0\x08\x1E\0\n", ); #[derive(Default, Debug, PartialEq, Eq, Hash)] - /**Function with signature `ensureTradePreconditions(address,address,uint256,address,address)` and selector `0x542eb77d`. + /**Function with signature `ensureTradePreconditions(address,address,uint256,address)` and selector `0x5bbe8b3f`. ```solidity - function ensureTradePreconditions(address settlementContract, address sellToken, uint256 sellAmount, address nativeToken, address spardose) external; + function ensureTradePreconditions(address settlementContract, address sellToken, uint256 sellAmount, address spardose) external; ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] @@ -158,12 +153,10 @@ pub mod Trader { #[allow(missing_docs)] pub sellAmount: alloy_sol_types::private::primitives::aliases::U256, #[allow(missing_docs)] - pub nativeToken: alloy_sol_types::private::Address, - #[allow(missing_docs)] pub spardose: alloy_sol_types::private::Address, } ///Container type for the return parameters of the - /// [`ensureTradePreconditions(address,address,uint256,address, + /// [`ensureTradePreconditions(address,address,uint256, /// address)`](ensureTradePreconditionsCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] @@ -184,7 +177,6 @@ pub mod Trader { alloy_sol_types::sol_data::Address, alloy_sol_types::sol_data::Uint<256>, alloy_sol_types::sol_data::Address, - alloy_sol_types::sol_data::Address, ); #[doc(hidden)] type UnderlyingRustTuple<'a> = ( @@ -192,7 +184,6 @@ pub mod Trader { alloy_sol_types::private::Address, alloy_sol_types::private::primitives::aliases::U256, alloy_sol_types::private::Address, - alloy_sol_types::private::Address, ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] @@ -211,7 +202,6 @@ pub mod Trader { value.settlementContract, value.sellToken, value.sellAmount, - value.nativeToken, value.spardose, ) } @@ -224,8 +214,7 @@ pub mod Trader { settlementContract: tuple.0, sellToken: tuple.1, sellAmount: tuple.2, - nativeToken: tuple.3, - spardose: tuple.4, + spardose: tuple.3, } } } @@ -275,16 +264,15 @@ pub mod Trader { alloy_sol_types::sol_data::Address, alloy_sol_types::sol_data::Uint<256>, alloy_sol_types::sol_data::Address, - alloy_sol_types::sol_data::Address, ); type Return = ensureTradePreconditionsReturn; type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; type ReturnTuple<'a> = (); type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SELECTOR: [u8; 4] = [84u8, 46u8, 183u8, 125u8]; + const SELECTOR: [u8; 4] = [91u8, 190u8, 139u8, 63u8]; const SIGNATURE: &'static str = - "ensureTradePreconditions(address,address,uint256,address,address)"; + "ensureTradePreconditions(address,address,uint256,address)"; #[inline] fn new<'a>( @@ -305,9 +293,6 @@ pub mod Trader { as alloy_sol_types::SolType>::tokenize( &self.sellAmount, ), - ::tokenize( - &self.nativeToken, - ), ::tokenize( &self.spardose, ), @@ -679,7 +664,7 @@ pub mod Trader { /// Prefer using `SolInterface` methods instead. pub const SELECTORS: &'static [[u8; 4usize]] = &[ [22u8, 38u8, 186u8, 126u8], - [84u8, 46u8, 183u8, 125u8], + [91u8, 190u8, 139u8, 63u8], [235u8, 86u8, 37u8, 217u8], ]; /// The signatures in the same order as `SELECTORS`. @@ -1027,14 +1012,12 @@ pub mod Trader { settlementContract: alloy_sol_types::private::Address, sellToken: alloy_sol_types::private::Address, sellAmount: alloy_sol_types::private::primitives::aliases::U256, - nativeToken: alloy_sol_types::private::Address, spardose: alloy_sol_types::private::Address, ) -> alloy_contract::SolCallBuilder<&P, ensureTradePreconditionsCall, N> { self.call_builder(&ensureTradePreconditionsCall { settlementContract, sellToken, sellAmount, - nativeToken, spardose, }) } diff --git a/contracts/solidity/Solver.sol b/contracts/solidity/Solver.sol index b141f28653..0698e0a47d 100644 --- a/contracts/solidity/Solver.sol +++ b/contracts/solidity/Solver.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.30; -import { IERC20, INativeERC20 } from "./interfaces/IERC20.sol"; +import { IERC20 } from "./interfaces/IERC20.sol"; import { Interaction, Trade, ISettlement } from "./interfaces/ISettlement.sol"; import { Caller } from "./libraries/Caller.sol"; import { Math } from "./libraries/Math.sol"; @@ -117,7 +117,6 @@ contract Solver layout at 0x14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff1 ISettlement settlementContract, address sellToken, uint256 sellAmount, - address nativeToken, address spardose ) external { uint256 gasStart = gasleft(); @@ -125,7 +124,6 @@ contract Solver layout at 0x14f5b2c185fc03c75c787d1f0e10ea137cc6d235a0047448eff1 settlementContract, sellToken, sellAmount, - nativeToken, spardose ); // Account for costs of gas used outside of metered section. diff --git a/contracts/solidity/Trader.sol b/contracts/solidity/Trader.sol index f73e805ec9..be5dcdc158 100644 --- a/contracts/solidity/Trader.sol +++ b/contracts/solidity/Trader.sol @@ -55,34 +55,15 @@ contract Trader layout at 0x02565dba7d68dcbed629110024b7b5e785bfc1a484602045eea5 /// a stable address in tests. /// @param sellToken - token being sold by the trade /// @param sellAmount - expected amount to be sold according to the quote - /// @param nativeToken - ERC20 version of the chain's native token /// @param spardose - piggy bank for requesting additional funds function ensureTradePreconditions( ISettlement settlementContract, address sellToken, uint256 sellAmount, - address nativeToken, address spardose ) external { require(!triggerInitialization(), "prepareSwap can only be called once"); - if (sellToken == nativeToken) { - uint256 availableNativeToken = IERC20(sellToken).balanceOf(address(this)); - if (availableNativeToken < sellAmount) { - uint256 amountToWrap = sellAmount - availableNativeToken; - // If the user has sufficient balance, simulate the wrapping the missing - // `ETH` so the user doesn't have to spend gas on that just to get a quote. - // If they are happy with the quote and want to create an order they will - // actually have to do the wrapping, though. Note that we don't attempt to - // wrap if the user doesn't have sufficient `ETH` balance, since that would - // revert. Instead, we fall-through so that we handle insufficient sell - // token balances uniformly for all tokens. - if (address(this).balance >= amountToWrap) { - INativeERC20(nativeToken).deposit{value: amountToWrap}(); - } - } - } - address vaultRelayer = settlementContract.vaultRelayer(); uint256 currentAllowance = IERC20(sellToken).allowance(address(this), vaultRelayer); if (currentAllowance < sellAmount) { diff --git a/crates/e2e/tests/e2e/order_simulation.rs b/crates/e2e/tests/e2e/order_simulation.rs index e7c63dc762..1217ed2d69 100644 --- a/crates/e2e/tests/e2e/order_simulation.rs +++ b/crates/e2e/tests/e2e/order_simulation.rs @@ -1,10 +1,19 @@ use { - alloy::{primitives::Address, providers::Provider}, + alloy::{ + primitives::{Address, ruint::aliases::U256}, + providers::Provider, + }, configs::test_util::TestDefault, e2e::setup::{API_HOST, OnchainComponents, Services, TIMEOUT, run_test, wait_for_condition}, ethrpc::{Web3, alloy::CallBuilderExt}, model::{ - order::{OrderCreation, OrderKind}, + order::{ + BuyTokenDestination, + OrderCreation, + OrderCreationAppData, + OrderKind, + SellTokenSource, + }, signature::EcdsaSigningScheme, }, number::units::EthUnit, @@ -50,15 +59,53 @@ async fn custom_order_simulation(web3: Web3) { .await; let client = services.client(); + let valid_to = model::time::now_in_epoch_seconds() + 100; + let sell_amount = 1u64.eth(); - let request = orderbook::dto::OrderSimulationRequest { + let app_data = "{}"; + + // Sign an OrderCreation with the same fields the simulation will encode. + // simulate_custom_order hashes `app_data` with keccak256; OrderCreation::Full + // does the same, so the signature covers exactly the same OrderData hash. + let signed = OrderCreation { sell_token: *token.address(), buy_token: *onchain.contracts().weth.address(), - sell_amount: sell_amount.try_into().expect("Sell amount is non zero"), + sell_amount, buy_amount: 1u64.eth(), kind: OrderKind::Sell, - owner: trader.address(), + receiver: Some(Address::default()), + sell_token_balance: SellTokenSource::Erc20, + buy_token_balance: BuyTokenDestination::Erc20, + fee_amount: U256::ZERO, + valid_to, + app_data: OrderCreationAppData::Full { + full: app_data.to_string(), + }, + partially_fillable: false, ..Default::default() + } + .sign( + EcdsaSigningScheme::Eip712, + &onchain.contracts().domain_separator, + &trader.signer, + ); + + let request = orderbook::dto::OrderSimulationRequest { + sell_token: signed.sell_token, + buy_token: signed.buy_token, + sell_amount: signed.sell_amount.try_into().unwrap(), + buy_amount: signed.buy_amount, + kind: signed.kind, + owner: trader.address(), + receiver: signed.receiver, + sell_token_balance: signed.sell_token_balance, + buy_token_balance: signed.buy_token_balance, + app_data: app_data.to_string(), + block_number: None, + signature: signed.signature, + fee_amount: signed.fee_amount, + valid_to: signed.valid_to, + partially_fillable: signed.partially_fillable, }; // Trader has no sell tokens — simulation should revert. diff --git a/crates/e2e/tests/e2e/quote_verification.rs b/crates/e2e/tests/e2e/quote_verification.rs index a7561b96ad..89eaf9f071 100644 --- a/crates/e2e/tests/e2e/quote_verification.rs +++ b/crates/e2e/tests/e2e/quote_verification.rs @@ -12,7 +12,7 @@ use { price_estimation::BalanceOverridesConfig, test_util::TestDefault, }, - contracts::ERC20, + contracts::{ERC20, GPv2Settlement}, e2e::setup::*, ethrpc::{Web3, alloy::CallBuilderExt}, model::{ @@ -28,7 +28,7 @@ use { trade_verifier::{PriceQuery, TradeVerifier, TradeVerifying}, }, serde_json::json, - simulator::swap_simulator::SwapSimulator, + simulator::simulation_builder::SettlementSimulator, std::{collections::HashMap, sync::Arc}, }; @@ -189,32 +189,33 @@ async fn test_bypass_verification_for_rfq_quotes(web3: Web3) { .unwrap(); let onchain = OnchainComponents::deployed(web3.clone()).await; let balance_overrides = Arc::new(BalanceOverrides::default()); - let gas_limit = 12_000_000; - let simulator = SwapSimulator::new( - balance_overrides.clone(), + let gas_limit = 12_000_000u64; + let settlement_contract = GPv2Settlement::GPv2Settlement::new( *onchain.contracts().gp_settlement.address(), + web3.provider.clone(), + ); + let simulator = SettlementSimulator::new( + settlement_contract, + Default::default(), + Default::default(), *onchain.contracts().weth.address(), - block_stream.clone(), - web3.clone(), gas_limit, + balance_overrides, + block_stream.clone(), + None, ) .await .unwrap(); let verifier = TradeVerifier::new( - web3.clone(), - None, simulator, + None, Arc::new(web3.clone()), - balance_overrides, - *onchain.contracts().gp_settlement.address(), BigDecimal::zero(), Default::default(), 0, u32::MAX, - ) - .await - .unwrap(); + ); let verify_trade = |tx_origin| { let verifier = verifier.clone(); diff --git a/crates/orderbook/openapi.yml b/crates/orderbook/openapi.yml index b2191161ea..aa4d136b22 100644 --- a/crates/orderbook/openapi.yml +++ b/crates/orderbook/openapi.yml @@ -2731,24 +2731,37 @@ components: if omitted. allOf: - $ref: "#/components/schemas/Address" - nullable: true sellTokenBalance: description: Where the sell token should be drawn from. allOf: - $ref: "#/components/schemas/SellTokenSource" - default: erc20 buyTokenBalance: description: Where the buy token should be transferred to. allOf: - $ref: "#/components/schemas/BuyTokenDestination" - default: erc20 appData: description: > - Full app data JSON string. Defaults to `"{}"` if omitted. + Full app data JSON string. type: string - nullable: true blockNumber: type: integer + nullable: true + signingScheme: + $ref: "#/components/schemas/SigningScheme" + signature: + $ref: "#/components/schemas/Signature" + feeAmount: + description: > + The fee amount in sell token atoms. Expected to be 0; only present + because it must be part of the signed order data. + allOf: + - $ref: "#/components/schemas/TokenAmount" + validTo: + description: Unix timestamp (`uint32`) until which the order is valid. + type: integer + partiallyFillable: + description: Whether the order can be partially filled or must be filled all at once. + type: boolean required: - sellToken - buyToken @@ -2756,6 +2769,8 @@ components: - buyAmount - kind - owner + - signingScheme + - signature OrderSimulation: description: > The Tenderly simulation request for an order, along with any diff --git a/crates/orderbook/src/dto/mod.rs b/crates/orderbook/src/dto/mod.rs index 75b868d17f..cb5cf0b26a 100644 --- a/crates/orderbook/src/dto/mod.rs +++ b/crates/orderbook/src/dto/mod.rs @@ -4,7 +4,10 @@ pub mod order; use { alloy::primitives::U256, eth_domain_types::{Address, NonZeroU256}, - model::order::{BuyTokenDestination, OrderKind, SellTokenSource}, + model::{ + order::{BuyTokenDestination, OrderKind, SellTokenSource}, + signature::Signature, + }, number::serialization::HexOrDecimalU256, serde::{Deserialize, Serialize}, serde_with::serde_as, @@ -45,12 +48,22 @@ pub struct OrderSimulationRequest { /// token transfer or internal Balancer Vault transfer. #[serde(default)] pub buy_token_balance: BuyTokenDestination, - /// Full app data JSON. Defaults to `"{}"` if omitted. - #[serde(default)] - pub app_data: Option, + /// Full app data JSON. + pub app_data: String, /// The block number at which the simulation should happen - #[serde(default)] pub block_number: Option, + /// The order signature (signing scheme + bytes). Required to pass + /// signature verification in the settlement contract during simulation. + #[serde(flatten)] + pub signature: Signature, + /// The fee amount signed by the user. This field is expected to be 0 and + /// only still there because it needs to be signed by the user. + pub fee_amount: U256, + /// UNIX timestamp when the order will expire. + pub valid_to: u32, + /// Whether the order needs to be filled all at once or allows to be filled + /// over multiple partial executions. + pub partially_fillable: bool, } /// The result of Order simulation, contains the error (if any) diff --git a/crates/orderbook/src/lib.rs b/crates/orderbook/src/lib.rs index c5c92d4a6a..2b380334fa 100644 --- a/crates/orderbook/src/lib.rs +++ b/crates/orderbook/src/lib.rs @@ -5,7 +5,6 @@ pub mod database; pub mod dto; mod ipfs; mod ipfs_app_data; -pub mod order_simulator; pub mod orderbook; mod quoter; pub mod run; diff --git a/crates/orderbook/src/order_simulator.rs b/crates/orderbook/src/order_simulator.rs deleted file mode 100644 index b6a604732b..0000000000 --- a/crates/orderbook/src/order_simulator.rs +++ /dev/null @@ -1,299 +0,0 @@ -use { - crate::dto::OrderSimulationResult, - alloy::{ - eips::BlockId, - primitives::{Address, Bytes, U256}, - rpc::types::state::AccountOverride, - }, - anyhow::{Context, Result, anyhow}, - app_data::WrapperCall, - balance_overrides::BalanceOverrideRequest, - contracts::support::{AnyoneAuthenticator, Trader}, - eth_domain_types::{BlockNo, NonZeroU256}, - model::order::Order, - shared::remaining_amounts, - simulator::{ - encoding::InteractionEncoding, - swap_simulator::{EncodedSwap, Query, SwapSimulator, TradeEncoding}, - tenderly, - }, - thiserror::Error, -}; -pub struct OrderSimulator { - simulator: SwapSimulator, - tenderly: Option>, - chain_id: String, -} - -#[derive(Error, Debug)] -pub enum Error { - #[error("simulation could not be created")] - Other(anyhow::Error), - #[error("malformed input")] - MalformedInput(anyhow::Error), -} - -impl OrderSimulator { - pub fn new( - simulator: SwapSimulator, - chain_id: String, - tenderly: Option>, - ) -> Self { - Self { - simulator, - tenderly, - chain_id, - } - } - - /// Calculates the remaining sell and buy amounts - /// Returns a tuple of (remaining_sell, remaining_buy) - async fn remaining_amounts( - &self, - order: &Order, - block: Option, - ) -> Result<(U256, U256), Error> { - let mut filled_amount_call = self - .simulator - .settlement - .filledAmount(Bytes::from(order.metadata.uid.0)); - - if let Some(block) = block { - filled_amount_call = filled_amount_call.block(block); - } - let executed_amount = filled_amount_call - .call() - .await - .map_err(|err| Error::Other(anyhow!(err)))?; - - let remaining_order = remaining_amounts::Order { - kind: order.data.kind, - buy_amount: order.data.buy_amount, - sell_amount: order.data.sell_amount, - fee_amount: order.data.fee_amount, - executed_amount, - partially_fillable: order.data.partially_fillable, - }; - let remaining = remaining_amounts::Remaining::from_order(&remaining_order) - .with_context(|| { - format!( - "could not compute remaining amounts for order {}", - order.metadata.uid - ) - }) - .map_err(Error::Other)?; - let remaining_sell = remaining - .remaining(order.data.sell_amount) - .context("overflow computing remaining sell amount") - .map_err(Error::Other)?; - let remaining_buy = remaining - .remaining(order.data.buy_amount) - .context("overflow computing remaining buy amount") - .map_err(Error::Other)?; - - Ok((remaining_sell, remaining_buy)) - } - - /// Encodes an order for simulation. - /// - /// `executed_amount` overrides how much of the order has already been - /// filled (in the order's fill token: sell token for sell orders, buy - /// token for buy orders). When `None`, the executed amount is taken from - /// the order's metadata, which reflects the actual on-chain fill state. - pub async fn encode_order( - &self, - order: &Order, - wrappers: Vec, - block: Option, - ) -> Result { - let tokens = vec![order.data.sell_token, order.data.buy_token]; - // Clearing prices represent the limit price of the order; both order kinds - // produce the same ratio: [buy_amount, sell_amount] for [sell_token, - // buy_token]. - let clearing_prices = vec![order.data.buy_amount, order.data.sell_amount]; - let solver = Address::random(); - let (remaining_sell, remaining_buy) = - self.remaining_amounts(order, block.map(Into::into)).await?; - let query = Query { - sell_amount: NonZeroU256::try_from(remaining_sell).map_err(|err| { - Error::MalformedInput(anyhow!("sell_amount `{}`: {err}", remaining_sell)) - })?, - sell_token: order.data.sell_token, - buy_amount: remaining_buy, - buy_token: order.data.buy_token, - kind: order.data.kind, - receiver: order.data.receiver.unwrap_or(order.metadata.owner), - sell_token_source: order.data.sell_token_balance, - buy_token_destination: order.data.buy_token_balance, - from: order.metadata.owner, - tx_origin: None, - clearing_prices, - solver, - tokens, - wrappers: wrappers - .iter() - .map(|wrapper| simulator::encoding::WrapperCall { - address: wrapper.address, - data: wrapper.data.clone().into(), - }) - .collect(), - }; - - let swap = self - .simulator - .fake_swap(&query, TradeEncoding::Simple) - .await - .map_err(Error::Other)?; - let swap = add_interactions(swap, order); - let swap = self.add_state_overrides(&query, swap).await?; - - Ok(swap) - } - - /// Simulates a swap of the provided EncodedSwap. - /// - /// The result contains the transaction simulation error (if any) - /// and a full API request object that can be used to resimulate the swap - /// using Tenderly. - pub async fn simulate_swap( - &self, - swap: EncodedSwap, - block_number: Option, - ) -> Result { - let block_number = - block_number.unwrap_or_else(|| self.simulator.current_block.borrow().number); - let result = self - .simulator - .simulate_settle_call(swap, block_number) - .await - .map_err(Error::Other)?; - - let tenderly_request = simulator::tenderly::dto::Request { - transaction_index: None, - save: Some(true), - save_if_fails: Some(true), - ..simulator::tenderly::prepare_request( - self.chain_id.clone(), - &result.tx, - result.overrides, - BlockNo(block_number), - ) - .map_err(|err| Error::Other(anyhow!(err)))? - }; - - let tenderly_url = match &self.tenderly { - Some(api) => match api.simulate_and_share(tenderly_request.clone()).await { - Ok(url) => Some(url), - Err(err) => { - tracing::warn!(?err, "failed to create Tenderly simulation"); - None - } - }, - None => None, - }; - - Ok(OrderSimulationResult { - tenderly_request, - tenderly_url, - error: result.result.err().map(|err| err.to_string()), - }) - } - - pub async fn add_state_overrides( - &self, - query: &Query, - mut swap: EncodedSwap, - ) -> Result { - // Override authenticator with AnyoneAuthenticator so our fake solver is - // accepted. - let authenticator = self - .simulator - .settlement - .authenticator() - .call() - .await - .context("could not fetch authenticator") - .map_err(Error::Other)?; - swap.overrides.insert( - authenticator, - AccountOverride { - code: Some(AnyoneAuthenticator::AnyoneAuthenticator::DEPLOYED_BYTECODE.clone()), - ..Default::default() - }, - ); - - // Set up fake solver. - swap.overrides.insert( - query.solver, - AccountOverride { - // Allow solver simulations to proceed even if the real account holds no ETH. - // The number is obscenely large, but not max to avoid potential overflows. - // We had this set to eth(1), but some simulations require more than that on non-ETH - // networks e.g. polygon so it led to reverts. - balance: Some(U256::MAX / U256::from(2)), - ..Default::default() - }, - ); - - // Override trader address with Trader bytecode so EIP-1271 signature - // verification works for EOA traders (settlement calls isValidSignature - // on the trader address, which would revert for plain EOAs). - swap.overrides.insert( - query.from, - AccountOverride { - code: Some(Trader::Trader::DEPLOYED_BYTECODE.clone()), - ..Default::default() - }, - ); - - // Fund the settlement contract with enough buy tokens to be paid out. - // Add 1 to account for ceiling division in the settlement contract's - // executedBuyAmount calculation, which can be 1 unit above remaining_buy. - match self - .simulator - .balance_overrides - .state_override(BalanceOverrideRequest { - token: query.buy_token, - holder: *self.simulator.settlement.address(), - amount: query.buy_amount + U256::ONE, - }) - .await - { - Some((token, balance_override)) => { - swap.overrides.insert(token, balance_override); - } - None => { - tracing::warn!("Could not set state balance override for the settlement contract"); - } - }; - - Ok(swap) - } -} - -fn add_interactions(mut swap: EncodedSwap, order: &Order) -> EncodedSwap { - // Add order pre interactions before encoded swap's pre interactions - let pre_interactions = order - .interactions - .pre - .iter() - .map(InteractionEncoding::encode) - .collect(); - // Prepend order pre_interactions so they run first - let settlement_pre_interactions = - std::mem::replace(&mut swap.settlement.interactions.pre, pre_interactions); - swap.settlement - .interactions - .pre - .extend(settlement_pre_interactions); - - // Add order post interactions after encoded swap's post interactions - let post_interactions = order - .interactions - .post - .iter() - .map(InteractionEncoding::encode); - swap.settlement.interactions.post.extend(post_interactions); - - swap -} diff --git a/crates/orderbook/src/orderbook.rs b/crates/orderbook/src/orderbook.rs index 2058f8a91c..16e6a1802a 100644 --- a/crates/orderbook/src/orderbook.rs +++ b/crates/orderbook/src/orderbook.rs @@ -5,25 +5,22 @@ use { trades::{TradeFilter, TradeRetrieving}, }, dto::{self, OrderSimulationRequest, OrderSimulationResult}, - order_simulator::{self, OrderSimulator}, solver_competition::{Identifier, LoadSolverCompetitionError, SolverCompetitionStoring}, }, - alloy::primitives::{Address, B256}, + alloy::primitives::{Address, B256, keccak256}, anyhow::{Context, Result, anyhow}, - app_data::{AppDataHash, Validator, WrapperCall}, + app_data::{AppDataHash, Validator}, bigdecimal::ToPrimitive, chrono::Utc, database::order_events::OrderEventLabel, model::{ DomainSeparator, order::{ - Interactions, Order, OrderCancellation, OrderCreation, OrderCreationAppData, OrderData, - OrderMetadata, OrderStatus, OrderUid, SignedOrderCancellations, @@ -42,6 +39,7 @@ use { is_order_outside_market_price, }, }, + simulator::simulation_builder::{self, SettlementSimulator}, std::{borrow::Cow, sync::Arc}, strum::Display, thiserror::Error, @@ -239,7 +237,7 @@ pub struct Orderbook { order_validator: Arc, app_data: Arc, active_order_competition_threshold: u32, - order_simulator: Option>, + order_simulator: Option, } impl Orderbook { @@ -252,7 +250,7 @@ impl Orderbook { order_validator: Arc, app_data: Arc, active_order_competition_threshold: u32, - order_simulator: Option>, + order_simulator: Option, ) -> Self { Metrics::initialize(); Self { @@ -613,26 +611,6 @@ impl Orderbook { Ok(status) } - fn parse_interactions_and_wrappers( - &self, - full_app_data: &str, - ) -> Result<(Interactions, Vec)> { - if !full_app_data.is_empty() { - let app_data = self - .order_validator - .validate_app_data( - &OrderCreationAppData::Full { - full: full_app_data.to_string(), - }, - &None, - ) - .map_err(|err| anyhow::anyhow!("{:?}", err))?; - Ok((app_data.interactions, app_data.inner.protocol.wrappers)) - } else { - Ok((Interactions::default(), Vec::default())) - } - } - /// Simulates an order based on its Uid using the OrderSimulator. /// /// The returned value contains the simulation result and tenderly API @@ -653,18 +631,43 @@ impl Orderbook { return Ok(None); }; - let (_, wrappers) = self - .parse_interactions_and_wrappers( - order.metadata.full_app_data.as_deref().unwrap_or_default(), + let full_app_data = order + .metadata + .full_app_data + .clone() + .ok_or_else(|| OrderSimulationError::Other(anyhow!("can't find appdata")))?; + + let sim = order_simulator + .new_simulation_builder() + .add_orders([simulation_builder::Order::new(order.data) + .with_signature(order.metadata.owner, order.signature) + .fill_at( + simulation_builder::ExecutionAmount::Remaining, + simulation_builder::PriceEncoding::LimitPrice, + )]) + .parameters_from_app_data(&full_app_data) + .context("failed to parse app data")? + .at_block( + block_number + .map(simulation_builder::Block::Number) + .unwrap_or(simulation_builder::Block::Latest), ) - .map_err(OrderSimulationError::Other)?; + .with_overrides([simulation_builder::AccountOverrideRequest::BuyTokensForBuffers]) + .from_solver(simulation_builder::Solver::Fake(None)) + .build() + .await + .context("failed to finalize simulation")?; - let swap = order_simulator - .encode_order(&order, wrappers, block_number) - .await?; - Ok(Some( - order_simulator.simulate_swap(swap, block_number).await?, - )) + let simulation_result = sim + .simulate_with_tenderly_report() + .await + .context("failed to execute simulation")?; + + Ok(Some(OrderSimulationResult { + tenderly_url: simulation_result.tenderly_url, + tenderly_request: simulation_result.tenderly_request, + error: simulation_result.error, + })) } /// Simulates an arbitrary order without requiring it to exist in the @@ -676,19 +679,11 @@ impl Orderbook { let Some(order_simulator) = &self.order_simulator else { return Err(OrderSimulationError::NotEnabled); }; - let full_app_data = request.app_data.unwrap_or_default(); - let (interactions, wrappers) = self - .parse_interactions_and_wrappers(&full_app_data) - .map_err(|err| { - OrderSimulationError::MalformedInput(anyhow!("app_data `{}`: {err}", full_app_data)) - })?; - let order = Order { - metadata: OrderMetadata { - owner: request.owner, - full_app_data: Some(full_app_data), - ..Default::default() - }, - data: OrderData { + let app_data_hash = keccak256(&request.app_data); + + let sim = order_simulator + .new_simulation_builder() + .add_orders([simulation_builder::Order::new(OrderData { sell_token: request.sell_token, buy_token: request.buy_token, sell_amount: request.sell_amount.into(), @@ -697,24 +692,42 @@ impl Orderbook { receiver: request.receiver, sell_token_balance: request.sell_token_balance, buy_token_balance: request.buy_token_balance, - ..Default::default() - }, - interactions, - ..Default::default() - }; + fee_amount: request.fee_amount, + valid_to: request.valid_to, + app_data: AppDataHash(app_data_hash.into()), + partially_fillable: request.partially_fillable, + }) + .with_signature(request.owner, request.signature) + .fill_at( + simulation_builder::ExecutionAmount::Full, + simulation_builder::PriceEncoding::LimitPrice, + )]) + .parameters_from_app_data(&request.app_data) + .context("failed to parse app data")? + .at_block( + request + .block_number + .map(simulation_builder::Block::Number) + .unwrap_or(simulation_builder::Block::Latest), + ) + .with_overrides([simulation_builder::AccountOverrideRequest::BuyTokensForBuffers]) + .from_solver(simulation_builder::Solver::Fake(None)) + .build() + .await + .context("failed to finalize simulation") + .map_err(OrderSimulationError::Other)?; - let swap = order_simulator - .encode_order(&order, wrappers, request.block_number) + let simulation_result = sim + .simulate_with_tenderly_report() .await - .map_err(|err| match err { - order_simulator::Error::Other(err) => OrderSimulationError::Other(err), - order_simulator::Error::MalformedInput(err) => { - OrderSimulationError::MalformedInput(err) - } - })?; - Ok(order_simulator - .simulate_swap(swap, request.block_number) - .await?) + .context("failed to execute simulation") + .map_err(OrderSimulationError::Other)?; + + Ok(OrderSimulationResult { + tenderly_url: simulation_result.tenderly_url, + tenderly_request: simulation_result.tenderly_request, + error: simulation_result.error, + }) } } @@ -740,20 +753,11 @@ pub enum OrderSimulationError { #[error("order simulation is not enabled")] NotEnabled, #[error("malformed input")] - MalformedInput(anyhow::Error), + MalformedInput(#[from] anyhow::Error), #[error("simulation could not be created for order")] Other(anyhow::Error), } -impl From for OrderSimulationError { - fn from(value: order_simulator::Error) -> Self { - match value { - order_simulator::Error::Other(err) => Self::Other(err), - order_simulator::Error::MalformedInput(err) => Self::MalformedInput(err), - } - } -} - #[async_trait::async_trait] impl LivenessChecking for Orderbook { async fn is_alive(&self) -> bool { diff --git a/crates/orderbook/src/run.rs b/crates/orderbook/src/run.rs index 912680642c..70c1797bb5 100644 --- a/crates/orderbook/src/run.rs +++ b/crates/orderbook/src/run.rs @@ -5,7 +5,6 @@ use { database::Postgres, ipfs::Ipfs, ipfs_app_data::IpfsAppData, - order_simulator::OrderSimulator, orderbook::Orderbook, quoter::QuoteHandler, }, @@ -43,7 +42,6 @@ use { order_quoting::{self, OrderQuoter}, order_validation::{OrderValidPeriodConfiguration, OrderValidator}, }, - simulator::swap_simulator::SwapSimulator, std::{future::Future, net::SocketAddr, sync::Arc, time::Duration}, token_info::{CachedTokenInfoFetcher, TokenInfoFetcher}, tokio::task::{self, JoinHandle}, @@ -171,6 +169,7 @@ pub async fn run(config: Configuration) { .await .expect("load hooks trampoline contract"), }; + let hooks_trampoline_address = *hooks_contract.address(); verify_deployed_contract_constants(&settlement_contract, chain_id) .await @@ -412,31 +411,28 @@ pub async fn run(config: Configuration) { )); let order_simulator = if let Some(config) = config.order_simulation { - let tenderly: Option> = + let tenderly: Option> = config.tenderly.as_ref().map(|tenderly_config| { - Box::new(simulator::tenderly::TenderlyApi::new( + Arc::new(simulator::tenderly::TenderlyApi::new( tenderly_config, &http_factory, chain.id().to_string(), )) as _ }); - Some(Arc::new(OrderSimulator::new( - SwapSimulator::new( - balance_overrider.clone(), - *settlement_contract.address(), + Some( + simulator::simulation_builder::SettlementSimulator::new( + settlement_contract.clone(), + Default::default(), + hooks_trampoline_address, *native_token.address(), + config.gas_limit.saturating_to(), + balance_overrider.clone(), current_block_stream.clone(), - web3, - config - .gas_limit - .try_into() - .expect("gas_limit must fit in u64"), + tenderly, ) .await - .expect("failed to create SwapSimulator"), - chain.id().to_string(), - tenderly, - ))) + .unwrap(), + ) } else { None }; diff --git a/crates/price-estimation/src/factory.rs b/crates/price-estimation/src/factory.rs index 6dc1e9c971..05c90731e7 100644 --- a/crates/price-estimation/src/factory.rs +++ b/crates/price-estimation/src/factory.rs @@ -21,14 +21,14 @@ use { anyhow::{Context as _, Result}, bad_tokens::list_based::DenyListedTokens, configs::price_estimation::PriceEstimation, - contracts::WETH9, + contracts::{GPv2Settlement, WETH9}, ethrpc::{Web3, alloy::ProviderLabelingExt, block_stream::CurrentBlockWatcher}, gas_price_estimation::GasPriceEstimating, http_client::HttpClientFactory, number::nonzero::NonZeroU256, rate_limit::RateLimiter, reqwest::Url, - simulator::{swap_simulator::SwapSimulator, tenderly}, + simulator::{simulation_builder::SettlementSimulator, tenderly}, std::{collections::HashMap, num::NonZeroUsize, sync::Arc}, token_info::TokenInfoFetching, }; @@ -106,29 +106,29 @@ impl<'a> PriceEstimatorFactory<'a> { network.chain.id().to_string(), )) as Arc }); - let simulator = SwapSimulator::new( - balance_overrides.clone(), - network.settlement, + let settlement_contract = + GPv2Settlement::GPv2Settlement::new(network.settlement, web3.provider.clone()); + let simulator = SettlementSimulator::new( + settlement_contract, + Default::default(), + Default::default(), network.native_token, - network.block_stream.clone(), - web3.clone(), args.max_gas_per_tx, + balance_overrides, + network.block_stream.clone(), + tenderly.clone(), ) .await?; let verifier = TradeVerifier::new( - web3, - tenderly, simulator, + tenderly, components.code_fetcher.clone(), - balance_overrides, - network.settlement, args.quote_inaccuracy_limit.clone(), args.tokens_without_verification.iter().cloned().collect(), args.min_gas_amount_for_unverified_quotes, args.max_gas_amount_for_unverified_quotes, - ) - .await?; + ); Ok(Some(Arc::new(verifier))) } diff --git a/crates/price-estimation/src/trade_verifier/mod.rs b/crates/price-estimation/src/trade_verifier/mod.rs index 2bca6404e5..ea4274328e 100644 --- a/crates/price-estimation/src/trade_verifier/mod.rs +++ b/crates/price-estimation/src/trade_verifier/mod.rs @@ -2,7 +2,6 @@ use { super::{Estimate, Verification}, crate::{ trade_finding::{ - Interaction, QuoteExecution, TradeKind, external::dto::{self, Side}, @@ -11,21 +10,17 @@ use { trade_verifier::code_fetching::CodeFetching, }, ::alloy::sol_types::SolCall, - alloy::{ - primitives::{Address, U256, address, aliases::I512, map::AddressMap}, - rpc::types::{eth::state::StateOverride, state::AccountOverride}, - }, + alloy::primitives::{Address, Bytes, U256, address, aliases::I512}, anyhow::{Context, Result}, - balance_overrides::{BalanceOverrideRequest, BalanceOverriding}, bigdecimal::BigDecimal, contracts::{ - GPv2Settlement, - support::{AnyoneAuthenticator, Solver, Spardose, Trader}, + WETH9, + support::{Solver, Spardose, Trader}, }, - ethrpc::Web3, model::{ DomainSeparator, - order::{OrderData, OrderKind}, + interaction::InteractionData, + order::{BUY_ETH_ADDRESS, OrderData, OrderKind}, signature::{Signature, SigningScheme}, }, num::BigRational, @@ -39,9 +34,15 @@ use { nonzero::NonZeroU256, }, simulator::{ - encoding::{EncodedTrade, InteractionEncoding, encode_trade}, - swap_simulator::{EncodedSwap, SwapSimulator, TradeEncoding}, - tenderly::{self}, + simulation_builder::{ + self as sim_builder, + AccountOverrideRequest, + ExecutionAmount, + PriceEncoding, + SettlementSimulator, + Solver as SimulationSolver, + }, + tenderly, }, std::{ collections::{HashMap, HashSet}, @@ -69,10 +70,8 @@ pub trait TradeVerifying: Send + Sync + 'static { #[derive(Clone)] pub struct TradeVerifier { tenderly: Option>, - simulator: SwapSimulator, + simulator: SettlementSimulator, code_fetcher: Arc, - balance_overrides: Arc, - settlement: GPv2Settlement::Instance, quote_inaccuracy_limit: BigRational, tokens_without_verification: HashSet
, min_gas_amount_for_unverified_quotes: u32, @@ -83,37 +82,29 @@ impl TradeVerifier { const SPARDOSE: Address = address!("0000000000000000000000000000000000020000"); const TRADER_IMPL: Address = address!("0000000000000000000000000000000000010000"); - #[expect(clippy::too_many_arguments)] - pub async fn new( - web3: Web3, + pub fn new( + simulator: SettlementSimulator, tenderly: Option>, - simulator: SwapSimulator, code_fetcher: Arc, - balance_overrides: Arc, - settlement: Address, quote_inaccuracy_limit: BigDecimal, tokens_without_verification: HashSet
, min_gas_amount_for_unverified_quotes: u32, max_gas_amount_for_unverified_quotes: u32, - ) -> Result { + ) -> Self { assert!( min_gas_amount_for_unverified_quotes <= max_gas_amount_for_unverified_quotes, "gas floor ({min_gas_amount_for_unverified_quotes}) exceeds gas ceiling \ ({max_gas_amount_for_unverified_quotes}) for unverified quotes" ); - let settlement_contract = - GPv2Settlement::GPv2Settlement::new(settlement, web3.provider.clone()); - Ok(Self { + Self { tenderly, simulator, code_fetcher, - balance_overrides, - settlement: settlement_contract, quote_inaccuracy_limit: big_decimal_to_big_rational("e_inaccuracy_limit), tokens_without_verification, min_gas_amount_for_unverified_quotes, max_gas_amount_for_unverified_quotes, - }) + } } async fn verify_inner( @@ -124,28 +115,46 @@ impl TradeVerifier { out_amount: &U256, ) -> Result { let start = std::time::Instant::now(); - let overrides = self - .prepare_state_overrides(&mut verification, query, trade) + + if verification.from.is_zero() { + verification.from = Address::random(); + tracing::debug!( + trader = ?verification.from, + "use random trader address with fake balances" + ); + } + + let override_requests = self + .prepare_state_overrides(&verification, query, trade) .await?; // Use `tx_origin` if response indicates that a special address is needed for // the simulation to pass. Otherwise just use the solver address. let solver_address = trade.tx_origin().unwrap_or(trade.solver()); - let (tokens, clearing_prices) = match trade { - TradeKind::Legacy(_) => { - let tokens = vec![query.sell_token, query.buy_token]; - let prices = match query.kind { - OrderKind::Sell => { - vec![*out_amount, query.in_amount.get()] - } - OrderKind::Buy => { - vec![query.in_amount.get(), *out_amount] - } - }; - (tokens, prices) - } - TradeKind::Regular(trade) => trade.clearing_prices.iter().unzip(), + // `tokens` is passed to `Solver::swap` so it can measure balance changes; + // it is independent of the settlement's token/price vectors. + let tokens: Vec
= match trade { + TradeKind::Legacy(_) => vec![query.sell_token, query.buy_token], + TradeKind::Regular(trade) => trade.clearing_prices.keys().copied().collect(), + }; + let (fake_sell_price, fake_buy_price) = match trade { + TradeKind::Legacy(_) => match query.kind { + OrderKind::Sell => (*out_amount, query.in_amount.get()), + OrderKind::Buy => (query.in_amount.get(), *out_amount), + }, + TradeKind::Regular(trade) => ( + trade + .clearing_prices + .get(&query.sell_token) + .copied() + .unwrap_or(U256::ONE), + trade + .clearing_prices + .get(&query.buy_token) + .copied() + .unwrap_or(U256::ONE), + ), }; let (sell_amount, buy_amount) = match query.kind { @@ -155,92 +164,185 @@ impl TradeVerifier { query.in_amount.get(), ), }; - let simulator_query = simulator::swap_simulator::Query { - sell_token: query.sell_token, - buy_token: query.buy_token, - kind: query.kind, - sell_amount, - buy_amount, - receiver: verification.receiver, - sell_token_source: verification.sell_token_source, - buy_token_destination: verification.buy_token_destination, - from: verification.from, - tx_origin: trade.tx_origin(), - solver: solver_address, - tokens: tokens.clone(), - clearing_prices, - wrappers: Default::default(), + // Determine effective receiver (zero means owner receives) + let effective_receiver = if verification.receiver.is_zero() { + verification.from + } else { + verification.receiver }; - let mut swap = self - .simulator - .fake_swap(&simulator_query, TradeEncoding::Disadvantageous) - .await - .map_err(Error::SimulationFailed)?; + // storeBalance interactions bracket the settlement to measure the actual + // out_amount + let (tracked_token, tracked_owner) = match query.kind { + OrderKind::Sell => (query.buy_token, effective_receiver), + OrderKind::Buy => (query.sell_token, verification.from), + }; + let store_balance = InteractionData { + target: solver_address, + value: U256::ZERO, + call_data: Solver::Solver::storeBalanceCall { + token: tracked_token, + owner: tracked_owner, + countGas: true, + } + .abi_encode(), + }; - swap.overrides.extend(overrides); + // WETH unwrap so ETH buy orders can pay out native tokens + let weth_unwrap = (query.buy_token == BUY_ETH_ADDRESS).then(|| InteractionData { + target: self.simulator.native_token(), + value: U256::ZERO, + call_data: WETH9::WETH9::withdrawCall { wad: buy_amount }.abi_encode(), + }); - let mut pre_interactions = verification + // pre: [verification.pre, trade.pre, trade_setup, storeBalance_before] + let pre_interactions: Vec = map_interactions_data( + verification .pre_interactions .iter() - // pre_interactions introduced by the solver - .chain(trade.pre_interactions()) - .map(InteractionEncoding::encode) - .collect::>(); - - // Join custom pre_interactions in the following order: - // pre_interactions, trade setup interaction, encoded swap pre interactions - pre_interactions.extend([self - .trade_setup_interaction(out_amount, &verification, query, trade) - .encode()]); - pre_interactions.extend(swap.settlement.interactions.pre); - swap.settlement.interactions.pre = pre_interactions; - - // Join interactions introduced by the solver, set up in the following order: - // trade interactions, encoded swap interactions - let interactions = trade.interactions().map(InteractionEncoding::encode); - swap.settlement.interactions.main = interactions + .chain(trade.pre_interactions()), + ) + .into_iter() + .chain([self.trade_setup_interaction(out_amount, &verification, query, trade)]) + .chain([store_balance.clone()]) + .collect(); + + // main: [trade.main, weth_unwrap] + let main_interactions: Vec = map_interactions_data(trade.interactions()) .into_iter() - .chain(swap.settlement.interactions.main) + .chain(weth_unwrap) .collect(); - // Join post interactions in the following order: - // encoded swap post interactions, verification post interactions, - let post_interactions = verification - .post_interactions - .iter() - .map(InteractionEncoding::encode); - swap.settlement.interactions.post = swap - .settlement - .interactions - .post - .into_iter() - .chain(post_interactions) + // post: [storeBalance_after, verification.post] + let post_interactions: Vec = std::iter::once(store_balance) + .chain(map_interactions_data(verification.post_interactions.iter())) .collect(); - add_balance_queries(&mut swap, query, &verification); + // Set limit amounts to always pass the settlement check so the actual + // out_amount can be measured via the storeBalance interactions. + let (fake_sell_amount, fake_buy_amount) = match query.kind { + OrderKind::Sell => (sell_amount.get(), U256::ZERO), + OrderKind::Buy => (sell_amount.get().max(U256::from(u128::MAX)), buy_amount), + }; + let fake_order = sim_builder::Order::new(OrderData { + sell_token: query.sell_token, + sell_amount: fake_sell_amount, + buy_token: query.buy_token, + buy_amount: fake_buy_amount, + receiver: Some(verification.receiver), + valid_to: u32::MAX, + app_data: Default::default(), + fee_amount: U256::ZERO, + kind: query.kind, + partially_fillable: false, + sell_token_balance: verification.sell_token_source, + buy_token_balance: verification.buy_token_destination, + }) + .with_signature( + verification.from, + Signature::default_with(SigningScheme::Eip1271), + ) + .fill_at( + ExecutionAmount::Full, + PriceEncoding::Custom { + sell_price: fake_sell_price, + buy_price: fake_buy_price, + }, + ); - if let TradeKind::Regular(trade) = trade { - swap.settlement.trades.extend(encode_jit_orders( - &trade.jit_orders, - &swap.settlement.tokens, - &self.simulator.domain_separator, - )?); - } - let block = *self.simulator.current_block.borrow(); - let output = self + let jit_orders: Vec = match trade { + TradeKind::Regular(t) => t + .jit_orders + .iter() + .map(|jit_order| { + let order_data = OrderData { + sell_token: jit_order.sell_token, + buy_token: jit_order.buy_token, + receiver: Some(jit_order.receiver), + sell_amount: jit_order.sell_amount, + buy_amount: jit_order.buy_amount, + valid_to: jit_order.valid_to, + app_data: jit_order.app_data, + fee_amount: U256::ZERO, + kind: match &jit_order.side { + Side::Buy => OrderKind::Buy, + Side::Sell => OrderKind::Sell, + }, + partially_fillable: jit_order.partially_fillable, + sell_token_balance: jit_order.sell_token_source, + buy_token_balance: jit_order.buy_token_destination, + }; + let (owner, signature) = recover_jit_order_owner( + jit_order, + &order_data, + &self.simulator.domain_separator(), + )?; + Ok(sim_builder::Order::new(order_data) + .with_signature(owner, signature) + .fill_at( + ExecutionAmount::Explicit(jit_order.executed_amount), + PriceEncoding::LimitPrice, + )) + }) + .collect::>()?, + _ => vec![], + }; + + let eth_call_inputs = self .simulator - .simulate_swap_with_solver(swap, block) - .await?; + .new_simulation_builder() + .add_orders(std::iter::once(fake_order).chain(jit_orders)) + .from_solver(SimulationSolver::OriginUnaltered(solver_address)) + .with_pre_interactions(pre_interactions) + .with_main_interactions(main_interactions) + .with_post_interactions(post_interactions) + .with_overrides(override_requests) + .build() + .await + .map_err(|e| Error::SimulationFailed(anyhow::anyhow!("{e}")))?; + + let settlement_target = eth_call_inputs + .request + .to + .as_ref() + .and_then(|t| t.to()) + .copied() + .expect("settlement target is always set"); + let calldata: Bytes = eth_call_inputs + .request + .input + .input + .clone() + .unwrap_or_default(); + + let solver_contract = Solver::Instance::new(solver_address, self.simulator.provider()); + let swap_call = solver_contract + .swap( + settlement_target, + tokens.clone(), + effective_receiver, + calldata, + ) + .from(solver_address) + .gas(self.simulator.max_gas_limit()); + + let tx = swap_call.clone().into_transaction_request(); + let result = swap_call + .call() + .overrides(eth_call_inputs.state_overrides.clone()) + .block(eth_call_inputs.block.into()) + .await; if let Some(tenderly) = &self.tenderly - && let Err(err) = - tenderly.log_simulation_command(output.tx, output.overrides, block.number.into()) + && let Err(err) = tenderly.log_simulation_command( + tx, + eth_call_inputs.state_overrides, + eth_call_inputs.block.into(), + ) { tracing::debug!(?err, "could not log tenderly simulation command"); } - let output = output - .result + let output = result .context("failed to simulate quote") .map_err(Error::SimulationFailed); @@ -288,7 +390,7 @@ impl TradeVerifier { // It looks like the contract lost a lot of sell tokens but only because it was // the trader and had to pay for the trade. Adjust tokens lost downward. - if verification.from == *self.settlement.address() { + if verification.from == self.simulator.settlement_address() { summary .tokens_lost .entry(query.sell_token) @@ -297,7 +399,7 @@ impl TradeVerifier { // It looks like the contract gained a lot of buy tokens (negative loss) but // only because it was the receiver and got the payout. Adjust the tokens lost // upward. - if verification.receiver == *self.settlement.address() { + if verification.receiver == self.simulator.settlement_address() { summary .tokens_lost .entry(query.buy_token) @@ -368,12 +470,20 @@ impl TradeVerifier { /// trade. async fn prepare_state_overrides( &self, - verification: &mut Verification, + verification: &Verification, query: &PriceQuery, trade: &TradeKind, - ) -> Result { - let mut overrides = AddressMap::default(); + ) -> Result> { + let mut requests: Vec = Vec::new(); + // Setup the funding contract override. Regardless of whether or not the + // contract has funds, it needs to exist in order to not revert + // simulations (Solidity reverts on attempts to call addresses without + // any code). + requests.push(AccountOverrideRequest::Code { + account: Self::SPARDOSE, + code: Spardose::Spardose::DEPLOYED_BYTECODE.clone(), + }); // Provide mocked balances if possible to the spardose to allow it to // give some balances to the trader in order to verify trades even for // owners without balances. Note that we use a separate account for @@ -392,47 +502,17 @@ impl TradeVerifier { &query.kind, )?, }; - match self - .balance_overrides - .state_override(BalanceOverrideRequest { - token: query.sell_token, - holder: Self::SPARDOSE, - amount: spardose_amount_with_buffer(needed), - }) - .await - { - Some((token, solver_balance_override)) => { - tracing::trace!(?solver_balance_override, "solver balance override enabled"); - overrides.insert(token, solver_balance_override); - - if verification.from.is_zero() { - verification.from = Address::random(); - tracing::debug!( - trader = ?verification.from, - "use random trader address with fake balances" - ); - } - } - _ => { - tracing::warn!( - sell_token = ?query.sell_token, - "could not set spardose balance override for sell token; trade \ - verification will rely on the trader's real balance" - ); - if verification.from.is_zero() { - anyhow::bail!("trader is zero address and balances can not be faked"); - } - } - } + requests.push(AccountOverrideRequest::Balance { + holder: Self::SPARDOSE, + token: query.sell_token, + amount: spardose_amount_with_buffer(needed), + }); // Set up mocked trader. - overrides.insert( - verification.from, - AccountOverride { - code: Some(Trader::Trader::DEPLOYED_BYTECODE.clone()), - ..Default::default() - }, - ); + requests.push(AccountOverrideRequest::Code { + account: verification.from, + code: Trader::Trader::DEPLOYED_BYTECODE.clone(), + }); // If the trader is a smart contract we also need to store its implementation // to proxy into it during the simulation. @@ -442,62 +522,30 @@ impl TradeVerifier { .await .context("failed to fetch trader code")?; if !trader_impl.0.is_empty() { - overrides.insert( - Self::TRADER_IMPL, - AccountOverride { - code: Some(trader_impl), - ..Default::default() - }, - ); + requests.push(AccountOverrideRequest::Code { + account: Self::TRADER_IMPL, + code: trader_impl, + }); } - // Setup the funding contract override. Regardless of whether or not the - // contract has funds, it needs to exist in order to not revert - // simulations (Solidity reverts on attempts to call addresses without - // any code). - overrides.insert( - Self::SPARDOSE, - AccountOverride { - code: Some(Spardose::Spardose::DEPLOYED_BYTECODE.clone()), - ..Default::default() - }, - ); - - // Set up mocked solver. - let solver_override = AccountOverride { - code: Some(Solver::Solver::DEPLOYED_BYTECODE.clone()), - // Allow solver simulations to proceed even if the real account holds no ETH. - // The number is obscenely large, but not max to avoid potential overflows. - // We had this set to eth(1), but some simulations require more than that on non-ETH - // netowrks e.g. polygon so it led to reverts. - balance: Some(U256::MAX / U256::from(2)), - ..Default::default() - }; - - // If the trade requires a special tx.origin we also need to fake the - // authenticator. - if trade - .tx_origin() - .is_some_and(|origin| origin != trade.solver()) + // Set up mocked solver with enough ETH to proceed even if the real account + // holds none. + let solver = trade.tx_origin().unwrap_or(trade.solver()); + requests.push(AccountOverrideRequest::Code { + account: solver, + code: Solver::Solver::DEPLOYED_BYTECODE.clone(), + }); + requests.push(AccountOverrideRequest::SufficientEthBalance(solver)); + + // If the trade requires a special tx.origin we also need to allow list + // it in the authenticator + if let Some(custom_origin) = trade.tx_origin() + && custom_origin != trade.solver() { - let authenticator = self - .settlement - .authenticator() - .call() - .await - .context("could not fetch authenticator")?; - overrides.insert( - authenticator, - AccountOverride { - code: Some(AnyoneAuthenticator::AnyoneAuthenticator::DEPLOYED_BYTECODE.clone()), - ..Default::default() - }, - ); + requests.push(AccountOverrideRequest::AuthenticateAsSolver(custom_origin)) } - overrides.insert(trade.tx_origin().unwrap_or(trade.solver()), solver_override); - - Ok(overrides) + Ok(requests) } /// Create interaction that sets up the trade right before transfering @@ -511,24 +559,23 @@ impl TradeVerifier { verification: &Verification, query: &PriceQuery, trade: &TradeKind, - ) -> Interaction { + ) -> InteractionData { let sell_amount = match query.kind { OrderKind::Sell => query.in_amount.get(), OrderKind::Buy => *out_amount, }; let setup_call = Solver::Solver::ensureTradePreconditionsCall { trader: verification.from, - settlementContract: *self.settlement.address(), + settlementContract: self.simulator.settlement_address(), sellToken: query.sell_token, sellAmount: sell_amount, - nativeToken: self.simulator.native_token, spardose: Self::SPARDOSE, } .abi_encode(); - Interaction { + InteractionData { target: trade.solver(), value: U256::ZERO, - data: setup_call, + call_data: setup_call, } } } @@ -618,36 +665,6 @@ impl TradeVerifying for TradeVerifier { } } -fn add_balance_queries(swap: &mut EncodedSwap, query: &PriceQuery, verification: &Verification) { - let (token, owner) = match query.kind { - // track how much `buy_token` the `receiver` actually got - OrderKind::Sell => { - let receiver = match verification.receiver.is_zero() { - // Settlement contract sends fund to owner if receiver is the 0 address. - true => verification.from, - false => verification.receiver, - }; - - (query.buy_token, receiver) - } - // track how much `sell_token` the `from` address actually spent - OrderKind::Buy => (query.sell_token, verification.from), - }; - let query_balance_call = Solver::Solver::storeBalanceCall { - token, - owner, - countGas: true, - } - .abi_encode(); - - let interaction = (swap.solver, U256::ZERO, query_balance_call.into()); - - // query balance query at the end of pre-interactions - swap.settlement.interactions.pre.push(interaction.clone()); - // query balance right after we payed out all `buy_token` - swap.settlement.interactions.post.insert(0, interaction); -} - /// Analyzed output of `Solver::settle` smart contract call. #[derive(Debug)] struct SettleOutput { @@ -764,53 +781,6 @@ pub struct PriceQuery { pub in_amount: NonZeroU256, } -pub fn encode_jit_orders( - jit_orders: &[dto::JitOrder], - tokens: &[Address], - domain_separator: &DomainSeparator, -) -> Result> { - jit_orders - .iter() - .map(|jit_order| { - let order_data = OrderData { - sell_token: jit_order.sell_token, - buy_token: jit_order.buy_token, - receiver: Some(jit_order.receiver), - sell_amount: jit_order.sell_amount, - buy_amount: jit_order.buy_amount, - valid_to: jit_order.valid_to, - app_data: jit_order.app_data, - fee_amount: U256::ZERO, - kind: match &jit_order.side { - Side::Buy => OrderKind::Buy, - Side::Sell => OrderKind::Sell, - }, - partially_fillable: jit_order.partially_fillable, - sell_token_balance: jit_order.sell_token_source, - buy_token_balance: jit_order.buy_token_destination, - }; - let (owner, signature) = - recover_jit_order_owner(jit_order, &order_data, domain_separator)?; - - Ok(encode_trade( - &order_data, - &signature, - owner, - // the tokens set length is small so the linear search is acceptable - tokens - .iter() - .position(|token| *token == jit_order.sell_token) - .context("missing jit order sell token index")?, - tokens - .iter() - .position(|token| *token == jit_order.buy_token) - .context("missing jit order buy token index")?, - jit_order.executed_amount, - )) - }) - .collect::>>() -} - /// Recovers the owner and signature from a `JitOrder`. fn recover_jit_order_owner( jit_order: &dto::JitOrder, diff --git a/crates/simulator/Cargo.toml b/crates/simulator/Cargo.toml index 1b4777003b..5c41b774e0 100644 --- a/crates/simulator/Cargo.toml +++ b/crates/simulator/Cargo.toml @@ -8,6 +8,7 @@ license = "MIT OR Apache-2.0" [dependencies] alloy-contract = { workspace = true } alloy-eips = { workspace = true } +alloy-network = { workspace = true } alloy-primitives = { workspace = true } alloy-provider = { workspace = true } alloy-rpc-types = { workspace = true } @@ -25,6 +26,7 @@ contracts = { workspace = true } derive_more = { workspace = true } eth-domain-types = { workspace = true } ethrpc = { workspace = true } +futures = { workspace = true } gas-price-estimation = { workspace = true } hex-literal = { workspace = true } http-client = { workspace = true } diff --git a/crates/simulator/src/encoding.rs b/crates/simulator/src/encoding.rs index 8c6d188c24..61b3db0105 100644 --- a/crates/simulator/src/encoding.rs +++ b/crates/simulator/src/encoding.rs @@ -241,9 +241,12 @@ impl From for Interaction { } } -pub fn encode_interactions<'a>( - interactions: impl IntoIterator, -) -> Vec { +pub fn encode_interactions<'a, I>( + interactions: impl IntoIterator, +) -> Vec +where + I: InteractionEncoding + 'a, +{ interactions.into_iter().map(|i| i.encode()).collect() } diff --git a/crates/simulator/src/lib.rs b/crates/simulator/src/lib.rs index e3f98f0362..ac90a39592 100644 --- a/crates/simulator/src/lib.rs +++ b/crates/simulator/src/lib.rs @@ -1,6 +1,7 @@ pub mod encoding; pub mod ethereum; -pub mod swap_simulator; +pub mod simulation_builder; +mod simulation_encoding; pub mod tenderly; mod utils; diff --git a/crates/simulator/src/simulation_builder.rs b/crates/simulator/src/simulation_builder.rs new file mode 100644 index 0000000000..38ad3fef16 --- /dev/null +++ b/crates/simulator/src/simulation_builder.rs @@ -0,0 +1,548 @@ +use { + crate::{encoding::WrapperCall, tenderly::dto::StateObject}, + alloy_primitives::{Address, B256, Bytes, TxKind, U256}, + alloy_provider::{DynProvider, Provider}, + alloy_rpc_types::{ + TransactionRequest, + state::{AccountOverride, StateOverride}, + }, + alloy_sol_types::SolCall, + alloy_transport::RpcError, + anyhow::{Context, Result}, + balance_overrides::BalanceOverriding, + ethrpc::block_stream::CurrentBlockWatcher, + model::{ + DomainSeparator, + interaction::InteractionData, + order::OrderData, + signature::{Signature, SigningScheme}, + }, + std::sync::Arc, +}; + +/// Holds the settlement contract and its authenticator address, and acts as a +/// factory for [`SimulationBuilder`] instances that are pre-configured with +/// these values. +#[derive(Clone)] +pub struct SettlementSimulator(pub(crate) Arc); + +pub(crate) struct Inner { + pub(crate) settlement: contracts::GPv2Settlement::Instance, + pub(crate) authenticator: Address, + pub(crate) flash_loan_router: Address, + pub(crate) hooks_trampoline: Address, + pub(crate) native_token: Address, + pub(crate) max_gas_limit: u64, + pub(crate) balance_overrides: Arc, + pub(crate) provider: DynProvider, + pub(crate) domain_separator: DomainSeparator, + pub(crate) chain_id: u64, + pub(crate) current_block: CurrentBlockWatcher, + pub(crate) tenderly: Option>, +} + +impl SettlementSimulator { + #[expect(clippy::too_many_arguments)] + pub async fn new( + settlement: contracts::GPv2Settlement::Instance, + flash_loan_router: Address, + hooks_trampoline: Address, + native_token: Address, + max_gas_limit: u64, + balance_overrides: Arc, + current_block: CurrentBlockWatcher, + tenderly: Option>, + ) -> Result { + let authenticator = Address(settlement.authenticator().call().await?.0); + let domain_separator = DomainSeparator(settlement.domainSeparator().call().await?.0); + let provider = settlement.provider().clone(); + let chain_id = provider.get_chain_id().await?; + Ok(Self(Arc::new(Inner { + settlement, + authenticator, + flash_loan_router, + hooks_trampoline, + native_token, + max_gas_limit, + balance_overrides, + provider, + domain_separator, + chain_id, + current_block, + tenderly, + }))) + } + + pub fn native_token(&self) -> Address { + self.0.native_token + } + + pub fn max_gas_limit(&self) -> u64 { + self.0.max_gas_limit + } + + pub fn provider(&self) -> DynProvider { + self.0.provider.clone() + } + + pub fn settlement_address(&self) -> Address { + *self.0.settlement.address() + } + + pub fn authenticator_address(&self) -> Address { + self.0.authenticator + } + + pub fn new_simulation_builder(&self) -> SimulationBuilder { + SimulationBuilder { + simulator: self.clone(), + orders: vec![], + pre_interactions: vec![], + main_interactions: vec![], + post_interactions: vec![], + wrapper: WrapperConfig::NoWrapper, + solver: None, + auction_id: None, + account_override_requests: vec![], + block: Block::Latest, + } + } + + pub fn domain_separator(&self) -> DomainSeparator { + self.0.domain_separator + } +} + +/// Which block to simulate against. +pub enum Block { + /// Use the current head block from the block stream, pinning the + /// simulation to a concrete number at build time. + Latest, + Number(u64), +} + +/// Assembles a GPv2 settlement call for simulation purposes. +/// +/// Call [`SimulationBuilder::build`] when done to produce a [`SettlementCall`]. +pub struct SimulationBuilder { + pub(crate) orders: Vec, + pub(crate) pre_interactions: Vec, + pub(crate) main_interactions: Vec, + pub(crate) post_interactions: Vec, + pub(crate) wrapper: WrapperConfig, + pub(crate) solver: Option, + pub(crate) auction_id: Option, + pub(crate) simulator: SettlementSimulator, + pub(crate) account_override_requests: Vec, + pub(crate) block: Block, +} + +impl SimulationBuilder { + pub fn add_orders(mut self, orders: impl IntoIterator) -> Self { + self.orders.extend(orders); + self + } + + pub fn with_pre_interactions( + mut self, + interactions: impl IntoIterator, + ) -> Self { + self.pre_interactions = interactions.into_iter().collect(); + self + } + + pub fn with_main_interactions( + mut self, + interactions: impl IntoIterator, + ) -> Self { + self.main_interactions = interactions.into_iter().collect(); + self + } + + pub fn with_post_interactions( + mut self, + interactions: impl IntoIterator, + ) -> Self { + self.post_interactions = interactions.into_iter().collect(); + self + } + + pub fn with_wrapper(mut self, wrapper: WrapperConfig) -> Self { + self.wrapper = wrapper; + self + } + + pub fn from_solver(mut self, solver: Solver) -> Self { + self.solver = Some(solver); + self + } + + pub fn with_auction_id(mut self, id: i64) -> Self { + self.auction_id = Some(id); + self + } + + pub fn at_block(mut self, block: Block) -> Self { + self.block = block; + self + } + + /// Parses the app data JSON and configures the builder accordingly: + /// - Pre/post hooks are encoded as interactions via the [`HooksTrampoline`] + /// - Flashloan/wrapper fields set the [`WrapperConfig`]. + pub fn parameters_from_app_data(mut self, app_data: &str) -> Result { + let protocol = app_data::parse(app_data.as_bytes()).map_err(BuildError::AppDataParse)?; + + let encode_hooks = |hooks: &[app_data::Hook]| -> Vec { + if hooks.is_empty() { + return vec![]; + } + vec![InteractionData { + target: self.simulator.0.hooks_trampoline, + value: U256::ZERO, + call_data: contracts::HooksTrampoline::HooksTrampoline::executeCall { + hooks: hooks + .iter() + .map(|h| contracts::HooksTrampoline::HooksTrampoline::Hook { + target: h.target, + callData: Bytes::copy_from_slice(&h.call_data), + gasLimit: U256::from(h.gas_limit), + }) + .collect(), + } + .abi_encode(), + }] + }; + self.pre_interactions = encode_hooks(&protocol.hooks.pre); + self.post_interactions = encode_hooks(&protocol.hooks.post); + + let has_wrappers = !protocol.wrappers.is_empty(); + let has_flashloan = protocol.flashloan.is_some(); + if has_wrappers && has_flashloan { + return Err(BuildError::FlashloanWrappersIncompatible); + } + if has_wrappers { + self.wrapper = WrapperConfig::Custom( + protocol + .wrappers + .into_iter() + .map(|w| WrapperCall { + address: w.address, + data: w.data.into(), + }) + .collect(), + ); + } else if let Some(flashloan) = protocol.flashloan { + self.wrapper = WrapperConfig::Flashloan(vec![FlashloanRequest { + amount: flashloan.amount, + borrower: flashloan.protocol_adapter, + lender: flashloan.liquidity_provider, + token: flashloan.token, + }]); + } + + Ok(self) + } + + /// Queues [`AccountOverrideRequest`]s to be resolved and applied during + /// [`build`](Self::build). Multiple requests may target the same address + /// and will be applied on a best-effort basis (failure to compute balance + /// overrides or conflicting state overrides will get logged but do not + /// lead to an error). + pub fn with_overrides( + mut self, + requests: impl IntoIterator, + ) -> Self { + self.account_override_requests.extend(requests); + self + } + + /// Finishes the simulation struct based on the configuration thus far. + pub async fn build(self) -> Result { + // Forward to a helper function to split the boring repetitive builder + // code from the non-trivial code that actually does the encoding. + crate::simulation_encoding::encode(self).await + } +} + +pub enum Solver { + /// Simulation assumes this is an actual solver so no state overrides will + /// be applied to allow list it explicitly. + /// If you need a very specific solver setup for your simulation consider + /// using this and explicitly adding the necessary + /// [`AccountOverrideRequest`]s using with + /// [`SimulationBuilder::with_overrides()`]. + OriginUnaltered(Address), + /// A fake solver for simulation. Uses the provided address or generates a + /// random one. The simulation builder will automatically set the required + /// state overrides to give it enough ETH and allow list it as a solver. + Fake(Option
), +} + +/// How much of an order should be filled during simulation. +pub enum ExecutionAmount { + /// Fill the full order amount (sell_amount for sell orders, buy_amount for + /// buy orders), ignoring any on-chain filled state. + Full, + /// Fill whatever is still remaining on-chain (queries the settlement + /// contract for the already-filled amount and subtracts it). Falls back to + /// the full amount if the query fails. + Remaining, + /// Use an explicit fill amount. + Explicit(U256), +} + +/// How clearing prices are determined for the encoded settlement. +pub enum PriceEncoding { + /// Derive clearing prices directly from the order's limit price. + /// + /// Sets `price[sell_token] = buy_amount` and `price[buy_token] = + /// sell_amount`, exactly satisfying the order's limit with no surplus. + LimitPrice, + /// Explicit clearing prices for the order's sell and buy token. Use this + /// when the prices differ from the order's limit — e.g. in trade + /// verification where the order amounts are set to always pass the limit + /// check and the solver's quoted prices are supplied separately. + Custom { sell_price: U256, buy_price: U256 }, +} + +/// A simulator-specific order that bundles the data needed to encode a trade. +/// +/// Construct with [`Order::new`] and add optional fields via the builder +/// methods. Defaults to an EIP-1271 signature (pairs with [`FakeUser`] for +/// simulations that need to bypass signature verification). +pub struct Order { + pub(crate) data: OrderData, + pub(crate) owner: Address, + pub(crate) signature: Signature, + pub(crate) pre_interactions: Vec, + pub(crate) post_interactions: Vec, + pub(crate) executed_amount: ExecutionAmount, + pub(crate) price_encoding: PriceEncoding, +} + +/// Configuration for wrapping the settlement in a flashloan or custom wrapper +/// contract chain. +pub enum WrapperConfig { + Flashloan(Vec), + Custom(Vec), + NoWrapper, +} + +pub struct FlashloanRequest { + pub amount: U256, + pub borrower: Address, + pub lender: Address, + pub token: Address, +} + +impl Order { + pub fn new(data: OrderData) -> Self { + Self { + data, + owner: Address::ZERO, + signature: Signature::default_with(SigningScheme::Eip1271), + pre_interactions: vec![], + post_interactions: vec![], + executed_amount: ExecutionAmount::Remaining, + price_encoding: PriceEncoding::LimitPrice, + } + } + + pub fn with_signature(mut self, owner: Address, signature: Signature) -> Self { + self.owner = owner; + self.signature = signature; + self + } + + pub fn with_pre_interactions( + mut self, + interactions: impl IntoIterator, + ) -> Self { + self.pre_interactions = interactions.into_iter().collect(); + self + } + + pub fn with_post_interactions( + mut self, + interactions: impl IntoIterator, + ) -> Self { + self.post_interactions = interactions.into_iter().collect(); + self + } + + pub fn fill_at(mut self, execution: ExecutionAmount, price: PriceEncoding) -> Self { + self.executed_amount = execution; + self.price_encoding = price; + self + } +} + +/// The output of [`SimulationBuilder::build`]: a transaction request and state +/// overrides ready to be passed to an alloy provider for simulation. +pub struct EthCallInputs { + pub request: TransactionRequest, + pub state_overrides: StateOverride, + pub simulator: SettlementSimulator, + pub block: u64, +} + +/// The result of Order simulation, contains the error (if any) +/// and full Tenderly API request that can be used to resimulate +/// and debug using Tenderly +#[derive(Clone, Debug)] +pub struct TenderlyReport { + /// Full request object that can be used directly with the Tenderly API + pub tenderly_request: crate::tenderly::dto::Request, + /// Shared Tenderly simulation URL for debugging in the dashboard + pub tenderly_url: Option, + /// Any error that might have been reported during order simulation + pub error: Option, +} + +impl EthCallInputs { + pub async fn simulate(self) -> Result> { + self.simulator + .0 + .provider + .clone() + .call(self.request) + .overrides(self.state_overrides) + .block(self.block.into()) + .await + } + + pub async fn simulate_with_tenderly_report(self) -> Result { + let tenderly_request = self + .to_tenderly_request() + .context("failed to convert to tenderly request")?; + let tenderly_url = match &self.simulator.0.tenderly { + Some(api) => Some( + api.simulate_and_share(tenderly_request.clone()) + .await + .context("tenderly failed")?, + ), + None => None, + }; + let simulation_result = self.simulate().await; + + Ok(TenderlyReport { + tenderly_request, + tenderly_url, + error: match simulation_result { + Ok(_) => None, + Err(err) => Some(err.to_string()), + }, + }) + } + + /// Converts the simulation into a request that can be simulated with + /// tenderly. + pub fn to_tenderly_request(&self) -> Result { + Ok(crate::tenderly::dto::Request { + // By default tenderly simulates calls at the start of the block. So if we simulate + // something when the latest block is `n` we need to tell tenderly to simulate at + // block `n+1` to still have all of block n's txs happen before our simulation runs. + block_number: Some(self.block + 1), + network_id: self.simulator.0.chain_id.to_string(), + from: self.request.from.unwrap_or_default(), + to: match &self.request.to.ok_or(ConversionError::MissingTo)? { + TxKind::Create => Default::default(), + TxKind::Call(to) => *to, + }, + input: self + .request + .input + .input + .as_ref() + .map(|bytes| bytes.to_vec()) + .unwrap_or_default(), + gas: self.request.gas, + value: self.request.value, + simulation_type: Some(crate::tenderly::dto::SimulationType::Full), + state_objects: Some( + self.state_overrides + .iter() + .map(|(key, value)| { + Ok(( + *key, + StateObject::try_from(value.clone()) + .map_err(|_| ConversionError::StateOverrides)?, + )) + }) + .collect::>()?, + ), + access_list: self.request.access_list.as_ref().map(Into::into), + save: Some(true), + gas_price: None, // use tenderly default for now + save_if_fails: Some(true), + transaction_index: None, + generate_access_list: None, + }) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum ConversionError { + #[error("simulation does not have a target")] + MissingTo, + #[error("could not convert state overrides")] + StateOverrides, +} + +#[derive(Debug, thiserror::Error)] +pub enum BuildError { + #[error("no order was added")] + NoOrder, + #[error("no solver was set")] + NoSolver, + #[error("failed to query filled amount from settlement contract: {0}")] + FilledAmountQuery(#[source] anyhow::Error), + #[error("failed to parse app data: {0}")] + AppDataParse(#[source] serde_json::Error), + #[error("both wrappers and flashloans cannot be encoded in the same settlement")] + FlashloanWrappersIncompatible, +} + +#[derive(Debug)] +pub enum AccountOverrideRequest { + /// Gives the address a huge amount of ETH. + SufficientEthBalance(Address), + /// Allowlists an address as a solver to let it settle orders. + AuthenticateAsSolver(Address), + /// Computes necessary state overrides for the requested balance. + Balance { + holder: Address, + token: Address, + amount: U256, + }, + /// Gives the settlement contract enough buy tokens to pay for all + /// orders. + BuyTokensForBuffers, + /// Deploys the provided code at the requested address. + Code { account: Address, code: Bytes }, + /// Allows to build fully custom overrides for the most exotic use cases. + Custom { + account: Address, + state: AccountOverride, + }, + // TODO: add Allowance +} + +/// Error returned when two [`AccountOverride`]s set the same field for the same +/// address and cannot be merged. +#[derive(Debug, thiserror::Error)] +pub(crate) enum MergeConflict { + #[error("both overrides set the ETH balance")] + Balance, + #[error("both overrides set the nonce")] + Nonce, + #[error("both overrides set the contract code")] + Code, + #[error("both overrides replace the full storage state")] + State, + #[error("overrides use incompatible storage strategies (state vs state_diff)")] + StateAndStateDiff, + #[error("both overrides write storage slot {0}")] + StateDiffSlot(B256), +} diff --git a/crates/simulator/src/simulation_encoding.rs b/crates/simulator/src/simulation_encoding.rs new file mode 100644 index 0000000000..1dc8a04981 --- /dev/null +++ b/crates/simulator/src/simulation_encoding.rs @@ -0,0 +1,385 @@ +use { + crate::{ + encoding::{ + EncodedSettlement, + Interactions, + encode_interactions, + encode_trade, + encode_wrapper_settlement, + }, + simulation_builder::{ + AccountOverrideRequest, + Block, + BuildError, + EthCallInputs, + ExecutionAmount, + MergeConflict, + Order, + PriceEncoding, + SimulationBuilder, + Solver, + WrapperConfig, + }, + }, + alloy_primitives::{Address, B256, Bytes, U256, keccak256}, + alloy_rpc_types::{ + TransactionRequest, + state::{AccountOverride, StateOverride}, + }, + alloy_sol_types::SolCall, + balance_overrides::{BalanceOverrideRequest, BalanceOverriding}, + model::{interaction::InteractionData, order::OrderKind}, +}; + +pub(crate) async fn encode(mut builder: SimulationBuilder) -> Result { + if builder.orders.is_empty() { + return Err(BuildError::NoOrder); + } + + let block = match builder.block { + Block::Latest => builder.simulator.0.current_block.borrow().number, + Block::Number(n) => n, + }; + + let executed_amounts = futures::future::try_join_all( + builder + .orders + .iter() + .map(|o| executed_amount(&builder, o, block)), + ) + .await?; + + // Each order occupies exactly 2 consecutive slots in the token/price + // vectors: [2*i] = sell_token, [2*i+1] = buy_token. + // This lets every order be encoded independently without requiring a shared + // global token list. + let n = builder.orders.len(); + let mut tokens = Vec::with_capacity(n * 2); + let mut clearing_prices = Vec::with_capacity(n * 2); + for order in &builder.orders { + let (sell_price, buy_price) = match &order.price_encoding { + PriceEncoding::LimitPrice => (order.data.buy_amount, order.data.sell_amount), + PriceEncoding::Custom { + sell_price, + buy_price, + } => (*sell_price, *buy_price), + }; + tokens.push(order.data.sell_token); + tokens.push(order.data.buy_token); + clearing_prices.push(sell_price); + clearing_prices.push(buy_price); + } + + // Expand any BuyTokensForBuffers request into one Balance override per + // order, then remove all BuyTokensForBuffers entries so duplicates are + // impossible. + if builder + .account_override_requests + .iter() + .any(|r| matches!(r, AccountOverrideRequest::BuyTokensForBuffers)) + { + builder + .account_override_requests + .retain(|r| !matches!(r, AccountOverrideRequest::BuyTokensForBuffers)); + let settlement = *builder.simulator.0.settlement.address(); + for (i, (order, &exec)) in builder.orders.iter().zip(&executed_amounts).enumerate() { + let sell_price = clearing_prices[2 * i]; + let buy_price = clearing_prices[2 * i + 1]; + let amount = match order.data.kind { + OrderKind::Sell => sell_price + .saturating_mul(exec) + .checked_div(buy_price) + .unwrap_or(U256::MAX), + OrderKind::Buy => exec, + } + // give 1 wei extra to avoid issues with rounding divisions + .saturating_add(U256::ONE); + builder + .account_override_requests + .push(AccountOverrideRequest::Balance { + holder: settlement, + token: order.data.buy_token, + amount, + }); + } + } + + // Encode every order as a trade, then collect all their interactions. + let mut trades = Vec::with_capacity(n); + let mut all_order_pre: Vec = vec![]; + let mut all_order_post: Vec = vec![]; + for (i, (order, exec)) in builder.orders.iter().zip(&executed_amounts).enumerate() { + trades.push(encode_trade( + &order.data, + &order.signature, + order.owner, + 2 * i, + 2 * i + 1, + *exec, + )); + all_order_pre.extend_from_slice(&order.pre_interactions); + all_order_post.extend_from_slice(&order.post_interactions); + } + + let settlement = EncodedSettlement { + tokens, + clearing_prices, + trades, + interactions: Interactions { + // order pre-hooks run before any additional pre-interactions + pre: encode_interactions(all_order_pre.iter().chain(&builder.pre_interactions)), + main: encode_interactions(&builder.main_interactions), + // additional post-interactions run before order post-hooks + post: encode_interactions(builder.post_interactions.iter().chain(&all_order_post)), + }, + }; + + let settle_calldata = { + let mut bytes = settlement.into_settle_call().to_vec(); + if let Some(id) = builder.auction_id { + bytes.extend_from_slice(&id.to_be_bytes()); + } + bytes.into() + }; + + let wrapper = builder.wrapper; + let (to, input) = match wrapper { + WrapperConfig::Custom(wrappers) if !wrappers.is_empty() => { + encode_wrapper_settlement(&wrappers, settle_calldata).expect("wrappers is non-empty") + } + WrapperConfig::Flashloan(loans) => { + let calldata = contracts::FlashLoanRouter::FlashLoanRouter::flashLoanAndSettleCall { + loans: loans + .into_iter() + .map(|l| contracts::FlashLoanRouter::LoanRequest::Data { + amount: l.amount, + borrower: l.borrower, + lender: l.lender, + token: l.token, + }) + .collect(), + settlement: settle_calldata, + } + .abi_encode() + .into(); + (builder.simulator.0.flash_loan_router, calldata) + } + _ => (*builder.simulator.0.settlement.address(), settle_calldata), + }; + + let from = match builder.solver { + Some(Solver::OriginUnaltered(addr)) => addr, + Some(Solver::Fake(opt)) => { + let addr = opt.unwrap_or_else(Address::random); + builder + .account_override_requests + .push(AccountOverrideRequest::SufficientEthBalance(addr)); + builder + .account_override_requests + .push(AccountOverrideRequest::AuthenticateAsSolver(addr)); + addr + } + None => return Err(BuildError::NoSolver), + }; + let state_overrides = build_final_state_overrides( + builder.account_override_requests, + builder.simulator.0.balance_overrides.as_ref(), + builder.simulator.0.authenticator, + ) + .await; + + Ok(EthCallInputs { + request: TransactionRequest { + from: Some(from), + to: Some(to.into()), + input: input.into(), + gas: Some(builder.simulator.0.max_gas_limit), + ..Default::default() + }, + state_overrides, + block, + simulator: builder.simulator, + }) +} + +async fn executed_amount( + builder: &SimulationBuilder, + order: &Order, + block: u64, +) -> Result { + let full = match order.data.kind { + OrderKind::Sell => order.data.sell_amount, + OrderKind::Buy => order.data.buy_amount, + }; + + Ok(match order.executed_amount { + ExecutionAmount::Full => full, + ExecutionAmount::Explicit(amount) => amount, + ExecutionAmount::Remaining => { + let uid = order + .data + .uid(&builder.simulator.0.domain_separator, order.owner); + let filled_amount = builder + .simulator + .0 + .settlement + .filledAmount(Bytes::from(uid.0)) + .block(block.into()) + .call() + .await + .map_err(|err| BuildError::FilledAmountQuery(err.into()))?; + full.saturating_sub(filled_amount) + } + }) +} + +/// Resolves all [`AccountOverrideRequest`]s concurrently on a best-effort +/// basis. Failures are logged and the corresponding override is skipped rather +/// than aborting the whole build. +async fn build_final_state_overrides( + requests: Vec, + balance_overrides: &dyn BalanceOverriding, + authenticator: Address, +) -> StateOverride { + let futures = requests.into_iter().map(|request| async move { + match request { + AccountOverrideRequest::SufficientEthBalance(addr) => Some(( + addr, + AccountOverride::default().with_balance(U256::MAX / U256::from(2)), + )), + AccountOverrideRequest::AuthenticateAsSolver(addr) => { + // GPv2AllowListAuthentication stores `mapping(address => bool) managers` + // at storage slot 1. Solidity mapping key: keccak256(address_padded ++ + // slot_padded). + let mut buf = [0u8; 64]; + buf[12..32].copy_from_slice(addr.as_slice()); + buf[32..64].copy_from_slice(&U256::ONE.to_be_bytes::<32>()); + let slot = keccak256(buf); + Some(( + authenticator, + AccountOverride::default() + .with_state_diff(std::iter::once((slot, B256::with_last_byte(1)))), + )) + } + AccountOverrideRequest::Balance { + holder, + token, + amount, + } => { + let result = balance_overrides + .state_override(BalanceOverrideRequest { + token, + holder, + amount, + }) + .await; + if result.is_none() { + tracing::warn!(%token, %holder, "failed to compute balance state override, skipping"); + } + result + } + AccountOverrideRequest::BuyTokensForBuffers => { + unreachable!( + "replaced with specific Balance requests before state overrides get \ + computed" + ) + } + AccountOverrideRequest::Code { account, code } => Some(( + account, + AccountOverride { + code: Some(code), + ..Default::default() + }, + )), + AccountOverrideRequest::Custom { account, state } => Some((account, state)), + } + }); + + let mut state_overrides = StateOverride::default(); + for (address, account_override) in futures::future::join_all(futures) + .await + .into_iter() + .flatten() + { + if let Err(err) = apply_account_override(&mut state_overrides, address, account_override) { + tracing::warn!(?err, %address, "conflicting state overrides for address, skipping"); + } + } + state_overrides +} + +/// Merges `new` into `existing` field by field. +/// +/// Returns [`MergeConflict`] if both overrides write the same field. +/// Non-conflicting `state_diff` entries are combined into a single map. +fn merge_account_override( + existing: &mut AccountOverride, + new: AccountOverride, +) -> Result<(), MergeConflict> { + if new.balance.is_some() { + if existing.balance.is_some() { + return Err(MergeConflict::Balance); + } + existing.balance = new.balance; + } + if new.nonce.is_some() { + if existing.nonce.is_some() { + return Err(MergeConflict::Nonce); + } + existing.nonce = new.nonce; + } + if new.code.is_some() { + if existing.code.is_some() { + return Err(MergeConflict::Code); + } + existing.code = new.code; + } + match (new.state, new.state_diff) { + (Some(new_state), None) => { + if existing.state.is_some() { + return Err(MergeConflict::State); + } + if existing.state_diff.is_some() { + return Err(MergeConflict::StateAndStateDiff); + } + existing.state = Some(new_state); + } + (None, Some(new_diff)) => { + if existing.state.is_some() { + return Err(MergeConflict::StateAndStateDiff); + } + match &mut existing.state_diff { + None => existing.state_diff = Some(new_diff), + Some(existing_diff) => { + for (slot, value) in new_diff { + if existing_diff.contains_key(&slot) { + return Err(MergeConflict::StateDiffSlot(slot)); + } + existing_diff.insert(slot, value); + } + } + } + } + (None, None) => {} + // alloy does not allow both simultaneously, treat as incompatible + (Some(_), Some(_)) => return Err(MergeConflict::StateAndStateDiff), + } + Ok(()) +} + +/// Applies `new` to the override map for `address`. +/// +/// If `address` already has an entry, the overrides are merged via +/// [`merge_account_override`]. Returns an error on conflict. +fn apply_account_override( + overrides: &mut StateOverride, + address: Address, + new: AccountOverride, +) -> Result<(), MergeConflict> { + if let Some(existing) = overrides.get_mut(&address) { + merge_account_override(existing, new) + } else { + overrides.insert(address, new); + Ok(()) + } +} diff --git a/crates/simulator/src/swap_simulator.rs b/crates/simulator/src/swap_simulator.rs deleted file mode 100644 index bf0b9f840d..0000000000 --- a/crates/simulator/src/swap_simulator.rs +++ /dev/null @@ -1,338 +0,0 @@ -use { - crate::encoding::{ - EncodedSettlement, - EncodedTrade, - Interactions, - WrapperCall, - encode_trade, - encode_wrapper_settlement, - }, - alloy_primitives::{Address, Bytes, U256}, - alloy_provider::Provider, - alloy_rpc_types::{TransactionRequest, state::StateOverride}, - alloy_sol_types::SolCall, - anyhow::{Context, Result, anyhow}, - balance_overrides::BalanceOverriding, - contracts::{ - GPv2Settlement::{self}, - WETH9, - support::Solver::{self, Solver::swapReturn}, - }, - eth_domain_types::NonZeroU256, - ethrpc::{ - Web3, - block_stream::{BlockInfo, CurrentBlockWatcher}, - }, - model::{ - DomainSeparator, - order::{BUY_ETH_ADDRESS, BuyTokenDestination, OrderData, OrderKind, SellTokenSource}, - signature::{Signature, SigningScheme}, - }, - std::sync::Arc, -}; - -/// Query for the Swap Simulator to prepare a fake settlement with -/// Contains the minimum data required to encode a fake settlement -#[derive(Debug)] -pub struct Query { - pub sell_token: Address, - pub sell_amount: NonZeroU256, - pub buy_token: Address, - pub buy_amount: U256, - pub kind: OrderKind, - pub receiver: Address, - pub sell_token_source: SellTokenSource, - pub buy_token_destination: BuyTokenDestination, - pub from: Address, - pub tx_origin: Option
, - pub solver: Address, - pub tokens: Vec
, - pub clearing_prices: Vec, - pub wrappers: Vec, -} - -/// Controls how the trade is encoded for the provided Query -#[derive(Clone, Debug)] -pub enum TradeEncoding { - /// Encodes the trade amounts exactly as in the Query - Simple, - /// Encodes a trade with the most disadvantageous in and out amounts - /// possible (while taking possible overflows into account). Should the - /// trader not receive the amount promised by the [`Query`] the - /// simulation will still work and the actual out amount can be computed - /// afterwards. - Disadvantageous, -} - -#[derive(Clone)] -pub struct SwapSimulator { - pub balance_overrides: Arc, - pub settlement: GPv2Settlement::Instance, - pub native_token: Address, - pub domain_separator: DomainSeparator, - pub current_block: CurrentBlockWatcher, - pub web3: Web3, - pub gas_limit: u64, -} - -pub struct EncodedSwap { - pub settlement: EncodedSettlement, - pub overrides: StateOverride, - pub wrappers: Vec, - pub solver: Address, - pub receiver: Address, -} - -/// The output of a swap simulation. -/// -/// Contains the transaction request that was used to perform the simulation -/// (useful for introspection), The used state overrides and simulation result -/// The result is of generic type O, and depends on the type of simulation: -/// - solver swap simulation returns Solver::swapResult -/// - generic simulation returns Bytes -pub struct SwapSimulation { - pub tx: TransactionRequest, - pub overrides: StateOverride, - pub result: Result, -} - -impl SwapSimulator { - pub async fn new( - balance_overrides: Arc, - settlement: Address, - native_token: Address, - current_block: CurrentBlockWatcher, - web3: Web3, - gas_limit: u64, - ) -> Result { - let settlement = GPv2Settlement::GPv2Settlement::new(settlement, web3.provider.clone()); - let domain_separator = DomainSeparator(settlement.domainSeparator().call().await?.0); - - Ok(Self { - balance_overrides, - settlement, - native_token, - current_block, - web3, - gas_limit, - domain_separator, - }) - } - - /// Creates a fake swap based on the provided query - /// The result can be further post processed depending on the needs - /// - /// It can then be simulated with SwapSimulator::simulate_swap - /// - /// The trade_encoding controls if the trade should be encoded as-is, - /// based on the Query or if it should be encoded as the most - /// disadvantegous trade possible. - /// - /// The TradeEncoding::Disadvantegous is useful for price verification since - /// the resulting out amounts can be calculated later while allowing the - /// simulation to pass. - pub async fn fake_swap( - &self, - query: &Query, - trade_encoding: TradeEncoding, - ) -> Result { - let overrides = StateOverride::default(); - - let pre_interactions = Vec::new(); - let mut interactions = Vec::new(); - - if query.buy_token == BUY_ETH_ADDRESS { - // Because the `driver` manages `WETH` unwraps under the hood the `TradeFinder` - // does not have to emit unwraps to pay out `ETH` in a trade. - // However, for the simulation to be successful this has to happen so we do it - // ourselves here. - interactions.push(( - self.native_token, - U256::ZERO, - WETH9::WETH9::withdrawCall { - wad: query.buy_amount, - } - .abi_encode() - .into(), - )); - tracing::trace!("adding unwrap interaction for paying out ETH"); - } - - Ok(EncodedSwap { - settlement: EncodedSettlement { - tokens: query.tokens.to_vec(), - clearing_prices: query.clearing_prices.to_vec(), - trades: vec![encode_fake_trade(query, trade_encoding)?], - interactions: Interactions { - pre: pre_interactions, - main: interactions, - post: Vec::new(), - }, - }, - solver: query.tx_origin.unwrap_or(query.solver), - receiver: query.receiver, - overrides, - wrappers: query.wrappers.clone(), - }) - } - - /// For wrapped settlements, the Solver contract must call the first wrapper - /// (not the settlement directly). The wrapper then chains to the - /// settlement. For non-wrapped settlements, the Solver calls the - /// settlement contract directly. - fn get_target_and_calldata(&self, swap: &EncodedSwap) -> (Address, Bytes) { - if !swap.wrappers.is_empty() { - encode_wrapper_settlement(&swap.wrappers, swap.settlement.into_settle_call()) - .expect("wrappers is not empty") - } else { - ( - *self.settlement.address(), - swap.settlement.into_settle_call(), - ) - } - } - - /// Simulates a solver call to settlement contract with the provided swap - /// data. The swap call result is contained in the returned - /// SwapSimulation struct, along with the original TransactionRequest - /// and State overrides (if needed to be logged, or processed elsewhere). - /// - /// The caller supplies the `block` so the gas-price computation, the - /// pinned `.call()` block, and any downstream logging all reference the - /// same snapshot of chain state. - pub async fn simulate_swap_with_solver( - &self, - swap: EncodedSwap, - block: BlockInfo, - ) -> Result> { - let (settlement_target, calldata) = self.get_target_and_calldata(&swap); - let solver = Solver::Instance::new(swap.solver, self.web3.provider.clone()); - let overrides = swap.overrides; - - let swap = solver - .swap( - settlement_target, - swap.settlement.tokens.clone(), - swap.receiver, - calldata, - ) - .from(swap.solver) - .gas(self.gas_limit) - .gas_price( - u128::try_from(block.gas_price.saturating_mul(U256::from(2))) - .map_err(|err| anyhow!(err)) - .context("converting gas price to u128")?, - ); - - // Save the transaction request, so the caller can inspect it. - // For example, to create a tenderly API request and provide the ability to - // simulate it. - let tx = swap.clone().into_transaction_request(); - let result = swap - .call() - .overrides(overrides.clone()) - .block(block.number.into()) - .await - .map_err(|err| anyhow!(err)) - .context("failed to simulate swap"); - - Ok(SwapSimulation { - tx, - overrides, - result, - }) - } - - /// Simulate settle call on the latest block - pub async fn simulate_settle_call_on_latest( - &self, - swap: EncodedSwap, - ) -> Result> { - let block_number = self.current_block.borrow().number; - self.simulate_settle_call(swap, block_number).await - } - - pub async fn simulate_settle_call( - &self, - swap: EncodedSwap, - block_number: u64, - ) -> Result> { - let (settlement_target, calldata) = self.get_target_and_calldata(&swap); - - let overrides = swap.overrides; - let tx = TransactionRequest { - from: Some(swap.solver), - to: Some(settlement_target.into()), - input: calldata.into(), - gas: Some(self.gas_limit), - ..Default::default() - }; - - let result = self - .web3 - .provider - .call(tx.clone()) - .overrides(overrides.clone()) - .block(block_number.into()) - .await - .map_err(|err| anyhow!(err)); - - Ok(SwapSimulation { - tx, - overrides, - result, - }) - } -} - -fn encode_fake_trade(query: &Query, trade_encoding: TradeEncoding) -> Result { - let (sell_amount, buy_amount) = match trade_encoding { - TradeEncoding::Simple => (query.sell_amount.into(), query.buy_amount), - TradeEncoding::Disadvantageous => match query.kind { - OrderKind::Sell => (query.sell_amount.get(), U256::ZERO), - OrderKind::Buy => ( - query.sell_amount.get().max(U256::from(u128::MAX)), - query.buy_amount, - ), - }, - }; - - let fake_order = OrderData { - sell_token: query.sell_token, - sell_amount, - buy_token: query.buy_token, - buy_amount, - receiver: Some(query.receiver), - valid_to: u32::MAX, - app_data: Default::default(), - fee_amount: U256::ZERO, - kind: query.kind, - partially_fillable: false, - sell_token_balance: query.sell_token_source, - buy_token_balance: query.buy_token_destination, - }; - - let fake_signature = Signature::default_with(SigningScheme::Eip1271); - let encoded_trade = encode_trade( - &fake_order, - &fake_signature, - query.from, - // the tokens set length is small so the linear search is acceptable - query - .tokens - .iter() - .position(|token| token == &query.sell_token) - .context("missing sell token index")?, - query - .tokens - .iter() - .position(|token| token == &query.buy_token) - .context("missing buy token index")?, - match query.kind { - OrderKind::Sell => query.sell_amount.get(), - OrderKind::Buy => query.buy_amount, - }, - ); - - Ok(encoded_trade) -}