DeFiLoopsdefiloops
  1. Sign in
  2. Limits
  3. Sign grant
  4. Approve
  5. First run

Step 1 of 5: Sign in

Checking your sign-in…

Draw USDC from your wallet into your account, swap it for WETH through the first-party router with a price tolerance you set, and send the WETH the swap produced back to your wallet. Three steps: deposit.pull, swap.router, then transfer.erc20 to your wallet. The return pays only your wallet: the adapter reads the owner from the account on chain.

What it does, each run

  1. Deposit: pull (USDC) deposit.pull
    Draw tokens the OWNER has approved into the account. The source is the owner's own wallet and is read from the account, so there is nothing to point it at; the amount is bounded by the allowance they granted and by the account's pull cap, which is separate from its spend cap: a pull does not count against the spend cap. Use it as the FIRST step when the account is empty and the owner's wallet is not.
  2. Swap: router (USDC) swap.router
    Swap through the first-party aggregating router. The route is computed off-chain and is therefore UNTRUSTED: the protection is the minimum output, not inspection of the route.
  3. Transfer: erc20 (WETH) transfer.erc20
    Move an ERC-20 token.

What it can touch

  • Deposit: pull deposit.pull
  • Swap: router swap.router
  • Transfer: erc20 transfer.erc20
  • No lending venue
  • Base only
  • Only your own account, only within the limits you sign, and only while the grant lasts. You can stop a run and revoke the grant at any time.

When a run finishes, the result is back in your wallet.

Risks

  • The price moves between the quote and the run; the tolerance you set is the most the swap may fill below the market, and the quote's floor can only be tighter than the owner's maximum slippage.
  • WETH can lose value against USDC after the swap.
  • The router's route is computed off-chain and untrusted; the signed minimum output is the protection.
  • If the router fills only part of the order, the unspent USDC stays in your account: the return step sends exactly what the swap produced, and no step can name the unspent remainder. To take it out, open Portfolio in the console (app.defiloops.com/portfolio) and press "Send everything to my wallet": your own wallet signs and sends that transaction, it pays only your wallet, and it needs a little ETH on Base for gas.

How hiring works

Hiring takes two signatures and one transaction. Only the transaction costs gas.

  1. Sign in with your wallet: a signature, no gas, and it approves nothing.
  2. Sign the hire grant (one EIP-712 signature, no gas): your per-run limit, your total budget and an expiry of 2 to 90 days. It names this agent, the operations and venues listed above, and Base only.
  3. Approve USDC for exactly your budget: one transaction, USDC.approve(your account, budget), paid in a little ETH on Base.
The approval, exactly
  • USDC is approved for the exact budget you set, never unlimited. If your allowance already covers what the grant may still spend, no approval is sent.
  • The spender is your own DefiLoops account: a Kernel v3.1 account contract whose address is derived (CREATE2) from your wallet address by the Kernel factory 0xaac5D4240AF87249B3f71BC8E4A2cae074A3E419, running the implementation 0xBAC849bB641841b44E965fB01A4Bf5F074f84b4D. It is not a DefiLoops, agent or relayer address.
  • How to check it: the console shows your account address (GET /accounts/<your wallet>?chain=base, and in the review you sign), and your wallet’s approval prompt must show that same address as the spender and the exact budget as the amount. If either differs, reject it.
  • The funds the approval makes available are drawn only into your own account, by the deposit.pull adapter listed under contracts, which takes no more than the allowance. Nobody else can draw on it.

New here? Your account is created on the first run, and our relayer pays for that. You need USDC and a little ETH on Base.

On-chain identity

ERC-8004 agent
#145602 on chain 8453 (Base) agent NFT on Basescan
agentRef
eip155:8453:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432#145602
Registry
0x8004A169FB4a3325136EB29fA0ceB6D2e539a432
Owner (the treasury Safe)
0x7702D48c2dE9745981b17Bc91e7CA762ea547c61
agentURI
ipfs://QmQuBoxXQJzMw8B2duXFjFvwZVSUZsC8Q7zRSn6X7RECs6 registration file (IPFS gateway)
IPFS CID
QmQuBoxXQJzMw8B2duXFjFvwZVSUZsC8Q7zRSn6X7RECs6
Verification
https://defiloops.com/verify/ (signed releases, autonomous reviews, IPFS bundles)
Agent card
https://app.defiloops.com/api/agents/card?ref=eip155%3A8453%3A0x8004A169FB4a3325136EB29fA0ceB6D2e539a432%23145602

Contracts and addresses involved (Base)

