Skip to content

Commit 5256c9f

Browse files
authored
feat: Simplify slasher settings (#16625)
Fixes #16597 Builds on #16617
2 parents db151be + cc519f7 commit 5256c9f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+409
-508
lines changed

l1-contracts/src/core/RollupCore.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ contract RollupCore is EIP712("Aztec Rollup", "1"), Ownable, IStakingCore, IVali
249249
_config.slashingRoundSize,
250250
_config.slashingLifetimeInRounds,
251251
_config.slashingExecutionDelayInRounds,
252-
_config.slashingUnit,
252+
_config.slashAmounts,
253253
_config.targetCommitteeSize,
254254
_config.aztecEpochDuration,
255255
_config.slashingOffsetInRounds

l1-contracts/src/core/interfaces/IRollup.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ struct RollupConfigInput {
6161
uint256 slashingRoundSize;
6262
uint256 slashingLifetimeInRounds;
6363
uint256 slashingExecutionDelayInRounds;
64-
uint256 slashingUnit;
64+
uint256[3] slashAmounts;
6565
uint256 slashingOffsetInRounds;
6666
SlasherFlavor slasherFlavor;
6767
address slashingVetoer;

l1-contracts/src/core/libraries/Errors.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ library Errors {
184184
error TallySlashingProposer__InvalidCommitteeCommitment();
185185
error TallySlashingProposer__InvalidQuorumAndRoundSize(uint256 quorum, uint256 roundSize);
186186
error TallySlashingProposer__QuorumMustBeGreaterThanZero();
187-
error TallySlashingProposer__SlashingUnitMustBeGreaterThanZero(uint256 slashingUnit);
187+
error TallySlashingProposer__InvalidSlashAmounts(uint256[3] slashAmounts);
188188
error TallySlashingProposer__LifetimeMustBeGreaterThanExecutionDelay(uint256 lifetime, uint256 executionDelay);
189189
error TallySlashingProposer__LifetimeMustBeLessThanRoundabout(uint256 lifetime, uint256 roundabout);
190190
error TallySlashingProposer__RoundSizeInEpochsMustBeGreaterThanZero(uint256 roundSizeInEpochs);

l1-contracts/src/core/libraries/rollup/TallySlasherDeploymentExtLib.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ library TallySlasherDeploymentExtLib {
2424
uint256 _roundSize,
2525
uint256 _lifetimeInRounds,
2626
uint256 _executionDelayInRounds,
27-
uint256 _slashingUnit,
27+
uint256[3] calldata _slashAmounts,
2828
uint256 _committeeSize,
2929
uint256 _epochDuration,
3030
uint256 _slashOffsetInRounds
@@ -40,7 +40,7 @@ library TallySlasherDeploymentExtLib {
4040
_roundSize,
4141
_lifetimeInRounds,
4242
_executionDelayInRounds,
43-
_slashingUnit,
43+
_slashAmounts,
4444
_committeeSize,
4545
_epochDuration,
4646
_slashOffsetInRounds

l1-contracts/src/core/slashing/TallySlashingProposer.sol

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ import {SafeCast} from "@oz/utils/math/SafeCast.sol";
8080
* - EXECUTION_DELAY_IN_ROUNDS: Rounds to wait before allowing execution
8181
* - LIFETIME_IN_ROUNDS: Maximum age of rounds that can still be executed
8282
* - SLASH_OFFSET_IN_ROUNDS: How far back to look for validators to slash
83-
* - SLASHING_UNIT: Base amount of slashing per unit voted
83+
* - SLASH_AMOUNT_SMALL/MEDIUM/LARGE: Specific amounts for each slash unit level
8484
* - COMMITTEE_SIZE: Number of validators per committee
8585
*/
8686
contract TallySlashingProposer is EIP712 {
@@ -195,8 +195,19 @@ contract TallySlashingProposer is EIP712 {
195195
/**
196196
* @notice Base amount of stake to slash per slashing unit (in wei)
197197
* @dev Validators can be voted to be slashed by 1-3 units, multiplied by this base amount
198+
* @notice Small slash amount for 1 unit votes (in wei)
198199
*/
199-
uint256 public immutable SLASHING_UNIT;
200+
uint256 public immutable SLASH_AMOUNT_SMALL;
201+
202+
/**
203+
* @notice Medium slash amount for 2 unit votes (in wei)
204+
*/
205+
uint256 public immutable SLASH_AMOUNT_MEDIUM;
206+
207+
/**
208+
* @notice Large slash amount for 3 unit votes (in wei)
209+
*/
210+
uint256 public immutable SLASH_AMOUNT_LARGE;
200211

201212
/**
202213
* @notice Minimum number of votes required to slash a validator
@@ -275,7 +286,7 @@ contract TallySlashingProposer is EIP712 {
275286
* _executionDelayInRounds and < ROUNDABOUT_SIZE)
276287
* @param _executionDelayInRounds The number of rounds to wait after a round ends before it can be executed (provides
277288
* time for review)
278-
* @param _slashingUnit The base amount of stake to slash per slashing unit (must be > 0)
289+
* @param _slashAmounts Array of 3 slash amounts [small, medium, large] for 1, 2, 3 unit votes (all must be > 0)
279290
* @param _committeeSize The number of validators in each committee (must be > 0)
280291
* @param _epochDuration The number of slots in each epoch (used to calculate ROUND_SIZE_IN_EPOCHS)
281292
* @param _slashOffsetInRounds How many rounds in the past to look when determining which validators to slash (must be
@@ -288,14 +299,16 @@ contract TallySlashingProposer is EIP712 {
288299
uint256 _roundSize,
289300
uint256 _lifetimeInRounds,
290301
uint256 _executionDelayInRounds,
291-
uint256 _slashingUnit,
302+
uint256[3] memory _slashAmounts,
292303
uint256 _committeeSize,
293304
uint256 _epochDuration,
294305
uint256 _slashOffsetInRounds
295306
) EIP712("TallySlashingProposer", "1") {
296307
INSTANCE = _instance;
297308
SLASHER = _slasher;
298-
SLASHING_UNIT = _slashingUnit;
309+
SLASH_AMOUNT_SMALL = _slashAmounts[0];
310+
SLASH_AMOUNT_MEDIUM = _slashAmounts[1];
311+
SLASH_AMOUNT_LARGE = _slashAmounts[2];
299312
QUORUM = _quorum;
300313
ROUND_SIZE = _roundSize;
301314
ROUND_SIZE_IN_EPOCHS = _roundSize / _epochDuration;
@@ -318,7 +331,8 @@ contract TallySlashingProposer is EIP712 {
318331
require(ROUND_SIZE > 1, Errors.TallySlashingProposer__InvalidQuorumAndRoundSize(QUORUM, ROUND_SIZE));
319332
require(QUORUM > ROUND_SIZE / 2, Errors.TallySlashingProposer__InvalidQuorumAndRoundSize(QUORUM, ROUND_SIZE));
320333
require(QUORUM <= ROUND_SIZE, Errors.TallySlashingProposer__InvalidQuorumAndRoundSize(QUORUM, ROUND_SIZE));
321-
require(SLASHING_UNIT > 0, Errors.TallySlashingProposer__SlashingUnitMustBeGreaterThanZero(SLASHING_UNIT));
334+
require(_slashAmounts[0] <= _slashAmounts[1], Errors.TallySlashingProposer__InvalidSlashAmounts(_slashAmounts));
335+
require(_slashAmounts[1] <= _slashAmounts[2], Errors.TallySlashingProposer__InvalidSlashAmounts(_slashAmounts));
322336
require(
323337
LIFETIME_IN_ROUNDS > EXECUTION_DELAY_IN_ROUNDS,
324338
Errors.TallySlashingProposer__LifetimeMustBeGreaterThanExecutionDelay(
@@ -863,11 +877,19 @@ contract TallySlashingProposer is EIP712 {
863877

864878
// Check if this slash amount has reached quorum
865879
if (voteCountForValidator >= QUORUM) {
880+
// Convert units to actual slash amount
881+
uint256 slashAmount;
882+
if (j == 1) {
883+
slashAmount = SLASH_AMOUNT_SMALL;
884+
} else if (j == 2) {
885+
slashAmount = SLASH_AMOUNT_MEDIUM;
886+
} else if (j == 3) {
887+
slashAmount = SLASH_AMOUNT_LARGE;
888+
}
889+
866890
// Record the slashing action
867-
actions[actionCount] = SlashAction({
868-
validator: _committees[i / COMMITTEE_SIZE][i % COMMITTEE_SIZE],
869-
slashAmount: SLASHING_UNIT * j
870-
});
891+
actions[actionCount] =
892+
SlashAction({validator: _committees[i / COMMITTEE_SIZE][i % COMMITTEE_SIZE], slashAmount: slashAmount});
871893
++actionCount;
872894

873895
// Mark this committee as having at least one slashed validator

l1-contracts/test/benchmark/happy.t.sol

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,8 @@ contract BenchmarkRollupTest is FeeModelTestPoints, DecoderBase {
187187
uint256 tallyRoundSize = EPOCH_DURATION * 2; // 64; // 2 * EPOCH_DURATION (32) = 64
188188
uint256 tallyQuorum = tallyRoundSize / 2 + 1; // Must be > ROUND_SIZE / 2
189189
builder.setSlasherFlavor(SlasherFlavor.TALLY).setSlashingQuorum(tallyQuorum).setSlashingRoundSize(tallyRoundSize)
190-
.setSlashingLifetimeInRounds(5).setSlashingExecutionDelayInRounds(1).setSlashingUnit(1e18);
190+
.setSlashingLifetimeInRounds(5).setSlashingExecutionDelayInRounds(1).setSlashAmountSmall(1e18)
191+
.setSlashAmountMedium(2e18).setSlashAmountLarge(3e18);
191192
}
192193

193194
builder.deploy();

l1-contracts/test/builder/RollupBuilder.sol

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,18 @@ contract RollupBuilder is Test {
205205
return this;
206206
}
207207

208-
function setSlashingUnit(uint256 _slashingUnit) public returns (RollupBuilder) {
209-
config.rollupConfigInput.slashingUnit = _slashingUnit;
208+
function setSlashAmountSmall(uint256 _slashAmountSmall) public returns (RollupBuilder) {
209+
config.rollupConfigInput.slashAmounts[0] = _slashAmountSmall;
210+
return this;
211+
}
212+
213+
function setSlashAmountMedium(uint256 _slashAmountMedium) public returns (RollupBuilder) {
214+
config.rollupConfigInput.slashAmounts[1] = _slashAmountMedium;
215+
return this;
216+
}
217+
218+
function setSlashAmountLarge(uint256 _slashAmountLarge) public returns (RollupBuilder) {
219+
config.rollupConfigInput.slashAmounts[2] = _slashAmountLarge;
210220
return this;
211221
}
212222

l1-contracts/test/governance/scenario/slashing/TallySlashing.t.sol

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,14 @@ contract SlashingTest is TestBase {
9191
// Create votes - for tally slashing we need to encode votes as bytes
9292
// Each validator gets a slash amount between 1-3 units
9393
// For simplicity, we'll vote to slash all validators by the same amount
94-
uint256 slashUnits = _slashAmount / slashingProposer.SLASHING_UNIT();
95-
if (slashUnits == 0) slashUnits = 1; // Minimum 1 unit
96-
if (slashUnits > 3) slashUnits = 3; // Maximum 3 units
94+
uint256 slashUnits;
95+
if (_slashAmount >= slashingProposer.SLASH_AMOUNT_LARGE()) {
96+
slashUnits = 3;
97+
} else if (_slashAmount >= slashingProposer.SLASH_AMOUNT_MEDIUM()) {
98+
slashUnits = 2;
99+
} else {
100+
slashUnits = 1;
101+
}
97102

98103
// Calculate expected vote length: (COMMITTEE_SIZE * ROUND_SIZE_IN_EPOCHS) / 4
99104
uint256 totalValidators = slashingProposer.COMMITTEE_SIZE() * slashingProposer.ROUND_SIZE_IN_EPOCHS();
@@ -335,10 +340,18 @@ contract SlashingTest is TestBase {
335340
slashingProposer.executeRound(firstSlashingRound, committees);
336341

337342
// Calculate actual slash amount (limited by max 3 units)
338-
uint256 slashUnits = slashAmount1 / slashingProposer.SLASHING_UNIT();
339-
if (slashUnits == 0) slashUnits = 1; // Minimum 1 unit
340-
if (slashUnits > 3) slashUnits = 3; // Maximum 3 units
341-
uint256 actualSlashAmount = slashUnits * slashingProposer.SLASHING_UNIT();
343+
uint256 slashUnits;
344+
uint256 actualSlashAmount;
345+
if (slashAmount1 >= slashingProposer.SLASH_AMOUNT_LARGE()) {
346+
slashUnits = 3;
347+
actualSlashAmount = slashingProposer.SLASH_AMOUNT_LARGE();
348+
} else if (slashAmount1 >= slashingProposer.SLASH_AMOUNT_MEDIUM()) {
349+
slashUnits = 2;
350+
actualSlashAmount = slashingProposer.SLASH_AMOUNT_MEDIUM();
351+
} else {
352+
slashUnits = 1;
353+
actualSlashAmount = slashingProposer.SLASH_AMOUNT_SMALL();
354+
}
342355

343356
// Check balances
344357
for (uint256 i = 0; i < howManyToSlash; i++) {

l1-contracts/test/harnesses/TestConstants.sol

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ library TestConstants {
2525
uint256 internal constant AZTEC_SLASHING_EXECUTION_DELAY_IN_ROUNDS = 0;
2626
uint256 internal constant AZTEC_SLASHING_OFFSET_IN_ROUNDS = 2;
2727
address internal constant AZTEC_SLASHING_VETOER = address(0);
28-
uint256 internal constant AZTEC_SLASHING_UNIT = 20e18;
28+
uint256 internal constant AZTEC_SLASH_AMOUNT_SMALL = 20e18;
29+
uint256 internal constant AZTEC_SLASH_AMOUNT_MEDIUM = 40e18;
30+
uint256 internal constant AZTEC_SLASH_AMOUNT_LARGE = 60e18;
2931
uint256 internal constant AZTEC_MANA_TARGET = 100_000_000;
3032
uint256 internal constant AZTEC_ENTRY_QUEUE_FLUSH_SIZE_MIN = 4;
3133
uint256 internal constant AZTEC_ENTRY_QUEUE_FLUSH_SIZE_QUOTIENT = 2;
@@ -106,7 +108,7 @@ library TestConstants {
106108
rewardConfig: getRewardConfig(),
107109
rewardBoostConfig: getRewardBoostConfig(),
108110
stakingQueueConfig: getStakingQueueConfig(),
109-
slashingUnit: AZTEC_SLASHING_UNIT,
111+
slashAmounts: [AZTEC_SLASH_AMOUNT_SMALL, AZTEC_SLASH_AMOUNT_MEDIUM, AZTEC_SLASH_AMOUNT_LARGE],
110112
slasherFlavor: SlasherFlavor.EMPIRE
111113
});
112114

l1-contracts/test/slashing/TallySlashingProposer.t.sol

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,11 @@ contract TallySlashingProposerTest is TestBase {
8686
RollupBuilder builder = new RollupBuilder(address(this)).setValidators(initialValidators).setTargetCommitteeSize(
8787
COMMITTEE_SIZE
8888
).setSlashingQuorum(QUORUM).setSlashingRoundSize(ROUND_SIZE).setSlashingLifetimeInRounds(LIFETIME_IN_ROUNDS)
89-
.setSlashingExecutionDelayInRounds(EXECUTION_DELAY_IN_ROUNDS).setEpochDuration(EPOCH_DURATION).setSlashingUnit(
89+
.setSlashingExecutionDelayInRounds(EXECUTION_DELAY_IN_ROUNDS).setEpochDuration(EPOCH_DURATION).setSlashAmountSmall(
9090
SLASHING_UNIT
91-
).setSlasherFlavor(SlasherFlavor.TALLY);
91+
).setSlashAmountMedium(SLASHING_UNIT * 2).setSlashAmountLarge(SLASHING_UNIT * 3).setSlasherFlavor(
92+
SlasherFlavor.TALLY
93+
);
9294
builder.deploy();
9395

9496
rollup = builder.getConfig().rollup;

0 commit comments

Comments
 (0)