Skip to content

Commit 5a8ade7

Browse files
authored
feat: Base target module for Aerodrome (#35)
* introduce target modules * add initiator contract * add aerodrom local tes * remove example file * module for aerodrome * add aerodrome guide * scripts to try swaps * fix amount bug * increase gas limit * add tip in onSettle interface * update address in sample contract * add amount check * use safe transfer * add more checks for initiate swap
1 parent 7d05406 commit 5a8ade7

File tree

16 files changed

+1373
-183
lines changed

16 files changed

+1373
-183
lines changed

.gitignore

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@ out/
88
/broadcast/*/31337/
99
/broadcast/**/dry-run/
1010

11-
# Docs
12-
docs/
13-
1411
# Dotenv file
1512
.env
1613

docs/aerodrome.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# Aerodrome Cross-Chain Swap Integration: Creating Intents
2+
3+
This document explains how to create intents for cross-chain swaps on Aerodrome DEX using the AerodromeInitiator contract.
4+
5+
## Creating an Aerodrome Swap Intent
6+
7+
You can use Foundry's `cast` command to create Aerodrome swap intents from the command line.
8+
9+
### Step 1: Approve Tokens to the Initiator
10+
11+
First, approve the AerodromeInitiator contract to spend your tokens:
12+
13+
```shell
14+
cast send [TOKEN_ADDRESS] "approve(address,uint256)" \
15+
[AERODROME_INITIATOR_ADDRESS] \
16+
[AMOUNT+TIP] \
17+
--rpc-url [SOURCE_RPC_URL] \
18+
--private-key [YOUR_PRIVATE_KEY]
19+
```
20+
21+
### Step 2: Create the Swap Intent
22+
23+
Call the `initiateAerodromeSwap` function on the AerodromeInitiator contract:
24+
25+
```shell
26+
# Define the parameters for the swap
27+
SOURCE_TOKEN=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 # Source chain USDC
28+
TARGET_TOKEN=0x4200000000000000000000000000000000000006 # Base WETH
29+
AMOUNT=1000000 # 1 USDC (6 decimals)
30+
TIP=100000 # 0.1 USDC
31+
SALT=123 # Any unique number
32+
GAS_LIMIT=300000
33+
MIN_AMOUNT_OUT=0 # Be careful with this in production!
34+
DEADLINE=$(($(date +%s) + 3600)) # 1 hour from now
35+
RECEIVER=0xYourAddressHere # Your address on Base
36+
37+
# Execute the swap intent creation
38+
cast send $AERODROME_INITIATOR_ADDRESS \
39+
"initiateAerodromeSwap(address,uint256,uint256,uint256,uint256,address[],bool[],uint256,uint256,address)" \
40+
$SOURCE_TOKEN \
41+
$AMOUNT \
42+
$TIP \
43+
$SALT \
44+
$GAS_LIMIT \
45+
"[\"$SOURCE_TOKEN\",\"$TARGET_TOKEN\"]" \
46+
"[false]" \
47+
$MIN_AMOUNT_OUT \
48+
$DEADLINE \
49+
$RECEIVER \
50+
--rpc-url $SOURCE_RPC_URL \
51+
--private-key $PRIVATE_KEY
52+
```
53+
54+
## Complete Example (Ready to Run)
55+
56+
Here's a concrete example with all parameters directly in the command:
57+
58+
```shell
59+
# This command initiates a swap of 1 USDC to WETH on Base
60+
cast send 0x123456789AbCdEf0123456789aBcDeF01234567 \
61+
"initiateAerodromeSwap(address,uint256,uint256,uint256,uint256,address[],bool[],uint256,uint256,address)" \
62+
0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 \
63+
1000000 \
64+
100000 \
65+
12345 \
66+
300000 \
67+
"[\"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\"0x4200000000000000000000000000000000000006\"]" \
68+
"[false]" \
69+
0 \
70+
1718438400 \
71+
0xaB1234C567dEf890123456789aBcDef012345678 \
72+
--rpc-url https://zetachain-evm.blockpi.network/v1/rpc/public \
73+
--private-key 0xYOUR_PRIVATE_KEY_HERE
74+
```
75+
76+
Replace:
77+
- `0x123456789AbCdEf0123456789aBcDeF01234567` with your AerodromeInitiator contract address
78+
- `0xaB1234C567dEf890123456789aBcDef012345678` with your receiving address on Base
79+
- `0xYOUR_PRIVATE_KEY_HERE` with your private key
80+
- `1718438400` with a future timestamp (this example is set to June 15, 2024)
81+
82+
## Parameter Breakdown
83+
84+
- **SOURCE_TOKEN**: The token you're sending (e.g., USDC on ZetaChain)
85+
- **AMOUNT**: Amount of tokens to swap (in the token's smallest unit)
86+
- **TIP**: Incentive for fulfillers to execute your intent
87+
- **SALT**: A unique number to generate a distinct intent ID
88+
- **GAS_LIMIT**: Gas limit for execution on Base
89+
- **PATH**: Array of token addresses for the swap path (must start with SOURCE_TOKEN)
90+
- **STABLE_FLAGS**: Array of booleans indicating if each pool is stable (false) or volatile (true)
91+
- **MIN_AMOUNT_OUT**: Minimum amount to receive after the swap
92+
- **DEADLINE**: Unix timestamp after which the swap will revert
93+
- **RECEIVER**: Address on Base to receive the swapped tokens
94+
95+
## Troubleshooting
96+
97+
### Common Issues
98+
99+
1. **Path and Flags Length Mismatch**: Ensure that `stableFlags.length == path.length - 1`
100+
2. **Token Mismatch**: The first token in the path must match the `asset` parameter
101+
3. **Insufficient Approval**: Ensure you've approved the initiator to spend at least `amount + tip` tokens
102+

examples/CrossChainSwapper.sol

Lines changed: 0 additions & 168 deletions
This file was deleted.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity 0.8.26;
3+
4+
import {Script, console2} from "forge-std/Script.sol";
5+
import {AerodromeInitiator} from "../../../src/targetModules/base/AerodromeInitiator.sol";
6+
7+
/**
8+
* @title AerodromeInitiatorScript
9+
* @dev Deployment script for the Aerodrome initiator contract on source chain
10+
*/
11+
contract AerodromeInitiatorScript is Script {
12+
function setUp() public {}
13+
14+
function run() public {
15+
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
16+
vm.startBroadcast(deployerPrivateKey);
17+
18+
// Get addresses from environment variables
19+
address intentContract = vm.envAddress("INTENT_CONTRACT");
20+
address targetModule = vm.envAddress("AERODROME_MODULE_ADDRESS");
21+
uint256 targetChainId = vm.envUint("BASE_CHAIN_ID");
22+
23+
// Deploy AerodromeInitiator on the source chain
24+
AerodromeInitiator aerodromeInitiator = new AerodromeInitiator(intentContract, targetModule, targetChainId);
25+
26+
console2.log("AerodromeInitiator deployed to:", address(aerodromeInitiator));
27+
console2.log("Intent Contract:", intentContract);
28+
console2.log("Target Module:", targetModule);
29+
console2.log("Target Chain ID:", targetChainId);
30+
31+
vm.stopBroadcast();
32+
}
33+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity 0.8.26;
3+
4+
import {Script, console2} from "forge-std/Script.sol";
5+
import {AerodromeModule} from "../../../src/targetModules/base/AerodromeModule.sol";
6+
7+
/**
8+
* @title AerodromeModuleScript
9+
* @dev Deployment script for the Aerodrome module contract on Base chain
10+
*/
11+
contract AerodromeModuleScript is Script {
12+
function setUp() public {}
13+
14+
function run() public {
15+
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
16+
vm.startBroadcast(deployerPrivateKey);
17+
18+
// Get addresses from environment variables
19+
address aerodromeRouter = vm.envAddress("AERODROME_ROUTER");
20+
address poolFactory = vm.envAddress("AERODROME_POOL_FACTORY");
21+
address intentContract = vm.envAddress("INTENT_CONTRACT");
22+
23+
// Deploy AerodromeModule on the target chain (Base)
24+
AerodromeModule aerodromeModule = new AerodromeModule(aerodromeRouter, poolFactory, intentContract);
25+
26+
console2.log("AerodromeModule deployed to:", address(aerodromeModule));
27+
console2.log("Aerodrome Router:", aerodromeRouter);
28+
console2.log("Pool Factory:", poolFactory);
29+
console2.log("Intent Contract:", intentContract);
30+
31+
// Optional: Set reward percentage if different from default (5%)
32+
// uint256 customRewardPercentage = 10;
33+
// aerodromeModule.setRewardPercentage(customRewardPercentage);
34+
// console2.log("Reward percentage set to:", customRewardPercentage);
35+
36+
vm.stopBroadcast();
37+
}
38+
}

0 commit comments

Comments
 (0)