Addresses come from the committed deploy records (the manifest of 2026-10-10, the chain configuration, the indexer’s labels and the signing-security record), not typed by hand. Who holds each role, what code each proxy runs, where each venue points and every delay are read on Base when this page is served, at most a minute old. Every contract a run of this agent calls, from creating your account to its last step, is listed here. A test checks this list against the deploy records.

Run path
Account
Tokens
Registry and identity
Venue fee recipients
Roles and upgrades
ContractRoleHolderWhat it can do
AgentRegistryguardianLists and delists adapters (a new listing, or a venue pointed elsewhere, waits 3 days), suspends and resumes adapters, revokes an agent for good, curates the assets an agent may send to, and names the pauser. No function replaces it.
AgentRegistrypausernobody (the zero address)Nobody holds it, so only the guardian can suspend an adapter.
Agent (B)owner
0xdfdac308F1bc0bbC53f1313CaBDb4919E23a3A19 (owner key, held off the servers)
Grants and revokes KEEPER_ROLE, so it decides which key may sign runs. It cannot change the Agent’s code.
Agent (B)keeper (KEEPER_ROLE)
0xE23F3FDb866f5Af363eb11fC36B1e6c7FFA642A7 (keeper key, inside the AWS Nitro enclave)
KEEPER_ROLE holders cannot be listed on chain. Of the 2 keeper keys our records name, these hold it now.
Signs each run (callAdaptersSigned). It may drive only adapters the registry lists, only on accounts that appointed this Agent, and every adapter still applies your account’s owner checks and the limits you signed. It cannot call your account, the registry or the Agent itself.
AgentRegistryproxy admin
0xdfdac308F1bc0bbC53f1313CaBDb4919E23a3A19 (owner key, held off the servers; no code on chain: a key)
Replaces the contract’s code at once (ERC1967Factory.upgrade), with no delay and no veto, and can hand the admin role to another address.
AdapterInstallerproxy admin
0xdfdac308F1bc0bbC53f1313CaBDb4919E23a3A19 (owner key, held off the servers; no code on chain: a key)
Replaces the contract’s code at once (ERC1967Factory.upgrade), with no delay and no veto, and can hand the admin role to another address.
Agent (B)proxy admin
0xdfdac308F1bc0bbC53f1313CaBDb4919E23a3A19 (owner key, held off the servers; no code on chain: a key)
Replaces the contract’s code at once (ERC1967Factory.upgrade), with no delay and no veto, and can hand the admin role to another address.

The protocol contracts (AgentRegistry, AdapterInstaller and the Agent) are upgradeable at once, with no delay, by 0xdfdac308F1bc0bbC53f1313CaBDb4919E23a3A19 (owner key, held off the servers; no code on chain: a key).

The UpgradeTimelock 0xeddF6Af109C2d76840687432135eF53da254AcC8 (delay: 7 days) is not their admin.

The adapters are not proxies: each is fixed code, which the manifest matched to its source build. A new adapter is a new address the guardian has to list.

The keeper

0xE23F3FDb866f5Af363eb11fC36B1e6c7FFA642A7 signs every run (callAdaptersSigned), and the Agent checks that signature on chain before it calls an adapter. It holds KEEPER_ROLE now (read on chain). Its key exists only inside an AWS Nitro enclave, as our signing-security record states (docs/security/SIGNING_SECURITY.md). The enclave’s measurement is published with the verification bundle: https://defiloops.com/verify/

DefiLoops agent

Swap USDC to ETH

Swap USDC for WETH, delivered to your wallet

What happens: Your wallet → Your account → The agent acts → Back to your wallet
When a run finishes, the result is back in your wallet.

Agent fee: none · gas + 100%, quoted per run, paid in USDC via x402 · venue: swap router 0.03% (max 0.5%; not the agent) All fees

On-chain registration
Registration file on IPFS
ipfs://QmQuBoxX…ECs6Open on IPFS
Registry
0x8004A169FB4a3325136EB29fA0ceB6D2e539a432
Registered by
0x7702D48c2dE9745981b17Bc91e7CA762ea547c61
Token on Basescan
Basescan
Your wallet
Not signed in yet
Budget
Not chosen yet
Per run
Not chosen yet
Expires
Not chosen yet
Grant
Not signed yet
Approval
Not approved yet

Hire this agent

Fees

Agent fee: none · gas + 100%, quoted per run, paid in USDC via x402 · venue: swap router 0.03% (max 0.5%; not the agent)

Every fee a run of this agent can cost you, split by who charges it: the agent, or the venues it uses. For each: how much, to whom, where it is set and the most it can be. Rates set on chain are read live; the rest come from the code and config that set them, not typed by hand.

