Skip to content
Mandates / Mandates

Mandates

Bounded authority: an allocator arms ETH behind an agent, inside hard limits the contract checks on every execution.

What a mandate is

A mandate lets an agent spend your ETH on your behalf, but only inside limits you set and the contract enforces. You (the allocator) arm ETH into the MandateVault contract and name an agent (the originator). The agent decides when and what to buy. It can never withdraw your ETH, move it anywhere else, or keep the tokens: every fill sends tokens straight to your wallet.

It is the standing version of a cluster. Instead of approving each trade, you approve a policy once, and every execution the agent runs clears all participating mandates together at one uniform price, the agent's own size included.

The limits

LimitOnchain fieldWhat it stops
Per-trade capperExecWeiAny single execution from taking more than this from your mandate
Daily capdailyCapWeiA busy day from spending more than this. Must be at least the per-trade cap. Resets 24 hours after the current day window started
Max impactceilingBpsYour ETH joining an execution that allows more price impact than you accept (10 to 2,000 bps)
ExpiryexpiryThe mandate outliving your intent. Unix seconds; 0 means no expiry
Armed balancebalanceThe agent ever touching more than you put in

Limits are checked by the contract on every execution, per mandate. A mandate that would breach any of them simply contributes less, or nothing, to that execution.

How an execution uses a mandate

Per-execution cap0.50 ETH
Left in today's cap0.30 ETH
Armed balance2.00 ETH

Wants 0.30 ETH

zero if revoked, expired, wrong originator, or its ceiling is stricter than the execution's

Admitted 0.24 ETH

at an 80% fill ratio; the rest stays armed

FigureIllustration: how the vault sizes one mandate's contribution. The smallest limit binds, then the execution's fill ratio applies. Numbers are examples, not live data.
  1. The originator calls execute(market, ceilingBps, ids, minTokensOut) with up to 64 mandate ids in strictly increasing order and, optionally, its own ETH. minTokensOut is a floor on the whole execution's fill.
  2. For each mandate the vault computes what it can contribute: the smallest of the per-trade cap, what is left of the daily cap, and the armed balance. It is zero if the mandate is revoked, expired, names a different originator, has a stricter ceiling than the execution, is bound to a different market, or the pre-trade spot is above its price cap.
  3. The venue reports capacity under the execution's ceiling. The originator's own ETH is admitted first; mandates share the remaining room by one common fill ratio.
  4. The vault makes one venue buy, takes the 10 bps fee, and transfers tokens to every allocator and the originator in proportion to what each put in: one uniform price for all.

Each fill emits a Filled event with your mandate id, the ETH taken and the tokens sent. The API groups them into MandateExecution records.

Arm, top up, revoke

ActionContract callNotes
Armarm((originator, perExecWei, dailyCapWei, ceilingBps, expiry, market, maxSpotWad)) with ETHCreates the mandate with your ETH as its balance. market binds it to one market (zero address = any market the router accepts); maxSpotWad skips it when spot is above that price (0 = no cap)
Top uptopUp(id) with ETHAdds to the balance. Limits stay as armed
Revokerevoke(id)Instant and unconditional. The whole remaining balance comes back in the same transaction. A revoked mandate can't be reactivated; arm a new one

There is no operator switch that can pause revocation or move armed ETH. Only you can revoke, and only an execution by the originator you named can spend, inside your limits.

Doing it over the API

The API builds the transaction; your wallet signs it. Amounts are decimal ETH strings. The response is a PreparedTx with to, data and value.

Arm a mandate (unsigned transaction)
curl -X POST $NOFOMO/api/v1/tx/arm \
  -H 'content-type: application/json' \
  -d '{
    "originator": "0xAgent...",
    "amountEth": "1.0",
    "perExecEth": "0.1",
    "dailyCapEth": "0.3",
    "ceilingBps": 300,
    "expiry": 0,
    "market": "0xd0601CE157Db5bdC3162BbaC2a2C8aF5320D9EEC",
    "maxSpotEth": "0.09"
  }'

POST /api/v1/tx/top-up takes { mandateId, amountEth } and POST /api/v1/tx/revoke takes { mandateId }. Read your mandates with GET /api/v1/mandates?allocator=0x… and their fills with GET /api/v1/executions?allocator=0x…. Full details in the API reference.

What to watch

A mandate bounds how much an agent can spend and how much impact it can accept. It does not judge whether the agent picks good assets. An originator could also hold the same token elsewhere and benefit from buying it with mandate capital. Watch its history (GET /api/v1/agents/0x…), start with small caps, and use expiry.

Cookie settings

Choose what we may store on this device. You can change this at any time from the footer.

  • Strictly necessary

    Needed for the site to work and to remember your choices here, and to keep a wallet connection you started. These can't be switched off.

  • Preferences

    Remember interface choices such as dismissed hints and layout settings. We don't set any preference storage today; this switch covers it if we add some.

  • Analytics

    Aggregate, privacy-respecting measurement of how pages are used, so we can improve them. No analytics run today, and none will run unless you allow them here.

Full list of every cookie and storage key: cookie policy.