1- use std:: { str:: FromStr , sync:: Arc } ;
1+ use std:: { collections :: HashMap , str:: FromStr , sync:: Arc } ;
22
33use alloy:: {
44 rpc:: types:: { state:: AccountOverride , Block , TransactionRequest } ,
55 sol_types:: SolValue ,
66} ;
77use miette:: { miette, IntoDiagnostic , WrapErr } ;
88use num_bigint:: BigUint ;
9- use tracing:: debug;
9+ use tracing:: { debug, info } ;
1010use tycho_common:: {
1111 models:: { token:: Token , Chain } ,
1212 simulation:: protocol_sim:: ProtocolSim ,
@@ -25,7 +25,12 @@ use tycho_simulation::{
2525 protocol:: models:: ProtocolComponent ,
2626} ;
2727
28- use crate :: { execution:: tenderly:: OverwriteMetadata , RPCTools } ;
28+ use crate :: {
29+ execution:: tenderly:: { get_overwites_string, OverwriteMetadata } ,
30+ RPCTools ,
31+ } ;
32+
33+ const USER_ADDR : & str = "0xf847a638E44186F3287ee9F8cAF73FF4d4B80784" ;
2934
3035pub fn encode_swap (
3136 component : & ProtocolComponent ,
@@ -72,8 +77,7 @@ fn create_solution(
7277 amount_in : BigUint ,
7378 expected_amount_out : BigUint ,
7479) -> miette:: Result < Solution > {
75- let user_address =
76- Bytes :: from_str ( "0xf847a638E44186F3287ee9F8cAF73FF4d4B80784" ) . into_diagnostic ( ) ?;
80+ let user_address = Bytes :: from_str ( USER_ADDR ) . into_diagnostic ( ) ?;
7781
7882 // Prepare data to encode. First we need to create a swap object
7983 let simple_swap =
@@ -168,121 +172,124 @@ fn encode_input(selector: &str, mut encoded_args: Vec<u8>) -> Vec<u8> {
168172/// Returns both the overwrites and metadata for human-readable logging.
169173pub ( crate ) async fn setup_user_overwrites (
170174 rpc_tools : & RPCTools ,
171- solution : & Solution ,
172- transaction : & Transaction ,
175+ user_balances : HashMap < Bytes , BigUint > ,
173176 block : & Block ,
174- user_address : Address ,
175- ) -> miette:: Result < ( AddressHashMap < AccountOverride > , OverwriteMetadata ) > {
177+ to_address : Bytes ,
178+ ) -> miette:: Result < ( AddressHashMap < AccountOverride > , Vec < Bytes > ) > {
176179 let mut overwrites = AddressHashMap :: default ( ) ;
177180 let mut metadata = OverwriteMetadata :: new ( ) ;
178- let token_address = Address :: from_slice ( & solution. given_token [ ..20 ] ) ;
179- // If given token is ETH, add the given amount + 10 ETH for gas
180- if solution. given_token == Bytes :: zero ( 20 ) {
181- let eth_balance = biguint_to_u256 ( & solution. given_amount ) +
182- U256 :: from_str ( "10000000000000000000" ) . unwrap ( ) ; // given_amount + 1 ETH for gas
183- overwrites. insert ( user_address, AccountOverride :: default ( ) . with_balance ( eth_balance) ) ;
184- // if the given token is not ETH, do balance and allowance slots overwrites
185- } else {
186- let results = rpc_tools
187- . evm_balance_slot_detector
188- . detect_balance_slots (
189- std:: slice:: from_ref ( & solution. given_token ) ,
190- ( * * user_address) . into ( ) ,
191- ( * block. header . hash ) . into ( ) ,
192- )
193- . await ;
181+ let mut failed_tokens: Vec < Bytes > = Vec :: new ( ) ;
182+ let user_address = Address :: from_str ( USER_ADDR ) . into_diagnostic ( ) ?;
183+ let spender_address = Address :: from_slice ( & to_address[ ..20 ] ) ;
184+ for ( token_address, balance) in user_balances {
185+ // ETH
186+ if token_address == Bytes :: zero ( 20 ) {
187+ overwrites. insert (
188+ user_address,
189+ AccountOverride :: default ( ) . with_balance ( biguint_to_u256 ( & balance) ) ,
190+ ) ;
191+ } else {
192+ let results = rpc_tools
193+ . evm_balance_slot_detector
194+ . detect_balance_slots (
195+ std:: slice:: from_ref ( & token_address) ,
196+ ( * * user_address) . into ( ) ,
197+ ( * block. header . hash ) . into ( ) ,
198+ )
199+ . await ;
194200
195- let ( balance_storage_addr, balance_slot) =
196- if let Some ( Ok ( ( storage_addr, slot) ) ) = results. get ( & solution. given_token . clone ( ) ) {
197- ( storage_addr, slot)
198- } else {
199- return Err ( miette ! ( "Couldn't find balance storage slot for token {token_address}" ) ) ;
200- } ;
201+ let ( balance_storage_addr, balance_slot) =
202+ if let Some ( Ok ( ( storage_addr, slot) ) ) = results. get ( & token_address) {
203+ ( storage_addr, slot)
204+ } else {
205+ failed_tokens. push ( token_address. clone ( ) ) ;
206+ continue ;
207+ } ;
201208
202- let results = rpc_tools
203- . evm_allowance_slot_detector
204- . detect_allowance_slots (
205- std:: slice:: from_ref ( & solution . given_token ) ,
206- ( * * user_address) . into ( ) ,
207- transaction . to . clone ( ) , // tycho router
208- ( * block. header . hash ) . into ( ) ,
209- )
210- . await ;
209+ let results = rpc_tools
210+ . evm_allowance_slot_detector
211+ . detect_allowance_slots (
212+ std:: slice:: from_ref ( & token_address ) ,
213+ ( * * user_address) . into ( ) ,
214+ to_address . clone ( ) , // tycho router
215+ ( * block. header . hash ) . into ( ) ,
216+ )
217+ . await ;
211218
212- let ( allowance_storage_addr , allowance_slot ) = if let Some ( Ok ( ( storage_addr , slot ) ) ) =
213- results. get ( & solution . given_token . clone ( ) )
214- {
215- ( storage_addr , slot )
216- } else {
217- return Err ( miette ! ( "Couldn't find allowance storage slot for token {token_address}" ) ) ;
218- } ;
219+ let ( allowance_storage_addr , allowance_slot ) =
220+ if let Some ( Ok ( ( storage_addr , slot ) ) ) = results. get ( & token_address . clone ( ) ) {
221+ ( storage_addr , slot )
222+ } else {
223+ failed_tokens . push ( token_address . clone ( ) ) ;
224+ continue ;
225+ } ;
219226
220- // Use the exact given amount for balance and allowance (no buffer, no max)
221- let token_balance = biguint_to_u256 ( & solution . given_amount ) ;
222- let token_allowance = biguint_to_u256 ( & solution . given_amount ) ;
227+ // Use the exact given amount for balance and allowance (no buffer, no max)
228+ let token_balance = biguint_to_u256 ( & balance ) ;
229+ let token_allowance = biguint_to_u256 ( & balance ) ;
223230
224- let balance_storage_address = Address :: from_slice ( & balance_storage_addr[ ..20 ] ) ;
225- let allowance_storage_address = Address :: from_slice ( & allowance_storage_addr[ ..20 ] ) ;
231+ let balance_storage_address = Address :: from_slice ( & balance_storage_addr[ ..20 ] ) ;
232+ let allowance_storage_address = Address :: from_slice ( & allowance_storage_addr[ ..20 ] ) ;
226233
227- let balance_slot_b256 = alloy:: primitives:: B256 :: from_slice ( balance_slot) ;
228- let allowance_slot_b256 = alloy:: primitives:: B256 :: from_slice ( allowance_slot) ;
229- let spender_address = Address :: from_slice ( & transaction. to [ ..20 ] ) ;
234+ let balance_slot_b256 = alloy:: primitives:: B256 :: from_slice ( balance_slot) ;
235+ let allowance_slot_b256 = alloy:: primitives:: B256 :: from_slice ( allowance_slot) ;
230236
231- debug ! (
237+ debug ! (
232238 "Setting token override for {token_address}: balance={}, allowance={}, balance_storage={}, allowance_storage={}" ,
233239 token_balance, token_allowance, balance_storage_address, allowance_storage_address
234240 ) ;
235241
236- // Add metadata for human-readable logging
237- metadata. add_balance ( balance_storage_address, user_address, balance_slot_b256) ;
238- metadata. add_allowance (
239- allowance_storage_address,
240- user_address,
241- spender_address,
242- allowance_slot_b256,
243- ) ;
242+ // Add metadata for human-readable logging
243+ metadata. add_balance ( balance_storage_address, user_address, balance_slot_b256) ;
244+ metadata. add_allowance (
245+ allowance_storage_address,
246+ user_address,
247+ spender_address,
248+ allowance_slot_b256,
249+ ) ;
244250
245- // Apply balance and allowance overrides
246- // If both storage addresses are the same, combine them into one override
247- if balance_storage_address == allowance_storage_address {
248- overwrites. insert (
249- balance_storage_address,
250- AccountOverride :: default ( ) . with_state_diff ( vec ! [
251- (
251+ // Apply balance and allowance overrides
252+ // If both storage addresses are the same, combine them into one override
253+ if balance_storage_address == allowance_storage_address {
254+ overwrites. insert (
255+ balance_storage_address,
256+ AccountOverride :: default ( ) . with_state_diff ( vec ! [
257+ (
258+ balance_slot_b256,
259+ alloy:: primitives:: B256 :: from_slice( & token_balance. to_be_bytes:: <32 >( ) ) ,
260+ ) ,
261+ (
262+ allowance_slot_b256,
263+ alloy:: primitives:: B256 :: from_slice(
264+ & token_allowance. to_be_bytes:: <32 >( ) ,
265+ ) ,
266+ ) ,
267+ ] ) ,
268+ ) ;
269+ } else {
270+ // Different storage addresses, apply separately
271+ overwrites. insert (
272+ balance_storage_address,
273+ AccountOverride :: default ( ) . with_state_diff ( vec ! [ (
252274 balance_slot_b256,
253275 alloy:: primitives:: B256 :: from_slice( & token_balance. to_be_bytes:: <32 >( ) ) ,
254- ) ,
255- (
276+ ) ] ) ,
277+ ) ;
278+ overwrites. insert (
279+ allowance_storage_address,
280+ AccountOverride :: default ( ) . with_state_diff ( vec ! [ (
256281 allowance_slot_b256,
257282 alloy:: primitives:: B256 :: from_slice( & token_allowance. to_be_bytes:: <32 >( ) ) ,
258- ) ,
259- ] ) ,
260- ) ;
261- } else {
262- // Different storage addresses, apply separately
263- overwrites. insert (
264- balance_storage_address,
265- AccountOverride :: default ( ) . with_state_diff ( vec ! [ (
266- balance_slot_b256,
267- alloy:: primitives:: B256 :: from_slice( & token_balance. to_be_bytes:: <32 >( ) ) ,
268- ) ] ) ,
269- ) ;
270- overwrites. insert (
271- allowance_storage_address,
272- AccountOverride :: default ( ) . with_state_diff ( vec ! [ (
273- allowance_slot_b256,
274- alloy:: primitives:: B256 :: from_slice( & token_allowance. to_be_bytes:: <32 >( ) ) ,
275- ) ] ) ,
276- ) ;
283+ ) ] ) ,
284+ ) ;
285+ }
277286 }
278-
279- // Add 10 ETH for gas for non-ETH token swaps
280- let eth_balance = U256 :: from_str ( "10000000000000000000" ) . unwrap ( ) ; // 1 ETH for gas
281- overwrites. insert ( user_address, AccountOverride :: default ( ) . with_balance ( eth_balance) ) ;
282- debug ! ( "Setting ETH balance override for user {user_address}: {eth_balance} (for gas)" ) ;
283287 }
284288
285- Ok ( ( overwrites, metadata) )
289+ let overwrites_string = get_overwites_string ( & overwrites, Some ( & metadata) ) ;
290+ info ! ( "Block {} overwrites: {}" , block. number( ) , overwrites_string) ;
291+
292+ Ok ( ( overwrites, failed_tokens) )
286293}
287294
288295pub ( crate ) fn swap_request (
0 commit comments