tycho_simulation/evm/protocol/erc4626/
decoder.rs1use std::{collections::HashMap, str::FromStr};
2
3use tycho_client::feed::{synchronizer::ComponentWithState, BlockHeader};
4use tycho_common::{models::token::Token, Bytes};
5
6use super::state::ERC4626State;
7use crate::{
8 evm::{
9 engine_db::{create_engine, SHARED_TYCHO_DB},
10 protocol::erc4626::vm,
11 },
12 protocol::{
13 errors::InvalidSnapshotError,
14 models::{DecoderContext, TryFromWithBlock},
15 },
16};
17
18impl TryFromWithBlock<ComponentWithState, BlockHeader> for ERC4626State {
19 type Error = InvalidSnapshotError;
20
21 async fn try_from_with_header(
22 snapshot: ComponentWithState,
23 _block: BlockHeader,
24 _account_balances: &HashMap<Bytes, HashMap<Bytes, Bytes>>,
25 all_tokens: &HashMap<Bytes, Token>,
26 decoder_context: &DecoderContext,
27 ) -> Result<Self, Self::Error> {
28 let pool_address = Bytes::from_str(snapshot.component.id.as_str()).map_err(|e| {
29 InvalidSnapshotError::ValueError(format!(
30 "Expected component id to be pool contract address: {e}"
31 ))
32 })?;
33 let asset_address = snapshot
34 .component
35 .tokens
36 .iter()
37 .find(|t| **t != pool_address)
38 .ok_or_else(|| {
39 InvalidSnapshotError::ValueError(format!(
40 "Failed to determine asset address: no token different from pool address ({pool_address}) was found"
41 ))
42 })?;
43 let asset_token = all_tokens
44 .get(asset_address)
45 .ok_or_else(|| {
46 InvalidSnapshotError::ValueError(format!(
47 "Missing asset_token in state: {asset_address}"
48 ))
49 })?;
50 let share_token = all_tokens
51 .get(&pool_address)
52 .ok_or_else(|| {
53 InvalidSnapshotError::ValueError(format!(
54 "Missing share_token in state: {pool_address}"
55 ))
56 })?;
57 let engine = create_engine(
58 SHARED_TYCHO_DB.clone(),
59 decoder_context
60 .vm_traces
61 .unwrap_or_default(),
62 )
63 .expect("Failed to create engine");
64
65 let erc4626_state = vm::decode_from_vm(&pool_address, asset_token, share_token, engine)?;
66 Ok(erc4626_state)
67 }
68}