Skip to content

Commit

Permalink
Merge pull request #604 from morph-l2/stake-msg
Browse files Browse the repository at this point in the history
Add nonce for L1 -> L2 staker msg
  • Loading branch information
SegueII authored Nov 15, 2024
2 parents 65b99be + 1beb812 commit e24f4a1
Show file tree
Hide file tree
Showing 12 changed files with 324 additions and 159 deletions.
2 changes: 1 addition & 1 deletion bindings/bin/l1staking_deployed.hex

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion bindings/bin/l2staking_deployed.hex

Large diffs are not rendered by default.

35 changes: 33 additions & 2 deletions bindings/bindings/l1staking.go

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions bindings/bindings/l1staking_more.go

Large diffs are not rendered by default.

125 changes: 99 additions & 26 deletions bindings/bindings/l2staking.go

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions bindings/bindings/l2staking_more.go

Large diffs are not rendered by default.

19 changes: 16 additions & 3 deletions contracts/contracts/l1/staking/L1Staking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ contract L1Staking is IL1Staking, Staking, OwnableUpgradeable, ReentrancyGuardUp
/// @notice challenge deposit value
uint256 public challengeDeposit;

/// @notice nonce of staking L1 => L2 msg
uint256 public nonce;

/**********************
* Function Modifiers *
**********************/
Expand Down Expand Up @@ -219,6 +222,9 @@ contract L1Staking is IL1Staking, Staking, OwnableUpgradeable, ReentrancyGuardUp

uint256 valueSum;
for (uint256 i = 0; i < sequencers.length; i++) {
if (sequencers[i] == address(0)) {
continue;
}
if (withdrawals[sequencers[i]] > 0) {
delete withdrawals[sequencers[i]];
valueSum += stakingValue;
Expand Down Expand Up @@ -475,9 +481,10 @@ contract L1Staking is IL1Staking, Staking, OwnableUpgradeable, ReentrancyGuardUp
MESSENGER.sendMessage(
address(OTHER_STAKING),
0,
abi.encodeCall(IL2Staking.addStaker, (add)),
abi.encodeCall(IL2Staking.addStaker, (nonce, add)),
gasLimitAddStaker
);
nonce = nonce + 1;
}

/// @notice remove stakers
Expand All @@ -486,16 +493,22 @@ contract L1Staking is IL1Staking, Staking, OwnableUpgradeable, ReentrancyGuardUp
MESSENGER.sendMessage(
address(OTHER_STAKING),
0,
abi.encodeCall(IL2Staking.removeStakers, (remove)),
abi.encodeCall(IL2Staking.removeStakers, (nonce, remove)),
gasLimitRemoveStakers
);
nonce = nonce + 1;
}

