Skip to main content

tycho_simulation/evm/protocol/etherfi/
decoder.rs

1use std::collections::HashMap;
2
3use alloy::primitives::U256;
4use tycho_client::feed::{synchronizer::ComponentWithState, BlockHeader};
5use tycho_common::{models::token::Token, Bytes};
6
7use crate::{
8    evm::protocol::etherfi::state::{BucketLimit, EtherfiState, RedemptionInfo, EETH_ADDRESS},
9    protocol::{
10        errors::InvalidSnapshotError,
11        models::{DecoderContext, TryFromWithBlock},
12    },
13};
14
15impl TryFromWithBlock<ComponentWithState, BlockHeader> for EtherfiState {
16    type Error = InvalidSnapshotError;
17
18    async fn try_from_with_header(
19        snapshot: ComponentWithState,
20        block: BlockHeader,
21        _account_balances: &HashMap<Bytes, HashMap<Bytes, Bytes>>,
22        _all_tokens: &HashMap<Bytes, Token>,
23        _decoder_context: &DecoderContext,
24    ) -> Result<Self, Self::Error> {
25        let total_value_out_of_lp = U256::from_be_slice(
26            snapshot
27                .state
28                .attributes
29                .get("totalValueOutOfLp")
30                .ok_or_else(|| {
31                    InvalidSnapshotError::MissingAttribute("totalValueOutOfLp".to_string())
32                })?,
33        );
34
35        let total_value_in_lp = U256::from_be_slice(
36            snapshot
37                .state
38                .attributes
39                .get("totalValueInLp")
40                .ok_or_else(|| {
41                    InvalidSnapshotError::MissingAttribute("totalValueInLp".to_string())
42                })?,
43        );
44
45        let total_shares = U256::from_be_slice(
46            snapshot
47                .state
48                .attributes
49                .get("totalShares")
50                .ok_or_else(|| InvalidSnapshotError::MissingAttribute("totalShares".to_string()))?,
51        );
52
53        let mut liquidity_pool_native_balance: Option<U256> = None;
54        let mut eth_amount_locked_for_withdrawl: Option<U256> = None;
55        let mut eth_redemption_info: Option<RedemptionInfo> = None;
56
57        if snapshot.component.id == format!("0x{}", hex::encode(EETH_ADDRESS)) {
58            liquidity_pool_native_balance = Some(U256::from_be_slice(
59                snapshot
60                    .state
61                    .attributes
62                    .get("liquidityPoolNativeBalance")
63                    .ok_or_else(|| {
64                        InvalidSnapshotError::MissingAttribute(
65                            "liquidityPoolNativeBalance".to_string(),
66                        )
67                    })?,
68            ));
69            eth_amount_locked_for_withdrawl = Some(U256::from_be_slice(
70                snapshot
71                    .state
72                    .attributes
73                    .get("ethAmountLockedForWithdrawl")
74                    .ok_or_else(|| {
75                        InvalidSnapshotError::MissingAttribute(
76                            "ethAmountLockedForWithdrawl".to_string(),
77                        )
78                    })?,
79            ));
80
81            let eth_bucket_limiter_raw = snapshot
82                .state
83                .attributes
84                .get("ethBucketLimiter")
85                .ok_or_else(|| {
86                    InvalidSnapshotError::MissingAttribute("ethBucketLimiter".to_string())
87                })?;
88            let eth_bucket_limiter_value = U256::from_be_slice(eth_bucket_limiter_raw);
89
90            let eth_redemption_info_raw = snapshot
91                .state
92                .attributes
93                .get("ethRedemptionInfo")
94                .ok_or_else(|| {
95                    InvalidSnapshotError::MissingAttribute("ethRedemptionInfo".to_string())
96                })?;
97            let eth_redemption_info_value = U256::from_be_slice(eth_redemption_info_raw);
98
99            eth_redemption_info = Some(RedemptionInfo::from_u256(
100                BucketLimit::from_u256(eth_bucket_limiter_value),
101                eth_redemption_info_value,
102            ));
103        }
104
105        Ok(EtherfiState::new(
106            block.timestamp,
107            total_value_out_of_lp,
108            total_value_in_lp,
109            total_shares,
110            eth_amount_locked_for_withdrawl,
111            eth_redemption_info,
112            liquidity_pool_native_balance,
113        ))
114    }
115}