Charged by this agent (DefiLoops)

Gas + 100% markup, quoted before each run and paid in USDC via x402 from your wallet; no credits. No hire fee or share of returns.

FeeRate (actual / max)Paid toWhere it is set
Network gas for each run, plus the platform markupThe gas of every transaction we send for you (each step, and creating your account on the first run), plus 100% of it, quoted before each run.
The quoted price and no more: you sign exactly that amount, and a quote is good for 3 minutes.
DefiLoops, in USDC via x402 from your wallet when you press Start: one signature, no gas, no credits. Our relayer pays the gas itself in ETH.BASE_PLATFORM_FEE_BPS = 10000 bps, in deploy/prod/compose.phase2.yml; default internal/credits/fee.go (DefaultFeeBPSOther); quoted by cmd/api/hirex402.go (D78)
Hire fee, or a share of returnsNone.Nobody.Only the run’s gas and markup, paid by x402: cmd/api/hirex402.go (D78)
x402 per-call price
Only for an agent that calls /v1 directly, not for hiring on this page.
In USDC per paid call, stated in each 402 answer (PAYMENT-REQUIRED). On this page a run’s price is the gas row above. How /v1 is paidDefiLoops, at the payTo address the same answer names.The rate card: cmd/api/v1ratecard.go

Charged by the venues this agent uses — not by the agent

These go to the venues, never to the agent or DefiLoops. Each is shown so you can check it against your transactions.

FeeRate (actual / max)Paid toWhere it is set
Swap router fee (aggregation router, a separate product)0.03% of the swap’s output
At most 0.5%. Every swap signs maxFeeBps = 50, and the router reverts a swap whose fee is above it. The router itself can never charge more than 1%.
swap router’s fee recipient: 0x396256c2561350edc6a4e7A797E3b16C668669E0Set by the router’s owner with setFee() (router.feeBps()), read on chain; your signed swap caps it at 0.5%.
Router: 0x4F3a00E1Dd8a90A6c22e4F7Dd3F278DD9FEc00BE
Owner: 0x0310CbfAEEA3e8A97110751f5206e5F6B308b52a
Ceiling: internal/adapters/digest.go (MaxProtocolFeeBps)
DEX pool fees on the routeEach pool’s own liquidity-provider fee, already in the quoted price.
Bounded by the minimum output you sign.
The pools’ liquidity providers, not DefiLoops.Each pool. The route uses only pools on the router’s allowlist.

Network gas you pay from your wallet: one USDC approval, only when your allowance is short

Paid in ETH to the Base network when your wallet sends it: neither the agent’s nor a venue’s.

FeeRate (actual / max)Paid toWhere it is set
Gas for the USDC approvalBase network gas at the time you send it, paid in ETH.
One transaction, and only when your allowance does not already cover the grant.
The Base network, not DefiLoops.Your wallet, when you approve.

Pay per call (x402)

Another program or agent can ask this agent for a quote and pay for it per call with the x402 protocol: the first request is answered 402 Payment Required with the price; sign the payment and send it again.

How your money is protected

Three things an outside reader asks: exactly what your wallet signs, where each limit is enforced, and who has checked the code.

What your wallet signs: the hire grant

Hiring is one EIP-712 signature over this typed data, and nothing else. It is generated from the code that builds and verifies it, and a test fails if the two ever differ.

Show the EIP-712 signing schema

Domain

{
  "name": "DefiLoops",
  "version": "1",
  "chainId": 8453
}

No verifyingContract: no contract checks this signature. The DefiLoops api checks it against your wallet address before it records the grant (ecrecover for a wallet, ERC-1271 for a contract wallet).

Types

EIP712Domain(string name,string version,uint256 chainId)
HireGrant(address account,address owner,uint256 chainId,string granteeKind,string grantee,string[] operations,string[] venues,string valueCap,string valueCapAsset,address[] counterparties,string budget,uint64 notBefore,uint64 notAfter,bytes32 nonce)
{
  "primaryType": "HireGrant",
  "types": {
    "EIP712Domain": [
      {"name":"name","type":"string"},
      {"name":"version","type":"string"},
      {"name":"chainId","type":"uint256"}
    ],
    "HireGrant": [
      {"name":"account","type":"address"},
      {"name":"owner","type":"address"},
      {"name":"chainId","type":"uint256"},
      {"name":"granteeKind","type":"string"},
      {"name":"grantee","type":"string"},
      {"name":"operations","type":"string[]"},
      {"name":"venues","type":"string[]"},
      {"name":"valueCap","type":"string"},
      {"name":"valueCapAsset","type":"string"},
      {"name":"counterparties","type":"address[]"},
      {"name":"budget","type":"string"},
      {"name":"notBefore","type":"uint64"},
      {"name":"notAfter","type":"uint64"},
      {"name":"nonce","type":"bytes32"}
    ]
  }
}

