Inspiration
On September 29, 2021, Compound executed Proposal 62, an upgrade to its Comptroller. The code compiled, the tests passed, and governance approved it. A one-character bug (> instead of >=) then started paying users far more COMP than they'd earned. One transaction alone paid out 18,977 COMP.
Smart contract teams still ship upgrades this way: tests pass, the audit is done, deploy. And on July 1, 2026, OpenZeppelin Defender, the main hosted platform for deploying and monitoring contracts, shut down, so teams now stitch together their own release pipelines.
We asked one question: what if every upgrade had to survive your users' real transactions before it shipped?
What it does
Reenact is a hands-off release agent for upgradeable smart contracts, built on GitLab Duo Agent Platform.
When a merge request changes a contract, Reenact:
- Replays real history. It forks the chain, takes recent real transactions that touched the contract, and replays them twice: once on the current code, once on the upgrade.
- Compares outcomes exactly. Status, return data, events and every token balance change must match to the wei. The EVM is deterministic, so any difference comes from the code change itself.
- Decides with a deterministic, pre-registered gate:
- SHIP: no user is affected. Reenact auto-merges, deploys to Base Sepolia and creates a GitLab Release with the report.
- PAUSE: something changed that a human should confirm, such as a silent change to a return value that integrators depend on.
- BLOCK: a real user's transaction now behaves differently, or the storage layout broke.
- Fixes what it blocks. On BLOCK, Reenact opens an issue naming the failing transaction, the affected user, the expected and actual outcome, and the culprit line. It hands that issue to the GitLab Duo Developer flow, which writes a fix MR. Duo Code Review reviews the fix, Reenact re-evaluates it, and if it passes, it ships.
- Monitors the deployed contracts on a schedule and keeps a live dashboard.
The model never decides whether code ships. Deterministic code decides; Duo explains, reviews and fixes.
It covers all 9 DevSecOps stages:
| Stage | What Reenact does |
|---|---|
| Plan | Opens an issue for every BLOCK, with the failing transaction and culprit line |
| Create | Duo Developer flow writes the fix MR |
| Verify | Foundry tests, real-transaction replay, Duo Code Review |
| Package | Versioned build artifacts per release |
| Secure | Slither, plus a hardened pipeline: secret isolation and sanitized agent inputs |
| Release | GitLab Releases with a report for every ship |
| Configure | Environment-scoped deploy config and protected variables |
| Monitor | Scheduled checks on deployed contracts, plus a health alarm on the pipeline itself |
| Govern | A frozen, pre-registered gate, auto-merge restricted to same-project contract changes, and a decision log |
How we built it
- GitLab CI/CD runs the deterministic pipeline: Foundry build and tests, Slither, storage-layout diff, fork replay, gate and deploy.
- GitLab Duo Agent Platform, called through the Flows API: the Developer flow writes fix MRs from BLOCK issues, and Code Review reviews every fix and demo MR.
- A dispatcher on
mainevaluates open MRs on a schedule and on every push. The job that runs untrusted contract code never sees a secret, and only one job holds the API token. - Prompt-injection safety. Every comment, issue and flow goal is built only from validated fields (transaction hashes, addresses, integers, file paths and line numbers), never from raw user text.
- Path B: Bring Your Own. We imported Offmint, our own MIT-licensed vault protocol, into GitLab, deployed it to Base Sepolia, and let Reenact run its release lifecycle.
- GitLab Pages hosts the live dashboard: contracts, releases, verdicts and monitor status.
- TypeScript and viem for the replay engine, gate and dispatcher, with 275+ unit tests plus Offmint's 160 Foundry tests.
Challenges we ran into
- No permission to create custom flows. Hackathon accounts get the Developer role, but creating custom flows needs Maintainer. We rebuilt the agent layer on the Duo Flows API, triggering the built-in Developer and Code Review flows from CI with no human click.
- Replaying history is harder than it sounds. Our first backtest crashed because skipped transactions had funded later ones. We fixed it by giving senders their real historical balances identically on both forks, and logged the method change before seeing any result.
- Keeping the gate honest. Thresholds were frozen before the first real run: exact match, zero tolerance. When something failed, we fixed the harness, never the rules.
- Securing a public, AI-driven pipeline. Public job logs, agent-written branches and attacker-writable on-chain data meant we had to isolate secrets so the code under test can't reach them.
- One honest human step. On one fix MR, Duo Code Review requested a change. Reenact applied its suggestion, but the review status didn't clear on its own, so a human cleared it once. Reenact never overrides a reviewer.
Accomplishments that we're proud of
- It would have caught Compound Proposal 62. We forked Ethereum at block 13,322,797 and replayed the 50 transactions that touched the Comptroller after the upgrade, with and without it:
| Transaction | Without upgrade | With Proposal 62 |
|---|---|---|
0xc9244e53… |
0.0449 COMP | 18,977.35 COMP (matches mainnet to the wei) |
0xcde79593… |
0.175 COMP | 1,577.19 COMP |
The gate returned BLOCK. A control fork without the upgrade showed zero divergences, and the run took about 4.5 minutes.
- The full loop ran on its own: BLOCK → issue → Duo Developer fix MR → Duo Code Review → SHIP → auto-merge → deploy → GitLab Release. Real vault upgrades shipped to Base Sepolia this way.
- All 9 lifecycle stages covered, each with a real artifact in the repo.
- A gate that can't be gamed: an MR can't edit the rules that judge it, because evaluation always runs main's reviewed code.
What we learned
- Tests tell you the code does what you wrote. Replay tells you it still does what your users rely on.
- Agents are most trustworthy when they act on decisions made by deterministic code, not when they make those decisions themselves.
- Replay-based upgrade testing has academic roots: CATANA pioneered capture-replay for upgradeable contracts. Our contribution is turning it into an autonomous release lifecycle inside GitLab.
What's next for Reenact
- One-line adoption for any GitLab project through a reusable CI template
- More chains, and mainnet releases behind multisig approval
- Replay across cross-contract call paths and bigger transaction windows
Built With
- anvil
- base-sepolia
- ethereum
- foundry
- gitlab
- gitlab-ci
- gitlab-duo
- gitlab-pages
- node.js
- pnpm
- slither
- solidity
- typescript
- viem
- vitest
Log in or sign up for Devpost to join the conversation.