Your transaction runs twice. The first time is a rehearsal.
Forklift pins a Portaldot block, lifts the chain's real state at that block, forks it on your machine and checks the fork against the live chain key by key. Then forklift rehearse signs a transaction once, applies those exact bytes on the fork as the prediction, and with --send sends the same bytes to the V3 testnet and lists every field that differs.
What is measured on the V3 testnet
-
Lift at #118,061: 5,508 keys.
verify --sample 200exits 0: 200/200 draws identical, key set 5,508 = 5,508. -
Rehearse: three real V3 transactions, each predicted on a fork first, then sent:
118555-1System.remark,118621-1Balances.transfer_keep_alive,118669-1Utility.batch. Each had the same tx hash, success and event sequence as predicted, and the same recipient delta where there is one. - What differed: the fee-bearing event amounts, the fee (3,660 to 8,269 planck), the signer delta and the inclusion height. Forklift lists every one and exits 7, never a quiet fix.
- Replay re-runs a V3 extrinsic on a fork of its parent block: 118555-1 10/10, 118621-1 14/14, 118669-1 16/16 fields equal.
-
Fork Receipt v2, a Revive contract on V3 at
0x52f0edd92af9ff410ca63ccc83735552e1b2abc7(84 bytes): the emitted event and the storedreceipt()equal the #118,061 manifest.
Mainnet, too
Three mainnet extrinsics replayed field-equal on a fork of their parent block (24/24, 25/25, 24/24). runtime-diff and migrate-report compare mainnet spec 1002 with V3: of a 16,324-key lift, 10,499 keys carry over, 5,443 re-encode and 382 have no home on V3.
Things I learned
- A fee difference is not a bug, but it must be said. Each transaction landed a few blocks after its prediction, so the fee moved. Listing it, with an exit code, is more useful than hiding it.
-
Sampling is honest only if you say it is a sample.
verifychecks 200 random keys, not every key, and Forklift says so.
Honest limits
A V3 fork is Chopsticks, not a V3 node (no public V3 node binary exists). Forklift reads mainnet and V3; the only writes to a real chain are rehearse --send and receipt --target v3, and only to V3. The PyPI package is not published yet.
Links
- Code: https://github.com/edycutjong/portaldot-hackathon-2026-forklift-edycu
- Demo video: https://youtu.be/iVvEXQvfTYY
- Site: https://forklift.edycu.dev
- Proof:
docs/PROOF.md
324 offline tests and 10 live tests. Built for the Portaldot Hacker House 2026.

Top comments (0)