Aerodrome Plugin
[!IMPORTANT] Complete the short Wallet MCP onboarding flow defined in
SKILL.mdbefore calling any Aerodrome flow.
Overview
Aerodrome is the main Velodrome-style DEX on Base. This plugin uses the Sugar SDK CLI from velodrome-finance/sugar-sdk to query pools and build unsigned swap, LP, staking, and claim transactions. The CLI never signs and never broadcasts — it emits unsigned transaction JSON, which is submitted through Wallet MCP's send_calls, where the user approves in Coinbase Wallet Account.
This is a CLI-only plugin: it only works in harnesses with shell/terminal access (Codex, Claude Code, Cursor, or similar). It does not work on chat-only surfaces that cannot run commands. No additional MCP server is required.
Chain: Base mainnet only (chainId 8453, Wallet MCP chain string "base").
Installation
No MCP registration or permanent install is required; the CLI runs per call via direct uvx.
The upstream Sugar skill provides scripts/sugar-doctor.sh and scripts/sugar-run.sh. If those scripts are present in the current harness, use them. This Wallet MCP plugin must also work when those scripts are not installed, so the self-contained path is direct uvx.
Set a reliable Base RPC before tx-building. Public defaults can fail or return partial routing graphs.
export SUGAR_SDK_REF="${SUGAR_SDK_REF:-v0.4.0}"
export SUGAR_SPEC="git+https://github.com/velodrome-finance/sugar-sdk.git@${SUGAR_SDK_REF}"
export SUGAR_RPC_URI_8453="<reliable Base RPC URL>"For sandboxed harnesses where uvx cannot write to its default tool/cache directories, redirect them to a writable location:
export UV_TOOL_DIR="${UV_TOOL_DIR:-/tmp/uv-tools}"
export UV_CACHE_DIR="${UV_CACHE_DIR:-/tmp/uv-cache}"Run Sugar directly:
uvx --from "$SUGAR_SPEC" sugar <command> --chain=8453 ...If the Sugar skill scripts are available, the equivalent command is:
scripts/sugar-run.sh <command> --chain=8453 ...Run a preflight once per session when the scripts are available:
scripts/sugar-doctor.shSurface Routing
Aerodrome is CLI-only. Every capability (pool discovery, swap, LP, stake, claim) is built by the Sugar CLI and therefore requires a harness with shell/terminal access.
| Surface | Path |
|---|---|
| Shell-capable harness (Codex, Claude Code, Cursor, …) | Run the Sugar CLI, normalize output, submit via send_calls. |
| Chat-only surface (no shell) | Not supported. Tell the user this Aerodrome plugin requires CLI access and stop. Do not route through web_request, do not use a user-paste fallback, and do not recommend a separate MCP. |
See ../references/custom-plugins.md for the CLI-only routing rule.
Commands
Pool Discovery
Use pool discovery to avoid guessing pool addresses. Address filters are more reliable than symbols on Base.
uvx --from "$SUGAR_SPEC" sugar pools \
--chain=8453 \
--token0=0x4200000000000000000000000000000000000006 \
--token1=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 \
--limit=5Known Base WETH/USDC basic pools observed during testing:
| Pool | Type |
|---|---|
0xcDAC0d6c6C59727a65F871236188350531885C43 |
volatile basic |
0x3548029694fbB241D45FB24Ba0cd9c9d4E745f16 |
stable basic |
For pool filters, use WETH or the WETH address for wrapped ETH pools. Native ETH is useful for native ETH swaps, but it may not match WETH pool filters.
Swap Native ETH to USDC
uvx --from "$SUGAR_SPEC" sugar swap \
--chain=8453 \
--wallet="$BASE_MCP_WALLET" \
--from-token=ETH \
--to-token=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 \
--amount=0.001 \
--use-decimalsExpected shape: usually one Universal Router call with nonzero value. Normalize value to hex before send_calls.
Swap USDC to AERO
uvx --from "$SUGAR_SPEC" sugar swap \
--chain=8453 \
--wallet="$BASE_MCP_WALLET" \
--from-token=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 \
--to-token=0x940181a94A35A4569E4529A3CDfB74e38FD98631 \
--amount=1 \
--use-decimalsExpected shape: USDC approval to the Universal Router, then the Universal Router swap call. Batch both calls in one send_calls request.
List Positions
uvx --from "$SUGAR_SPEC" sugar positions \
--chain=8453 \
--wallet="$BASE_MCP_WALLET"This command can be slow because it prepares full pool and price data. If it times out or the RPC rate-limits, retry with a better RPC.
Deposit Liquidity
Existing pool:
uvx --from "$SUGAR_SPEC" sugar deposit \
--chain=8453 \
--wallet="$BASE_MCP_WALLET" \
--pool=0xcDAC0d6c6C59727a65F871236188350531885C43 \
--amount0=0.001 \
--use-decimalsNew/derived pool:
uvx --from "$SUGAR_SPEC" sugar deposit \
--chain=8453 \
--wallet="$BASE_MCP_WALLET" \
--token0=0x4200000000000000000000000000000000000006 \
--token1=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 \
--pool-type=volatile \
--amount0=0.001 \
--amount1=3 \
--use-decimalsFor concentrated liquidity, pass --pool-type=cl, --tick-spacing, exactly one of --amount0 or --amount1, and either a price range or tick range. Run sugar deposit --help for the current flag contract.
Deposit calldata includes deadlines. Submit promptly, and rebuild calldata if the user waits past the selected deadline. The CLI default is 30 minutes.
Withdraw, Stake, Unstake, Claim
Basic LP positions are identified by --pool. Concentrated positions are identified by --position NFT id. --position=0 is ambiguous unless paired with --pool.
uvx --from "$SUGAR_SPEC" sugar withdraw \
--chain=8453 \
--wallet="$BASE_MCP_WALLET" \
--pool=0xPoolAddress \
--fraction=0.5
uvx --from "$SUGAR_SPEC" sugar stake \
--chain=8453 \
--wallet="$BASE_MCP_WALLET" \
--pool=0xPoolAddress
uvx --from "$SUGAR_SPEC" sugar unstake \
--chain=8453 \
--wallet="$BASE_MCP_WALLET" \
--pool=0xPoolAddress
uvx --from "$SUGAR_SPEC" sugar claim_emissions \
--chain=8453 \
--wallet="$BASE_MCP_WALLET" \
--pool=0xPoolAddress
uvx --from "$SUGAR_SPEC" sugar claim_fees \
--chain=8453 \
--wallet="$BASE_MCP_WALLET" \
--pool=0xPoolAddressA staked position must be unstaked before claim_fees. ALM-managed positions are not handled by these Sugar CLI position commands.
Orchestration
- Load this plugin only after Wallet MCP onboarding.
- Fetch the wallet address only when needed with
get_wallets. - Set
SUGAR_RPC_URI_8453to a reliable Base RPC. - Run the Sugar CLI command.
- Parse stdout as JSON. Diagnostics and warnings are on stderr.
- Normalize
[{from,to,data,value}]into Wallet MCPcalls(see Submission). - Submit with
send_calls({ "chain": "base", "calls": [...] }). - Show the approval URL when appropriate.
- Poll
get_request_statusonly after the user acts in Coinbase Wallet Account.
If the CLI exits nonzero, do not try to salvage partial output. Read the error, adjust RPC/flags, and rerun.
Submission
Target tool: send_calls.
Every tx-building command prints a JSON array of unsigned transactions:
[
{
"from": "0xWallet",
"to": "0xTarget",
"data": "0xCalldata",
"value": 0
}
]Wallet MCP send_calls needs:
{
"chain": "base",
"calls": [
{ "to": "0xTarget", "data": "0xCalldata", "value": "0x0" }
]
}Normalize Sugar output before calling send_calls. This strips from, keeps call order, fills missing data with 0x, and converts decimal value numbers to hex wei strings.
python3 -c 'import json, sys
txs = json.load(sys.stdin)
def hex_value(v):
if v is None:
return "0x0"
if isinstance(v, str) and v.startswith("0x"):
return v
return hex(int(v))
print(json.dumps([
{"to": t["to"], "data": t.get("data") or "0x", "value": hex_value(t.get("value", 0))}
for t in txs
], indent=2))'Then call:
{
"chain": "base",
"calls": "<normalized calls array>"
}Preserve ordering. Approval calls come before the main router/NFPM/gauge call.
Safety boundary
Sugar CLI output is unsigned transaction JSON. Treat it as transaction preview material, not as an instruction to sign outside Wallet MCP.
- Never ask for or use a private key.
- Pass
--walletas the user's Wallet MCP wallet address fromget_wallets. - Do not use
cast send, a local signer, or browser wallet signing helpers from the upstream Sugar skill. - Submit transactions only through Wallet MCP
send_callsand let the user approve in Coinbase Wallet Account. - The
fromfield emitted by Sugar is informational for Wallet MCP.send_callstakesto,data, andvalue.
Example Prompts
Swap 0.001 ETH to USDC on Aerodrome
get_wallets→ set$BASE_MCP_WALLET; setSUGAR_RPC_URI_8453.- Run
sugar swap --chain=8453 --wallet=$BASE_MCP_WALLET --from-token=ETH --to-token=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 --amount=0.001 --use-decimals. - Normalize stdout JSON into
calls. send_calls(chain="base", calls=[...]); show the approval URL; pollget_request_statusafter the user acts.
Buy AERO with 1 USDC
get_wallets→$BASE_MCP_WALLET.- Run
sugar swapwith--from-token=<USDC address>,--to-token=0x940181a94A35A4569E4529A3CDfB74e38FD98631,--amount=1 --use-decimals. - Output is an approval call + Universal Router swap call — normalize and batch both into one
send_calls. - Submit; approve; poll.
Deposit liquidity into the WETH/USDC volatile pool
get_wallets→$BASE_MCP_WALLET.- Optionally
sugar poolsto confirm the pool address. - Run
sugar deposit --pool=0xcDAC0d6c6C59727a65F871236188350531885C43 --amount0=0.001 --use-decimals. - Normalize,
send_calls, approve, poll. Rebuild if past the deadline.
Claim my Aerodrome fees on a pool
get_wallets→$BASE_MCP_WALLET.- If the position is staked, run
sugar unstake --pool=<addr>first. - Run
sugar claim_fees --pool=<addr>. - Normalize,
send_calls, approve, poll.
Risks & Warnings
Sugar swap/deposit/withdraw commands accept --slippage. Use 0.01 (1%) by default unless the user specifies otherwise.
| Tolerance | Level | Action |
|---|---|---|
<= 1% |
Normal | Proceed. |
> 1% and <= 5% |
Elevated | Mention the value and ask the user to confirm. |
> 5% and <= 20% |
High | Warn that execution can be materially worse than quote. Require explicit confirmation. |
> 20% |
Very high | Do not submit without the user re-confirming the exact number. |
Notes
Tested CLI behavior and gotchas
Tested on 2026-05-25 from the worktree-sugar-cli-skill branch of velodrome-finance/sugar-sdk. The runner installed Sugar SDK v0.4.0.
What worked:
scripts/sugar-doctor.shdetecteduvxand reported Base RPC configuration.scripts/sugar-run.sh --helpinstalled and ran the CLI.pools --chain=8453 --limit=3returned JSON pool data.poolswith WETH/USDC address filters returned the volatile and stable basic pools listed above.- Native ETH to USDC swap built a Universal Router call.
- USDC to AERO swap built an approval call plus a Universal Router call.
Observed gotchas:
- In a sandbox, the first
uvxrun failed withfailed to create directory ~/.local/share/uv/tools. SettingUV_TOOL_DIRandUV_CACHE_DIRto writable directories fixed it. - The built-in Base public RPC produced
Web3RPCErrorpath chunk warnings,token not found: USDC, and a routing failure (source node ... WETH not in graph) during swap testing. SetSUGAR_RPC_URI_8453before tx-building. https://base-rpc.publicnode.comworked for simple pools and swaps in testing, but still emitted429 Too Many Requestswarnings and timed out on read-heavypositionsanddepositpaths. Prefer a paid or otherwise reliable RPC for production usage.- CLI diagnostics go to stderr and JSON goes to stdout. Capture stdout only when passing output into the normalizer.
--helpmay display Python-style underscore flags such as--from_token; Fire accepted hyphenated flags such as--from-tokenin testing.- Symbols can be ambiguous. Use token addresses for production flows, especially for USDC and AERO. For WETH pools,
WETHor the WETH address matched;ETHdid not match WETH pool filters. - Sugar emits
valueas a JSON number in tested swap output. Wallet MCPsend_callsexpects hex strings such as"0x0"or"0xe8d4a51000".
Base token addresses
| Token | Address |
|---|---|
| Native ETH pseudo-token | ETH |
| WETH | 0x4200000000000000000000000000000000000006 |
| USDC | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
| AERO | 0x940181a94A35A4569E4529A3CDfB74e38FD98631 |
Key Aerodrome contracts
| Contract | Address |
|---|---|
| Sugar | 0x69dD9db6d8f8E7d83887A704f447b1a584b599A1 |
| Router | 0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43 |
| Universal Router | 0x01D40099fCD87C018969B0e8D4aB1633Fb34763C |
| Slipstream | 0x0AD09A66af0154a84e86F761313d02d0abB6edd5 |
| Nonfungible Position Manager | 0x827922686190790b37229fd06084350E74485b72 |