Skip to main content
This strategy is a standard DeFi lending position (protocol: "Aave", network: base-sepolia) running entirely on the Base Sepolia testnet (chain 84532). Use it to integrate and test the Pods lend / withdraw flow end-to-end before pointing your client at a mainnet Aave strategy. You lend faucet USDC into the Aave v3 pool and receive an interest-bearing aToken position; withdrawing redeems it back to USDC. Everything is same-chain and synchronous — there is no bridge leg and no async order fill.
Testnet only. Funds have no real value. USD / TVL figures for this strategy are not meaningful — the faucet USDC has no price feed. Drive your test assertions off raw underlying balances and the on-chain aToken balance, not USD values.

Overview

ItemValue
Strategy IDaave-aBasSepUSDC-base-sepolia
ProtocolAave
NetworkBase Sepolia (84532)
Strategy assetaBasSepUSDC aToken — 0x10F1A9D11CDf50041f3f8cB7191CBE2f31750ACC (6 decimals)
Underlying assetFaucet USDC — 0xba50Cd2A20f6DA35D788639E581bca8d0B5d4D5f (6 decimals)
Actionslend (deposit) / withdraw (redeem)
SettlementSynchronous, single chain (no bridge, no async fill)
Lend:     USDC (Base Sepolia)  → [client signs on Base Sepolia] → aBasSepUSDC shares
Withdraw: aBasSepUSDC shares    → [client signs on Base Sepolia] → USDC (Base Sepolia)

Position: queried with the wallet on Base Sepolia
GET /strategies/:id/bytecode returns bytecode[] (to execute on-chain) plus tracking fields (id, feeCharged, chainIdIn, chainIdOut, crossChain). For a direct same-chain lend/withdraw the quote field is null — it is only populated when an extra swap or bridge leg is involved. aTokens are 1:1 with the underlying at any instant — 1 USDC lent ≈ 1 aBasSepUSDC share.

Initial setup

Before your first request, the signing wallet must be funded on Base Sepolia:
1

Have funds of the underlying asset (faucet USDC)

There is no point buying it — it has no value. Mint it from the Aave faucet (see Get the faucet below).
2

Have Base Sepolia ETH for gas

Your wallet signs and broadcasts the lend / withdraw transaction, so it needs native ETH to pay gas. Grab some from any Base Sepolia faucet.
3

Have a Pods API key

Every request is authenticated with the x-api-key header. See Authentication.
Once the wallet holds faucet USDC and a little Base Sepolia ETH, you can run the full lend → position → withdraw cycle.

1. Get the faucet (USDC)

The underlying is a mock USDC deployed by Aave for Base Sepolia. You acquire it by minting from the Aave testnet faucet — you cannot buy it and it carries no value.
TokenAddressDecimalsChain
Faucet USDC0xba50Cd2A20f6DA35D788639E581bca8d0B5d4D5f684532
aBasSepUSDC0x10F1A9D11CDf50041f3f8cB7191CBE2f31750ACC684532
You only ever mint USDC (the underlying). The aBasSepUSDC aToken is minted by the Aave pool when you lend — never mint or transfer it directly.
1

Open the Aave faucet

2

Select Base Sepolia

Switch the network selector to testnet mode and pick Base Sepolia.
3

Connect your wallet

Connect the wallet you will use to sign Pods transactions.
4

Mint USDC

Click Faucet on USDC — it mints a fixed batch of test USDC to your wallet (repeatable). Confirm the transaction.
After it confirms, the faucet USDC (0xba50Cd2A20f6DA35D788639E581bca8d0B5d4D5f) shows up in your wallet balance. Import the token address if it doesn’t appear automatically.

Option B — mint directly via BaseScan

The Aave faucet is an on-chain contract; you can mint without the UI:
1

Find the Faucet address

Get the Faucet address for the Aave v3 Base Sepolia market from the Aave address-book (testnet markets), or read it from the Aave UI transaction in Option A.
2

Open the contract on BaseScan

Open it on sepolia.basescan.orgContract → Write Contract → Connect.
3

Call mint

Call mint(address token, address to, uint256 amount) with token = the faucet USDC, to = your wallet, amount = base units (6 decimals — 100000000 = 100 USDC).

Base Sepolia ETH for gas

You also need a small amount of native ETH on Base Sepolia to pay gas. A fraction of an ETH covers many test transactions. Public faucets (these are the ones we used):
These faucets dispense ETH for gas, not USDC. Get the underlying USDC from the Aave faucet (Option A / Option B) above.

2. Integration flow

LEND (deposit)                              WITHDRAW (redeem)
──────────────                              ─────────────────
1. GET /v2/strategies?protocol=Aave&network=base-sepolia  → strategyId   (same)
2. Confirm wallet has faucet USDC + ETH     Confirm wallet holds the position
3. GET /strategies/:id/bytecode             GET /strategies/:id/bytecode
     action=lend                              action=withdraw
     amount=<usdcBaseUnits>                    amount=<usdcBaseUnits>
     wallet=<address>                          wallet=<address>
4. Review feeCharged / amounts               Review feeCharged / amounts
5. Sign & broadcast bytecode[] on Base Sepolia (1 tx, synchronous)  (same)
6. Wait for the on-chain receipt             (same)
7. Refresh position                          (same)

3. Resolve the strategy ID

The strategy ID is fixed (aave-aBasSepUSDC-base-sepolia), but you can also discover it:
GET /v2/strategies?protocol=Aave&network=base-sepolia
Returns { data: [...], pagination }. Pick the strategy where asset matches the aToken (0x10F1A9D11CDf50041f3f8cB7191CBE2f31750ACC) and networkId === 84532. Use actions lend and withdraw from availableActions.

4. Lend — lend

GET /strategies/:strategyId/bytecode
ParameterRequiredDescription
actionyeslend
walletyesAddress that signs on Base Sepolia and holds the position
amountyesFaucet USDC in base units (6 decimals — 1000000 = 1 USDC)
outputnobytecode (default) / userOperation / fireblocks / instructions
Example request:
GET /strategies/aave-aBasSepUSDC-base-sepolia/bytecode?action=lend&amount=10000000&wallet=0x1234...
Example response:
{
  "feeCharged": "0",                 // entry fee deducted from the deposit, in USDC base units
  "chainIdIn": 84532,
  "chainIdOut": 84532,
  "id": "65f3a1c8e9b2d4f8a7c1d2e3", // action id (record-keeping; queryable via GET /actions/:id)
  "crossChain": { "isCrossChain": false, "chainIdIn": 84532, "chainIdOut": 84532 },
  "quote": null,                     // null for a direct same-chain lend
  "bytecode": [
    // typically: entry-fee transfer (if any) → ERC20 approve(USDC, AavePool) → AavePool.supply → tracking
    { "to": "0x…", "value": "0", "data": "0x…", "chainId": 84532 }
  ]
}
All bytecode legs are on chainId 84532 (Base Sepolia). Sign and broadcast them on Base Sepolia; the position is live as soon as the transaction confirms.
An entry fee may be deducted from the deposited amount (configured per customer). The amount charged is reported in the top-level feeCharged field, and the aToken shares you receive correspond to the amount after the fee.

5. Withdraw — withdraw

GET /strategies/:strategyId/bytecode
ParameterRequiredDescription
actionyeswithdraw
walletyesAddress on Base Sepolia that holds the position
amountyesUnderlying USDC to redeem, in base units (6 decimals)
outputnobytecode (default) / userOperation / fireblocks / instructions
Because aTokens are 1:1 with the underlying, amount is denominated in USDC base units (not a separate share unit). To exit the full position, use the current position value (see Position). The response shape matches lend (feeCharged, chainIdIn, chainIdOut, id, crossChain, quote: null, bytecode); all legs are on chainId 84532.
A performance fee may be charged on profit at withdraw time and transferred out as part of the bytecode — the redeemed amount reflects the amount after that fee.

6. Position

The wallet is the same EVM address used for signing (always on Base Sepolia for this strategy). Pass wallet to get position fields; omit it to get only APY fields. Single strategy position:
GET /v2/strategies/:strategyId?wallet=<address>
or GET /v2/wallets/:address/strategies/:strategyId (same shape). Wallet snapshot (all positions): GET /v2/wallets/:address?include=all — Aave positions appear under earn.positions where strategy.protocol === "Aave". Position shape (with wallet). Balance fields are AssetAmount objects ({ value, decimals, symbol, displaySymbol }), where value is the raw integer string:
{
  "spotPosition": {
    "currentPosition":   { "value": "<raw>", "decimals": 6, "symbol": "USDC", "displaySymbol": "USDC" },
    "principal":         { "value": "<raw>", "decimals": 6, "symbol": "USDC", "displaySymbol": "USDC" },
    "profit":            { "value": "<raw>", "decimals": 6, "symbol": "USDC", "displaySymbol": "USDC" },
    "cumulativeProfit":  { "value": "<raw>", "decimals": 6, "symbol": "USDC", "displaySymbol": "USDC" },
    "profitInUSD": 0,            // null/0 on testnet — no USDC price feed
    "underlyingBalanceUSD": 0,   // null/0 on testnet — no USDC price feed
    "apy": 0.0,                  // net APY (after performance fee)
    "grossAPY": 0.0,
    "netAPY": 0.0,
    "apyAfterFees": 0.0,
    "inceptionApy": 0.0,
    "avgApy": 0.0,
    "performanceFee": "<raw>"    // optional
  },
  "strategy": {
    "protocol": "Aave",
    "id": "aave-aBasSepUSDC-base-sepolia",
    "asset": "0x10F1A9D11CDf50041f3f8cB7191CBE2f31750ACC",
    "networkId": 84532
  }
}
Without wallet, spotPosition contains only apy, grossAPY, netAPY, inceptionApy, avgApy (and optionally performanceFee) — no balance fields.
underlyingBalanceUSD, profitInUSD and any TVL/USD figure are not meaningful on testnet — the mock USDC has no USD rate. Assert on currentPosition.value (raw underlying) and the on-chain aToken balance.

7. Track the transaction

Settlement is synchronous: once the Base Sepolia transaction confirms, the lend / withdraw is complete — there is no separate async order to await.
  • Wait for the on-chain receipt (status === 1) on chainId 84532.
  • Refresh the position endpoints after confirmation.
  • History is available via GET /wallets/:wallet/history/:strategyId. Ignore INITIAL status (a quote artifact). Optionally subscribe to wss://<api-host>/updates and the wallet channel for action_update events.

8. Network & addresses

ItemValue
NetworkBase Sepolia
Chain ID84532
Explorerhttps://sepolia.basescan.org
Native gas assetETH
Aave Pool0x8bAB6d1b75f19e9eD9fCe8b9BD338844fF79aE27
Aave DataProvider0x3cB7B00B6C09B71998124196691e8bF2694De863
Faucet USDC (underlying)0xba50Cd2A20f6DA35D788639E581bca8d0B5d4D5f (6 decimals)
aBasSepUSDC (aToken)0x10F1A9D11CDf50041f3f8cB7191CBE2f31750ACC (6 decimals)

9. End-to-end testnet run

A full smoke test from a clean wallet:
1

Fund the wallet

Mint faucet USDC (§1) and grab a little Base Sepolia ETH for gas. Verify both balances on BaseScan.
2

Resolve the strategy

Confirm availableActions includes lend and withdraw (§3).
3

Lend a small amount (e.g. 10 USDC)

curl -H "x-api-key: $API_KEY" \
  "https://api.pods.finance/strategies/aave-aBasSepUSDC-base-sepolia/bytecode\
?action=lend&amount=10000000&wallet=0xYOUR_WALLET"
Sign every bytecode leg (chainId 84532) on Base Sepolia.
4

Confirm the position

currentPosition.value should reflect ≈ 10 USDC in base units (minus entry fee, if configured):
curl -H "x-api-key: $API_KEY" \
  "https://api.pods.finance/v2/strategies/aave-aBasSepUSDC-base-sepolia?wallet=0xYOUR_WALLET"
5

Withdraw

curl -H "x-api-key: $API_KEY" \
  "https://api.pods.finance/strategies/aave-aBasSepUSDC-base-sepolia/bytecode\
?action=withdraw&amount=10000000&wallet=0xYOUR_WALLET"
Sign the bytecode on Base Sepolia.
6

Confirm the exit

Refresh the position — currentPosition.value drops back toward 0 and the USDC returns to the wallet (minus any performance fee).
Keep amounts small, re-run the faucet whenever you run low, and assert on raw underlying balances / on-chain aToken balance rather than USD values (no testnet price feed).

10. Errors

The amount-specific errors (LEND_AMOUNT_TOO_SMALL, WITHDRAW_AMOUNT_TOO_SMALL, WITHDRAW_AMOUNT_REQUIRED, REQUEST_LEND_AMOUNT_TOO_LOW) are Ondo-stock specific and do not apply to this Aave strategy. The ones you can actually hit here:
CodeHTTPWhen
NO_API_KEY / INVALID_API_KEY401Missing or invalid x-api-key
QUOTE_NOT_FOUND404Quote no longer available — re-request the bytecode
QUOTE_EXPIRED400Quote expired — re-request the bytecode
BYTECODE_GENERATION_FAILED500Bytecode could not be built (e.g. wallet has no USDC / no position to withdraw)
INTERNAL_SERVER_ERROR500Unexpected server error
There is no dedicated insufficient-balance error code: lending more USDC than the wallet holds (or withdrawing more than the position) surfaces as BYTECODE_GENERATION_FAILED, or the on-chain transaction reverts. See Error Codes for the full list, and preserve error.code in your UI for user-friendly messages.

Integration notes

  1. Use the generic actions: lend (deposit) and withdraw (redeem). There is no request-lend / request-withdraw here — settlement is synchronous and same-chain.
  2. Sign on Base Sepolia (84532) for every leg; the position lives on the same wallet/chain.
  3. Amounts are in USDC base units (6 decimals) for both lend and withdraw — aTokens are 1:1 with the underlying, so there is no separate share unit to convert.
  4. Fees: an entry fee may reduce the lent amount (reported as top-level feeCharged); a performance fee may be taken on profit at withdraw.
  5. Testnet caveats: USD / TVL values are unreliable (no price feed) — assert on raw balances.
  6. Smart accounts: pass output=userOperation, or output=fireblocks with accountId.

Next Steps

Deposit to Yield

The full deposit reference (same-chain & cross-chain) for mainnet strategies

Check Positions

Monitor your open yield positions