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
getSecretsreleases six of the seven mandate fields from the Vault DON into the enclave; the enclave recomputeskeccak256(abi.encode(Mandate))and stops if it differs from the configured hash.- Two
eth_callbatches from inside the enclave: the account from the vault, the pool's price, fee and liquidity fromStateView, the position from thePositionManager. - Decide: hold on expiry, cooldown, or in range; otherwise a range of exactly
rangeWidthTickscentred on the tick, only if a mirror of the vault's_checkRangeaccepts it. - Size: what the burn returns, the swap that funds the other side, bounded inside the new
range, and the liquidity that funds. Below
minRetainedBpsis a hold. - Cross out with the verdict only.
delivery: 'forwarder'writesabi.encode(bool act, bytes32 mandateHash, RecenterParams p)to the vault'sonReport;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, production | 0xF8344CFd5c43616a4366C34E3EEE75af79a74482 |
MockKeystoneForwarder, what simulate --broadcast uses; verifies nothing | 0xd770499057619c9a76205fd4168161cf94abc532 |
v4 PoolManager / StateView / PositionManager | 0x360E68faCcca8cA495c1B759Fd9EEe466db9FB32 / 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 registration | index.ts#L268-L276 |
| the confidential handler | index.ts#L173-L234 |
| the decision | index.ts#L111-L170 |
| reads from inside the enclave | chain.ts#L20-L44 |
| the verdict delivered to the vault | index.ts#L244-L265 |
| the vault receiving it | HelicoVault.sol#L469-L482 |
Check it: bun run --filter @helico/plugin-cre typecheck and ... test.