Skip to content

Commit

Permalink
feat: Add adapter_contract to EVMPoolState
Browse files Browse the repository at this point in the history
--- don't change below this line ---
ENG-3790 Took 3 hours 42 minutes
  • Loading branch information
dianacarvalho1 committed Oct 29, 2024
1 parent c30887a commit 345ad1b
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 17 deletions.
2 changes: 1 addition & 1 deletion src/protocol/vm/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::protocol::vm::errors::ProtosimError;
use ethers::abi::Uint;

#[allow(dead_code)]
#[derive(Eq, PartialEq, Hash)]
#[derive(Eq, PartialEq, Hash, Debug)]
pub enum Capability {
SellSide = 0,
BuySide = 1,
Expand Down
6 changes: 4 additions & 2 deletions src/protocol/vm/protosim_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ use tracing::warn;
use crate::{
evm::simulation::{SimulationEngine, SimulationParameters, SimulationResult},
protocol::vm::{
constants::EXTERNAL_ACCOUNT,
errors::ProtosimError,
utils::{load_swap_abi, maybe_coerce_error},
},
};

#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct ProtoSimResponse {
pub return_value: Vec<Token>,
pub simulation_result: SimulationResult,
Expand Down Expand Up @@ -51,6 +52,7 @@ pub struct ProtoSimResponse {
/// # Errors
/// Returns errors of type `ProtosimError` when encoding, decoding, or simulation operations fail.
/// These errors provide detailed feedback on potential issues.
#[derive(Clone)]
pub struct ProtosimContract<D: DatabaseRef + std::clone::Clone> {
abi: Abi,
address: Address,
Expand Down Expand Up @@ -156,7 +158,7 @@ where
.timestamp() as u64
}),
overrides,
caller: caller.unwrap_or(Address::ZERO),
caller: caller.unwrap_or(*EXTERNAL_ACCOUNT),
value,
gas_limit: None,
};
Expand Down
94 changes: 80 additions & 14 deletions src/protocol/vm/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,52 +15,83 @@ use crate::{
constants::{ADAPTER_ADDRESS, EXTERNAL_ACCOUNT, MAX_BALANCE},
engine::{create_engine, SHARED_TYCHO_DB},
errors::ProtosimError,
utils::get_code_for_address,
protosim_contract::ProtosimContract,
utils::{get_code_for_address, get_contract_bytecode},
},
};
use chrono::Utc;
use ethers::{
abi::{decode, Address as EthAddress, ParamType},
prelude::U256,
types::{Res, H160},
utils::to_checksum,
};
use revm::{
precompile::{Address, Bytes},
primitives::{alloy_primitives::Keccak256, AccountInfo, Bytecode},
primitives::{alloy_primitives::Keccak256, keccak256, AccountInfo, Bytecode, B256},
DatabaseRef,
};
use std::{collections::HashMap, fmt::Debug, sync::Arc};
use tokio::sync::RwLock;

#[derive(Clone)]
pub struct EVMPoolState<D: DatabaseRef + EngineDatabaseInterface + Clone> {
/// The pool's identifier
pub id: String,
/// The pools tokens
pub tokens: Vec<ERC20Token>,
/// The current block, will be used to set vm context
pub block: BlockHeader,
/// The pools token balances
pub balances: HashMap<H160, U256>,
/// The contract address for where protocol balances are stored (i.e. a vault contract).
/// If given, balances will be overwritten here instead of on the pool contract during
/// simulations
pub balance_owner: Option<H160>, // TODO: implement this in ENG-3758
/// The address to bytecode map of all stateless contracts used by the protocol
/// for simulations. If the bytecode is None, an RPC call is done to get the code from our node
pub stateless_contracts: HashMap<String, Option<Vec<u8>>>,
/// If set, vm will emit detailed traces about the execution
pub trace: bool,
engine: Option<SimulationEngine<D>>,
/// The adapter contract. This is used to run simulations
adapter_contract: Option<ProtosimContract<D>>,
adapter_contract_path: String,
}

