Skip to content

Commit

Permalink
feat(contracts): support validator system V2 from genesis
Browse files Browse the repository at this point in the history
  • Loading branch information
seolaoh committed May 21, 2024
1 parent 6ce71fb commit cffe3ed
Show file tree
Hide file tree
Showing 15 changed files with 246 additions and 261 deletions.
90 changes: 45 additions & 45 deletions kroma-bindings/bindings/l2outputoracle.go

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions kroma-bindings/bindings/l2outputoracle_more.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion kroma-bindings/bindings/validatormanager.go

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions kroma-bindings/bindings/validatormanager_more.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion kroma-bindings/bindings/validatorpool.go

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions kroma-bindings/bindings/validatorpool_more.go

Large diffs are not rendered by default.

270 changes: 135 additions & 135 deletions packages/contracts/.gas-snapshot

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions packages/contracts/.storage-layout
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,14 @@
➡ contracts/L1/L2OutputOracle.sol:L2OutputOracle
=======================

| Name | Type | Slot | Offset | Bytes | Contract |
|----------------------------|---------------------------------|------|--------|-------|------------------------------------------------|
| _initialized | uint8 | 0 | 0 | 1 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
| _initializing | bool | 0 | 1 | 1 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
| startingBlockNumber | uint256 | 1 | 0 | 32 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
| startingTimestamp | uint256 | 2 | 0 | 32 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
| l2Outputs | struct Types.CheckpointOutput[] | 3 | 0 | 32 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
| latestFinalizedOutputIndex | uint256 | 4 | 0 | 32 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
| Name | Type | Slot | Offset | Bytes | Contract |
|-------------------------|---------------------------------|------|--------|-------|------------------------------------------------|
| _initialized | uint8 | 0 | 0 | 1 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
| _initializing | bool | 0 | 1 | 1 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
| startingBlockNumber | uint256 | 1 | 0 | 32 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
| startingTimestamp | uint256 | 2 | 0 | 32 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
| l2Outputs | struct Types.CheckpointOutput[] | 3 | 0 | 32 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
| nextFinalizeOutputIndex | uint256 | 4 | 0 | 32 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |

=======================
➡ contracts/L1/KromaPortal.sol:KromaPortal
Expand Down
20 changes: 10 additions & 10 deletions packages/contracts/contracts/L1/L2OutputOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ contract L2OutputOracle is Initializable, ISemver {
Types.CheckpointOutput[] internal l2Outputs;

/**
* @notice The output index of the latest finalized output.
* @notice The output index of the next finalization target output.
*/
uint256 public latestFinalizedOutputIndex;
uint256 public nextFinalizeOutputIndex;

/**
* @notice Emitted when an output is submitted.
Expand Down Expand Up @@ -279,26 +279,26 @@ contract L2OutputOracle is Initializable, ISemver {
}

/**
* @notice Updates the latest finalized output index. This function may only be called by the
* validator pool contract before terminated, after that by the validator manager
* @notice Updates the next output index to be finalized. This function may only be called by
* the validator pool contract before terminated, after that by the validator manager
* contract.
*
* @param _outputIndex Index of the latest finalized output.
* @param _outputIndex Index of the next output to be finalized.
*/
function setLatestFinalizedOutputIndex(uint256 _outputIndex) external {
if (VALIDATOR_POOL.isTerminated(_outputIndex)) {
function setNextFinalizeOutputIndex(uint256 _outputIndex) external {
if (VALIDATOR_POOL.isTerminated(_outputIndex - 1)) {
require(
msg.sender == address(VALIDATOR_MANAGER),
"L2OutputOracle: only the validator manager contract can set latest finalized output index"
"L2OutputOracle: only the validator manager contract can set next finalize output index"
);
} else {
require(
msg.sender == address(VALIDATOR_POOL),
"L2OutputOracle: only the validator pool contract can set latest finalized output index"
"L2OutputOracle: only the validator pool contract can set next finalize output index"
);
}

latestFinalizedOutputIndex = _outputIndex;
nextFinalizeOutputIndex = _outputIndex;
}

/**
Expand Down
16 changes: 9 additions & 7 deletions packages/contracts/contracts/L1/ValidatorManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,9 @@ contract ValidatorManager is ISemver, IValidatorManager {
}

// Select the next priority validator.
_updatePriorityValidator();
unchecked {
_updatePriorityValidator();
}
}

/**
Expand Down Expand Up @@ -302,7 +304,7 @@ contract ValidatorManager is ISemver, IValidatorManager {

_sendToJail(loser);

if (L2_ORACLE.latestFinalizedOutputIndex() < outputIndex) {
if (L2_ORACLE.nextFinalizeOutputIndex() <= outputIndex) {
// If output is not rewarded yet, add slashing asset to the pending challenge reward.
unchecked {
_pendingChallengeReward[outputIndex] += challengeReward;
Expand Down Expand Up @@ -490,7 +492,7 @@ contract ValidatorManager is ISemver, IValidatorManager {
* @return Whether the reward distribution is done at least once or not.
*/
function _distributeReward() private returns (bool) {
uint256 outputIndex = L2_ORACLE.latestFinalizedOutputIndex() + 1;
uint256 outputIndex = L2_ORACLE.nextFinalizeOutputIndex();
uint256 latestOutputIndex = L2_ORACLE.latestOutputIndex();

if (!L2_ORACLE.VALIDATOR_POOL().isTerminated(outputIndex)) {
Expand Down Expand Up @@ -539,7 +541,7 @@ contract ValidatorManager is ISemver, IValidatorManager {
}

if (finalizedOutputNum > 0) {
L2_ORACLE.setLatestFinalizedOutputIndex(outputIndex - 1);
L2_ORACLE.setNextFinalizeOutputIndex(outputIndex);

return true;
}
Expand Down Expand Up @@ -600,11 +602,11 @@ contract ValidatorManager is ISemver, IValidatorManager {
*/
function _updatePriorityValidator() private {
uint120 weightSum = activatedValidatorTotalWeight();
uint256 nextFinalizeOutputIndex = L2_ORACLE.nextFinalizeOutputIndex();

if (weightSum > 0) {
uint256 latestFinalizedOutputIndex = L2_ORACLE.latestFinalizedOutputIndex();
if (weightSum > 0 && nextFinalizeOutputIndex > 0) {
Types.CheckpointOutput memory output = L2_ORACLE.getL2Output(
latestFinalizedOutputIndex
nextFinalizeOutputIndex - 1
);

uint120 weight = uint120(
Expand Down
4 changes: 2 additions & 2 deletions packages/contracts/contracts/L1/ValidatorPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -416,8 +416,8 @@ contract ValidatorPool is ReentrancyGuardUpgradeable, ISemver {
nextUnbondOutputIndex = outputIndex;
}

// Set the latest finalized output index in L2OutputOracle.
L2_ORACLE.setLatestFinalizedOutputIndex(outputIndex - 1);
// Set the next output index to be finalized in L2OutputOracle.
L2_ORACLE.setNextFinalizeOutputIndex(outputIndex);

return true;
}
Expand Down
4 changes: 2 additions & 2 deletions packages/contracts/contracts/test/AssetManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,12 @@ contract AssetManagerTest is ValidatorSystemUpgrade_Initializer {
// KRO bridged from L2 Validator Reward Vault
kro.transfer(address(assetManager), 1e22);

// Submit until terminateOutputIndex and set it latest finalized output
// Submit until terminateOutputIndex and set next output index to be finalized after it
for (uint256 i = mockOracle.nextOutputIndex(); i <= terminateOutputIndex; i++) {
_submitOutputRoot(pool.nextValidator());
}
vm.warp(mockOracle.finalizedAt(terminateOutputIndex));
mockOracle.mockSetLatestFinalizedOutputIndex(terminateOutputIndex);
mockOracle.mockSetNextFinalizeOutputIndex(terminateOutputIndex + 1);
}

function _submitOutputRoot(address _validator) internal {
Expand Down
40 changes: 13 additions & 27 deletions packages/contracts/contracts/test/L2OutputOracle.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -482,50 +482,36 @@ contract L2OutputOracle_ValidatorSystemUpgrade_Test is ValidatorSystemUpgrade_In
oracle.submitL2Output(outputRoot, nextBlockNumber, 0, 0);
}

function test_setLatestFinalizedOutputIndex_succeeds() external {
function test_setNextFinalizeOutputIndex_succeeds() external {
// Only ValidatorPool can set finalized output before upgrade
uint256 outputIndex = oracle.latestOutputIndex();
vm.prank(address(pool));
oracle.setLatestFinalizedOutputIndex(outputIndex);
oracle.setNextFinalizeOutputIndex(1);
assertEq(oracle.nextFinalizeOutputIndex(), 1);

assertEq(oracle.latestFinalizedOutputIndex(), outputIndex);

// Submit more outputs to progress after upgrade
for (uint256 i = oracle.nextOutputIndex(); i <= terminateOutputIndex + 1; i++) {
_submitL2OutputV1();
}
vm.prank(address(pool));
oracle.setNextFinalizeOutputIndex(terminateOutputIndex + 1);
assertEq(oracle.nextFinalizeOutputIndex(), terminateOutputIndex + 1);

// Now only ValidatorManager can set finalized output after upgrade
vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS());
outputIndex = oracle.latestOutputIndex();
vm.prank(address(valMgr));
oracle.setLatestFinalizedOutputIndex(outputIndex);

assertEq(oracle.latestFinalizedOutputIndex(), outputIndex);
oracle.setNextFinalizeOutputIndex(terminateOutputIndex + 2);
assertEq(oracle.nextFinalizeOutputIndex(), terminateOutputIndex + 2);
}

function test_setLatestFinalizedOutputIndex_wrongCaller_reverts() external {
function test_setNextFinalizeOutputIndex_wrongCaller_reverts() external {
// Only ValidatorPool can set finalized output before upgrade
uint256 outputIndex = oracle.latestOutputIndex();
vm.prank(address(valMgr));
vm.expectRevert(
"L2OutputOracle: only the validator pool contract can set latest finalized output index"
"L2OutputOracle: only the validator pool contract can set next finalize output index"
);
oracle.setLatestFinalizedOutputIndex(outputIndex);

// Submit more outputs to progress after upgrade
for (uint256 i = oracle.nextOutputIndex(); i <= terminateOutputIndex + 1; i++) {
_submitL2OutputV1();
}
oracle.setNextFinalizeOutputIndex(1);

// Now only ValidatorManager can set finalized output after upgrade
vm.warp(block.timestamp + oracle.FINALIZATION_PERIOD_SECONDS());
outputIndex = oracle.latestOutputIndex();
vm.prank(address(pool));
vm.expectRevert(
"L2OutputOracle: only the validator manager contract can set latest finalized output index"
"L2OutputOracle: only the validator manager contract can set next finalize output index"
);
oracle.setLatestFinalizedOutputIndex(outputIndex);
oracle.setNextFinalizeOutputIndex(terminateOutputIndex + 2);
}
}

Expand Down
18 changes: 9 additions & 9 deletions packages/contracts/contracts/test/ValidatorManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ contract MockL2OutputOracle is L2OutputOracle {
l2Outputs[outputIndex].outputRoot = bytes32(0);
}

function mockSetLatestFinalizedOutputIndex(uint256 l2OutputIndex) external {
latestFinalizedOutputIndex = l2OutputIndex;
function mockSetNextFinalizeOutputIndex(uint256 l2OutputIndex) external {
nextFinalizeOutputIndex = l2OutputIndex;
}
}

Expand Down Expand Up @@ -144,14 +144,14 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer {

VKRO_PER_KGH = assetMan.VKRO_PER_KGH();

// Submit until terminateOutputIndex and set it latest finalized output
// Submit until terminateOutputIndex and set next output index to be finalized after it
vm.prank(trusted);
pool.deposit{ value: trusted.balance }();
for (uint256 i = oracle.nextOutputIndex(); i <= terminateOutputIndex; i++) {
_submitL2OutputV1();
}
vm.warp(oracle.finalizedAt(terminateOutputIndex));
mockOracle.mockSetLatestFinalizedOutputIndex(terminateOutputIndex);
mockOracle.mockSetNextFinalizeOutputIndex(terminateOutputIndex + 1);
}

function test_constructor_succeeds() external {
Expand Down Expand Up @@ -388,7 +388,7 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer {
validatorReward
);

assertEq(oracle.latestFinalizedOutputIndex(), terminateOutputIndex + 1);
assertEq(oracle.nextFinalizeOutputIndex(), terminateOutputIndex + 2);
}

function test_afterSubmitL2Output_updatePriorityValidator_succeeds() external {
Expand All @@ -403,8 +403,8 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer {
// Submit the first output which interacts with ValidatorManager
_submitL2OutputV2(false);

// Check if lastest finalized output is not updated
assertEq(oracle.latestFinalizedOutputIndex(), terminateOutputIndex);
// Check if next finalize output is not updated
assertEq(oracle.nextFinalizeOutputIndex(), terminateOutputIndex + 1);
// Check if next priority validator is set in ValidatorManager
address nextValidator = mockValMgr.nextPriorityValidator();
assertTrue(nextValidator != address(0));
Expand All @@ -416,8 +416,8 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer {
_submitL2OutputV2(true);
vm.stopPrank();

// Check if lastest finalized output is updated
assertEq(oracle.latestFinalizedOutputIndex(), terminateOutputIndex + 1);
// Check if next finalize output is updated
assertEq(oracle.nextFinalizeOutputIndex(), terminateOutputIndex + 2);

// Submit 10 outputs
uint256 tries = 10;
Expand Down
14 changes: 7 additions & 7 deletions packages/contracts/contracts/test/ValidatorPool.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ contract ValidatorPoolTest is L2OutputOracle_Initializer {
emit Unbonded(0, firstOutput.submitter, uint128(firstBond.amount));
vm.expectCall(
address(oracle),
abi.encodeWithSelector(L2OutputOracle.setLatestFinalizedOutputIndex.selector, 0)
abi.encodeWithSelector(L2OutputOracle.setNextFinalizeOutputIndex.selector, 1)
);
pool.createBond(nextOutputIndex, expiresAt);
assertEq(pool.balanceOf(firstOutput.submitter), requiredBondAmount);
Expand Down Expand Up @@ -391,8 +391,8 @@ contract ValidatorPoolTest is L2OutputOracle_Initializer {
vm.expectCall(
address(oracle),
abi.encodeWithSelector(
L2OutputOracle.setLatestFinalizedOutputIndex.selector,
outputIndex
L2OutputOracle.setNextFinalizeOutputIndex.selector,
outputIndex + 1
)
);
vm.prank(trusted);
Expand Down Expand Up @@ -465,8 +465,8 @@ contract ValidatorPoolTest is L2OutputOracle_Initializer {
vm.expectCall(
address(oracle),
abi.encodeWithSelector(
L2OutputOracle.setLatestFinalizedOutputIndex.selector,
secondOutputIndex
L2OutputOracle.setNextFinalizeOutputIndex.selector,
secondOutputIndex + 1
)
);
vm.prank(trusted);
Expand Down Expand Up @@ -518,8 +518,8 @@ contract ValidatorPoolTest is L2OutputOracle_Initializer {
bond = pool.getBond(tries - 1);
assertEq(bond.amount, requiredBondAmount);

// check if latest finalized output index is set correctly
assertEq(oracle.latestFinalizedOutputIndex(), outputIndex - 1);
// check if next finalize output index is set correctly
assertEq(oracle.nextFinalizeOutputIndex(), outputIndex);
}

function test_unbond_notExpired_reverts() external {
Expand Down

0 comments on commit cffe3ed

Please sign in to comment.