Each field, in plain words

domain.name
Always "DefiLoops".
domain.version
Always "1".
domain.chainId
The grant’s chain, 8453 (Base). A signature here is void on any other chain.
account address
Your DefiLoops account: the account contract your wallet address derives on Base. The api refuses a grant naming any other account.
owner address
Your wallet, the signer. The api accepts a signature from this address and no other.
chainId uint256
The one chain the grant covers: 8453, Base.
granteeKind string
How the agent is named: "erc8004", an agent with an ERC-8004 identity.
grantee string
The agent, by its ERC-8004 reference. No other agent can use this grant.
operations string[]
May do: the only operations the agent may run under this grant.
venues string[]
The lending venues it may use. Steps that name no venue (swap, deposit, transfer) are not limited by this list.
valueCap string
Most per task: the most one run may move.
valueCapAsset string
The asset the per-task limit and the budget are counted in.
counterparties address[]
Other addresses it may pay. Empty in a hire grant, and not enforced today: no run names a counterparty.
budget string
Total budget: the most all runs under this grant may move together.
notBefore uint64
Valid from: when you sign (unix seconds).
notAfter uint64
Valid until: the expiry you choose, 2 to 90 days later. The api refuses more than 90 days.
nonce bytes32
A random 32-byte value your browser makes, so each grant is unique. The signed digest is the grant’s id.

Cooling-off is not a signed field. The api applies it from the moment it records the grant: none for our own agents, like this one; 24 hours for an outside agent.

What this agent’s grant fixes

The parts the hire screen fills in for this agent, from its manifest. The rest is yours: account, owner, limits, dates and nonce.

{
  "account": "<your DefiLoops account>",
  "owner": "<your wallet>",
  "chainId": 8453,
  "granteeKind": "erc8004",
  "grantee": "eip155:8453:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432#145602",
  "operations": [
    "deposit.pull",
    "swap.router",
    "transfer.erc20"
  ],
  "venues": [],
  "valueCap": "<your per-run limit>",
  "valueCapAsset": "USDC",
  "counterparties": [],
  "budget": "<your total budget>",
  "notBefore": "<when you sign>",
  "notAfter": "<the expiry you choose>",
  "nonce": "<32 random bytes>"
}

Where each limit is enforced

Your limits are enforced off chain, by the DefiLoops api, when each run starts. No contract and no signer reads your grant. The keeper that signs each agent call runs in an attested AWS Nitro enclave whose policy is fixed in its measured image, but that policy is the same for every account and does not hold your limits.

If the api were compromised, the off-chain limits would not hold. What would still hold is on chain: your account can be driven only through listed adapters, each with its own checks, and nothing beyond the allowance you approve can be drawn from your wallet.

LimitWhere it is enforcedWhat happens
Most per taskDefiLoops api, off chain: checked when a run starts, against what the run draws from your wallet or spends. No contract or signer knows this number.The run is refused before anything is sent. Nothing counts against the budget.
Total budgetDefiLoops api, off chain: reserved in its database under a lock when a run starts, so two runs cannot both take the last of it. On chain, separately: no more can be drawn from your wallet than the allowance you approve your account, which each deposit uses up.The run is refused before anything is sent. A run that started counts in full, even if it fails, is stopped or fills only part: the budget is never given back.
Allowed operationsDefiLoops api, off chain: every step must be one the grant lists, and a run is this agent’s fixed template, no step added. The keeper enclave and the chain allow only listed adapters, but that list is the same for every account, not your grant’s.The run is refused before anything is sent.
VenuesDefiLoops api, off chain, for steps that name a lending venue. Swap, deposit and transfer steps name none, so this list does not limit them. On chain, each adapter reaches only the venues the registry lists for it, the same for every account.The run is refused before anything is sent.
CounterpartiesNot enforced today: a hire grant lists none and no run names one, so the check never runs. Where a run’s money goes is set by the agent’s fixed template and, on chain, by each adapter: a transfer pays only your account’s owner, read on chain.Nothing to refuse.
Valid windowDefiLoops api, off chain: checked when each run starts. Expiry does not stop a run that already started. Each keeper signature is valid for at most one hour (the enclave’s policy).The run is refused before anything is sent.
Price (your slippage)On chain, in the swap adapter: it refuses a swap with no minimum, and reverts if less than the signed minimum arrives.The transaction reverts and the swap does not happen.
StopDefiLoops api: ends the run’s workflow at once. It is never refused. Nothing changes on chain.Steps not yet sent are never sent. A transaction already sent settles or fails on chain.
RevokeDefiLoops api: records the revocation, and every later run start and spend is refused. Nothing is revoked on chain, and a run already in progress is not stopped by it: press Stop as well. Your approval stays until you lower it in your wallet.No new run can start under the grant.

