From 51ebd32e163a76524644049e0b09153c57f52de4 Mon Sep 17 00:00:00 2001 From: MartinquaXD Date: Wed, 11 Dec 2024 11:43:36 +0000 Subject: [PATCH 1/7] e2e test --- crates/e2e/tests/e2e/quote_verification.rs | 46 +++++++++++++++++----- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/crates/e2e/tests/e2e/quote_verification.rs b/crates/e2e/tests/e2e/quote_verification.rs index 149afbfc7d..1602ee9d15 100644 --- a/crates/e2e/tests/e2e/quote_verification.rs +++ b/crates/e2e/tests/e2e/quote_verification.rs @@ -1,14 +1,8 @@ use { - bigdecimal::{BigDecimal, Zero}, - e2e::{setup::*, tx}, - ethcontract::{H160, U256}, - ethrpc::Web3, - model::{ + bigdecimal::{BigDecimal, Zero}, e2e::{setup::*, tx}, ethcontract::{H160, U256}, ethrpc::Web3, model::{ order::{BuyTokenDestination, OrderKind, SellTokenSource}, quote::{OrderQuoteRequest, OrderQuoteSide, SellAmount}, - }, - number::nonzero::U256 as NonZeroU256, - shared::{ + }, number::nonzero::U256 as NonZeroU256, serde_json::json, shared::{ price_estimation::{ trade_verifier::{ balance_overrides::BalanceOverrides, @@ -20,8 +14,7 @@ use { Verification, }, trade_finding::{Interaction, LegacyTrade, TradeKind}, - }, - std::{str::FromStr, sync::Arc}, + }, std::{str::FromStr, sync::Arc} }; #[tokio::test] @@ -427,4 +420,37 @@ async fn verified_quote_with_simulated_balance(web3: Web3) { .await .unwrap(); assert!(response.verified); + + // Previously quote verification did not set up the trade correctly + // if the user provided pre-interactions. This works now. + let response = services + .submit_quote(&OrderQuoteRequest { + from: H160::zero(), + sell_token: weth.address(), + buy_token: token.address(), + side: OrderQuoteSide::Sell { + sell_amount: SellAmount::BeforeFee { + value: to_wei(1).try_into().unwrap(), + }, + }, + app_data: model::order::OrderCreationAppData::Full { + full: json!({ + "metadata": { + "hooks": { + "pre": [ + { + "target": "0x0000000000000000000000000000000000000000", + "callData": "0x", + "gasLimit": "0" + } + ] + } + } + }).to_string() + }, + ..Default::default() + }) + .await + .unwrap(); + assert!(response.verified); } From bb29f0f2b58a34adabc1f3df45a7c79f9745128d Mon Sep 17 00:00:00 2001 From: MartinquaXD Date: Wed, 11 Dec 2024 11:44:47 +0000 Subject: [PATCH 2/7] fixup --- crates/e2e/tests/e2e/quote_verification.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/crates/e2e/tests/e2e/quote_verification.rs b/crates/e2e/tests/e2e/quote_verification.rs index 1602ee9d15..b0ff67dd4f 100644 --- a/crates/e2e/tests/e2e/quote_verification.rs +++ b/crates/e2e/tests/e2e/quote_verification.rs @@ -1,8 +1,15 @@ use { - bigdecimal::{BigDecimal, Zero}, e2e::{setup::*, tx}, ethcontract::{H160, U256}, ethrpc::Web3, model::{ + bigdecimal::{BigDecimal, Zero}, + e2e::{setup::*, tx}, + ethcontract::{H160, U256}, + ethrpc::Web3, + model::{ order::{BuyTokenDestination, OrderKind, SellTokenSource}, quote::{OrderQuoteRequest, OrderQuoteSide, SellAmount}, - }, number::nonzero::U256 as NonZeroU256, serde_json::json, shared::{ + }, + number::nonzero::U256 as NonZeroU256, + serde_json::json, + shared::{ price_estimation::{ trade_verifier::{ balance_overrides::BalanceOverrides, @@ -14,7 +21,8 @@ use { Verification, }, trade_finding::{Interaction, LegacyTrade, TradeKind}, - }, std::{str::FromStr, sync::Arc} + }, + std::{str::FromStr, sync::Arc}, }; #[tokio::test] @@ -446,7 +454,8 @@ async fn verified_quote_with_simulated_balance(web3: Web3) { ] } } - }).to_string() + }) + .to_string(), }, ..Default::default() }) From 056604998055ac2a94e1dc189fcd3743dc65e2b8 Mon Sep 17 00:00:00 2001 From: MartinquaXD Date: Wed, 11 Dec 2024 11:49:08 +0000 Subject: [PATCH 3/7] Simplify trade setup logic --- crates/contracts/artifacts/Solver.json | 2 +- crates/contracts/artifacts/Trader.json | 2 +- crates/contracts/solidity/Solver.sol | 34 +++++++------------ crates/contracts/solidity/Trader.sol | 22 +++++++----- .../src/price_estimation/trade_verifier.rs | 7 +--- 5 files changed, 28 insertions(+), 39 deletions(-) diff --git a/crates/contracts/artifacts/Solver.json b/crates/contracts/artifacts/Solver.json index 19639cbd96..9658065386 100644 --- a/crates/contracts/artifacts/Solver.json +++ b/crates/contracts/artifacts/Solver.json @@ -1 +1 @@ -{"abi":[{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"countGas","type":"bool"}],"name":"storeBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISettlement","name":"settlementContract","type":"address"},{"internalType":"address payable","name":"trader","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"address","name":"nativeToken","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"bytes","name":"settlementCall","type":"bytes"},{"components":[{"internalType":"bool","name":"enabled","type":"bool"},{"internalType":"address","name":"spardose","type":"address"}],"internalType":"struct Solver.Mock","name":"mock","type":"tuple"}],"name":"swap","outputs":[{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256[]","name":"queriedBalances","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"}],"bytecode":"0x608060405234801561001057600080fd5b506109e0806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806317b86b161461003b5780633bbb2e1d14610065575b600080fd5b61004e61004936600461072c565b61007a565b60405161005c929190610817565b60405180910390f35b610078610073366004610865565b6102aa565b005b60006060333014610111576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b8251156101bf5760208301516040517f66b00f6800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8f811660048301528d81166024830152604482018d90528b811660648301529182166084820152908d16906366b00f689060a401600060405180830381600087803b1580156101a657600080fd5b505af11580156101ba573d6000803e3d6000fd5b505050505b60008673ffffffffffffffffffffffffffffffffffffffff16600060405160006040518083038185875af1925050503d806000811461021a576040519150601f19603f3d011682016040523d82523d6000602084013e61021f565b606091505b505090505061022f88888f6103df565b61023a8d86866104b7565b915061024788888f6103df565b600180548060200260200160405190810160405280929190818152602001828054801561029357602002820191906000526020600020905b81548152602001906001019080831161027f575b505050505090509b509b9950505050505050505050565b60005a9050600173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff861614610377576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa15801561034e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037291906108ac565b610390565b8373ffffffffffffffffffffffffffffffffffffffff16315b8154600181018355600092835260209092209091015581156103d9575a6103b790826108f4565b6103c39061116c61090d565b6000808282546103d3919061090d565b90915550505b50505050565b60005b828110156103d95730633bbb2e1d85858481811061040257610402610920565b9050602002016020810190610417919061094f565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9182166004820152908516602482015260006044820152606401600060405180830381600087803b15801561048c57600080fd5b505af11580156104a0573d6000803e3d6000fd5b5050505080806104af9061096c565b9150506103e2565b6000805a905061051484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505073ffffffffffffffffffffffffffffffffffffffff891692915050610536565b506000545a61052390836108f4565b61052d91906108f4565b95945050505050565b60606105448360008461054b565b9392505050565b606060008473ffffffffffffffffffffffffffffffffffffffff16848460405161057591906109a4565b60006040518083038185875af1925050503d80600081146105b2576040519150601f19603f3d011682016040523d82523d6000602084013e6105b7565b606091505b5092509050806105c957815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146105f357600080fd5b50565b8035610601816105d1565b919050565b60008083601f84011261061857600080fd5b50813567ffffffffffffffff81111561063057600080fd5b6020830191508360208260051b850101111561064b57600080fd5b9250929050565b60008083601f84011261066457600080fd5b50813567ffffffffffffffff81111561067c57600080fd5b60208301915083602082850101111561064b57600080fd5b8035801515811461060157600080fd5b6000604082840312156106b657600080fd5b6040516040810181811067ffffffffffffffff82111715610700577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290508061070f83610694565b8152602083013561071f816105d1565b6020919091015292915050565b60008060008060008060008060008060006101408c8e03121561074e57600080fd5b6107588c356105d1565b8b359a5061076960208d01356105d1565b60208c0135995061077c60408d016105f6565b985060608c0135975061079160808d016105f6565b965067ffffffffffffffff8060a08e013511156107ad57600080fd5b6107bd8e60a08f01358f01610606565b90975095506107ce60c08e016105f6565b94508060e08e013511156107e157600080fd5b506107f28d60e08e01358e01610652565b90935091506108058d6101008e016106a4565b90509295989b509295989b9093969950565b6000604082018483526020604081850152818551808452606086019150828701935060005b818110156108585784518352938301939183019160010161083c565b5090979650505050505050565b60008060006060848603121561087a57600080fd5b8335610885816105d1565b92506020840135610895816105d1565b91506108a360408501610694565b90509250925092565b6000602082840312156108be57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610907576109076108c5565b92915050565b80820180821115610907576109076108c5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561096157600080fd5b8135610544816105d1565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361099d5761099d6108c5565b5060010190565b6000825160005b818110156109c557602081860181015185830152016109ab565b50600092019182525091905056fea164736f6c6343000811000a","deployedBytecode":"0x608060405234801561001057600080fd5b50600436106100365760003560e01c806317b86b161461003b5780633bbb2e1d14610065575b600080fd5b61004e61004936600461072c565b61007a565b60405161005c929190610817565b60405180910390f35b610078610073366004610865565b6102aa565b005b60006060333014610111576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b8251156101bf5760208301516040517f66b00f6800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8f811660048301528d81166024830152604482018d90528b811660648301529182166084820152908d16906366b00f689060a401600060405180830381600087803b1580156101a657600080fd5b505af11580156101ba573d6000803e3d6000fd5b505050505b60008673ffffffffffffffffffffffffffffffffffffffff16600060405160006040518083038185875af1925050503d806000811461021a576040519150601f19603f3d011682016040523d82523d6000602084013e61021f565b606091505b505090505061022f88888f6103df565b61023a8d86866104b7565b915061024788888f6103df565b600180548060200260200160405190810160405280929190818152602001828054801561029357602002820191906000526020600020905b81548152602001906001019080831161027f575b505050505090509b509b9950505050505050505050565b60005a9050600173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff861614610377576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa15801561034e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037291906108ac565b610390565b8373ffffffffffffffffffffffffffffffffffffffff16315b8154600181018355600092835260209092209091015581156103d9575a6103b790826108f4565b6103c39061116c61090d565b6000808282546103d3919061090d565b90915550505b50505050565b60005b828110156103d95730633bbb2e1d85858481811061040257610402610920565b9050602002016020810190610417919061094f565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9182166004820152908516602482015260006044820152606401600060405180830381600087803b15801561048c57600080fd5b505af11580156104a0573d6000803e3d6000fd5b5050505080806104af9061096c565b9150506103e2565b6000805a905061051484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505073ffffffffffffffffffffffffffffffffffffffff891692915050610536565b506000545a61052390836108f4565b61052d91906108f4565b95945050505050565b60606105448360008461054b565b9392505050565b606060008473ffffffffffffffffffffffffffffffffffffffff16848460405161057591906109a4565b60006040518083038185875af1925050503d80600081146105b2576040519150601f19603f3d011682016040523d82523d6000602084013e6105b7565b606091505b5092509050806105c957815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146105f357600080fd5b50565b8035610601816105d1565b919050565b60008083601f84011261061857600080fd5b50813567ffffffffffffffff81111561063057600080fd5b6020830191508360208260051b850101111561064b57600080fd5b9250929050565b60008083601f84011261066457600080fd5b50813567ffffffffffffffff81111561067c57600080fd5b60208301915083602082850101111561064b57600080fd5b8035801515811461060157600080fd5b6000604082840312156106b657600080fd5b6040516040810181811067ffffffffffffffff82111715610700577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290508061070f83610694565b8152602083013561071f816105d1565b6020919091015292915050565b60008060008060008060008060008060006101408c8e03121561074e57600080fd5b6107588c356105d1565b8b359a5061076960208d01356105d1565b60208c0135995061077c60408d016105f6565b985060608c0135975061079160808d016105f6565b965067ffffffffffffffff8060a08e013511156107ad57600080fd5b6107bd8e60a08f01358f01610606565b90975095506107ce60c08e016105f6565b94508060e08e013511156107e157600080fd5b506107f28d60e08e01358e01610652565b90935091506108058d6101008e016106a4565b90509295989b509295989b9093969950565b6000604082018483526020604081850152818551808452606086019150828701935060005b818110156108585784518352938301939183019160010161083c565b5090979650505050505050565b60008060006060848603121561087a57600080fd5b8335610885816105d1565b92506020840135610895816105d1565b91506108a360408501610694565b90509250925092565b6000602082840312156108be57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115610907576109076108c5565b92915050565b80820180821115610907576109076108c5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561096157600080fd5b8135610544816105d1565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361099d5761099d6108c5565b5060010190565b6000825160005b818110156109c557602081860181015185830152016109ab565b50600092019182525091905056fea164736f6c6343000811000a","devdoc":{"methods":{}},"userdoc":{"methods":{}}} +{"abi":[{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"countGas","type":"bool"}],"name":"storeBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISettlement","name":"settlementContract","type":"address"},{"internalType":"address payable","name":"trader","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"address","name":"nativeToken","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"bytes","name":"settlementCall","type":"bytes"},{"internalType":"address","name":"spardose","type":"address"}],"name":"swap","outputs":[{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256[]","name":"queriedBalances","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"}],"bytecode":"0x608060405234801561001057600080fd5b50610942806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806311c737681461003b5780633bbb2e1d14610065575b600080fd5b61004e610049366004610686565b61007a565b60405161005c929190610770565b60405180910390f35b6100786100733660046107be565b61029c565b005b60006060333014610111576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b6040517f66b00f6800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8e811660048301528c81166024830152604482018c90528a8116606483015284811660848301528d16906366b00f689060a401600060405180830381600087803b15801561019957600080fd5b505af11580156101ad573d6000803e3d6000fd5b5050505060008673ffffffffffffffffffffffffffffffffffffffff16600060405160006040518083038185875af1925050503d806000811461020c576040519150601f19603f3d011682016040523d82523d6000602084013e610211565b606091505b505090505061022188888f6103d1565b61022c8d86866104a9565b915061023988888f6103d1565b600180548060200260200160405190810160405280929190818152602001828054801561028557602002820191906000526020600020905b815481526020019060010190808311610271575b505050505090509b509b9950505050505050505050565b60005a9050600173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff861614610369576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa158015610340573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610364919061080e565b610382565b8373ffffffffffffffffffffffffffffffffffffffff16315b8154600181018355600092835260209092209091015581156103cb575a6103a99082610856565b6103b59061116c61086f565b6000808282546103c5919061086f565b90915550505b50505050565b60005b828110156103cb5730633bbb2e1d8585848181106103f4576103f4610882565b905060200201602081019061040991906108b1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9182166004820152908516602482015260006044820152606401600060405180830381600087803b15801561047e57600080fd5b505af1158015610492573d6000803e3d6000fd5b5050505080806104a1906108ce565b9150506103d4565b6000805a905061050684848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505073ffffffffffffffffffffffffffffffffffffffff891692915050610528565b506000545a6105159083610856565b61051f9190610856565b95945050505050565b60606105368360008461053d565b9392505050565b606060008473ffffffffffffffffffffffffffffffffffffffff1684846040516105679190610906565b60006040518083038185875af1925050503d80600081146105a4576040519150601f19603f3d011682016040523d82523d6000602084013e6105a9565b606091505b5092509050806105bb57815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146105e557600080fd5b50565b80356105f3816105c3565b919050565b60008083601f84011261060a57600080fd5b50813567ffffffffffffffff81111561062257600080fd5b6020830191508360208260051b850101111561063d57600080fd5b9250929050565b60008083601f84011261065657600080fd5b50813567ffffffffffffffff81111561066e57600080fd5b60208301915083602082850101111561063d57600080fd5b60008060008060008060008060008060006101208c8e0312156106a857600080fd5b6106b28c356105c3565b8b359a506106c360208d01356105c3565b60208c013599506106d660408d016105e8565b985060608c013597506106eb60808d016105e8565b965067ffffffffffffffff8060a08e0135111561070757600080fd5b6107178e60a08f01358f016105f8565b909750955061072860c08e016105e8565b94508060e08e0135111561073b57600080fd5b5061074c8d60e08e01358e01610644565b909350915061075e6101008d016105e8565b90509295989b509295989b9093969950565b6000604082018483526020604081850152818551808452606086019150828701935060005b818110156107b157845183529383019391830191600101610795565b5090979650505050505050565b6000806000606084860312156107d357600080fd5b83356107de816105c3565b925060208401356107ee816105c3565b91506040840135801515811461080357600080fd5b809150509250925092565b60006020828403121561082057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561086957610869610827565b92915050565b8082018082111561086957610869610827565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156108c357600080fd5b8135610536816105c3565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036108ff576108ff610827565b5060010190565b6000825160005b81811015610927576020818601810151858301520161090d565b50600092019182525091905056fea164736f6c6343000811000a","deployedBytecode":"0x608060405234801561001057600080fd5b50600436106100365760003560e01c806311c737681461003b5780633bbb2e1d14610065575b600080fd5b61004e610049366004610686565b61007a565b60405161005c929190610770565b60405180910390f35b6100786100733660046107be565b61029c565b005b60006060333014610111576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b6040517f66b00f6800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8e811660048301528c81166024830152604482018c90528a8116606483015284811660848301528d16906366b00f689060a401600060405180830381600087803b15801561019957600080fd5b505af11580156101ad573d6000803e3d6000fd5b5050505060008673ffffffffffffffffffffffffffffffffffffffff16600060405160006040518083038185875af1925050503d806000811461020c576040519150601f19603f3d011682016040523d82523d6000602084013e610211565b606091505b505090505061022188888f6103d1565b61022c8d86866104a9565b915061023988888f6103d1565b600180548060200260200160405190810160405280929190818152602001828054801561028557602002820191906000526020600020905b815481526020019060010190808311610271575b505050505090509b509b9950505050505050505050565b60005a9050600173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff861614610369576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa158015610340573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610364919061080e565b610382565b8373ffffffffffffffffffffffffffffffffffffffff16315b8154600181018355600092835260209092209091015581156103cb575a6103a99082610856565b6103b59061116c61086f565b6000808282546103c5919061086f565b90915550505b50505050565b60005b828110156103cb5730633bbb2e1d8585848181106103f4576103f4610882565b905060200201602081019061040991906108b1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9182166004820152908516602482015260006044820152606401600060405180830381600087803b15801561047e57600080fd5b505af1158015610492573d6000803e3d6000fd5b5050505080806104a1906108ce565b9150506103d4565b6000805a905061050684848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505073ffffffffffffffffffffffffffffffffffffffff891692915050610528565b506000545a6105159083610856565b61051f9190610856565b95945050505050565b60606105368360008461053d565b9392505050565b606060008473ffffffffffffffffffffffffffffffffffffffff1684846040516105679190610906565b60006040518083038185875af1925050503d80600081146105a4576040519150601f19603f3d011682016040523d82523d6000602084013e6105a9565b606091505b5092509050806105bb57815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146105e557600080fd5b50565b80356105f3816105c3565b919050565b60008083601f84011261060a57600080fd5b50813567ffffffffffffffff81111561062257600080fd5b6020830191508360208260051b850101111561063d57600080fd5b9250929050565b60008083601f84011261065657600080fd5b50813567ffffffffffffffff81111561066e57600080fd5b60208301915083602082850101111561063d57600080fd5b60008060008060008060008060008060006101208c8e0312156106a857600080fd5b6106b28c356105c3565b8b359a506106c360208d01356105c3565b60208c013599506106d660408d016105e8565b985060608c013597506106eb60808d016105e8565b965067ffffffffffffffff8060a08e0135111561070757600080fd5b6107178e60a08f01358f016105f8565b909750955061072860c08e016105e8565b94508060e08e0135111561073b57600080fd5b5061074c8d60e08e01358e01610644565b909350915061075e6101008d016105e8565b90509295989b509295989b9093969950565b6000604082018483526020604081850152818551808452606086019150828701935060005b818110156107b157845183529383019391830191600101610795565b5090979650505050505050565b6000806000606084860312156107d357600080fd5b83356107de816105c3565b925060208401356107ee816105c3565b91506040840135801515811461080357600080fd5b809150509250925092565b60006020828403121561082057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561086957610869610827565b92915050565b8082018082111561086957610869610827565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156108c357600080fd5b8135610536816105c3565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036108ff576108ff610827565b5060010190565b6000825160005b81811015610927576020818601810151858301520161090d565b50600092019182525091905056fea164736f6c6343000811000a","devdoc":{"methods":{}},"userdoc":{"methods":{}}} diff --git a/crates/contracts/artifacts/Trader.json b/crates/contracts/artifacts/Trader.json index eef29787b2..54a0a01cf2 100644 --- a/crates/contracts/artifacts/Trader.json +++ b/crates/contracts/artifacts/Trader.json @@ -1 +1 @@ -{"abi":[{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"contract ISettlement","name":"settlementContract","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"address","name":"nativeToken","type":"address"},{"internalType":"address","name":"spardose","type":"address"}],"name":"prepareSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}],"bytecode":"0x608060405234801561001057600080fd5b50610ba4806100206000396000f3fe60806040526004361061002d5760003560e01c80631626ba7e1461008657806366b00f68146100fe57610034565b3661003457005b600061007c6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062010000939250506101209050565b9050805160208201f35b34801561009257600080fd5b506100c96100a13660046109cd565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010a57600080fd5b5061011e610119366004610a6e565b6101a2565b005b606060008373ffffffffffffffffffffffffffffffffffffffff16836040516101499190610ad6565b600060405180830381855af49150503d8060008114610184576040519150601f19603f3d011682016040523d82523d6000602084013e610189565b606091505b50925090508061019b57815160208301fd5b5092915050565b6101aa6107c5565b1561023c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e6365000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610385576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa1580156102dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103009190610b05565b9050838110156103835760006103168286610b1e565b9050804710610381578373ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561036757600080fd5b505af115801561037b573d6000803e3d6000fd5b50505050505b505b505b60008473ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e308873ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104139190610b58565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa158015610483573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a79190610b05565b9050838110156105f2576105428673ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105239190610b58565b73ffffffffffffffffffffffffffffffffffffffff8716906000610800565b6105f28673ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610590573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b49190610b58565b73ffffffffffffffffffffffffffffffffffffffff8716907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610800565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa15801561065f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106839190610b05565b9050848110156107bc5773ffffffffffffffffffffffffffffffffffffffff831663494666b6876106b48489610b1e565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b15801561071f57600080fd5b505af1925050508015610730575060015b6107bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f74726164657220646f6573206e6f74206861766520656e6f7567682073656c6c60448201527f20746f6b656e00000000000000000000000000000000000000000000000000006064820152608401610233565b50505050505050565b6000806107f360017f7f36ecad6e52bbe2ff70badce94360882c890b7877b16131c08eabfc635c9735610b1e565b8054600190915592915050565b6040805173ffffffffffffffffffffffffffffffffffffffff848116602483015260448083018590528351808403909101815260649092019092526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052906000906108939086168361090b565b905061089e81610920565b610904576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f5361666545524332303a20617070726f76616c206661696c65640000000000006044820152606401610233565b5050505050565b606061091983600084610947565b9392505050565b60008151600014806109415750818060200190518101906109419190610b75565b92915050565b606060008473ffffffffffffffffffffffffffffffffffffffff1684846040516109719190610ad6565b60006040518083038185875af1925050503d80600081146109ae576040519150601f19603f3d011682016040523d82523d6000602084013e6109b3565b606091505b5092509050806109c557815160208301fd5b509392505050565b6000806000604084860312156109e257600080fd5b83359250602084013567ffffffffffffffff80821115610a0157600080fd5b818601915086601f830112610a1557600080fd5b813581811115610a2457600080fd5b876020828501011115610a3657600080fd5b6020830194508093505050509250925092565b73ffffffffffffffffffffffffffffffffffffffff81168114610a6b57600080fd5b50565b600080600080600060a08688031215610a8657600080fd5b8535610a9181610a49565b94506020860135610aa181610a49565b9350604086013592506060860135610ab881610a49565b91506080860135610ac881610a49565b809150509295509295909350565b6000825160005b81811015610af75760208186018101518583015201610add565b506000920191825250919050565b600060208284031215610b1757600080fd5b5051919050565b81810381811115610941577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600060208284031215610b6a57600080fd5b815161091981610a49565b600060208284031215610b8757600080fd5b8151801515811461091957600080fdfea164736f6c6343000811000a","deployedBytecode":"0x60806040526004361061002d5760003560e01c80631626ba7e1461008657806366b00f68146100fe57610034565b3661003457005b600061007c6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062010000939250506101209050565b9050805160208201f35b34801561009257600080fd5b506100c96100a13660046109cd565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010a57600080fd5b5061011e610119366004610a6e565b6101a2565b005b606060008373ffffffffffffffffffffffffffffffffffffffff16836040516101499190610ad6565b600060405180830381855af49150503d8060008114610184576040519150601f19603f3d011682016040523d82523d6000602084013e610189565b606091505b50925090508061019b57815160208301fd5b5092915050565b6101aa6107c5565b1561023c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e6365000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610385576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa1580156102dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103009190610b05565b9050838110156103835760006103168286610b1e565b9050804710610381578373ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561036757600080fd5b505af115801561037b573d6000803e3d6000fd5b50505050505b505b505b60008473ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e308873ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104139190610b58565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa158015610483573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a79190610b05565b9050838110156105f2576105428673ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105239190610b58565b73ffffffffffffffffffffffffffffffffffffffff8716906000610800565b6105f28673ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610590573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b49190610b58565b73ffffffffffffffffffffffffffffffffffffffff8716907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610800565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa15801561065f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106839190610b05565b9050848110156107bc5773ffffffffffffffffffffffffffffffffffffffff831663494666b6876106b48489610b1e565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b15801561071f57600080fd5b505af1925050508015610730575060015b6107bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f74726164657220646f6573206e6f74206861766520656e6f7567682073656c6c60448201527f20746f6b656e00000000000000000000000000000000000000000000000000006064820152608401610233565b50505050505050565b6000806107f360017f7f36ecad6e52bbe2ff70badce94360882c890b7877b16131c08eabfc635c9735610b1e565b8054600190915592915050565b6040805173ffffffffffffffffffffffffffffffffffffffff848116602483015260448083018590528351808403909101815260649092019092526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b300000000000000000000000000000000000000000000000000000000179052906000906108939086168361090b565b905061089e81610920565b610904576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f5361666545524332303a20617070726f76616c206661696c65640000000000006044820152606401610233565b5050505050565b606061091983600084610947565b9392505050565b60008151600014806109415750818060200190518101906109419190610b75565b92915050565b606060008473ffffffffffffffffffffffffffffffffffffffff1684846040516109719190610ad6565b60006040518083038185875af1925050503d80600081146109ae576040519150601f19603f3d011682016040523d82523d6000602084013e6109b3565b606091505b5092509050806109c557815160208301fd5b509392505050565b6000806000604084860312156109e257600080fd5b83359250602084013567ffffffffffffffff80821115610a0157600080fd5b818601915086601f830112610a1557600080fd5b813581811115610a2457600080fd5b876020828501011115610a3657600080fd5b6020830194508093505050509250925092565b73ffffffffffffffffffffffffffffffffffffffff81168114610a6b57600080fd5b50565b600080600080600060a08688031215610a8657600080fd5b8535610a9181610a49565b94506020860135610aa181610a49565b9350604086013592506060860135610ab881610a49565b91506080860135610ac881610a49565b809150509295509295909350565b6000825160005b81811015610af75760208186018101518583015201610add565b506000920191825250919050565b600060208284031215610b1757600080fd5b5051919050565b81810381811115610941577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600060208284031215610b6a57600080fd5b815161091981610a49565b600060208284031215610b8757600080fd5b8151801515811461091957600080fdfea164736f6c6343000811000a","devdoc":{"methods":{}},"userdoc":{"methods":{}}} +{"abi":[{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"contract ISettlement","name":"settlementContract","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"address","name":"nativeToken","type":"address"},{"internalType":"address","name":"spardose","type":"address"}],"name":"prepareSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}],"bytecode":"0x608060405234801561001057600080fd5b50610aad806100206000396000f3fe60806040526004361061002d5760003560e01c80631626ba7e1461008657806366b00f68146100fe57610034565b3661003457005b600061007c6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062010000939250506101209050565b9050805160208201f35b34801561009257600080fd5b506100c96100a13660046108c9565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010a57600080fd5b5061011e61011936600461096a565b6101a2565b005b606060008373ffffffffffffffffffffffffffffffffffffffff168360405161014991906109d2565b600060405180830381855af49150503d8060008114610184576040519150601f19603f3d011682016040523d82523d6000602084013e610189565b606091505b50925090508061019b57815160208301fd5b5092915050565b6101aa61088e565b1561023b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e63650000000000000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361037e576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa1580156102db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ff9190610a01565b90508381101561037c5760006103158286610a1a565b905080471061037a578373ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561036657600080fd5b505af193505050508015610378575060015b505b505b505b60008473ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e308873ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040c9190610a5a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa15801561047c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a09190610a01565b905083811015610745578473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610511573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105359190610a5a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152600060248201526044016020604051808303816000875af19250505080156105e1575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526105de91810190610a7e565b60015b156105e857505b8473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190610a5a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff90911660048201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248201526044016020604051808303816000875af192505050801561073e575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261073b91810190610a7e565b60015b1561074557505b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa1580156107b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d69190610a01565b9050848110156108855773ffffffffffffffffffffffffffffffffffffffff831663494666b6876108078489610a1a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b15801561087257600080fd5b505af1925050508015610883575060015b505b50505050505050565b6000806108bc60017f7f36ecad6e52bbe2ff70badce94360882c890b7877b16131c08eabfc635c9735610a1a565b8054600190915592915050565b6000806000604084860312156108de57600080fd5b83359250602084013567ffffffffffffffff808211156108fd57600080fd5b818601915086601f83011261091157600080fd5b81358181111561092057600080fd5b87602082850101111561093257600080fd5b6020830194508093505050509250925092565b73ffffffffffffffffffffffffffffffffffffffff8116811461096757600080fd5b50565b600080600080600060a0868803121561098257600080fd5b853561098d81610945565b9450602086013561099d81610945565b93506040860135925060608601356109b481610945565b915060808601356109c481610945565b809150509295509295909350565b6000825160005b818110156109f357602081860181015185830152016109d9565b506000920191825250919050565b600060208284031215610a1357600080fd5b5051919050565b81810381811115610a54577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b600060208284031215610a6c57600080fd5b8151610a7781610945565b9392505050565b600060208284031215610a9057600080fd5b81518015158114610a7757600080fdfea164736f6c6343000811000a","deployedBytecode":"0x60806040526004361061002d5760003560e01c80631626ba7e1461008657806366b00f68146100fe57610034565b3661003457005b600061007c6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062010000939250506101209050565b9050805160208201f35b34801561009257600080fd5b506100c96100a13660046108c9565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010a57600080fd5b5061011e61011936600461096a565b6101a2565b005b606060008373ffffffffffffffffffffffffffffffffffffffff168360405161014991906109d2565b600060405180830381855af49150503d8060008114610184576040519150601f19603f3d011682016040523d82523d6000602084013e610189565b606091505b50925090508061019b57815160208301fd5b5092915050565b6101aa61088e565b1561023b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e63650000000000000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361037e576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa1580156102db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ff9190610a01565b90508381101561037c5760006103158286610a1a565b905080471061037a578373ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561036657600080fd5b505af193505050508015610378575060015b505b505b505b60008473ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e308873ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040c9190610a5a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa15801561047c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a09190610a01565b905083811015610745578473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610511573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105359190610a5a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152600060248201526044016020604051808303816000875af19250505080156105e1575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526105de91810190610a7e565b60015b156105e857505b8473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190610a5a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff90911660048201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248201526044016020604051808303816000875af192505050801561073e575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261073b91810190610a7e565b60015b1561074557505b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa1580156107b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d69190610a01565b9050848110156108855773ffffffffffffffffffffffffffffffffffffffff831663494666b6876108078489610a1a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b15801561087257600080fd5b505af1925050508015610883575060015b505b50505050505050565b6000806108bc60017f7f36ecad6e52bbe2ff70badce94360882c890b7877b16131c08eabfc635c9735610a1a565b8054600190915592915050565b6000806000604084860312156108de57600080fd5b83359250602084013567ffffffffffffffff808211156108fd57600080fd5b818601915086601f83011261091157600080fd5b81358181111561092057600080fd5b87602082850101111561093257600080fd5b6020830194508093505050509250925092565b73ffffffffffffffffffffffffffffffffffffffff8116811461096757600080fd5b50565b600080600080600060a0868803121561098257600080fd5b853561098d81610945565b9450602086013561099d81610945565b93506040860135925060608601356109b481610945565b915060808601356109c481610945565b809150509295509295909350565b6000825160005b818110156109f357602081860181015185830152016109d9565b506000920191825250919050565b600060208284031215610a1357600080fd5b5051919050565b81810381811115610a54577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b600060208284031215610a6c57600080fd5b8151610a7781610945565b9392505050565b600060208284031215610a9057600080fd5b81518015158114610a7757600080fdfea164736f6c6343000811000a","devdoc":{"methods":{}},"userdoc":{"methods":{}}} diff --git a/crates/contracts/solidity/Solver.sol b/crates/contracts/solidity/Solver.sol index cf6aea29ac..e1986e9360 100644 --- a/crates/contracts/solidity/Solver.sol +++ b/crates/contracts/solidity/Solver.sol @@ -17,11 +17,6 @@ contract Solver { using Caller for *; using Math for *; - struct Mock { - bool enabled; - address spardose; - } - uint256 private _simulationOverhead; uint256[] private _queriedBalances; @@ -39,10 +34,7 @@ contract Solver { /// @param tokens - list of tokens used in the trade /// @param receiver - address receiving the bought tokens /// @param settlementCall - the calldata of the `settle()` call - /// @param mock - mocking configuration for the simulation; this controls - /// whether things like ETH wrapping, setting allowance and - /// pre-funding should be done on behalf of the user to support - /// quote verification for users who aren't ready to swap. + /// @param spardose - contract to provide missing funds with /// /// @return gasUsed - gas used for the `settle()` call /// @return queriedBalances - list of balances stored during the simulation @@ -55,25 +47,23 @@ contract Solver { address[] calldata tokens, address payable receiver, bytes calldata settlementCall, - Mock memory mock + address spardose ) external returns ( uint256 gasUsed, uint256[] memory queriedBalances ) { require(msg.sender == address(this), "only simulation logic is allowed to call 'swap' function"); - if (mock.enabled) { - // Prepare the trade in the context of the trader so we are allowed - // to set approvals and things like that. - Trader(trader) - .prepareSwap( - settlementContract, - sellToken, - sellAmount, - nativeToken, - mock.spardose - ); - } + // Prepare the trade in the context of the trader so we are allowed + // to set approvals and things like that. + Trader(trader) + .prepareSwap( + settlementContract, + sellToken, + sellAmount, + nativeToken, + spardose + ); // Warm the storage for sending ETH to smart contract addresses. // We allow this call to revert becaues it was either unnecessary in the first place diff --git a/crates/contracts/solidity/Trader.sol b/crates/contracts/solidity/Trader.sol index 695bcdd4f1..7b95e3d96d 100644 --- a/crates/contracts/solidity/Trader.sol +++ b/crates/contracts/solidity/Trader.sol @@ -64,6 +64,12 @@ contract Trader { /// @dev Executes needed actions on behalf of the trader to make the trade possible. /// (e.g. wrapping ETH, setting approvals, and funding the account) + /// To support cases where the user's pre-interactions set up the trade + /// themselves (e.g. get tokens by unstaking) AND cases where we need to + /// set up everything for the trade we catch all relevant reverts here. + /// At the end of the function we can assume that all necessary pre-conditions + /// are met. If that is not the case the simulation will simply fail at a later + /// point in time anyway. /// @param settlementContract - pass in settlement contract because it does not have /// a stable address in tests. /// @param sellToken - token being sold by the trade @@ -91,7 +97,8 @@ contract Trader { // 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}(); + try INativeERC20(nativeToken).deposit{value: amountToWrap}() {} + catch {} } } } @@ -104,8 +111,10 @@ contract Trader { // We first reset the allowance to 0 since some ERC20 tokens (e.g. USDT) // require that due to this attack: // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 - IERC20(sellToken).safeApprove(address(settlementContract.vaultRelayer()), 0); - IERC20(sellToken).safeApprove(address(settlementContract.vaultRelayer()), type(uint256).max); + try IERC20(sellToken).approve(address(settlementContract.vaultRelayer()), 0) {} + catch {} + try IERC20(sellToken).approve(address(settlementContract.vaultRelayer()), type(uint256).max) {} + catch {} } // Ensure that the user has sufficient sell token balance. If not, request some @@ -114,12 +123,7 @@ contract Trader { uint256 sellBalance = IERC20(sellToken).balanceOf(address(this)); if (sellBalance < sellAmount) { try Spardose(spardose).requestFunds(sellToken, sellAmount - sellBalance) {} - catch { - // The trader does not have sufficient sell token balance, and the - // piggy bank pre-fund failed, as balance overrides are not available. - // Revert with a helpful message. - revert("trader does not have enough sell token"); - } + catch {} } } diff --git a/crates/shared/src/price_estimation/trade_verifier.rs b/crates/shared/src/price_estimation/trade_verifier.rs index 496cecdd4f..7580afdfca 100644 --- a/crates/shared/src/price_estimation/trade_verifier.rs +++ b/crates/shared/src/price_estimation/trade_verifier.rs @@ -161,11 +161,6 @@ impl TradeVerifier { OrderKind::Buy => *out_amount, }; - // Only enable additional mocking (approvals, native token wrapping, - // balance overrides) if the user did not provide pre-interactions. If - // the user did provide pre-interactions, it's reasonable to assume that - // they will set up all the necessary details of the trade. - let mock_enabled = verification.pre_interactions.is_empty(); let simulation = solver .methods() .swap( @@ -177,7 +172,7 @@ impl TradeVerifier { tokens.clone(), verification.receiver, Bytes(settlement.data.unwrap().0), - (mock_enabled, Self::SPARDOSE), + Self::SPARDOSE, ) .tx; From d3eefedee33b687c357add6168df77031ff1a61b Mon Sep 17 00:00:00 2001 From: MartinquaXD Date: Fri, 13 Dec 2024 11:11:46 +0000 Subject: [PATCH 4/7] Improve solution --- crates/contracts/artifacts/Solver.json | 2 +- crates/contracts/artifacts/Trader.json | 2 +- crates/contracts/solidity/Solver.sol | 46 +++++++++--------- crates/contracts/solidity/Trader.sol | 17 +++---- .../src/price_estimation/trade_verifier.rs | 48 +++++++++++++------ 5 files changed, 68 insertions(+), 47 deletions(-) diff --git a/crates/contracts/artifacts/Solver.json b/crates/contracts/artifacts/Solver.json index 9658065386..0843bb5e94 100644 --- a/crates/contracts/artifacts/Solver.json +++ b/crates/contracts/artifacts/Solver.json @@ -1 +1 @@ -{"abi":[{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"countGas","type":"bool"}],"name":"storeBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISettlement","name":"settlementContract","type":"address"},{"internalType":"address payable","name":"trader","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"address","name":"nativeToken","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"bytes","name":"settlementCall","type":"bytes"},{"internalType":"address","name":"spardose","type":"address"}],"name":"swap","outputs":[{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256[]","name":"queriedBalances","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"}],"bytecode":"0x608060405234801561001057600080fd5b50610942806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806311c737681461003b5780633bbb2e1d14610065575b600080fd5b61004e610049366004610686565b61007a565b60405161005c929190610770565b60405180910390f35b6100786100733660046107be565b61029c565b005b60006060333014610111576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b6040517f66b00f6800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8e811660048301528c81166024830152604482018c90528a8116606483015284811660848301528d16906366b00f689060a401600060405180830381600087803b15801561019957600080fd5b505af11580156101ad573d6000803e3d6000fd5b5050505060008673ffffffffffffffffffffffffffffffffffffffff16600060405160006040518083038185875af1925050503d806000811461020c576040519150601f19603f3d011682016040523d82523d6000602084013e610211565b606091505b505090505061022188888f6103d1565b61022c8d86866104a9565b915061023988888f6103d1565b600180548060200260200160405190810160405280929190818152602001828054801561028557602002820191906000526020600020905b815481526020019060010190808311610271575b505050505090509b509b9950505050505050505050565b60005a9050600173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff861614610369576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa158015610340573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610364919061080e565b610382565b8373ffffffffffffffffffffffffffffffffffffffff16315b8154600181018355600092835260209092209091015581156103cb575a6103a99082610856565b6103b59061116c61086f565b6000808282546103c5919061086f565b90915550505b50505050565b60005b828110156103cb5730633bbb2e1d8585848181106103f4576103f4610882565b905060200201602081019061040991906108b1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9182166004820152908516602482015260006044820152606401600060405180830381600087803b15801561047e57600080fd5b505af1158015610492573d6000803e3d6000fd5b5050505080806104a1906108ce565b9150506103d4565b6000805a905061050684848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505073ffffffffffffffffffffffffffffffffffffffff891692915050610528565b506000545a6105159083610856565b61051f9190610856565b95945050505050565b60606105368360008461053d565b9392505050565b606060008473ffffffffffffffffffffffffffffffffffffffff1684846040516105679190610906565b60006040518083038185875af1925050503d80600081146105a4576040519150601f19603f3d011682016040523d82523d6000602084013e6105a9565b606091505b5092509050806105bb57815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146105e557600080fd5b50565b80356105f3816105c3565b919050565b60008083601f84011261060a57600080fd5b50813567ffffffffffffffff81111561062257600080fd5b6020830191508360208260051b850101111561063d57600080fd5b9250929050565b60008083601f84011261065657600080fd5b50813567ffffffffffffffff81111561066e57600080fd5b60208301915083602082850101111561063d57600080fd5b60008060008060008060008060008060006101208c8e0312156106a857600080fd5b6106b28c356105c3565b8b359a506106c360208d01356105c3565b60208c013599506106d660408d016105e8565b985060608c013597506106eb60808d016105e8565b965067ffffffffffffffff8060a08e0135111561070757600080fd5b6107178e60a08f01358f016105f8565b909750955061072860c08e016105e8565b94508060e08e0135111561073b57600080fd5b5061074c8d60e08e01358e01610644565b909350915061075e6101008d016105e8565b90509295989b509295989b9093969950565b6000604082018483526020604081850152818551808452606086019150828701935060005b818110156107b157845183529383019391830191600101610795565b5090979650505050505050565b6000806000606084860312156107d357600080fd5b83356107de816105c3565b925060208401356107ee816105c3565b91506040840135801515811461080357600080fd5b809150509250925092565b60006020828403121561082057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561086957610869610827565b92915050565b8082018082111561086957610869610827565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156108c357600080fd5b8135610536816105c3565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036108ff576108ff610827565b5060010190565b6000825160005b81811015610927576020818601810151858301520161090d565b50600092019182525091905056fea164736f6c6343000811000a","deployedBytecode":"0x608060405234801561001057600080fd5b50600436106100365760003560e01c806311c737681461003b5780633bbb2e1d14610065575b600080fd5b61004e610049366004610686565b61007a565b60405161005c929190610770565b60405180910390f35b6100786100733660046107be565b61029c565b005b60006060333014610111576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b6040517f66b00f6800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8e811660048301528c81166024830152604482018c90528a8116606483015284811660848301528d16906366b00f689060a401600060405180830381600087803b15801561019957600080fd5b505af11580156101ad573d6000803e3d6000fd5b5050505060008673ffffffffffffffffffffffffffffffffffffffff16600060405160006040518083038185875af1925050503d806000811461020c576040519150601f19603f3d011682016040523d82523d6000602084013e610211565b606091505b505090505061022188888f6103d1565b61022c8d86866104a9565b915061023988888f6103d1565b600180548060200260200160405190810160405280929190818152602001828054801561028557602002820191906000526020600020905b815481526020019060010190808311610271575b505050505090509b509b9950505050505050505050565b60005a9050600173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff861614610369576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa158015610340573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610364919061080e565b610382565b8373ffffffffffffffffffffffffffffffffffffffff16315b8154600181018355600092835260209092209091015581156103cb575a6103a99082610856565b6103b59061116c61086f565b6000808282546103c5919061086f565b90915550505b50505050565b60005b828110156103cb5730633bbb2e1d8585848181106103f4576103f4610882565b905060200201602081019061040991906108b1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9182166004820152908516602482015260006044820152606401600060405180830381600087803b15801561047e57600080fd5b505af1158015610492573d6000803e3d6000fd5b5050505080806104a1906108ce565b9150506103d4565b6000805a905061050684848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505073ffffffffffffffffffffffffffffffffffffffff891692915050610528565b506000545a6105159083610856565b61051f9190610856565b95945050505050565b60606105368360008461053d565b9392505050565b606060008473ffffffffffffffffffffffffffffffffffffffff1684846040516105679190610906565b60006040518083038185875af1925050503d80600081146105a4576040519150601f19603f3d011682016040523d82523d6000602084013e6105a9565b606091505b5092509050806105bb57815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146105e557600080fd5b50565b80356105f3816105c3565b919050565b60008083601f84011261060a57600080fd5b50813567ffffffffffffffff81111561062257600080fd5b6020830191508360208260051b850101111561063d57600080fd5b9250929050565b60008083601f84011261065657600080fd5b50813567ffffffffffffffff81111561066e57600080fd5b60208301915083602082850101111561063d57600080fd5b60008060008060008060008060008060006101208c8e0312156106a857600080fd5b6106b28c356105c3565b8b359a506106c360208d01356105c3565b60208c013599506106d660408d016105e8565b985060608c013597506106eb60808d016105e8565b965067ffffffffffffffff8060a08e0135111561070757600080fd5b6107178e60a08f01358f016105f8565b909750955061072860c08e016105e8565b94508060e08e0135111561073b57600080fd5b5061074c8d60e08e01358e01610644565b909350915061075e6101008d016105e8565b90509295989b509295989b9093969950565b6000604082018483526020604081850152818551808452606086019150828701935060005b818110156107b157845183529383019391830191600101610795565b5090979650505050505050565b6000806000606084860312156107d357600080fd5b83356107de816105c3565b925060208401356107ee816105c3565b91506040840135801515811461080357600080fd5b809150509250925092565b60006020828403121561082057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561086957610869610827565b92915050565b8082018082111561086957610869610827565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156108c357600080fd5b8135610536816105c3565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036108ff576108ff610827565b5060010190565b6000825160005b81811015610927576020818601810151858301520161090d565b50600092019182525091905056fea164736f6c6343000811000a","devdoc":{"methods":{}},"userdoc":{"methods":{}}} +{"abi":[{"inputs":[{"internalType":"contract Trader","name":"trader","type":"address"},{"internalType":"contract ISettlement","name":"settlementContract","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"address","name":"nativeToken","type":"address"},{"internalType":"address","name":"spardose","type":"address"}],"name":"ensureTradePreconditions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"countGas","type":"bool"}],"name":"storeBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISettlement","name":"settlementContract","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"bytes","name":"settlementCall","type":"bytes"}],"name":"swap","outputs":[{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256[]","name":"queriedBalances","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"}],"bytecode":"0x608060405234801561001057600080fd5b50610997806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80631d47e7f4146100465780632582edb4146100705780633bbb2e1d14610085575b600080fd5b61005961005436600461068a565b610098565b60405161006792919061074c565b60405180910390f35b61008361007e36600461079a565b610215565b005b610083610093366004610813565b6102e5565b6000606033301461012f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b60008573ffffffffffffffffffffffffffffffffffffffff16600060405160006040518083038185875af1925050503d806000811461018a576040519150601f19603f3d011682016040523d82523d6000602084013e61018f565b606091505b505090505061019f87878a61041a565b6101aa8885856104f2565b91506101b787878a61041a565b600180548060200260200160405190810160405280929190818152602001828054801561020357602002820191906000526020600020905b8154815260200190600101908083116101ef575b50505050509050965096945050505050565b60005a6040517f542eb77d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152878116602483015260448201879052858116606483015284811660848301529192509088169063542eb77d9060a401600060405180830381600087803b1580156102a457600080fd5b505af11580156102b8573d6000803e3d6000fd5b505050505a6102c79082610892565b6000808282546102d791906108ab565b909155505050505050505050565b60005a9050600173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff8616146103b2576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa158015610389573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ad91906108be565b6103cb565b8373ffffffffffffffffffffffffffffffffffffffff16315b815460018101835560009283526020909220909101558115610414575a6103f29082610892565b6103fe9061116c6108ab565b60008082825461040e91906108ab565b90915550505b50505050565b60005b828110156104145730633bbb2e1d85858481811061043d5761043d6108d7565b90506020020160208101906104529190610906565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9182166004820152908516602482015260006044820152606401600060405180830381600087803b1580156104c757600080fd5b505af11580156104db573d6000803e3d6000fd5b5050505080806104ea90610923565b91505061041d565b6000805a905061054f84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505073ffffffffffffffffffffffffffffffffffffffff891692915050610571565b506000545a61055e9083610892565b6105689190610892565b95945050505050565b606061057f83600084610586565b9392505050565b606060008473ffffffffffffffffffffffffffffffffffffffff1684846040516105b0919061095b565b60006040518083038185875af1925050503d80600081146105ed576040519150601f19603f3d011682016040523d82523d6000602084013e6105f2565b606091505b50925090508061060457815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461062e57600080fd5b50565b803561063c8161060c565b919050565b60008083601f84011261065357600080fd5b50813567ffffffffffffffff81111561066b57600080fd5b60208301915083602082850101111561068357600080fd5b9250929050565b600080600080600080608087890312156106a357600080fd5b86356106ae8161060c565b9550602087013567ffffffffffffffff808211156106cb57600080fd5b818901915089601f8301126106df57600080fd5b8135818111156106ee57600080fd5b8a60208260051b850101111561070357600080fd5b602083019750955061071760408a01610631565b9450606089013591508082111561072d57600080fd5b5061073a89828a01610641565b979a9699509497509295939492505050565b6000604082018483526020604081850152818551808452606086019150828701935060005b8181101561078d57845183529383019391830191600101610771565b5090979650505050505050565b60008060008060008060c087890312156107b357600080fd5b86356107be8161060c565b955060208701356107ce8161060c565b945060408701356107de8161060c565b93506060870135925060808701356107f58161060c565b915060a08701356108058161060c565b809150509295509295509295565b60008060006060848603121561082857600080fd5b83356108338161060c565b925060208401356108438161060c565b91506040840135801515811461085857600080fd5b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156108a5576108a5610863565b92915050565b808201808211156108a5576108a5610863565b6000602082840312156108d057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561091857600080fd5b813561057f8161060c565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361095457610954610863565b5060010190565b6000825160005b8181101561097c5760208186018101518583015201610962565b50600092019182525091905056fea164736f6c6343000811000a","deployedBytecode":"0x608060405234801561001057600080fd5b50600436106100415760003560e01c80631d47e7f4146100465780632582edb4146100705780633bbb2e1d14610085575b600080fd5b61005961005436600461068a565b610098565b60405161006792919061074c565b60405180910390f35b61008361007e36600461079a565b610215565b005b610083610093366004610813565b6102e5565b6000606033301461012f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b60008573ffffffffffffffffffffffffffffffffffffffff16600060405160006040518083038185875af1925050503d806000811461018a576040519150601f19603f3d011682016040523d82523d6000602084013e61018f565b606091505b505090505061019f87878a61041a565b6101aa8885856104f2565b91506101b787878a61041a565b600180548060200260200160405190810160405280929190818152602001828054801561020357602002820191906000526020600020905b8154815260200190600101908083116101ef575b50505050509050965096945050505050565b60005a6040517f542eb77d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152878116602483015260448201879052858116606483015284811660848301529192509088169063542eb77d9060a401600060405180830381600087803b1580156102a457600080fd5b505af11580156102b8573d6000803e3d6000fd5b505050505a6102c79082610892565b6000808282546102d791906108ab565b909155505050505050505050565b60005a9050600173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff8616146103b2576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa158015610389573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ad91906108be565b6103cb565b8373ffffffffffffffffffffffffffffffffffffffff16315b815460018101835560009283526020909220909101558115610414575a6103f29082610892565b6103fe9061116c6108ab565b60008082825461040e91906108ab565b90915550505b50505050565b60005b828110156104145730633bbb2e1d85858481811061043d5761043d6108d7565b90506020020160208101906104529190610906565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9182166004820152908516602482015260006044820152606401600060405180830381600087803b1580156104c757600080fd5b505af11580156104db573d6000803e3d6000fd5b5050505080806104ea90610923565b91505061041d565b6000805a905061054f84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505073ffffffffffffffffffffffffffffffffffffffff891692915050610571565b506000545a61055e9083610892565b6105689190610892565b95945050505050565b606061057f83600084610586565b9392505050565b606060008473ffffffffffffffffffffffffffffffffffffffff1684846040516105b0919061095b565b60006040518083038185875af1925050503d80600081146105ed576040519150601f19603f3d011682016040523d82523d6000602084013e6105f2565b606091505b50925090508061060457815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461062e57600080fd5b50565b803561063c8161060c565b919050565b60008083601f84011261065357600080fd5b50813567ffffffffffffffff81111561066b57600080fd5b60208301915083602082850101111561068357600080fd5b9250929050565b600080600080600080608087890312156106a357600080fd5b86356106ae8161060c565b9550602087013567ffffffffffffffff808211156106cb57600080fd5b818901915089601f8301126106df57600080fd5b8135818111156106ee57600080fd5b8a60208260051b850101111561070357600080fd5b602083019750955061071760408a01610631565b9450606089013591508082111561072d57600080fd5b5061073a89828a01610641565b979a9699509497509295939492505050565b6000604082018483526020604081850152818551808452606086019150828701935060005b8181101561078d57845183529383019391830191600101610771565b5090979650505050505050565b60008060008060008060c087890312156107b357600080fd5b86356107be8161060c565b955060208701356107ce8161060c565b945060408701356107de8161060c565b93506060870135925060808701356107f58161060c565b915060a08701356108058161060c565b809150509295509295509295565b60008060006060848603121561082857600080fd5b83356108338161060c565b925060208401356108438161060c565b91506040840135801515811461085857600080fd5b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156108a5576108a5610863565b92915050565b808201808211156108a5576108a5610863565b6000602082840312156108d057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561091857600080fd5b813561057f8161060c565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361095457610954610863565b5060010190565b6000825160005b8181101561097c5760208186018101518583015201610962565b50600092019182525091905056fea164736f6c6343000811000a","devdoc":{"methods":{}},"userdoc":{"methods":{}}} diff --git a/crates/contracts/artifacts/Trader.json b/crates/contracts/artifacts/Trader.json index 54a0a01cf2..c41d8b65bf 100644 --- a/crates/contracts/artifacts/Trader.json +++ b/crates/contracts/artifacts/Trader.json @@ -1 +1 @@ -{"abi":[{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"contract ISettlement","name":"settlementContract","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"address","name":"nativeToken","type":"address"},{"internalType":"address","name":"spardose","type":"address"}],"name":"prepareSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}],"bytecode":"0x608060405234801561001057600080fd5b50610aad806100206000396000f3fe60806040526004361061002d5760003560e01c80631626ba7e1461008657806366b00f68146100fe57610034565b3661003457005b600061007c6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062010000939250506101209050565b9050805160208201f35b34801561009257600080fd5b506100c96100a13660046108c9565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010a57600080fd5b5061011e61011936600461096a565b6101a2565b005b606060008373ffffffffffffffffffffffffffffffffffffffff168360405161014991906109d2565b600060405180830381855af49150503d8060008114610184576040519150601f19603f3d011682016040523d82523d6000602084013e610189565b606091505b50925090508061019b57815160208301fd5b5092915050565b6101aa61088e565b1561023b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e63650000000000000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361037e576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa1580156102db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ff9190610a01565b90508381101561037c5760006103158286610a1a565b905080471061037a578373ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561036657600080fd5b505af193505050508015610378575060015b505b505b505b60008473ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e308873ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040c9190610a5a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa15801561047c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a09190610a01565b905083811015610745578473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610511573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105359190610a5a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152600060248201526044016020604051808303816000875af19250505080156105e1575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526105de91810190610a7e565b60015b156105e857505b8473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190610a5a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff90911660048201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248201526044016020604051808303816000875af192505050801561073e575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261073b91810190610a7e565b60015b1561074557505b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa1580156107b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d69190610a01565b9050848110156108855773ffffffffffffffffffffffffffffffffffffffff831663494666b6876108078489610a1a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b15801561087257600080fd5b505af1925050508015610883575060015b505b50505050505050565b6000806108bc60017f7f36ecad6e52bbe2ff70badce94360882c890b7877b16131c08eabfc635c9735610a1a565b8054600190915592915050565b6000806000604084860312156108de57600080fd5b83359250602084013567ffffffffffffffff808211156108fd57600080fd5b818601915086601f83011261091157600080fd5b81358181111561092057600080fd5b87602082850101111561093257600080fd5b6020830194508093505050509250925092565b73ffffffffffffffffffffffffffffffffffffffff8116811461096757600080fd5b50565b600080600080600060a0868803121561098257600080fd5b853561098d81610945565b9450602086013561099d81610945565b93506040860135925060608601356109b481610945565b915060808601356109c481610945565b809150509295509295909350565b6000825160005b818110156109f357602081860181015185830152016109d9565b506000920191825250919050565b600060208284031215610a1357600080fd5b5051919050565b81810381811115610a54577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b600060208284031215610a6c57600080fd5b8151610a7781610945565b9392505050565b600060208284031215610a9057600080fd5b81518015158114610a7757600080fdfea164736f6c6343000811000a","deployedBytecode":"0x60806040526004361061002d5760003560e01c80631626ba7e1461008657806366b00f68146100fe57610034565b3661003457005b600061007c6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062010000939250506101209050565b9050805160208201f35b34801561009257600080fd5b506100c96100a13660046108c9565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010a57600080fd5b5061011e61011936600461096a565b6101a2565b005b606060008373ffffffffffffffffffffffffffffffffffffffff168360405161014991906109d2565b600060405180830381855af49150503d8060008114610184576040519150601f19603f3d011682016040523d82523d6000602084013e610189565b606091505b50925090508061019b57815160208301fd5b5092915050565b6101aa61088e565b1561023b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e63650000000000000000000000000000000000000000000000000000000000606482015260840160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361037e576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa1580156102db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ff9190610a01565b90508381101561037c5760006103158286610a1a565b905080471061037a578373ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561036657600080fd5b505af193505050508015610378575060015b505b505b505b60008473ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e308873ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040c9190610a5a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa15801561047c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a09190610a01565b905083811015610745578473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610511573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105359190610a5a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152600060248201526044016020604051808303816000875af19250505080156105e1575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526105de91810190610a7e565b60015b156105e857505b8473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190610a5a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff90911660048201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248201526044016020604051808303816000875af192505050801561073e575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261073b91810190610a7e565b60015b1561074557505b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa1580156107b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d69190610a01565b9050848110156108855773ffffffffffffffffffffffffffffffffffffffff831663494666b6876108078489610a1a565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b15801561087257600080fd5b505af1925050508015610883575060015b505b50505050505050565b6000806108bc60017f7f36ecad6e52bbe2ff70badce94360882c890b7877b16131c08eabfc635c9735610a1a565b8054600190915592915050565b6000806000604084860312156108de57600080fd5b83359250602084013567ffffffffffffffff808211156108fd57600080fd5b818601915086601f83011261091157600080fd5b81358181111561092057600080fd5b87602082850101111561093257600080fd5b6020830194508093505050509250925092565b73ffffffffffffffffffffffffffffffffffffffff8116811461096757600080fd5b50565b600080600080600060a0868803121561098257600080fd5b853561098d81610945565b9450602086013561099d81610945565b93506040860135925060608601356109b481610945565b915060808601356109c481610945565b809150509295509295909350565b6000825160005b818110156109f357602081860181015185830152016109d9565b506000920191825250919050565b600060208284031215610a1357600080fd5b5051919050565b81810381811115610a54577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b600060208284031215610a6c57600080fd5b8151610a7781610945565b9392505050565b600060208284031215610a9057600080fd5b81518015158114610a7757600080fdfea164736f6c6343000811000a","devdoc":{"methods":{}},"userdoc":{"methods":{}}} +{"abi":[{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"contract ISettlement","name":"settlementContract","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"address","name":"nativeToken","type":"address"},{"internalType":"address","name":"spardose","type":"address"}],"name":"ensureTradePreconditions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"stateMutability":"payable","type":"receive"}],"bytecode":"0x608060405234801561001057600080fd5b50610cee806100206000396000f3fe60806040526004361061002d5760003560e01c80631626ba7e14610086578063542eb77d146100fe57610034565b3661003457005b600061007c6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062010000939250506101209050565b9050805160208201f35b34801561009257600080fd5b506100c96100a1366004610b0a565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010a57600080fd5b5061011e610119366004610bab565b6101a2565b005b606060008373ffffffffffffffffffffffffffffffffffffffff16836040516101499190610c13565b600060405180830381855af49150503d8060008114610184576040519150601f19603f3d011682016040523d82523d6000602084013e610189565b606091505b50925090508061019b57815160208301fd5b5092915050565b6101aa610acf565b1561023c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e6365000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361037f576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa1580156102dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103009190610c42565b90508381101561037d5760006103168286610c5b565b905080471061037b578373ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561036757600080fd5b505af193505050508015610379575060015b505b505b505b60008473ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e308873ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040d9190610c9b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa15801561047d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a19190610c42565b9050838110156108fc578473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190610c9b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152600060248201526044016020604051808303816000875af19250505080156105e2575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526105df91810190610cbf565b60015b156105e957505b8473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610650573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106749190610c9b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff90911660048201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248201526044016020604051808303816000875af192505050801561073f575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261073c91810190610cbf565b60015b1561074657505b60008573ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e308973ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d49190610c9b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa158015610844573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108689190610c42565b9050848110156108fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f74726164657220646964206e6f7420676976652074686520726571756972656460448201527f20617070726f76616c73000000000000000000000000000000000000000000006064820152608401610233565b505b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa158015610969573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098d9190610c42565b905084811015610ac65773ffffffffffffffffffffffffffffffffffffffff831663494666b6876109be8489610c5b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b158015610a2957600080fd5b505af1925050508015610a3a575060015b610ac6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f74726164657220646f6573206e6f74206861766520656e6f7567682073656c6c60448201527f20746f6b656e00000000000000000000000000000000000000000000000000006064820152608401610233565b50505050505050565b600080610afd60017f7f36ecad6e52bbe2ff70badce94360882c890b7877b16131c08eabfc635c9735610c5b565b8054600190915592915050565b600080600060408486031215610b1f57600080fd5b83359250602084013567ffffffffffffffff80821115610b3e57600080fd5b818601915086601f830112610b5257600080fd5b813581811115610b6157600080fd5b876020828501011115610b7357600080fd5b6020830194508093505050509250925092565b73ffffffffffffffffffffffffffffffffffffffff81168114610ba857600080fd5b50565b600080600080600060a08688031215610bc357600080fd5b8535610bce81610b86565b94506020860135610bde81610b86565b9350604086013592506060860135610bf581610b86565b91506080860135610c0581610b86565b809150509295509295909350565b6000825160005b81811015610c345760208186018101518583015201610c1a565b506000920191825250919050565b600060208284031215610c5457600080fd5b5051919050565b81810381811115610c95577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b600060208284031215610cad57600080fd5b8151610cb881610b86565b9392505050565b600060208284031215610cd157600080fd5b81518015158114610cb857600080fdfea164736f6c6343000811000a","deployedBytecode":"0x60806040526004361061002d5760003560e01c80631626ba7e14610086578063542eb77d146100fe57610034565b3661003457005b600061007c6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062010000939250506101209050565b9050805160208201f35b34801561009257600080fd5b506100c96100a1366004610b0a565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010a57600080fd5b5061011e610119366004610bab565b6101a2565b005b606060008373ffffffffffffffffffffffffffffffffffffffff16836040516101499190610c13565b600060405180830381855af49150503d8060008114610184576040519150601f19603f3d011682016040523d82523d6000602084013e610189565b606091505b50925090508061019b57815160208301fd5b5092915050565b6101aa610acf565b1561023c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e6365000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361037f576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa1580156102dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103009190610c42565b90508381101561037d5760006103168286610c5b565b905080471061037b578373ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561036757600080fd5b505af193505050508015610379575060015b505b505b505b60008473ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e308873ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040d9190610c9b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa15801561047d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a19190610c42565b9050838110156108fc578473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190610c9b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152600060248201526044016020604051808303816000875af19250505080156105e2575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526105df91810190610cbf565b60015b156105e957505b8473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610650573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106749190610c9b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff90911660048201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248201526044016020604051808303816000875af192505050801561073f575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261073c91810190610cbf565b60015b1561074657505b60008573ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e308973ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d49190610c9b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa158015610844573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108689190610c42565b9050848110156108fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f74726164657220646964206e6f7420676976652074686520726571756972656460448201527f20617070726f76616c73000000000000000000000000000000000000000000006064820152608401610233565b505b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa158015610969573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098d9190610c42565b905084811015610ac65773ffffffffffffffffffffffffffffffffffffffff831663494666b6876109be8489610c5b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b158015610a2957600080fd5b505af1925050508015610a3a575060015b610ac6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f74726164657220646f6573206e6f74206861766520656e6f7567682073656c6c60448201527f20746f6b656e00000000000000000000000000000000000000000000000000006064820152608401610233565b50505050505050565b600080610afd60017f7f36ecad6e52bbe2ff70badce94360882c890b7877b16131c08eabfc635c9735610c5b565b8054600190915592915050565b600080600060408486031215610b1f57600080fd5b83359250602084013567ffffffffffffffff80821115610b3e57600080fd5b818601915086601f830112610b5257600080fd5b813581811115610b6157600080fd5b876020828501011115610b7357600080fd5b6020830194508093505050509250925092565b73ffffffffffffffffffffffffffffffffffffffff81168114610ba857600080fd5b50565b600080600080600060a08688031215610bc357600080fd5b8535610bce81610b86565b94506020860135610bde81610b86565b9350604086013592506060860135610bf581610b86565b91506080860135610c0581610b86565b809150509295509295909350565b6000825160005b81811015610c345760208186018101518583015201610c1a565b506000920191825250919050565b600060208284031215610c5457600080fd5b5051919050565b81810381811115610c95577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b600060208284031215610cad57600080fd5b8151610cb881610b86565b9392505050565b600060208284031215610cd157600080fd5b81518015158114610cb857600080fdfea164736f6c6343000811000a","devdoc":{"methods":{}},"userdoc":{"methods":{}}} diff --git a/crates/contracts/solidity/Solver.sol b/crates/contracts/solidity/Solver.sol index e1986e9360..e9aa29035f 100644 --- a/crates/contracts/solidity/Solver.sol +++ b/crates/contracts/solidity/Solver.sol @@ -27,44 +27,23 @@ contract Solver { /// /// @param settlementContract - address of the settlement contract because /// it does not have a stable address in tests. - /// @param trader - address of the order owner doing the trade - /// @param sellToken - address of the token being sold - /// @param sellAmount - amount being sold - /// @param nativeToken - ERC20 version of the chain's token /// @param tokens - list of tokens used in the trade /// @param receiver - address receiving the bought tokens /// @param settlementCall - the calldata of the `settle()` call - /// @param spardose - contract to provide missing funds with /// /// @return gasUsed - gas used for the `settle()` call /// @return queriedBalances - list of balances stored during the simulation function swap( ISettlement settlementContract, - address payable trader, - address sellToken, - uint256 sellAmount, - address nativeToken, address[] calldata tokens, address payable receiver, - bytes calldata settlementCall, - address spardose + bytes calldata settlementCall ) external returns ( uint256 gasUsed, uint256[] memory queriedBalances ) { require(msg.sender == address(this), "only simulation logic is allowed to call 'swap' function"); - // Prepare the trade in the context of the trader so we are allowed - // to set approvals and things like that. - Trader(trader) - .prepareSwap( - settlementContract, - sellToken, - sellAmount, - nativeToken, - spardose - ); - // Warm the storage for sending ETH to smart contract addresses. // We allow this call to revert becaues it was either unnecessary in the first place // or failing to send `ETH` to the `receiver` will cause a revert in the settlement @@ -125,4 +104,27 @@ contract Solver { address(settlementContract).doCall(settlementCall); gasUsed = gasStart - gasleft() - _simulationOverhead; } + + /// @dev Simple wrapper around `Trader.ensureTradePreconditions()` that + /// discounts the gas used to prepare the swap (setting up approvals + /// and balances) from the total gas cost since that would normally + /// not happen during the settlement. + function ensureTradePreconditions( + Trader trader, + ISettlement settlementContract, + address sellToken, + uint256 sellAmount, + address nativeToken, + address spardose + ) external { + uint256 gasStart = gasleft(); + trader.ensureTradePreconditions( + settlementContract, + sellToken, + sellAmount, + nativeToken, + spardose + ); + _simulationOverhead += gasStart - gasleft(); + } } diff --git a/crates/contracts/solidity/Trader.sol b/crates/contracts/solidity/Trader.sol index 7b95e3d96d..37f34f75c3 100644 --- a/crates/contracts/solidity/Trader.sol +++ b/crates/contracts/solidity/Trader.sol @@ -64,19 +64,13 @@ contract Trader { /// @dev Executes needed actions on behalf of the trader to make the trade possible. /// (e.g. wrapping ETH, setting approvals, and funding the account) - /// To support cases where the user's pre-interactions set up the trade - /// themselves (e.g. get tokens by unstaking) AND cases where we need to - /// set up everything for the trade we catch all relevant reverts here. - /// At the end of the function we can assume that all necessary pre-conditions - /// are met. If that is not the case the simulation will simply fail at a later - /// point in time anyway. /// @param settlementContract - pass in settlement contract because it does not have /// 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 prepareSwap( + function ensureTradePreconditions( ISettlement settlementContract, address sellToken, uint256 sellAmount, @@ -115,6 +109,8 @@ contract Trader { catch {} try IERC20(sellToken).approve(address(settlementContract.vaultRelayer()), type(uint256).max) {} catch {} + uint256 allowance = IERC20(sellToken).allowance(address(this), address(settlementContract.vaultRelayer())); + require(allowance >= sellAmount, "trader did not give the required approvals"); } // Ensure that the user has sufficient sell token balance. If not, request some @@ -123,7 +119,12 @@ contract Trader { uint256 sellBalance = IERC20(sellToken).balanceOf(address(this)); if (sellBalance < sellAmount) { try Spardose(spardose).requestFunds(sellToken, sellAmount - sellBalance) {} - catch {} + catch { + // The trader does not have sufficient sell token balance, and the + // piggy bank pre-fund failed, as balance overrides are not available. + // Revert with a helpful message. + revert("trader does not have enough sell token"); + } } } diff --git a/crates/shared/src/price_estimation/trade_verifier.rs b/crates/shared/src/price_estimation/trade_verifier.rs index 5103b446e2..12bad16c16 100644 --- a/crates/shared/src/price_estimation/trade_verifier.rs +++ b/crates/shared/src/price_estimation/trade_verifier.rs @@ -143,6 +143,7 @@ impl TradeVerifier { out_amount, self.native_token, &self.domain_separator, + self.settlement.address(), )?; let settlement = add_balance_queries(settlement, query, &verification, &solver); @@ -158,23 +159,13 @@ impl TradeVerifier { ) .tx; - let sell_amount = match query.kind { - OrderKind::Sell => query.in_amount.get(), - OrderKind::Buy => *out_amount, - }; - let simulation = solver .methods() .swap( self.settlement.address(), - verification.from, - query.sell_token, - sell_amount, - self.native_token, tokens.clone(), verification.receiver, Bytes(settlement.data.unwrap().0), - Self::SPARDOSE, ) .tx; @@ -466,6 +457,7 @@ fn encode_settlement( out_amount: &U256, native_token: H160, domain_separator: &DomainSeparator, + settlement: H160, ) -> Result { let mut trade_interactions = encode_interactions(&trade.interactions()); if query.buy_token == BUY_ETH_ADDRESS { @@ -493,11 +485,37 @@ fn encode_settlement( )?); } - let pre_interactions = [ - verification.pre_interactions.clone(), - trade.pre_interactions(), - ] - .concat(); + // Execute interaction to set up trade right before transfering funds. + // This interaction does nothing if the user-provided pre-interactions + // already set everything up (e.g. approvals, balances). That way we can + // correctly verify quotes with or without these user pre-interactions + // with helpful error messages. + let trade_setup_interaction = { + let sell_amount = match query.kind { + OrderKind::Sell => query.in_amount.get(), + OrderKind::Buy => *out_amount, + }; + let solver = dummy_contract!(Solver, trade.solver()); + let setup_step = solver.ensure_trade_preconditions( + verification.from, + settlement, + query.sell_token, + sell_amount, + native_token, + TradeVerifier::SPARDOSE, + ); + Interaction { + target: solver.address(), + value: 0.into(), + data: setup_step.tx.data.unwrap().0, + } + }; + + let user_interactions = verification.pre_interactions.iter().cloned(); + let pre_interactions: Vec<_> = user_interactions + .chain(trade.pre_interactions()) + .chain([trade_setup_interaction]) + .collect(); Ok(EncodedSettlement { tokens: tokens.to_vec(), From 1b84b2b2e7a76bf4ffcb90b6b0d35303b0e96557 Mon Sep 17 00:00:00 2001 From: Martin Magnus Date: Thu, 12 Dec 2024 12:27:18 +0100 Subject: [PATCH 5/7] Remove naive solver (#3161) # Description The naive solver is extremely basic and never wins any auctions anymore. Also AFAICT it's no longer used in e2e tests either so by now it's just dead weight. Sparked by this [thread](https://cowservices.slack.com/archives/C036JAGRQ04/p1733911881085109) # Changes Removes: * original algorithm in legacy code * wrapper logic in `solvers` crate * config code * test cases * documentation Also in many cases we had an enum with 2 variants (`baseline` and `naive`). Since we now only have 1 variant left I collapsed all the logic and got rid of a few modules which are no longer necessary. --- README.md | 11 - crates/solver/src/settlement/mod.rs | 8 - .../{solver/baseline_solver.rs => solver.rs} | 20 + crates/solver/src/solver/mod.rs | 25 - crates/solver/src/solver/naive_solver.rs | 1086 ----------------- crates/solvers/src/boundary/baseline.rs | 14 +- crates/solvers/src/boundary/mod.rs | 1 - crates/solvers/src/boundary/naive.rs | 249 ---- .../domain/{solver/baseline.rs => solver.rs} | 12 +- crates/solvers/src/domain/solver/mod.rs | 30 - crates/solvers/src/domain/solver/naive.rs | 107 -- crates/solvers/src/infra/cli.rs | 2 - .../infra/{config/baseline.rs => config.rs} | 28 +- crates/solvers/src/infra/config/mod.rs | 21 - crates/solvers/src/run.rs | 7 +- .../{baseline => cases}/bal_liquidity.rs | 0 .../{baseline => cases}/buy_order_rounding.rs | 0 .../tests/{baseline => cases}/direct_swap.rs | 0 .../{baseline => cases}/internalization.rs | 0 .../limit_order_quoting.rs | 0 .../src/tests/{baseline => cases}/mod.rs | 0 .../tests/{baseline => cases}/partial_fill.rs | 0 crates/solvers/src/tests/mod.rs | 3 +- .../src/tests/naive/extract_deepest_pool.rs | 139 --- .../naive/filters_out_of_price_orders.rs | 172 --- .../src/tests/naive/limit_order_price.rs | 70 -- .../solvers/src/tests/naive/matches_orders.rs | 508 -------- crates/solvers/src/tests/naive/mod.rs | 8 - .../src/tests/naive/reserves_too_small.rs | 123 -- .../rounds_prices_in_favour_of_traders.rs | 137 --- .../tests/naive/swap_less_than_reserves.rs | 99 -- .../solvers/src/tests/naive/without_pool.rs | 120 -- 32 files changed, 60 insertions(+), 2940 deletions(-) rename crates/solver/src/{solver/baseline_solver.rs => solver.rs} (73%) delete mode 100644 crates/solver/src/solver/mod.rs delete mode 100644 crates/solver/src/solver/naive_solver.rs delete mode 100644 crates/solvers/src/boundary/naive.rs rename crates/solvers/src/domain/{solver/baseline.rs => solver.rs} (97%) delete mode 100644 crates/solvers/src/domain/solver/mod.rs delete mode 100644 crates/solvers/src/domain/solver/naive.rs rename crates/solvers/src/infra/{config/baseline.rs => config.rs} (81%) delete mode 100644 crates/solvers/src/infra/config/mod.rs rename crates/solvers/src/tests/{baseline => cases}/bal_liquidity.rs (100%) rename crates/solvers/src/tests/{baseline => cases}/buy_order_rounding.rs (100%) rename crates/solvers/src/tests/{baseline => cases}/direct_swap.rs (100%) rename crates/solvers/src/tests/{baseline => cases}/internalization.rs (100%) rename crates/solvers/src/tests/{baseline => cases}/limit_order_quoting.rs (100%) rename crates/solvers/src/tests/{baseline => cases}/mod.rs (100%) rename crates/solvers/src/tests/{baseline => cases}/partial_fill.rs (100%) delete mode 100644 crates/solvers/src/tests/naive/extract_deepest_pool.rs delete mode 100644 crates/solvers/src/tests/naive/filters_out_of_price_orders.rs delete mode 100644 crates/solvers/src/tests/naive/limit_order_price.rs delete mode 100644 crates/solvers/src/tests/naive/matches_orders.rs delete mode 100644 crates/solvers/src/tests/naive/mod.rs delete mode 100644 crates/solvers/src/tests/naive/reserves_too_small.rs delete mode 100644 crates/solvers/src/tests/naive/rounds_prices_in_favour_of_traders.rs delete mode 100644 crates/solvers/src/tests/naive/swap_less_than_reserves.rs delete mode 100644 crates/solvers/src/tests/naive/without_pool.rs diff --git a/README.md b/README.md index 844da11f15..016bcf40d6 100644 --- a/README.md +++ b/README.md @@ -27,17 +27,6 @@ Concretely, it is responsible for "cutting" new auctions (i.e. determining aucti The `autopilot` connects to the same PostgreSQL database as the `orderbook` and uses it to query orders as well as storing the most recent auction and settlement competition. -## Solver - -The `solver` crate is responsible for submitting on-chain settlements based on the orders it gets from the order book and other liquidity sources like Balancer or Uniswap pools. - -It implements a few settlement strategies directly in Rust: - -- Naive Solver: Can match to overlapping opposing orders (e.g. DAI for WETH & WETH for DAI) with one another settling the excess with Uniswap -- Uniswap Baseline: Same path finding as used by the Uniswap frontend (settling orders individually instead of batching them together) - -It can also interact with a more advanced, Gnosis internal, closed source solver which tries to settle all orders using the combinatorial optimization formulations described in [Multi-Token Batch Auctions with Uniform Clearing Price](https://github.com/gnosis/dex-research/blob/master/BatchAuctionOptimization/batchauctions.pdf) - ## Other Crates There are additional crates that live in the cargo workspace. diff --git a/crates/solver/src/settlement/mod.rs b/crates/solver/src/settlement/mod.rs index 01dda9c696..a63db21a85 100644 --- a/crates/solver/src/settlement/mod.rs +++ b/crates/solver/src/settlement/mod.rs @@ -131,14 +131,6 @@ impl Settlement { self.encoder.clearing_prices() } - /// Returns the clearing price for the specified token. - /// - /// Returns `None` if the token is not part of the settlement. - #[cfg(test)] - pub(crate) fn clearing_price(&self, token: H160) -> Option { - self.clearing_prices().get(&token).copied() - } - /// Returns all orders included in the settlement. pub fn traded_orders(&self) -> impl Iterator + '_ { self.encoder.all_trades().map(|trade| &trade.data.order) diff --git a/crates/solver/src/solver/baseline_solver.rs b/crates/solver/src/solver.rs similarity index 73% rename from crates/solver/src/solver/baseline_solver.rs rename to crates/solver/src/solver.rs index be79d85a0e..3c694e7048 100644 --- a/crates/solver/src/solver/baseline_solver.rs +++ b/crates/solver/src/solver.rs @@ -1,12 +1,32 @@ use { crate::liquidity::{ConstantProductOrder, WeightedProductOrder}, + anyhow::anyhow, ethcontract::{H160, U256}, shared::{ baseline_solver::BaselineSolvable, sources::{balancer_v2::swap::WeightedPoolRef, uniswap_v2::pool_fetching::Pool}, }, + std::{fmt::Debug, str::FromStr}, }; +// Wrapper type for AWS ARN identifiers +#[derive(Debug, Clone)] +pub struct Arn(pub String); + +impl FromStr for Arn { + type Err = anyhow::Error; + + fn from_str(s: &str) -> std::result::Result { + // Could be more strict here, but this should suffice to catch unintended + // configuration mistakes + if s.starts_with("arn:aws:kms:") { + Ok(Self(s.to_string())) + } else { + Err(anyhow!("Invalid ARN identifier: {}", s)) + } + } +} + impl BaselineSolvable for ConstantProductOrder { fn get_amount_out(&self, out_token: H160, input: (U256, H160)) -> Option { amm_to_pool(self).get_amount_out(out_token, input) diff --git a/crates/solver/src/solver/mod.rs b/crates/solver/src/solver/mod.rs deleted file mode 100644 index e285094723..0000000000 --- a/crates/solver/src/solver/mod.rs +++ /dev/null @@ -1,25 +0,0 @@ -use { - anyhow::anyhow, - std::{fmt::Debug, str::FromStr}, -}; - -mod baseline_solver; -pub mod naive_solver; - -// Wrapper type for AWS ARN identifiers -#[derive(Debug, Clone)] -pub struct Arn(pub String); - -impl FromStr for Arn { - type Err = anyhow::Error; - - fn from_str(s: &str) -> std::result::Result { - // Could be more strict here, but this should suffice to catch unintended - // configuration mistakes - if s.starts_with("arn:aws:kms:") { - Ok(Self(s.to_string())) - } else { - Err(anyhow!("Invalid ARN identifier: {}", s)) - } - } -} diff --git a/crates/solver/src/solver/naive_solver.rs b/crates/solver/src/solver/naive_solver.rs deleted file mode 100644 index dc0fba6243..0000000000 --- a/crates/solver/src/solver/naive_solver.rs +++ /dev/null @@ -1,1086 +0,0 @@ -use { - crate::{ - liquidity::{self, slippage::SlippageContext, LimitOrderExecution}, - settlement::{PricedTrade, Settlement}, - }, - anyhow::Result, - liquidity::{AmmOrderExecution, ConstantProductOrder, LimitOrder}, - model::order::OrderKind, - num::{rational::Ratio, BigInt, BigRational, CheckedDiv}, - number::conversions::{big_int_to_u256, big_rational_to_u256, u256_to_big_int}, - primitive_types::U256, - shared::{ - conversions::{RatioExt, U256Ext}, - http_solver::model::TokenAmount, - }, - std::collections::HashMap, - web3::types::Address, -}; - -#[derive(Debug, Clone)] -struct TokenContext { - address: Address, - reserve: U256, - buy_volume: U256, - sell_volume: U256, -} - -impl TokenContext { - pub fn is_excess_after_fees(&self, deficit: &TokenContext, fee: Ratio) -> bool { - fee.denom() - * u256_to_big_int(&self.reserve) - * (u256_to_big_int(&deficit.sell_volume) - u256_to_big_int(&deficit.buy_volume)) - < (fee.denom() - fee.numer()) - * u256_to_big_int(&deficit.reserve) - * (u256_to_big_int(&self.sell_volume) - u256_to_big_int(&self.buy_volume)) - } - - pub fn is_excess_before_fees(&self, deficit: &TokenContext) -> bool { - u256_to_big_int(&self.reserve) - * (u256_to_big_int(&deficit.sell_volume) - u256_to_big_int(&deficit.buy_volume)) - < u256_to_big_int(&deficit.reserve) - * (u256_to_big_int(&self.sell_volume) - u256_to_big_int(&self.buy_volume)) - } -} - -pub fn solve( - slippage: &SlippageContext, - orders: impl IntoIterator, - pool: &ConstantProductOrder, -) -> Option { - let mut orders: Vec = orders.into_iter().collect(); - while !orders.is_empty() { - let (context_a, context_b) = split_into_contexts(&orders, pool); - if let Some(valid_solution) = - solve_orders(slippage, &orders, pool, &context_a, &context_b).filter(is_valid_solution) - { - return Some(valid_solution); - } else { - // remove order with worst limit price that is selling excess token (to make it - // less excessive) and try again - let excess_token = if context_a.is_excess_before_fees(&context_b) { - context_a.address - } else { - context_b.address - }; - let order_to_remove = orders - .iter() - .enumerate() - .filter(|o| o.1.sell_token == excess_token) - .max_by(|lhs, rhs| { - (lhs.1.buy_amount * rhs.1.sell_amount) - .cmp(&(lhs.1.sell_amount * rhs.1.buy_amount)) - }); - match order_to_remove { - Some((index, _)) => orders.swap_remove(index), - None => break, - }; - } - } - - None -} - -/// -/// Computes a settlement using orders of a single pair and the direct AMM -/// between those tokens.get(. Panics if orders are not already filtered for a -/// specific token pair, or the reserve information for that pair is not -/// available. -fn solve_orders( - slippage: &SlippageContext, - orders: &[LimitOrder], - pool: &ConstantProductOrder, - context_a: &TokenContext, - context_b: &TokenContext, -) -> Option { - if context_a.is_excess_after_fees(context_b, pool.fee) { - solve_with_uniswap(slippage, orders, pool, context_b, context_a) - } else if context_b.is_excess_after_fees(context_a, pool.fee) { - solve_with_uniswap(slippage, orders, pool, context_a, context_b) - } else { - solve_without_uniswap(orders, context_a, context_b).ok() - } -} - -/// -/// Creates a solution using the current AMM spot price, without using any of -/// its liquidity -fn solve_without_uniswap( - orders: &[LimitOrder], - context_a: &TokenContext, - context_b: &TokenContext, -) -> Result { - let mut settlement = Settlement::new(maplit::hashmap! { - context_a.address => context_b.reserve, - context_b.address => context_a.reserve, - }); - for order in orders { - let execution = LimitOrderExecution { - filled: order.full_execution_amount(), - fee: order.user_fee, - }; - settlement.with_liquidity(order, execution)?; - } - - Ok(settlement) -} - -/// -/// Creates a solution using the current AMM's liquidity to balance excess and -/// shortage. The clearing price is the effective exchange rate used by the AMM -/// interaction. -fn solve_with_uniswap( - slippage: &SlippageContext, - orders: &[LimitOrder], - pool: &ConstantProductOrder, - shortage: &TokenContext, - excess: &TokenContext, -) -> Option { - let uniswap_in_token = excess.address; - let uniswap_out_token = shortage.address; - - let uniswap_out = compute_uniswap_out(shortage, excess, pool.fee)?; - let uniswap_in = compute_uniswap_in(uniswap_out.clone(), shortage, excess, pool.fee)?; - - let uniswap_out = big_rational_to_u256(&uniswap_out).ok()?; - let uniswap_in = big_rational_to_u256(&uniswap_in).ok()?; - - let mut settlement = Settlement::new(maplit::hashmap! { - uniswap_in_token => uniswap_out, - uniswap_out_token => uniswap_in, - }); - for order in orders { - let execution = LimitOrderExecution { - filled: order.full_execution_amount(), - // TODO: We still need to compute a fee for partially fillable limit orders. - fee: order.user_fee, - }; - settlement.with_liquidity(order, execution).ok()?; - } - - // Because the smart contracts round in the favour of the traders, it could - // be that we actually require a bit more from the Uniswap pool in order to - // pay out all proceeds. We move the rounding error to the sell token so that - // it either comes out of the fees or existing buffers. It is also important - // to use the **synthetic** order amounts for this, as this output amount - // needs to be computed for what is actually intented to be traded against - // an AMM and not how the order will be executed (including things like - // surplus fees). - let uniswap_out_required_by_orders = big_int_to_u256(&orders.iter().try_fold( - BigInt::default(), - |mut total, order| { - if order.sell_token == uniswap_out_token { - total -= match order.kind { - OrderKind::Sell => order.sell_amount, - OrderKind::Buy => order - .buy_amount - .checked_mul(uniswap_out)? - .checked_div(uniswap_in)?, - } - .to_big_int(); - } else { - total += match order.kind { - OrderKind::Sell => order - .sell_amount - .checked_mul(uniswap_out)? - .checked_ceil_div(&uniswap_in)?, - OrderKind::Buy => order.buy_amount, - } - .to_big_int(); - }; - Some(total) - }, - )?) - .ok()?; - - // In theory, not all limit orders are GPv2 trades (although in practice - // they are). Since those orders don't generate trades, they aren't - // considered in the `uniswap_out_with_rounding` computation. Luckily, they - // don't get any surplus anyway, so we can just use the original output - // amount as the rounding error will come from the surplus that those orders - // would have otherwise received. - let uniswap_out_with_rounding = uniswap_out_required_by_orders.max(uniswap_out); - - settlement - .with_liquidity( - pool, - slippage - .apply_to_amm_execution(AmmOrderExecution { - input_max: TokenAmount::new(uniswap_in_token, uniswap_in), - output: TokenAmount::new(uniswap_out_token, uniswap_out_with_rounding), - internalizable: false, - }) - .ok()?, - ) - .ok()?; - - Some(settlement) -} - -impl ConstantProductOrder { - fn get_reserve(&self, token: &Address) -> Option { - if &self.tokens.get().0 == token { - Some(self.reserves.0.into()) - } else if &self.tokens.get().1 == token { - Some(self.reserves.1.into()) - } else { - None - } - } -} - -fn split_into_contexts( - orders: &[LimitOrder], - pool: &ConstantProductOrder, -) -> (TokenContext, TokenContext) { - let mut contexts = HashMap::new(); - for order in orders { - let buy_context = contexts - .entry(order.buy_token) - .or_insert_with(|| TokenContext { - address: order.buy_token, - reserve: pool - .get_reserve(&order.buy_token) - .unwrap_or_else(|| panic!("No reserve for token {}", &order.buy_token)), - buy_volume: U256::zero(), - sell_volume: U256::zero(), - }); - if matches!(order.kind, OrderKind::Buy) { - buy_context.buy_volume += order.buy_amount - } - - let sell_context = contexts - .entry(order.sell_token) - .or_insert_with(|| TokenContext { - address: order.sell_token, - reserve: pool - .get_reserve(&order.sell_token) - .unwrap_or_else(|| panic!("No reserve for token {}", &order.sell_token)), - buy_volume: U256::zero(), - sell_volume: U256::zero(), - }); - if matches!(order.kind, OrderKind::Sell) { - sell_context.sell_volume += order.sell_amount - } - } - assert_eq!(contexts.len(), 2, "Orders contain more than two tokens"); - let mut contexts = contexts.drain().map(|(_, v)| v); - (contexts.next().unwrap(), contexts.next().unwrap()) -} - -/// -/// Given information about the shortage token (the one we need to take from -/// Uniswap) and the excess token (the one we give to Uniswap), this function -/// computes the exact out_amount required from Uniswap to perfectly match -/// demand and supply at the effective Uniswap price (the one used for that -/// in/out swap). -/// -/// The derivation of this formula is described in https://docs.google.com/document/d/1jS22wxbCqo88fGsqEMZgRQgiAcHlPqxoMw3CJTHst6c/edit -/// It assumes GP fee (φ) to be 1 -fn compute_uniswap_out( - shortage: &TokenContext, - excess: &TokenContext, - amm_fee: Ratio, -) -> Option { - let numerator_minuend = (amm_fee.denom() - amm_fee.numer()) - * (u256_to_big_int(&excess.sell_volume) - u256_to_big_int(&excess.buy_volume)) - * u256_to_big_int(&shortage.reserve); - let numerator_subtrahend = amm_fee.denom() - * (u256_to_big_int(&shortage.sell_volume) - u256_to_big_int(&shortage.buy_volume)) - * u256_to_big_int(&excess.reserve); - let denominator: BigInt = amm_fee.denom() * u256_to_big_int(&excess.reserve) - + (amm_fee.denom() - amm_fee.numer()) - * (u256_to_big_int(&excess.sell_volume) - u256_to_big_int(&excess.buy_volume)); - BigRational::new_checked(numerator_minuend - numerator_subtrahend, denominator).ok() -} - -/// -/// Given the desired amount to receive and the state of the pool, this computes -/// the required amount of tokens to be sent to the pool. -/// Taken from: https://github.com/Uniswap/uniswap-v2-periphery/blob/4123f93278b60bcf617130629c69d4016f9e7584/contracts/libraries/UniswapV2Library.sol#L53 -/// Not adding + 1 in the end, because we are working with rationals and thus -/// don't round up. -fn compute_uniswap_in( - out: BigRational, - shortage: &TokenContext, - excess: &TokenContext, - amm_fee: Ratio, -) -> Option { - let numerator = U256::from(*amm_fee.denom()).to_big_rational() - * out.clone() - * u256_to_big_int(&excess.reserve); - let denominator = U256::from(amm_fee.denom() - amm_fee.numer()).to_big_rational() - * (shortage.reserve.to_big_rational() - out); - numerator.checked_div(&denominator) -} - -/// -/// Returns true if for each trade the executed price is not smaller than the -/// limit price Thus we ensure that `buy_token_price / sell_token_price >= -/// limit_buy_amount / limit_sell_amount` -fn is_valid_solution(solution: &Settlement) -> bool { - for PricedTrade { - data, - sell_token_price, - buy_token_price, - } in solution.encoder.all_trades() - { - let order = &data.order.data; - - // Check execution respects individual order's limit price - match ( - order.sell_amount.checked_mul(sell_token_price), - order.buy_amount.checked_mul(buy_token_price), - ) { - (Some(sell_volume), Some(buy_volume)) if sell_volume >= buy_volume => (), - _ => return false, - } - - // Check individual order's execution price satisfies uniform clearing price - // E.g. liquidity orders may have a different executed price. - let clearing_prices = solution.encoder.clearing_prices(); - match ( - clearing_prices - .get(&order.buy_token) - .map(|clearing_sell_price| clearing_sell_price.checked_mul(sell_token_price)), - clearing_prices - .get(&order.sell_token) - .map(|clearing_buy_price| clearing_buy_price.checked_mul(buy_token_price)), - ) { - (Some(execution_sell_value), Some(clearing_buy_value)) - if execution_sell_value <= clearing_buy_value => {} - _ => return false, - } - } - - true -} - -#[cfg(test)] -mod tests { - use { - super::*, - crate::liquidity::slippage::SlippageCalculator, - ethcontract::H160, - liquidity::tests::CapturingSettlementHandler, - maplit::hashmap, - model::{ - order::{Order, OrderData}, - TokenPair, - }, - num::rational::Ratio, - once_cell::sync::OnceCell, - shared::{ - baseline_solver::BaselineSolvable, - external_prices::ExternalPrices, - sources::uniswap_v2::pool_fetching::Pool, - }, - }; - - fn to_wei(base: u128) -> U256 { - U256::from(base) * U256::from(10).pow(18.into()) - } - - fn without_slippage() -> SlippageContext<'static> { - static CONTEXT: OnceCell<(ExternalPrices, SlippageCalculator)> = OnceCell::new(); - let (prices, calculator) = - CONTEXT.get_or_init(|| (Default::default(), SlippageCalculator::from_bps(0, None))); - calculator.context(prices) - } - - #[test] - fn finds_clearing_price_with_sell_orders_on_both_sides() { - let token_a = Address::from_low_u64_be(0); - let token_b = Address::from_low_u64_be(1); - let orders = vec![ - LimitOrder { - sell_token: token_a, - buy_token: token_b, - sell_amount: to_wei(40), - buy_amount: to_wei(30), - kind: OrderKind::Sell, - id: 0.into(), - ..Default::default() - }, - LimitOrder { - sell_token: token_b, - buy_token: token_a, - sell_amount: to_wei(100), - buy_amount: to_wei(90), - kind: OrderKind::Sell, - id: 1.into(), - ..Default::default() - }, - ]; - - let amm_handler = CapturingSettlementHandler::arc(); - let pool = ConstantProductOrder { - address: H160::from_low_u64_be(1), - tokens: TokenPair::new(token_a, token_b).unwrap(), - reserves: (to_wei(1000).as_u128(), to_wei(1000).as_u128()), - fee: Ratio::new(3, 1000), - settlement_handling: amm_handler.clone(), - }; - let result = solve(&without_slippage(), orders.clone(), &pool).unwrap(); - - // Make sure the uniswap interaction is using the correct direction - let interaction = amm_handler.calls()[0].clone(); - assert_eq!(interaction.input_max.token, token_b); - assert_eq!(interaction.output.token, token_a); - - // Make sure the sell amounts +/- uniswap interaction satisfy min_buy amounts - assert!(orders[0].sell_amount + interaction.output.amount >= orders[1].buy_amount); - assert!(orders[1].sell_amount - interaction.input_max.amount > orders[0].buy_amount); - - // Make sure the sell amounts +/- uniswap interaction satisfy expected buy - // amounts given clearing price - let price_a = result.clearing_price(token_a).unwrap(); - let price_b = result.clearing_price(token_b).unwrap(); - - // Multiplying sellAmount with priceA, gives us sell value in "$", divided by - // priceB gives us value in buy token We should have at least as much to - // give (sell amount +/- uniswap) as is expected by the buyer - let expected_buy = (orders[0].sell_amount * price_a).ceil_div(&price_b); - assert!(orders[1].sell_amount - interaction.input_max.amount >= expected_buy); - - let expected_buy = (orders[1].sell_amount * price_b).ceil_div(&price_a); - assert!(orders[0].sell_amount + interaction.input_max.amount >= expected_buy); - } - - #[test] - fn finds_clearing_price_with_sell_orders_on_one_side() { - let token_a = Address::from_low_u64_be(0); - let token_b = Address::from_low_u64_be(1); - let orders = vec![ - LimitOrder { - sell_token: token_a, - buy_token: token_b, - sell_amount: to_wei(40), - buy_amount: to_wei(30), - kind: OrderKind::Sell, - id: 0.into(), - ..Default::default() - }, - LimitOrder { - sell_token: token_a, - buy_token: token_b, - sell_amount: to_wei(100), - buy_amount: to_wei(90), - kind: OrderKind::Sell, - id: 1.into(), - ..Default::default() - }, - ]; - - let amm_handler = CapturingSettlementHandler::arc(); - let pool = ConstantProductOrder { - address: H160::from_low_u64_be(1), - tokens: TokenPair::new(token_a, token_b).unwrap(), - reserves: (to_wei(1_000_000).as_u128(), to_wei(1_000_000).as_u128()), - fee: Ratio::new(3, 1000), - settlement_handling: amm_handler.clone(), - }; - let result = solve(&without_slippage(), orders.clone(), &pool).unwrap(); - - // Make sure the uniswap interaction is using the correct direction - let interaction = amm_handler.calls()[0].clone(); - assert_eq!(interaction.input_max.token, token_a); - assert_eq!(interaction.output.token, token_b); - - // Make sure the sell amounts cover the uniswap in, and min buy amounts are - // covered by uniswap out - assert!(orders[0].sell_amount + orders[1].sell_amount >= interaction.input_max.amount); - assert!(interaction.output.amount >= orders[0].buy_amount + orders[1].buy_amount); - - // Make sure expected buy amounts (given prices) are also covered by uniswap out - // amounts - let price_a = result.clearing_price(token_a).unwrap(); - let price_b = result.clearing_price(token_b).unwrap(); - - let first_expected_buy = orders[0].sell_amount * price_a / price_b; - let second_expected_buy = orders[1].sell_amount * price_a / price_b; - assert!(interaction.output.amount >= first_expected_buy + second_expected_buy); - } - - #[test] - fn finds_clearing_price_with_buy_orders_on_both_sides() { - let token_a = Address::from_low_u64_be(0); - let token_b = Address::from_low_u64_be(1); - let orders = vec![ - LimitOrder { - sell_token: token_a, - buy_token: token_b, - sell_amount: to_wei(40), - buy_amount: to_wei(30), - kind: OrderKind::Buy, - id: 0.into(), - ..Default::default() - }, - LimitOrder { - sell_token: token_b, - buy_token: token_a, - sell_amount: to_wei(100), - buy_amount: to_wei(90), - kind: OrderKind::Buy, - id: 1.into(), - ..Default::default() - }, - ]; - - let amm_handler = CapturingSettlementHandler::arc(); - let pool = ConstantProductOrder { - address: H160::from_low_u64_be(1), - tokens: TokenPair::new(token_a, token_b).unwrap(), - reserves: (to_wei(1000).as_u128(), to_wei(1000).as_u128()), - fee: Ratio::new(3, 1000), - settlement_handling: amm_handler.clone(), - }; - let result = solve(&SlippageContext::default(), orders.clone(), &pool).unwrap(); - - // Make sure the uniswap interaction is using the correct direction - let interaction = amm_handler.calls()[0].clone(); - assert_eq!(interaction.input_max.token, token_b); - assert_eq!(interaction.output.token, token_a); - - // Make sure the buy amounts +/- uniswap interaction satisfy max_sell amounts - assert!(orders[0].sell_amount >= orders[1].buy_amount - interaction.output.amount); - assert!(orders[1].sell_amount >= orders[0].buy_amount + interaction.input_max.amount); - - // Make sure buy sell amounts +/- uniswap interaction satisfy expected sell - // amounts given clearing price - let price_a = result.clearing_price(token_a).unwrap(); - let price_b = result.clearing_price(token_b).unwrap(); - - // Multiplying buyAmount with priceB, gives us sell value in "$", divided by - // priceA gives us value in sell token The seller should expect to sell - // at least as much as we require for the buyer + uniswap. - let expected_sell = orders[0].buy_amount * price_b / price_a; - assert!(orders[1].buy_amount - interaction.input_max.amount <= expected_sell); - - let expected_sell = orders[1].buy_amount * price_a / price_b; - assert!(orders[0].buy_amount + interaction.output.amount <= expected_sell); - } - - #[test] - fn finds_clearing_price_with_buy_orders_and_sell_orders() { - let token_a = Address::from_low_u64_be(0); - let token_b = Address::from_low_u64_be(1); - let orders = vec![ - LimitOrder { - sell_token: token_a, - buy_token: token_b, - sell_amount: to_wei(40), - buy_amount: to_wei(30), - kind: OrderKind::Buy, - id: 0.into(), - ..Default::default() - }, - LimitOrder { - sell_token: token_b, - buy_token: token_a, - sell_amount: to_wei(100), - buy_amount: to_wei(90), - kind: OrderKind::Sell, - id: 1.into(), - ..Default::default() - }, - ]; - - let amm_handler = CapturingSettlementHandler::arc(); - let pool = ConstantProductOrder { - address: H160::from_low_u64_be(1), - tokens: TokenPair::new(token_a, token_b).unwrap(), - reserves: (to_wei(1000).as_u128(), to_wei(1000).as_u128()), - fee: Ratio::new(3, 1000), - settlement_handling: amm_handler.clone(), - }; - let result = solve(&SlippageContext::default(), orders.clone(), &pool).unwrap(); - - // Make sure the uniswap interaction is using the correct direction - let interaction = amm_handler.calls()[0].clone(); - assert_eq!(interaction.input_max.token, token_b); - assert_eq!(interaction.output.token, token_a); - - // Make sure the buy order's sell amount - uniswap interaction satisfies sell - // order's limit - assert!(orders[0].sell_amount >= orders[1].buy_amount - interaction.output.amount); - - // Make sure the sell order's buy amount + uniswap interaction satisfies buy - // order's limit - assert!(orders[1].buy_amount + interaction.input_max.amount >= orders[0].sell_amount); - - // Make sure buy sell amounts +/- uniswap interaction satisfy expected sell - // amounts given clearing price - let price_a = result.clearing_price(token_a).unwrap(); - let price_b = result.clearing_price(token_b).unwrap(); - - // Multiplying buy_amount with priceB, gives us sell value in "$", divided by - // priceA gives us value in sell token The seller should expect to sell - // at least as much as we require for the buyer + uniswap. - let expected_sell = orders[0].buy_amount * price_b / price_a; - assert!(orders[1].buy_amount - interaction.input_max.amount <= expected_sell); - - // Multiplying sell_amount with priceA, gives us sell value in "$", divided by - // priceB gives us value in buy token We should have at least as much to - // give (sell amount + uniswap out) as is expected by the buyer - let expected_buy = orders[1].sell_amount * price_b / price_a; - assert!(orders[0].sell_amount + interaction.output.amount >= expected_buy); - } - - #[test] - fn finds_clearing_without_using_uniswap() { - let token_a = Address::from_low_u64_be(0); - let token_b = Address::from_low_u64_be(1); - let orders = vec![ - LimitOrder { - sell_token: token_a, - buy_token: token_b, - sell_amount: to_wei(1001), - buy_amount: to_wei(1000), - kind: OrderKind::Sell, - id: 0.into(), - ..Default::default() - }, - LimitOrder { - sell_token: token_b, - buy_token: token_a, - sell_amount: to_wei(1001), - buy_amount: to_wei(1000), - kind: OrderKind::Sell, - id: 1.into(), - ..Default::default() - }, - ]; - - let amm_handler = CapturingSettlementHandler::arc(); - let pool = ConstantProductOrder { - address: H160::from_low_u64_be(1), - tokens: TokenPair::new(token_a, token_b).unwrap(), - reserves: (to_wei(1_000_001).as_u128(), to_wei(1_000_000).as_u128()), - fee: Ratio::new(3, 1000), - settlement_handling: amm_handler.clone(), - }; - let result = solve(&SlippageContext::default(), orders, &pool).unwrap(); - assert!(amm_handler.calls().is_empty()); - assert_eq!( - result.clearing_prices(), - &maplit::hashmap! { - token_a => to_wei(1_000_000), - token_b => to_wei(1_000_001) - } - ); - } - - #[test] - fn finds_solution_excluding_orders_whose_limit_price_is_not_satisfiable() { - let token_a = Address::from_low_u64_be(0); - let token_b = Address::from_low_u64_be(1); - let orders = vec![ - // Unreasonable order a -> b - Order { - data: OrderData { - sell_token: token_a, - buy_token: token_b, - sell_amount: to_wei(1), - buy_amount: to_wei(1000), - kind: OrderKind::Sell, - partially_fillable: false, - ..Default::default() - }, - ..Default::default() - } - .into(), - // Reasonable order a -> b - Order { - data: OrderData { - sell_token: token_a, - buy_token: token_b, - sell_amount: to_wei(1000), - buy_amount: to_wei(1000), - kind: OrderKind::Sell, - partially_fillable: false, - ..Default::default() - }, - ..Default::default() - } - .into(), - // Reasonable order b -> a - Order { - data: OrderData { - sell_token: token_b, - buy_token: token_a, - sell_amount: to_wei(1000), - buy_amount: to_wei(1000), - kind: OrderKind::Sell, - partially_fillable: false, - ..Default::default() - }, - ..Default::default() - } - .into(), - // Unreasonable order b -> a - Order { - data: OrderData { - sell_token: token_b, - buy_token: token_a, - sell_amount: to_wei(2), - buy_amount: to_wei(1000), - kind: OrderKind::Sell, - partially_fillable: false, - ..Default::default() - }, - ..Default::default() - } - .into(), - ]; - - let amm_handler = CapturingSettlementHandler::arc(); - let pool = ConstantProductOrder { - address: H160::from_low_u64_be(1), - tokens: TokenPair::new(token_a, token_b).unwrap(), - reserves: (to_wei(1_000_000).as_u128(), to_wei(1_000_000).as_u128()), - fee: Ratio::new(3, 1000), - settlement_handling: amm_handler, - }; - let result = solve(&SlippageContext::default(), orders, &pool).unwrap(); - - assert_eq!(result.traded_orders().count(), 2); - assert!(is_valid_solution(&result)); - } - - #[test] - fn returns_empty_solution_if_orders_have_no_overlap() { - let token_a = Address::from_low_u64_be(0); - let token_b = Address::from_low_u64_be(1); - let orders = vec![ - Order { - data: OrderData { - sell_token: token_a, - buy_token: token_b, - sell_amount: to_wei(900), - buy_amount: to_wei(1000), - kind: OrderKind::Sell, - partially_fillable: false, - ..Default::default() - }, - ..Default::default() - } - .into(), - Order { - data: OrderData { - sell_token: token_b, - buy_token: token_a, - sell_amount: to_wei(900), - buy_amount: to_wei(1000), - kind: OrderKind::Sell, - partially_fillable: false, - ..Default::default() - }, - ..Default::default() - } - .into(), - ]; - - let amm_handler = CapturingSettlementHandler::arc(); - let pool = ConstantProductOrder { - address: H160::from_low_u64_be(1), - tokens: TokenPair::new(token_a, token_b).unwrap(), - reserves: (to_wei(1_000_001).as_u128(), to_wei(1_000_000).as_u128()), - fee: Ratio::new(3, 1000), - settlement_handling: amm_handler, - }; - assert!(solve(&SlippageContext::default(), orders, &pool).is_none()); - } - - #[test] - fn test_is_valid_solution() { - let token_a = Address::from_low_u64_be(0); - let token_b = Address::from_low_u64_be(1); - let orders = vec![ - Order { - data: OrderData { - sell_token: token_a, - buy_token: token_b, - sell_amount: to_wei(10), - buy_amount: to_wei(8), - kind: OrderKind::Sell, - partially_fillable: false, - ..Default::default() - }, - ..Default::default() - }, - Order { - data: OrderData { - sell_token: token_b, - buy_token: token_a, - sell_amount: to_wei(10), - buy_amount: to_wei(9), - kind: OrderKind::Sell, - partially_fillable: false, - ..Default::default() - }, - ..Default::default() - }, - ]; - - let settlement_with_prices = |prices: HashMap| { - let mut settlement = Settlement::new(prices); - for order in orders.iter().cloned() { - let limit_order = LimitOrder::from(order); - let execution = LimitOrderExecution::new( - limit_order.full_execution_amount(), - limit_order.user_fee, - ); - settlement.with_liquidity(&limit_order, execution).unwrap(); - } - settlement - }; - - // Price in the middle is ok - assert!(is_valid_solution(&settlement_with_prices( - maplit::hashmap! { - token_a => to_wei(1), - token_b => to_wei(1) - } - ),)); - - // Price at the limit of first order is ok - assert!(is_valid_solution(&settlement_with_prices( - maplit::hashmap! { - token_a => to_wei(8), - token_b => to_wei(10) - } - ),)); - - // Price at the limit of second order is ok - assert!(is_valid_solution(&settlement_with_prices( - maplit::hashmap! { - token_a => to_wei(10), - token_b => to_wei(9) - } - ),)); - - // Price violating first order is not ok - assert!(!is_valid_solution(&settlement_with_prices( - maplit::hashmap! { - token_a => to_wei(7), - token_b => to_wei(10) - } - ),)); - - // Price violating second order is not ok - assert!(!is_valid_solution(&settlement_with_prices( - maplit::hashmap! { - token_a => to_wei(10), - token_b => to_wei(8) - } - ),)); - } - - #[test] - fn does_not_panic() { - let token_a = Address::from_low_u64_be(0); - let token_b = Address::from_low_u64_be(1); - let orders = vec![ - Order { - data: OrderData { - sell_token: token_a, - buy_token: token_b, - sell_amount: U256::MAX, - buy_amount: 1.into(), - kind: OrderKind::Sell, - partially_fillable: false, - ..Default::default() - }, - ..Default::default() - } - .into(), - Order { - data: OrderData { - sell_token: token_b, - buy_token: token_a, - sell_amount: 1.into(), - buy_amount: 1.into(), - kind: OrderKind::Sell, - partially_fillable: false, - ..Default::default() - }, - ..Default::default() - } - .into(), - ]; - - let amm_handler = CapturingSettlementHandler::arc(); - let pool = ConstantProductOrder { - address: H160::from_low_u64_be(1), - tokens: TokenPair::new(token_a, token_b).unwrap(), - reserves: (u128::MAX, u128::MAX), - fee: Ratio::new(3, 1000), - settlement_handling: amm_handler, - }; - // This line should not panic. - solve(&SlippageContext::default(), orders, &pool); - } - - #[test] - fn reserves_are_too_small() { - let token_a = Address::from_low_u64_be(0); - let token_b = Address::from_low_u64_be(1); - let orders = vec![ - Order { - data: OrderData { - sell_token: token_a, - buy_token: token_b, - sell_amount: 70145218378783248142575u128.into(), - buy_amount: 70123226323u128.into(), - kind: OrderKind::Sell, - partially_fillable: false, - ..Default::default() - }, - ..Default::default() - } - .into(), - Order { - data: OrderData { - sell_token: token_a, - buy_token: token_b, - sell_amount: 900_000_000_000_000u128.into(), - buy_amount: 100.into(), - kind: OrderKind::Sell, - partially_fillable: false, - ..Default::default() - }, - ..Default::default() - } - .into(), - ]; - // Reserves are much smaller than buy amount - let pool = ConstantProductOrder { - address: H160::from_low_u64_be(1), - tokens: TokenPair::new(token_a, token_b).unwrap(), - reserves: (25000075, 2500007500), - fee: Ratio::new(3, 1000), - settlement_handling: CapturingSettlementHandler::arc(), - }; - - // The first order by itself should not be matchable. - assert!(solve(&SlippageContext::default(), orders[0..1].to_vec(), &pool).is_none()); - - // Only the second order should match - let result = solve(&SlippageContext::default(), orders, &pool).unwrap(); - assert_eq!(result.traded_orders().count(), 1); - } - - #[test] - fn rounds_prices_in_favour_of_traders() { - let token_a = Address::from_low_u64_be(0); - let token_b = Address::from_low_u64_be(1); - let orders = vec![ - Order { - data: OrderData { - sell_token: token_a, - buy_token: token_b, - sell_amount: 9_000_000.into(), - buy_amount: 8_500_000.into(), - kind: OrderKind::Sell, - partially_fillable: false, - ..Default::default() - }, - ..Default::default() - } - .into(), - Order { - data: OrderData { - buy_token: token_a, - sell_token: token_b, - buy_amount: 8_000_001.into(), - sell_amount: 8_500_000.into(), - kind: OrderKind::Buy, - partially_fillable: false, - ..Default::default() - }, - ..Default::default() - } - .into(), - ]; - - let pool = Pool::uniswap( - H160::from_low_u64_be(1), - TokenPair::new(token_a, token_b).unwrap(), - (1_000_000_000_000_000_000, 1_000_000_000_000_000_000), - ); - - // Note that these orders have an excess of ~1e6 T_a because the first - // order is a sell order selling 9e6 T_a and the second order is buying - // 8e6 T_a. Use this to compute the exact amount that will get swapped - // with the pool. This will define our prices. - let excess_amount_a = 999_999.into(); - let swapped_amount_b = pool - .get_amount_out(token_b, (excess_amount_a, token_a)) - .unwrap(); - - // The naive solver sets the prices to the the swapped amounts, so: - let expected_prices = hashmap! { - token_a => swapped_amount_b, - token_b => excess_amount_a, - }; - - let settlement = solve(&SlippageContext::default(), orders, &pool.into()).unwrap(); - let trades = settlement.trade_executions().collect::>(); - - // Check the prices are set according to the expected pool swap: - assert_eq!(settlement.clearing_prices(), &expected_prices); - - // Check the executed buy amount gets rounded up for the sell order: - assert_eq!( - trades[0].buy_amount, - U256::from(9_000_000) * expected_prices[&token_a] / expected_prices[&token_b] + 1, - ); - - // Check the executed sell amount gets rounded down for the buy order: - assert_eq!( - trades[1].sell_amount, - U256::from(8_000_001) * expected_prices[&token_a] / expected_prices[&token_b], - ); - } - - #[test] - fn applies_slippage_to_amm_execution() { - let token_a = Address::from_low_u64_be(0); - let token_b = Address::from_low_u64_be(1); - let orders = vec![LimitOrder { - sell_token: token_a, - buy_token: token_b, - sell_amount: to_wei(40), - buy_amount: to_wei(30), - kind: OrderKind::Sell, - id: 0.into(), - ..Default::default() - }]; - - let amm_handler = CapturingSettlementHandler::arc(); - let pool = ConstantProductOrder { - address: H160::from_low_u64_be(1), - tokens: TokenPair::new(token_a, token_b).unwrap(), - reserves: (to_wei(1000).as_u128(), to_wei(1000).as_u128()), - fee: Ratio::new(3, 1000), - settlement_handling: amm_handler.clone(), - }; - let slippage = SlippageContext::default(); - solve(&slippage, orders, &pool).unwrap(); - - assert_eq!( - amm_handler.calls(), - vec![slippage - .apply_to_amm_execution(AmmOrderExecution { - input_max: TokenAmount::new(token_a, to_wei(40)), - output: TokenAmount::new( - token_b, - pool.get_amount_out(token_b, (to_wei(40), token_a)).unwrap() - ), - internalizable: false - }) - .unwrap()], - ); - } -} diff --git a/crates/solvers/src/boundary/baseline.rs b/crates/solvers/src/boundary/baseline.rs index 51a4a8a2ab..b704475ce2 100644 --- a/crates/solvers/src/boundary/baseline.rs +++ b/crates/solvers/src/boundary/baseline.rs @@ -3,7 +3,7 @@ use { crate::{ boundary, - domain::{eth, liquidity, order, solver::baseline}, + domain::{eth, liquidity, order, solver}, }, ethereum_types::{H160, U256}, model::TokenPair, @@ -33,11 +33,7 @@ impl<'a> Solver<'a> { } } - pub fn route( - &self, - request: baseline::Request, - max_hops: usize, - ) -> Option> { + pub fn route(&self, request: solver::Request, max_hops: usize) -> Option> { let candidates = self.base_tokens.path_candidates_with_hops( request.sell.token.0, request.buy.token.0, @@ -95,7 +91,7 @@ impl<'a> Solver<'a> { .max_by_key(|(_, buy)| buy.value)?, }; - baseline::Route::new(segments) + solver::Route::new(segments) } fn traverse_path( @@ -103,7 +99,7 @@ impl<'a> Solver<'a> { path: &[&OnchainLiquidity], mut sell_token: H160, mut sell_amount: U256, - ) -> Option>> { + ) -> Option>> { let mut segments = Vec::new(); for liquidity in path { let reference_liquidity = self @@ -117,7 +113,7 @@ impl<'a> Solver<'a> { .expect("Inconsistent path"); let buy_amount = liquidity.get_amount_out(buy_token, (sell_amount, sell_token))?; - segments.push(baseline::Segment { + segments.push(solver::Segment { liquidity: reference_liquidity, input: eth::Asset { token: eth::TokenAddress(sell_token), diff --git a/crates/solvers/src/boundary/mod.rs b/crates/solvers/src/boundary/mod.rs index 74319cdcdd..3be2864e8d 100644 --- a/crates/solvers/src/boundary/mod.rs +++ b/crates/solvers/src/boundary/mod.rs @@ -3,6 +3,5 @@ pub mod baseline; pub mod liquidity; -pub mod naive; pub type Result = anyhow::Result; diff --git a/crates/solvers/src/boundary/naive.rs b/crates/solvers/src/boundary/naive.rs deleted file mode 100644 index 5a463040b2..0000000000 --- a/crates/solvers/src/boundary/naive.rs +++ /dev/null @@ -1,249 +0,0 @@ -use { - crate::{ - boundary::liquidity::constant_product::to_boundary_pool, - domain::{ - eth, - liquidity, - order, - solution::{self}, - }, - }, - ethereum_types::H160, - itertools::Itertools, - model::order::{Order, OrderClass, OrderData, OrderKind, OrderMetadata, OrderUid}, - num::{BigRational, One}, - shared::external_prices::ExternalPrices, - solver::{ - liquidity::{ - slippage::{SlippageCalculator, SlippageContext}, - AmmOrderExecution, - ConstantProductOrder, - Exchange, - LimitOrder, - LimitOrderExecution, - LimitOrderId, - SettlementHandling, - }, - settlement::SettlementEncoder, - solver::naive_solver, - }, - std::sync::{Arc, Mutex}, -}; - -pub fn solve( - orders: &[&order::Order], - liquidity: &liquidity::Liquidity, -) -> Option { - let pool = match &liquidity.state { - liquidity::State::ConstantProduct(pool) => pool, - _ => return None, - }; - - // Note that the `order::Order` -> `boundary::LimitOrder` mapping here is - // not exact. Among other things, the signature and various signed order - // fields are missing from the `order::Order` data that the solver engines - // have access to. This means that the naive solver in the `solver` crate - // will encode "incorrect" settlements. This is fine, since we give it just - // enough data to compute the correct swapped orders and the swap amounts - // which is what the naive solver in the `solvers` crate cares about. The - // `driver` is then responsible for encoding the solution into a valid - // settlement transaction anyway. - let boundary_orders = orders - .iter() - // The naive solver currently doesn't support limit orders, so filter them out. - .filter(|order| !order.solver_determines_fee()) - .map(|order| LimitOrder { - id: match order.class { - order::Class::Market => LimitOrderId::Market(OrderUid(order.uid.0)), - order::Class::Limit => LimitOrderId::Limit(OrderUid(order.uid.0)), - }, - sell_token: order.sell.token.0, - buy_token: order.buy.token.0, - sell_amount: order.sell.amount, - buy_amount: order.buy.amount, - kind: match order.side { - order::Side::Buy => OrderKind::Buy, - order::Side::Sell => OrderKind::Sell, - }, - partially_fillable: order.partially_fillable, - user_fee: 0.into(), - settlement_handling: Arc::new(OrderHandler { - order: Order { - metadata: OrderMetadata { - uid: OrderUid(order.uid.0), - class: match order.class { - order::Class::Market => OrderClass::Market, - order::Class::Limit => OrderClass::Limit, - }, - solver_fee: 0.into(), - ..Default::default() - }, - data: OrderData { - sell_token: order.sell.token.0, - buy_token: order.buy.token.0, - sell_amount: order.sell.amount, - buy_amount: order.buy.amount, - fee_amount: 0.into(), - kind: match order.side { - order::Side::Buy => OrderKind::Buy, - order::Side::Sell => OrderKind::Sell, - }, - partially_fillable: order.partially_fillable, - ..Default::default() - }, - ..Default::default() - }, - }), - exchange: Exchange::GnosisProtocol, - }) - .collect_vec(); - - let slippage = Slippage::new(pool.tokens()); - let pool_handler = Arc::new(PoolHandler::default()); - let boundary_pool = ConstantProductOrder::for_pool( - to_boundary_pool(liquidity.address, pool)?, - pool_handler.clone(), - ); - - let boundary_solution = - naive_solver::solve(&slippage.context(), boundary_orders, &boundary_pool)?; - - let swap = pool_handler.swap.lock().unwrap().take(); - Some(solution::Solution { - id: Default::default(), - prices: solution::ClearingPrices::new( - boundary_solution - .clearing_prices() - .iter() - .map(|(token, price)| (eth::TokenAddress(*token), *price)), - ), - trades: boundary_solution - .traded_orders() - .map(|order| { - solution::Trade::Fulfillment( - solution::Fulfillment::fill( - orders - .iter() - .copied() - .find(|o| o.uid.0 == order.metadata.uid.0) - .unwrap() - .clone(), - ) - .expect("all orders can be filled, as limit orders are filtered out"), - ) - }) - .collect(), - // We can skip computing a gas estimate here because that is only used by the protocol - // when quoting trades. And because the naive solver is not able to solve single order - // auctions (which is how we model a /quote request) it can not be used for - // quoting anyway. - gas: None, - pre_interactions: vec![], - interactions: swap - .into_iter() - .map(|(input, output)| { - solution::Interaction::Liquidity(solution::LiquidityInteraction { - liquidity: liquidity.clone(), - input, - output, - internalize: false, - }) - }) - .collect(), - post_interactions: vec![], - }) -} - -// Beyond this point is... well... nameless and boundless chaos. The -// unfathomable horrors that follow are not for the faint of heart! -// -// Joking aside, the existing naive solver implementation is tightly coupled -// with the `Settlement` and `SettlementEncoder` types in the `solver` crate. -// This means that there is no convenient way to say: "please compute a solution -// given this list of orders and constant product pool" without it creating a -// full settlement for encoding. In order to adapt that API into something that -// is useful in this boundary module, we create a fake slippage context that -// applies 0 slippage (so that we can recover the exact executed amounts from -// the constant product pool) and we create capturing settlement handler -// implementations that record the swap that gets added to each settlement so -// that it can be recovered later to build a solution. - -struct Slippage { - calculator: SlippageCalculator, - prices: ExternalPrices, -} - -impl Slippage { - fn new(tokens: liquidity::TokenPair) -> Self { - // We don't actually want to include slippage yet. This is because the - // Naive solver encodes liquidity interactions and the driver is - // responsible for applying slippage to those. Create a dummy slippage - // context for use with the legacy Naive solver. - let (token0, token1) = tokens.get(); - Self { - calculator: SlippageCalculator::from_bps(0, None), - prices: ExternalPrices::new( - H160::default(), - [ - (token0.0, BigRational::one()), - (token1.0, BigRational::one()), - ] - .into_iter() - .collect(), - ) - .unwrap(), - } - } - - fn context(&self) -> SlippageContext { - self.calculator.context(&self.prices) - } -} - -struct OrderHandler { - order: Order, -} - -impl SettlementHandling for OrderHandler { - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn encode( - &self, - execution: LimitOrderExecution, - encoder: &mut SettlementEncoder, - ) -> anyhow::Result<()> { - encoder.add_trade(self.order.clone(), execution.filled, execution.fee)?; - Ok(()) - } -} - -#[derive(Default)] -struct PoolHandler { - swap: Mutex>, -} - -impl SettlementHandling for PoolHandler { - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn encode( - &self, - execution: AmmOrderExecution, - _: &mut SettlementEncoder, - ) -> anyhow::Result<()> { - *self.swap.lock().unwrap() = Some(( - eth::Asset { - token: eth::TokenAddress(execution.input_max.token), - amount: execution.input_max.amount, - }, - eth::Asset { - token: eth::TokenAddress(execution.output.token), - amount: execution.output.amount, - }, - )); - Ok(()) - } -} diff --git a/crates/solvers/src/domain/solver/baseline.rs b/crates/solvers/src/domain/solver.rs similarity index 97% rename from crates/solvers/src/domain/solver/baseline.rs rename to crates/solvers/src/domain/solver.rs index 83adb83127..9d991d5c60 100644 --- a/crates/solvers/src/domain/solver/baseline.rs +++ b/crates/solvers/src/domain/solver.rs @@ -15,12 +15,13 @@ use { order::{self, Order}, solution, }, + infra::metrics, }, ethereum_types::U256, std::{cmp, collections::HashSet, sync::Arc}, }; -pub struct Baseline(Arc); +pub struct Solver(Arc); /// The amount of time we aim the solver to finish before the final deadline is /// reached. @@ -66,7 +67,7 @@ struct Inner { native_token_price_estimation_amount: eth::U256, } -impl Baseline { +impl Solver { /// Creates a new baseline solver for the specified configuration. pub fn new(config: Config) -> Self { Self(Arc::new(Inner { @@ -82,12 +83,14 @@ impl Baseline { /// Solves the specified auction, returning a vector of all possible /// solutions. pub async fn solve(&self, auction: auction::Auction) -> Vec { + metrics::solve(&auction); + let deadline = auction.deadline.clone(); // Make sure to push the CPU-heavy code to a separate thread in order to // not lock up the [`tokio`] runtime and cause it to slow down handling // the real async things. For larger settlements, this can block in the // 100s of ms. let (sender, mut receiver) = tokio::sync::mpsc::unbounded_channel(); - let deadline = auction + let remaining = auction .deadline .clone() .reduce(DEADLINE_SLACK) @@ -101,7 +104,7 @@ impl Baseline { inner.solve(auction, sender); }; - if tokio::time::timeout(deadline, tokio::spawn(background_work)) + if tokio::time::timeout(remaining, tokio::spawn(background_work)) .await .is_err() { @@ -112,6 +115,7 @@ impl Baseline { while let Ok(solution) = receiver.try_recv() { solutions.push(solution); } + metrics::solved(&deadline, &solutions); solutions } } diff --git a/crates/solvers/src/domain/solver/mod.rs b/crates/solvers/src/domain/solver/mod.rs deleted file mode 100644 index cf4d134583..0000000000 --- a/crates/solvers/src/domain/solver/mod.rs +++ /dev/null @@ -1,30 +0,0 @@ -use crate::{ - domain::{auction, solution}, - infra::metrics, -}; - -pub mod baseline; -pub mod naive; - -pub use self::{baseline::Baseline, naive::Naive}; - -pub enum Solver { - Baseline(Baseline), - Naive(Naive), -} - -impl Solver { - /// Solves a given auction and returns multiple solutions. We allow - /// returning multiple solutions to later merge multiple non-overlapping - /// solutions to get one big more gas efficient solution. - pub async fn solve(&self, auction: auction::Auction) -> Vec { - metrics::solve(&auction); - let deadline = auction.deadline.clone(); - let solutions = match self { - Solver::Baseline(solver) => solver.solve(auction).await, - Solver::Naive(solver) => solver.solve(auction).await, - }; - metrics::solved(&deadline, &solutions); - solutions - } -} diff --git a/crates/solvers/src/domain/solver/naive.rs b/crates/solvers/src/domain/solver/naive.rs deleted file mode 100644 index 8b31ff7227..0000000000 --- a/crates/solvers/src/domain/solver/naive.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! "Naive" solver implementation. -//! -//! The naive solver is a solver that collects all orders over a single token -//! pair, computing how many leftover tokens can't be matched peer-to-peer, and -//! matching that excess over a Uniswap V2 pool. This allows for naive -//! coincidence of wants over a single Uniswap V2 pools. - -use { - crate::{ - boundary, - domain::{auction, eth, liquidity, order, solution}, - }, - std::collections::HashMap, -}; - -pub struct Naive; - -impl Naive { - /// Solves the specified auction, returning a vector of all possible - /// solutions. - pub async fn solve(&self, auction: auction::Auction) -> Vec { - // Make sure to push the CPU-heavy code to a separate thread in order to - // not lock up the [`tokio`] runtime and cause it to slow down handling - // the real async things. - let span = tracing::Span::current(); - tokio::task::spawn_blocking(move || { - let _entered = span.enter(); - let groups = group_by_token_pair(&auction); - groups - .values() - .enumerate() - .filter_map(|(i, group)| { - boundary::naive::solve(&group.orders, group.liquidity).map(|solution| { - let gas = solution::INITIALIZATION_COST - + solution::SETTLEMENT - + solution::ERC20_TRANSFER * solution.trades.len() as u64 * 2 - + group.liquidity.gas.0.as_u64(); // this is pessimistic in case the pool is not used - solution - .with_gas(eth::Gas(gas.into())) - .with_id(solution::Id(i as u64)) - }) - }) - .map(|solution| solution.with_buffers_internalizations(&auction.tokens)) - .collect() - }) - .await - .expect("naive solver unexpected panic") - } -} - -#[derive(Debug)] -struct Group<'a> { - orders: Vec<&'a order::Order>, - liquidity: &'a liquidity::Liquidity, - pool: &'a liquidity::constant_product::Pool, -} - -type Groups<'a> = HashMap>; - -/// Groups an auction by token pairs, where each group contains all orders over -/// the token pair as well as the **deepest** constant product pool (i.e. most -/// liquidity, which translates to a higher `K` value for Uniswap V2 style -/// constant product pools). -fn group_by_token_pair(auction: &auction::Auction) -> Groups { - let mut groups = Groups::new(); - - for liquidity in &auction.liquidity { - let pool = match &liquidity.state { - liquidity::State::ConstantProduct(pool) => pool, - _ => continue, - }; - - groups - .entry(pool.tokens()) - .and_modify(|group| { - if group.pool.k() < pool.k() { - group.liquidity = liquidity; - group.pool = pool; - } - }) - .or_insert_with(|| Group { - orders: Vec::new(), - liquidity, - pool, - }); - } - - for order in &auction.orders { - // The naive solver algorithm is sensitive to 0-amount orders (i.e. they - // cause panics). Make sure we don't consider them. - if order.sell.amount.is_zero() || order.buy.amount.is_zero() { - continue; - } - - let tokens = match liquidity::TokenPair::new(order.sell.token, order.buy.token) { - Some(value) => value, - None => continue, - }; - - groups - .entry(tokens) - .and_modify(|group| group.orders.push(order)); - } - - groups.retain(|_, group| !group.orders.is_empty()); - groups -} diff --git a/crates/solvers/src/infra/cli.rs b/crates/solvers/src/infra/cli.rs index 3130bbd9cd..002ba141da 100644 --- a/crates/solvers/src/infra/cli.rs +++ b/crates/solvers/src/infra/cli.rs @@ -35,6 +35,4 @@ pub enum Command { #[clap(long, env)] config: PathBuf, }, - /// optimistically batch similar orders and get difference from AMMs - Naive, } diff --git a/crates/solvers/src/infra/config/baseline.rs b/crates/solvers/src/infra/config.rs similarity index 81% rename from crates/solvers/src/infra/config/baseline.rs rename to crates/solvers/src/infra/config.rs index 354d383bff..9f17f40c66 100644 --- a/crates/solvers/src/infra/config/baseline.rs +++ b/crates/solvers/src/infra/config.rs @@ -1,7 +1,7 @@ use { crate::{ - domain::{eth, solver::baseline}, - infra::{config::unwrap_or_log, contracts}, + domain::{eth, solver}, + infra::contracts, util::serialize, }, chain::Chain, @@ -9,7 +9,7 @@ use { serde::Deserialize, serde_with::serde_as, shared::price_estimation::gas::SETTLEMENT_OVERHEAD, - std::path::Path, + std::{fmt::Debug, path::Path}, tokio::fs, }; @@ -55,7 +55,7 @@ struct Config { /// # Panics /// /// This method panics if the config is invalid or on I/O errors. -pub async fn load(path: &Path) -> baseline::Config { +pub async fn load(path: &Path) -> solver::Config { let data = fs::read_to_string(path) .await .unwrap_or_else(|e| panic!("I/O error while reading {path:?}: {e:?}")); @@ -73,7 +73,7 @@ pub async fn load(path: &Path) -> baseline::Config { ), }; - baseline::Config { + solver::Config { weth, base_tokens: config .base_tokens @@ -87,6 +87,24 @@ pub async fn load(path: &Path) -> baseline::Config { } } +/// Unwraps result or logs a `TOML` parsing error. +fn unwrap_or_log(result: Result, path: &P) -> T +where + E: Debug, + P: Debug, +{ + result.unwrap_or_else(|err| { + if std::env::var("TOML_TRACE_ERROR").is_ok_and(|v| v == "1") { + panic!("failed to parse TOML config at {path:?}: {err:#?}") + } else { + panic!( + "failed to parse TOML config at: {path:?}. Set TOML_TRACE_ERROR=1 to print \ + parsing error but this may leak secrets." + ) + } + }) +} + /// Returns minimum gas used for settling a single order. /// (not accounting for the cost of additional interactions) fn default_gas_offset() -> i64 { diff --git a/crates/solvers/src/infra/config/mod.rs b/crates/solvers/src/infra/config/mod.rs deleted file mode 100644 index 0804e5834a..0000000000 --- a/crates/solvers/src/infra/config/mod.rs +++ /dev/null @@ -1,21 +0,0 @@ -use std::fmt::Debug; - -pub mod baseline; - -/// Unwraps result or logs a `TOML` parsing error. -fn unwrap_or_log(result: Result, path: &P) -> T -where - E: Debug, - P: Debug, -{ - result.unwrap_or_else(|err| { - if std::env::var("TOML_TRACE_ERROR").is_ok_and(|v| v == "1") { - panic!("failed to parse TOML config at {path:?}: {err:#?}") - } else { - panic!( - "failed to parse TOML config at: {path:?}. Set TOML_TRACE_ERROR=1 to print \ - parsing error but this may leak secrets." - ) - } - }) -} diff --git a/crates/solvers/src/run.rs b/crates/solvers/src/run.rs index e047643453..1b2e212db9 100644 --- a/crates/solvers/src/run.rs +++ b/crates/solvers/src/run.rs @@ -2,7 +2,7 @@ use tokio::signal::unix::{self, SignalKind}; use { crate::{ - domain::solver::{self, Solver}, + domain::solver, infra::{cli, config}, }, clap::Parser, @@ -30,10 +30,9 @@ async fn run_with(args: cli::Args, bind: Option>) { let solver = match args.command { cli::Command::Baseline { config } => { - let config = config::baseline::load(&config).await; - Solver::Baseline(solver::Baseline::new(config)) + let config = config::load(&config).await; + solver::Solver::new(config) } - cli::Command::Naive => Solver::Naive(solver::Naive), }; crate::api::Api { diff --git a/crates/solvers/src/tests/baseline/bal_liquidity.rs b/crates/solvers/src/tests/cases/bal_liquidity.rs similarity index 100% rename from crates/solvers/src/tests/baseline/bal_liquidity.rs rename to crates/solvers/src/tests/cases/bal_liquidity.rs diff --git a/crates/solvers/src/tests/baseline/buy_order_rounding.rs b/crates/solvers/src/tests/cases/buy_order_rounding.rs similarity index 100% rename from crates/solvers/src/tests/baseline/buy_order_rounding.rs rename to crates/solvers/src/tests/cases/buy_order_rounding.rs diff --git a/crates/solvers/src/tests/baseline/direct_swap.rs b/crates/solvers/src/tests/cases/direct_swap.rs similarity index 100% rename from crates/solvers/src/tests/baseline/direct_swap.rs rename to crates/solvers/src/tests/cases/direct_swap.rs diff --git a/crates/solvers/src/tests/baseline/internalization.rs b/crates/solvers/src/tests/cases/internalization.rs similarity index 100% rename from crates/solvers/src/tests/baseline/internalization.rs rename to crates/solvers/src/tests/cases/internalization.rs diff --git a/crates/solvers/src/tests/baseline/limit_order_quoting.rs b/crates/solvers/src/tests/cases/limit_order_quoting.rs similarity index 100% rename from crates/solvers/src/tests/baseline/limit_order_quoting.rs rename to crates/solvers/src/tests/cases/limit_order_quoting.rs diff --git a/crates/solvers/src/tests/baseline/mod.rs b/crates/solvers/src/tests/cases/mod.rs similarity index 100% rename from crates/solvers/src/tests/baseline/mod.rs rename to crates/solvers/src/tests/cases/mod.rs diff --git a/crates/solvers/src/tests/baseline/partial_fill.rs b/crates/solvers/src/tests/cases/partial_fill.rs similarity index 100% rename from crates/solvers/src/tests/baseline/partial_fill.rs rename to crates/solvers/src/tests/cases/partial_fill.rs diff --git a/crates/solvers/src/tests/mod.rs b/crates/solvers/src/tests/mod.rs index f12dc63a5a..fcf64af0e0 100644 --- a/crates/solvers/src/tests/mod.rs +++ b/crates/solvers/src/tests/mod.rs @@ -10,8 +10,7 @@ use { tokio::{sync::oneshot, task::JoinHandle}, }; -mod baseline; -mod naive; +mod cases; /// A solver engine handle for E2E testing. pub struct SolverEngine { diff --git a/crates/solvers/src/tests/naive/extract_deepest_pool.rs b/crates/solvers/src/tests/naive/extract_deepest_pool.rs deleted file mode 100644 index 2f046cb6ba..0000000000 --- a/crates/solvers/src/tests/naive/extract_deepest_pool.rs +++ /dev/null @@ -1,139 +0,0 @@ -//! Test that demonstrates that the Naive solver will use the **deepest** pool -//! for solving when multiple different UniswapV2-like pools exist for a -//! specific token pair. -//! -//! The rationale behind this choise is that the deepest pools are typically the -//! most representative of the actual token price, and in general give better -//! prices for larger orders (in theory, for smaller orders it is possible for -//! the shallow pool to offer better prices, but this should be in exceptional -//! cases, and not worth considering in the solver in order to keep things -//! simple). - -use {crate::tests, serde_json::json}; - -#[tokio::test] -async fn test() { - let engine = tests::SolverEngine::new("naive", tests::Config::None).await; - - let solution = engine - .solve(json!({ - "id": "1", - "tokens": {}, - "orders": [ - { - "uid": "0x2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a\ - 2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a\ - 2a2a2a2a", - "sellToken": "0x0101010101010101010101010101010101010101", - "buyToken": "0x0202020202020202020202020202020202020202", - "sellAmount": "100", - "fullSellAmount": "1000000000000000000", - "buyAmount": "1", - "fullBuyAmount": "1000000000000000000000", - "feePolicies": [], - "validTo": 0, - "kind": "sell", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - ], - "liquidity": [ - { - "kind": "constantProduct", - "tokens": { - "0x0101010101010101010101010101010101010101": { - "balance": "100" - }, - "0x0202020202020202020202020202020202020202": { - "balance": "100" - } - }, - "fee": "0.003", - "id": "0", - "address": "0x2222222222222222222222222222222222222222", - "router": "0xffffffffffffffffffffffffffffffffffffffff", - "gasEstimate": "0" - }, - { - "kind": "constantProduct", - "tokens": { - "0x0101010101010101010101010101010101010101": { - "balance": "10000000" - }, - "0x0202020202020202020202020202020202020202": { - "balance": "10000000" - } - }, - "fee": "0.003", - "id": "1", - "address": "0x1111111111111111111111111111111111111111", - "router": "0xffffffffffffffffffffffffffffffffffffffff", - "gasEstimate": "0" - }, - { - "kind": "constantProduct", - "tokens": { - "0x0303030303030303030303030303030303030303": { - "balance": "10000000000000000" - }, - "0x0404040404040404040404040404040404040404": { - "balance": "10000000000000000" - } - }, - "fee": "0.003", - "id": "2", - "address": "0x3333333333333333333333333333333333333333", - "router": "0xffffffffffffffffffffffffffffffffffffffff", - "gasEstimate": "0" - }, - ], - "effectiveGasPrice": "0", - "deadline": "2106-01-01T00:00:00.000Z", - "surplusCapturingJitOrderOwners": [] - })) - .await; - - assert_eq!( - solution, - json!({ - "solutions": [{ - "id": 0, - "prices": { - "0x0101010101010101010101010101010101010101": "99", - "0x0202020202020202020202020202020202020202": "100", - }, - "trades": [ - { - "kind": "fulfillment", - "order": "0x2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a\ - 2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a\ - 2a2a2a2a", - "executedAmount": "100", - }, - ], - "preInteractions": [], - "interactions": [ - { - "kind": "liquidity", - "internalize": false, - "id": "1", - "inputToken": "0x0101010101010101010101010101010101010101", - "outputToken": "0x0202020202020202020202020202020202020202", - "inputAmount": "100", - "outputAmount": "99" - }, - ], - "postInteractions": [], - "gas": 94391, - }] - }), - ); -} diff --git a/crates/solvers/src/tests/naive/filters_out_of_price_orders.rs b/crates/solvers/src/tests/naive/filters_out_of_price_orders.rs deleted file mode 100644 index 8ea6f874e3..0000000000 --- a/crates/solvers/src/tests/naive/filters_out_of_price_orders.rs +++ /dev/null @@ -1,172 +0,0 @@ -//! This test verifies that orders that are out of price get filtered out, but -//! a solution with the "reasonably" priced orders is produced. - -use {crate::tests, serde_json::json}; - -#[tokio::test] -async fn sell_orders_on_both_sides() { - let engine = tests::SolverEngine::new("naive", tests::Config::None).await; - - let solution = engine - .solve(json!({ - "id": "1", - "tokens": {}, - "orders": [ - // Unreasonable order a -> b - { - "uid": "0x0101010101010101010101010101010101010101010101010101010101010101\ - 0101010101010101010101010101010101010101\ - 01010101", - "sellToken": "0x000000000000000000000000000000000000000a", - "buyToken": "0x000000000000000000000000000000000000000b", - "sellAmount": "1000000000000000000", - "fullSellAmount": "1000000000000000000", - "buyAmount": "1000000000000000000000", - "fullBuyAmount": "1000000000000000000000", - "feePolicies": [], - "validTo": 0, - "kind": "sell", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - // Reasonable order a -> b - { - "uid": "0x0202020202020202020202020202020202020202020202020202020202020202\ - 0202020202020202020202020202020202020202\ - 02020202", - "sellToken": "0x000000000000000000000000000000000000000a", - "buyToken": "0x000000000000000000000000000000000000000b", - "sellAmount": "1000000000000000000000", - "fullSellAmount": "1000000000000000000000", - "buyAmount": "1000000000000000000000", - "fullBuyAmount": "1000000000000000000000", - "feePolicies": [], - "validTo": 0, - "kind": "sell", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - // Reasonable order a -> b - { - "uid": "0x0303030303030303030303030303030303030303030303030303030303030303\ - 0303030303030303030303030303030303030303\ - 03030303", - "sellToken": "0x000000000000000000000000000000000000000b", - "buyToken": "0x000000000000000000000000000000000000000a", - "sellAmount": "1000000000000000000000", - "fullSellAmount": "1000000000000000000000", - "buyAmount": "1000000000000000000000", - "fullBuyAmount": "1000000000000000000000", - "feePolicies": [], - "validTo": 0, - "kind": "sell", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - // Unreasonable order a -> b - { - "uid": "0x0404040404040404040404040404040404040404040404040404040404040404\ - 0404040404040404040404040404040404040404\ - 04040404", - "sellToken": "0x000000000000000000000000000000000000000b", - "buyToken": "0x000000000000000000000000000000000000000a", - "sellAmount": "2000000000000000000", - "fullSellAmount": "2000000000000000000", - "buyAmount": "1000000000000000000000", - "fullBuyAmount": "1000000000000000000000", - "feePolicies": [], - "validTo": 0, - "kind": "sell", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - ], - "liquidity": [ - { - "kind": "constantProduct", - "tokens": { - "0x000000000000000000000000000000000000000a": { - "balance": "1000000000000000000000000" - }, - "0x000000000000000000000000000000000000000b": { - "balance": "1000000000000000000000000" - } - }, - "fee": "0.003", - "id": "0", - "address": "0xffffffffffffffffffffffffffffffffffffffff", - "router": "0xffffffffffffffffffffffffffffffffffffffff", - "gasEstimate": "110000" - }, - ], - "effectiveGasPrice": "15000000000", - "deadline": "2106-01-01T00:00:00.000Z", - "surplusCapturingJitOrderOwners": [] - })) - .await; - - assert_eq!( - solution, - json!({ - "solutions": [{ - "id": 0, - "prices": { - "0x000000000000000000000000000000000000000a": "1000000000000000000000000", - "0x000000000000000000000000000000000000000b": "1000000000000000000000000", - }, - "trades": [ - { - "kind": "fulfillment", - "order": "0x0303030303030303030303030303030303030303030303030303030303030303\ - 0303030303030303030303030303030303030303\ - 03030303", - "executedAmount": "1000000000000000000000", - }, - { - "kind": "fulfillment", - "order": "0x0202020202020202020202020202020202020202020202020202020202020202\ - 0202020202020202020202020202020202020202\ - 02020202", - "executedAmount": "1000000000000000000000", - }, - ], - "preInteractions": [], - "interactions": [], - "postInteractions": [], - "gas": 259417, - }] - }), - ); -} diff --git a/crates/solvers/src/tests/naive/limit_order_price.rs b/crates/solvers/src/tests/naive/limit_order_price.rs deleted file mode 100644 index 0ac2df06ab..0000000000 --- a/crates/solvers/src/tests/naive/limit_order_price.rs +++ /dev/null @@ -1,70 +0,0 @@ -//! This test verifies that the limit order's limit price is respected after -//! surplus fees are taken from the order. - -use {crate::tests, serde_json::json}; - -#[tokio::test] -async fn test() { - let engine = tests::SolverEngine::new("naive", tests::Config::None).await; - - let solution = engine - .solve(json!({ - "id": "1", - "tokens": {}, - "orders": [ - { - "uid": "0x2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a\ - 2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a\ - 2a2a2a2a", - "sellToken": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", - "buyToken": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", - "sellAmount": "22397494", - "fullSellAmount": "1000000000000000000", - "buyAmount": "18477932550000000", - "fullBuyAmount": "1000000000000000000000", - "feePolicies": [], - "validTo": 0, - "kind": "sell", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "limit", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - ], - "liquidity": [ - { - "kind": "constantProduct", - "tokens": { - "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48": { - "balance": "36338096110368" - }, - "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2": { - "balance": "30072348537379906026018" - } - }, - "fee": "0.003", - "id": "0", - "address": "0x0000000000000000000000000000000000000000", - "router": "0xffffffffffffffffffffffffffffffffffffffff", - "gasEstimate": "110000" - }, - ], - "effectiveGasPrice": "15000000000", - "deadline": "2106-01-01T00:00:00.000Z", - "surplusCapturingJitOrderOwners": [] - })) - .await; - - assert_eq!( - solution, - json!({ - "solutions": [] - }), - ); -} diff --git a/crates/solvers/src/tests/naive/matches_orders.rs b/crates/solvers/src/tests/naive/matches_orders.rs deleted file mode 100644 index 031224f057..0000000000 --- a/crates/solvers/src/tests/naive/matches_orders.rs +++ /dev/null @@ -1,508 +0,0 @@ -//! Tests for various permutiations of matching combinatinos of sell and buy -//! orders. - -use {crate::tests, serde_json::json}; - -#[tokio::test] -async fn sell_orders_on_both_sides() { - let engine = tests::SolverEngine::new("naive", tests::Config::None).await; - - let solution = engine - .solve(json!({ - "id": "1", - "tokens": {}, - "orders": [ - { - "uid": "0x0101010101010101010101010101010101010101010101010101010101010101\ - 0101010101010101010101010101010101010101\ - 01010101", - "sellToken": "0x000000000000000000000000000000000000000a", - "buyToken": "0x000000000000000000000000000000000000000b", - "sellAmount": "40000000000000000000", - "fullSellAmount": "40000000000000000000", - "buyAmount": "30000000000000000000", - "fullBuyAmount": "30000000000000000000", - "feePolicies": [], - "validTo": 0, - "kind": "sell", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - { - "uid": "0x0202020202020202020202020202020202020202020202020202020202020202\ - 0202020202020202020202020202020202020202\ - 02020202", - "sellToken": "0x000000000000000000000000000000000000000b", - "buyToken": "0x000000000000000000000000000000000000000a", - "sellAmount": "100000000000000000000", - "fullSellAmount": "100000000000000000000", - "buyAmount": "90000000000000000000", - "fullBuyAmount": "90000000000000000000", - "feePolicies": [], - "validTo": 0, - "kind": "sell", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - ], - "liquidity": [ - { - "kind": "constantProduct", - "tokens": { - "0x000000000000000000000000000000000000000a": { - "balance": "1000000000000000000000" - }, - "0x000000000000000000000000000000000000000b": { - "balance": "1000000000000000000000" - } - }, - "fee": "0.003", - "id": "0", - "address": "0xffffffffffffffffffffffffffffffffffffffff", - "router": "0xffffffffffffffffffffffffffffffffffffffff", - "gasEstimate": "110000" - }, - ], - "effectiveGasPrice": "15000000000", - "deadline": "2106-01-01T00:00:00.000Z", - "surplusCapturingJitOrderOwners": [] - })) - .await; - - assert_eq!( - solution, - json!({ - "solutions": [{ - "id": 0, - "prices": { - "0x000000000000000000000000000000000000000a": "57576575881490625723", - "0x000000000000000000000000000000000000000b": "54287532963535509684", - }, - "trades": [ - { - "kind": "fulfillment", - "order": "0x0101010101010101010101010101010101010101010101010101010101010101\ - 0101010101010101010101010101010101010101\ - 01010101", - "executedAmount": "40000000000000000000", - }, - { - "kind": "fulfillment", - "order": "0x0202020202020202020202020202020202020202020202020202020202020202\ - 0202020202020202020202020202020202020202\ - 02020202", - "executedAmount": "100000000000000000000", - }, - ], - "preInteractions": [], - "interactions": [ - { - "kind": "liquidity", - "internalize": false, - "id": "0", - "inputToken": "0x000000000000000000000000000000000000000b", - "outputToken": "0x000000000000000000000000000000000000000a", - "inputAmount": "57576575881490625723", - "outputAmount": "54287532963535509685" - }, - ], - "postInteractions": [], - "gas": 259417, - }] - }), - ); -} - -#[tokio::test] -async fn sell_orders_on_one_side() { - let engine = tests::SolverEngine::new("naive", tests::Config::None).await; - - let solution = engine - .solve(json!({ - "id": "1", - "tokens": {}, - "orders": [ - { - "uid": "0x0101010101010101010101010101010101010101010101010101010101010101\ - 0101010101010101010101010101010101010101\ - 01010101", - "sellToken": "0x000000000000000000000000000000000000000a", - "buyToken": "0x000000000000000000000000000000000000000b", - "sellAmount": "40000000000000000000", - "fullSellAmount": "40000000000000000000", - "buyAmount": "30000000000000000000", - "fullBuyAmount": "30000000000000000000", - "feePolicies": [], - "validTo": 0, - "kind": "sell", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - { - "uid": "0x0202020202020202020202020202020202020202020202020202020202020202\ - 0202020202020202020202020202020202020202\ - 02020202", - "sellToken": "0x000000000000000000000000000000000000000a", - "buyToken": "0x000000000000000000000000000000000000000b", - "sellAmount": "100000000000000000000", - "fullSellAmount": "100000000000000000000", - "buyAmount": "90000000000000000000", - "fullBuyAmount": "90000000000000000000", - "feePolicies": [], - "validTo": 0, - "kind": "sell", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - ], - "liquidity": [ - { - "kind": "constantProduct", - "tokens": { - "0x000000000000000000000000000000000000000a": { - "balance": "1000000000000000000000000" - }, - "0x000000000000000000000000000000000000000b": { - "balance": "1000000000000000000000000" - } - }, - "fee": "0.003", - "id": "0", - "address": "0xffffffffffffffffffffffffffffffffffffffff", - "router": "0xffffffffffffffffffffffffffffffffffffffff", - "gasEstimate": "110000" - }, - ], - "effectiveGasPrice": "15000000000", - "deadline": "2106-01-01T00:00:00.000Z", - "surplusCapturingJitOrderOwners": [] - })) - .await; - - assert_eq!( - solution, - json!({ - "solutions": [{ - "id": 0, - "prices": { - "0x000000000000000000000000000000000000000a": "139560520142598496101", - "0x000000000000000000000000000000000000000b": "140000000000000000000", - }, - "trades": [ - { - "kind": "fulfillment", - "order": "0x0101010101010101010101010101010101010101010101010101010101010101\ - 0101010101010101010101010101010101010101\ - 01010101", - "executedAmount": "40000000000000000000", - }, - { - "kind": "fulfillment", - "order": "0x0202020202020202020202020202020202020202020202020202020202020202\ - 0202020202020202020202020202020202020202\ - 02020202", - "executedAmount": "100000000000000000000", - }, - ], - "preInteractions": [], - "interactions": [ - { - "kind": "liquidity", - "internalize": false, - "id": "0", - "inputToken": "0x000000000000000000000000000000000000000a", - "outputToken": "0x000000000000000000000000000000000000000b", - "inputAmount": "140000000000000000000", - "outputAmount": "139560520142598496102" - }, - ], - "postInteractions": [], - "gas": 259417, - }] - }), - ); -} - -#[tokio::test] -async fn buy_orders_on_both_sides() { - let engine = tests::SolverEngine::new("naive", tests::Config::None).await; - - let solution = engine - .solve(json!({ - "id": "1", - "tokens": {}, - "orders": [ - { - "uid": "0x0101010101010101010101010101010101010101010101010101010101010101\ - 0101010101010101010101010101010101010101\ - 01010101", - "sellToken": "0x000000000000000000000000000000000000000a", - "buyToken": "0x000000000000000000000000000000000000000b", - "sellAmount": "40000000000000000000", - "fullSellAmount": "40000000000000000000", - "buyAmount": "30000000000000000000", - "fullBuyAmount": "30000000000000000000", - "feePolicies": [], - "validTo": 0, - "kind": "buy", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - { - "uid": "0x0202020202020202020202020202020202020202020202020202020202020202\ - 0202020202020202020202020202020202020202\ - 02020202", - "sellToken": "0x000000000000000000000000000000000000000b", - "buyToken": "0x000000000000000000000000000000000000000a", - "sellAmount": "100000000000000000000", - "fullSellAmount": "100000000000000000000", - "buyAmount": "90000000000000000000", - "fullBuyAmount": "90000000000000000000", - "feePolicies": [], - "validTo": 0, - "kind": "buy", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - ], - "liquidity": [ - { - "kind": "constantProduct", - "tokens": { - "0x000000000000000000000000000000000000000a": { - "balance": "1000000000000000000000" - }, - "0x000000000000000000000000000000000000000b": { - "balance": "1000000000000000000000" - } - }, - "fee": "0.003", - "id": "0", - "address": "0xffffffffffffffffffffffffffffffffffffffff", - "router": "0xffffffffffffffffffffffffffffffffffffffff", - "gasEstimate": "110000" - }, - ], - "effectiveGasPrice": "15000000000", - "deadline": "2106-01-01T00:00:00.000Z", - "surplusCapturingJitOrderOwners": [] - })) - .await; - - assert_eq!( - solution, - json!({ - "solutions": [{ - "id": 0, - "prices": { - "0x000000000000000000000000000000000000000a": "66231662019024105282", - "0x000000000000000000000000000000000000000b": "61942706346833798925", - }, - "trades": [ - { - "kind": "fulfillment", - "order": "0x0101010101010101010101010101010101010101010101010101010101010101\ - 0101010101010101010101010101010101010101\ - 01010101", - "executedAmount": "30000000000000000000", - }, - { - "kind": "fulfillment", - "order": "0x0202020202020202020202020202020202020202020202020202020202020202\ - 0202020202020202020202020202020202020202\ - 02020202", - "executedAmount": "90000000000000000000", - }, - ], - "preInteractions": [], - "interactions": [ - { - "kind": "liquidity", - "internalize": false, - "id": "0", - "inputToken": "0x000000000000000000000000000000000000000b", - "outputToken": "0x000000000000000000000000000000000000000a", - "inputAmount": "66231662019024105282", - "outputAmount": "61942706346833798926" - }, - ], - "postInteractions": [], - "gas": 259417, - }] - }), - ); -} - -#[tokio::test] -async fn buy_and_sell_orders() { - let engine = tests::SolverEngine::new("naive", tests::Config::None).await; - - let solution = engine - .solve(json!({ - "id": "1", - "tokens": {}, - "orders": [ - { - "uid": "0x0101010101010101010101010101010101010101010101010101010101010101\ - 0101010101010101010101010101010101010101\ - 01010101", - "sellToken": "0x000000000000000000000000000000000000000a", - "buyToken": "0x000000000000000000000000000000000000000b", - "sellAmount": "40000000000000000000", - "fullSellAmount": "40000000000000000000", - "buyAmount": "30000000000000000000", - "fullBuyAmount": "30000000000000000000", - "feePolicies": [], - "validTo": 0, - "kind": "buy", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - { - "uid": "0x0202020202020202020202020202020202020202020202020202020202020202\ - 0202020202020202020202020202020202020202\ - 02020202", - "sellToken": "0x000000000000000000000000000000000000000b", - "buyToken": "0x000000000000000000000000000000000000000a", - "sellAmount": "100000000000000000000", - "fullSellAmount": "40000000000000000000", - "buyAmount": "90000000000000000000", - "fullBuyAmount": "30000000000000000000", - "feePolicies": [], - "validTo": 0, - "kind": "sell", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - ], - "liquidity": [ - { - "kind": "constantProduct", - "tokens": { - "0x000000000000000000000000000000000000000a": { - "balance": "1000000000000000000000" - }, - "0x000000000000000000000000000000000000000b": { - "balance": "1000000000000000000000" - } - }, - "fee": "0.003", - "id": "0", - "address": "0xffffffffffffffffffffffffffffffffffffffff", - "router": "0xffffffffffffffffffffffffffffffffffffffff", - "gasEstimate": "110000" - }, - ], - "effectiveGasPrice": "15000000000", - "deadline": "2106-01-01T00:00:00.000Z", - "surplusCapturingJitOrderOwners": [] - })) - .await; - - assert_eq!( - solution, - json!({ - "solutions": [{ - "id": 0, - "prices": { - "0x000000000000000000000000000000000000000a": "70000000000000000000", - "0x000000000000000000000000000000000000000b": "65237102608923246618", - }, - "trades": [ - { - "kind": "fulfillment", - "order": "0x0101010101010101010101010101010101010101010101010101010101010101\ - 0101010101010101010101010101010101010101\ - 01010101", - "executedAmount": "30000000000000000000", - }, - { - "kind": "fulfillment", - "order": "0x0202020202020202020202020202020202020202020202020202020202020202\ - 0202020202020202020202020202020202020202\ - 02020202", - "executedAmount": "100000000000000000000", - }, - ], - "preInteractions": [], - "interactions": [ - { - "kind": "liquidity", - "internalize": false, - "id": "0", - "inputToken": "0x000000000000000000000000000000000000000b", - "outputToken": "0x000000000000000000000000000000000000000a", - "inputAmount": "70000000000000000000", - "outputAmount": "65237102608923246619" - }, - ], - "postInteractions": [], - "gas": 259417, - }] - }), - ); -} diff --git a/crates/solvers/src/tests/naive/mod.rs b/crates/solvers/src/tests/naive/mod.rs deleted file mode 100644 index df3005f3f3..0000000000 --- a/crates/solvers/src/tests/naive/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -mod extract_deepest_pool; -mod filters_out_of_price_orders; -mod limit_order_price; -mod matches_orders; -mod reserves_too_small; -mod rounds_prices_in_favour_of_traders; -mod swap_less_than_reserves; -mod without_pool; diff --git a/crates/solvers/src/tests/naive/reserves_too_small.rs b/crates/solvers/src/tests/naive/reserves_too_small.rs deleted file mode 100644 index a4c72d5132..0000000000 --- a/crates/solvers/src/tests/naive/reserves_too_small.rs +++ /dev/null @@ -1,123 +0,0 @@ -//! This test verifies that it filters out large orders when pool reserves are -//! too small to be able to handle them. - -use {crate::tests, serde_json::json}; - -#[tokio::test] -async fn test() { - let engine = tests::SolverEngine::new("naive", tests::Config::None).await; - - let solution = engine - .solve(json!({ - "id": "1", - "tokens": {}, - "orders": [ - { - "uid": "0x0101010101010101010101010101010101010101010101010101010101010101\ - 0101010101010101010101010101010101010101\ - 01010101", - "sellToken": "0x000000000000000000000000000000000000000a", - "buyToken": "0x000000000000000000000000000000000000000b", - "sellAmount": "70145218378783248142575", - "fullSellAmount": "70145218378783248142575", - "buyAmount": "70123226323", - "fullBuyAmount": "70123226323", - "feePolicies": [], - "validTo": 0, - "kind": "sell", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - { - "uid": "0x0202020202020202020202020202020202020202020202020202020202020202\ - 0202020202020202020202020202020202020202\ - 02020202", - "sellToken": "0x000000000000000000000000000000000000000a", - "buyToken": "0x000000000000000000000000000000000000000b", - "sellAmount": "900000000000000", - "fullSellAmount": "900000000000000", - "buyAmount": "100", - "fullBuyAmount": "100", - "feePolicies": [], - "validTo": 0, - "kind": "sell", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - ], - "liquidity": [ - { - "kind": "constantProduct", - "tokens": { - "0x000000000000000000000000000000000000000a": { - "balance": "25000075" - }, - "0x000000000000000000000000000000000000000b": { - "balance": "2500007500" - } - }, - "fee": "0.003", - "id": "0", - "address": "0xffffffffffffffffffffffffffffffffffffffff", - "router": "0xffffffffffffffffffffffffffffffffffffffff", - "gasEstimate": "110000" - }, - ], - "effectiveGasPrice": "15000000000", - "deadline": "2106-01-01T00:00:00.000Z", - "surplusCapturingJitOrderOwners": [] - })) - .await; - - assert_eq!( - solution, - json!({ - "solutions": [{ - "id": 0, - "prices": { - "0x000000000000000000000000000000000000000a": "2500007430", - "0x000000000000000000000000000000000000000b": "900000000000000", - }, - "trades": [ - { - "kind": "fulfillment", - "order": "0x0202020202020202020202020202020202020202020202020202020202020202\ - 0202020202020202020202020202020202020202\ - 02020202", - "executedAmount": "900000000000000", - }, - ], - "preInteractions": [], - "interactions": [ - { - "kind": "liquidity", - "internalize": false, - "id": "0", - "inputToken": "0x000000000000000000000000000000000000000a", - "outputToken": "0x000000000000000000000000000000000000000b", - "inputAmount": "900000000000000", - "outputAmount": "2500007430" - }, - ], - "postInteractions": [], - "gas": 204391, - }] - }), - ); -} diff --git a/crates/solvers/src/tests/naive/rounds_prices_in_favour_of_traders.rs b/crates/solvers/src/tests/naive/rounds_prices_in_favour_of_traders.rs deleted file mode 100644 index 1be1dd491c..0000000000 --- a/crates/solvers/src/tests/naive/rounds_prices_in_favour_of_traders.rs +++ /dev/null @@ -1,137 +0,0 @@ -//! This test verifies that rounding is done in favour of the traders. This is -//! a weird detail that stems from the fact the UniswapV2-like pool swaps are -//! encoded as **swapTokensForExactTokens** (i.e. a "buy" order). The reason for -//! this is to make settlements less likely to revert (because buy swaps have -//! order fees as guaranteed "buffers", while sell swaps only have buffers if -//! they are already in the contract). The rounding is needed because the -//! settlement contract will round executed amounts in favour or the trader, -//! meaning that the clearing prices can cause the total buy amount to be a few -//! wei larger than the exact output that is encoded. - -use {crate::tests, serde_json::json}; - -#[tokio::test] -async fn test() { - let engine = tests::SolverEngine::new("naive", tests::Config::None).await; - - let solution = engine - .solve(json!({ - "id": "1", - "tokens": {}, - "orders": [ - { - "uid": "0x0101010101010101010101010101010101010101010101010101010101010101\ - 0101010101010101010101010101010101010101\ - 01010101", - "sellToken": "0x000000000000000000000000000000000000000a", - "buyToken": "0x000000000000000000000000000000000000000b", - "sellAmount": "9000000", - "fullSellAmount": "9000000", - "buyAmount": "8500000", - "fullBuyAmount": "8500000", - "feePolicies": [], - "validTo": 0, - "kind": "sell", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - { - "uid": "0x0202020202020202020202020202020202020202020202020202020202020202\ - 0202020202020202020202020202020202020202\ - 02020202", - "sellToken": "0x000000000000000000000000000000000000000b", - "buyToken": "0x000000000000000000000000000000000000000a", - "sellAmount": "8500000", - "fullSellAmount": "8500000", - "buyAmount": "8000001", - "fullBuyAmount": "8000001", - "feePolicies": [], - "validTo": 0, - "kind": "buy", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - ], - "liquidity": [ - { - "kind": "constantProduct", - "tokens": { - "0x000000000000000000000000000000000000000a": { - "balance": "1000000000000000000" - }, - "0x000000000000000000000000000000000000000b": { - "balance": "1000000000000000000" - } - }, - "fee": "0.003", - "id": "0", - "address": "0xffffffffffffffffffffffffffffffffffffffff", - "router": "0xffffffffffffffffffffffffffffffffffffffff", - "gasEstimate": "110000" - }, - ], - "effectiveGasPrice": "15000000000", - "deadline": "2106-01-01T00:00:00.000Z", - "surplusCapturingJitOrderOwners": [] - })) - .await; - - assert_eq!( - solution, - json!({ - "solutions": [{ - "id": 0, - "prices": { - "0x000000000000000000000000000000000000000a": "996999", - "0x000000000000000000000000000000000000000b": "999999", - }, - "trades": [ - { - "kind": "fulfillment", - "order": "0x0101010101010101010101010101010101010101010101010101010101010101\ - 0101010101010101010101010101010101010101\ - 01010101", - "executedAmount": "9000000", - }, - { - "kind": "fulfillment", - "order": "0x0202020202020202020202020202020202020202020202020202020202020202\ - 0202020202020202020202020202020202020202\ - 02020202", - "executedAmount": "8000001", - }, - ], - "preInteractions": [], - "interactions": [ - { - "kind": "liquidity", - "internalize": false, - "id": "0", - "inputToken": "0x000000000000000000000000000000000000000a", - "outputToken": "0x000000000000000000000000000000000000000b", - "inputAmount": "999999", - "outputAmount": "997000" - }, - ], - "postInteractions": [], - "gas": 259417, - }] - }), - ); -} diff --git a/crates/solvers/src/tests/naive/swap_less_than_reserves.rs b/crates/solvers/src/tests/naive/swap_less_than_reserves.rs deleted file mode 100644 index 3df8a591f0..0000000000 --- a/crates/solvers/src/tests/naive/swap_less_than_reserves.rs +++ /dev/null @@ -1,99 +0,0 @@ -//! This test verifies that given a swap with multiple orders, including limit -//! orders, the settlement building does not cause the naive solver to generate -//! a solution that swaps more than the pools reserves. -//! -//! This test verifies a regression that was introduced with limit orders, where -//! the incorrect order amounts were used for computing the final pool swap -//! amounts, causing it buy more from the pool than it actual had. - -use {crate::tests, serde_json::json}; - -#[tokio::test] -async fn test() { - let engine = tests::SolverEngine::new("naive", tests::Config::None).await; - - let solution = engine - .solve(json!({ - "id": "1", - "tokens": {}, - "orders": [ - { - "uid": "0x0101010101010101010101010101010101010101010101010101010101010101\ - 0101010101010101010101010101010101010101\ - 01010101", - "sellToken": "0xD533a949740bb3306d119CC777fa900bA034cd52", - "buyToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", - "sellAmount": "2161740107040163317224", - "fullSellAmount": "2161740107040163317224", - "buyAmount": "2146544862", - "fullBuyAmount": "2146544862", - "feePolicies": [], - "validTo": 0, - "kind": "sell", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "limit", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - { - "uid": "0x0202020202020202020202020202020202020202020202020202020202020202\ - 0202020202020202020202020202020202020202\ - 02020202", - "sellToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", - "buyToken": "0xD533a949740bb3306d119CC777fa900bA034cd52", - "sellAmount": "495165988", - "fullSellAmount": "495165988", - "buyAmount": "1428571428571428571428", - "fullBuyAmount": "1428571428571428571428", - "feePolicies": [], - "validTo": 0, - "kind": "sell", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "limit", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - ], - "liquidity": [ - { - "kind": "constantProduct", - "tokens": { - "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48": { - "balance": "32275540" - }, - "0xD533a949740bb3306d119CC777fa900bA034cd52": { - "balance": "33308141034569852391" - } - }, - "fee": "0.003", - "id": "0", - "address": "0x210a97ba874a8e279c95b350ae8ba143a143c159", - "router": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d", - "gasEstimate": "110000" - }, - ], - "effectiveGasPrice": "15000000000", - "deadline": "2106-01-01T00:00:00.000Z", - "surplusCapturingJitOrderOwners": [] - })) - .await; - - assert_eq!( - solution, - json!({ - "solutions": [] - }), - ); -} diff --git a/crates/solvers/src/tests/naive/without_pool.rs b/crates/solvers/src/tests/naive/without_pool.rs deleted file mode 100644 index d6b4419092..0000000000 --- a/crates/solvers/src/tests/naive/without_pool.rs +++ /dev/null @@ -1,120 +0,0 @@ -//! This test verifies that the naive solver doesn't use liquidity from the pool -//! when order amounts overlap. - -use {crate::tests, serde_json::json}; - -#[tokio::test] -async fn test() { - let engine = tests::SolverEngine::new("naive", tests::Config::None).await; - - let solution = engine - .solve(json!({ - "id": "1", - "tokens": {}, - "orders": [ - { - "uid": "0x0101010101010101010101010101010101010101010101010101010101010101\ - 0101010101010101010101010101010101010101\ - 01010101", - "sellToken": "0x000000000000000000000000000000000000000a", - "buyToken": "0x000000000000000000000000000000000000000b", - "sellAmount": "1001000000000000000000", - "fullSellAmount": "1001000000000000000000", - "buyAmount": "1000000000000000000000", - "fullBuyAmount": "1000000000000000000000", - "feePolicies": [], - "validTo": 0, - "kind": "sell", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - { - "uid": "0x0202020202020202020202020202020202020202020202020202020202020202\ - 0202020202020202020202020202020202020202\ - 02020202", - "sellToken": "0x000000000000000000000000000000000000000b", - "buyToken": "0x000000000000000000000000000000000000000a", - "sellAmount": "1001000000000000000000", - "fullSellAmount": "1001000000000000000000", - "buyAmount": "1000000000000000000000", - "fullBuyAmount": "1000000000000000000000", - "feePolicies": [], - "validTo": 0, - "kind": "sell", - "owner": "0x5b1e2c2762667331bc91648052f646d1b0d35984", - "partiallyFillable": false, - "preInteractions": [], - "postInteractions": [], - "sellTokenSource": "erc20", - "buyTokenDestination": "erc20", - "class": "market", - "appData": "0x6000000000000000000000000000000000000000000000000000000000000007", - "signingScheme": "presign", - "signature": "0x", - }, - ], - "liquidity": [ - { - "kind": "constantProduct", - "tokens": { - "0x000000000000000000000000000000000000000a": { - "balance": "1000001000000000000000000" - }, - "0x000000000000000000000000000000000000000b": { - "balance": "1000000000000000000000000" - } - }, - "fee": "0.003", - "id": "0", - "address": "0xffffffffffffffffffffffffffffffffffffffff", - "router": "0xffffffffffffffffffffffffffffffffffffffff", - "gasEstimate": "110000" - }, - ], - "effectiveGasPrice": "15000000000", - "deadline": "2106-01-01T00:00:00.000Z", - "surplusCapturingJitOrderOwners": [] - })) - .await; - - assert_eq!( - solution, - json!({ - "solutions": [{ - "id": 0, - "prices": { - "0x000000000000000000000000000000000000000a": "1000000000000000000000000", - "0x000000000000000000000000000000000000000b": "1000001000000000000000000", - }, - "trades": [ - { - "kind": "fulfillment", - "order": "0x0101010101010101010101010101010101010101010101010101010101010101\ - 0101010101010101010101010101010101010101\ - 01010101", - "executedAmount": "1001000000000000000000", - }, - { - "kind": "fulfillment", - "order": "0x0202020202020202020202020202020202020202020202020202020202020202\ - 0202020202020202020202020202020202020202\ - 02020202", - "executedAmount": "1001000000000000000000", - }, - ], - "preInteractions": [], - "interactions": [], - "postInteractions": [], - "gas": 259417, - }] - }), - ); -} From be7b80e184863272ab9c44bfb01d5b0fd7506ed5 Mon Sep 17 00:00:00 2001 From: MartinquaXD Date: Fri, 13 Dec 2024 12:34:36 +0000 Subject: [PATCH 6/7] Use `.expect()` and comment on try-catch blocks --- crates/contracts/solidity/Trader.sol | 1 + .../src/price_estimation/trade_verifier.rs | 42 +++++++++++++------ 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/crates/contracts/solidity/Trader.sol b/crates/contracts/solidity/Trader.sol index 37f34f75c3..ff486515ab 100644 --- a/crates/contracts/solidity/Trader.sol +++ b/crates/contracts/solidity/Trader.sol @@ -105,6 +105,7 @@ contract Trader { // We first reset the allowance to 0 since some ERC20 tokens (e.g. USDT) // require that due to this attack: // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + // We catch reverts because we'll later assert the correct approval got set anyway. try IERC20(sellToken).approve(address(settlementContract.vaultRelayer()), 0) {} catch {} try IERC20(sellToken).approve(address(settlementContract.vaultRelayer()), type(uint256).max) {} diff --git a/crates/shared/src/price_estimation/trade_verifier.rs b/crates/shared/src/price_estimation/trade_verifier.rs index 12bad16c16..dd99562cb2 100644 --- a/crates/shared/src/price_estimation/trade_verifier.rs +++ b/crates/shared/src/price_estimation/trade_verifier.rs @@ -470,7 +470,13 @@ fn encode_settlement( OrderKind::Buy => query.in_amount.get(), }; let weth = dummy_contract!(WETH9, native_token); - let calldata = weth.methods().withdraw(buy_amount).tx.data.unwrap().0; + let calldata = weth + .methods() + .withdraw(buy_amount) + .tx + .data + .expect("data gets populated by function call above") + .0; trade_interactions.push((native_token, 0.into(), Bytes(calldata))); tracing::trace!("adding unwrap interaction for paying out ETH"); } @@ -496,18 +502,23 @@ fn encode_settlement( OrderKind::Buy => *out_amount, }; let solver = dummy_contract!(Solver, trade.solver()); - let setup_step = solver.ensure_trade_preconditions( - verification.from, - settlement, - query.sell_token, - sell_amount, - native_token, - TradeVerifier::SPARDOSE, - ); + let setup_call = solver + .ensure_trade_preconditions( + verification.from, + settlement, + query.sell_token, + sell_amount, + native_token, + TradeVerifier::SPARDOSE, + ) + .tx + .data + .expect("data gets populated by function call above") + .0; Interaction { target: solver.address(), value: 0.into(), - data: setup_step.tx.data.unwrap().0, + data: setup_call, } }; @@ -681,9 +692,14 @@ fn add_balance_queries( // track how much `sell_token` the `from` address actually spent OrderKind::Buy => (query.sell_token, verification.from), }; - let query_balance = solver.methods().store_balance(token, owner, true); - let query_balance = Bytes(query_balance.tx.data.unwrap().0); - let interaction = (solver.address(), 0.into(), query_balance); + let query_balance_call = solver + .methods() + .store_balance(token, owner, true) + .tx + .data + .expect("data gets populated by function call above") + .0; + let interaction = (solver.address(), 0.into(), Bytes(query_balance_call)); // query balance query at the end of pre-interactions settlement.interactions[0].push(interaction.clone()); // query balance right after we payed out all `buy_token` From 01bdcb3ff61b0817ce31db38f12de3fb53bea252 Mon Sep 17 00:00:00 2001 From: MartinquaXD Date: Fri, 13 Dec 2024 12:41:06 +0000 Subject: [PATCH 7/7] Use adjust gas measurement and remove unnecessary try-catch --- crates/contracts/artifacts/Solver.json | 2 +- crates/contracts/artifacts/Trader.json | 2 +- crates/contracts/solidity/Solver.sol | 3 ++- crates/contracts/solidity/Trader.sol | 3 +-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/contracts/artifacts/Solver.json b/crates/contracts/artifacts/Solver.json index 0843bb5e94..a046d11cdf 100644 --- a/crates/contracts/artifacts/Solver.json +++ b/crates/contracts/artifacts/Solver.json @@ -1 +1 @@ -{"abi":[{"inputs":[{"internalType":"contract Trader","name":"trader","type":"address"},{"internalType":"contract ISettlement","name":"settlementContract","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"address","name":"nativeToken","type":"address"},{"internalType":"address","name":"spardose","type":"address"}],"name":"ensureTradePreconditions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"countGas","type":"bool"}],"name":"storeBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISettlement","name":"settlementContract","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"bytes","name":"settlementCall","type":"bytes"}],"name":"swap","outputs":[{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256[]","name":"queriedBalances","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"}],"bytecode":"0x608060405234801561001057600080fd5b50610997806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80631d47e7f4146100465780632582edb4146100705780633bbb2e1d14610085575b600080fd5b61005961005436600461068a565b610098565b60405161006792919061074c565b60405180910390f35b61008361007e36600461079a565b610215565b005b610083610093366004610813565b6102e5565b6000606033301461012f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b60008573ffffffffffffffffffffffffffffffffffffffff16600060405160006040518083038185875af1925050503d806000811461018a576040519150601f19603f3d011682016040523d82523d6000602084013e61018f565b606091505b505090505061019f87878a61041a565b6101aa8885856104f2565b91506101b787878a61041a565b600180548060200260200160405190810160405280929190818152602001828054801561020357602002820191906000526020600020905b8154815260200190600101908083116101ef575b50505050509050965096945050505050565b60005a6040517f542eb77d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152878116602483015260448201879052858116606483015284811660848301529192509088169063542eb77d9060a401600060405180830381600087803b1580156102a457600080fd5b505af11580156102b8573d6000803e3d6000fd5b505050505a6102c79082610892565b6000808282546102d791906108ab565b909155505050505050505050565b60005a9050600173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff8616146103b2576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa158015610389573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ad91906108be565b6103cb565b8373ffffffffffffffffffffffffffffffffffffffff16315b815460018101835560009283526020909220909101558115610414575a6103f29082610892565b6103fe9061116c6108ab565b60008082825461040e91906108ab565b90915550505b50505050565b60005b828110156104145730633bbb2e1d85858481811061043d5761043d6108d7565b90506020020160208101906104529190610906565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9182166004820152908516602482015260006044820152606401600060405180830381600087803b1580156104c757600080fd5b505af11580156104db573d6000803e3d6000fd5b5050505080806104ea90610923565b91505061041d565b6000805a905061054f84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505073ffffffffffffffffffffffffffffffffffffffff891692915050610571565b506000545a61055e9083610892565b6105689190610892565b95945050505050565b606061057f83600084610586565b9392505050565b606060008473ffffffffffffffffffffffffffffffffffffffff1684846040516105b0919061095b565b60006040518083038185875af1925050503d80600081146105ed576040519150601f19603f3d011682016040523d82523d6000602084013e6105f2565b606091505b50925090508061060457815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461062e57600080fd5b50565b803561063c8161060c565b919050565b60008083601f84011261065357600080fd5b50813567ffffffffffffffff81111561066b57600080fd5b60208301915083602082850101111561068357600080fd5b9250929050565b600080600080600080608087890312156106a357600080fd5b86356106ae8161060c565b9550602087013567ffffffffffffffff808211156106cb57600080fd5b818901915089601f8301126106df57600080fd5b8135818111156106ee57600080fd5b8a60208260051b850101111561070357600080fd5b602083019750955061071760408a01610631565b9450606089013591508082111561072d57600080fd5b5061073a89828a01610641565b979a9699509497509295939492505050565b6000604082018483526020604081850152818551808452606086019150828701935060005b8181101561078d57845183529383019391830191600101610771565b5090979650505050505050565b60008060008060008060c087890312156107b357600080fd5b86356107be8161060c565b955060208701356107ce8161060c565b945060408701356107de8161060c565b93506060870135925060808701356107f58161060c565b915060a08701356108058161060c565b809150509295509295509295565b60008060006060848603121561082857600080fd5b83356108338161060c565b925060208401356108438161060c565b91506040840135801515811461085857600080fd5b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156108a5576108a5610863565b92915050565b808201808211156108a5576108a5610863565b6000602082840312156108d057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561091857600080fd5b813561057f8161060c565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361095457610954610863565b5060010190565b6000825160005b8181101561097c5760208186018101518583015201610962565b50600092019182525091905056fea164736f6c6343000811000a","deployedBytecode":"0x608060405234801561001057600080fd5b50600436106100415760003560e01c80631d47e7f4146100465780632582edb4146100705780633bbb2e1d14610085575b600080fd5b61005961005436600461068a565b610098565b60405161006792919061074c565b60405180910390f35b61008361007e36600461079a565b610215565b005b610083610093366004610813565b6102e5565b6000606033301461012f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b60008573ffffffffffffffffffffffffffffffffffffffff16600060405160006040518083038185875af1925050503d806000811461018a576040519150601f19603f3d011682016040523d82523d6000602084013e61018f565b606091505b505090505061019f87878a61041a565b6101aa8885856104f2565b91506101b787878a61041a565b600180548060200260200160405190810160405280929190818152602001828054801561020357602002820191906000526020600020905b8154815260200190600101908083116101ef575b50505050509050965096945050505050565b60005a6040517f542eb77d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152878116602483015260448201879052858116606483015284811660848301529192509088169063542eb77d9060a401600060405180830381600087803b1580156102a457600080fd5b505af11580156102b8573d6000803e3d6000fd5b505050505a6102c79082610892565b6000808282546102d791906108ab565b909155505050505050505050565b60005a9050600173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff8616146103b2576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa158015610389573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103ad91906108be565b6103cb565b8373ffffffffffffffffffffffffffffffffffffffff16315b815460018101835560009283526020909220909101558115610414575a6103f29082610892565b6103fe9061116c6108ab565b60008082825461040e91906108ab565b90915550505b50505050565b60005b828110156104145730633bbb2e1d85858481811061043d5761043d6108d7565b90506020020160208101906104529190610906565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9182166004820152908516602482015260006044820152606401600060405180830381600087803b1580156104c757600080fd5b505af11580156104db573d6000803e3d6000fd5b5050505080806104ea90610923565b91505061041d565b6000805a905061054f84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505073ffffffffffffffffffffffffffffffffffffffff891692915050610571565b506000545a61055e9083610892565b6105689190610892565b95945050505050565b606061057f83600084610586565b9392505050565b606060008473ffffffffffffffffffffffffffffffffffffffff1684846040516105b0919061095b565b60006040518083038185875af1925050503d80600081146105ed576040519150601f19603f3d011682016040523d82523d6000602084013e6105f2565b606091505b50925090508061060457815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461062e57600080fd5b50565b803561063c8161060c565b919050565b60008083601f84011261065357600080fd5b50813567ffffffffffffffff81111561066b57600080fd5b60208301915083602082850101111561068357600080fd5b9250929050565b600080600080600080608087890312156106a357600080fd5b86356106ae8161060c565b9550602087013567ffffffffffffffff808211156106cb57600080fd5b818901915089601f8301126106df57600080fd5b8135818111156106ee57600080fd5b8a60208260051b850101111561070357600080fd5b602083019750955061071760408a01610631565b9450606089013591508082111561072d57600080fd5b5061073a89828a01610641565b979a9699509497509295939492505050565b6000604082018483526020604081850152818551808452606086019150828701935060005b8181101561078d57845183529383019391830191600101610771565b5090979650505050505050565b60008060008060008060c087890312156107b357600080fd5b86356107be8161060c565b955060208701356107ce8161060c565b945060408701356107de8161060c565b93506060870135925060808701356107f58161060c565b915060a08701356108058161060c565b809150509295509295509295565b60008060006060848603121561082857600080fd5b83356108338161060c565b925060208401356108438161060c565b91506040840135801515811461085857600080fd5b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156108a5576108a5610863565b92915050565b808201808211156108a5576108a5610863565b6000602082840312156108d057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561091857600080fd5b813561057f8161060c565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361095457610954610863565b5060010190565b6000825160005b8181101561097c5760208186018101518583015201610962565b50600092019182525091905056fea164736f6c6343000811000a","devdoc":{"methods":{}},"userdoc":{"methods":{}}} +{"abi":[{"inputs":[{"internalType":"contract Trader","name":"trader","type":"address"},{"internalType":"contract ISettlement","name":"settlementContract","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"address","name":"nativeToken","type":"address"},{"internalType":"address","name":"spardose","type":"address"}],"name":"ensureTradePreconditions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"countGas","type":"bool"}],"name":"storeBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISettlement","name":"settlementContract","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"bytes","name":"settlementCall","type":"bytes"}],"name":"swap","outputs":[{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256[]","name":"queriedBalances","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"}],"bytecode":"0x608060405234801561001057600080fd5b506109a3806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80631d47e7f4146100465780632582edb4146100705780633bbb2e1d14610085575b600080fd5b610059610054366004610696565b610098565b604051610067929190610758565b60405180910390f35b61008361007e3660046107a6565b610215565b005b61008361009336600461081f565b6102f1565b6000606033301461012f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b60008573ffffffffffffffffffffffffffffffffffffffff16600060405160006040518083038185875af1925050503d806000811461018a576040519150601f19603f3d011682016040523d82523d6000602084013e61018f565b606091505b505090505061019f87878a610426565b6101aa8885856104fe565b91506101b787878a610426565b600180548060200260200160405190810160405280929190818152602001828054801561020357602002820191906000526020600020905b8154815260200190600101908083116101ef575b50505050509050965096945050505050565b60005a6040517f542eb77d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152878116602483015260448201879052858116606483015284811660848301529192509088169063542eb77d9060a401600060405180830381600087803b1580156102a457600080fd5b505af11580156102b8573d6000803e3d6000fd5b505050505a6102c7908261089e565b6102d39061116c6108b7565b6000808282546102e391906108b7565b909155505050505050505050565b60005a9050600173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff8616146103be576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa158015610395573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b991906108ca565b6103d7565b8373ffffffffffffffffffffffffffffffffffffffff16315b815460018101835560009283526020909220909101558115610420575a6103fe908261089e565b61040a9061116c6108b7565b60008082825461041a91906108b7565b90915550505b50505050565b60005b828110156104205730633bbb2e1d858584818110610449576104496108e3565b905060200201602081019061045e9190610912565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9182166004820152908516602482015260006044820152606401600060405180830381600087803b1580156104d357600080fd5b505af11580156104e7573d6000803e3d6000fd5b5050505080806104f69061092f565b915050610429565b6000805a905061055b84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505073ffffffffffffffffffffffffffffffffffffffff89169291505061057d565b506000545a61056a908361089e565b610574919061089e565b95945050505050565b606061058b83600084610592565b9392505050565b606060008473ffffffffffffffffffffffffffffffffffffffff1684846040516105bc9190610967565b60006040518083038185875af1925050503d80600081146105f9576040519150601f19603f3d011682016040523d82523d6000602084013e6105fe565b606091505b50925090508061061057815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461063a57600080fd5b50565b803561064881610618565b919050565b60008083601f84011261065f57600080fd5b50813567ffffffffffffffff81111561067757600080fd5b60208301915083602082850101111561068f57600080fd5b9250929050565b600080600080600080608087890312156106af57600080fd5b86356106ba81610618565b9550602087013567ffffffffffffffff808211156106d757600080fd5b818901915089601f8301126106eb57600080fd5b8135818111156106fa57600080fd5b8a60208260051b850101111561070f57600080fd5b602083019750955061072360408a0161063d565b9450606089013591508082111561073957600080fd5b5061074689828a0161064d565b979a9699509497509295939492505050565b6000604082018483526020604081850152818551808452606086019150828701935060005b818110156107995784518352938301939183019160010161077d565b5090979650505050505050565b60008060008060008060c087890312156107bf57600080fd5b86356107ca81610618565b955060208701356107da81610618565b945060408701356107ea81610618565b935060608701359250608087013561080181610618565b915060a087013561081181610618565b809150509295509295509295565b60008060006060848603121561083457600080fd5b833561083f81610618565b9250602084013561084f81610618565b91506040840135801515811461086457600080fd5b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156108b1576108b161086f565b92915050565b808201808211156108b1576108b161086f565b6000602082840312156108dc57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561092457600080fd5b813561058b81610618565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036109605761096061086f565b5060010190565b6000825160005b81811015610988576020818601810151858301520161096e565b50600092019182525091905056fea164736f6c6343000811000a","deployedBytecode":"0x608060405234801561001057600080fd5b50600436106100415760003560e01c80631d47e7f4146100465780632582edb4146100705780633bbb2e1d14610085575b600080fd5b610059610054366004610696565b610098565b604051610067929190610758565b60405180910390f35b61008361007e3660046107a6565b610215565b005b61008361009336600461081f565b6102f1565b6000606033301461012f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f6f6e6c792073696d756c6174696f6e206c6f67696320697320616c6c6f77656460448201527f20746f2063616c6c202773776170272066756e6374696f6e0000000000000000606482015260840160405180910390fd5b60008573ffffffffffffffffffffffffffffffffffffffff16600060405160006040518083038185875af1925050503d806000811461018a576040519150601f19603f3d011682016040523d82523d6000602084013e61018f565b606091505b505090505061019f87878a610426565b6101aa8885856104fe565b91506101b787878a610426565b600180548060200260200160405190810160405280929190818152602001828054801561020357602002820191906000526020600020905b8154815260200190600101908083116101ef575b50505050509050965096945050505050565b60005a6040517f542eb77d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152878116602483015260448201879052858116606483015284811660848301529192509088169063542eb77d9060a401600060405180830381600087803b1580156102a457600080fd5b505af11580156102b8573d6000803e3d6000fd5b505050505a6102c7908261089e565b6102d39061116c6108b7565b6000808282546102e391906108b7565b909155505050505050505050565b60005a9050600173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee73ffffffffffffffffffffffffffffffffffffffff8616146103be576040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528616906370a0823190602401602060405180830381865afa158015610395573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b991906108ca565b6103d7565b8373ffffffffffffffffffffffffffffffffffffffff16315b815460018101835560009283526020909220909101558115610420575a6103fe908261089e565b61040a9061116c6108b7565b60008082825461041a91906108b7565b90915550505b50505050565b60005b828110156104205730633bbb2e1d858584818110610449576104496108e3565b905060200201602081019061045e9190610912565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9182166004820152908516602482015260006044820152606401600060405180830381600087803b1580156104d357600080fd5b505af11580156104e7573d6000803e3d6000fd5b5050505080806104f69061092f565b915050610429565b6000805a905061055b84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505073ffffffffffffffffffffffffffffffffffffffff89169291505061057d565b506000545a61056a908361089e565b610574919061089e565b95945050505050565b606061058b83600084610592565b9392505050565b606060008473ffffffffffffffffffffffffffffffffffffffff1684846040516105bc9190610967565b60006040518083038185875af1925050503d80600081146105f9576040519150601f19603f3d011682016040523d82523d6000602084013e6105fe565b606091505b50925090508061061057815160208301fd5b509392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461063a57600080fd5b50565b803561064881610618565b919050565b60008083601f84011261065f57600080fd5b50813567ffffffffffffffff81111561067757600080fd5b60208301915083602082850101111561068f57600080fd5b9250929050565b600080600080600080608087890312156106af57600080fd5b86356106ba81610618565b9550602087013567ffffffffffffffff808211156106d757600080fd5b818901915089601f8301126106eb57600080fd5b8135818111156106fa57600080fd5b8a60208260051b850101111561070f57600080fd5b602083019750955061072360408a0161063d565b9450606089013591508082111561073957600080fd5b5061074689828a0161064d565b979a9699509497509295939492505050565b6000604082018483526020604081850152818551808452606086019150828701935060005b818110156107995784518352938301939183019160010161077d565b5090979650505050505050565b60008060008060008060c087890312156107bf57600080fd5b86356107ca81610618565b955060208701356107da81610618565b945060408701356107ea81610618565b935060608701359250608087013561080181610618565b915060a087013561081181610618565b809150509295509295509295565b60008060006060848603121561083457600080fd5b833561083f81610618565b9250602084013561084f81610618565b91506040840135801515811461086457600080fd5b809150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156108b1576108b161086f565b92915050565b808201808211156108b1576108b161086f565b6000602082840312156108dc57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561092457600080fd5b813561058b81610618565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036109605761096061086f565b5060010190565b6000825160005b81811015610988576020818601810151858301520161096e565b50600092019182525091905056fea164736f6c6343000811000a","devdoc":{"methods":{}},"userdoc":{"methods":{}}} diff --git a/crates/contracts/artifacts/Trader.json b/crates/contracts/artifacts/Trader.json index c41d8b65bf..2884646dee 100644 --- a/crates/contracts/artifacts/Trader.json +++ b/crates/contracts/artifacts/Trader.json @@ -1 +1 @@ -{"abi":[{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"contract ISettlement","name":"settlementContract","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"address","name":"nativeToken","type":"address"},{"internalType":"address","name":"spardose","type":"address"}],"name":"ensureTradePreconditions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"stateMutability":"payable","type":"receive"}],"bytecode":"0x608060405234801561001057600080fd5b50610cee806100206000396000f3fe60806040526004361061002d5760003560e01c80631626ba7e14610086578063542eb77d146100fe57610034565b3661003457005b600061007c6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062010000939250506101209050565b9050805160208201f35b34801561009257600080fd5b506100c96100a1366004610b0a565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010a57600080fd5b5061011e610119366004610bab565b6101a2565b005b606060008373ffffffffffffffffffffffffffffffffffffffff16836040516101499190610c13565b600060405180830381855af49150503d8060008114610184576040519150601f19603f3d011682016040523d82523d6000602084013e610189565b606091505b50925090508061019b57815160208301fd5b5092915050565b6101aa610acf565b1561023c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e6365000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361037f576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa1580156102dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103009190610c42565b90508381101561037d5760006103168286610c5b565b905080471061037b578373ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561036757600080fd5b505af193505050508015610379575060015b505b505b505b60008473ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e308873ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040d9190610c9b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa15801561047d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a19190610c42565b9050838110156108fc578473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190610c9b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152600060248201526044016020604051808303816000875af19250505080156105e2575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526105df91810190610cbf565b60015b156105e957505b8473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610650573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106749190610c9b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff90911660048201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248201526044016020604051808303816000875af192505050801561073f575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261073c91810190610cbf565b60015b1561074657505b60008573ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e308973ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d49190610c9b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa158015610844573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108689190610c42565b9050848110156108fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f74726164657220646964206e6f7420676976652074686520726571756972656460448201527f20617070726f76616c73000000000000000000000000000000000000000000006064820152608401610233565b505b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa158015610969573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098d9190610c42565b905084811015610ac65773ffffffffffffffffffffffffffffffffffffffff831663494666b6876109be8489610c5b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b158015610a2957600080fd5b505af1925050508015610a3a575060015b610ac6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f74726164657220646f6573206e6f74206861766520656e6f7567682073656c6c60448201527f20746f6b656e00000000000000000000000000000000000000000000000000006064820152608401610233565b50505050505050565b600080610afd60017f7f36ecad6e52bbe2ff70badce94360882c890b7877b16131c08eabfc635c9735610c5b565b8054600190915592915050565b600080600060408486031215610b1f57600080fd5b83359250602084013567ffffffffffffffff80821115610b3e57600080fd5b818601915086601f830112610b5257600080fd5b813581811115610b6157600080fd5b876020828501011115610b7357600080fd5b6020830194508093505050509250925092565b73ffffffffffffffffffffffffffffffffffffffff81168114610ba857600080fd5b50565b600080600080600060a08688031215610bc357600080fd5b8535610bce81610b86565b94506020860135610bde81610b86565b9350604086013592506060860135610bf581610b86565b91506080860135610c0581610b86565b809150509295509295909350565b6000825160005b81811015610c345760208186018101518583015201610c1a565b506000920191825250919050565b600060208284031215610c5457600080fd5b5051919050565b81810381811115610c95577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b600060208284031215610cad57600080fd5b8151610cb881610b86565b9392505050565b600060208284031215610cd157600080fd5b81518015158114610cb857600080fdfea164736f6c6343000811000a","deployedBytecode":"0x60806040526004361061002d5760003560e01c80631626ba7e14610086578063542eb77d146100fe57610034565b3661003457005b600061007c6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062010000939250506101209050565b9050805160208201f35b34801561009257600080fd5b506100c96100a1366004610b0a565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010a57600080fd5b5061011e610119366004610bab565b6101a2565b005b606060008373ffffffffffffffffffffffffffffffffffffffff16836040516101499190610c13565b600060405180830381855af49150503d8060008114610184576040519150601f19603f3d011682016040523d82523d6000602084013e610189565b606091505b50925090508061019b57815160208301fd5b5092915050565b6101aa610acf565b1561023c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e6365000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361037f576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa1580156102dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103009190610c42565b90508381101561037d5760006103168286610c5b565b905080471061037b578373ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561036757600080fd5b505af193505050508015610379575060015b505b505b505b60008473ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e308873ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040d9190610c9b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa15801561047d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a19190610c42565b9050838110156108fc578473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190610c9b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152600060248201526044016020604051808303816000875af19250505080156105e2575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526105df91810190610cbf565b60015b156105e957505b8473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610650573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106749190610c9b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff90911660048201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248201526044016020604051808303816000875af192505050801561073f575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261073c91810190610cbf565b60015b1561074657505b60008573ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e308973ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107d49190610c9b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa158015610844573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108689190610c42565b9050848110156108fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f74726164657220646964206e6f7420676976652074686520726571756972656460448201527f20617070726f76616c73000000000000000000000000000000000000000000006064820152608401610233565b505b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa158015610969573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061098d9190610c42565b905084811015610ac65773ffffffffffffffffffffffffffffffffffffffff831663494666b6876109be8489610c5b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b158015610a2957600080fd5b505af1925050508015610a3a575060015b610ac6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f74726164657220646f6573206e6f74206861766520656e6f7567682073656c6c60448201527f20746f6b656e00000000000000000000000000000000000000000000000000006064820152608401610233565b50505050505050565b600080610afd60017f7f36ecad6e52bbe2ff70badce94360882c890b7877b16131c08eabfc635c9735610c5b565b8054600190915592915050565b600080600060408486031215610b1f57600080fd5b83359250602084013567ffffffffffffffff80821115610b3e57600080fd5b818601915086601f830112610b5257600080fd5b813581811115610b6157600080fd5b876020828501011115610b7357600080fd5b6020830194508093505050509250925092565b73ffffffffffffffffffffffffffffffffffffffff81168114610ba857600080fd5b50565b600080600080600060a08688031215610bc357600080fd5b8535610bce81610b86565b94506020860135610bde81610b86565b9350604086013592506060860135610bf581610b86565b91506080860135610c0581610b86565b809150509295509295909350565b6000825160005b81811015610c345760208186018101518583015201610c1a565b506000920191825250919050565b600060208284031215610c5457600080fd5b5051919050565b81810381811115610c95577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b600060208284031215610cad57600080fd5b8151610cb881610b86565b9392505050565b600060208284031215610cd157600080fd5b81518015158114610cb857600080fdfea164736f6c6343000811000a","devdoc":{"methods":{}},"userdoc":{"methods":{}}} +{"abi":[{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"contract ISettlement","name":"settlementContract","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"address","name":"nativeToken","type":"address"},{"internalType":"address","name":"spardose","type":"address"}],"name":"ensureTradePreconditions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"stateMutability":"payable","type":"receive"}],"bytecode":"0x608060405234801561001057600080fd5b50610cf4806100206000396000f3fe60806040526004361061002d5760003560e01c80631626ba7e14610086578063542eb77d146100fe57610034565b3661003457005b600061007c6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062010000939250506101209050565b9050805160208201f35b34801561009257600080fd5b506100c96100a1366004610b10565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010a57600080fd5b5061011e610119366004610bb1565b6101a2565b005b606060008373ffffffffffffffffffffffffffffffffffffffff16836040516101499190610c19565b600060405180830381855af49150503d8060008114610184576040519150601f19603f3d011682016040523d82523d6000602084013e610189565b606091505b50925090508061019b57815160208301fd5b5092915050565b6101aa610ad5565b1561023c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e6365000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610385576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa1580156102dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103009190610c48565b9050838110156103835760006103168286610c61565b9050804710610381578373ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561036757600080fd5b505af115801561037b573d6000803e3d6000fd5b50505050505b505b505b60008473ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e308873ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104139190610ca1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa158015610483573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a79190610c48565b905083811015610902578473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053c9190610ca1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152600060248201526044016020604051808303816000875af19250505080156105e8575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526105e591810190610cc5565b60015b156105ef57505b8473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610656573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067a9190610ca1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff90911660048201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248201526044016020604051808303816000875af1925050508015610745575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261074291810190610cc5565b60015b1561074c57505b60008573ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e308973ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107da9190610ca1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa15801561084a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086e9190610c48565b905084811015610900576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f74726164657220646964206e6f7420676976652074686520726571756972656460448201527f20617070726f76616c73000000000000000000000000000000000000000000006064820152608401610233565b505b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa15801561096f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109939190610c48565b905084811015610acc5773ffffffffffffffffffffffffffffffffffffffff831663494666b6876109c48489610c61565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b158015610a2f57600080fd5b505af1925050508015610a40575060015b610acc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f74726164657220646f6573206e6f74206861766520656e6f7567682073656c6c60448201527f20746f6b656e00000000000000000000000000000000000000000000000000006064820152608401610233565b50505050505050565b600080610b0360017f7f36ecad6e52bbe2ff70badce94360882c890b7877b16131c08eabfc635c9735610c61565b8054600190915592915050565b600080600060408486031215610b2557600080fd5b83359250602084013567ffffffffffffffff80821115610b4457600080fd5b818601915086601f830112610b5857600080fd5b813581811115610b6757600080fd5b876020828501011115610b7957600080fd5b6020830194508093505050509250925092565b73ffffffffffffffffffffffffffffffffffffffff81168114610bae57600080fd5b50565b600080600080600060a08688031215610bc957600080fd5b8535610bd481610b8c565b94506020860135610be481610b8c565b9350604086013592506060860135610bfb81610b8c565b91506080860135610c0b81610b8c565b809150509295509295909350565b6000825160005b81811015610c3a5760208186018101518583015201610c20565b506000920191825250919050565b600060208284031215610c5a57600080fd5b5051919050565b81810381811115610c9b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b600060208284031215610cb357600080fd5b8151610cbe81610b8c565b9392505050565b600060208284031215610cd757600080fd5b81518015158114610cbe57600080fdfea164736f6c6343000811000a","deployedBytecode":"0x60806040526004361061002d5760003560e01c80631626ba7e14610086578063542eb77d146100fe57610034565b3661003457005b600061007c6000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525062010000939250506101209050565b9050805160208201f35b34801561009257600080fd5b506100c96100a1366004610b10565b7f1626ba7e000000000000000000000000000000000000000000000000000000009392505050565b6040517fffffffff00000000000000000000000000000000000000000000000000000000909116815260200160405180910390f35b34801561010a57600080fd5b5061011e610119366004610bb1565b6101a2565b005b606060008373ffffffffffffffffffffffffffffffffffffffff16836040516101499190610c19565b600060405180830381855af49150503d8060008114610184576040519150601f19603f3d011682016040523d82523d6000602084013e610189565b606091505b50925090508061019b57815160208301fd5b5092915050565b6101aa610ad5565b1561023c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f70726570617265537761702063616e206f6e6c792062652063616c6c6564206f60448201527f6e6365000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610385576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa1580156102dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103009190610c48565b9050838110156103835760006103168286610c61565b9050804710610381578373ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561036757600080fd5b505af115801561037b573d6000803e3d6000fd5b50505050505b505b505b60008473ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e308873ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104139190610ca1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa158015610483573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104a79190610c48565b905083811015610902578473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053c9190610ca1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152600060248201526044016020604051808303816000875af19250505080156105e8575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526105e591810190610cc5565b60015b156105ef57505b8473ffffffffffffffffffffffffffffffffffffffff1663095ea7b38773ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610656573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067a9190610ca1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff90911660048201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248201526044016020604051808303816000875af1925050508015610745575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261074291810190610cc5565b60015b1561074c57505b60008573ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e308973ffffffffffffffffffffffffffffffffffffffff16639b552cc26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107da9190610ca1565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff928316600482015291166024820152604401602060405180830381865afa15801561084a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086e9190610c48565b905084811015610900576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f74726164657220646964206e6f7420676976652074686520726571756972656460448201527f20617070726f76616c73000000000000000000000000000000000000000000006064820152608401610233565b505b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa15801561096f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109939190610c48565b905084811015610acc5773ffffffffffffffffffffffffffffffffffffffff831663494666b6876109c48489610c61565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b158015610a2f57600080fd5b505af1925050508015610a40575060015b610acc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f74726164657220646f6573206e6f74206861766520656e6f7567682073656c6c60448201527f20746f6b656e00000000000000000000000000000000000000000000000000006064820152608401610233565b50505050505050565b600080610b0360017f7f36ecad6e52bbe2ff70badce94360882c890b7877b16131c08eabfc635c9735610c61565b8054600190915592915050565b600080600060408486031215610b2557600080fd5b83359250602084013567ffffffffffffffff80821115610b4457600080fd5b818601915086601f830112610b5857600080fd5b813581811115610b6757600080fd5b876020828501011115610b7957600080fd5b6020830194508093505050509250925092565b73ffffffffffffffffffffffffffffffffffffffff81168114610bae57600080fd5b50565b600080600080600060a08688031215610bc957600080fd5b8535610bd481610b8c565b94506020860135610be481610b8c565b9350604086013592506060860135610bfb81610b8c565b91506080860135610c0b81610b8c565b809150509295509295909350565b6000825160005b81811015610c3a5760208186018101518583015201610c20565b506000920191825250919050565b600060208284031215610c5a57600080fd5b5051919050565b81810381811115610c9b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b600060208284031215610cb357600080fd5b8151610cbe81610b8c565b9392505050565b600060208284031215610cd757600080fd5b81518015158114610cbe57600080fdfea164736f6c6343000811000a","devdoc":{"methods":{}},"userdoc":{"methods":{}}} diff --git a/crates/contracts/solidity/Solver.sol b/crates/contracts/solidity/Solver.sol index e9aa29035f..f8fd460623 100644 --- a/crates/contracts/solidity/Solver.sol +++ b/crates/contracts/solidity/Solver.sol @@ -125,6 +125,7 @@ contract Solver { nativeToken, spardose ); - _simulationOverhead += gasStart - gasleft(); + // Account for costs of gas used outside of metered section. + _simulationOverhead += gasStart - gasleft() + 4460; } } diff --git a/crates/contracts/solidity/Trader.sol b/crates/contracts/solidity/Trader.sol index ff486515ab..fb86b5954d 100644 --- a/crates/contracts/solidity/Trader.sol +++ b/crates/contracts/solidity/Trader.sol @@ -91,8 +91,7 @@ contract Trader { // revert. Instead, we fall-through so that we handle insufficient sell // token balances uniformly for all tokens. if (address(this).balance >= amountToWrap) { - try INativeERC20(nativeToken).deposit{value: amountToWrap}() {} - catch {} + INativeERC20(nativeToken).deposit{value: amountToWrap}(); } } }