What Keel is, and how to use this site.
Everything on this site is explained here in plain language: the problem, the fix, what each page shows, and how to check the on-chain proof yourself.
Keel in one minute
On lending protocols like Aave, a loan is safe while its health factor (HF) stays above 1.0. If the collateral price falls far enough, the loan is liquidated and the borrower pays a penalty. So borrowers run defense bots: when HF drops to some trigger level, the bot adds collateral or repays debt.
The problem: everything the bot does is public. Watch when it acts and when it stays quiet, and you can work out its trigger, then push the price to that exact level to drain its reserve. Hiding the trigger in secure hardware does not help, because the bot's behavior still leaks the number.
Keel is a defense bot whose trigger cannot be worked out from watching it, and which still proves afterward that it followed one fixed, pre-committed policy the whole time. It runs as a Chainlink CRE confidential workflow, built for the ETHOnline 2026 Chainlink challenge.
The problem it solves
In the official challenge, health factor is a straight line in price: HF = price / 1794.87. The position opens at $2,000 (HF 1.114) and is liquidated near $1,795 (HF 1.00). The whole game happens inside that $205 window.
A bot with a fixed trigger gives one bit of information at every price level: it acted, or it did not. Each observation narrows the range where the trigger can be. Three or four well-chosen price pushes locate a fixed trigger to within a few dollars. After that, an attacker can tap the price to just below the trigger, force a spend, let the price recover, and repeat until the defender has nothing left for the real crash.
The bot's reserve is a public token balance, so the attacker always knows how much is left to drain. The only thing that can stay secret is when the bot will act, and only if it is built so that acting does not give the secret away.
How Keel works
1. The trigger moves, upward only
Keel's trigger is not one number. Each time the price changes, the trigger is re-drawn: a secret base level, plus a volatility term, plus a random offset derived from a secret salt. The offset only ever raises the trigger, so randomness can make Keel act earlier but never later. It never costs survival. And because every price level gets a fresh independent draw, no amount of watching narrows the base below the offset's width. The algorithm is public; the secrecy lives entirely in the salt.
2. The policy is sealed before the market moves
Before the scenario starts, Keel posts a hash of its entire policy (all parameters plus the salt) to a PolicyCommit contract on Sepolia. Think of it as a sealed envelope handed to the referee before the match. The policy cannot be swapped later without breaking the hash.
3. Every action carries a receipt, and the seal opens after
Each defense transaction is followed by an EIP-712 receipt, signed by a key derived from the same salt inside the enclave. After the challenge, Keel reveals the policy and salt. Anyone can then recompute every round's trigger from public price logs and check that every action, and every non-action, matched the sealed policy. That is the difference between private and provably unchanged.
Where it runs
The decision code runs inside a Chainlink CRE confidential workflow (handlerInTee, AWS Nitro enclave). Policy parameters, the salt, the wallet key and the RPC credential are Vault DON secrets, released only to the enclave. The handler reads the chain, decides, defends if needed, and reports a single word: IDLE, SAFE or DEFENDED. No number ever leaves the enclave.
Using this site
The three demo pages are a tour. Take them in order:
- 1.Pick a scenario and press PLAY. Each chart shows one bot's health factor falling as the price drops; markers are its defense actions.
- 2.The colored strip under each chart is the attacker's live estimate of that bot's trigger. The starter's strip collapses to a point; Keel's stays wide.
- 3.The scorecards use the official challenge scoring: surviving matters most, spending less capital and acting less often matter too.
- 4.Switch the source to CHAIN to see Keel's real recorded Sepolia run, every action linked to Etherscan.
- 1.The headline number is the “next-trigger band”: how precisely the attacker can predict each bot's next move. Smaller is worse for the defender.
- 2.The starter's band collapses to a point: its fixed trigger is found and stays found. Keel's band is floored by its per-level random jitter, no matter how long the Hunter watches.
- 3.Press ATTACK to watch the Hunter tap the price at the starter's discovered trigger, forcing spend after spend until the reserve is gone.
- 4.The ×1000 toggle scales the dollar figures to a realistically sized position, where this attack is worth real money.
- 1.The verdict at the top is the whole story: ALL ROUNDS CONSISTENT means the sealed policy provably produced every action.
- 2.Section 1 is the commitment: the policy hash was posted on-chain before any action, so it could not be swapped after seeing the market.
- 3.Section 2 lists the signed receipts. Each signature recovers to the exact signer address committed up front.
- 4.Section 3 is the reveal audit: each round's trigger is recomputed from public price logs and checked against what the bot actually did. Every row links to Etherscan.
- 1.Arrow keys, scroll or the side dots step through the slides.
Glossary
Verify it yourself
You do not have to trust this site. Three checks, all from public data:
- 1.The commitment came first. On PolicyCommit, the commit block number precedes the scenario start block. The policy was sealed before the market moved.
- 2.Receipts are signed by the committed key. Each receipt on Receipts recovers to the signer address stored with the commitment, and its action transaction sits at the previous nonce of the same wallet.
- 3.The reveal matches. After reveal, hash the revealed policy and salt: it must equal the on-chain commitment. Then recompute each round's trigger from public PriceUpdate logs and check every action against it. The Verify page runs all three checks live, but nothing stops you from doing them by hand.
Run it locally
The repo is public: github.com/sairammr/keel. No policy parameter or salt is committed anywhere in it.
git clone https://github.com/sairammr/keel && cd keel && bun install bun run test # 44 unit tests: controller + scenario + hunter bun run e2e # full lifecycle on a local Anvil chain, ends E2E PASSED bun run tune # grid search over policies vs starter baselines bun run replay --vs starter # text side-by-side replay (cd app && bun run dev) # this site on :3000 # CRE confidential workflow (simulation needs no deploy approval) cre workflow simulate workflow --target staging-settings \ --non-interactive --trigger-index 0
the handler only ever logs one word: COMMITTED / IDLE / SAFE / DEFENDED