Skip to content

Commit

Permalink
Merge pull request #45 from symbioticfi/weaken-sequencing
Browse files Browse the repository at this point in the history
Weaken sequencing checks
  • Loading branch information
1kresh authored Sep 26, 2024
2 parents 2d6162e + c385354 commit 24d47af
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 27 deletions.
22 changes: 15 additions & 7 deletions src/contracts/slasher/BaseSlasher.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ abstract contract BaseSlasher is Entity, StaticDelegateCallable, ReentrancyGuard
/**
* @inheritdoc IBaseSlasher
*/
mapping(bytes32 subnetwork => uint48 value) public latestSlashedCaptureTimestamp;
mapping(bytes32 subnetwork => mapping(address operator => uint48 value)) public latestSlashedCaptureTimestamp;

mapping(bytes32 subnetwork => mapping(address operator => Checkpoints.Trace256 amount)) internal _cumulativeSlash;

Expand Down Expand Up @@ -96,7 +96,7 @@ abstract contract BaseSlasher is Entity, StaticDelegateCallable, ReentrancyGuard

if (
captureTimestamp < Time.timestamp() - IVault(vault).epochDuration() || captureTimestamp >= Time.timestamp()
|| captureTimestamp < latestSlashedCaptureTimestamp[subnetwork]
|| captureTimestamp < latestSlashedCaptureTimestamp[subnetwork][operator]
) {
return 0;
}
Expand All @@ -120,15 +120,23 @@ abstract contract BaseSlasher is Entity, StaticDelegateCallable, ReentrancyGuard
}
}

