On-chain conditions · ERC-8211

Between signing and execution,
the chain is not the same.

Assertions check what has to be true the moment your transaction runs. If one fails, nothing happens.

For DAO proposals, Safe batches, and EIP-7702 wallets.

Adding assertions to a vote

Upgrade the vault. Hand over the keys.

A DAO proposal upgrades a vault and hands admin to a council Safe. Each concern becomes an assertion that runs right after both actions, in the same transaction. If any assertion fails, the entire transaction reverts.

We’re voting to upgrade the vault and hand admin to the council Safe. It executes in seven days. How do I know it lands the way we voted?

assertions.ethassistant

Once the actions run, the council Safe owns the vault.

If it doesn’t, the whole proposal reverts.

assert $vault::!{owner()(address)} == $councilSafe "handover didn't land"

Answered with Assertions

The owner’s right. But the vault is a proxy. What code is it actually running?

assertions.ethassistant

The implementation behind the proxy, read at execution time, matches the audited build.

One call’s answer feeds the next: read the address, then hash its code.

assert @codeHash!($vault::!{implementation()(address)}) == 0xdfff…9ca9 "unaudited code"

Answered with Operations

We’re handing the keys to a Safe. Who holds its keys?

assertions.ethassistant

Every signer on the council Safe is on the approved list, and at least three must sign.

The owner list is read live and checked one by one, however long it is.

def @onCouncil! "$o: address -> bool" @includes!($council $o)
assert @all!(@safe:owners!($councilSafe) @onCouncil!) "unknown signer"
assert @safe:threshold!($councilSafe) >= 3 "threshold too low"

Answered with Collections

●4 assertions · appended to the proposal’s batch

Use cases

What else has to be true?

Every proposal raises its own questions. Each one becomes a check.

Treasury floor

Is there still enough left after this pays out?

Price bounds

Is the oracle price still where it was when we voted?

Execution window

Is this landing inside the window we agreed on?

Total value

Do all our balances, added together, still cover what we owe?

Deep reads

Is the field buried in that struct what we expect?

Bytes and strings

Is this the token we think it is, by name and not just by address?

The toolkit

One main contract. Three expansion packs.

We use the main contract to check your conditions. We add a pack when a condition needs math, lists, or a value used more than once.

Expansion packv2.0

Collections

Check the whole set.

Array management: check every or any element, find, filter, sort, deduplicate, and total the lists that contracts return, in one call instead of one read per element.

Before you sign,
keep an eye on what needs watching.

Tell the builder what to watch. It turns each condition into an assertion, previews the live value, and adds it to your batch.

Every function on all four contracts →