Skip to content

Commit

Permalink
E2E test for partially fillable hooks (#1917)
Browse files Browse the repository at this point in the history
# Description
Follow up on #1892. h/t @nlordell for the support (especially with
fixing the Makefile)

# Changes
- Introduce a simple Counter contract to count how many times we execute
pre and post interactions
- Introduce a new e2e test with 2 partial executions that increment the
counter in pre/post hooks

## How to test
This is a test
  • Loading branch information
fleupold authored Oct 6, 2023
1 parent 8be3d0d commit c3dcbf2
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 3 deletions.
1 change: 1 addition & 0 deletions crates/contracts/artifacts/Counter.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"abi":[{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"counters","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"key","type":"string"}],"name":"incrementCounter","outputs":[],"stateMutability":"nonpayable","type":"function"}],"bytecode":"0x608060405234801561001057600080fd5b5061023e806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806357cedf401461003b5780639424c8c814610078575b600080fd5b6100666100493660046100f3565b805160208183018101805160008252928201919093012091525481565b60405190815260200160405180910390f35b61008b6100863660046100f3565b61008d565b005b600160008260405161009f91906101c2565b908152602001604051809103902060008282546100bc91906101f1565b909155505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561010557600080fd5b813567ffffffffffffffff8082111561011d57600080fd5b818401915084601f83011261013157600080fd5b813581811115610143576101436100c4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610189576101896100c4565b816040528281528760208487010111156101a257600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000825160005b818110156101e357602081860181015185830152016101c9565b506000920191825250919050565b8082018082111561022b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea164736f6c6343000811000a","deployedBytecode":"0x608060405234801561001057600080fd5b50600436106100365760003560e01c806357cedf401461003b5780639424c8c814610078575b600080fd5b6100666100493660046100f3565b805160208183018101805160008252928201919093012091525481565b60405190815260200160405180910390f35b61008b6100863660046100f3565b61008d565b005b600160008260405161009f91906101c2565b908152602001604051809103902060008282546100bc91906101f1565b909155505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561010557600080fd5b813567ffffffffffffffff8082111561011d57600080fd5b818401915084601f83011261013157600080fd5b813581811115610143576101436100c4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610189576101896100c4565b816040528281528760208487010111156101a257600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000825160005b818110156101e357602081860181015185830152016101c9565b506000920191825250919050565b8082018082111561022b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea164736f6c6343000811000a","devdoc":{"methods":{}},"userdoc":{"methods":{}}}
3 changes: 3 additions & 0 deletions crates/contracts/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,9 @@ fn main() {

// Contract for batching multiple `eth_call`s into a single one.
generate_contract("Multicall");

// Test Contract for incrementing arbitrary counters.
generate_contract("Counter");
}

fn generate_contract(name: &str) {
Expand Down
14 changes: 13 additions & 1 deletion crates/contracts/solidity/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ CONTRACTS := \
Trader.sol
ARTIFACTS := $(patsubst %.sol,$(ARTIFACTDIR)/%.json,$(CONTRACTS))

TEST_CONTRACTS := Counter.sol
TEST_ARTIFACTS := $(patsubst %.sol,$(ARTIFACTDIR)/%.json,$(TEST_CONTRACTS))

.PHONY: artifacts
artifacts: $(ARTIFACTS)
artifacts: $(ARTIFACTS) $(TEST_ARTIFACTS)

define ARTIFACTTEMPLATE
{
Expand Down Expand Up @@ -52,3 +55,12 @@ $(TARGETDIR)/%.abi: %.sol
-v "$(abspath $(TARGETDIR)):/target" \
$(SOLC) \
$(SOLFLAGS) -o /target $<

$(TARGETDIR)/%.abi: test/%.sol
@mkdir -p $(TARGETDIR)
@echo solc $(SOLFLAGS) -o /target $(notdir $<)
@$(DOCKER) run -it --rm \
-v "$(abspath .)/test:/contracts" -w "/contracts" \
-v "$(abspath $(TARGETDIR)):/target" \
$(SOLC) \
$(SOLFLAGS) -o /target $(notdir $<)
11 changes: 11 additions & 0 deletions crates/contracts/solidity/tests/Counter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

/// @title Helper contract to count how many times a function is called
contract Counter {
mapping(string => uint256) public counters;

function incrementCounter(string memory key) public {
counters[key] += 1;
}
}
6 changes: 6 additions & 0 deletions crates/contracts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ pub mod support {
}
}

pub mod test {
include_contracts! {
Counter;
}
}

#[cfg(test)]
mod tests {
const MAINNET: u64 = 1;
Expand Down
118 changes: 117 additions & 1 deletion crates/e2e/tests/e2e/colocation_hooks.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use {
contracts::{GnosisSafe, GnosisSafeCompatibilityFallbackHandler, GnosisSafeProxyFactory},
e2e::setup::*,
e2e::{setup::*, tx, tx_value},
ethcontract::{Bytes, H160, U256},
model::{
order::{Hook, OrderCreation, OrderCreationAppData, OrderKind},
Expand All @@ -24,6 +24,12 @@ async fn local_node_signature() {
run_test(signature).await;
}

#[tokio::test]
#[ignore]
async fn local_node_partial_fills() {
run_test(partial_fills).await;
}

async fn allowance(web3: Web3) {
let mut onchain = OnchainComponents::deploy(web3).await;

Expand Down Expand Up @@ -322,3 +328,113 @@ async fn signature(web3: Web3) {
let auction_is_empty = || async { services.get_auction().await.auction.orders.is_empty() };
wait_for_condition(TIMEOUT, auction_is_empty).await.unwrap();
}

async fn partial_fills(web3: Web3) {
let mut onchain = OnchainComponents::deploy(web3.clone()).await;

let [solver] = onchain.make_solvers(to_wei(1)).await;
let [trader] = onchain.make_accounts(to_wei(3)).await;

let counter = contracts::test::Counter::builder(&web3)
.deploy()
.await
.unwrap();

let [token] = onchain
.deploy_tokens_with_weth_uni_v2_pools(to_wei(1_000), to_wei(1_000))
.await;

tx!(
trader.account(),
onchain
.contracts()
.weth
.approve(onchain.contracts().allowance, to_wei(2))
);
tx_value!(
trader.account(),
to_wei(1),
onchain.contracts().weth.deposit()
);

tracing::info!("Starting services.");
let solver_endpoint = colocation::start_solver(onchain.contracts().weth.address()).await;
colocation::start_driver(onchain.contracts(), &solver_endpoint, &solver);

let services = Services::new(onchain.contracts()).await;
services.start_autopilot(vec![
"--enable-colocation=true".to_string(),
"--drivers=http://localhost:11088/test_solver".to_string(),
]);
services
.start_api(vec!["--enable-custom-interactions=true".to_string()])
.await;

tracing::info!("Placing order");
let order = OrderCreation {
sell_token: onchain.contracts().weth.address(),
sell_amount: to_wei(2),
buy_token: token.address(),
buy_amount: to_wei(1),
valid_to: model::time::now_in_epoch_seconds() + 300,
kind: OrderKind::Sell,
partially_fillable: true,
app_data: OrderCreationAppData::Full {
full: json!({
"metadata": {
"hooks": {
"pre": [hook_for_transaction(counter.increment_counter("pre".to_string()).tx).await],
"post": [hook_for_transaction(counter.increment_counter("post".to_string()).tx).await],
},
},
})
.to_string(),
},
..Default::default()
}
.sign(
EcdsaSigningScheme::Eip712,
&onchain.contracts().domain_separator,
SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()),
);
services.create_order(&order).await.unwrap();

tracing::info!("Waiting for first trade.");
let trade_happened = || async {
onchain
.contracts()
.weth
.balance_of(trader.address())
.call()
.await
.unwrap()
== 0.into()
};
wait_for_condition(TIMEOUT, trade_happened).await.unwrap();
assert_eq!(
counter.counters("pre".to_string()).call().await.unwrap(),
1.into()
);
assert_eq!(
counter.counters("post".to_string()).call().await.unwrap(),
1.into()
);

tracing::info!("Fund remaining sell balance.");
tx_value!(
trader.account(),
to_wei(1),
onchain.contracts().weth.deposit()
);

tracing::info!("Waiting for second trade.");
wait_for_condition(TIMEOUT, trade_happened).await.unwrap();
assert_eq!(
counter.counters("pre".to_string()).call().await.unwrap(),
1.into()
);
assert_eq!(
counter.counters("post".to_string()).call().await.unwrap(),
2.into()
);
}
2 changes: 1 addition & 1 deletion crates/orderbook/src/arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ pub struct Arguments {
pub allow_placing_fill_or_kill_limit_orders: bool,

/// Note that partially fillable liquidity limit orders are always allowed.
#[clap(long, env, action = clap::ArgAction::Set, default_value = "false")]
#[clap(long, env, action = clap::ArgAction::Set, default_value = "true")]
pub allow_placing_partially_fillable_limit_orders: bool,

/// Max number of limit orders per user.
Expand Down

0 comments on commit c3dcbf2

Please sign in to comment.