Releases: Dealers-sh/dealers-contracts
Release list
v1.3.0 — Bank Heist Vault V2
v1.3.0 — Bank Heist Vault V2
Bank Heist has been rebuilt around an ETH performance bond and a competitive, scalable leaderboard. V2 is deployed paused on Abstract mainnet while the legacy season finishes; this release publishes the exact source tree used for that deployment.
🏦 Bank Heist Vault V2
- ETH performance bond — entering costs the exact configured ETH fee. The launch configuration uses 0.0005 ETH.
- Minimum qualified payout — every qualified dealer can claim at least the full entry fee. Cancelled, below-minimum, zero-qualifier, and abandoned seasons refund entries.
- Competitive cumulative rewards — qualified dealers share a score-weighted base pool, while stronger ranks also stack contender, elite, and podium rewards.
- Launch allocation — podium 8% / 4.5% / 2.5%, top 5% elite pool 20%, top 20% contender pool 25%, and all-qualified base pool 40%.
- Small-season protection — a percentile pool requires at least four recipients. If it does not activate, its allocation rolls into the all-qualified base pool.
- Deterministic final rankings — higher frozen score wins; ties use reputation snapshotted during finalization, then lower dealer token ID.
- Scalable settlement — score freezing and heap-based ranking are permissionless and paginated for up to 10,000 entrants.
- Explicit solvency accounting — live entries, refunds, and settled claims remain reserved. Gross and available vault balances are exposed separately.
- Activity starts at entry — only qualifying activity performed after a dealer enters the season contributes.
📦 Multicall v1.3
DealersMulticall now exposes the V2 season, entry, score, rank, qualification, reward, reserve, and vault data needed by the app and indexer.
🌐 Abstract mainnet
- Bank Heist V2: 0x987779Fd28E24D9cBeB7c22Eb1AFE1B7771ED5e1
- Multicall v1.3: 0x01C186418FE87F53E1A95dE49CCf13D501868669
- PaymentHandler.bankVault remains unchanged by design.
- V2 remains paused until the legacy season is settled, its claim reserves are preserved, only genuinely available ETH is migrated, and the app/API bundle is switched.
✅ Validation
- Full Foundry suite: 665 passing, 0 failing
- Native zkSync build: passed
- Bank Heist V2 mainnet source: verified
- Mainnet V2 deployment: paused and authorized on Core
- Multicall V2 references: verified on-chain
Deployment note
The merged GitHub CI run stopped at repository-wide forge fmt --check before build/tests because the installed formatter expects broad formatting changes, including files predating this release. The tag intentionally preserves the exact deployed and locally validated source tree instead of creating a post-deployment formatter-only source mismatch.
Full changelog: v1.2.0...v1.3.0
v1.2.0 — Daily & Weekly Missions
v1.2.0 — Daily & Weekly Missions
Second post-GA content release. DealersMissions is live on Abstract mainnet — a daily/weekly objective board scored entirely by observing the counters the game modules already keep, so no existing contract changed.
🎯 Missions (DealersMissions)
- Snapshot-delta scoring (the BankHeist observation pattern):
checkInsnapshots a full-metric baseline for the current daily and weekly epoch, the dealer plays normally, thenclaimre-reads the live counters and pays the difference. PVE / PVP / Heists / Core are read-only — no game module was modified or called back. - 12 metrics — PVE games/wins, PVP attack/defend wins and games, heist runs/stages/cash-outs, reputation and infamy gain,
ANY_GAMES(the three attempt-spending actions summed, so heist- and PVP-leaning players aren't taxed), andMISSIONS_CLAIMEDfor capstones. - Rewards through Core — any mix of reputation, infamy, $CASH and loot drugs, paid over the existing authorization path.
- Epochs advance themselves — daily = 00:00 UTC, weekly = unix-anchored (rolls Thursday 00:00 UTC). No admin tx ever advances a board, and the active set derives deterministically per epoch from the template pool (partial Fisher-Yates over the enabled templates), so every player grinds the same missions.
- The boundary is a hard deadline — a met-but-unclaimed mission dies at the roll. Progress is measured against live counters, so honouring a stale epoch would let one play score twice.
- Guardrails — daily action targets capped to the 5 free attempts (
maxDailyTarget); one capstone per cadence with its target strictly below that board's size, enforced on add and on resize; pool bounded at 64 templates; mid-epoch template edits are safe because baselines snapshot every metric and claims are keyed by template id, so a shifted board can never double-pay. - One-call board —
getMissionStatus(tokenId)returns every active daily + weekly with live progress, check-in state and claimability.MissionClaimed/MissionsClearedcarry the full payout for indexers. - Mainnet:
0xaf461430D2e2cCd89CFE3Ee335F77a8BF3031F5b· Testnet:0xDb6e3f433E9eA73FB60C2B9C3b1A24A7Fe66F8Bb
🗂 Launch board (pinned — SetupMissions)
Enabled templates exactly equal the active counts, so the board is pinned rather than rotating; only progress resets on the epoch boundary.
- Daily (1) —
ANY_GAMES3 → 10 rep + 1 Goods. Deliberately slack at 3 of the 5 free attempts, leaving room for a wanted poster or a jail stint. - Weekly (5) — PVE games 25, PVE wins 5, heist stages 5, PVP attack wins 3, plus the capstone that pays 1 Jewel once the other four are claimed. Sized as the wall: ~35 attempts against the ~35 a free week provides.
🛠 Ops
DeployMissions— deploys, authorizes on Core, ships paused with an empty pool; mainnet gated behindCONFIRM=DealersMissions.SetupMissions— idempotent template seeder (skips when the pool is non-empty); retune live withsetTemplate, no redeploy needed.Wiring.s.solgains_syncMissionsRefs, so every neighbouring redeploy re-points Missions, andSetupWiringcovers it in the full-graph drift check.verify-source.shgains amissionstarget.- New
/dealer-compareskill — rank wallets side by side on lifetime spend, activity and XP-eligible events.
✅ Testing
74 mission tests (68 unit + 6 integration flows). Full suite: 640 passing, 0 failing — forge test --zksync --skip "RendererSVG" --skip "UploadTraits".
Deploying
Build and deploy from this tag so on-chain bytecode maps to source. Game contracts: forge build --zksync --skip "RendererSVG" --skip "UploadTraits". See script/DEPLOY.md.
Full changelog: v1.1.0...v1.2.0
v1.1.0 — Bank Heist + Season 1 economy patch
v1.1.0 — Bank Heist, Multicall season views, and the Season-1 economy patch
First post-GA content release. Bank Heist and the upgraded Multicall are live on Abstract mainnet, and the Season-1 economy patch (new areas, drugs, fees) is applied on-chain.
🏦 Bank Heist is live (DealersBankHeist)
- Recurring community bank-heist seasons — a shared vault-funded pot split pro-rata by each entrant's frozen score across the three scored games.
- Genesis season opens with
zeroBaseline = true, so lifetime play since launch counts retroactively. - Full lifecycle on-chain:
openSeason→ daily focus check-ins →freezeScores→settle→ pro-rataclaim, with owner escape hatches (cancelSeason, entry reclaim for below-min / cancelled seasons) and a keeper tip on settle. - Ops tooling:
SetupBankHeistSeason(fund vault, unpause, open) andEndBankHeistSeason(freeze → settle), plus the/end-seasonskill. - Matured out of "concept / out-of-scope" (v1.0.0-rc.1) — the
OUT OF AUDIT SCOPEmarker is removed; this ships as post-audit content. - Mainnet:
0xE219B3E8909Ebc26404080618339b947075FAF2B
🔭 Multicall upgrade (DealersMulticall)
- New read-only aggregators for the bank-heist UI:
getHeistStandings(seasonId, start, count)(paginated, client-sorted leaderboard) andgetHeistDealerStatus(seasonId, tokenId)(season-card view: live score, focus, estimated pot share). - Wires in
IDealersBankHeist+setBankHeist; covered bytest/heists/DealersMulticallHeist.t.sol. - Mainnet:
0xda7ebc1c2B95Dd8A52AcfB9e576021A6727B4cd4
🧪 Season-1 economy patch (script/patch-1-1-0)
Sim-validated in economy_sim.py. Full runbook: script/patch-1-1-0/RUNBOOK.md.
- New areas — Warsaw (id 8, gate 2,200, EE mid-game) and Moscow (id 9, gate 7,000, endgame). Ladder: Seoul 1,500 → Warsaw 2,200 → Tokyo 3,000 → Dubai 5,500 → Moscow 7,000.
- New drugs — Slivo (12), Krokodil (13, Moscow-exclusive buy-to-flex), Speed (14).
- Season shuffle + move fees — 0.0006 default / 0.001 Tokyo+Dubai, maintained across all 9 areas.
- Fees trimmed — bribe and bail 0.001 → 0.0006 ETH.
- Late-game tier caps trimmed — Consigliere/Underboss/Don/Godfather to 56/62/70/78.
🛠 Deploy infrastructure
DeployAllretired for self-wiring per-contract deploy scripts (script/base/Wiring.s.sol) — each redeploy re-asserts exactly the edges touching it, idempotently.SetupWiringre-asserts the full graph as a drift check.script/DEPLOY.mdrewritten as a per-contract runbook; mainnet redeploys gated behindCONFIRM=<ContractName>.- Operator skills added:
/dealer-research,/jackpot-status,/referral-rewards,/end-season.
Deploying
Build and deploy from this tag so on-chain bytecode maps to source. Game contracts:
forge build --zksync --skip "RendererSVG" --skip "UploadTraits". See script/DEPLOY.md + script/patch-1-1-0/RUNBOOK.md.
Full changelog: v1.0.0...v1.1.0
v1.0.0
First production release (GA), AI-audited with v12.sh + evmbench (Paradigm) against this commit (c5d90b6).
Since v1.0.0-rc.2
- Mint & reveal — single public mint with per-token, snipe-proof commit-reveal art assignment; the renderer is re-keyed to pool index so the pre-uploaded art can't be cherry-picked (#2).
Deploying
Build and deploy from this tag so the on-chain bytecode maps to the audited source. See script/DEPLOY.md.
Note: the existing mainnet
PaymentHandlerpredates the M-8 fix (strictonlyAuthorized, owner-bypass removed) — deploying from this tag is what ships the fixed version; ensure the redeploy replaces it rather than reusing the old address.
v1.0.0-rc.2 — Audit candidate (scope trim)
v1.0.0-rc.2 — Audit candidate
Release candidate for the security audit. Pre-release / not for production deployment.
🔍 Audit-scope trim (nSLOC reduction)
- Frontend preview views moved out of the audited modules into
DealersMulticall(out of primary scope):canPlay,previewHustle(PVE);calculateWinChance,canAttack,getPotentialTargets(PVP);getActiveTiers,checkBoostStatus,calculateBatchCost(Boosts). They mirror module logic for display only — the modules re-validate everything at commit time, and no state-changing path consults them. AUDIT.mdscope rewritten around ETH custody + session-key reachability: primary scope is nowDealersCore,DealersPVE,DealersPVP,DealersBoosts,DealersActions,DealersHeists,DealersPaymentHandler,DealersRandomness.
🏆 Heist stats + achievements (tag updated 2026-06-11)
DealersHeistsnow tracks lifetime per-dealer counters (HeistStats: runs, stages cleared, cash-outs, setbacks, busts, jackpots won — packed in one slot). Cash-outs count every full-pot finalize; setbacks (partial-pot endings) are counted separately.DealersClaimsgains six heist-based achievement conditions (HEIST_RUNS…HEIST_JACKPOTS_WON). Heist stats are read lazily so non-heist claims pay no extra calls; heist conditions fail closed insetAchievementuntil the heists contract is wired.VerifyConfigextended to check the full deployment wiring (heists/claims/randomness/payment-handler cross-references, auth, setup state); deploy + setup scripts updated accordingly.- Testnet deployment addresses refreshed (
script/data/deployments/testnet.json).
🔧 Other changes since rc.1
- Heists config update (sim-tuned values in
SetupHeists.s.sol). DealersMulticallgainssetBoostswiring (deploy scripts +VerifyConfigupdated).- CI fixes.
✅ Verification
- 504 zkSync tests + 60 EVM renderer tests passing at this tag.
Build/test: forge test --zksync --skip "RendererSVG" --skip "UploadTraits" (game) · forge test --match-contract "DealerRendererSVG" (EVM renderer).
v1.0.0-rc.1 — Heists + audit-prep
v1.0.0-rc.1 — Heists module + audit-prep release candidate
First release candidate for the 1.0 mainnet launch. Pre-release / not for production deployment.
✨ New: Daily Heists (DealersHeists)
- Solo five-stage push-your-luck runs paying out drugs (Supply) or
$CASH, costing one daily attempt + a$CASHstake. - Optional 0.001 ETH jackpot add-on — winning stages roll for an ETH jackpot, valued by Pyth Entropy.
- One jackpot per run (first trigger locks it; a reserve-skip stays eligible). Solvent by construction — a jackpot only fires if the reserve covers the max payout.
- Commit-reveal randomness; jailed dealers pause/resume; 24h idle force-finalize.
🧪 Concept (not deployed, out of audit scope)
DealersBankHeist— recurring community bank-heist event. Marked in-source@custom:status OUT OF AUDIT SCOPE; mainnetbankHeiststaysaddress(0).
🔍 Audit readiness
AUDIT.md— in/out scope, build/test commands, trust model, and the prioritized AGW session-key attack surface (the 25 mainnet-delegated entrypoints + value limits).- CI workflow (fmt → zkSync build/test → EVM renderer), README with contract table + audit status,
forge fmtacross the codebase.
⚠️ Known follow-ups
- Dependencies are vendored (
lib/, gitignored, unpinned). The CI dependency step is a stopgap until deps are pinned (submodules or canonical tags) — see discussion inAUDIT.md.
Build/test: forge test --zksync --skip "RendererSVG" --skip "UploadTraits" (game) · forge test --match-contract "DealerRendererSVG" (EVM renderer).
v0.991 (pre-release)
Fixes findings from the v12 audit report.
Changes
- DealersBoosts.purchaseBoost / DealersActions.purchase{AttemptReset,Cash}: admin path now refunds full
msg.valueinstead of stranding ETH in the contract. - DealersActions._settle{Marketplace,Movement}Fee: revert
ContractNotSetwhenfee > 0andpaymentHandleris unset — previously fees were silently swallowed. - DealersAreaRegistry.createArea: cap at
BLACK_MARKET_AREA - 1so the 254thcreateAreacall can no longer overwrite the reserved Black Market slot.
Prior commit on this branch (Acknowledge post-commit simulation via comment, remove set drug active function = deadcode) is also part of the v12 response:
- Natspec honesty on PVE/PVP expiry asymmetry (arrest skip via expiry accepted by design)
- Natspec on DealersRandomness acknowledging post-commit simulation surface
- Removed dead
setDrugActivefunction (DrugRegistry footgun)
v0.99-audit — pre-release (audit candidate)
v0.99-audit — pre-release (audit candidate)
Internal audit pass complete. Codebase prepared for external T1 review.
Critical / High findings resolved
- C-1: PVE expiry treated as LOSS (closes simulate-then-skip refund loophole)
- C-2: ATTEMPTS reward now refills daily attempts (was a no-op with harmful side effects)
- H-1: invalid (mathematically equivalent to honest play)
- H-2: PVP expiry treated as attacker LOSS
- H-3: implicitly closed by C-1
- H-4: verified (Abstract blockhash non-zero, sequencer trust acknowledged)
- H-5: boost purchase pours over delta extras (no full attempt refill)
- H-6: nonReentrant on all 17 Core mutators
Medium / Low resolved
- M-2: config() returns struct, not positional tuple
- M-4: setBoostTier validates cashMultiplier
- M-7: PVP defender slot refunded on no-battle exits
- M-8: onlyAuthorized hardened (owner bypass removed; recovery via temporary-module pattern)
- L-3: drug ID 0 invariant asserted
- L-4: isActive flag on BoostData
- L-7: setBoostTier caps extraAttempts to prevent uint8 wrap
Cleanup
- I-2: magic numbers lifted to named constants
- I-3: achievementCount renamed nextAchievementId
- I-4: NatSpec normalized to /** */
Affected for redeployment (per audit pass)
Core, NFT, PVE, PVP, Boosts, Claims, Actions, Multicall, AreaRegistry, DrugRegistry, RendererSVG, RendererHTML.
Unaffected (no redeploy needed)
PaymentHandler, Randomness, ChatFactory.
444 / 444 tests pass (forge test --zksync --skip RendererSVG --skip UploadTraits).
v0.98
Changes since v0.92
v0.92 — Audit Candidate
Audit candidate. Hand this tag to the auditing firm.
Highlights
- Commit-reveal schema across PVE, PVP, jail breakout, and wanted poster
- Economy rebalance (fees, rep, jail mechanics)
- Cleanup pass — dead code removal, payment-settlement helpers in DealersActions, tier-upgrade dedup in DealersBoosts, PVP infamy jail cap tightened (25 → 20)
Build & test
- Game contracts:
forge build --zksync --skip "RendererSVG" - Renderer (EVM mode for SSTORE2/EXTCODECOPY):
forge build - zkSync test suite:
forge test --zksync --skip "RendererSVG"— 434 tests - Renderer test suite:
forge test --match-contract "DealerRendererSVG"— 60 tests
Key entry points
- State hub:
src/core/DealersCore.sol - Gameplay modules:
DealersPVE,DealersPVP,DealersActions,DealersBoosts,DealersClaims - Renderer:
src/nft/DealerRendererSVG.sol,DealerRendererHTML.sol