Chainlink CRE

The confidential workflow that makes the only decision the product has.

The decision runs inside a Chainlink CRE enclave, registered with cre.handlerInTee. The logic is a package, @helico/plugin-cre, so 116 unit tests cover it without the CLI; apps/cre is what the CLI compiles.

Every run

  1. getSecrets releases six of the seven mandate fields from the Vault DON into the enclave; the enclave recomputes keccak256(abi.encode(Mandate)) and stops if it differs from the configured hash.
  2. Two eth_call batches from inside the enclave: the account from the vault, the pool's price, fee and liquidity from StateView, the position from the PositionManager.
  3. Decide: hold on expiry, cooldown, or in range; otherwise a range of exactly rangeWidthTicks centred on the tick, only if a mirror of the vault's _checkRange accepts it.
  4. Size: what the burn returns, the swap that funds the other side, bounded inside the new range, and the liquidity that funds. Below minRetainedBps is a hold.
  5. Cross out with the verdict only. delivery: 'forwarder' writes abi.encode(bool act, bytes32 mandateHash, RecenterParams p) to the vault's onReport; delivery: 'signature' signs an EIP-712 authorisation with a key that never leaves.

The binary is public. What stays inside is the data, the RPC traffic, and the intermediate values. The mandate hash proves consistency, not secrecy.

Config

schedule, rpcUrl, delivery, vault, positionManager, stateView, owner, poolId, mandateHash, gasLimit, slippageBps, maxPoolFeePips, deadlineSeconds; for signature also chainId; for forwarder also chainSelectorName (ethereum-mainnet-arbitrum-1). secrets.yaml maps the six mandate fields, and in signature mode AGENT_KEY, to env vars.

On Arbitrum One

KeystoneForwarder, production0xF8344CFd5c43616a4366C34E3EEE75af79a74482
MockKeystoneForwarder, what simulate --broadcast uses; verifies nothing0xd770499057619c9a76205fd4168161cf94abc532
v4 PoolManager / StateView / PositionManager0x360E68faCcca8cA495c1B759Fd9EEe466db9FB32 / 0x76Fd297e2D437cd7f76d50F01AfE6160f86e9990 / 0xd88F38F930b7952f2DB2432Cb002E7abbF3dD869
Demo pool, ETH/ARB 0.05%0xb37da7d5beb04539b6c497a15794748fc0ce1da7afc61133e3253eff76229ae5

What the simulation proves

In the simulator the enclave is the simulator and the forwarder is the mock. A run proves the delivery path and the vault's execution, not DON authorisation. Chainlink's qualification text accepts a CRE CLI simulation as evidence; a live deployment additionally needs the Confidential Workflows beta.

A transaction hash is not evidence

KeystoneForwarder calls the receiver inside a try. A reverting onReport still leaves a transaction with status 1. rehearse.sh reads positionOf before and after and only counts a position that changed. That is how #78 was found.

Where to look

handlerInTee registrationindex.ts#L268-L276
the confidential handlerindex.ts#L173-L234
the decisionindex.ts#L111-L170
reads from inside the enclavechain.ts#L20-L44
the verdict delivered to the vaultindex.ts#L244-L265
the vault receiving itHelicoVault.sol#L469-L482

Check it: bun run --filter @helico/plugin-cre typecheck and ... test.

On this page