the layer the console The layer explains the bound. The console is where you write one.
THE CONSOLE

Make an agent.
Say what it may do.

Then send it wherever it already trades.

UNTOLL sits between your agent and your wallet. You write the bound here, once. It holds inside the contract that moves the funds, so the agent trades at any destination you pick and it cannot spend past what you allowed. When it tries, the refusal carries a reason.

THE TEN THINGS A SCOPE CAN REFUSE one reason per refusal, named on chain
TARGET
A contract the scope never named.
SELECTOR
A call the scope never allowed.
PER_TX
More value in one transaction than you set.
PER_EPOCH
More value in a window than you set.
RECIPIENT
Output pointed somewhere you did not allow.
EXPIRED
After the date the scope runs out.
UNIT_PER_TX
More token units in one transaction than you set.
UNIT_PER_EPOCH
More token units in a window than you set.
GRANT_LIMIT
More standing approvals left behind than you set.
CALLDATA_SHORT
A call too short to carry the arguments the scope checks.

Every control in the console arms one of these. Nothing in the interface exists that the contract cannot enforce, and nothing the contract enforces is missing from it. The counter beside every scope screen reports that while you work.

where it runs · you pick, the bound travels

The agent trades where it already trades.

The bound lives at your wallet, not at the venue, so a destination is a choice you make rather than an agreement anyone has to sign. Four of them are here. The full list has six, and room to name your own.

Open the destination list →
Who is acting A name you will recognise in a refusal six weeks from now.
Name
Lives in the console only. The chain sees an address.
What it is for
Written for the person deciding whether to renew this scope. That person is usually you, later, with less context than you have now.
Its keyA fresh session key, generated in your browser.
Session keygenerated on save
The session key acts strictly inside the scope. Your own key stays unrestricted and stays yours.
the record · what your agent asked for, and what it got

Every attempt gets an answer.

Two answers exist. A call inside the scope settles. A call outside it is held, and the reason is written down where you can point at it later. Both live in the same list, because both are the scope working.

scout
Your agent. Nothing attempted yet.
0
settled
0
held

The record fills the first time your agent acts. Until then the interesting reading is below: the same scope, six attempts, one of them allowed.

Six attempts, one scope
From the public demo run. One command, a local chain in Prague mode, the delegate deployed fresh and the keys generated per run.
1
settled
5
held
4
mined as events
0
wei to the attacker
#what the agent asked foranswer
01
An in-scope call to an allowed contract, output to the owner.
SETTLED
02
The identical call, output redirected to another address.
RECIPIENT

Same contract, same function, one address different a hundred bytes into the arguments. The scope reads that argument.

Held
reverted, named reason
RecipientNotAllowed
moved 0 wei
03
The same redirect again, this time through the monitored path.
RECIPIENT

Nothing forwards, and the refusal is mined as a ScopeViolation event, so the attempt is a published fact rather than a log you have to trust.

Held
mined ScopeViolation
moved 0 wei
04
A call to drain() on an allowed contract.
SELECTOR

The contract was on the list. This call was not. Allowing a contract is not allowing everything it exposes.

Held
mined ScopeViolation
moved 0 wei
05
An allowed call carrying 2 ETH.
PER_TX

Against a 1.0 ETH per-transaction cap. The window counter was never touched, because nothing settled.

Held
mined ScopeViolation
moved 0 wei
06
An allowed call, to a contract the scope never named.
TARGET

The list is stored once at install. There is no function that adds to it later, which is why a compromised agent cannot widen its own reach.

Held
mined ScopeViolation
moved 0 wei
Five held, one settled, and the balance that mattered never moved. Run it yourself: git clone github.com/hookwright/untoll-agent-demo then npm install && npm run demo. The keys are generated per run and never funded, so nothing on your machine is at stake.

Attempts 02 and 03 are the same call twice, on the two entry points the delegate exposes. One reverts with a named reason and one mines an event. Neither forwards anything, and the difference is only where the receipt lives.

Scope an agent →See the destinations
UNTOLL, the enforcement layer for agent trading. the layer  ·  run the demo  ·  a destination in detail