1#![allow(async_fn_in_trait)]
7
8use alloy::primitives::{Address, U256};
9
10use crate::erc4626::IERC4626;
11use crate::error::{ContractError, Result};
12use crate::provider::HttpProvider;
13
14pub trait Erc4626Client {
19 fn provider(&self) -> &HttpProvider;
21
22 fn signer_address(&self) -> Address;
24
25 async fn get_asset(&self, vault: Address) -> Result<Address> {
27 let contract = IERC4626::new(vault, self.provider());
28 let result = contract
29 .asset()
30 .call()
31 .await
32 .map_err(|e| ContractError::TransactionFailed(format!("Failed to get asset: {}", e)))?;
33 Ok(result)
34 }
35
36 async fn total_assets(&self, vault: Address) -> Result<U256> {
38 let contract = IERC4626::new(vault, self.provider());
39 let result = contract.totalAssets().call().await.map_err(|e| {
40 ContractError::TransactionFailed(format!("Failed to get total assets: {}", e))
41 })?;
42 Ok(result)
43 }
44
45 async fn convert_to_shares(&self, vault: Address, assets: U256) -> Result<U256> {
47 let contract = IERC4626::new(vault, self.provider());
48 let result = contract.convertToShares(assets).call().await.map_err(|e| {
49 ContractError::TransactionFailed(format!("Failed to convert to shares: {}", e))
50 })?;
51 Ok(result)
52 }
53
54 async fn convert_to_assets(&self, vault: Address, shares: U256) -> Result<U256> {
56 let contract = IERC4626::new(vault, self.provider());
57 let result = contract.convertToAssets(shares).call().await.map_err(|e| {
58 ContractError::TransactionFailed(format!("Failed to convert to assets: {}", e))
59 })?;
60 Ok(result)
61 }
62
63 async fn max_deposit(&self, vault: Address, receiver: Address) -> Result<U256> {
65 let contract = IERC4626::new(vault, self.provider());
66 let result = contract.maxDeposit(receiver).call().await.map_err(|e| {
67 ContractError::TransactionFailed(format!("Failed to get max deposit: {}", e))
68 })?;
69 Ok(result)
70 }
71
72 async fn max_withdraw(&self, vault: Address, owner: Address) -> Result<U256> {
74 let contract = IERC4626::new(vault, self.provider());
75 let result = contract.maxWithdraw(owner).call().await.map_err(|e| {
76 ContractError::TransactionFailed(format!("Failed to get max withdraw: {}", e))
77 })?;
78 Ok(result)
79 }
80
81 async fn max_mint(&self, vault: Address, receiver: Address) -> Result<U256> {
83 let contract = IERC4626::new(vault, self.provider());
84 let result = contract.maxMint(receiver).call().await.map_err(|e| {
85 ContractError::TransactionFailed(format!("Failed to get max mint: {}", e))
86 })?;
87 Ok(result)
88 }
89
90 async fn max_redeem(&self, vault: Address, owner: Address) -> Result<U256> {
92 let contract = IERC4626::new(vault, self.provider());
93 let result = contract.maxRedeem(owner).call().await.map_err(|e| {
94 ContractError::TransactionFailed(format!("Failed to get max redeem: {}", e))
95 })?;
96 Ok(result)
97 }
98
99 async fn preview_deposit(&self, vault: Address, assets: U256) -> Result<U256> {
101 let contract = IERC4626::new(vault, self.provider());
102 let result = contract.previewDeposit(assets).call().await.map_err(|e| {
103 ContractError::TransactionFailed(format!("Failed to preview deposit: {}", e))
104 })?;
105 Ok(result)
106 }
107
108 async fn preview_mint(&self, vault: Address, shares: U256) -> Result<U256> {
110 let contract = IERC4626::new(vault, self.provider());
111 let result = contract.previewMint(shares).call().await.map_err(|e| {
112 ContractError::TransactionFailed(format!("Failed to preview mint: {}", e))
113 })?;
114 Ok(result)
115 }
116
117 async fn preview_withdraw(&self, vault: Address, assets: U256) -> Result<U256> {
119 let contract = IERC4626::new(vault, self.provider());
120 let result = contract.previewWithdraw(assets).call().await.map_err(|e| {
121 ContractError::TransactionFailed(format!("Failed to preview withdraw: {}", e))
122 })?;
123 Ok(result)
124 }
125
126 async fn preview_redeem(&self, vault: Address, shares: U256) -> Result<U256> {
128 let contract = IERC4626::new(vault, self.provider());
129 let result = contract.previewRedeem(shares).call().await.map_err(|e| {
130 ContractError::TransactionFailed(format!("Failed to preview redeem: {}", e))
131 })?;
132 Ok(result)
133 }
134}
135
136#[macro_export]
148macro_rules! impl_erc4626_transactions {
149 ($client:ty) => {
150 impl $client {
151 pub fn deposit(
154 &self,
155 vault: alloy::primitives::Address,
156 amount: alloy::primitives::U256,
157 receiver: alloy::primitives::Address,
158 ) -> $crate::prepared_call::PreparedCall<'_, $crate::erc4626::IERC4626::depositCall> {
159 let call = $crate::erc4626::IERC4626::depositCall {
160 assets: amount,
161 receiver,
162 };
163 $crate::prepared_call::PreparedCall::new(
164 vault,
165 call,
166 alloy::primitives::U256::ZERO,
167 &self.provider,
168 )
169 }
170
171 pub fn withdraw(
174 &self,
175 vault: alloy::primitives::Address,
176 amount: alloy::primitives::U256,
177 receiver: alloy::primitives::Address,
178 owner: alloy::primitives::Address,
179 ) -> $crate::prepared_call::PreparedCall<'_, $crate::erc4626::IERC4626::withdrawCall>
180 {
181 let call = $crate::erc4626::IERC4626::withdrawCall {
182 assets: amount,
183 receiver,
184 owner,
185 };
186 $crate::prepared_call::PreparedCall::new(
187 vault,
188 call,
189 alloy::primitives::U256::ZERO,
190 &self.provider,
191 )
192 }
193
194 pub fn mint(
197 &self,
198 vault: alloy::primitives::Address,
199 shares: alloy::primitives::U256,
200 receiver: alloy::primitives::Address,
201 ) -> $crate::prepared_call::PreparedCall<'_, $crate::erc4626::IERC4626::mintCall> {
202 let call = $crate::erc4626::IERC4626::mintCall { shares, receiver };
203 $crate::prepared_call::PreparedCall::new(
204 vault,
205 call,
206 alloy::primitives::U256::ZERO,
207 &self.provider,
208 )
209 }
210
211 pub fn redeem(
214 &self,
215 vault: alloy::primitives::Address,
216 shares: alloy::primitives::U256,
217 receiver: alloy::primitives::Address,
218 owner: alloy::primitives::Address,
219 ) -> $crate::prepared_call::PreparedCall<'_, $crate::erc4626::IERC4626::redeemCall>
220 {
221 let call = $crate::erc4626::IERC4626::redeemCall {
222 shares,
223 receiver,
224 owner,
225 };
226 $crate::prepared_call::PreparedCall::new(
227 vault,
228 call,
229 alloy::primitives::U256::ZERO,
230 &self.provider,
231 )
232 }
233 }
234 };
235}