function _checkLatestSlashedCaptureTimestamp(bytes32 subnetwork, uint48 captureTimestamp) internal view {
if (captureTimestamp < latestSlashedCaptureTimestamp[subnetwork]) {
function _checkLatestSlashedCaptureTimestamp(
bytes32 subnetwork,
address operator,
uint48 captureTimestamp
) internal view {
if (captureTimestamp < latestSlashedCaptureTimestamp[subnetwork][operator]) {
revert OutdatedCaptureTimestamp();
}
}

function _updateLatestSlashedCaptureTimestamp(bytes32 subnetwork, uint48 captureTimestamp) internal {
if (latestSlashedCaptureTimestamp[subnetwork] < captureTimestamp) {
latestSlashedCaptureTimestamp[subnetwork] = captureTimestamp;
function _updateLatestSlashedCaptureTimestamp(
bytes32 subnetwork,
address operator,
uint48 captureTimestamp
) internal {
if (latestSlashedCaptureTimestamp[subnetwork][operator] < captureTimestamp) {
latestSlashedCaptureTimestamp[subnetwork][operator] = captureTimestamp;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/contracts/slasher/Slasher.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ contract Slasher is BaseSlasher, ISlasher {
revert InsufficientSlash();
}

_updateLatestSlashedCaptureTimestamp(subnetwork, captureTimestamp);
_updateLatestSlashedCaptureTimestamp(subnetwork, operator, captureTimestamp);

_updateCumulativeSlash(subnetwork, operator, slashedAmount);

Expand Down
4 changes: 2 additions & 2 deletions src/contracts/slasher/VetoSlasher.sol
Original file line number Diff line number Diff line change
Expand Up @@ -154,15 +154,15 @@ contract VetoSlasher is BaseSlasher, IVetoSlasher {
revert SlashPeriodEnded();
}

_checkLatestSlashedCaptureTimestamp(request.subnetwork, request.captureTimestamp);
_checkLatestSlashedCaptureTimestamp(request.subnetwork, request.operator, request.captureTimestamp);

if (request.completed) {
revert SlashRequestCompleted();
}

request.completed = true;

_updateLatestSlashedCaptureTimestamp(request.subnetwork, request.captureTimestamp);
_updateLatestSlashedCaptureTimestamp(request.subnetwork, request.operator, request.captureTimestamp);

slashedAmount = Math.min(
request.amount,
Expand Down
5 changes: 2 additions & 3 deletions src/interfaces/slasher/IBaseSlasher.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,10 @@ interface IBaseSlasher is IEntity {
/**
* @notice Get the latest capture timestamp that was slashed on a subnetwork.
* @param subnetwork full identifier of the subnetwork (address of the network concatenated with the uint96 identifier)
* @param operator address of the operator
* @return latest capture timestamp that was slashed
*/
function latestSlashedCaptureTimestamp(
bytes32 subnetwork
) external view returns (uint48);
function latestSlashedCaptureTimestamp(bytes32 subnetwork, address operator) external view returns (uint48);

/**
* @notice Get a cumulative slash amount for an operator on a subnetwork until a given timestamp (inclusively) using a hint.
Expand Down
15 changes: 7 additions & 8 deletions test/slasher/Slasher.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -230,14 +230,14 @@ contract SlasherTest is Test {
slasher.slashableStake(network.subnetwork(0), alice, uint48(blockTimestamp - 1), ""),
delegator.stakeAt(network.subnetwork(0), alice, uint48(blockTimestamp - 1), "")
);
assertEq(slasher.latestSlashedCaptureTimestamp(network.subnetwork(0)), 0);
assertEq(slasher.latestSlashedCaptureTimestamp(network.subnetwork(0), alice), 0);

assertEq(
Math.min(slashAmount1, delegator.stakeAt(network.subnetwork(0), alice, uint48(blockTimestamp - 1), "")),
_slash(alice, network, alice, slashAmount1, uint48(blockTimestamp - 1), "")
);

assertEq(slasher.latestSlashedCaptureTimestamp(network.subnetwork(0)), uint48(blockTimestamp - 1));
assertEq(slasher.latestSlashedCaptureTimestamp(network.subnetwork(0), alice), uint48(blockTimestamp - 1));
assertEq(slasher.cumulativeSlashAt(alice.subnetwork(0), alice, uint48(blockTimestamp - 1), ""), 0);
assertEq(
slasher.cumulativeSlashAt(alice.subnetwork(0), alice, uint48(blockTimestamp), ""),
Expand All @@ -254,6 +254,7 @@ contract SlasherTest is Test {
- Math.min(slashAmount1, delegator.stakeAt(network.subnetwork(0), alice, uint48(blockTimestamp - 1), ""))
);

assertEq(slasher.latestSlashedCaptureTimestamp(network.subnetwork(0), bob), 0);
assertEq(slasher.slashableStake(network.subnetwork(0), bob, uint48(blockTimestamp - epochDuration - 1), ""), 0);
assertEq(slasher.slashableStake(network.subnetwork(0), bob, uint48(blockTimestamp), ""), 0);
assertEq(
Expand All @@ -266,7 +267,7 @@ contract SlasherTest is Test {
_slash(alice, network, bob, slashAmount2, uint48(blockTimestamp - 1), "")
);

assertEq(slasher.latestSlashedCaptureTimestamp(network.subnetwork(0)), uint48(blockTimestamp - 1));
assertEq(slasher.latestSlashedCaptureTimestamp(network.subnetwork(0), bob), uint48(blockTimestamp - 1));
assertEq(slasher.cumulativeSlashAt(alice.subnetwork(0), bob, uint48(blockTimestamp - 1), ""), 0);
assertEq(
slasher.cumulativeSlashAt(alice.subnetwork(0), bob, uint48(blockTimestamp), ""),
Expand All @@ -293,7 +294,7 @@ contract SlasherTest is Test {
vm.assume(slashAmountReal3 > 0);
assertEq(slashAmountReal3, _slash(alice, network, alice, slashAmount3, uint48(blockTimestamp - 2), ""));

assertEq(slasher.latestSlashedCaptureTimestamp(network.subnetwork(0)), uint48(blockTimestamp - 2));
assertEq(slasher.latestSlashedCaptureTimestamp(network.subnetwork(0), alice), uint48(blockTimestamp - 2));
assertEq(slasher.cumulativeSlashAt(alice.subnetwork(0), alice, uint48(blockTimestamp - 2), ""), 0);
assertEq(
slasher.cumulativeSlashAt(alice.subnetwork(0), alice, uint48(blockTimestamp - 1), ""),
Expand Down Expand Up @@ -612,8 +613,7 @@ contract SlasherTest is Test {
uint256 operatorNetworkLimit1,
uint256 operatorNetworkLimit2,
uint256 slashAmount1,
uint256 slashAmount2,
uint256 slashAmount3
uint256 slashAmount2
) public {
epochDuration = uint48(bound(epochDuration, 2, 10 days));
depositAmount = bound(depositAmount, 1, 100 * 10 ** 18);
Expand All @@ -622,7 +622,6 @@ contract SlasherTest is Test {
operatorNetworkLimit2 = bound(operatorNetworkLimit2, 1, type(uint256).max / 2);
slashAmount1 = bound(slashAmount1, 1, type(uint256).max);
slashAmount2 = bound(slashAmount2, 1, type(uint256).max);
slashAmount3 = bound(slashAmount3, 1, type(uint256).max);

uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp;
blockTimestamp = blockTimestamp + 1_720_700_948;
Expand Down Expand Up @@ -656,7 +655,7 @@ contract SlasherTest is Test {
_slash(alice, network, alice, slashAmount1, uint48(blockTimestamp - 1), "");

vm.expectRevert(ISlasher.InsufficientSlash.selector);
_slash(alice, network, bob, slashAmount2, uint48(blockTimestamp - 2), "");
_slash(alice, network, alice, slashAmount2, uint48(blockTimestamp - 2), "");
}

function test_SlashRevertNotNetworkMiddleware(
Expand Down
12 changes: 6 additions & 6 deletions test/slasher/VetoSlasher.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ contract VetoSlasherTest is Test {

assertTrue(blockTimestamp - uint48(blockTimestamp - 1) <= epochDuration);

assertEq(slasher.latestSlashedCaptureTimestamp(alice.subnetwork(0)), 0);
assertEq(slasher.latestSlashedCaptureTimestamp(alice.subnetwork(0), alice), 0);

assertEq(_executeSlash(alice, 0, ""), slashAmountReal1);

Expand All @@ -640,7 +640,7 @@ contract VetoSlasherTest is Test {
completed_
) = slasher.slashRequests(0);

assertEq(slasher.latestSlashedCaptureTimestamp(alice.subnetwork(0)), captureTimestamp_);
assertEq(slasher.latestSlashedCaptureTimestamp(alice.subnetwork(0), alice), captureTimestamp_);

assertEq(subnetwork_, alice.subnetwork(0));
assertEq(operator_, alice);
Expand Down Expand Up @@ -700,7 +700,7 @@ contract VetoSlasherTest is Test {
completed_
) = slasher.slashRequests(1);

assertEq(slasher.latestSlashedCaptureTimestamp(alice.subnetwork(0)), captureTimestamp_);
assertEq(slasher.latestSlashedCaptureTimestamp(alice.subnetwork(0), alice), captureTimestamp_);

assertEq(subnetwork_, alice.subnetwork(0));
assertEq(operator_, alice);
Expand Down Expand Up @@ -810,7 +810,7 @@ contract VetoSlasherTest is Test {

assertTrue(blockTimestamp - uint48(blockTimestamp - 1) <= epochDuration);

assertEq(slasher.latestSlashedCaptureTimestamp(alice.subnetwork(0)), 0);
assertEq(slasher.latestSlashedCaptureTimestamp(alice.subnetwork(0), alice), 0);

assertEq(_executeSlash(alice, 0, ""), slashAmountReal1);

Expand All @@ -826,7 +826,7 @@ contract VetoSlasherTest is Test {
completed_
) = slasher.slashRequests(0);

assertEq(slasher.latestSlashedCaptureTimestamp(alice.subnetwork(0)), captureTimestamp_);
assertEq(slasher.latestSlashedCaptureTimestamp(alice.subnetwork(0), alice), captureTimestamp_);

assertEq(subnetwork_, alice.subnetwork(0));
assertEq(operator_, alice);
Expand Down Expand Up @@ -859,7 +859,7 @@ contract VetoSlasherTest is Test {
completed_
) = slasher.slashRequests(1);

assertEq(slasher.latestSlashedCaptureTimestamp(alice.subnetwork(0)), captureTimestamp_);
assertEq(slasher.latestSlashedCaptureTimestamp(alice.subnetwork(0), alice), captureTimestamp_);

assertEq(subnetwork_, alice.subnetwork(0));
assertEq(operator_, alice);
Expand Down

0 comments on commit 24d47af

Please sign in to comment.