From be77e20e5843bd8178fdb3186d8ba2b54d78d69b Mon Sep 17 00:00:00 2001 From: ts0yu <120932697+ts0yu@users.noreply.github.com> Date: Thu, 15 Aug 2024 14:58:44 +0000 Subject: [PATCH] feat(refactor): deploy tokens and liquid exchange --- .gitmodules | 3 ++ contracts/utils/lib/solmate | 1 + contracts/utils/script/Counter.s.sol | 19 -------- contracts/utils/src/Counter.sol | 14 ------ contracts/utils/test/Counter.t.sol | 24 ---------- src/arena.rs | 72 ++++++++++++++++++++++++---- src/lib.rs | 67 ++++++++++++++++++++------ 7 files changed, 120 insertions(+), 80 deletions(-) create mode 160000 contracts/utils/lib/solmate delete mode 100644 contracts/utils/script/Counter.s.sol delete mode 100644 contracts/utils/src/Counter.sol delete mode 100644 contracts/utils/test/Counter.t.sol diff --git a/.gitmodules b/.gitmodules index b0caa9c..f852f6a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "contracts/utils/lib/forge-std"] path = contracts/utils/lib/forge-std url = https://github.com/foundry-rs/forge-std +[submodule "contracts/utils/lib/solmate"] + path = contracts/utils/lib/solmate + url = https://github.com/tranmissions11/solmate diff --git a/contracts/utils/lib/solmate b/contracts/utils/lib/solmate new file mode 160000 index 0000000..97bdb20 --- /dev/null +++ b/contracts/utils/lib/solmate @@ -0,0 +1 @@ +Subproject commit 97bdb2003b70382996a79a406813f76417b1cf90 diff --git a/contracts/utils/script/Counter.s.sol b/contracts/utils/script/Counter.s.sol deleted file mode 100644 index cdc1fe9..0000000 --- a/contracts/utils/script/Counter.s.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {Script, console} from "forge-std/Script.sol"; -import {Counter} from "../src/Counter.sol"; - -contract CounterScript is Script { - Counter public counter; - - function setUp() public {} - - function run() public { - vm.startBroadcast(); - - counter = new Counter(); - - vm.stopBroadcast(); - } -} diff --git a/contracts/utils/src/Counter.sol b/contracts/utils/src/Counter.sol deleted file mode 100644 index aded799..0000000 --- a/contracts/utils/src/Counter.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -contract Counter { - uint256 public number; - - function setNumber(uint256 newNumber) public { - number = newNumber; - } - - function increment() public { - number++; - } -} diff --git a/contracts/utils/test/Counter.t.sol b/contracts/utils/test/Counter.t.sol deleted file mode 100644 index 54b724f..0000000 --- a/contracts/utils/test/Counter.t.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {Test, console} from "forge-std/Test.sol"; -import {Counter} from "../src/Counter.sol"; - -contract CounterTest is Test { - Counter public counter; - - function setUp() public { - counter = new Counter(); - counter.setNumber(0); - } - - function test_Increment() public { - counter.increment(); - assertEq(counter.number(), 1); - } - - function testFuzz_SetNumber(uint256 x) public { - counter.setNumber(x); - assertEq(counter.number(), x); - } -} diff --git a/src/arena.rs b/src/arena.rs index 42c5292..a3fda14 100644 --- a/src/arena.rs +++ b/src/arena.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use alloy::{providers::ProviderBuilder, signers::local::PrivateKeySigner}; +use alloy::{primitives::U256, providers::ProviderBuilder, signers::local::PrivateKeySigner}; use super::*; use crate::{ @@ -8,7 +8,7 @@ use crate::{ feed::Feed, inspector::Inspector, strategy::Strategy, - types::{PoolManager, PoolManager::PoolKey}, + types::{ArenaToken, LiquidExchange, PoolManager, PoolManager::PoolKey}, }; /// Represents an [`Arena`] that can be used to run a simulation and execute strategies. @@ -40,6 +40,38 @@ impl Arena { .await .unwrap(); + let currency_0 = ArenaToken::deploy( + admin_provider.clone(), + String::from("Currency 0"), + String::from("C0"), + 18, + ) + .await + .unwrap(); + + let currency_1 = ArenaToken::deploy( + admin_provider.clone(), + String::from("Currency 1"), + String::from("C1"), + 18, + ) + .await + .unwrap(); + + let liquid_exchange = LiquidExchange::deploy( + admin_provider.clone(), + *currency_0.address(), + *currency_1.address(), + U256::from(1), + ) + .await + .unwrap(); + + if *currency_1.address() < *currency_0.address() { + self.pool.currency0 = *currency_1.address(); + self.pool.currency1 = *currency_0.address(); + } + pool_manager .initialize( self.pool.clone(), @@ -65,6 +97,18 @@ impl Arena { for step in 0..config.steps { for (idx, strategy) in self.strategies.iter_mut().enumerate() { + liquid_exchange + .setPrice( + alloy::primitives::utils::parse_ether(&self.feed.step().to_string()) + .unwrap(), + ) + .send() + .await + .unwrap() + .watch() + .await + .unwrap(); + strategy.process( self.providers[&(idx + 1)].clone(), Signal::new( @@ -91,7 +135,7 @@ pub struct ArenaBuilder { pub strategies: Vec>>, /// [`Arena::pool`] - pub pool: Option, + pub pool: PoolKey, /// [`Arena::feed`] pub feed: Option>, @@ -114,7 +158,7 @@ impl ArenaBuilder { ArenaBuilder { env: Anvil::default().spawn(), strategies: Vec::new(), - pool: None, + pool: PoolKey::default(), feed: None, providers: None, inspector: None, @@ -127,9 +171,21 @@ impl ArenaBuilder { self } - /// Set the pool that the strategies are to be run against. - pub fn with_pool(mut self, pool: PoolKey) -> Self { - self.pool = Some(pool); + /// Set the pool fee. + pub fn with_fee(mut self, fee: u32) -> Self { + self.pool.fee = fee; + self + } + + /// Set the pool tick spacing. + pub fn with_tick_spacing(mut self, tick_spacing: i32) -> Self { + self.pool.tickSpacing = tick_spacing; + self + } + + /// Set the pool hooks. + pub fn with_hooks(mut self, hooks: Address) -> Self { + self.pool.hooks = hooks; self } @@ -166,7 +222,7 @@ impl ArenaBuilder { Arena { env: self.env, strategies: self.strategies, - pool: self.pool.unwrap(), + pool: self.pool, feed: self.feed.unwrap(), inspector: self.inspector.unwrap(), providers, diff --git a/src/lib.rs b/src/lib.rs index 2f6ae72..95e7e00 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,10 +46,26 @@ mod types { #[allow(missing_docs)] sol! { #[sol(rpc)] - #[derive(Debug)] + #[derive(Debug, Default)] PoolManager, "contracts/v4-core/out/PoolManager.sol/PoolManager.json" } + + #[allow(missing_docs)] + sol! { + #[sol(rpc)] + #[derive(Debug)] + LiquidExchange, + "contracts/utils/out/LiquidExchange.sol/LiquidExchange.json" + } + + #[allow(missing_docs)] + sol! { + #[sol(rpc)] + #[derive(Debug)] + ArenaToken, + "contracts/utils/out/ArenaToken.sol/ArenaToken.json" + } } /// A signal that is passed to a [`Strategy`] to provide information about the current state of the pool. @@ -83,29 +99,50 @@ impl Signal { #[cfg(test)] mod tests { use super::*; - use crate::{arena::ArenaBuilder, config::Config, feed::OrnsteinUhlenbeck, strategy::Strategy}; - + use crate::{ + arena::{Arena, ArenaBuilder}, + config::Config, + feed::OrnsteinUhlenbeck, + strategy::Strategy, + }; struct StrategyMock; + struct InspectorMock; - impl Strategy for StrategyMock { - fn init(&self, _provider: AnvilProvider, _signal: Signal) {} - fn process(&self, _provider: AnvilProvider, _signal: Signal) {} + impl Inspector for InspectorMock { + fn inspect(&self, _step: usize) -> Option { + None + } + fn log(&mut self, _value: f64) {} + fn save(&self) {} + } + + impl Strategy for StrategyMock { + fn init( + &self, + _provider: AnvilProvider, + _signal: Signal, + _inspector: &mut Box>, + ) { + } + fn process( + &self, + _provider: AnvilProvider, + _signal: Signal, + _inspector: &mut Box>, + ) { + } } #[tokio::test] async fn test_arena() { - let builder = ArenaBuilder::new(); + let builder: ArenaBuilder<_> = ArenaBuilder::new(); - let mut arena = builder + let mut arena: Arena = builder .with_strategy(Box::new(StrategyMock {})) - .with_pool(PoolKey { - currency0: Address::default(), - currency1: Address::repeat_byte(1), - fee: 4000, - tickSpacing: 2, - hooks: Address::default(), - }) + .with_fee(4000) + .with_tick_spacing(2) .with_feed(Box::new(OrnsteinUhlenbeck::new(0.1, 0.1, 0.1, 0.1, 0.1))) + .with_inspector(Box::new(InspectorMock {})) .build(); arena.run(Config::new(0)).await;