Guides

Earn with Aave

Let your users earn on USDC in Aave’s lending market, with Execute.

Your user sends USDC to an executable address, which supplies it to Aave V3 on Base, and the aTokens that represent it go to your user’s wallet. They never connect their wallet to your app, and never approve anything.

  1. Get an API key

    Create one in the dashboard, and keep it on your server. From a web page, use a client ID instead.

  2. The contracts

    Everything happens on Base. The intent calls these contracts, and nothing else:

    ContractAddressWhy
    USDC0x8335…2913The token your user supplies.
    Aave V3 Pool0xA238…d1c5Aave’s lending pool on Base. Supplying USDC to it mints aBasUSDC.
  3. The intent

    The token is USDC, and the amount is in its base units: USDC has 6 decimals, so 100 USDC is "100000000". Once the address holds exactly the amount, it makes these calls, as itself, in one transaction:

    1approve(address spender, uint256 amount)on USDC

    The pool pulls the USDC with transferFrom, so the address first allows it to take exactly the amount, and no more.

    ArgumentValueWhy
    spender0xA238…d1c5The pool, which takes the USDC in the next call.
    amount$AMOUNTExactly the deposit, so nothing is left approved afterwards.

    2supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode)on Aave V3 Pool

    Aave’s deposit: the pool takes the USDC and mints aBasUSDC to onBehalfOf.

    ArgumentValueWhy
    asset0x8335…2913The asset supplied: USDC.
    amount$AMOUNTAll of it.
    onBehalfOf$WALLETYour user’s wallet: the aBasUSDC is theirs.
    referralCode0Aave’s referral codes are unused: 0.

    recovery is $WALLET: your user’s wallet, so if the supply can’t happen, their USDC goes straight back to them.

  4. Create the address

    Post the intent to Create an address. The expiry is 5 minutes away and the salt is random, so every run gives a new address:

    Request
    AMOUNT=100000000   # the deposit in base units: 100 USDC
    WALLET=0x…         # your user’s wallet
    
    curl https://api.execute.cash/v1/address/create \
      -H "Authorization: Bearer $EXECUTE_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
        "amount": "'$AMOUNT'",
        "calls": [
          {
            "target": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
            "function": "approve(address spender, uint256 amount)",
            "args": ["0xA238Dd80C259a72e81d7e4664a9801593F98d1c5", "'$AMOUNT'"]
          },
          {
            "target": "0xA238Dd80C259a72e81d7e4664a9801593F98d1c5",
            "function": "supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode)",
            "args": ["0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "'$AMOUNT'", "'$WALLET'", "0"]
          }
        ],
        "expirationTimestamp": '$(( $(date +%s) + 300 ))',
        "recovery": "'$WALLET'",
        "salt": "0x'$(openssl rand -hex 32)'",
        "chainId": 8453
      }'

    The response’s address is the executable address. Check it as the quickstart shows before you show it to anyone.

  5. Show it to your user

    Show the address with the exact amount, the token and the chain, in words, and a way to copy each. Beside them, a QR code of an EIP-681 payment request lets your user’s wallet fill in the chain, the token and the amount by itself:

    Payment request
    // address and intent, from the create response
    const request = `ethereum:${intent.token}@${intent.chainId}/transfer?address=${address}&uint256=${intent.amount}`;

    uint256 is in the token’s base units, like the intent’s amount. Say under the code what it fills in, and offer a plain code of the address alone for wallets that can’t read a request; your user then picks the token and chain and enters the amount themselves. The address’s page, execute.cash/address/<address>, shows your user what paying it will do.

    Your user pays with an ordinary transfer, from any wallet or exchange. They connect nothing and approve nothing.

  6. Track it

    Poll the address’s status, or get webhooks. Once it’s settled, your user’s wallet holds aBasUSDC, Aave’s receipt for USDC supplied on Base. Its balance grows as interest accrues, and it redeems for USDC at any time, from any app that supports Aave.