trident_sdk/evm/
deposit.rs1use alloy_primitives::{Address, U256};
2use alloy_provider::network::Network;
3use alloy_provider::{PendingTransactionBuilder, Provider};
4use trident_evm_aa::{MulticallBuilder, MulticallError};
5
6use crate::evm::abi::{IERC20, TridentDeposits};
7
8#[derive(Debug, thiserror::Error)]
11pub enum EvmDepositError {
12 #[error("Contract call failed: {0}")]
14 Contract(#[from] alloy_contract::Error),
15
16 #[error("Approval transaction pending error: {0}")]
18 PendingApproval(#[from] alloy_provider::PendingTransactionError),
19
20 #[error(transparent)]
22 Multicall(#[from] MulticallError),
23}
24
25pub async fn deposit<P, N>(
37 provider: P,
38 deposit_contract: Address,
39 signer_address: Address,
40 token: Address,
41 amount: U256,
42) -> Result<PendingTransactionBuilder<N>, EvmDepositError>
43where
44 P: Provider<N>,
45 N: Network,
46{
47 ensure_allowance(&provider, token, signer_address, deposit_contract, amount).await?;
48 let deposits = TridentDeposits::new(deposit_contract, provider);
49 Ok(deposits.deposit(token, amount).send().await?)
50}
51
52pub async fn deposit_multicall<P, N, I>(
61 provider: P,
62 deposit_contract: Address,
63 signer_address: Address,
64 deposits: I,
65) -> Result<PendingTransactionBuilder<N>, EvmDepositError>
66where
67 P: Provider<N>,
68 N: Network,
69 I: IntoIterator<Item = (Address, U256)>,
70{
71 let mut builder = MulticallBuilder::new();
72 for (token, amount) in deposits {
73 let approve = IERC20::approveCall {
74 spender: deposit_contract,
75 value: amount,
76 };
77 builder = builder.call(token, &approve);
78 let deposit = TridentDeposits::depositCall { token, amount };
79 builder = builder.call(deposit_contract, &deposit);
80 }
81 Ok(builder.send(provider, signer_address).await?)
82}
83
84async fn ensure_allowance<P, N>(
85 provider: P,
86 token: Address,
87 owner: Address,
88 spender: Address,
89 required: U256,
90) -> Result<(), EvmDepositError>
91where
92 P: Provider<N>,
93 N: Network,
94{
95 let erc20 = IERC20::new(token, provider);
96 let current = erc20.allowance(owner, spender).call().await?;
97 if current >= required {
98 return Ok(());
99 }
100 let pending = erc20.approve(spender, required).send().await?;
101 pending.get_receipt().await?;
102 Ok(())
103}