/// @notice clean staker store
function _cleanStakerStore() internal {
uint256 i = 0;
while (i < deleteList.length) {
if (deleteableHeight[deleteList[i]] <= block.number) {
if (deleteList[i] == address(0)) {
// clean deleteList
delete deleteableHeight[deleteList[i]];
deleteList[i] = deleteList[deleteList.length - 1];
deleteList.pop();
} else if (deleteableHeight[deleteList[i]] <= block.number) {
// clean stakerSet
delete stakerSet[stakerIndexes[deleteList[i]] - 1];
delete stakerIndexes[deleteList[i]];
Expand Down
10 changes: 6 additions & 4 deletions contracts/contracts/l2/staking/IL2Staking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,14 @@ interface IL2Staking {
*****************************/

/// @notice add staker, sync from L1
/// @param add staker to add. {addr, tmKey, blsKey}
function addStaker(Types.StakerInfo calldata add) external;
/// @param nonce msg nonce
/// @param add staker to add. {addr, tmKey, blsKey}
function addStaker(uint256 nonce, Types.StakerInfo calldata add) external;

/// @notice remove stakers, sync from L1
/// @param remove staker to remove
function removeStakers(address[] calldata remove) external;
/// @param nonce msg nonce
/// @param remove staker to remove
function removeStakers(uint256 nonce, address[] calldata remove) external;

/// @notice setCommissionRate set delegate commission percentage
/// @param commission commission percentage, denominator is 100
Expand Down
73 changes: 69 additions & 4 deletions contracts/contracts/l2/staking/L2Staking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ contract L2Staking is IL2Staking, Staking, OwnableUpgradeable, ReentrancyGuardUp
/// @notice delegator's undelegations
mapping(address delegator => Undelegation[]) public undelegations;

/// @notice nonce of staking L1 => L2 msg
uint256 public nonce;

/**********************
* Function Modifiers *
**********************/
Expand All @@ -94,6 +97,12 @@ contract L2Staking is IL2Staking, Staking, OwnableUpgradeable, ReentrancyGuardUp
_;
}

/// @notice check nonce
modifier checkNonce(uint256 _nonce) {
require(_nonce == nonce, "invalid nonce");
_;
}

/***************
* Constructor *
***************/
Expand Down Expand Up @@ -154,8 +163,10 @@ contract L2Staking is IL2Staking, Staking, OwnableUpgradeable, ReentrancyGuardUp
************************/

/// @notice add staker, sync from L1
/// @param add staker to add. {addr, tmKey, blsKey}
function addStaker(Types.StakerInfo calldata add) external onlyOtherStaking {
/// @param _nonce msg nonce
/// @param add staker to add. {addr, tmKey, blsKey}
function addStaker(uint256 _nonce, Types.StakerInfo calldata add) external onlyOtherStaking checkNonce(_nonce) {
nonce = _nonce + 1;
if (stakerRankings[add.addr] == 0) {
stakerAddresses.push(add.addr);
stakerRankings[add.addr] = stakerAddresses.length;
Expand All @@ -169,8 +180,62 @@ contract L2Staking is IL2Staking, Staking, OwnableUpgradeable, ReentrancyGuardUp
}

/// @notice remove stakers, sync from L1. If new sequencer set is nil, layer2 will stop producing blocks
/// @param remove staker to remove
function removeStakers(address[] calldata remove) external onlyOtherStaking {
/// @param _nonce msg nonce
/// @param remove staker to remove
function removeStakers(uint256 _nonce, address[] calldata remove) external onlyOtherStaking checkNonce(_nonce) {
nonce = _nonce + 1;
bool updateSequencerSet = false;
for (uint256 i = 0; i < remove.length; i++) {
if (stakerRankings[remove[i]] <= latestSequencerSetSize) {
updateSequencerSet = true;
}

if (stakerRankings[remove[i]] > 0) {
// update stakerRankings
for (uint256 j = stakerRankings[remove[i]] - 1; j < stakerAddresses.length - 1; j++) {
stakerAddresses[j] = stakerAddresses[j + 1];
stakerRankings[stakerAddresses[j]] -= 1;
}
stakerAddresses.pop();
delete stakerRankings[remove[i]];

// update candidateNumber
if (stakerDelegations[remove[i]] > 0) {
candidateNumber -= 1;
}
}

delete stakers[remove[i]];
}
emit StakerRemoved(remove);

if (updateSequencerSet) {
_updateSequencerSet();
}
}

/// @notice add staker. Only can be called when a serious bug causes L1 and L2 data to be out of sync
/// @param _nonce msg nonce
/// @param add staker to add. {addr, tmKey, blsKey}
function emergencyAddStaker(uint256 _nonce, Types.StakerInfo calldata add) external onlyOwner checkNonce(_nonce) {
nonce = _nonce + 1;
if (stakerRankings[add.addr] == 0) {
stakerAddresses.push(add.addr);
stakerRankings[add.addr] = stakerAddresses.length;
}
stakers[add.addr] = add;
emit StakerAdded(add.addr, add.tmKey, add.blsKey);

if (!rewardStarted && stakerAddresses.length <= sequencerSetMaxSize) {
_updateSequencerSet();
}
}

/// @notice remove stakers. Only can be called when a serious bug causes L1 and L2 data to be out of sync
/// @param _nonce msg nonce
/// @param remove staker to remove
function emergencyRemoveStakers(uint256 _nonce, address[] calldata remove) external onlyOwner checkNonce(_nonce) {
nonce = _nonce + 1;
bool updateSequencerSet = false;
for (uint256 i = 0; i < remove.length; i++) {
if (stakerRankings[remove[i]] <= latestSequencerSetSize) {
Expand Down
6 changes: 4 additions & 2 deletions contracts/contracts/test/Gov.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,12 @@ contract GovTest is L2StakingBaseTest {
abi.encode(address(l2Staking.OTHER_STAKING()))
);
hevm.startPrank(address(l2CrossDomainMessenger));
uint256 nonce = 0;
for (uint256 i = SEQUENCER_SIZE; i < SEQUENCER_SIZE * 2; i++) {
address staker = address(uint160(beginSeq + i));
Types.StakerInfo memory stakerInfo = ffi.generateStakerInfo(staker);
l2Staking.addStaker(stakerInfo);
l2Staking.addStaker(nonce, stakerInfo);
nonce++;
}

// remove old sequencer
Expand All @@ -242,7 +244,7 @@ contract GovTest is L2StakingBaseTest {
address staker = address(uint160(beginSeq + i));
removed[i] = staker;
}
l2Staking.removeStakers(removed);
l2Staking.removeStakers(nonce, removed);
hevm.stopPrank();

(, executed) = gov.proposalInfos(proposalID);
Expand Down
6 changes: 0 additions & 6 deletions contracts/contracts/test/L1Staking.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -387,12 +387,6 @@ contract StakingTest is L1MessageBaseTest {
assertEq(stakersAddr.length, stakersConvert.length);
assertEq(stakersAddr[0], stakersConvert[0]);
assertEq(stakersAddr[stakersAddr.length - 1], stakersConvert[stakersConvert.length - 1]);

// console.logString("......................");
// console.logUint(bitmap);
// console.logUint(stakersAddr.length);
// console.logUint(stakersConvert.length);
// console.logString("......................");
}

function test_slash_succeeds() external {
Expand Down
Loading

0 comments on commit e24f4a1

Please sign in to comment.