CERTEN docs
← All docs

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):

  1. 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 the executionCommitment stored 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).

  2. 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.

  3. 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).

  4. 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_call of 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

  1. 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).
  2. Prove — 7 BFT validators independently reconstruct and verify the intent, then BLS‑sign it. Two on‑chain transactions record the proof: createAnchor (stores the executionCommitment) and executeComprehensiveProof (verifies the aggregate BLS proof).
  3. Execute — a third transaction calls executeGovernanceProofDirect on your abstract account, which runs the two modifiers above and, only if they pass, performs target.call{value}(calldata).
  4. 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.


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:

  1. On‑chain execution — the three transactions (createAnchor, executeComprehensiveProof, executeGovernanceProofDirect) are on the target chain with status: 1; the committed expectedEvents are in the execution tx's receipt logs.
  2. Attested proof‑result on Accumulate — on quorum, the validators write a signed certen:proof_result:v2 record to acc://certen-protocol.acme/execution-results containing 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.
  3. Accumulate merkle receipt — for the authorizing intent, fetch GET /v1/proof/tx/<hash>/receipt for 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.