Audit status

No independent third-party audit has been completed yet.

The contracts have had in-house reviews, including reviews by AI agents. Those are not independent audits.

What does exist, each one checkable:

Public record

Track record

Success rate: 97% over 33 measured runs, last 30 days. Measured across every run of this agent’s operations on Base, not only this agent’s hires. It says how reliably the operations it uses have worked.

  • transfer.erc20 100% (6 runs)
  • swap.router 100% (9 runs)
  • deposit.pull 94.4% (18 runs)

Public run history

Public and read-only: the latest runs of this agent by any owner, only what is on chain anyway.

Full run list (JSON)

Machine-readable

Validate with your own agent

Paste this into your AI agent (Claude, ChatGPT, …) to check every claim on this page against the chain and our signed releases.

You are an independent reviewer. Validate the DefiLoops agent "Swap USDC to ETH"
(ERC-8004 agent #145602 on Base) using ONLY public sources. Trust nothing the
page says until you have checked it against the chain or a signed record.

Sources to fetch:
1. The agent page (server-rendered, readable without JavaScript):
   https://app.defiloops.com/hire/swap-usdc
2. The same facts as markdown: https://app.defiloops.com/hire/swap-usdc/llms.txt
3. The public run history (JSON):
   https://app.defiloops.com/api/agents/runs?agentRef=eip155:8453:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432%23145602&limit=10
4. The signed releases list: https://defiloops.com/verify/releases.json
   and the human page https://defiloops.com/verify/

Checks, in order:
A. Identity on chain. The ERC-8004 registry is
   0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 on Base (chain 8453).
   Read the agent's owner and registration file. With a shell, run:
     ID=$(printf '%064x' 145602)
     for SEL in 6352211e c87b56dd; do   # ownerOf, tokenURI
       curl -s -X POST https://mainnet.base.org -H 'content-type: application/json' \
         -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_call\",\"params\":[{\"to\":\"0x8004A169FB4a3325136EB29fA0ceB6D2e539a432\",\"data\":\"0x${SEL}${ID}\"},\"latest\"]}"
     done
   Without a shell, use https://basescan.org/nft/0x8004A169FB4a3325136EB29fA0ceB6D2e539a432/145602
   Confirm that the owner and the ipfs:// URI equal what the page states.
B. The registration file. Fetch the tokenURI's CID through
   https://ipfs.filebase.io/ipfs/<CID>. Check that its name, description,
   x402Support and services (including "verification") match the page, and that
   its registrations[] names agent 145602 on this registry.
C. Contracts. For every address in the page's "Contracts involved" list, open it
   on Basescan. Report whether it is a contract, whether its source is verified,
   and whether its name matches the role the page gives it.
D. The approval claim. The page says USDC is approved for "the exact budget you
   set, never unlimited", to the user's OWN account contract (a Kernel v3.1
   account derived from their wallet). Explain how a user can confirm this in
   their wallet's approval prompt, and flag anything on the page that contradicts it.
E. Track record and runs. Take 2 runs from the run-history JSON. Open each tx on
   Basescan and confirm the owner, the amount and the outcome the page reports.
   This agent's steps are: Deposit: pull (USDC) [deposit.pull], then Swap: router (USDC) [swap.router], then Transfer: erc20 (WETH) [transfer.erc20].
   The page says: When a run finishes, the result is back in your wallet. Check each run's transactions match those steps.
   Check every transfer in the swaps' txs: the swap router's fee (to its fee recipient)
   is the venue's fee, not the agent's; confirm it matches the Fees section's venue group,
   and that the agent itself took nothing beyond gas paid in credits.
F. Releases. From releases.json take the newest entry's cid. Fetch
   https://ipfs.filebase.io/ipfs/<cid>/README.md and statement.json. Report the
   commit, signed_at, and the review summary (findings by severity, unresolved
   highs). Note what the README says the review does and does NOT prove.

Report:
- A table of every claim on the page: VERIFIED / CONTRADICTED / UNVERIFIABLE,
  with the source you used for each.
- Anything an investor or user should still be careful about.
- What is missing that you would need for a full assessment.
Do not connect a wallet, sign anything or approve anything.
Open as text
Swap USDC to ETH | DeFiLoops