diff --git a/contracts/child/NetworkParams.sol b/contracts/child/NetworkParams.sol index 2a8cc416..5caf5be1 100644 --- a/contracts/child/NetworkParams.sol +++ b/contracts/child/NetworkParams.sol @@ -42,7 +42,7 @@ contract NetworkParams is Ownable2Step, Initializable { event NewEpochSize(uint256 indexed size); event NewEpochReward(uint256 indexed reward); event NewMinValidatorSetSize(uint256 indexed minValidatorSet); - event NewMaxValdidatorSetSize(uint256 indexed maxValidatorSet); + event NewMaxValidatorSetSize(uint256 indexed maxValidatorSet); event NewWithdrawalWaitPeriod(uint256 indexed withdrawalPeriod); event NewBlockTime(uint256 indexed blockTime); event NewBlockTimeDrift(uint256 indexed blockTimeDrift); @@ -144,7 +144,7 @@ contract NetworkParams is Ownable2Step, Initializable { require(newMaxValidatorSetSize != 0, "NetworkParams: INVALID_MAX_VALIDATOR_SET_SIZE"); maxValidatorSetSize = newMaxValidatorSetSize; - emit NewMaxValdidatorSetSize(newMaxValidatorSetSize); + emit NewMaxValidatorSetSize(newMaxValidatorSetSize); } /** diff --git a/contracts/child/validator/RewardPool.sol b/contracts/child/validator/RewardPool.sol index 3b0be195..bb43487f 100644 --- a/contracts/child/validator/RewardPool.sol +++ b/contracts/child/validator/RewardPool.sol @@ -42,11 +42,10 @@ contract RewardPool is IRewardPool, System, Initializable { /** * @inheritdoc IRewardPool */ - function distributeRewardFor(uint256 epochId, Uptime[] calldata uptime) external onlySystemCall { + function distributeRewardFor(uint256 epochId, Uptime[] calldata uptime, uint256 epochSize) external onlySystemCall { require(paidRewardPerEpoch[epochId] == 0, "REWARD_ALREADY_DISTRIBUTED"); uint256 totalBlocks = validatorSet.totalBlocks(epochId); require(totalBlocks != 0, "EPOCH_NOT_COMMITTED"); - uint256 epochSize = networkParams.epochSize(); // slither-disable-next-line divide-before-multiply uint256 reward = (networkParams.epochReward() * totalBlocks) / epochSize; // TODO disincentivize long epoch times diff --git a/contracts/child/validator/ValidatorSet.sol b/contracts/child/validator/ValidatorSet.sol index d9ad911f..771372e3 100644 --- a/contracts/child/validator/ValidatorSet.sol +++ b/contracts/child/validator/ValidatorSet.sol @@ -56,14 +56,11 @@ contract ValidatorSet is IValidatorSet, ERC20VotesUpgradeable, System { /** * @inheritdoc IValidatorSet */ - function commitEpoch(uint256 id, Epoch calldata epoch) external onlySystemCall { + function commitEpoch(uint256 id, Epoch calldata epoch, uint256 epochSize) external onlySystemCall { uint256 newEpochId = currentEpochId++; require(id == newEpochId, "UNEXPECTED_EPOCH_ID"); require(epoch.endBlock > epoch.startBlock, "NO_BLOCKS_COMMITTED"); - require( - (epoch.endBlock - epoch.startBlock + 1) % networkParams.epochSize() == 0, - "EPOCH_MUST_BE_DIVISIBLE_BY_EPOCH_SIZE" - ); + require((epoch.endBlock - epoch.startBlock + 1) % epochSize == 0, "EPOCH_MUST_BE_DIVISIBLE_BY_EPOCH_SIZE"); require(epochs[newEpochId - 1].endBlock + 1 == epoch.startBlock, "INVALID_START_BLOCK"); epochs[newEpochId] = epoch; _commitBlockNumbers[newEpochId] = block.number; diff --git a/contracts/interfaces/child/validator/IRewardPool.sol b/contracts/interfaces/child/validator/IRewardPool.sol index 376059b1..5479e5eb 100644 --- a/contracts/interfaces/child/validator/IRewardPool.sol +++ b/contracts/interfaces/child/validator/IRewardPool.sol @@ -20,7 +20,7 @@ interface IRewardPool { /// @notice distributes reward for the given epoch /// @dev transfers funds from sender to this contract /// @param uptime uptime data for every validator - function distributeRewardFor(uint256 epochId, Uptime[] calldata uptime) external; + function distributeRewardFor(uint256 epochId, Uptime[] calldata uptime, uint256 epochSize) external; /// @notice withdraws pending rewards for the sender (validator) function withdrawReward() external; diff --git a/contracts/interfaces/child/validator/IValidatorSet.sol b/contracts/interfaces/child/validator/IValidatorSet.sol index ad30828b..d9fefdcd 100644 --- a/contracts/interfaces/child/validator/IValidatorSet.sol +++ b/contracts/interfaces/child/validator/IValidatorSet.sol @@ -28,7 +28,7 @@ interface IValidatorSet is IStateReceiver { /// @notice commits a new epoch /// @dev system call - function commitEpoch(uint256 id, Epoch calldata epoch) external; + function commitEpoch(uint256 id, Epoch calldata epoch, uint256 epochSize) external; /// @notice allows a validator to announce their intention to withdraw a given amount of tokens /// @dev initializes a waiting period before the tokens can be withdrawn diff --git a/test/forge/child/validator/RewardPool.t.sol b/test/forge/child/validator/RewardPool.t.sol index d8196e06..652fccf5 100644 --- a/test/forge/child/validator/RewardPool.t.sol +++ b/test/forge/child/validator/RewardPool.t.sol @@ -17,12 +17,13 @@ abstract contract Uninitialized is Test { RewardPool pool; address rewardWallet = makeAddr("rewardWallet"); address alice = makeAddr("alice"); + uint256 epochSize = 64; NetworkParams networkParams; function setUp() public virtual { networkParams = new NetworkParams(); - networkParams.initialize(NetworkParams.InitParams(address(1), 1, 64, 1 ether, 1, 1, 1, 1, 1, 1, 1, 1)); + networkParams.initialize(NetworkParams.InitParams(address(1), 1, 1, 1 ether, 1, 1, 1, 1, 1, 1, 1, 1)); token = new MockERC20(); validatorSet = new ValidatorSet(); @@ -32,7 +33,7 @@ abstract contract Uninitialized is Test { validatorSet.initialize(address(1), address(1), address(1), address(networkParams), init); Epoch memory epoch = Epoch({startBlock: 1, endBlock: 64, epochRoot: bytes32(0)}); vm.prank(SYSTEM); - validatorSet.commitEpoch(1, epoch); + validatorSet.commitEpoch(1, epoch, epochSize); vm.roll(block.number + 1); pool = new RewardPool(); token.mint(rewardWallet, 1000 ether); @@ -55,7 +56,7 @@ abstract contract Distributed is Initialized { uptime[0] = Uptime({validator: address(this), signedBlocks: 64}); uptime[1] = Uptime({validator: alice, signedBlocks: 64}); vm.prank(SYSTEM); - pool.distributeRewardFor(1, uptime); + pool.distributeRewardFor(1, uptime, epochSize); } } @@ -73,21 +74,21 @@ contract RewardPool_Distribute is Initialized { function test_RevertOnlySystem() public { vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, "SYSTEMCALL")); - pool.distributeRewardFor(1, new Uptime[](0)); + pool.distributeRewardFor(1, new Uptime[](0), epochSize); } function test_RevertGenesisEpoch() public { Uptime[] memory uptime = new Uptime[](0); vm.expectRevert("EPOCH_NOT_COMMITTED"); vm.prank(SYSTEM); - pool.distributeRewardFor(0, uptime); + pool.distributeRewardFor(0, uptime, epochSize); } function test_RevertFutureEpoch() public { Uptime[] memory uptime = new Uptime[](0); vm.expectRevert("EPOCH_NOT_COMMITTED"); vm.prank(SYSTEM); - pool.distributeRewardFor(2, uptime); + pool.distributeRewardFor(2, uptime, epochSize); } function test_RevertSignedBlocksExceedsTotalBlocks() public { @@ -95,7 +96,7 @@ contract RewardPool_Distribute is Initialized { uptime[0] = Uptime({validator: address(this), signedBlocks: 65}); vm.prank(SYSTEM); vm.expectRevert("SIGNED_BLOCKS_EXCEEDS_TOTAL"); - pool.distributeRewardFor(1, uptime); + pool.distributeRewardFor(1, uptime, epochSize); } function test_DistributeRewards(uint256 epochReward) public { @@ -111,7 +112,7 @@ contract RewardPool_Distribute is Initialized { vm.prank(SYSTEM); vm.expectEmit(true, true, true, true); emit RewardDistributed(1, totalReward); - pool.distributeRewardFor(1, uptime); + pool.distributeRewardFor(1, uptime, epochSize); assertEq(pool.pendingRewards(address(this)), reward1); assertEq(pool.pendingRewards(alice), reward2); assertEq(pool.paidRewardPerEpoch(1), totalReward); @@ -123,7 +124,7 @@ contract RewardPool_DuplicateDistribution is Distributed { Uptime[] memory uptime = new Uptime[](0); vm.startPrank(SYSTEM); vm.expectRevert("REWARD_ALREADY_DISTRIBUTED"); - pool.distributeRewardFor(1, uptime); + pool.distributeRewardFor(1, uptime, epochSize); } } diff --git a/test/forge/child/validator/ValidatorSet.t.sol b/test/forge/child/validator/ValidatorSet.t.sol index ee79c97b..24d9e4d7 100644 --- a/test/forge/child/validator/ValidatorSet.t.sol +++ b/test/forge/child/validator/ValidatorSet.t.sol @@ -24,7 +24,7 @@ abstract contract Uninitialized is Test { function setUp() public virtual { networkParams = new NetworkParams(); - networkParams.initialize(NetworkParams.InitParams(address(1), 1, epochSize, 1 ether, 1, 1, 1, 1, 1, 1, 1, 1)); + networkParams.initialize(NetworkParams.InitParams(address(1), 1, 1, 1 ether, 1, 1, 1, 1, 1, 1, 1, 1)); stateSender = new L2StateSender(); validatorSet = new ValidatorSet(); @@ -47,7 +47,7 @@ abstract contract Committed is Initialized { _beforeCommit(); Epoch memory epoch = Epoch({startBlock: 1, endBlock: 64, epochRoot: bytes32(0)}); vm.prank(SYSTEM); - validatorSet.commitEpoch(1, epoch); + validatorSet.commitEpoch(1, epoch, epochSize); vm.roll(block.number + 1); _afterCommit(); } @@ -77,7 +77,7 @@ contract ValidatorSet_CommitEpoch is Initialized { function test_RevertOnlySystemCall() public { Epoch memory epoch = Epoch({startBlock: 1, endBlock: 64, epochRoot: bytes32(0)}); vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, "SYSTEMCALL")); - validatorSet.commitEpoch(1, epoch); + validatorSet.commitEpoch(1, epoch, epochSize); } function test_RevertInvalidEpochId(uint256 id) public { @@ -85,7 +85,7 @@ contract ValidatorSet_CommitEpoch is Initialized { Epoch memory epoch = Epoch({startBlock: 1, endBlock: 64, epochRoot: bytes32(0)}); vm.expectRevert("UNEXPECTED_EPOCH_ID"); vm.prank(SYSTEM); - validatorSet.commitEpoch(id, epoch); + validatorSet.commitEpoch(id, epoch, epochSize); } function test_RevertNoBlocksCommitted(uint256 startBlock, uint256 endBlock) public { @@ -93,7 +93,7 @@ contract ValidatorSet_CommitEpoch is Initialized { Epoch memory epoch = Epoch({startBlock: startBlock, endBlock: endBlock, epochRoot: bytes32(0)}); vm.expectRevert("NO_BLOCKS_COMMITTED"); vm.prank(SYSTEM); - validatorSet.commitEpoch(1, epoch); + validatorSet.commitEpoch(1, epoch, epochSize); } function test_RevertEpochSize(uint256 startBlock, uint256 endBlock) public { @@ -102,14 +102,14 @@ contract ValidatorSet_CommitEpoch is Initialized { Epoch memory epoch = Epoch({startBlock: startBlock, endBlock: endBlock, epochRoot: bytes32(0)}); vm.expectRevert("EPOCH_MUST_BE_DIVISIBLE_BY_EPOCH_SIZE"); vm.prank(SYSTEM); - validatorSet.commitEpoch(1, epoch); + validatorSet.commitEpoch(1, epoch, epochSize); } function test_RevertInvalidStartBlock() public { Epoch memory epoch = Epoch({startBlock: 0, endBlock: 63, epochRoot: bytes32(0)}); vm.expectRevert("INVALID_START_BLOCK"); vm.prank(SYSTEM); - validatorSet.commitEpoch(1, epoch); + validatorSet.commitEpoch(1, epoch, epochSize); } function test_CommitEpoch() public { @@ -117,7 +117,7 @@ contract ValidatorSet_CommitEpoch is Initialized { vm.prank(SYSTEM); vm.expectEmit(true, true, true, true); emit NewEpoch(1, 1, 64, bytes32(0)); - validatorSet.commitEpoch(1, epoch); + validatorSet.commitEpoch(1, epoch, epochSize); assertEq(validatorSet.currentEpochId(), 2); assertEq(validatorSet.epochEndBlocks(1), 64); assertEq(validatorSet.totalBlocks(1), 64);