A starter repo for interacting with the BattleChain Safe Harbor protocol. It walks the full flow: deploy a deliberately vulnerable vault, register a Safe Harbor agreement, open it for attack, and execute a whitehat rescue that splits the proceeds per the agreement terms.
Every step is a single transaction, so it works equally well from a keystore (below) or signed in your own browser wallet (see Sign with your own wallet).
| Network | Chain ID | RPC |
|---|---|---|
| BattleChain | 626 | https://mainnet.battlechain.com |
| BattleChain Testnet | 627 | https://testnet.battlechain.com |
The Safe Harbor core contracts (registry, agreement factory, attack registry), CreateX,
and the Safe contract suite are deployed on both networks, and both have a block explorer
with contract verification: mainnet and
testnet. The flows here target BattleChain
Testnet, since the mock dependencies (such as the permissionless MockRegistryModerator
used to approve attack mode) are testnet-only.
- git —
git --version - foundry —
forge --version- The browser-wallet targets (
just *-browser) need Foundry nightly:foundryup -i nightly
- The browser-wallet targets (
- just —
just --version
git clone <MY_REPO>
cd <MY_REPO>
forge install
just buildThe steps chain by passing addresses through .env. After each deploy step, copy the
logged address into .env before running the next one.
Create a fresh keystore account named battlechain and put its address in .env:
just generate-key # imports a random key as the `battlechain` keystore accountAdd to .env (use the address generate-key prints; for this demo the protocol's
recovery address is just your own wallet):
SENDER_ADDRESS=0xYourAddress
RECOVERY_ADDRESS=0xYourAddress
Fund the address with a little BattleChain Testnet ETH for gas (bridge Sepolia ETH at https://portal.battlechain.com/bridge).
# Deploy the vulnerable protocol. The vault deploys + seeds its own MockToken.
# Copy the logged VAULT_ADDRESS and TOKEN_ADDRESS into .env.
just deploy-protocol
# Register a Safe Harbor agreement scoping the vault. Copy AGREEMENT_ADDRESS into .env.
just create-agreement
# Lock the agreement's commitment window — REQUIRED before attack mode can be
# requested (the AttackRegistry reverts with InsufficientCommitment otherwise).
just set-commitment-window
# Adopt the agreement in the registry.
just adopt-agreement
# Request attack mode for the agreement.
just request-attack-mode# Deploy the Exploit: it approves attack mode (via the permissionless testnet
# moderator), drains the vault via reentrancy, and splits the proceeds
# (90% returned to the recovery address, 10% kept as the bounty).
just attackjust verify-protocol # verify MockToken + VulnerableVault
just verify-exploit # verify the Exploit + AttackerEvery step above has a -browser variant that signs in your own wallet instead of a
keystore. These need Foundry nightly (foundryup -i nightly) and use cast under
the hood (forge script --browser hangs waiting on the wallet; cast send doesn't):
just deploy-protocol-browser
just create-agreement-browser
just adopt-agreement-browser
just request-attack-mode-browser
just attack-browserApprove each transaction in your wallet when it pops up, then copy the resulting address
into .env (the deployed addresses appear in the ContractCreation logs of the receipt).
just check-state # agreement state (2=ATTACK_REQUESTED, 3=UNDER_ATTACK)
just test # run the reentrancy tests
just set-commitment-window # optional: lock the agreement terms for a period