Certen as a Proof‑Gated Enforcement Layer
Certen makes on‑chain execution conditional on cryptographic proof. You authorize one exact operation — a value transfer or an arbitrary contract call — and it executes on the target chain only if a quorum of independent validators has attested that this exact operation was authorized. Nothing else can execute in its place.
This is the property that matters for anything beyond a plain transfer:
| Domain | What Certen enforces |
|---|---|
| Governance / DAOs | a treasury spend or parameter change runs only if the proposal was actually authorized — not a swapped target or amount |
| Voting | the tally‑execution call fires only against the proven result |
| Bridges | funds release only on proof of the corresponding lock/burn event on the source chain |
| AI agents | an autonomous agent's action executes only if the multi‑validator proof authorizes that call — a compromised agent can't substitute a different one |
| Dapps | any sensitive function is gated behind the same proof, with per‑call authorization |
Certen never holds your keys. Your identity signs an intent locally; the gateway turns it into an Accumulate transaction the validators prove; the proof is what unlocks execution.
The guarantee — four things that cannot happen
These are enforced on‑chain by the user's ADI‑derived abstract account
(CertenAccountV5.executeGovernanceProofDirect) and are independently verifiable
(read the contract, or reproduce the reverts with eth_call):
You cannot execute a different call than authorized. The account recomputes
keccak256(chainId, target, value, keccak256(calldata))from the runtime arguments and requires it to equal theexecutionCommitmentstored in the anchor at creation — derived from your signed intent. Change the target, the value, or one byte of calldata and it reverts (runtime params do not match anchor execution commitment).A forged or absent proof reverts. Execution requires the anchor to exist, its merkle proof to verify, and the validator BLS signatures to check out. A fabricated proof reverts (
invalid governance proof). No proof, no execution.A used proof can't be replayed. Each anchor is single‑use (
_anchorConsumed). Re‑submitting the same valid proof after it executed reverts (invalid governance proof).The gate runs before execution, not as cleanup. The checks are contract modifiers that run before the call is made. On any failure nothing executes — no event, no state change, no partial effect. (An
eth_callof a tampered proof reverts without touching state.)
Rigor is identical for a value transfer and a contract call — the only difference is
whether calldata is empty. A call is not "trusted more"; it is bound by the same commitment.
How a call flows
- Authorize — your identity signs an intent naming the exact
(chain, target, value, calldata)and, optionally, the effect that must occur (an event or a storage slot). - Prove — 7 BFT validators independently reconstruct and verify the intent, then BLS‑sign
it. Two on‑chain transactions record the proof:
createAnchor(stores theexecutionCommitment) andexecuteComprehensiveProof(verifies the aggregate BLS proof). - Execute — a third transaction calls
executeGovernanceProofDirecton your abstract account, which runs the two modifiers above and, only if they pass, performstarget.call{value}(calldata). - Attest & write back — the validators re‑observe the execution, verify the committed effect, and (on quorum) write a signed proof‑result back to Accumulate.
You express steps 1–3 through one API call — see below.
Expressing it: the API
Use POST /v1/transaction with a contractCall leg (full field reference in
agent‑quickstart §6). The two‑step signing is the standard
hash_to_sign → sign → submit_url pattern.
{
"identity_id": "<your identity id>",
"intent": {
"adiUrl": "acc://your-org.acme",
"legs": [{
"legId": "leg-1",
"chain": "ethereum-sepolia", "chainId": 11155111,
"fromAddress": "<your abstract account>", // the on-chain msg.sender
"toAddress": "<contract>",
"amount": "0", // native wei; "0" for a pure call
"contractCall": {
"target": "<contract>",
"value": "0", // wei forwarded WITH the call
"functionSignature": "execute(uint256)", // human-readable; bridge ABI-encodes
"args": [42],
"expectedEvents": [ /* RB-4, below */ ],
"expectedState": [ /* RB-5, below */ ]
}
}]
}
}
The validators execute exactly execute(42) on target, forwarding value — or nothing
executes.
Proof‑of‑effect: expectedEvents (RB‑4) and expectedState (RB‑5)
By default "success" means the authorized call executed. For higher‑assurance flows you can require Certen to prove the effect, so validators attest success only if the effect is present in the inclusion‑proven receipt/state — not merely that the tx didn't revert.
expectedEvents(RB‑4) — an event the call must emit:"expectedEvents": [{ "contract": "<emitter>", "topic0": "<keccak256('Released(bytes32,address,uint256)')>", "dataHash": "<optional keccak256 of expected non-indexed data>" }]Validators must find this event in the inclusion‑proven logs before attesting.
expectedState(RB‑5) — a storage slot that must hold a value after execution, proven against the finalized blockstateRoot(the strongest guarantee):"expectedState": [{ "account": "<contract>", "slot": "<32-byte storage slot key, 0x-hex>", "value": "<expected 32-byte slot value, 0x-hex>" }]Use this when an event isn't enough — e.g. a bridge must prove
processed[transferId] == true.
Recipes
1. Governance — execute a passed proposal (treasury / params)
Gate a Governor's execute (or a direct treasury call) so it fires only against the authorized
proposal, and only if it actually took effect.
"contractCall": {
"target": "<governor>",
"value": "0",
"functionSignature": "execute(uint256)",
"args": [1024],
"expectedEvents": [{ "contract": "<governor>",
"topic0": "<keccak256('ProposalExecuted(uint256)')>" }]
}
A malicious relayer cannot redirect the spend, change the amount, or execute a different
proposal — the commitment binds all of it, and RB‑4 requires the ProposalExecuted effect.
2. Bridge — release only on proof of the lock
Release bridged funds only when the destination‑side Released event fires, and prove the
processed flag flipped so the same transfer can't be released twice.
"contractCall": {
"target": "<bridge>",
"value": "0",
"functionSignature": "release(bytes32,address,uint256)",
"args": ["0x<transferId>", "0x<recipient>", "1000000000000000000"],
"expectedEvents": [{ "contract": "<bridge>",
"topic0": "<keccak256('Released(bytes32,address,uint256)')>" }],
"expectedState": [{ "account": "<bridge>",
"slot": "<keccak256(transferId . slot(processedMapping))>", "value": "0x..01" }]
}
3. AI agent — run an escrow/marketplace action
An autonomous agent authorizes a settlement action. If the agent's key is later compromised, an attacker still cannot execute anything but the exact call the quorum proved.
"contractCall": {
"target": "<escrow>",
"value": "1500000", // pays into escrow with the call
"functionSignature": "buy(bytes32)",
"args": ["0x<orderId>"],
"expectedEvents": [{ "contract": "<escrow>",
"topic0": "<keccak256('Paid(bytes32,address)')>" }]
}
4. Dapp — gate any sensitive function
Any function — setConfig, mint, withdraw, upgradeTo — becomes proof‑gated by naming it
as the contractCall. Per‑call authorization, bound to the exact arguments.
Verifying it happened — and was proven
A relying party can confirm both the execution and its proof, without trusting the caller:
- On‑chain execution — the three transactions (
createAnchor,executeComprehensiveProof,executeGovernanceProofDirect) are on the target chain withstatus: 1; the committedexpectedEventsare in the execution tx's receipt logs. - Attested proof‑result on Accumulate — on quorum, the validators write a signed
certen:proof_result:v2record toacc://certen-protocol.acme/execution-resultscontaining the intent id, the execution tx hash, the confirmation depth, the attestation hash, and the result hash. That record is the multi‑validator attestation that the exact authorized effect occurred — query it to close the loop. - Accumulate merkle receipt — for the authorizing intent, fetch
GET /v1/proof/tx/<hash>/receiptfor the inclusion proof → anchor.
Errors are specific
Malformed intents return 400 naming the leg and field — e.g.
Leg 0: contractCall.functionSignature is required (e.g. "buy(bytes32)"), or
Leg 0: amount must be a non-negative number. You never get an opaque "it didn't work."
Certen is the enforcement primitive: authorize the exact operation, and it executes only against its proof. For value transfers, contract calls, governance, voting, bridges, and agents alike — the proof is the permission.