Skip to content

Instantly share code, notes, and snippets.

@Thegaram
Last active February 12, 2025 12:52
Show Gist options
  • Save Thegaram/51a49a829b2a13ebc88990894a30912b to your computer and use it in GitHub Desktop.
Save Thegaram/51a49a829b2a13ebc88990894a30912b to your computer and use it in GitHub Desktop.

Run dev network:

# set to an L1 node RPC
eth_rpc=""

# run 7702-enabled local forked network
anvil --fork-url "$eth_rpc" --auto-impersonate --odyssey

Configure parameters:

# Anvil dev account
alice="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
alice_pk="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"

# contracts
usdt="0xdac17f958d2ee523a2206206994597c13d831ec7"
multicall="0xcA11bde05977b3631167028862bE2a173976CA11"
scroll_erc20_gateway="0xd8a791fe2be73eb6e6cf1eb0cb3f36adc9b3f8f9"
scroll_message_queue="0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B"

# message configs
amount="1"
gas_limit="200000"

# estimate cross-layer message fee
fee=$(cast call "$scroll_message_queue" "estimateCrossDomainMessageFee(uint256 _gasLimit)(uint256)" "$gas_limit" --json | jq -r '.[]')

Fund test account:

# pre-fund account with ETH
cast rpc anvil_setBalance "$alice" 10000000000000000000

# pre-fund account with USDT
export issuer=$(cast call "$usdt" "owner()(address)")
cast send --from "$issuer" --unlocked "$usdt" "transfer(address to, uint value)" "$alice" "$(( 10 * $amount ))"

Deposit without EIP-7702:

# approve token spending
cast send --from "$alice" --unlocked "$usdt" "approve(address spender, uint256 value)" "$scroll_erc20_gateway" "$amount"

# deposit USDT to Scroll
cast send --from "$alice" --unlocked "$scroll_erc20_gateway" "depositERC20(address _token,uint256 _amount,uint256 _gasLimit)" "$usdt" "$amount" "$gas_limit" --value $fee

# (optional) reset token approval
cast send --from "$alice" --unlocked "$usdt" "approve(address spender, uint256 value)" "$scroll_erc20_gateway" "0"

Deposit with EIP-7702:

# check code without delegation, should return 0x
cast code "$alice"

# execute 7702 delegation
cast send --from "$alice" --private-key "$alice_pk" --auth "$multicall" $(cast az)

# check code again, should return 0xef0100dac17f958d2ee523a2206206994597c13d831ec7
cast code "$alice"

# construct sequence of calls
calls=()

calldata=$(cast calldata "approve(address spender, uint256 value)" "$scroll_erc20_gateway" "$amount")
calls+=("($usdt, false, 0, $calldata)")

calldata=$(cast calldata "depositERC20(address _token,uint256 _amount,uint256 _gasLimit)" "$usdt" "$amount" "$gas_limit")
calls+=("($scroll_erc20_gateway, false, $fee, $calldata)")

calldata=$(cast calldata "approve(address spender, uint256 value)" "$scroll_erc20_gateway" "0")
calls+=("($usdt, false, 0, $calldata)")

# send in a single tx
cast send --from "$alice" --unlocked "$alice" --value $fee "aggregate3Value((address,bool,uint256,bytes)[] calldata calls)" "[${calls[1]}, ${calls[2]}, ${calls[3]}]"
@Turupawn
Copy link

@Thegaram Last line should be

cast send --from "$alice" --unlocked "$alice" --value $fee "aggregate3Value((address,bool,uint256,bytes)[] calldata calls)" "[${calls[0]}, ${calls[1]}, ${calls[2]}]"

Notice the array indices.

@Thegaram
Copy link
Author

Thanks for the feedback. Turns out zsh and bash use different array start indices: https://stackoverflow.com/a/56311706 (the example uses zsh).

@Turupawn
Copy link

Aah I see!
Btw, thanks for this example and the Pectra summary, so helpful!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment