# Cross-chain execution and Aave funding

Implemented contract, 25 September 2026. This extends the existing public `/v1` bot API; the gateway remains in `wagmi-api`, while grants, durable execution, signing and settlement remain in `wagmi-platform`. These notes supersede earlier same-chain-only coverage.

## Deployment and authorization

Deploy `wagmi-platform` for runtime changes. `wagmi-api` already proxies these paths and JSON fields; its changes in this release are documentation and regression tests. No new environment variables or database columns are required. Keep the existing bot worker cron enabled, `WAGMI_BOT_LIVE_ENABLED=true`, platform credential-encryption key, and shared service secret configured. Workers need outbound HTTPS access to the chain RPCs, Across API and configured THORNode endpoints.

In Settings → Bot trading access, revoke the old grant once it has no pending operations, then enable access with the desired networks, actions, **cross-chain swaps** and **automatic USDC funding** selected. Select swaps and Earn withdrawals for funding, plus arbitrage for the final arb. Set spending, daily input, loss/gas and slippage limits. Aave's minimum health factor defaults to 1.2 and may be increased. Existing grants are deliberately not expanded on deployment. The wallet password is entered only in Settings. The bot continues using its existing API key; no pairing or per-trade approval is needed.

## Adapter coverage

| Adapter | Supported actions and networks |
| --- | --- |
| LI.FI | Existing same-chain ERC-20 swaps: ETH, BASE, ARB, BSC, AVAX, OP |
| Across | Direct canonical-USDC transfers: ETH, BASE, ARB, OP, BSC where the live protocol quote supports the pair |
| THORChain | Direct ERC-20 streaming swaps between available token pools on ETH, BASE, AVAX, BSC; halted, staged or missing pools are rejected |
| Aave V3 | Exact underlying-token withdrawals: ETH, BASE, ARB, OP, AVAX; no bot Aave deposits |
| Morpho | Existing supported vault deposits/redemptions: ETH, BASE, ARB |

Network listing is not a promise that every asset pair is available. Native-token swaps, arbitrary contract calls, external recipients, NEAR, CoW and Liquidy execution remain unsupported. Every source, destination and refund address belongs to the grant's selected WAGMI wallet.

An email's observed `1inch, THORChain` route is a discovery signal. The API returns an explicit executable adapter and fresh economics; it does not promise to reproduce that historical composite route. `/arbs/active` includes supported cross-chain pairs for fresh quoting while the opportunity is active. `eligible_for_quote` is structural eligibility, not proof of funding or profit. Use `executable_only=false` to inspect blocked opportunities and follow pagination.

## Bot connection and funding flow

1. Store `WAGMI_BOT_KEY` privately in the runner. Read `/me`, `/capabilities`, and `/bot/grants/current?wallet_id=…`. Check effective scopes, networks, `allow_cross_chain` and `allow_funding`.
2. Read spot inventory with `/balances?wallet_id=…` (use full `asset_id` filters as needed). Read `/earn/positions?wallet_id=…&adapter=aave` for canonical-USDC Aave positions. Repeat `asset_id` (up to 12) for other underlying reserves. `available:false` is unknown/unavailable, never a zero balance. `liquid_assets` still requires a health-factor check before withdrawal.
3. Discover candidates with `/arbs/active?wallet_id=…`. Select an opportunity ID and obtain a fresh quote. If source USDC is insufficient, include explicit funding source, location and amount. Funding is never selected silently.
4. Check the returned minimum output, full economics, funding stages and grant limits. Persist `quote_id`, wallet ID, unique client order ID and idempotency key before executing. A quote moves no funds.
5. Execute the accepted quote once. Poll its execution ID. Source confirmation, `bridging` and `refund_pending` are not completed swaps. Keep the same state file across restarts.
6. On transport uncertainty, look up the original client order and retry the identical execute request/key. Never obtain and submit another funding sequence until the existing execution is terminal. `/recover`, `/resume` and `/reconcile` resume observation of existing hashes; they accept no replacement transaction, destination or password.
7. After a refund or a failure following funding, re-read balances and Aave positions before making a new decision. Tokens may now be in spot on another chain. Do not repeat a withdrawal based on the original inventory.

### Aave withdrawal alone

Discover canonical reserve IDs with `GET /v1/earn/vaults?adapter=aave&chain=BASE`, then:

```http
POST /v1/earn/withdraw/quote
Authorization: Bearer <bot-key>
Content-Type: application/json
```

```json
{
  "wallet_id": "YOUR_WALLET_ID",
  "vault_id": "aave:BASE:0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
  "amount": "505",
  "slippage_bps": 30
}
```

Accept with `POST /v1/earn/withdraw`, the normal `{wallet_id, quote_id, client_order_id}` body and `Idempotency-Key`. Amount is an underlying-token decimal string, not atomic units. Aave does not accept `shares`. Reserve address, supply, liquidity, oracle valuation and conservative post-withdraw health factor are verified on-chain; the exact owned-recipient call is simulated again before broadcast.

### General cross-chain transfer

```http
POST /v1/swaps/quote
```