impl EVMPoolState<PreCachedDB> {
pub async fn new(
id: String,
tokens: Vec<ERC20Token>,
block: BlockHeader,
balances: HashMap<H160, U256>,
adapter_contract_path: String, // TODO: include this in the adpater contrcat thinsg
stateless_contracts: HashMap<String, Option<Vec<u8>>>,
trace: bool,
) -> Self {
let mut state =
EVMPoolState { id, tokens, block, stateless_contracts, trace, engine: None };
) -> Result<Self, ProtosimError> {
let mut state = EVMPoolState {
id,
tokens,
block,
adapter_contract_path,
balances,
balance_owner: None,
stateless_contracts,
trace,
engine: None,
adapter_contract: None,
};
state
.set_engine()
.await
.expect("Unable to set engine");
state
state.adapter_contract = Some(ProtosimContract::new(
*ADAPTER_ADDRESS,
state
.engine
.clone()
.expect("Engine not set"),
)?);
Ok(state)
}

async fn set_engine(&mut self) -> Result<(), Box<dyn std::error::Error>> {
Expand Down Expand Up @@ -97,15 +128,27 @@ impl EVMPoolState<PreCachedDB> {
None,
false,
);
let adapter_contract_code = get_contract_bytecode(&self.adapter_contract_path)
.map(|bytecode_vec| Some(Bytecode::new_raw(bytecode_vec.into())))
.map_err(|_| {
ProtosimError::DecodingError(
"Error in converting adapter contract bytecode".into(),
)
})?;

engine.state.init_account(
Address::parse_checksummed(ADAPTER_ADDRESS.to_string(), None)
.expect("Invalid checksum for external account address"),
AccountInfo {
balance: *MAX_BALANCE,
nonce: 0,
code_hash: Default::default(),
code: None,
// get_contract_bytecode(self.adapter_contract_path)
code_hash: B256::from(keccak256(
&adapter_contract_code
.clone()
.ok_or(ProtosimError::EncodingError("Can't encode code hash".into()))?
.bytes(),
)),
code: adapter_contract_code,
},
None,
false,
Expand All @@ -128,7 +171,9 @@ impl EVMPoolState<PreCachedDB> {
AccountInfo {
balance: Default::default(),
nonce: 0,
code_hash: Default::default(),
code_hash: B256::from(keccak256(&code.clone().ok_or(
ProtosimError::EncodingError("Can't encode code hash".into()),
)?)),
code: code
.clone()
.map(|vec| Bytecode::new_raw(Bytes::from(vec))),
Expand Down Expand Up @@ -208,10 +253,29 @@ impl EVMPoolState<PreCachedDB> {
#[cfg(test)]
mod tests {
use super::*;
use crate::{evm::simulation_db::BlockHeader, models::ERC20Token};
use ethers::{prelude::U256, types::Address as EthAddress};
use std::collections::HashMap;
use crate::{
evm::{simulation_db::BlockHeader, tycho_models::AccountUpdate},
models::ERC20Token,
protocol::{
vm::{models::Capability, utils::maybe_coerce_error},
BytesConvertible,
},
};
use ethers::{
prelude::{H256, U256},
types::Address as EthAddress,
utils::hex::traits::FromHex,
};
use serde_json::Value;
use std::{
collections::{HashMap, HashSet},
fs::File,
io::Read,
path::Path,
str::FromStr,
};
use tokio::runtime::Runtime;
use tycho_core::{dto::ChangeType, Bytes};

#[tokio::test]
async fn test_set_engine_initialization() {
Expand Down Expand Up @@ -239,6 +303,8 @@ mod tests {
id.clone(),
tokens,
block,
HashMap::new(),
"src/protocol/vm/assets/BalancerV2SwapAdapter.evm.runtime".to_string(),
stateless_contracts.clone(),
true,
)
Expand Down

0 comments on commit 345ad1b

Please sign in to comment.