Testnet, tokens have no value. Do not send real assets.
Skip to Content
Testnet appsSwap and pools

Swap and pools

The testnet DEX is Uniswap v2 (core and periphery, GPL-3.0, unmodified math) on Aeva’s EVM. Its pools hold AE-20 tokens, the ERC-20 view of native Aeva rights, so a swap moves native rights: the explorer shows an EventTransferred from the pool’s address, and the policy of the asset applies as it does to any transfer. Testnet, tokens have no value.

Run the setup block first; this guide also uses cast.

The contracts

ContractAddress
Router (UniswapV2Router02)0xf2ea4660567aaA99e7061B5c88C7Fa35Bf5FEA39
Factory0x73959bdf411C9f73eFA08e05a7073418A3CD33F7
WAEVA (wrapped AEVA)0x53eD54339c3dFbEf259F431071e09e4831d13FDE
aeUSD (6 decimals)0x5aB37c022D0ce153F1C1949a88a93A8DC3E546D7

Each pool pairs aeUSD with a test stock’s bundle token (all its kinds as one ERC-20) or with WAEVA:

PoolPairOther token
AEVA / aeUSD0xFC404f637fBa0a964D3Dee6DAb417B3DD8c8A3A3WAEVA
tTSLA / aeUSD0x6ACB18102bCF1a889673B267CdE278d324C61fD60xA1A7C28D97A74E803E7f1237cE49f8272669c22a
tNVDA / aeUSD0xCA3c77AC85c374b34C57FDf0b803dF6dE02284A30xe6239aA4136Eb34149d8d3b47b2fC73BAbeca4fE
tAAPL / aeUSD0xF637A4b041cF827e98f5f5E15813023A9AE339040x3AcfD0e4c178474d452B61B5e0C57321def4E998
tAMZN / aeUSD0x1F53c6Ff0ec596C2864CDDcdB853aAb4180e7a510x55b22C594f43E68029575d0d088A16c34cAc992F
tPLTR / aeUSD0xf7ACFE70E80AC7885D38A0723c3dBdEEA3A5aEaa0x66D45B79305B45Bf0d9BF2E884BD844791faD974

The pair init code hash is 147ac9b133c17a106ca8749a1705605798b9173af80c790796e2716b3f24cafd; the build is reproducible from dex/ in the repository.

1. Read a pool and quote a swap

ROUTER=0xf2ea4660567aaA99e7061B5c88C7Fa35Bf5FEA39 AEUSD=0x5aB37c022D0ce153F1C1949a88a93A8DC3E546D7 TAAPL=0x3AcfD0e4c178474d452B61B5e0C57321def4E998 PAIR=0xF637A4b041cF827e98f5f5E15813023A9AE33904 cast call "$PAIR" "getReserves()(uint112,uint112,uint32)" --rpc-url "$AEVA_EVM" cast call "$ROUTER" "getAmountsOut(uint256,address[])(uint256[])" 10000000 "[$AEUSD,$TAAPL]" --rpc-url "$AEVA_EVM"
Expected output
<reserve0> [<…>] <reserve1> [<…>] <timestamp> [10000000 [1e7], <units out> [<…>]]

A pair orders its tokens by address: tAAPL (0x3Acf…) sorts before aeUSD (0x5aB3…), so reserve0 is tAAPL and reserve1 aeUSD, at the time of writing 2 000 shares against 400 000 aeUSD, 200 aeUSD a share. The quote is the tAAPL units (six decimals) that 10 aeUSD buys after the 0.3 % pool fee, about 0.05 of a share.

2. Swap 10 aeUSD for tAAPL

Your Aeva key is also an Ethereum key: the same secp256k1 key signs both, and 0x… and aeva1… are two spellings of one account.

unsafe-export-eth-key prints the private key. Do this with the throwaway test keyring only.

PK=$(aevad keys unsafe-export-eth-key me --home "$AEVA_HOME" --keyring-backend test) ME_HEX=$(cast wallet address --private-key "$PK") OUT=$(cast call "$ROUTER" "getAmountsOut(uint256,address[])(uint256[])" 10000000 "[$AEUSD,$TAAPL]" --rpc-url "$AEVA_EVM" | tr -d '[]' | awk -F', ' '{print $2}' | awk '{print $1}') MIN=$((OUT * 99 / 100)) cast send "$AEUSD" "approve(address,uint256)" "$ROUTER" 10000000 --private-key "$PK" --rpc-url "$AEVA_EVM" >/dev/null cast send "$ROUTER" "swapExactTokensForTokens(uint256,uint256,address[],address,uint256)" 10000000 "$MIN" "[$AEUSD,$TAAPL]" "$ME_HEX" $(($(date +%s) + 600)) --private-key "$PK" --rpc-url "$AEVA_EVM" --json | jq -r '"swap: status \(.status), tx \(.transactionHash)"'
Expected output
swap: status 0x1, tx 0x…

MIN accepts at most 1 % slippage from the quote. The pool now holds 10 more aeUSD, and you hold more tAAPL, natively, as rights:

curl -s "$AEVA_INDEXER/v1/accounts/$ME" | jq -r --arg a 84f50ea918e0c15c9321362330d513593fd4536b807e1b40a39682dab3e21b55 '.assets[] | select(.asset_id == $a) | "tAAPL: \(.whole_units) units of every kind"'
Expected output
tAAPL: <units> units of every kind

To swap native AEVA, use swapExactETHForTokens with WAEVA as the first hop, as on any Uniswap v2. The app’s /swap  and /pools  pages do the same from MetaMask, and add liquidity.

Notes for contract authors

  • AE-20 tokens are precompiles: there is no code at their address. Solidity before 0.8.10 checks extcodesize before a high-level call and reverts, so the testnet DEX reads balanceOf with a low-level staticcall. See The EVM facade & AE-20.
  • A pool is an ordinary account on the native side: it holds rights, accrues their income, and every transfer in or out passes the asset’s policy.
Last updated