diff --git a/l1-contracts/test/Rollup.t.sol b/l1-contracts/test/Rollup.t.sol index 65baf5829688..a1307c44f569 100644 --- a/l1-contracts/test/Rollup.t.sol +++ b/l1-contracts/test/Rollup.t.sol @@ -39,6 +39,7 @@ import {RollupBuilder} from "./builder/RollupBuilder.sol"; import {Ownable} from "@oz/access/Ownable.sol"; import {AttestationLib, CommitteeAttestations} from "@aztec/core/libraries/rollup/AttestationLib.sol"; import {AttestationLibHelper} from "@test/helper_libraries/AttestationLibHelper.sol"; +import {Bps, BpsLib} from "@aztec/core/libraries/rollup/RewardLib.sol"; // solhint-disable comprehensive-interface /** @@ -419,7 +420,8 @@ contract RollupTest is RollupBase { ); proverFees *= 10; // the price conversion - uint256 expectedProverRewards = rollup.getBlockReward() / 2 * 2 + proverFees; + uint256 sequencerBlockReward = BpsLib.mul(rollup.getBlockReward(), rollup.getRewardConfig().sequencerBps); + uint256 expectedProverRewards = (rollup.getBlockReward() - sequencerBlockReward) * 2 + proverFees; assertEq(rollup.getCollectiveProverRewardsForEpoch(Epoch.wrap(0)), expectedProverRewards, "invalid prover rewards"); } @@ -524,9 +526,10 @@ contract RollupTest is RollupBase { assertEq(provingCosts, FeeAssetValue.unwrap(interim.provingCostPerManaInFeeAsset), "invalid proving costs"); } - uint256 expectedProverReward = - rollup.getBlockReward() / 2 + FeeAssetValue.unwrap(interim.provingCostPerManaInFeeAsset) * interim.manaUsed; - uint256 expectedSequencerReward = rollup.getBlockReward() / 2 + interim.feeAmount + uint256 sequencerBlockReward = BpsLib.mul(rollup.getBlockReward(), rollup.getRewardConfig().sequencerBps); + uint256 expectedProverReward = rollup.getBlockReward() - sequencerBlockReward + + FeeAssetValue.unwrap(interim.provingCostPerManaInFeeAsset) * interim.manaUsed; + uint256 expectedSequencerReward = sequencerBlockReward + interim.feeAmount - FeeAssetValue.unwrap(interim.provingCostPerManaInFeeAsset) * interim.manaUsed; assertEq(rollup.getSequencerRewards(header.coinbase), expectedSequencerReward, "invalid sequencer rewards"); diff --git a/l1-contracts/test/benchmark/happy.t.sol b/l1-contracts/test/benchmark/happy.t.sol index e845e5fc3c61..4bb3ef1b5467 100644 --- a/l1-contracts/test/benchmark/happy.t.sol +++ b/l1-contracts/test/benchmark/happy.t.sol @@ -412,7 +412,7 @@ contract BenchmarkRollupTest is FeeModelTestPoints, DecoderBase { * @param _size - The number of validators * @return Encoded vote data */ - function createTallyVoteData(uint256 _size) internal returns (bytes memory) { + function createTallyVoteData(uint256 _size) internal view returns (bytes memory) { require(_size % 4 == 0, "Vote data must have multiple of 4 validators"); bytes32 seed = keccak256(abi.encode(_size, block.timestamp)); diff --git a/l1-contracts/test/builder/RollupBuilder.sol b/l1-contracts/test/builder/RollupBuilder.sol index 33eb07069913..ad239140fc23 100644 --- a/l1-contracts/test/builder/RollupBuilder.sol +++ b/l1-contracts/test/builder/RollupBuilder.sol @@ -22,6 +22,8 @@ import {CoinIssuer} from "@aztec/governance/CoinIssuer.sol"; import {stdStorage, StdStorage} from "forge-std/Test.sol"; import {GSEWithSkip} from "@test/GSEWithSkip.sol"; import {TestGov} from "@test/governance/helpers/TestGov.sol"; +import {Bps} from "@aztec/core/libraries/rollup/RewardLib.sol"; +import {SafeCast} from "@oz/utils/math/SafeCast.sol"; // Stack the layers to avoid the stack too deep 🧌 struct ConfigFlags { @@ -62,6 +64,7 @@ struct Config { */ contract RollupBuilder is Test { using stdStorage for StdStorage; + using SafeCast for uint256; Config public config; @@ -160,6 +163,12 @@ contract RollupBuilder is Test { return this; } + function setSequencerBps(uint256 _sequencerBps) public returns (RollupBuilder) { + require(_sequencerBps <= 10_000, "Sequencer BPS must be less than or equal to 10000"); + config.rollupConfigInput.rewardConfig.sequencerBps = Bps.wrap(_sequencerBps.toUint32()); + return this; + } + function setManaTarget(uint256 _manaTarget) public returns (RollupBuilder) { config.rollupConfigInput.manaTarget = _manaTarget; return this; diff --git a/l1-contracts/test/fees/FeeRollup.t.sol b/l1-contracts/test/fees/FeeRollup.t.sol index 7a79ff19cfc7..1c4ce89aa2ab 100644 --- a/l1-contracts/test/fees/FeeRollup.t.sol +++ b/l1-contracts/test/fees/FeeRollup.t.sol @@ -51,7 +51,6 @@ import {FeeModelTestPoints, TestPoint, FeeHeaderModel, ManaBaseFeeComponentsMode import {Timestamp, Slot, Epoch} from "@aztec/core/libraries/TimeLib.sol"; import {ProposedHeader} from "@aztec/core/libraries/rollup/ProposedHeaderLib.sol"; - import {MinimalFeeModel} from "./MinimalFeeModel.sol"; import {RollupBuilder} from "../builder/RollupBuilder.sol"; import {AttestationLibHelper} from "@test/helper_libraries/AttestationLibHelper.sol"; @@ -103,7 +102,8 @@ contract FeeRollupTest is FeeModelTestPoints, DecoderBase { RollupBuilder builder = new RollupBuilder(address(this)).setProvingCostPerMana(provingCost).setManaTarget( MANA_TARGET - ).setSlotDuration(SLOT_DURATION).setEpochDuration(EPOCH_DURATION).setMintFeeAmount(1e30).setTargetCommitteeSize(0); + ).setSlotDuration(SLOT_DURATION).setEpochDuration(EPOCH_DURATION).setMintFeeAmount(1e30).setTargetCommitteeSize(0) + .setSequencerBps(5000); builder.deploy(); rollup = builder.getConfig().rollup; diff --git a/l1-contracts/test/governance/governance/scenarios/noVoteAndExit.t.sol b/l1-contracts/test/governance/governance/scenarios/noVoteAndExit.t.sol index 005368af29b1..c6d51a387904 100644 --- a/l1-contracts/test/governance/governance/scenarios/noVoteAndExit.t.sol +++ b/l1-contracts/test/governance/governance/scenarios/noVoteAndExit.t.sol @@ -14,7 +14,7 @@ contract NoVoteAndExitTest is GovernanceBase { function test_CannotVoteAndExit(address _voter, uint256 _totalPower, uint256 _votesCast, uint256 _yeas) external { bytes32 _proposalName = "empty"; - vm.assume(_voter != address(0)); + vm.assume(_voter != address(0) && _voter != address(governance)); proposal = proposals[_proposalName]; proposalId = proposalIds[_proposalName]; diff --git a/l1-contracts/test/governance/scenario/AddRollup.t.sol b/l1-contracts/test/governance/scenario/AddRollup.t.sol index 181235762e87..8275c7b517dd 100644 --- a/l1-contracts/test/governance/scenario/AddRollup.t.sol +++ b/l1-contracts/test/governance/scenario/AddRollup.t.sol @@ -129,19 +129,21 @@ contract AddRollupTest is TestBase { assertEq(originalPayload, address(payload)); assertEq(gsePayload.getURI(), payload.getURI()); + uint256 emperorPower = 10_000e18 + rollup.getActivationThreshold() * VALIDATOR_COUNT; + vm.prank(token.owner()); - token.mint(EMPEROR, 10_000 ether); + token.mint(EMPEROR, emperorPower); vm.startPrank(EMPEROR); - token.approve(address(governance), 10_000 ether); - governance.deposit(EMPEROR, 10_000 ether); + token.approve(address(governance), emperorPower); + governance.deposit(EMPEROR, emperorPower); vm.stopPrank(); vm.warp(Timestamp.unwrap(upw.pendingThrough(proposal)) + 1); assertTrue(governance.getProposalState(0) == ProposalState.Active); vm.prank(EMPEROR); - governance.vote(0, 10_000 ether, true); + governance.vote(0, emperorPower, true); vm.warp(Timestamp.unwrap(upw.activeThrough(proposal)) + 1); assertTrue(governance.getProposalState(0) == ProposalState.Queued); diff --git a/l1-contracts/test/governance/scenario/UpgradeGovernanceProposerTest.t.sol b/l1-contracts/test/governance/scenario/UpgradeGovernanceProposerTest.t.sol index 69f2e415ea65..3e95d2e1d6b0 100644 --- a/l1-contracts/test/governance/scenario/UpgradeGovernanceProposerTest.t.sol +++ b/l1-contracts/test/governance/scenario/UpgradeGovernanceProposerTest.t.sol @@ -113,19 +113,21 @@ contract UpgradeGovernanceProposerTest is TestBase { assertEq(originalPayload, address(payload)); assertEq(gsePayload.getURI(), payload.getURI()); + uint256 emperorPower = 10_000e18 + rollup.getActivationThreshold() * VALIDATOR_COUNT; + vm.prank(token.owner()); - token.mint(EMPEROR, 10_000 ether); + token.mint(EMPEROR, emperorPower); vm.startPrank(EMPEROR); - token.approve(address(governance), 10_000 ether); - governance.deposit(EMPEROR, 10_000 ether); + token.approve(address(governance), emperorPower); + governance.deposit(EMPEROR, emperorPower); vm.stopPrank(); vm.warp(Timestamp.unwrap(upw.pendingThrough(proposal)) + 1); assertTrue(governance.getProposalState(0) == ProposalState.Active); vm.prank(EMPEROR); - governance.vote(0, 10_000 ether, true); + governance.vote(0, emperorPower, true); vm.warp(Timestamp.unwrap(upw.activeThrough(proposal)) + 1); assertTrue(governance.getProposalState(0) == ProposalState.Queued); diff --git a/l1-contracts/test/governance/scenario/slashing/EmpireSlashing.t.sol b/l1-contracts/test/governance/scenario/slashing/EmpireSlashing.t.sol index 408906f0b174..0cacc2732f01 100644 --- a/l1-contracts/test/governance/scenario/slashing/EmpireSlashing.t.sol +++ b/l1-contracts/test/governance/scenario/slashing/EmpireSlashing.t.sol @@ -65,7 +65,9 @@ contract SlashingTest is TestBase { IPayload payload = slashFactory.createSlashPayload(offenders, amounts, offenses); - for (uint256 i = 0; i < 10; i++) { + uint256 quorum = slashingProposer.QUORUM_SIZE(); + + for (uint256 i = 0; i < quorum; i++) { address proposer = rollup.getCurrentProposer(); vm.prank(proposer); slashingProposer.signal(payload); @@ -225,6 +227,11 @@ contract SlashingTest is TestBase { // We slash a small amount and see that they are all still validating, but less stake uint96 slashAmount1 = 10e18; (uint256 firstSlashingRound,) = _createPayloadAndSignalForSlashing(attesters, slashAmount1, howManyToSlash); + + uint256 firstExecutableSlot = + (firstSlashingRound + slashingProposer.EXECUTION_DELAY_IN_ROUNDS() + 1) * slashingProposer.ROUND_SIZE(); + timeCheater.cheat__jumpToSlot(firstExecutableSlot); + slashingProposer.submitRoundWinner(firstSlashingRound); for (uint256 i = 0; i < howManyToSlash; i++) { @@ -237,8 +244,14 @@ contract SlashingTest is TestBase { // Now we do it all again, but this time enough to kick them out of the system! // Why we doing it in two steps explicitly here? To make sure that it is clear // that it works like this. - uint96 slashAmount2 = 40e18 + 1; + uint96 slashAmount2 = + uint96(rollup.getActivationThreshold()) - uint96(rollup.getEjectionThreshold()) - slashAmount1 + 1; (uint256 secondSlashingRound,) = _createPayloadAndSignalForSlashing(attesters, slashAmount2, howManyToSlash); + + uint256 secondExecutableSlot = + (secondSlashingRound + slashingProposer.EXECUTION_DELAY_IN_ROUNDS() + 1) * slashingProposer.ROUND_SIZE(); + timeCheater.cheat__jumpToSlot(secondExecutableSlot); + slashingProposer.submitRoundWinner(secondSlashingRound); for (uint256 i = 0; i < howManyToSlash; i++) { diff --git a/l1-contracts/test/governance/scenario/slashing/TallySlashing.t.sol b/l1-contracts/test/governance/scenario/slashing/TallySlashing.t.sol index 03a1375f80b2..28ac9cfbabb2 100644 --- a/l1-contracts/test/governance/scenario/slashing/TallySlashing.t.sol +++ b/l1-contracts/test/governance/scenario/slashing/TallySlashing.t.sol @@ -33,6 +33,7 @@ import {BN254Lib, G1Point, G2Point} from "@aztec/shared/libraries/BN254Lib.sol"; import {SignatureLib, Signature} from "@aztec/shared/libraries/SignatureLib.sol"; import {SlashRound} from "@aztec/core/libraries/SlashRoundLib.sol"; import {SlasherFlavor} from "@aztec/core/interfaces/ISlasher.sol"; +import {Ownable} from "@oz/access/Ownable.sol"; // solhint-disable comprehensive-interface // solhint-disable func-name-mixedcase @@ -197,6 +198,7 @@ contract SlashingTest is TestBase { assertEq(rollup.getActiveAttesterCount(), validatorCount, "Invalid attester count"); } + /// forge-config: default.fuzz.runs = 8 function test_CannotSlashBeforeDelay(uint256 _lifetimeInRounds, uint256 _executionDelayInRounds, uint256 _jumpToSlot) public { @@ -225,6 +227,7 @@ contract SlashingTest is TestBase { slashingProposer.executeRound(firstSlashingRound, committees); } + /// forge-config: default.fuzz.runs = 8 function test_CanSlashAfterDelay(uint256 _lifetimeInRounds, uint256 _executionDelayInRounds, uint256 _jumpToSlot) public { @@ -267,6 +270,7 @@ contract SlashingTest is TestBase { } } + /// forge-config: default.fuzz.runs = 8 function test_CannotSlashIfVetoed(uint256 _lifetimeInRounds, uint256 _executionDelayInRounds, uint256 _jumpToSlot) public { @@ -309,9 +313,6 @@ contract SlashingTest is TestBase { function test_SlashingDisableTimestamp() public { _setupCommitteeForSlashing(); - address[] memory attesters = rollup.getEpochCommittee(Epoch.wrap(INITIAL_EPOCH)); - uint96 slashAmount = uint96(slashingProposer.SLASH_AMOUNT_SMALL()); - SlashRound firstSlashingRound = _createSlashingVotes(slashAmount, attesters.length); // Initially slashing should be enabled assertEq(slasher.isSlashingEnabled(), true, "Slashing should be enabled initially"); @@ -387,7 +388,7 @@ contract SlashingTest is TestBase { uint256 howManyToSlash = HOW_MANY_SLASHED; // We slash a small amount and see that they are all still validating, but less stake - uint96 slashAmount1 = 10e18; + uint96 slashAmount1 = uint96(slashingProposer.SLASH_AMOUNT_SMALL()); SlashRound firstSlashingRound = _createSlashingVotes(slashAmount1, howManyToSlash); // Grab the attesters and their initial stakes @@ -445,7 +446,57 @@ contract SlashingTest is TestBase { uint256 howManyToSlash = HOW_MANY_SLASHED; // We slash a small amount and see that they are all still validating, but less stake - uint96 slashAmount1 = 60e18; + uint96 slashAmount1 = uint96(slashingProposer.SLASH_AMOUNT_LARGE()); + SlashRound firstSlashingRound = _createSlashingVotes(slashAmount1, howManyToSlash); + + // Grab the attesters and their initial stakes + address[][] memory committees = new address[][](slashingProposer.ROUND_SIZE_IN_EPOCHS()); + address[] memory attesters = new address[](slashingProposer.ROUND_SIZE_IN_EPOCHS() * COMMITTEE_SIZE); + uint256[] memory stakes = new uint256[](attesters.length); + for (uint256 i = 0; i < slashingProposer.ROUND_SIZE_IN_EPOCHS(); i++) { + Epoch epochSlashed = slashingProposer.getSlashTargetEpoch(firstSlashingRound, i); + address[] memory committee = rollup.getEpochCommittee(epochSlashed); + committees[i] = committee; + for (uint256 j = 0; j < committee.length; j++) { + address attester = committee[j]; + attesters[i * COMMITTEE_SIZE + j] = attester; + AttesterView memory attesterView = rollup.getAttesterView(attester); + stakes[i * COMMITTEE_SIZE + j] = attesterView.effectiveBalance; + assertTrue(attesterView.status == Status.VALIDATING, "Invalid status"); + } + } + + // Wait for execution delay and execute - need to be in the next round for execution + uint256 roundsToWait = slashingProposer.EXECUTION_DELAY_IN_ROUNDS() + 1; + timeCheater.cheat__jumpForwardSlots(roundsToWait * slashingProposer.ROUND_SIZE()); + + // Execute the slash + slashingProposer.executeRound(firstSlashingRound, committees); + + // Check balances + for (uint256 i = 0; i < howManyToSlash; i++) { + AttesterView memory attesterView = rollup.getAttesterView(attesters[i]); + assertEq(attesterView.effectiveBalance, stakes[i] - slashAmount1); + assertEq(attesterView.exit.amount, 0, "Invalid stake"); + assertTrue(attesterView.status == Status.VALIDATING, "Invalid status"); + } + + // Verify that slashing was successful and validators are still active + assertEq(rollup.getActiveAttesterCount(), VALIDATOR_COUNT, "All validators should remain active after small slash"); + } + + function test_SlashingLargeAmount_smallLocalEjectionThreshold() public { + _setupCommitteeForSlashing(); + + uint256 howManyToSlash = HOW_MANY_SLASHED; + + // We slash a large amount AND alter the local ejection threshold, to see that this should kick us out. + uint96 slashAmount1 = uint96(slashingProposer.SLASH_AMOUNT_LARGE()); + uint256 localEjectionThreshold = rollup.getActivationThreshold() - slashAmount1 + 1; + + vm.prank(Ownable(address(rollup)).owner()); + rollup.setLocalEjectionThreshold(localEjectionThreshold); + SlashRound firstSlashingRound = _createSlashingVotes(slashAmount1, howManyToSlash); // Grab the attesters and their initial stakes diff --git a/l1-contracts/test/harnesses/TestConstants.sol b/l1-contracts/test/harnesses/TestConstants.sol index cf540d40242b..a84547afb056 100644 --- a/l1-contracts/test/harnesses/TestConstants.sol +++ b/l1-contracts/test/harnesses/TestConstants.sol @@ -20,16 +20,16 @@ library TestConstants { uint256 internal constant AZTEC_TARGET_COMMITTEE_SIZE = 48; uint256 internal constant AZTEC_LAG_IN_EPOCHS = 2; uint256 internal constant AZTEC_PROOF_SUBMISSION_EPOCHS = 1; - uint256 internal constant AZTEC_SLASHING_QUORUM = 6; - uint256 internal constant AZTEC_SLASHING_ROUND_SIZE = 10; - uint256 internal constant AZTEC_SLASHING_LIFETIME_IN_ROUNDS = 5; - uint256 internal constant AZTEC_SLASHING_EXECUTION_DELAY_IN_ROUNDS = 0; + uint256 internal constant AZTEC_SLASHING_QUORUM = 65; + uint256 internal constant AZTEC_SLASHING_ROUND_SIZE = 4 * AZTEC_EPOCH_DURATION; + uint256 internal constant AZTEC_SLASHING_LIFETIME_IN_ROUNDS = 40; + uint256 internal constant AZTEC_SLASHING_EXECUTION_DELAY_IN_ROUNDS = 28; uint256 internal constant AZTEC_SLASHING_OFFSET_IN_ROUNDS = 2; address internal constant AZTEC_SLASHING_VETOER = address(0); uint256 internal constant AZTEC_SLASHING_DISABLE_DURATION = 5 days; - uint256 internal constant AZTEC_SLASH_AMOUNT_SMALL = 20e18; - uint256 internal constant AZTEC_SLASH_AMOUNT_MEDIUM = 40e18; - uint256 internal constant AZTEC_SLASH_AMOUNT_LARGE = 60e18; + uint256 internal constant AZTEC_SLASH_AMOUNT_SMALL = 2000e18; + uint256 internal constant AZTEC_SLASH_AMOUNT_MEDIUM = 10_000e18; + uint256 internal constant AZTEC_SLASH_AMOUNT_LARGE = 30_000e18; uint256 internal constant AZTEC_MANA_TARGET = 100_000_000; uint256 internal constant AZTEC_ENTRY_QUEUE_FLUSH_SIZE_MIN = 4; uint256 internal constant AZTEC_ENTRY_QUEUE_FLUSH_SIZE_QUOTIENT = 2; @@ -40,8 +40,8 @@ library TestConstants { EthValue internal constant AZTEC_PROVING_COST_PER_MANA = EthValue.wrap(100); uint256 internal constant AZTEC_COIN_ISSUER_RATE = uint256(25_000_000_000e18) / uint256(60 * 60 * 24 * 365); - uint256 internal constant ACTIVATION_THRESHOLD = 100e18; - uint256 internal constant EJECTION_THRESHOLD = 50e18; + uint256 internal constant ACTIVATION_THRESHOLD = 200_000e18; + uint256 internal constant EJECTION_THRESHOLD = 100_000e18; // Genesis state bytes32 internal constant GENESIS_ARCHIVE_ROOT = bytes32(Constants.GENESIS_ARCHIVE_ROOT); @@ -70,15 +70,15 @@ library TestConstants { } function getRewardBoostConfig() internal pure returns (RewardBoostConfig memory) { - return RewardBoostConfig({increment: 200_000, maxScore: 5_000_000, a: 5000, k: 1_000_000, minimum: 100_000}); + return RewardBoostConfig({increment: 1.25e5, maxScore: 150e5, a: 0.01e5, k: 10e5, minimum: 1e5}); } function getRewardConfig() internal pure returns (RewardConfig memory) { return RewardConfig({ rewardDistributor: IRewardDistributor(address(0)), - sequencerBps: Bps.wrap(5000), + sequencerBps: Bps.wrap(8000), booster: IBoosterCore(address(0)), // Will cause a deployment - blockReward: 50e18 + blockReward: 500e18 }); } diff --git a/l1-contracts/test/portals/TokenPortal.sol b/l1-contracts/test/portals/TokenPortal.sol index ff5ab3b16602..71a85c88cb86 100644 --- a/l1-contracts/test/portals/TokenPortal.sol +++ b/l1-contracts/test/portals/TokenPortal.sol @@ -146,7 +146,7 @@ contract TokenPortal { outbox.consume(message, _l2BlockNumber, _leafIndex, _path); - underlying.transfer(_recipient, _amount); + underlying.safeTransfer(_recipient, _amount); } // docs:end:token_portal_withdraw } diff --git a/l1-contracts/test/staking/15050.t.sol b/l1-contracts/test/staking/15050.t.sol index e19abe6dd5e8..78f3a4d7de99 100644 --- a/l1-contracts/test/staking/15050.t.sol +++ b/l1-contracts/test/staking/15050.t.sol @@ -63,11 +63,13 @@ contract Test15050 is StakingBase { assertEq(caller.getCurrentRound(), 0); - while (caller.getCurrentRound() == 0) { + uint256 waitUntilRound = caller.EXECUTION_DELAY_IN_ROUNDS() + 1; + + while (caller.getCurrentRound() < waitUntilRound) { vm.warp(block.timestamp + 12); } - assertEq(caller.getCurrentRound(), 1); + assertEq(caller.getCurrentRound(), waitUntilRound); RoundAccounting memory r = caller.getRoundData(address(staking), 0); assertFalse(r.executed); diff --git a/l1-contracts/test/validator-selection/ValidatorSelection.t.sol b/l1-contracts/test/validator-selection/ValidatorSelection.t.sol index d62027a4d852..4a386a86c1d7 100644 --- a/l1-contracts/test/validator-selection/ValidatorSelection.t.sol +++ b/l1-contracts/test/validator-selection/ValidatorSelection.t.sol @@ -306,7 +306,7 @@ contract ValidatorSelectionTest is ValidatorSelectionTestBase { uint96[] memory amounts = new uint96[](attesters.length); // We say, these things are bad, call the baba yaga to take care of them! - uint96 slashAmount = 90e18; + uint96 slashAmount = 1 + uint96(rollup.getActivationThreshold()) - uint96(rollup.getEjectionThreshold()); for (uint256 i = 0; i < attesters.length; i++) { AttesterView memory attesterView = rollup.getAttesterView(attesters[i]); stakes[i] = attesterView.effectiveBalance; diff --git a/yarn-project/end-to-end/src/e2e_p2p/data_withholding_slash.test.ts b/yarn-project/end-to-end/src/e2e_p2p/data_withholding_slash.test.ts index f351d48863b6..646fa3773f77 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/data_withholding_slash.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/data_withholding_slash.test.ts @@ -37,7 +37,6 @@ describe('e2e_p2p_data_withholding_slash', () => { let t: P2PNetworkTest; let nodes: AztecNodeService[]; - const slashingUnit = BigInt(1e18); const slashingQuorum = 3; const slashingRoundSize = 4; // This test needs longer slot window to ensure that the client has enough time to submit their txs, @@ -59,9 +58,6 @@ describe('e2e_p2p_data_withholding_slash', () => { aztecProofSubmissionEpochs: 0, // effectively forces instant reorgs slashingQuorum, slashingRoundSizeInEpochs: slashingRoundSize / 2, - slashAmountSmall: slashingUnit, - slashAmountMedium: slashingUnit * 2n, - slashAmountLarge: slashingUnit * 3n, slashSelfAllowed: true, minTxsPerBlock: 0, }, @@ -101,7 +97,7 @@ describe('e2e_p2p_data_withholding_slash', () => { ]); // Slashing amount should be enough to kick validators out - const slashingAmount = slashingUnit * 3n; + const slashingAmount = t.ctx.aztecNodeConfig.slashAmountLarge; const biggestEjection = ejectionThreshold > localEjectionThreshold ? ejectionThreshold : localEjectionThreshold; expect(activationThreshold - slashingAmount).toBeLessThan(biggestEjection); diff --git a/yarn-project/end-to-end/src/e2e_p2p/inactivity_slash_test.ts b/yarn-project/end-to-end/src/e2e_p2p/inactivity_slash_test.ts index fbb7201f8460..28e55b8a37bb 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/inactivity_slash_test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/inactivity_slash_test.ts @@ -19,8 +19,6 @@ const SLASHING_ROUND_SIZE_IN_EPOCHS = 2; const BOOT_NODE_UDP_PORT = 4500; const ETHEREUM_SLOT_DURATION = 4; const AZTEC_SLOT_DURATION = 8; -const SLASHING_UNIT = BigInt(1e18); -const SLASHING_AMOUNT = SLASHING_UNIT * 3n; // How many epochs it may take to set everything up, so we dont slash during this period const SETUP_EPOCH_DURATION = 5; @@ -71,9 +69,6 @@ export class P2PInactivityTest { slashingRoundSizeInEpochs: SLASHING_ROUND_SIZE_IN_EPOCHS, slashInactivityTargetPercentage: 0.8, slashGracePeriodL2Slots: SETUP_EPOCH_DURATION * EPOCH_DURATION, // do not slash during setup - slashAmountSmall: SLASHING_UNIT, - slashAmountMedium: SLASHING_UNIT * 2n, - slashAmountLarge: SLASHING_UNIT * 3n, ...opts, }, }); @@ -92,8 +87,8 @@ export class P2PInactivityTest { rollup.getLocalEjectionThreshold(), ]); const biggestEjection = ejectionThreshold > localEjectionThreshold ? ejectionThreshold : localEjectionThreshold; - expect(activationThreshold - SLASHING_AMOUNT).toBeLessThan(biggestEjection); - this.test.ctx.aztecNodeConfig.slashInactivityPenalty = SLASHING_AMOUNT; + expect(activationThreshold - this.slashingAmount * 3n).toBeLessThan(biggestEjection); + this.test.ctx.aztecNodeConfig.slashInactivityPenalty = this.test.ctx.aztecNodeConfig.slashAmountSmall; this.rollup = rollup; if (!this.keepInitialNode) { @@ -169,6 +164,6 @@ export class P2PInactivityTest { } public get slashingAmount() { - return SLASHING_AMOUNT; + return this.test.ctx.aztecNodeConfig.slashAmountSmall; } } diff --git a/yarn-project/end-to-end/src/e2e_p2p/slash_veto_demo.test.ts b/yarn-project/end-to-end/src/e2e_p2p/slash_veto_demo.test.ts index 9ac39e72224d..bfd4fb90ec91 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/slash_veto_demo.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/slash_veto_demo.test.ts @@ -51,8 +51,6 @@ const SLASH_INACTIVITY_TARGET_PERCENTAGE = 0.5; const LIFETIME_IN_ROUNDS = 2; // round N must be submitted after round N + EXECUTION_DELAY_IN_ROUNDS const EXECUTION_DELAY_IN_ROUNDS = 1; -// unit of slashing -const SLASHING_UNIT = BigInt(20e18); // offset for slashing rounds const SLASH_OFFSET_IN_ROUNDS = 2; const COMMITEE_SIZE = NUM_VALIDATORS; @@ -85,9 +83,6 @@ describe('veto slash', () => { sentinelEnabled: true, slashSelfAllowed: true, slashingOffsetInRounds: SLASH_OFFSET_IN_ROUNDS, - slashAmountSmall: SLASHING_UNIT, - slashAmountMedium: SLASHING_UNIT * 2n, - slashAmountLarge: SLASHING_UNIT * 3n, slashingRoundSizeInEpochs: SLASHING_ROUND_SIZE / EPOCH_DURATION, slashingQuorum: SLASHING_QUORUM, slashInactivityTargetPercentage: SLASH_INACTIVITY_TARGET_PERCENTAGE, @@ -116,14 +111,15 @@ describe('veto slash', () => { ({ rollup } = await t.getContracts()); - const [activationThreshold, ejectionThreshold] = await Promise.all([ + const [activationThreshold, ejectionThreshold, localEjectionThreshold] = await Promise.all([ rollup.getActivationThreshold(), rollup.getEjectionThreshold(), + rollup.getLocalEjectionThreshold(), ]); - // Slashing amount should be enough to kick validators out - slashingAmount = SLASHING_UNIT * 3n; - expect(activationThreshold - slashingAmount).toBeLessThan(ejectionThreshold); + slashingAmount = t.ctx.aztecNodeConfig.slashAmountSmall; + const biggestEjection = ejectionThreshold > localEjectionThreshold ? ejectionThreshold : localEjectionThreshold; + expect(activationThreshold - slashingAmount * 3n).toBeLessThan(biggestEjection); t.ctx.aztecNodeConfig.slashInactivityPenalty = slashingAmount; for (const node of nodes) { @@ -181,7 +177,11 @@ describe('veto slash', () => { BigInt(SLASHING_ROUND_SIZE), BigInt(LIFETIME_IN_ROUNDS), BigInt(EXECUTION_DELAY_IN_ROUNDS), - [SLASHING_UNIT, SLASHING_UNIT * 2n, SLASHING_UNIT * 3n], + [ + t.ctx.aztecNodeConfig.slashAmountSmall, + t.ctx.aztecNodeConfig.slashAmountMedium, + t.ctx.aztecNodeConfig.slashAmountLarge, + ], BigInt(COMMITEE_SIZE), BigInt(EPOCH_DURATION), BigInt(SLASH_OFFSET_IN_ROUNDS), diff --git a/yarn-project/end-to-end/src/e2e_p2p/valid_epoch_pruned.test.ts b/yarn-project/end-to-end/src/e2e_p2p/valid_epoch_pruned.test.ts index 115c924919c5..f3c64f6a657c 100644 --- a/yarn-project/end-to-end/src/e2e_p2p/valid_epoch_pruned.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p/valid_epoch_pruned.test.ts @@ -32,7 +32,6 @@ describe('e2e_p2p_valid_epoch_pruned', () => { const slashingQuorum = 3; const slashingRoundSize = 4; const aztecSlotDuration = 8; - const slashingUnit = BigInt(1e18); beforeEach(async () => { t = await P2PNetworkTest.create({ @@ -50,9 +49,6 @@ describe('e2e_p2p_valid_epoch_pruned', () => { slashingQuorum, slashingRoundSizeInEpochs: slashingRoundSize / 2, slashSelfAllowed: true, - slashAmountSmall: slashingUnit, - slashAmountMedium: slashingUnit * 2n, - slashAmountLarge: slashingUnit * 3n, }, }); @@ -87,11 +83,11 @@ describe('e2e_p2p_valid_epoch_pruned', () => { ]); // Slashing amount should be enough to kick validators out - const slashingAmount = slashingUnit * 3n; + const slashingAmount = t.ctx.aztecNodeConfig.slashAmountLarge; const biggestEjection = ejectionThreshold > localEjectionThreshold ? ejectionThreshold : localEjectionThreshold; expect(activationThreshold - slashingAmount).toBeLessThan(biggestEjection); - t.ctx.aztecNodeConfig.slashPrunePenalty = slashingAmount; + t.ctx.aztecNodeConfig.slashPrunePenalty = t.ctx.aztecNodeConfig.slashAmountLarge; t.ctx.aztecNodeConfig.validatorReexecute = false; t.ctx.aztecNodeConfig.minTxsPerBlock = 0; diff --git a/yarn-project/ethereum/src/config.ts b/yarn-project/ethereum/src/config.ts index 494cddeaa53f..cbe6d057fa5f 100644 --- a/yarn-project/ethereum/src/config.ts +++ b/yarn-project/ethereum/src/config.ts @@ -79,12 +79,12 @@ export const DefaultL1ContractsConfig = { aztecTargetCommitteeSize: 48, lagInEpochs: 2, aztecProofSubmissionEpochs: 1, // you have a full epoch to submit a proof after the epoch to prove ends - activationThreshold: 100n * 10n ** 18n, - ejectionThreshold: 50n * 10n ** 18n, - localEjectionThreshold: 98n * 10n ** 18n, - slashAmountSmall: 10n * 10n ** 18n, - slashAmountMedium: 20n * 10n ** 18n, - slashAmountLarge: 50n * 10n ** 18n, + activationThreshold: 200_000n * 10n ** 18n, + ejectionThreshold: 100_000n * 10n ** 18n, + localEjectionThreshold: 196_000n * 10n ** 18n, + slashAmountSmall: 2_000n * 10n ** 18n, + slashAmountMedium: 10_000n * 10n ** 18n, + slashAmountLarge: 50_000n * 10n ** 18n, slashingRoundSizeInEpochs: 4, slashingLifetimeInRounds: 5, slashingExecutionDelayInRounds: 0, // round N may be submitted in round N + 1