```json
{
  "wallet_id": "YOUR_WALLET_ID",
  "source_asset_id": "BASE.USDC-0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  "destination_asset_id": "ETH.USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
  "sell_amount": "505",
  "slippage_bps": 30,
  "adapter": "across"
}
```

Accept through `/v1/swaps/execute`. A direct cross-chain swap needs no arb listing. Across uses fixed output and pinned SpokePool calls; THORChain uses live inbound addresses and explicit streaming minimum-output memos. The receiver and refund beneficiary remain the selected wallet.

### Aave Base → Ethereum funding → cross-chain arb

```http
POST /v1/arbs/ID_FROM_ARBS_ACTIVE/quote
```

```json
{
  "wallet_id": "YOUR_WALLET_ID",
  "sell_amount": "500",
  "slippage_bps": 30,
  "adapter": "thorchain",
  "funding": {
    "source_asset_id": "BASE.USDC-0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "location": "aave",
    "amount": "505",
    "adapter": "across"
  }
}
```

This example assumes the discovered arb sells Ethereum USDC. The chosen amounts are illustrative, not a profit claim. The entire sequence is preflighted before withdrawing: up to one Aave withdrawal, one funding bridge and the requested final trade. Funding supports canonical USDC only. `location: "spot"` omits Aave. If the trading wallet already has enough source USDC, funding is skipped. A funding shortfall after bridge fees is rejected rather than silently increasing the amount.

Accept with `/v1/arbs/ID_FROM_ARBS_ACTIVE/execute`. All stages share one execution ID, wallet lease and durable checkpoint. Each actual stage is freshly quoted after the preceding finalized receipt/delivery, using actual spendable balances. No private projected-balance switch is exposed to bots.

Funding principal counts for each stage against the daily input limit. Withdrawal gas, funding bridge fees, bridge gas and final trade costs are included in the full conservative profitability test. Every signing chain must already hold its native gas token. This release does not top up gas automatically.

If the final opportunity becomes unprofitable, the worker stops with `funding_completed_profit_below_threshold` (or another `funding_completed_*` reason). Already-funded tokens stay in the same wallet; no forced trade, automatic redeposit or duplicate withdrawal occurs. A thin 16 bps alert can correctly be rejected after these costs.

The downloadable `wagmi-trading-client.mjs` supports this request as `arbitrage`; add `arb_id` to its input JSON (the client puts it in the URL, not the API body):

```sh
BOT_STATE=./one-pending-order.json node wagmi-trading-client.mjs arbitrage ./funded-arbitrage-request.json
```

Set `WAGMI_API_BASE=https://wagmi-api.vercel.app/v1` and the bot key through the runner's secret store. Use one runner per wallet and durable state. The model can choose candidates; deterministic code handles credentials, request formats and retries.

## Settlement, refunds and failure handling

- A successful source receipt moves the job to `bridging`. Destination finality and actual matching protocol/token events are required for `filled`.
- Across `expired` means `refund_pending`, not refunded. Its indexed deposit/source hash and deposit ID locate a fill or refund; finalized matching delivery events or source token credit verify completion. Across refunds are protocol-managed and can take hours. The API cannot force or speed up a refund. Contract-deferred refunds with no token credit stay pending for investigation; this adapter does not submit separate refund-claim transactions.
- THORChain requires streaming completion/all outbounds signed, source-linked outbound memos, the pinned router's events and actual token credit. A partial swap plus refund is recorded as a partial outcome, never a successful complete fill. Unsupported or ambiguous evidence remains in recovery.
- Verified refund ends `failed` with `failure_code: "bridge_refunded"`; partial delivery ends `failed` with `bridge_partial_fill`. `bridge.received`, `bridge.refunded` and verified transactions describe the outcome. Amounts here are atomic units.
- `funding` exposes current stage, total stages and completed-stage amounts. A completed funding bridge remains indexed once in analytics and volume even if a later trade fails. Aave withdrawals, approvals and unfilled bridge deposits do not become swaps.
- Grant expiry/revocation or live mode off stops new signing. The worker continues receipt/refund observation without the credential. Unknown source broadcasts retain the known transaction hash and lock; no automatic replacement is created. `recovery_required` needs investigation using that execution ID, not another execution request.
- Price-based value changes are mark-to-market at quote prices. Cross-chain inventory conversion is not an atomic, guaranteed round-trip arbitrage.

## Validation and external contracts

Automated tests use mocked chain/provider responses and signing with an isolated PostgreSQL schema. They exercise calldata binding, Aave health/liquidity, quote costs, source-versus-destination finality, refunds, grant revocation, multi-stage retries and analytics idempotency. No production transaction or user withdrawal was performed while implementing this release.

Protocol references: [THORChain swap guide](https://dev.thorchain.org/swap-guide/quickstart-guide.html), [Across deposit tracking](https://docs.across.to/api-reference/deposit/status/get), [Across refund behavior](https://docs.across.to/introduction/refunds), [Aave Pool interface](https://github.com/aave-dao/aave-v3-origin/blob/main/src/contracts/interfaces/IPool.sol). Deployment addresses are pinned in the adapters and checked against live protocol metadata; a deployment change fails closed until reviewed.
