fix(testnet): scale per-offense slash penalties so slashing can trigger#24136
fix(testnet): scale per-offense slash penalties so slashing can trigger#24136aminsammara wants to merge 1 commit into
Conversation
testnet.env overrode the onchain slash amounts (SMALL=100000e18, MEDIUM/LARGE=250000e18) but left the per-offense penalties at the generated defaults (10e18). The slasher sums an offender's penalties for an epoch and maps the total to 1/2/3 slash units against [SMALL, MEDIUM, LARGE]; a total below SMALL maps to 0 units and is never voted on. At 10e18 every offense was ~10,000x below SMALL, so it always rounded down to 0 units and no validator could ever be slashed on testnet. Override the active offense penalties onto the same scale as the onchain amounts: liveness/catch-all faults map to SMALL (1 unit), provable validity and data-availability faults map to LARGE (3 units). The intentionally-disabled offenses (duplicate proposal/attestation, invalid checkpoint proposal) are left at 0.
|
Closing — this PR was based on an incomplete analysis and is not correct. The premise was wrong. I claimed the per-offense penalties default to The
This PR would have actively broken AZIP-16 compliance. All No change to |
Problem
The testnet config shipped with
v5.0.0-rc.1cannot ever slash a validator.spartan/environments/testnet.envraises the onchain slash amounts to be meaningful relative to the 200,000e18 activation threshold:…but it does not override the per-offense penalties, so they keep the generated defaults from
network-defaults.yml(~10e18).How slashing decides what to vote (
yarn-project/stdlib/src/slashing/votes.ts):getSlashUnitsForAmountmaps that total to 0/1/2/3 units by comparing against the onchain[SMALL, MEDIUM, LARGE]amounts (read from theSlashingProposercontract).SMALL→ 0 units → no vote is cast → quorum is never reached →executeRoundproduces noSlashAction.With penalties at
10e18andSMALLat100000e18, every offense is ~10,000× too small to reach even 1 unit. A slashing round spans only 2 epochs, so realistic accumulation (~1–2 offenses) never gets close. Result: the sentinel correctly detects offenses, but no validator is ever slashed. The collector even logsOffense amount … is below minimum slashing amount …on every offense (slash_offenses_collector.ts:100).Fix
Override the active per-offense penalties in
testnet.envonto the same scale as the onchain amounts:The intentionally-disabled offenses (duplicate proposal/attestation, invalid checkpoint proposal —
0in the defaults) are left untouched.This is the only fix deployable to the live testnet without redeploying L1 contracts:
AZTEC_SLASH_AMOUNT_*areSlashingProposerimmutables fixed at genesis, whereasSLASH_*_PENALTYis node-side config read at runtime and reaches pods viadeploy_network.sh→ helm → pod env.Notes / follow-ups (not in this PR)
AZTEC_LOCAL_EJECTION_THRESHOLD=199000e18, any slash on a 200k stake fully ejects the validator (StakingLib.slash):200k − 100k = 100k < 199k. SMALL burns 100k and returns 100k via exit; LARGE (capped at the 200k balance) burns the whole stake. There is no "small penalty, keep validating" path on testnet — that's a separate tuning decision.SLASH_INACTIVITY_CONSECUTIVE_EPOCH_THRESHOLDdefaults to1, so a single inactive epoch now ejects. If that's too aggressive for testnet, raise the threshold.