-
Notifications
You must be signed in to change notification settings - Fork 83
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# Description Supersedes #1531 #1469 introduced simulations to the single order solvers so that we can produce accurate fees when solving for partially fillable limit orders. This PR ports some of that logic to our solvers binary for the DEX aggregator solvers in the co-located world. In particular, it introduces a new `Swapper` helper contract for setting up simulations on-chain for DEX aggregator swaps. We also only do the simulation for limit orders (to avoid additional roudtrips for market orders, which don't use this gas information anyway, so the heuristic value is more than good enough). # Changes - [x] Introduce new simulation helper contract. - [x] Execute simulations for limit orders and use the simulated gas amount for computing accurate solver fees. - [x] : Mock node request/responses for executing the simulation in the `partial_fill` tests. ## How to test Adjusted some existing tests to work. ## Related Issues Fixes #1959 --------- Co-authored-by: Martin Beckmann <[email protected]> Co-authored-by: Martin Beckmann <[email protected]>
- Loading branch information
1 parent
53b77c1
commit 7aeb32b
Showing
40 changed files
with
490 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{"abi":[{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isSolver","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}],"bytecode":"0x608060405234801561001057600080fd5b50609a8061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806302cc250d14602d575b600080fd5b603e60383660046052565b50600190565b604051901515815260200160405180910390f35b600060208284031215606357600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114608657600080fd5b939250505056fea164736f6c6343000811000a","deployedBytecode":"0x6080604052348015600f57600080fd5b506004361060285760003560e01c806302cc250d14602d575b600080fd5b603e60383660046052565b50600190565b604051901515815260200160405180910390f35b600060208284031215606357600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114608657600080fd5b939250505056fea164736f6c6343000811000a","devdoc":{"methods":{}},"userdoc":{"methods":{}}} |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.17; | ||
|
||
contract AnyoneAuthenticator { | ||
function isSolver(address) external pure returns (bool) { | ||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.17; | ||
|
||
import { IERC20 } from "./interfaces/IERC20.sol"; | ||
import { ISettlement, Interaction, Trade } from "./interfaces/ISettlement.sol"; | ||
import { Caller } from "./libraries/Caller.sol"; | ||
import { SafeERC20 } from "./libraries/SafeERC20.sol"; | ||
|
||
struct Asset { | ||
address token; | ||
uint256 amount; | ||
} | ||
|
||
struct Allowance { | ||
address spender; | ||
uint256 amount; | ||
} | ||
|
||
/// @title A contract for verifying DEX aggregator swaps for solving. | ||
contract Swapper { | ||
using Caller for *; | ||
using SafeERC20 for *; | ||
|
||
/// @dev Simulates the execution of a single DEX swap over the CoW Protocol | ||
/// settlement contract. This is used for accurately simulating gas costs | ||
/// for orders with solver-computed fees. | ||
/// | ||
/// @param settlement - the CoW Protocol settlement contract. | ||
/// @param sell - the asset being sold in the swap. | ||
/// @param buy - the asset being bought in the swap. | ||
/// @param allowance - the required ERC-20 allowance for the swap; the | ||
/// approval will be me made on behalf of the settlement contract. | ||
/// @param call - the call for executing the swap. | ||
/// | ||
/// @return gasUsed - the cumulative gas used for executing the simulated | ||
/// settlement. | ||
function swap( | ||
ISettlement settlement, | ||
Asset calldata sell, | ||
Asset calldata buy, | ||
Allowance calldata allowance, | ||
Interaction calldata call | ||
) external returns ( | ||
uint256 gasUsed | ||
) { | ||
if (IERC20(sell.token).balanceOf(address(this)) < sell.amount) { | ||
// The swapper does not have sufficient balance. This can happen | ||
// when hooks set up required balance for a trade. This is currently | ||
// not supported by this simulation, so return "0" to indicate that | ||
// no simulation was possible and that heuristic gas estimates | ||
// should be used instead. | ||
return 0; | ||
} | ||
|
||
// We first reset the allowance to 0 because some ERC20 tokens (e.g. USDT) | ||
// require that due to this attack: | ||
// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 | ||
// Before approving the amount we actually need. | ||
IERC20(sell.token).safeApprove(address(settlement.vaultRelayer()), 0); | ||
IERC20(sell.token).safeApprove(address(settlement.vaultRelayer()), sell.amount); | ||
|
||
address[] memory tokens = new address[](2); | ||
tokens[0] = sell.token; | ||
tokens[1] = buy.token; | ||
|
||
uint256[] memory clearingPrices = new uint256[](2); | ||
clearingPrices[0] = buy.amount; | ||
clearingPrices[1] = sell.amount; | ||
|
||
Trade[] memory trades = new Trade[](1); | ||
trades[0] = Trade({ | ||
sellTokenIndex: 0, | ||
buyTokenIndex: 1, | ||
receiver: address(0), | ||
sellAmount: sell.amount, | ||
buyAmount: buy.amount, | ||
validTo: type(uint32).max, | ||
appData: bytes32(0), | ||
feeAmount: 0, | ||
flags: 0x40, // EIP-1271 | ||
// Actual amount is irrelevant because we configure a fill-or-kill | ||
// order for which the settlement contract determines the | ||
// `executedAmount` automatically. | ||
executedAmount: 0, | ||
signature: abi.encodePacked(address(this)) | ||
}); | ||
|
||
Interaction[][3] memory interactions; | ||
if ( | ||
IERC20(sell.token).allowance(address(settlement), allowance.spender) | ||
< allowance.amount | ||
) { | ||
interactions[0] = new Interaction[](1); | ||
interactions[0][0].target = sell.token; | ||
interactions[0][0].callData = abi.encodeCall( | ||
IERC20(sell.token).approve, | ||
(allowance.spender, allowance.amount) | ||
); | ||
} | ||
interactions[1] = new Interaction[](1); | ||
interactions[1][0] = call; | ||
|
||
gasUsed = address(settlement).doMeteredCallNoReturn( | ||
abi.encodeCall( | ||
settlement.settle, | ||
(tokens, clearingPrices, trades, interactions) | ||
) | ||
); | ||
} | ||
|
||
/// @dev Validate all signature requests. This makes "signing" CoW protocol | ||
/// orders trivial. | ||
function isValidSignature(bytes32, bytes calldata) external pure returns (bytes4) { | ||
return 0x1626ba7e; | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
node-url = "http://localhost:8545" | ||
absolute-slippage = "40000000000000000" # Denominated in wei, optional | ||
relative-slippage = "0.1" # Percentage in the [0, 1] range | ||
relative-slippage = "0.001" # Percentage in the [0, 1] range | ||
risk-parameters = [0,0,0,0] | ||
|
||
[dex] | ||
chain-id = "1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
use std::time::Duration; | ||
|
||
/// Creates a node RPC instance. | ||
pub fn rpc(url: &reqwest::Url) -> ethrpc::Web3 { | ||
ethrpc::web3( | ||
Default::default(), | ||
reqwest::ClientBuilder::new() | ||
.timeout(Duration::from_secs(10)) | ||
.user_agent("cowprotocol-solver-engine/1.0.0"), | ||
url, | ||
"base", | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.