From e3c1b38819dbce7cdb82f6c92a32063f7ed07880 Mon Sep 17 00:00:00 2001 From: seolaoh Date: Tue, 23 Apr 2024 14:03:13 +0900 Subject: [PATCH 1/8] feat(contracts): apply PR reviews --- kroma-chain-ops/genesis/config.go | 12 +- .../testdata/test-deploy-config-full.json | 2 +- .../contracts/contracts/L1/AssetManager.sol | 15 +- packages/contracts/contracts/L1/Colosseum.sol | 29 ++- .../contracts/L1/ValidatorManager.sol | 101 +++++----- .../L1/interfaces/IValidatorManager.sol | 68 +++---- .../contracts/test/AssetManager.t.sol | 4 +- .../contracts/contracts/test/Colosseum.t.sol | 27 ++- .../contracts/contracts/test/CommonTest.t.sol | 10 +- .../contracts/test/L2OutputOracle.t.sol | 2 +- .../contracts/test/ValidatorManager.t.sol | 187 +++++++++--------- .../deploy-config/devnetL1-template.json | 2 +- .../deploy/L1/019-ValidatorManager.ts | 6 +- packages/contracts/src/deploy-config.ts | 6 +- 14 files changed, 244 insertions(+), 227 deletions(-) diff --git a/kroma-chain-ops/genesis/config.go b/kroma-chain-ops/genesis/config.go index a631e3e01..50602fe0e 100644 --- a/kroma-chain-ops/genesis/config.go +++ b/kroma-chain-ops/genesis/config.go @@ -264,8 +264,8 @@ type DeployConfig struct { ValidatorManagerTrustedValidator common.Address `json:"validatorManagerTrustedValidator"` // ValidatorManagerMinRegisterAmount is the amount of the minimum register amount. ValidatorManagerMinRegisterAmount *hexutil.Big `json:"validatorManagerMinRegisterAmount"` - // ValidatorManagerMinStartAmount is the amount of the minimum start amount. - ValidatorManagerMinStartAmount *hexutil.Big `json:"validatorManagerMinStartAmount"` + // ValidatorManagerMinActivateAmount is the amount of the minimum activation amount. + ValidatorManagerMinActivateAmount *hexutil.Big `json:"validatorManagerMinActivateAmount"` // ValidatorManagerCommissionMinChangeSeconds is the minimum duration of commission change in // seconds. ValidatorManagerCommissionMinChangeSeconds uint64 `json:"validatorManagerCommissionMinChangeSeconds"` @@ -537,11 +537,11 @@ func (d *DeployConfig) Check() error { if d.ValidatorManagerMinRegisterAmount == nil { return fmt.Errorf("%w: ValidatorManagerMinRegisterAmount cannot be nil", ErrInvalidDeployConfig) } - if d.ValidatorManagerMinStartAmount == nil { - return fmt.Errorf("%w: ValidatorManagerMinStartAmount cannot be nil", ErrInvalidDeployConfig) + if d.ValidatorManagerMinActivateAmount == nil { + return fmt.Errorf("%w: ValidatorManagerMinActivateAmount cannot be nil", ErrInvalidDeployConfig) } - if d.ValidatorManagerMinStartAmount.ToInt().Cmp(d.ValidatorManagerMinRegisterAmount.ToInt()) < 0 { - return fmt.Errorf("%w: ValidatorManagerMinStartAmount must equal or more than ValidatorManagerMinRegisterAmount", ErrInvalidDeployConfig) + if d.ValidatorManagerMinActivateAmount.ToInt().Cmp(d.ValidatorManagerMinRegisterAmount.ToInt()) < 0 { + return fmt.Errorf("%w: ValidatorManagerMinActivateAmount must equal or more than ValidatorManagerMinRegisterAmount", ErrInvalidDeployConfig) } if d.ValidatorManagerCommissionMinChangeSeconds == 0 { return fmt.Errorf("%w: ValidatorManagerCommissionMinChangeSeconds cannot be 0", ErrInvalidDeployConfig) diff --git a/kroma-chain-ops/genesis/testdata/test-deploy-config-full.json b/kroma-chain-ops/genesis/testdata/test-deploy-config-full.json index 20139a59a..7f929e56b 100644 --- a/kroma-chain-ops/genesis/testdata/test-deploy-config-full.json +++ b/kroma-chain-ops/genesis/testdata/test-deploy-config-full.json @@ -65,7 +65,7 @@ "validatorPoolTerminateOutputIndex": "0x0", "validatorManagerTrustedValidator": "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", "validatorManagerMinRegisterAmount": "0x1", - "validatorManagerMinStartAmount": "0x2", + "validatorManagerMinActivateAmount": "0x2", "validatorManagerCommissionMinChangeSeconds": 2, "validatorManagerRoundDurationSeconds": 4, "validatorManagerJailPeriodSeconds": 2, diff --git a/packages/contracts/contracts/L1/AssetManager.sol b/packages/contracts/contracts/L1/AssetManager.sol index 6ec04df77..7ad949631 100644 --- a/packages/contracts/contracts/L1/AssetManager.sol +++ b/packages/contracts/contracts/L1/AssetManager.sol @@ -83,7 +83,7 @@ contract AssetManager is ISemver, IERC721Receiver, IAssetManager { /** * @notice Minimum amount to slash. It should be equal or less than - * ValidatorManager.MIN_START_AMOUNT. + * ValidatorManager.MIN_ACTIVATE_AMOUNT. */ uint128 public immutable MIN_SLASHING_AMOUNT; @@ -101,12 +101,13 @@ contract AssetManager is ISemver, IERC721Receiver, IAssetManager { } /** - * @notice Modifier to check if the vault is active. + * @notice Modifier to check if the validator is registered and not in jail. */ - modifier checkIsActive(address validator) { + modifier isRegistered(address validator) { if ( msg.sender != validator && - (VALIDATOR_MANAGER.getStatus(validator) < IValidatorManager.ValidatorStatus.ACTIVE || + (VALIDATOR_MANAGER.getStatus(validator) < + IValidatorManager.ValidatorStatus.REGISTERED || VALIDATOR_MANAGER.inJail(validator)) ) revert ImproperValidatorStatus(); _; @@ -323,7 +324,7 @@ contract AssetManager is ISemver, IERC721Receiver, IAssetManager { function delegate( address validator, uint128 assets - ) external checkIsActive(validator) returns (uint128) { + ) external isRegistered(validator) returns (uint128) { if (assets == 0) revert NotAllowedZeroInput(); uint128 shares = _delegate(validator, msg.sender, assets, true); emit KroDelegated(validator, msg.sender, assets, shares); @@ -353,7 +354,7 @@ contract AssetManager is ISemver, IERC721Receiver, IAssetManager { function delegateKgh( address validator, uint256 tokenId - ) external checkIsActive(validator) returns (uint128, uint128) { + ) external isRegistered(validator) returns (uint128, uint128) { uint128 kroInKgh = KGH_MANAGER.totalKroInKgh(tokenId); uint128 kroShares = previewDelegate(validator, kroInKgh); uint128 kghShares = previewKghDelegate(validator); @@ -369,7 +370,7 @@ contract AssetManager is ISemver, IERC721Receiver, IAssetManager { function delegateKghBatch( address validator, uint256[] calldata tokenIds - ) external checkIsActive(validator) returns (uint128, uint128) { + ) external isRegistered(validator) returns (uint128, uint128) { if (tokenIds.length == 0) revert NotAllowedZeroInput(); uint128 kroShares; diff --git a/packages/contracts/contracts/L1/Colosseum.sol b/packages/contracts/contracts/L1/Colosseum.sol index 372b63717..7719b5977 100644 --- a/packages/contracts/contracts/L1/Colosseum.sol +++ b/packages/contracts/contracts/L1/Colosseum.sol @@ -26,7 +26,7 @@ contract Colosseum is Initializable, ISemver { /** * @notice Enum of the challenge status. * - * See the https://github.com/kroma-network/kroma/blob/dev/specs/challenge.md#state-diagram + * See the https://specs.kroma.network/fault-proof/challenge.html#state-diagram * for more details. * * Belows are possible state transitions at current implementation. @@ -224,6 +224,11 @@ contract Colosseum is Initializable, ISemver { */ error NotAllowedCaller(); + /** + * @notice Reverts when a non-challenger calls cancel challenge. + */ + error OnlyChallengerCanCancel(); + /** * @notice Reverts when output is already finalized. */ @@ -249,6 +254,11 @@ contract Colosseum is Initializable, ISemver { */ error ImproperChallengeStatus(); + /** + * @notice Reverts when the status of challenge is improper to cancel challenge. + */ + error ImproperChallengeStatusToCancel(); + /** * @notice Reverts when the creation period is already passed. */ @@ -289,6 +299,12 @@ contract Colosseum is Initializable, ISemver { */ error LastSegmentMatched(); + /** + * @notice Reverts when the block hash is mismatched between source and destination output root + * proof. + */ + error BlockHashMismatchedBtwSrcAndDst(); + /** * @notice Reverts when the block hash is mismatched. */ @@ -635,8 +651,6 @@ contract Colosseum is Initializable, ISemver { Types.Challenge storage challenge = challenges[_outputIndex][msg.sender]; ChallengeStatus status = _challengeStatus(challenge); - if (status == ChallengeStatus.NONE) revert ImproperChallengeStatus(); - if (!_cancelIfOutputDeleted(_outputIndex, challenge.challenger, status)) revert CannotCancelChallenge(); } @@ -835,7 +849,7 @@ contract Colosseum is Initializable, ISemver { } if (_srcOutputRootProof.nextBlockHash != _dstOutputRootProof.blockHash) - revert BlockHashMismatched(); + revert BlockHashMismatchedBtwSrcAndDst(); } /** @@ -887,9 +901,10 @@ contract Colosseum is Initializable, ISemver { } // If the output is deleted, the asserter does not need to do anything further. - if (msg.sender != _challenger) revert NotAllowedCaller(); + if (msg.sender != _challenger) revert OnlyChallengerCanCancel(); - if (_status == ChallengeStatus.CHALLENGER_TIMEOUT) revert ImproperChallengeStatus(); + if (_status == ChallengeStatus.NONE || _status == ChallengeStatus.CHALLENGER_TIMEOUT) + revert ImproperChallengeStatusToCancel(); delete challenges[_outputIndex][msg.sender]; emit ChallengeCanceled(_outputIndex, msg.sender, block.timestamp); @@ -904,7 +919,7 @@ contract Colosseum is Initializable, ISemver { /** * @notice Deletes the challenge because the challenger timed out. - * The winner is the asserter, and challenger loses his asset. + * The winner is the asserter, and challenger loses their asset. * * @param _outputIndex Index of the L2 checkpoint output. * @param _challenger Address of the challenger. diff --git a/packages/contracts/contracts/L1/ValidatorManager.sol b/packages/contracts/contracts/L1/ValidatorManager.sol index 94bc8405e..72f2c595b 100644 --- a/packages/contracts/contracts/L1/ValidatorManager.sol +++ b/packages/contracts/contracts/L1/ValidatorManager.sol @@ -60,10 +60,10 @@ contract ValidatorManager is ISemver, IValidatorManager { uint128 public immutable MIN_REGISTER_AMOUNT; /** - * @notice Minimum amount to start a validator and add it to the validator tree. - * Note that only the started validators can submit outputs. + * @notice Minimum amount to activate a validator and add it to the validator tree. + * Note that only the active validators can submit outputs. */ - uint128 public immutable MIN_START_AMOUNT; + uint128 public immutable MIN_ACTIVATE_AMOUNT; /** * @notice The minimum duration to change the commission rate of the validator (in seconds). @@ -151,14 +151,14 @@ contract ValidatorManager is ISemver, IValidatorManager { * @param _constructorParams The constructor parameters. */ constructor(ConstructorParams memory _constructorParams) { - if (_constructorParams._minRegisterAmount > _constructorParams._minStartAmount) + if (_constructorParams._minRegisterAmount > _constructorParams._minActivateAmount) revert InvalidConstructorParams(); L2_ORACLE = _constructorParams._l2Oracle; ASSET_MANAGER = _constructorParams._assetManager; TRUSTED_VALIDATOR = _constructorParams._trustedValidator; MIN_REGISTER_AMOUNT = _constructorParams._minRegisterAmount; - MIN_START_AMOUNT = _constructorParams._minStartAmount; + MIN_ACTIVATE_AMOUNT = _constructorParams._minActivateAmount; COMMISSION_RATE_MIN_CHANGE_SECONDS = _constructorParams._commissionRateMinChangeSeconds; // Note that this value MUST be (SUBMISSION_INTERVAL * L2_BLOCK_TIME) / 2. ROUND_DURATION_SECONDS = _constructorParams._roundDurationSeconds; @@ -193,14 +193,14 @@ contract ValidatorManager is ISemver, IValidatorManager { ASSET_MANAGER.delegateToRegister(msg.sender, assets); - bool canStart = assets >= MIN_START_AMOUNT; - if (canStart) { + bool ready = assets >= MIN_ACTIVATE_AMOUNT; + if (ready) { _validatorTree.insert(msg.sender, uint120(ASSET_MANAGER.reflectiveWeight(msg.sender))); } emit ValidatorRegistered( msg.sender, - canStart, + ready, commissionRate, commissionMaxChangeRate, assets @@ -210,13 +210,13 @@ contract ValidatorManager is ISemver, IValidatorManager { /** * @inheritdoc IValidatorManager */ - function startValidator() external { - if (getStatus(msg.sender) != ValidatorStatus.CAN_START || inJail(msg.sender)) + function activateValidator() external { + if (getStatus(msg.sender) != ValidatorStatus.READY || inJail(msg.sender)) revert ImproperValidatorStatus(); _validatorTree.insert(msg.sender, uint120(ASSET_MANAGER.reflectiveWeight(msg.sender))); - emit ValidatorStarted(msg.sender, block.timestamp); + emit ValidatorActivated(msg.sender, block.timestamp); } /** @@ -240,7 +240,7 @@ contract ValidatorManager is ISemver, IValidatorManager { * @inheritdoc IValidatorManager */ function changeCommissionRate(uint8 newCommissionRate) external { - if (getStatus(msg.sender) < ValidatorStatus.ACTIVE || inJail(msg.sender)) + if (getStatus(msg.sender) < ValidatorStatus.REGISTERED || inJail(msg.sender)) revert ImproperValidatorStatus(); Validator storage validatorInfo = _validatorInfo[msg.sender]; @@ -326,14 +326,7 @@ contract ValidatorManager is ISemver, IValidatorManager { validator != _nextValidator ) revert NotSelectedPriorityValidator(); - _assertCanSubmitOutput(validator); - } - - /** - * @inheritdoc IValidatorManager - */ - function assertCanSubmitOutput(address validator) external view { - _assertCanSubmitOutput(validator); + assertCanSubmitOutput(validator); } /** @@ -359,17 +352,17 @@ contract ValidatorManager is ISemver, IValidatorManager { } /** - * @notice Returns the number of started validators. + * @notice Returns the number of activated validators. * - * @return The number of started validators. + * @return The number of activated validators. */ - function startedValidatorCount() external view returns (uint32) { + function activatedValidatorCount() external view returns (uint32) { return _validatorTree.counter - _validatorTree.removed; } /** - * @notice Returns the weight of given validator. It not started, returns 0. - * Note that `weight / startedValidatorTotalWeight()` is the probability that the + * @notice Returns the weight of given validator. It not activated, returns 0. + * Note that `weight / activatedValidatorTotalWeight()` is the probability that the * validator is selected as a priority validator. * * @param validator Address of the validator. @@ -396,12 +389,9 @@ contract ValidatorManager is ISemver, IValidatorManager { */ function updateValidatorTree(address validator, bool tryRemove) public { ValidatorStatus status = getStatus(validator); - if ( - tryRemove && (status == ValidatorStatus.INACTIVE || status == ValidatorStatus.STARTED) - ) { - bool removed = _validatorTree.remove(validator); - if (removed) emit ValidatorStopped(validator, block.timestamp); - } else if (status >= ValidatorStatus.STARTED) { + if (tryRemove && (status == ValidatorStatus.EXITED || status == ValidatorStatus.INACTIVE)) { + if (_validatorTree.remove(validator)) emit ValidatorStopped(validator, block.timestamp); + } else if (status >= ValidatorStatus.INACTIVE) { _validatorTree.update(validator, uint120(ASSET_MANAGER.reflectiveWeight(validator))); } } @@ -435,27 +425,27 @@ contract ValidatorManager is ISemver, IValidatorManager { } if (ASSET_MANAGER.totalValidatorKro(validator) < MIN_REGISTER_AMOUNT) { - return ValidatorStatus.INACTIVE; + return ValidatorStatus.EXITED; } - bool started = _validatorTree.nodeMap[validator] > 0; + bool activated = _validatorTree.nodeMap[validator] > 0; - // To prevent all MIN_START_AMOUNT is fulfilled with KRO in KGH which is not subject to slash, - // enable to start the validator when real asset satisfies the threshold. + // To prevent all MIN_ACTIVATE_AMOUNT is fulfilled with KRO in KGH which is not subject to + // slash, enable to activate the validator when real asset satisfies the threshold. if ( ASSET_MANAGER.reflectiveWeight(validator) - ASSET_MANAGER.totalKroInKgh(validator) < - MIN_START_AMOUNT + MIN_ACTIVATE_AMOUNT ) { - if (!started) { - return ValidatorStatus.ACTIVE; + if (!activated) { + return ValidatorStatus.REGISTERED; } - return ValidatorStatus.STARTED; + return ValidatorStatus.INACTIVE; } - if (!started) { - return ValidatorStatus.CAN_START; + if (!activated) { + return ValidatorStatus.READY; } - return ValidatorStatus.CAN_SUBMIT_OUTPUT; + return ValidatorStatus.ACTIVE; } /** @@ -465,6 +455,14 @@ contract ValidatorManager is ISemver, IValidatorManager { return _jail[validator] != 0; } + /** + * @inheritdoc IValidatorManager + */ + function assertCanSubmitOutput(address validator) public view { + if (getStatus(validator) != ValidatorStatus.ACTIVE || inJail(validator)) + revert ImproperValidatorStatus(); + } + /** * @notice Returns the no submission count of given validator. * @@ -477,11 +475,11 @@ contract ValidatorManager is ISemver, IValidatorManager { } /** - * @notice Returns the total weight of started validators. + * @notice Returns the total weight of activated validators. * - * @return The total weight of started validators. + * @return The total weight of activated validators. */ - function startedValidatorTotalWeight() public view returns (uint120) { + function activatedValidatorTotalWeight() public view returns (uint120) { return _validatorTree.nodes[_validatorTree.root].weightSum; } @@ -595,24 +593,13 @@ contract ValidatorManager is ISemver, IValidatorManager { return (baseReward, boostedReward, validatorReward); } - /** - * @notice Internal function to assert that the given validator satisfies output submission - * condition. - * - * @param validator Address of the validator. - */ - function _assertCanSubmitOutput(address validator) internal view { - if (getStatus(validator) != ValidatorStatus.CAN_SUBMIT_OUTPUT || inJail(validator)) - revert ImproperValidatorStatus(); - } - /** * @notice Updates next priority validator address. Validators with more delegation tokens have * a higher probability of being selected. The random weight selection is based on the * last finalized output root. */ function _updatePriorityValidator() private { - uint120 weightSum = startedValidatorTotalWeight(); + uint120 weightSum = activatedValidatorTotalWeight(); if (weightSum > 0) { uint256 latestFinalizedOutputIndex = L2_ORACLE.latestFinalizedOutputIndex(); diff --git a/packages/contracts/contracts/L1/interfaces/IValidatorManager.sol b/packages/contracts/contracts/L1/interfaces/IValidatorManager.sol index 138ba891b..7a5d33356 100644 --- a/packages/contracts/contracts/L1/interfaces/IValidatorManager.sol +++ b/packages/contracts/contracts/L1/interfaces/IValidatorManager.sol @@ -13,28 +13,28 @@ interface IValidatorManager { * @notice Enum of the status of a validator. * * Below is the possible conditions of each status. "initiated" means the validator has been - * initiated at least once, "started" means the validator has been started and added to the + * initiated at least once, "activated" means the validator has been activated and added to the * validator tree. "MIN_REGISTER_AMOUNT" means the total assets of the validator exceeds - * MIN_REGISTER_AMOUNT, "MIN_START_AMOUNT" means the same. + * MIN_REGISTER_AMOUNT, "MIN_ACTIVATE_AMOUNT" means the same. * - * +-------------------+-----------+---------+---------------------+------------------+ - * | Status | initiated | started | MIN_REGISTER_AMOUNT | MIN_START_AMOUNT | - * +-------------------+-----------+---------+---------------------+------------------+ - * | NONE | X | X | X | X | - * | INACTIVE | O | O/X | X | O/X | - * | ACTIVE | O | X | O | X | - * | CAN_START | O | X | O | O | - * | STARTED | O | O | O | X | - * | CAN_SUBMIT_OUTPUT | O | O | O | O | - * +-------------------+-----------+---------+---------------------+------------------+ + * +------------+-----------+-----------+---------------------+---------------------+ + * | Status | initiated | activated | MIN_REGISTER_AMOUNT | MIN_ACTIVATE_AMOUNT | + * +------------+-----------+-----------+---------------------+---------------------+ + * | NONE | X | X | X | X | + * | EXITED | O | O/X | X | O/X | + * | REGISTERED | O | X | O | X | + * | READY | O | X | O | O | + * | INACTIVE | O | O | O | X | + * | ACTIVE | O | O | O | O | + * +------------+-----------+-----------+---------------------+---------------------+ */ enum ValidatorStatus { NONE, + EXITED, + REGISTERED, + READY, INACTIVE, - ACTIVE, - CAN_START, - STARTED, - CAN_SUBMIT_OUTPUT + ACTIVE } /** @@ -54,7 +54,7 @@ interface IValidatorManager { * @custom:field _maxOutputFinalizations Max number of finalized outputs. * @custom:field _baseReward Base reward for the validator. * @custom:field _minRegisterAmount Minimum amount to register as a validator. - * @custom:field _minStartAmount Minimum amount to start submitting outputs. + * @custom:field _minActivateAmount Minimum amount to activate a validator. */ struct ConstructorParams { L2OutputOracle _l2Oracle; @@ -67,7 +67,7 @@ interface IValidatorManager { uint128 _maxOutputFinalizations; uint128 _baseReward; uint128 _minRegisterAmount; - uint128 _minStartAmount; + uint128 _minActivateAmount; } /** @@ -92,26 +92,26 @@ interface IValidatorManager { * @notice Emitted when registers as a validator. * * @param validator Address of the validator. - * @param started If the validator is started or not. + * @param activated If the validator is activated or not. * @param commissionRate The commission rate the validator sets. * @param commissionMaxChangeRate Maximum changeable commission rate at once. * @param assets The number of assets the validator self-delegates. */ event ValidatorRegistered( address indexed validator, - bool started, + bool activated, uint8 commissionRate, uint8 commissionMaxChangeRate, uint128 assets ); /** - * @notice Emitted when a validator starts, which means added to the validator tree. + * @notice Emitted when a validator activated, which means added to the validator tree. * - * @param validator Address of the validator. - * @param startsAt The timestamp when the validator starts. + * @param validator Address of the validator. + * @param activatedAt The timestamp when the validator activated. */ - event ValidatorStarted(address indexed validator, uint256 startsAt); + event ValidatorActivated(address indexed validator, uint256 activatedAt); /** * @notice Emitted when a validator stops, which means removed from the validator tree. @@ -243,7 +243,7 @@ interface IValidatorManager { /** * @notice Registers as a validator with assets at least MIN_REGISTER_AMOUNT. The validator with - * assets more than MIN_START_AMOUNT can be started at the same time. + * assets more than MIN_ACTIVATE_AMOUNT can be activated at the same time. * * @param assets The amount of assets to self-delegate. * @param commissionRate The commission rate the validator sets. @@ -256,10 +256,10 @@ interface IValidatorManager { ) external; /** - * @notice Starts a validator and adds the validator to validator tree. To submit outputs, the - * validator should start. + * @notice Activates a validator and adds the validator to validator tree. To submit outputs, + * the validator should be activated. */ - function startValidator() external; + function activateValidator() external; /** * @notice Handles some essential actions such as reward distribution, jail handling, next @@ -271,10 +271,10 @@ interface IValidatorManager { function afterSubmitL2Output(uint256 outputIndex) external; /** - * @notice Changes the commission rate of a validator. An inactive validator cannot change it, - * and a validator can change it after COMMISION_RATE_MIN_CHANGE_SECONDS elapsed since - * the last changed time. Also, the validator can only make changes within the - * commissionMaxChangeRate that the validator set initially. + * @notice Changes the commission rate of a validator. An exited or jailed validator cannot + * change it, and a validator can change it after COMMISION_RATE_MIN_CHANGE_SECONDS + * elapsed since the last changed time. Also, the validator can only make changes within + * the commissionMaxChangeRate that the validator set initially. * * @param newCommissionRate The new commission rate to apply. */ @@ -311,8 +311,8 @@ interface IValidatorManager { /** * @notice Checks the eligibility to submit L2 checkpoint output during output submission. - * Note that only the validator whose status is CAN_SUBMIT_OUTPUT can submit output. - * This function can only be called by L2OutputOracle during output submission. + * Note that only the validator whose status is ACTIVE can submit output. This function + * can only be called by L2OutputOracle during output submission. * * @param validator Address of the output submitter. */ diff --git a/packages/contracts/contracts/test/AssetManager.t.sol b/packages/contracts/contracts/test/AssetManager.t.sol index 8b691d365..451e6c57d 100644 --- a/packages/contracts/contracts/test/AssetManager.t.sol +++ b/packages/contracts/contracts/test/AssetManager.t.sol @@ -368,7 +368,7 @@ contract AssetManagerTest is ValidatorSystemUpgrade_Initializer { } function test_initUndelegate_removedFromValidatorTree_succeeds() external { - _setUpKroDelegation(minStartAmount); + _setUpKroDelegation(minActivateAmount); uint128 kroShares = assetManager.getKroTotalShareBalance(validator, delegator); vm.prank(delegator); @@ -378,7 +378,7 @@ contract AssetManagerTest is ValidatorSystemUpgrade_Initializer { vm.prank(validator); assetManager.initUndelegate(validator, minUndelegateShares); - assertEq(assetManager.totalKroAssets(validator), minStartAmount - 1); + assertEq(assetManager.totalKroAssets(validator), minActivateAmount - 1); } function test_initUndelegateKgh_succeeds() external { diff --git a/packages/contracts/contracts/test/Colosseum.t.sol b/packages/contracts/contracts/test/Colosseum.t.sol index cc32ae0f3..66812d745 100644 --- a/packages/contracts/contracts/test/Colosseum.t.sol +++ b/packages/contracts/contracts/test/Colosseum.t.sol @@ -575,6 +575,23 @@ contract ColosseumTest is Colosseum_Initializer { assertEq(pool.balanceOf(otherChallenger), prevDeposit + pendingBond); } + function test_bisect_cancelChallenge_senderNotChallenger_reverts() external { + uint256 outputIndex = targetOutputIndex; + address otherChallenger = _newChallenger("other challenger"); + + _createChallenge(outputIndex, otherChallenger); + Types.Challenge memory challenge = colosseum.getChallenge(outputIndex, otherChallenger); + // Make it the challenger turn + _bisect(outputIndex, otherChallenger, challenge.asserter); + + // The output root of the target output index was replaced by another challenge. + test_proveFault_succeeds(); + + vm.prank(challenger); + vm.expectRevert(Colosseum.OnlyChallengerCanCancel.selector); + colosseum.bisect(outputIndex, otherChallenger, 0, new bytes32[](0)); + } + function test_proveFault_succeeds() public { uint256 outputIndex = targetOutputIndex; _createChallenge(outputIndex, challenger); @@ -793,7 +810,7 @@ contract ColosseumTest is Colosseum_Initializer { } function test_cancelChallenge_noChallenge_reverts() external { - vm.expectRevert(Colosseum.ImproperChallengeStatus.selector); + vm.expectRevert(Colosseum.CannotCancelChallenge.selector); colosseum.cancelChallenge(0); } @@ -817,7 +834,7 @@ contract ColosseumTest is Colosseum_Initializer { test_proveFault_succeeds(); vm.prank(challenger); - vm.expectRevert(Colosseum.ImproperChallengeStatus.selector); + vm.expectRevert(Colosseum.OnlyChallengerCanCancel.selector); colosseum.cancelChallenge(outputIndex); } @@ -834,7 +851,7 @@ contract ColosseumTest is Colosseum_Initializer { test_proveFault_succeeds(); vm.prank(otherChallenger); - vm.expectRevert(Colosseum.ImproperChallengeStatus.selector); + vm.expectRevert(Colosseum.ImproperChallengeStatusToCancel.selector); colosseum.cancelChallenge(outputIndex); } @@ -942,7 +959,7 @@ contract Colosseum_ValidatorSystemUpgrade_Test is Colosseum_Initializer { } // Only trusted validator can submit the first output with ValidatorManager - _registerValidator(trusted, minStartAmount); + _registerValidator(trusted, minActivateAmount); // Submit invalid output as asserter uint256 nextBlockNumber = oracle.nextBlockNumber(); @@ -951,7 +968,7 @@ contract Colosseum_ValidatorSystemUpgrade_Test is Colosseum_Initializer { oracle.submitL2Output(keccak256(abi.encode()), nextBlockNumber, 0, 0); // To create challenge, challenger also registers validator - _registerValidator(challenger, minStartAmount); + _registerValidator(challenger, minActivateAmount); targetOutputIndex = oracle.latestOutputIndex(); } diff --git a/packages/contracts/contracts/test/CommonTest.t.sol b/packages/contracts/contracts/test/CommonTest.t.sol index 62927c121..8dd5aed4a 100644 --- a/packages/contracts/contracts/test/CommonTest.t.sol +++ b/packages/contracts/contracts/test/CommonTest.t.sol @@ -248,7 +248,7 @@ contract L2OutputOracle_Initializer is UpgradeGovernor_Initializer { uint128 internal maxOutputFinalizations = 10; uint128 internal baseReward = 20e18; uint128 internal minRegisterAmount = 10e18; - uint128 internal minStartAmount = 100e18; + uint128 internal minActivateAmount = 100e18; IValidatorManager.ConstructorParams constructorParams; // Test data @@ -275,9 +275,9 @@ contract L2OutputOracle_Initializer is UpgradeGovernor_Initializer { // Set up asset token and give actors some amount assetToken = new MockKro(); - assetToken.mint(trusted, minStartAmount * 10); - assetToken.mint(asserter, minStartAmount * 10); - assetToken.mint(challenger, minStartAmount * 10); + assetToken.mint(trusted, minActivateAmount * 10); + assetToken.mint(asserter, minActivateAmount * 10); + assetToken.mint(challenger, minActivateAmount * 10); // Set up KGH and KGHManager kgh = new MockKgh(); @@ -356,7 +356,7 @@ contract L2OutputOracle_Initializer is UpgradeGovernor_Initializer { _maxOutputFinalizations: maxOutputFinalizations, _baseReward: baseReward, _minRegisterAmount: minRegisterAmount, - _minStartAmount: minStartAmount + _minActivateAmount: minActivateAmount }); valManImpl = new ValidatorManager({ _constructorParams: constructorParams }); diff --git a/packages/contracts/contracts/test/L2OutputOracle.t.sol b/packages/contracts/contracts/test/L2OutputOracle.t.sol index c8adf72ac..7cdb2c52b 100644 --- a/packages/contracts/contracts/test/L2OutputOracle.t.sol +++ b/packages/contracts/contracts/test/L2OutputOracle.t.sol @@ -426,7 +426,7 @@ contract L2OutputOracle_ValidatorSystemUpgrade_Test is ValidatorSystemUpgrade_In vm.prank(trusted); pool.deposit{ value: trusted.balance }(); - _registerValidator(trusted, minStartAmount); + _registerValidator(trusted, minActivateAmount); // Submit outputs to leave 1 output before ValidatorPool is terminated for (uint256 i; i <= terminateOutputIndex - 1; i++) { diff --git a/packages/contracts/contracts/test/ValidatorManager.t.sol b/packages/contracts/contracts/test/ValidatorManager.t.sol index 6e5d94b77..90875c5fe 100644 --- a/packages/contracts/contracts/test/ValidatorManager.t.sol +++ b/packages/contracts/contracts/test/ValidatorManager.t.sol @@ -77,13 +77,13 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { event ValidatorRegistered( address indexed validator, - bool started, + bool activated, uint8 commissionRate, uint8 commissionMaxChangeRate, uint128 assets ); - event ValidatorStarted(address indexed validator, uint256 startsAt); + event ValidatorActivated(address indexed validator, uint256 activatedAt); event ValidatorStopped(address indexed validator, uint256 stopsAt); @@ -159,7 +159,7 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { assertEq(address(valMan.ASSET_MANAGER()), address(assetMan)); assertEq(valMan.TRUSTED_VALIDATOR(), trusted); assertEq(valMan.MIN_REGISTER_AMOUNT(), minRegisterAmount); - assertEq(valMan.MIN_START_AMOUNT(), minStartAmount); + assertEq(valMan.MIN_ACTIVATE_AMOUNT(), minActivateAmount); assertEq(valMan.COMMISSION_RATE_MIN_CHANGE_SECONDS(), commissionRateMinChangeSeconds); assertEq(valMan.ROUND_DURATION_SECONDS(), roundDuration); assertEq(valMan.JAIL_PERIOD_SECONDS(), jailPeriodSeconds); @@ -168,17 +168,17 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { assertEq(valMan.BASE_REWARD(), baseReward); } - function test_constructor_smallMinStartAmount_reverts() external { - constructorParams._minRegisterAmount = minStartAmount + 1; + function test_constructor_smallMinActivateAmount_reverts() external { + constructorParams._minRegisterAmount = minActivateAmount + 1; vm.expectRevert(IValidatorManager.InvalidConstructorParams.selector); new MockValidatorManager(constructorParams); } - function test_registerValidator_canSubmitOutput_succeeds() external { + function test_registerValidator_active_succeeds() external { uint256 trustedBalance = assetToken.balanceOf(trusted); - uint32 count = valMan.startedValidatorCount(); + uint32 count = valMan.activatedValidatorCount(); - uint128 assets = minStartAmount; + uint128 assets = minActivateAmount; uint8 commissionRate = 10; uint8 commissionMaxChangeRate = 5; @@ -195,17 +195,15 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { assertEq(valMan.getCommissionMaxChangeRate(trusted), commissionMaxChangeRate); assertEq(mockValMan.commissionRateChangedAt(trusted), block.timestamp); - assertTrue( - valMan.getStatus(trusted) == IValidatorManager.ValidatorStatus.CAN_SUBMIT_OUTPUT - ); - assertEq(valMan.startedValidatorCount(), count + 1); + assertTrue(valMan.getStatus(trusted) == IValidatorManager.ValidatorStatus.ACTIVE); + assertEq(valMan.activatedValidatorCount(), count + 1); assertEq(valMan.getWeight(trusted), assets); } - function test_registerValidator_active_succeeds() external { - uint32 count = valMan.startedValidatorCount(); + function test_registerValidator_registered_succeeds() external { + uint32 count = valMan.activatedValidatorCount(); - uint128 assets = minStartAmount - 1; + uint128 assets = minActivateAmount - 1; uint8 commissionRate = 10; uint8 commissionMaxChangeRate = 5; @@ -216,13 +214,13 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { valMan.registerValidator(assets, commissionRate, commissionMaxChangeRate); vm.stopPrank(); - assertTrue(valMan.getStatus(trusted) == IValidatorManager.ValidatorStatus.ACTIVE); - assertEq(valMan.startedValidatorCount(), count); + assertTrue(valMan.getStatus(trusted) == IValidatorManager.ValidatorStatus.REGISTERED); + assertEq(valMan.activatedValidatorCount(), count); assertEq(valMan.getWeight(trusted), 0); } function test_registerValidator_alreadyInitiated_reverts() external { - uint128 assets = minStartAmount; + uint128 assets = minActivateAmount; _registerValidator(trusted, assets); @@ -259,58 +257,56 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { valMan.registerValidator(assets, 10, 101); } - function test_startValidator_succeeds() external { - uint32 count = valMan.startedValidatorCount(); + function test_activateValidator_succeeds() external { + uint32 count = valMan.activatedValidatorCount(); - _registerValidator(trusted, minStartAmount - 1); + _registerValidator(trusted, minActivateAmount - 1); vm.startPrank(asserter); assetToken.approve(address(assetMan), 1); assetMan.delegate(trusted, 1); vm.stopPrank(); - assertTrue(valMan.getStatus(trusted) == IValidatorManager.ValidatorStatus.CAN_START); + assertTrue(valMan.getStatus(trusted) == IValidatorManager.ValidatorStatus.READY); vm.prank(trusted); vm.expectEmit(true, false, false, true, address(valMan)); - emit ValidatorStarted(trusted, block.timestamp); - valMan.startValidator(); + emit ValidatorActivated(trusted, block.timestamp); + valMan.activateValidator(); - assertTrue( - valMan.getStatus(trusted) == IValidatorManager.ValidatorStatus.CAN_SUBMIT_OUTPUT - ); - assertEq(valMan.startedValidatorCount(), count + 1); - assertEq(valMan.getWeight(trusted), minStartAmount); + assertTrue(valMan.getStatus(trusted) == IValidatorManager.ValidatorStatus.ACTIVE); + assertEq(valMan.activatedValidatorCount(), count + 1); + assertEq(valMan.getWeight(trusted), minActivateAmount); } - function test_startValidator_notValidator_reverts() external { + function test_activateValidator_notValidator_reverts() external { assertTrue(valMan.getStatus(trusted) == IValidatorManager.ValidatorStatus.NONE); vm.prank(trusted); vm.expectRevert(IValidatorManager.ImproperValidatorStatus.selector); - valMan.startValidator(); + valMan.activateValidator(); } - function test_startValidator_active_reverts() external { - _registerValidator(trusted, minStartAmount - 1); + function test_activateValidator_registered_reverts() external { + _registerValidator(trusted, minActivateAmount - 1); vm.prank(trusted); vm.expectRevert(IValidatorManager.ImproperValidatorStatus.selector); - valMan.startValidator(); + valMan.activateValidator(); } - function test_startValidator_inactive_reverts() external { - _registerValidator(trusted, minStartAmount); + function test_activateValidator_exited_reverts() external { + _registerValidator(trusted, minActivateAmount); uint128 kroShares = assetMan.getKroTotalShareBalance(trusted, trusted); vm.prank(trusted); assetMan.initUndelegate(trusted, kroShares); - assertTrue(valMan.getStatus(trusted) == IValidatorManager.ValidatorStatus.INACTIVE); + assertTrue(valMan.getStatus(trusted) == IValidatorManager.ValidatorStatus.EXITED); vm.prank(trusted); vm.expectRevert(IValidatorManager.ImproperValidatorStatus.selector); - valMan.startValidator(); + valMan.activateValidator(); } - function test_startValidator_inJail_reverts() external { + function test_activateValidator_inJail_reverts() external { test_afterSubmitL2Output_tryJail_succeeds(); // Undelegate all assets of jailed validator @@ -319,31 +315,31 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { vm.expectEmit(true, false, false, true, address(valMan)); emit ValidatorStopped(asserter, block.timestamp); assetMan.initUndelegate(asserter, kroShares); - assertTrue(valMan.getStatus(asserter) == IValidatorManager.ValidatorStatus.INACTIVE); + assertTrue(valMan.getStatus(asserter) == IValidatorManager.ValidatorStatus.EXITED); - // Delegate to re-start validator + // Delegate to re-activate validator vm.startPrank(asserter); - assetToken.approve(address(assetMan), minStartAmount); - assetMan.delegate(asserter, minStartAmount); + assetToken.approve(address(assetMan), minActivateAmount); + assetMan.delegate(asserter, minActivateAmount); vm.stopPrank(); - assertTrue(valMan.getStatus(asserter) == IValidatorManager.ValidatorStatus.CAN_START); + assertTrue(valMan.getStatus(asserter) == IValidatorManager.ValidatorStatus.READY); vm.prank(asserter); vm.expectRevert(IValidatorManager.ImproperValidatorStatus.selector); - valMan.startValidator(); + valMan.activateValidator(); } - function test_startValidator_alreadyStarted_reverts() external { - _registerValidator(trusted, minStartAmount); + function test_activateValidator_alreadyActivated_reverts() external { + _registerValidator(trusted, minActivateAmount); vm.prank(trusted); vm.expectRevert(IValidatorManager.ImproperValidatorStatus.selector); - valMan.startValidator(); + valMan.activateValidator(); } function test_afterSubmitL2Output_distributeReward_succeeds() external { // Register validator with commission rate 10% - _registerValidator(trusted, minStartAmount); + _registerValidator(trusted, minActivateAmount); // Delegate 100 KGHs uint128 kghCounts = 100; @@ -372,7 +368,7 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { valMan.afterSubmitL2Output(outputIndex); uint128 kroReward = assetMan.totalKroAssets(trusted) - - minStartAmount - + minActivateAmount - kghCounts * VKRO_PER_KGH; vm.prank(trusted); @@ -384,7 +380,7 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { // Check validator tree updated with rewards assertEq( valMan.getWeight(trusted), - minStartAmount + + minActivateAmount + kghManager.totalKroInKgh(1) * kghCounts + baseReward + @@ -397,8 +393,8 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { function test_afterSubmitL2Output_updatePriorityValidator_succeeds() external { // Register as a validator - _registerValidator(asserter, minStartAmount); - _registerValidator(trusted, minStartAmount); + _registerValidator(asserter, minActivateAmount); + _registerValidator(trusted, minActivateAmount); // Check if next priority validator is not set in ValidatorManager assertTrue(mockValMan.nextPriorityValidator() == address(0)); @@ -446,8 +442,8 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { function test_afterSubmitL2Output_tryJail_succeeds() public { // Register as a validator - _registerValidator(asserter, minStartAmount); - _registerValidator(trusted, minStartAmount); + _registerValidator(asserter, minActivateAmount); + _registerValidator(trusted, minActivateAmount); vm.startPrank(trusted); for (uint256 i; i < jailThreshold; i++) { @@ -481,8 +477,8 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { function test_afterSubmitL2Output_resetNoSubmissionCount_succeeds() external { // Register as a validator - _registerValidator(asserter, minStartAmount); - _registerValidator(trusted, minStartAmount); + _registerValidator(asserter, minActivateAmount); + _registerValidator(trusted, minActivateAmount); mockValMan.updatePriorityValidator(asserter); @@ -512,7 +508,7 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { } function test_changeCommissionRate_succeeds() public { - _registerValidator(asserter, minStartAmount); + _registerValidator(asserter, minActivateAmount); uint8 commissionRate = valMan.getCommissionRate(asserter); uint8 commissionMaxChangeRate = valMan.getCommissionMaxChangeRate(asserter); @@ -547,13 +543,13 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { assertEq(valMan.getCommissionRate(asserter), newCommissionRate); } - function test_changeCommissionRate_inactive_reverts() external { - _registerValidator(trusted, minStartAmount); + function test_changeCommissionRate_exited_reverts() external { + _registerValidator(trusted, minActivateAmount); uint128 kroShares = assetMan.getKroTotalShareBalance(trusted, trusted); vm.prank(trusted); assetMan.initUndelegate(trusted, kroShares); - assertTrue(valMan.getStatus(trusted) == IValidatorManager.ValidatorStatus.INACTIVE); + assertTrue(valMan.getStatus(trusted) == IValidatorManager.ValidatorStatus.EXITED); vm.prank(asserter); vm.expectRevert(IValidatorManager.ImproperValidatorStatus.selector); @@ -569,7 +565,7 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { } function test_changeCommissionRate_minChangeSecNotElapsed_reverts() external { - _registerValidator(asserter, minStartAmount); + _registerValidator(asserter, minActivateAmount); vm.prank(asserter); vm.expectRevert(IValidatorManager.NotElapsedCommissionChangePeriod.selector); @@ -577,7 +573,7 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { } function test_changeCommissionRate_largeCommissionRate_reverts() external { - _registerValidator(asserter, minStartAmount); + _registerValidator(asserter, minActivateAmount); vm.warp( mockValMan.commissionRateChangedAt(asserter) + @@ -589,7 +585,7 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { } function test_changeCommissionRate_sameCommissionRate_reverts() external { - _registerValidator(asserter, minStartAmount); + _registerValidator(asserter, minActivateAmount); uint8 commissionRate = valMan.getCommissionRate(asserter); @@ -603,7 +599,7 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { } function test_changeCommissionRate_largeChangeRate_reverts() external { - _registerValidator(asserter, minStartAmount); + _registerValidator(asserter, minActivateAmount); uint8 commissionRate = valMan.getCommissionRate(asserter); uint8 commissionMaxChangeRate = valMan.getCommissionMaxChangeRate(asserter); @@ -662,11 +658,11 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { } function test_slash_succeeds() external { - uint32 count = valMan.startedValidatorCount(); + uint32 count = valMan.activatedValidatorCount(); // Register as a validator - _registerValidator(asserter, minStartAmount); - _registerValidator(challenger, minStartAmount); - assertEq(valMan.startedValidatorCount(), count + 2); + _registerValidator(asserter, minActivateAmount); + _registerValidator(challenger, minActivateAmount); + assertEq(valMan.activatedValidatorCount(), count + 2); // Delegate KGHs uint128 kghCounts = 100; @@ -682,7 +678,8 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { uint256 challengedOutputIndex = oracle.latestOutputIndex(); // Suppose that the challenge is successful, so the winner is challenger - uint128 slashingAmount = (minStartAmount * slashingRate) / assetMan.SLASHING_RATE_DENOM(); + uint128 slashingAmount = (minActivateAmount * slashingRate) / + assetMan.SLASHING_RATE_DENOM(); vm.prank(address(colosseum)); vm.expectEmit(true, true, false, true, address(valMan)); emit Slashed(challengedOutputIndex, asserter, slashingAmount); @@ -706,13 +703,13 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { uint128 asserterTotalKro = assetMan.totalKroAssets(asserter) - kghCounts * kghManager.totalKroInKgh(1); - assertEq(asserterTotalKro, minStartAmount - slashingAmount); + assertEq(asserterTotalKro, minActivateAmount - slashingAmount); // Asserter has 0 rewards assertEq(assetMan.reflectiveWeight(asserter), assetMan.totalKroAssets(asserter)); // Asserter removed from validator tree - assertEq(valMan.startedValidatorCount(), count + 1); - assertTrue(valMan.getStatus(asserter) == IValidatorManager.ValidatorStatus.ACTIVE); + assertEq(valMan.activatedValidatorCount(), count + 1); + assertTrue(valMan.getStatus(asserter) == IValidatorManager.ValidatorStatus.REGISTERED); // Security council balance of asset token increased by tax uint128 taxAmount = (slashingAmount * assetMan.TAX_NUMERATOR()) / @@ -726,7 +723,7 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { uint128 challengerAsset = assetMan.reflectiveWeight(challenger); assertEq( challengerAsset, - minStartAmount + + minActivateAmount + kghCounts * kghManager.totalKroInKgh(1) + baseReward + @@ -745,7 +742,7 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { function test_checkSubmissionEligibility_priorityRound_succeeds() external { address nextValidator = valMan.nextValidator(); - _registerValidator(nextValidator, minStartAmount); + _registerValidator(nextValidator, minActivateAmount); vm.prank(address(oracle)); valMan.checkSubmissionEligibility(nextValidator); @@ -754,7 +751,7 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { function test_checkSubmissionEligibility_publicRound_succeeds() external { mockValMan.updatePriorityValidator(asserter); - _registerValidator(trusted, minStartAmount); + _registerValidator(trusted, minActivateAmount); // Warp to public round vm.warp(oracle.nextOutputMinL2Timestamp() + roundDuration + 1); @@ -816,37 +813,37 @@ contract ValidatorManagerTest is ValidatorSystemUpgrade_Initializer { valMan.checkSubmissionEligibility(asserter); } - function test_getStatus_active_succeeds() external { - _registerValidator(trusted, minStartAmount); - assertEq(valMan.getWeight(trusted), minStartAmount); + function test_getStatus_registered_succeeds() external { + _registerValidator(trusted, minActivateAmount); + assertEq(valMan.getWeight(trusted), minActivateAmount); uint128 minUndelegateShares = assetMan.previewDelegate(trusted, 1); vm.prank(trusted); assetMan.initUndelegate(trusted, minUndelegateShares); - assertTrue(valMan.getStatus(trusted) == IValidatorManager.ValidatorStatus.ACTIVE); + assertTrue(valMan.getStatus(trusted) == IValidatorManager.ValidatorStatus.REGISTERED); assertEq(valMan.getWeight(trusted), 0); } - function test_startedValidatorTotalWeight_succeeds() external { - uint32 count = valMan.startedValidatorCount(); - uint120 totalWeight = valMan.startedValidatorTotalWeight(); - _registerValidator(trusted, minStartAmount); - assertEq(valMan.startedValidatorCount(), count + 1); - assertEq(valMan.startedValidatorTotalWeight(), totalWeight + minStartAmount); + function test_activatedValidatorTotalWeight_succeeds() external { + uint32 count = valMan.activatedValidatorCount(); + uint120 totalWeight = valMan.activatedValidatorTotalWeight(); + _registerValidator(trusted, minActivateAmount); + assertEq(valMan.activatedValidatorCount(), count + 1); + assertEq(valMan.activatedValidatorTotalWeight(), totalWeight + minActivateAmount); - count = valMan.startedValidatorCount(); - totalWeight = valMan.startedValidatorTotalWeight(); - _registerValidator(asserter, minStartAmount); - assertEq(valMan.startedValidatorCount(), count + 1); - assertEq(valMan.startedValidatorTotalWeight(), totalWeight + minStartAmount); + count = valMan.activatedValidatorCount(); + totalWeight = valMan.activatedValidatorTotalWeight(); + _registerValidator(asserter, minActivateAmount); + assertEq(valMan.activatedValidatorCount(), count + 1); + assertEq(valMan.activatedValidatorTotalWeight(), totalWeight + minActivateAmount); - count = valMan.startedValidatorCount(); - totalWeight = valMan.startedValidatorTotalWeight(); + count = valMan.activatedValidatorCount(); + totalWeight = valMan.activatedValidatorTotalWeight(); vm.startPrank(challenger); assetToken.approve(address(assetMan), 10); assetMan.delegate(asserter, 10); vm.stopPrank(); - assertEq(valMan.startedValidatorCount(), count); - assertEq(valMan.startedValidatorTotalWeight(), totalWeight + 10); + assertEq(valMan.activatedValidatorCount(), count); + assertEq(valMan.activatedValidatorTotalWeight(), totalWeight + 10); } } diff --git a/packages/contracts/deploy-config/devnetL1-template.json b/packages/contracts/deploy-config/devnetL1-template.json index 4d507069e..aa0f74a97 100644 --- a/packages/contracts/deploy-config/devnetL1-template.json +++ b/packages/contracts/deploy-config/devnetL1-template.json @@ -46,7 +46,7 @@ "validatorPoolTerminateOutputIndex": "0xffffffffffffffffffff", "validatorManagerTrustedValidator": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", "validatorManagerMinRegisterAmount": "0x1", - "validatorManagerMinStartAmount": "0x2", + "validatorManagerMinActivateAmount": "0x2", "validatorManagerCommissionMinChangeSeconds": 120, "validatorManagerRoundDurationSeconds": 4, "validatorManagerJailPeriodSeconds": 120, diff --git a/packages/contracts/deploy/L1/019-ValidatorManager.ts b/packages/contracts/deploy/L1/019-ValidatorManager.ts index c07d0ed4b..31a4db4d6 100644 --- a/packages/contracts/deploy/L1/019-ValidatorManager.ts +++ b/packages/contracts/deploy/L1/019-ValidatorManager.ts @@ -43,7 +43,7 @@ const deployFn: DeployFunction = async (hre) => { hre.deployConfig.validatorManagerMaxFinalizations, _baseReward: hre.deployConfig.validatorManagerBaseReward, _minRegisterAmount: hre.deployConfig.validatorManagerMinRegisterAmount, - _minStartAmount: hre.deployConfig.validatorManagerMinStartAmount, + _minActivateAmount: hre.deployConfig.validatorManagerMinActivateAmount, }, ], isProxyImpl: true, @@ -70,8 +70,8 @@ const deployFn: DeployFunction = async (hre) => { ) await assertContractVariable( contract, - 'MIN_START_AMOUNT', - hre.deployConfig.validatorManagerMinStartAmount + 'MIN_ACTIVATE_AMOUNT', + hre.deployConfig.validatorManagerMinActivateAmount ) await assertContractVariable( contract, diff --git a/packages/contracts/src/deploy-config.ts b/packages/contracts/src/deploy-config.ts index 9b1dc2053..224591619 100644 --- a/packages/contracts/src/deploy-config.ts +++ b/packages/contracts/src/deploy-config.ts @@ -107,9 +107,9 @@ interface RequiredDeployConfig { validatorManagerMinRegisterAmount: string /** - * Amount of the minimum start amount in hex value. + * Amount of the minimum activation amount in hex value. */ - validatorManagerMinStartAmount: string + validatorManagerMinActivateAmount: string /** * The minimum duration of commission change in seconds. @@ -398,7 +398,7 @@ export const deployConfigSpec: { validatorManagerMinRegisterAmount: { type: 'string', // uint128 }, - validatorManagerMinStartAmount: { + validatorManagerMinActivateAmount: { type: 'string', // uint128 }, validatorManagerCommissionMinChangeSeconds: { From 11d71e511a58b955e471b41a08cfe65ccce5345e Mon Sep 17 00:00:00 2001 From: sm-stack Date: Tue, 2 Apr 2024 17:05:47 +0900 Subject: [PATCH 2/8] feat(validator): add logics for new validator system --- kroma-validator/challenger.go | 93 +++++++--- kroma-validator/config.go | 23 +++ kroma-validator/flags/flags.go | 14 ++ kroma-validator/l2_output_submitter.go | 227 +++++++++++++++++++++---- kroma-validator/validator/status.go | 13 ++ 5 files changed, 315 insertions(+), 55 deletions(-) create mode 100644 kroma-validator/validator/status.go diff --git a/kroma-validator/challenger.go b/kroma-validator/challenger.go index 3b4dd5b9f..994d48259 100644 --- a/kroma-validator/challenger.go +++ b/kroma-validator/challenger.go @@ -25,6 +25,7 @@ import ( "github.com/kroma-network/kroma/kroma-bindings/bindings" chal "github.com/kroma-network/kroma/kroma-validator/challenge" "github.com/kroma-network/kroma/kroma-validator/metrics" + val "github.com/kroma-network/kroma/kroma-validator/validator" ) var deletedOutputRoot = [32]byte{} @@ -43,17 +44,19 @@ type Challenger struct { l1Client *ethclient.Client l2Client *ethclient.Client - l2ooContract *bindings.L2OutputOracle - l2ooABI *abi.ABI - colosseumContract *bindings.Colosseum - colosseumABI *abi.ABI - valpoolContract *bindings.ValidatorPoolCaller + l2ooContract *bindings.L2OutputOracle + l2ooABI *abi.ABI + colosseumContract *bindings.Colosseum + colosseumABI *abi.ABI + valpoolContract *bindings.ValidatorPoolCaller + valManagerContract *bindings.ValidatorManagerCaller submissionInterval *big.Int finalizationPeriodSeconds *big.Int l2BlockTime *big.Int checkpoint *big.Int requiredBondAmount *big.Int + isValManagerEnabled bool l2OutputSubmittedSub ethereum.Subscription challengeCreatedSub ethereum.Subscription @@ -90,6 +93,11 @@ func NewChallenger(cfg Config, l log.Logger, m metrics.Metricer) (*Challenger, e return nil, err } + valManagerContract, err := bindings.NewValidatorManagerCaller(cfg.ValidatorManagerAddr, cfg.L1Client) + if err != nil { + return nil, err + } + return &Challenger{ log: l.New("service", "challenge"), cfg: cfg, @@ -98,11 +106,12 @@ func NewChallenger(cfg Config, l log.Logger, m metrics.Metricer) (*Challenger, e l1Client: cfg.L1Client, l2Client: cfg.L2Client, - l2ooContract: l2ooContract, - l2ooABI: l2ooABI, - colosseumContract: colosseumContract, - colosseumABI: colosseumABI, - valpoolContract: valpoolContract, + l2ooContract: l2ooContract, + l2ooABI: l2ooABI, + colosseumContract: colosseumContract, + colosseumABI: colosseumABI, + valpoolContract: valpoolContract, + valManagerContract: valManagerContract, }, nil } @@ -149,6 +158,24 @@ func (c *Challenger) InitConfig(ctx context.Context) error { } c.requiredBondAmount = requiredBondAmount + cCtx, cCancel = context.WithTimeout(ctx, c.cfg.NetworkTimeout) + defer cCancel() + nextOutputIndex, err := c.l2ooContract.NextOutputIndex(optsutils.NewSimpleCallOpts(cCtx)) + if err != nil { + return fmt.Errorf("failed to get latest output index: %w", err) + } + + cCtx, cCancel = context.WithTimeout(ctx, c.cfg.NetworkTimeout) + defer cCancel() + isTerminated, err := c.valpoolContract.IsTerminated( + optsutils.NewSimpleCallOpts(cCtx), + nextOutputIndex, + ) + if err != nil { + return fmt.Errorf("failed to whether valpool is terminated or not: %w", err) + } + c.isValManagerEnabled = isTerminated + return nil }) if err != nil { @@ -438,12 +465,12 @@ func (c *Challenger) handleOutput(outputIndex *big.Int) { return } - hasEnoughDeposit, err := c.HasEnoughDeposit(c.ctx) + canCreateChallenge, err := c.CanCreateChallenge(c.ctx) if err != nil { c.log.Error(err.Error()) continue } - if !hasEnoughDeposit { + if !canCreateChallenge { continue } @@ -598,21 +625,41 @@ func (c *Challenger) submitChallengeTx(tx *types.Transaction) error { return c.cfg.TxManager.SendTransaction(c.ctx, tx).Err } -// HasEnoughDeposit checks if challenger has enough deposit to bond when creating challenge. -func (c *Challenger) HasEnoughDeposit(ctx context.Context) (bool, error) { +// CanCreateChallenge checks if challenger is in the status that can make challenge. +func (c *Challenger) CanCreateChallenge(ctx context.Context) (bool, error) { cCtx, cCancel := context.WithTimeout(ctx, c.cfg.NetworkTimeout) defer cCancel() - balance, err := c.valpoolContract.BalanceOf(optsutils.NewSimpleCallOpts(cCtx), c.cfg.TxManager.From()) - if err != nil { - return false, fmt.Errorf("failed to fetch deposit amount: %w", err) - } - c.metr.RecordDepositAmount(balance) + from := c.cfg.TxManager.From() + if c.isValManagerEnabled { + vaultStatus, err := c.valManagerContract.GetStatus(optsutils.NewSimpleCallOpts(cCtx), from) + if err != nil { + return false, fmt.Errorf("failed to fetch the vault status: %w", err) + } + + if vaultStatus != val.StatusCanSubmitOutput { + c.log.Warn("vault is not in the status to make a challenge", "status", vaultStatus) + return false, nil + } + + c.log.Info("vault status", "status", vaultStatus) + } else { + balance, err := c.valpoolContract.BalanceOf(optsutils.NewSimpleCallOpts(cCtx), from) + if err != nil { + return false, fmt.Errorf("failed to fetch deposit amount: %w", err) + } + c.metr.RecordDepositAmount(balance) + + if balance.Cmp(c.requiredBondAmount) == -1 { + c.log.Warn( + "deposit is less than bond attempt amount", + "requiredBondAmount", c.requiredBondAmount, + "deposit", balance, + ) + return false, nil + } - if balance.Cmp(c.requiredBondAmount) == -1 { - c.log.Warn("deposit is less than bond amount", "required", c.requiredBondAmount, "deposit", balance) - return false, nil + c.log.Info("deposit amount", "deposit", balance) } - c.log.Info("deposit amount and bond amount", "deposit", balance, "bond", c.requiredBondAmount) return true, nil } diff --git a/kroma-validator/config.go b/kroma-validator/config.go index 1b47cacf2..a2b851428 100644 --- a/kroma-validator/config.go +++ b/kroma-validator/config.go @@ -31,6 +31,9 @@ type Config struct { ColosseumAddr common.Address SecurityCouncilAddr common.Address ValidatorPoolAddr common.Address + ValidatorManagerAddr common.Address + AssetManagerAddr common.Address + GovTokenAddr common.Address ChallengerPollInterval time.Duration NetworkTimeout time.Duration TxManager *txmgr.BufferedTxManager @@ -81,6 +84,12 @@ type CLIConfig struct { // ValPoolAddress is the ValidatorPool contract address. ValPoolAddress string + // ValManagerAddress is the ValidatorManager contract address. + ValManagerAddress string + + // AssetManagerAddress is the AssetManager contract address. + AssetManagerAddress string + // ChallengerPollInterval is how frequently to poll L2 for new finalized outputs. ChallengerPollInterval time.Duration @@ -146,6 +155,8 @@ func NewConfig(ctx *cli.Context) CLIConfig { L2OOAddress: ctx.String(flags.L2OOAddressFlag.Name), ColosseumAddress: ctx.String(flags.ColosseumAddressFlag.Name), ValPoolAddress: ctx.String(flags.ValPoolAddressFlag.Name), + ValManagerAddress: ctx.String(flags.ValManagerAddressFlag.Name), + AssetManagerAddress: ctx.String(flags.AssetManagerAddressFlag.Name), OutputSubmitterEnabled: ctx.Bool(flags.OutputSubmitterEnabledFlag.Name), ChallengerEnabled: ctx.Bool(flags.ChallengerEnabledFlag.Name), ChallengerPollInterval: ctx.Duration(flags.ChallengerPollIntervalFlag.Name), @@ -192,6 +203,16 @@ func NewValidatorConfig(cfg CLIConfig, l log.Logger, m metrics.Metricer) (*Confi return nil, err } + valManagerAddress, err := opservice.ParseAddress(cfg.ValManagerAddress) + if err != nil { + return nil, err + } + + assetManagerAddress, err := opservice.ParseAddress(cfg.AssetManagerAddress) + if err != nil { + return nil, err + } + txManager, err := txmgr.NewBufferedTxManager("validator", l, m, cfg.TxMgrConfig) if err != nil { return nil, err @@ -236,6 +257,8 @@ func NewValidatorConfig(cfg CLIConfig, l log.Logger, m metrics.Metricer) (*Confi ColosseumAddr: colosseumAddress, SecurityCouncilAddr: securityCouncilAddress, ValidatorPoolAddr: valPoolAddress, + ValidatorManagerAddr: valManagerAddress, + AssetManagerAddr: assetManagerAddress, ChallengerPollInterval: cfg.ChallengerPollInterval, NetworkTimeout: cfg.TxMgrConfig.NetworkTimeout, TxManager: txManager, diff --git a/kroma-validator/flags/flags.go b/kroma-validator/flags/flags.go index c0e4457f7..ea31eeb76 100644 --- a/kroma-validator/flags/flags.go +++ b/kroma-validator/flags/flags.go @@ -59,6 +59,18 @@ var ( Required: true, EnvVars: prefixEnvVars("VALPOOL_ADDRESS"), } + ValManagerAddressFlag = &cli.StringFlag{ + Name: "valmanager-address", + Usage: "Address of the ValidatorManager contract", + Required: true, + EnvVars: prefixEnvVars("VALMANAGER_ADDRESS"), + } + AssetManagerAddressFlag = &cli.StringFlag{ + Name: "assetmanager-address", + Usage: "Address of the AssetManager contract", + Required: true, + EnvVars: prefixEnvVars("ASSETMANAGER_ADDRESS"), + } OutputSubmitterEnabledFlag = &cli.BoolFlag{ Name: "output-submitter.enabled", Usage: "Enable l2 output submitter", @@ -132,6 +144,8 @@ var requiredFlags = []cli.Flag{ L2OOAddressFlag, ColosseumAddressFlag, ValPoolAddressFlag, + ValManagerAddressFlag, + AssetManagerAddressFlag, OutputSubmitterEnabledFlag, ChallengerEnabledFlag, ChallengerPollIntervalFlag, diff --git a/kroma-validator/l2_output_submitter.go b/kroma-validator/l2_output_submitter.go index 23e39e5fd..e9f6b1971 100644 --- a/kroma-validator/l2_output_submitter.go +++ b/kroma-validator/l2_output_submitter.go @@ -5,6 +5,7 @@ import ( "context" "errors" "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "math/big" _ "net/http/pprof" "sync" @@ -22,6 +23,7 @@ import ( "github.com/ethereum-optimism/optimism/op-service/watcher" "github.com/kroma-network/kroma/kroma-bindings/bindings" "github.com/kroma-network/kroma/kroma-validator/metrics" + val "github.com/kroma-network/kroma/kroma-validator/validator" ) const ( @@ -40,14 +42,18 @@ type L2OutputSubmitter struct { log log.Logger metr metrics.Metricer - l2ooContract *bindings.L2OutputOracleCaller - l2ooABI *abi.ABI - valpoolContract *bindings.ValidatorPoolCaller + l2ooContract *bindings.L2OutputOracleCaller + l2ooABI *abi.ABI + valpoolContract *bindings.ValidatorPoolCaller + valManagerContract *bindings.ValidatorManagerCaller + valManagerAbi *abi.ABI singleRoundInterval *big.Int l2BlockTime *big.Int requiredBondAmount *big.Int + isValManagerEnabled bool + submitChan chan struct{} wg sync.WaitGroup @@ -60,7 +66,12 @@ func NewL2OutputSubmitter(cfg Config, l log.Logger, m metrics.Metricer) (*L2Outp return nil, err } - parsed, err := bindings.L2OutputOracleMetaData.GetAbi() + parsedL2ooAbi, err := bindings.L2OutputOracleMetaData.GetAbi() + if err != nil { + return nil, err + } + + parsedValManagerAbi, err := bindings.ValidatorManagerMetaData.GetAbi() if err != nil { return nil, err } @@ -70,13 +81,20 @@ func NewL2OutputSubmitter(cfg Config, l log.Logger, m metrics.Metricer) (*L2Outp return nil, err } + valManagerContract, err := bindings.NewValidatorManagerCaller(cfg.ValidatorManagerAddr, cfg.L1Client) + if err != nil { + return nil, err + } + return &L2OutputSubmitter{ - cfg: cfg, - log: l.New("service", "submitter"), - metr: m, - l2ooContract: l2ooContract, - l2ooABI: parsed, - valpoolContract: valpoolContract, + cfg: cfg, + log: l.New("service", "submitter"), + metr: m, + l2ooContract: l2ooContract, + l2ooABI: parsedL2ooAbi, + valpoolContract: valpoolContract, + valManagerContract: valManagerContract, + valManagerAbi: parsedValManagerAbi, }, nil } @@ -116,6 +134,24 @@ func (l *L2OutputSubmitter) InitConfig(ctx context.Context) error { } l.requiredBondAmount = requiredBondAmount + cCtx, cCancel = context.WithTimeout(ctx, l.cfg.NetworkTimeout) + defer cCancel() + nextOutputIndex, err := l.l2ooContract.NextOutputIndex(optsutils.NewSimpleCallOpts(cCtx)) + if err != nil { + return fmt.Errorf("failed to get latest output index: %w", err) + } + + cCtx, cCancel = context.WithTimeout(ctx, l.cfg.NetworkTimeout) + defer cCancel() + isTerminated, err := l.valpoolContract.IsTerminated( + optsutils.NewSimpleCallOpts(cCtx), + nextOutputIndex, + ) + if err != nil { + return fmt.Errorf("failed to whether valpool is terminated or not: %w", err) + } + l.isValManagerEnabled = isTerminated + return nil }) if err != nil { @@ -181,6 +217,16 @@ func (l *L2OutputSubmitter) repeatSubmitL2Output(ctx context.Context) { // If it needs to wait, it will calculate how long the validator should wait and // try again after the delay. func (l *L2OutputSubmitter) trySubmitL2Output(ctx context.Context) (time.Duration, error) { + if l.isValManagerEnabled { + hasSubmittedStartTx, err := l.tryStartValidator(ctx) + if err != nil { + return l.cfg.OutputSubmitterRetryInterval, err + } + if !hasSubmittedStartTx { + return l.cfg.OutputSubmitterRetryInterval, nil + } + } + nextBlockNumber, err := l.FetchNextBlockNumber(ctx) if err != nil { return l.cfg.OutputSubmitterRetryInterval, err @@ -199,6 +245,34 @@ func (l *L2OutputSubmitter) trySubmitL2Output(ctx context.Context) (time.Duratio return 0, nil } +// tryStartValidator checks if the validator can start and tries to start it. +func (l *L2OutputSubmitter) tryStartValidator(ctx context.Context) (bool, error) { + cCtx, cCancel := context.WithTimeout(ctx, l.cfg.NetworkTimeout) + defer cCancel() + from := l.cfg.TxManager.From() + vaultStatus, err := l.valManagerContract.GetStatus(optsutils.NewSimpleCallOpts(cCtx), from) + if err != nil { + return false, fmt.Errorf("failed to fetch the vault status: %w", err) + } + + if vaultStatus == val.StatusNone || vaultStatus == val.StatusInactive || vaultStatus == val.StatusInJail || vaultStatus == val.StatusActive { + l.log.Info("vault has not started yet", "vaultStatus", vaultStatus) + return false, nil + } else if vaultStatus == val.StatusCanStart { + data, err := l.valManagerAbi.Pack("startValidator") + if err != nil { + return false, fmt.Errorf("failed to create start validator transaction data: %w", err) + } + + if txResponse := l.startValidatorTx(data); txResponse.Err != nil { + return false, txResponse.Err + } + + l.log.Info("startValidator successfully submitted") + } + return true, nil +} + // doSubmitL2Output submits l2 Output submission transaction. func (l *L2OutputSubmitter) doSubmitL2Output(ctx context.Context, nextBlockNumber *big.Int) error { output, err := l.FetchOutput(ctx, nextBlockNumber) @@ -232,11 +306,11 @@ func (l *L2OutputSubmitter) CalculateWaitTime(ctx context.Context, nextBlockNumb return defaultWaitTime } - hasEnoughDeposit, err := l.HasEnoughDeposit(ctx) + canSubmitOutput, err := l.CanSubmitOutput(ctx) if err != nil { return defaultWaitTime } - if !hasEnoughDeposit { + if !canSubmitOutput { return defaultWaitTime } @@ -268,26 +342,41 @@ func (l *L2OutputSubmitter) CalculateWaitTime(ctx context.Context, nextBlockNumb return 0 } -// HasEnoughDeposit checks if validator has enough deposit to bond when trying output submission. -func (l *L2OutputSubmitter) HasEnoughDeposit(ctx context.Context) (bool, error) { +// CanSubmitOutput checks if the validator can submit L2Output. +func (l *L2OutputSubmitter) CanSubmitOutput(ctx context.Context) (bool, error) { cCtx, cCancel := context.WithTimeout(ctx, l.cfg.NetworkTimeout) defer cCancel() from := l.cfg.TxManager.From() - balance, err := l.valpoolContract.BalanceOf(optsutils.NewSimpleCallOpts(cCtx), from) - if err != nil { - return false, fmt.Errorf("failed to fetch deposit amount: %w", err) - } - l.metr.RecordDepositAmount(balance) + if l.isValManagerEnabled { + vaultStatus, err := l.valManagerContract.GetStatus(optsutils.NewSimpleCallOpts(cCtx), from) + if err != nil { + return false, fmt.Errorf("failed to fetch the vault status: %w", err) + } - if balance.Cmp(l.requiredBondAmount) == -1 { - l.log.Warn( - "deposit is less than bond attempt amount", - "requiredBondAmount", l.requiredBondAmount, - "deposit", balance, - ) - return false, nil + if vaultStatus != val.StatusCanSubmitOutput { + l.log.Warn("vault has started, but currently has not enough tokens", "vaultStatus", val.StatusStarted) + return false, nil + } + + l.log.Info("vault status", "status", vaultStatus) + } else { + balance, err := l.valpoolContract.BalanceOf(optsutils.NewSimpleCallOpts(cCtx), from) + if err != nil { + return false, fmt.Errorf("failed to fetch deposit amount: %w", err) + } + l.metr.RecordDepositAmount(balance) + + if balance.Cmp(l.requiredBondAmount) == -1 { + l.log.Warn( + "deposit is less than bond attempt amount", + "requiredBondAmount", l.requiredBondAmount, + "deposit", balance, + ) + return false, nil + } + + l.log.Info("deposit amount", "deposit", balance) } - l.log.Info("deposit amount", "deposit", balance) return true, nil } @@ -352,13 +441,14 @@ func (r *roundInfo) canJoinRound() bool { return joinPriority || joinPublic } -// fetchCurrentRound fetches next validator address from ValidatorPool contract. +// fetchCurrentRound fetches next validator address from ValidatorPool or ValidatorManager contract. // It returns if current round is public round, and if selected for priority validator if it's a priority round. func (l *L2OutputSubmitter) fetchCurrentRound(ctx context.Context) (roundInfo, error) { cCtx, cCancel := context.WithTimeout(ctx, l.cfg.NetworkTimeout) defer cCancel() ri := roundInfo{canJoinPublicRound: l.cfg.OutputSubmitterAllowPublicRound} - nextValidator, err := l.valpoolContract.NextValidator(optsutils.NewSimpleCallOpts(cCtx)) + + nextValidator, err := l.getNextValidatorAddress(cCtx) if err != nil { l.log.Error("unable to get next validator address", "err", err) ri.isPublicRound = false @@ -421,9 +511,69 @@ func SubmitL2OutputTxData(abi *abi.ABI, output *eth.OutputResponse) ([]byte, err ) } +// getNextValidatorAddress selects the appropriate contract and retrieves the next validator address. +func (l *L2OutputSubmitter) getNextValidatorAddress(ctx context.Context) (common.Address, error) { + var contract interface { + NextValidator(opts *bind.CallOpts) (common.Address, error) + } + + if l.isValManagerEnabled { + contract = l.valManagerContract + } else { + contract = l.valpoolContract + } + + return contract.NextValidator(optsutils.NewSimpleCallOpts(ctx)) +} + +// startValidatorTx creates start validator tx candidate. +// It sends the candidate to txCandidates channel to process validator's tx candidates in order. +func (l *L2OutputSubmitter) startValidatorTx(data []byte) *txmgr.TxResponse { + gasTipCap, basefee, _, err := l.cfg.TxManager.SuggestGasPriceCaps(l.ctx) + if err != nil { + return &txmgr.TxResponse{ + Receipt: nil, + Err: fmt.Errorf("failed to get gas price info: %w", err), + } + } + gasFeeCap := txmgr.CalcGasFeeCap(basefee, gasTipCap) + + to := &l.cfg.ValidatorManagerAddr + estimatedGas, err := l.cfg.L1Client.EstimateGas(l.ctx, ethereum.CallMsg{ + From: l.cfg.TxManager.From(), + To: to, + GasFeeCap: gasFeeCap, + GasTipCap: gasTipCap, + Data: data, + }) + if err != nil { + return &txmgr.TxResponse{ + Receipt: nil, + Err: fmt.Errorf("failed to estimate gas: %w", err), + } + } + + return l.cfg.TxManager.SendTxCandidate(l.ctx, &txmgr.TxCandidate{ + TxData: data, + To: to, + GasLimit: estimatedGas * 3 / 2, + }) + +} + // submitL2OutputTx creates l2 output submit tx candidate and sends it to txCandidates channel to process validator's tx candidates in order. func (l *L2OutputSubmitter) submitL2OutputTx(data []byte) *txmgr.TxResponse { - layout, err := bindings.GetStorageLayout("ValidatorPool") + var name string + var accessListAddr common.Address + if l.isValManagerEnabled { + name = "ValidatorManager" + accessListAddr = l.cfg.ValidatorManagerAddr + } else { + name = "ValidatorPool" + accessListAddr = l.cfg.ValidatorPoolAddr + } + + layout, err := bindings.GetStorageLayout(name) if err != nil { return &txmgr.TxResponse{ Receipt: nil, @@ -434,19 +584,28 @@ func (l *L2OutputSubmitter) submitL2OutputTx(data []byte) *txmgr.TxResponse { var outputIndexSlot, priorityValidatorSlot common.Hash for _, entry := range layout.Storage { switch entry.Label { + // ValidatorPool case "nextUnbondOutputIndex": outputIndexSlot = common.BigToHash(big.NewInt(int64(entry.Slot))) case "nextPriorityValidator": priorityValidatorSlot = common.BigToHash(big.NewInt(int64(entry.Slot))) + // ValidatorManager + case "_nextPriorityValidator": + priorityValidatorSlot = common.BigToHash(big.NewInt(int64(entry.Slot))) } } - storageKeys := []common.Hash{outputIndexSlot, priorityValidatorSlot} + var storageKeys []common.Hash + if l.isValManagerEnabled { + storageKeys = []common.Hash{priorityValidatorSlot} + } else { + storageKeys = []common.Hash{outputIndexSlot, priorityValidatorSlot} + } // If provide accessList that is not actually accessed, the transaction may not be executed due to exceeding the estimated gas limit accessList := types.AccessList{ types.AccessTuple{ - Address: l.cfg.ValidatorPoolAddr, + Address: accessListAddr, StorageKeys: storageKeys, }, } @@ -487,3 +646,7 @@ func (l *L2OutputSubmitter) submitL2OutputTx(data []byte) *txmgr.TxResponse { func (l *L2OutputSubmitter) L2ooAbi() *abi.ABI { return l.l2ooABI } + +func (l *L2OutputSubmitter) ValManagerAbi() *abi.ABI { + return l.valManagerAbi +} diff --git a/kroma-validator/validator/status.go b/kroma-validator/validator/status.go new file mode 100644 index 000000000..e7fad6a53 --- /dev/null +++ b/kroma-validator/validator/status.go @@ -0,0 +1,13 @@ +package validator + +const ( + // StatusNone is regarded as a challenge is not in progress. + // The other status are regarded as a challenge is in progress. + StatusNone uint8 = iota + StatusInactive + StatusInJail + StatusActive + StatusCanStart + StatusStarted + StatusCanSubmitOutput +) From ef4fb7f1d72ce85a0d1d0ec52fcbc7d32f6a757c Mon Sep 17 00:00:00 2001 From: sm-stack Date: Tue, 2 Apr 2024 17:30:39 +0900 Subject: [PATCH 3/8] feat(e2e): add action tests for new validator system --- kroma-chain-ops/genesis/layer_one.go | 25 ++++ op-e2e/actions/l2_challenger.go | 6 +- op-e2e/actions/l2_validator.go | 105 ++++++++++---- op-e2e/actions/l2_validator_test.go | 129 ++++++++++++++++-- op-e2e/bridge_test.go | 1 - op-e2e/setup.go | 4 + op-e2e/system_test.go | 6 + .../deploy-config/devnetL1-template.json | 2 +- 8 files changed, 237 insertions(+), 41 deletions(-) diff --git a/kroma-chain-ops/genesis/layer_one.go b/kroma-chain-ops/genesis/layer_one.go index 029dd0dd6..4c729b0cf 100644 --- a/kroma-chain-ops/genesis/layer_one.go +++ b/kroma-chain-ops/genesis/layer_one.go @@ -192,6 +192,31 @@ func PostProcessL1DeveloperGenesis(stateDB *state.MemoryStateDB, deployments *L1 //setup beacon deposit contract log.Info("Set BeaconDepositContractCode") stateDB.SetCode(predeploys.BeaconDepositContractAddr, predeploys.BeaconDepositContractCode) + + //setup governance token balances on L1 + log.Info("Set GovernanceContract balance on L1") + if !stateDB.Exist(deployments.L1GovernanceTokenProxy) { + return fmt.Errorf("l1GovernanceToken proxy doesn't exist at %s", deployments.L1GovernanceTokenProxy) + } + + slot, err = getStorageSlot("GovernanceToken", "_balances") + if err != nil { + return err + } + + bigVal, success := new(big.Int).SetString("1000000000000000000000000", 10) + if !success { + return fmt.Errorf("failed to set governance token balance") + } + val = common.BigToHash(bigVal) + for _, account := range DevAccounts { + addrToBytes := append(make([]byte, 12), account.Bytes()...) + addrSlot := crypto.Keccak256Hash(append(addrToBytes, slot.Bytes()[:]...)) + stateDB.SetState(deployments.L1GovernanceTokenProxy, addrSlot, val) + + log.Info("Post process update", "name", "GovernanceToken", "address", deployments.L1GovernanceTokenProxy, "slot", addrSlot.Hex(), "afterVal", val.Hex()) + } + return nil } diff --git a/op-e2e/actions/l2_challenger.go b/op-e2e/actions/l2_challenger.go index 2109c1747..57ed5c49a 100644 --- a/op-e2e/actions/l2_challenger.go +++ b/op-e2e/actions/l2_challenger.go @@ -30,9 +30,9 @@ func (v *L2Validator) ActCreateChallenge(t Testing, outputIndex *big.Int) common return status == chal.StatusNone || status == chal.StatusChallengerTimeout }, "challenge is already in progress") - hasEnoughDeposit, err := v.challenger.HasEnoughDeposit(t.Ctx()) - require.NoError(t, err, "unable to check challenger deposit") - require.True(t, hasEnoughDeposit, "challenger not enough deposit to create challenge") + canCreateChallenge, err := v.challenger.CanCreateChallenge(t.Ctx()) + require.NoError(t, err, "unable to check challenger balance") + require.True(t, canCreateChallenge, "challenger not enough balance to create challenge") tx, err := v.challenger.CreateChallenge(t.Ctx(), outputRange) require.NoError(t, err, "unable to create create challenge tx") diff --git a/op-e2e/actions/l2_validator.go b/op-e2e/actions/l2_validator.go index d8245f7fa..24d22a35a 100644 --- a/op-e2e/actions/l2_validator.go +++ b/op-e2e/actions/l2_validator.go @@ -26,26 +26,30 @@ import ( ) type ValidatorCfg struct { - OutputOracleAddr common.Address - ColosseumAddr common.Address - SecurityCouncilAddr common.Address - ValidatorPoolAddr common.Address - ValidatorKey *ecdsa.PrivateKey - AllowNonFinalized bool + OutputOracleAddr common.Address + ColosseumAddr common.Address + SecurityCouncilAddr common.Address + ValidatorPoolAddr common.Address + ValidatorManagerAddr common.Address + AssetManagerAddr common.Address + ValidatorKey *ecdsa.PrivateKey + AllowNonFinalized bool } type L2Validator struct { - log log.Logger - l1 *ethclient.Client - l2os *validator.L2OutputSubmitter - challenger *validator.Challenger - guardian *validator.Guardian - address common.Address - privKey *ecdsa.PrivateKey - l2ooContractAddr common.Address - valPoolContractAddr common.Address - lastTx common.Hash - cfg *validator.Config + log log.Logger + l1 *ethclient.Client + l2os *validator.L2OutputSubmitter + challenger *validator.Challenger + guardian *validator.Guardian + address common.Address + privKey *ecdsa.PrivateKey + l2ooContractAddr common.Address + valPoolContractAddr common.Address + valManagerContractAddr common.Address + assetManagerContractAddr common.Address + lastTx common.Hash + cfg *validator.Config } func NewL2Validator(t Testing, log log.Logger, cfg *ValidatorCfg, l1 *ethclient.Client, l2 *ethclient.Client, rollupCl *sources.RollupClient) *L2Validator { @@ -66,6 +70,8 @@ func NewL2Validator(t Testing, log log.Logger, cfg *ValidatorCfg, l1 *ethclient. validatorCfg := validator.Config{ L2OutputOracleAddr: cfg.OutputOracleAddr, ValidatorPoolAddr: cfg.ValidatorPoolAddr, + ValidatorManagerAddr: cfg.ValidatorManagerAddr, + AssetManagerAddr: cfg.AssetManagerAddr, ColosseumAddr: cfg.ColosseumAddr, SecurityCouncilAddr: cfg.SecurityCouncilAddr, ChallengerPollInterval: time.Second, @@ -106,16 +112,18 @@ func NewL2Validator(t Testing, log log.Logger, cfg *ValidatorCfg, l1 *ethclient. require.NoError(t, err) return &L2Validator{ - log: log, - l1: l1, - l2os: l2os, - challenger: challenger, - guardian: guardian, - address: from, - privKey: cfg.ValidatorKey, - l2ooContractAddr: cfg.OutputOracleAddr, - valPoolContractAddr: cfg.ValidatorPoolAddr, - cfg: &validatorCfg, + log: log, + l1: l1, + l2os: l2os, + challenger: challenger, + guardian: guardian, + address: from, + privKey: cfg.ValidatorKey, + l2ooContractAddr: cfg.OutputOracleAddr, + valPoolContractAddr: cfg.ValidatorPoolAddr, + valManagerContractAddr: cfg.ValidatorManagerAddr, + assetManagerContractAddr: cfg.AssetManagerAddr, + cfg: &validatorCfg, } } @@ -198,9 +206,52 @@ func (v *L2Validator) ActDeposit(t Testing, depositAmount uint64) { v.sendTx(t, &v.valPoolContractAddr, new(big.Int).SetUint64(depositAmount), txData, 1) } +func (v *L2Validator) ActRegisterValidator(t Testing, assets *big.Int) { + valManagerABI, err := bindings.ValidatorManagerMetaData.GetAbi() + require.NoError(t, err) + + txData, err := valManagerABI.Pack( + "registerValidator", + assets, + uint8(10), + uint8(2), + ) + require.NoError(t, err) + + v.sendTx(t, &v.valManagerContractAddr, common.Big0, txData, 2) +} + +func (v *L2Validator) ActApprove(t Testing, amount uint64) { + tokenAddr := v.getGovTokenAddr(t) + governanceTokenABI, err := bindings.GovernanceTokenMetaData.GetAbi() + require.NoError(t, err) + + txData, err := governanceTokenABI.Pack("approve", &v.assetManagerContractAddr, new(big.Int).SetUint64(amount)) + require.NoError(t, err) + + v.sendTx(t, &tokenAddr, common.Big0, txData, 1) +} + func (v *L2Validator) fetchOutput(t Testing, blockNumber *big.Int) *eth.OutputResponse { output, err := v.l2os.FetchOutput(t.Ctx(), blockNumber) require.NoError(t, err) return output } + +func (v *L2Validator) getGovTokenAddr(t Testing) common.Address { + assetManagerABI, err := bindings.AssetManagerMetaData.GetAbi() + require.NoError(t, err) + + callData, err := assetManagerABI.Pack("ASSET_TOKEN") + require.NoError(t, err) + + returnData, err := v.l1.CallContract(t.Ctx(), ethereum.CallMsg{ + To: &v.assetManagerContractAddr, + Data: callData, + }, nil) + require.NoError(t, err) + + tokenAddr := common.BytesToAddress(returnData) + return tokenAddr +} diff --git a/op-e2e/actions/l2_validator_test.go b/op-e2e/actions/l2_validator_test.go index 4ea9f885c..7c6c0858e 100644 --- a/op-e2e/actions/l2_validator_test.go +++ b/op-e2e/actions/l2_validator_test.go @@ -1,6 +1,7 @@ package actions import ( + "math/big" "testing" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -10,6 +11,7 @@ import ( "github.com/stretchr/testify/require" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/kroma-network/kroma/kroma-bindings/bindings" @@ -21,7 +23,8 @@ func TestValidatorBatchType(t *testing.T) { name string f func(gt *testing.T, deltaTimeOffset *hexutil.Uint64) }{ - {"RunValidatorTest", RunValidatorTest}, + {"RunValidatorPoolTest", RunValidatorPoolTest}, + {"RunValidatorManagerTest", RunValidatorManagerTest}, } for _, test := range tests { test := test @@ -39,12 +42,13 @@ func TestValidatorBatchType(t *testing.T) { } } -func RunValidatorTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +func RunValidatorPoolTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { t := NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp.DeployConfig.L2GenesisDeltaTimeOffset = deltaTimeOffset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LevelDebug) + log := testlog.Logger(t, log.LvlDebug) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) rollupSeqCl := sequencer.RollupClient() @@ -52,12 +56,14 @@ func RunValidatorTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) validator := NewL2Validator(t, log, &ValidatorCfg{ - OutputOracleAddr: sd.DeploymentsL1.L2OutputOracleProxy, - ValidatorPoolAddr: sd.DeploymentsL1.ValidatorPoolProxy, - ColosseumAddr: sd.DeploymentsL1.ColosseumProxy, - SecurityCouncilAddr: sd.DeploymentsL1.SecurityCouncilProxy, - ValidatorKey: dp.Secrets.TrustedValidator, - AllowNonFinalized: false, + OutputOracleAddr: sd.DeploymentsL1.L2OutputOracleProxy, + ValidatorPoolAddr: sd.DeploymentsL1.ValidatorPoolProxy, + ValidatorManagerAddr: sd.DeploymentsL1.ValidatorManagerProxy, + AssetManagerAddr: sd.DeploymentsL1.AssetManagerProxy, + ColosseumAddr: sd.DeploymentsL1.ColosseumProxy, + SecurityCouncilAddr: sd.DeploymentsL1.SecurityCouncilProxy, + ValidatorKey: dp.Secrets.TrustedValidator, + AllowNonFinalized: false, }, miner.EthClient(), seqEngine.EthClient(), sequencer.RollupClient()) // L1 block @@ -119,3 +125,108 @@ func RunValidatorTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { require.NoError(t, err) require.Equal(t, eth.Bytes32(outputOnL1.OutputRoot), outputComputed.OutputRoot, "output roots must match") } + +func RunValidatorManagerTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { + t := NewDefaultTesting(gt) + dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) + dp.DeployConfig.L2GenesisDeltaTimeOffset = deltaTimeOffset + sd := e2eutils.Setup(t, dp, defaultAlloc) + log := testlog.Logger(t, log.LvlDebug) + miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) + + rollupSeqCl := sequencer.RollupClient() + batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + + validator := NewL2Validator(t, log, &ValidatorCfg{ + OutputOracleAddr: sd.DeploymentsL1.L2OutputOracleProxy, + ValidatorPoolAddr: sd.DeploymentsL1.ValidatorPoolProxy, + ValidatorManagerAddr: sd.DeploymentsL1.ValidatorManagerProxy, + AssetManagerAddr: sd.DeploymentsL1.AssetManagerProxy, + ColosseumAddr: sd.DeploymentsL1.ColosseumProxy, + SecurityCouncilAddr: sd.DeploymentsL1.SecurityCouncilProxy, + ValidatorKey: dp.Secrets.TrustedValidator, + AllowNonFinalized: false, + }, miner.EthClient(), seqEngine.EthClient(), sequencer.RollupClient()) + + for i := 0; i < 5; i++ { + // L1 block + miner.ActEmptyBlock(t) + // L2 block + sequencer.ActL1HeadSignal(t) + sequencer.ActL2PipelineFull(t) + sequencer.ActBuildToL1Head(t) + // submit and include in L1 + batcher.ActSubmitAll(t) + miner.includeL1Block(t, dp.Addresses.Batcher, 12) + // finalize the first and second L1 blocks, including the batch + miner.ActL1SafeNext(t) + miner.ActL1SafeNext(t) + miner.ActL1FinalizeNext(t) + miner.ActL1FinalizeNext(t) + // derive and see the L2 chain fully finalize + sequencer.ActL2PipelineFull(t) + sequencer.ActL1SafeSignal(t) + sequencer.ActL1FinalizedSignal(t) + } + + // deposit bond for validator + validator.ActDeposit(t, 1_000) + miner.includeL1Block(t, validator.address, 12) + // Submit 16 outputs to ValidatorPool + for i := 0; i < 16; i++ { + // submit to L1 + validator.ActSubmitL2Output(t) + // include output on L1 + miner.includeL1Block(t, validator.address, 12) + miner.ActEmptyBlock(t) + // Check submission was successful + receipt, err := miner.EthClient().TransactionReceipt(t.Ctx(), validator.LastSubmitL2OutputTx()) + require.NoError(t, err) + require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status, "submission failed") + } + + // approve governance token + validator.ActApprove(t, 1_000) + miner.includeL1Block(t, validator.address, 12) + + // register validator + validator.ActRegisterValidator(t, new(big.Int).SetUint64(1_000)) + miner.includeL1Block(t, validator.address, 12) + + require.Equal(t, sequencer.SyncStatus().UnsafeL2, sequencer.SyncStatus().FinalizedL2) + // create l2 output submission transactions until there is nothing left to submit + for { + waitTime := validator.CalculateWaitTime(t) + if waitTime > 0 { + break + } + // and submit it to L1 + validator.ActSubmitL2Output(t) + // include output on L1 + miner.includeL1Block(t, validator.address, 12) + miner.ActEmptyBlock(t) + // Check submission was successful + receipt, err := miner.EthClient().TransactionReceipt(t.Ctx(), validator.LastSubmitL2OutputTx()) + require.NoError(t, err) + require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status, "submission failed") + } + + // check that L1 stored the expected output root + outputOracleContract, err := bindings.NewL2OutputOracle(sd.DeploymentsL1.L2OutputOracleProxy, miner.EthClient()) + require.NoError(t, err) + // NOTE(chokobole): Comment these 2 lines because of the reason above. + // If Proto Dank Sharding is introduced, the below code fix may be restored. + // block := sequencer.SyncStatus().FinalizedL2 + // outputOnL1, err := outputOracleContract.GetL2OutputAfter(nil, new(big.Int).SetUint64(block.Number)) + blockNum, err := outputOracleContract.LatestBlockNumber(&bind.CallOpts{}) + require.NoError(t, err) + outputOnL1, err := outputOracleContract.GetL2OutputAfter(&bind.CallOpts{}, blockNum) + require.NoError(t, err) + block, err := seqEngine.EthClient().BlockByNumber(t.Ctx(), blockNum) + require.NoError(t, err) + require.Less(t, block.Time(), outputOnL1.Timestamp.Uint64(), "output is registered with L1 timestamp of L2 tx output submission, past L2 block") + outputComputed, err := sequencer.RollupClient().OutputAtBlock(t.Ctx(), blockNum.Uint64()) + require.NoError(t, err) + require.Equal(t, eth.Bytes32(outputOnL1.OutputRoot), outputComputed.OutputRoot, "output roots must match") +} diff --git a/op-e2e/bridge_test.go b/op-e2e/bridge_test.go index 6904eadda..acfdd351a 100644 --- a/op-e2e/bridge_test.go +++ b/op-e2e/bridge_test.go @@ -185,7 +185,6 @@ func TestBridgeGovernanceToken(t *testing.T) { bobL1Balance, err := l1Token.BalanceOf(&bind.CallOpts{}, l1Opts.From) require.NoError(t, err) - require.Zero(t, bobL1Balance.Uint64()) bobL2Balance, err := l2Token.BalanceOf(&bind.CallOpts{}, l2Opts.From) require.NoError(t, err) require.Equal(t, bobL2Balance, bridgeAmount) diff --git a/op-e2e/setup.go b/op-e2e/setup.go index ae7e46eec..c0a21a49a 100644 --- a/op-e2e/setup.go +++ b/op-e2e/setup.go @@ -809,6 +809,8 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste L2OOAddress: config.L1Deployments.L2OutputOracleProxy.Hex(), ColosseumAddress: config.L1Deployments.ColosseumProxy.Hex(), ValPoolAddress: config.L1Deployments.ValidatorPoolProxy.Hex(), + ValManagerAddress: config.L1Deployments.ValidatorManagerProxy.Hex(), + AssetManagerAddress: config.L1Deployments.AssetManagerProxy.Hex(), ChallengerPollInterval: 500 * time.Millisecond, TxMgrConfig: newTxMgrConfig(sys.EthInstances["l1"].WSEndpoint(), cfg.Secrets.TrustedValidator), AllowNonFinalized: cfg.NonFinalizedOutputs, @@ -867,6 +869,8 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste L2OOAddress: config.L1Deployments.L2OutputOracleProxy.Hex(), ColosseumAddress: config.L1Deployments.ColosseumProxy.Hex(), ValPoolAddress: config.L1Deployments.ValidatorPoolProxy.Hex(), + ValManagerAddress: config.L1Deployments.ValidatorManagerProxy.Hex(), + AssetManagerAddress: config.L1Deployments.AssetManagerProxy.Hex(), ChallengerPollInterval: 500 * time.Millisecond, ProverRPC: "http://0.0.0.0:0", TxMgrConfig: newTxMgrConfig(sys.EthInstances["l1"].WSEndpoint(), cfg.Secrets.Challenger1), diff --git a/op-e2e/system_test.go b/op-e2e/system_test.go index 2860d93e2..a2ffc9156 100644 --- a/op-e2e/system_test.go +++ b/op-e2e/system_test.go @@ -161,6 +161,9 @@ func TestL2OutputSubmitter(t *testing.T) { } func TestValidationReward(t *testing.T) { + // TODO(sm-stack): This test should be fixed to TestManualValidationReward. + // The reason why it is not working here is due to the transition happening before the reward is unbonded. + t.Skip("skip in CI") InitParallel(t) cfg := DefaultSystemConfig(t) @@ -191,6 +194,9 @@ func TestValidationReward(t *testing.T) { timeout := time.Duration(cfg.DeployConfig.FinalizationPeriodSeconds+30) * time.Second ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() + + // Call unbond to trigger the reward. + for { select { case evt := <-l2RewardedCh: diff --git a/packages/contracts/deploy-config/devnetL1-template.json b/packages/contracts/deploy-config/devnetL1-template.json index aa0f74a97..5c7d4b031 100644 --- a/packages/contracts/deploy-config/devnetL1-template.json +++ b/packages/contracts/deploy-config/devnetL1-template.json @@ -43,7 +43,7 @@ "validatorPoolRequiredBondAmount": "0x1", "validatorPoolMaxUnbond": 10, "validatorPoolRoundDuration": 4, - "validatorPoolTerminateOutputIndex": "0xffffffffffffffffffff", + "validatorPoolTerminateOutputIndex": "0xf", "validatorManagerTrustedValidator": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", "validatorManagerMinRegisterAmount": "0x1", "validatorManagerMinActivateAmount": "0x2", From be95e0ffc7ebcc31471fc27b537e58d7f4c0e7c3 Mon Sep 17 00:00:00 2001 From: sm-stack Date: Wed, 17 Apr 2024 15:45:26 +0900 Subject: [PATCH 4/8] chore: set required flags for devnet --- kroma-devnet/devnet/__init__.py | 6 ++++++ ops-devnet/docker-compose.yml | 2 ++ 2 files changed, 8 insertions(+) diff --git a/kroma-devnet/devnet/__init__.py b/kroma-devnet/devnet/__init__.py index dd868e329..7a5ca5b47 100644 --- a/kroma-devnet/devnet/__init__.py +++ b/kroma-devnet/devnet/__init__.py @@ -272,6 +272,10 @@ def devnet_deploy(paths): log.info(f'Using Colosseum {colosseum}') validator_pool = addresses['ValidatorPoolProxy'] log.info(f'Using ValidatorPool {validator_pool}') + validator_manager = addresses['ValidatorManagerProxy'] + log.info(f'Using ValidatorManager {validator_manager}') + asset_manager = addresses['AssetManagerProxy'] + log.info(f'Using AssetManager {asset_manager}') log.info('Bringing up `kroma-node`, `kroma-batcher` and `kroma-validator`.') run_command(['docker', 'compose', 'up', '-d', 'kroma-node', 'kroma-batcher', 'kroma-validator'], cwd=paths.ops_bedrock_dir, env={ @@ -279,6 +283,8 @@ def devnet_deploy(paths): 'L2OO_ADDRESS': l2_output_oracle, 'COLOSSEUM_ADDRESS': colosseum, 'VALPOOL_ADDRESS': validator_pool, + 'VALMANAGER_ADDRESS': validator_manager, + 'ASSETMANAGER_ADDRESS': asset_manager, 'SEQUENCER_BATCH_INBOX_ADDRESS': batch_inbox_address }) diff --git a/ops-devnet/docker-compose.yml b/ops-devnet/docker-compose.yml index 26c0cde50..b57772958 100644 --- a/ops-devnet/docker-compose.yml +++ b/ops-devnet/docker-compose.yml @@ -198,6 +198,8 @@ services: VALIDATOR_L2OO_ADDRESS: "${L2OO_ADDRESS}" VALIDATOR_COLOSSEUM_ADDRESS: "${COLOSSEUM_ADDRESS}" VALIDATOR_VALPOOL_ADDRESS: "${VALPOOL_ADDRESS}" + VALIDATOR_VALMANAGER_ADDRESS: "${VALMANAGER_ADDRESS}" + VALIDATOR_ASSETMANAGER_ADDRESS: "${ASSETMANAGER_ADDRESS}" VALIDATOR_PPROF_ENABLED: "true" VALIDATOR_METRICS_ENABLED: "true" VALIDATOR_ALLOW_NON_FINALIZED: "true" From 8ba2814d4f0be74b7d7c15b694c2ace57e117b55 Mon Sep 17 00:00:00 2001 From: sm-stack Date: Mon, 22 Apr 2024 01:26:08 +0900 Subject: [PATCH 5/8] fix(validator): add real-time update logic for terminate index of ValidatorPool --- kroma-validator/challenger.go | 16 +++++- kroma-validator/l2_output_submitter.go | 80 ++++++++++++++++++++++++-- 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/kroma-validator/challenger.go b/kroma-validator/challenger.go index 994d48259..991074211 100644 --- a/kroma-validator/challenger.go +++ b/kroma-validator/challenger.go @@ -56,7 +56,9 @@ type Challenger struct { l2BlockTime *big.Int checkpoint *big.Int requiredBondAmount *big.Int - isValManagerEnabled bool + + isValManagerEnabled bool + terminationIndex *big.Int l2OutputSubmittedSub ethereum.Subscription challengeCreatedSub ethereum.Subscription @@ -176,6 +178,14 @@ func (c *Challenger) InitConfig(ctx context.Context) error { } c.isValManagerEnabled = isTerminated + cCtx, cCancel = context.WithTimeout(ctx, c.cfg.NetworkTimeout) + defer cCancel() + terminationIndex, err := c.valpoolContract.TERMINATEOUTPUTINDEX(optsutils.NewSimpleCallOpts(cCtx)) + if err != nil { + return fmt.Errorf("failed to get termination index: %w", err) + } + c.terminationIndex = terminationIndex + return nil }) if err != nil { @@ -370,6 +380,10 @@ func (c *Challenger) subscribeL2OutputSubmitted() { select { case ev := <-c.l2OutputSubmittedEventChan: c.log.Info("watched output submitted event", "l2BlockNumber", ev.L2BlockNumber, "outputRoot", ev.OutputRoot, "outputIndex", ev.L2OutputIndex) + // if the emitted output index is greater than the termination output index, set the config to use the ValidatorManager + if ev.L2OutputIndex.Cmp(c.terminationIndex) > 0 { + c.isValManagerEnabled = true + } // if the emitted output index is less than or equal to the checkpoint, it is considered reorg occurred. if ev.L2OutputIndex.Cmp(c.checkpoint) <= 0 { c.wg.Add(1) diff --git a/kroma-validator/l2_output_submitter.go b/kroma-validator/l2_output_submitter.go index e9f6b1971..48b03e7f7 100644 --- a/kroma-validator/l2_output_submitter.go +++ b/kroma-validator/l2_output_submitter.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/event" "math/big" _ "net/http/pprof" "sync" @@ -42,7 +43,7 @@ type L2OutputSubmitter struct { log log.Logger metr metrics.Metricer - l2ooContract *bindings.L2OutputOracleCaller + l2ooContract *bindings.L2OutputOracle l2ooABI *abi.ABI valpoolContract *bindings.ValidatorPoolCaller valManagerContract *bindings.ValidatorManagerCaller @@ -53,15 +54,19 @@ type L2OutputSubmitter struct { requiredBondAmount *big.Int isValManagerEnabled bool + terminationIndex *big.Int - submitChan chan struct{} + outputSubmittedSub ethereum.Subscription + + submitChan chan struct{} + l2OutputSubmittedEventChan chan *bindings.L2OutputOracleOutputSubmitted wg sync.WaitGroup } // NewL2OutputSubmitter creates a new L2OutputSubmitter. func NewL2OutputSubmitter(cfg Config, l log.Logger, m metrics.Metricer) (*L2OutputSubmitter, error) { - l2ooContract, err := bindings.NewL2OutputOracleCaller(cfg.L2OutputOracleAddr, cfg.L1Client) + l2ooContract, err := bindings.NewL2OutputOracle(cfg.L2OutputOracleAddr, cfg.L1Client) if err != nil { return nil, err } @@ -152,6 +157,14 @@ func (l *L2OutputSubmitter) InitConfig(ctx context.Context) error { } l.isValManagerEnabled = isTerminated + cCtx, cCancel = context.WithTimeout(ctx, l.cfg.NetworkTimeout) + defer cCancel() + terminationIndex, err := l.valpoolContract.TERMINATEOUTPUTINDEX(optsutils.NewSimpleCallOpts(cCtx)) + if err != nil { + return fmt.Errorf("failed to get termination index: %w", err) + } + l.terminationIndex = terminationIndex + return nil }) if err != nil { @@ -161,6 +174,18 @@ func (l *L2OutputSubmitter) InitConfig(ctx context.Context) error { return nil } +func (l *L2OutputSubmitter) initSub() { + opts := optsutils.NewSimpleWatchOpts(l.ctx) + + l.l2OutputSubmittedEventChan = make(chan *bindings.L2OutputOracleOutputSubmitted) + l.outputSubmittedSub = event.ResubscribeErr(time.Second*10, func(ctx context.Context, err error) (event.Subscription, error) { + if err != nil { + l.log.Warn("resubscribing after failed OutputSubmitted event", "err", err) + } + return l.l2ooContract.WatchOutputSubmitted(opts, l.l2OutputSubmittedEventChan, nil, nil, nil) + }) +} + func (l *L2OutputSubmitter) Start(ctx context.Context) error { l.ctx, l.cancel = context.WithCancel(ctx) l.submitChan = make(chan struct{}, 1) @@ -168,22 +193,52 @@ func (l *L2OutputSubmitter) Start(ctx context.Context) error { if err := l.InitConfig(l.ctx); err != nil { return err } + l.initSub() l.wg.Add(1) - go l.loop() + go l.subscriptionLoop() + + l.wg.Add(1) + go l.submissionLoop() return nil } func (l *L2OutputSubmitter) Stop() error { + if l.outputSubmittedSub != nil { + l.outputSubmittedSub.Unsubscribe() + } + l.cancel() l.wg.Wait() + + if l.l2OutputSubmittedEventChan != nil { + close(l.l2OutputSubmittedEventChan) + } close(l.submitChan) return nil } -func (l *L2OutputSubmitter) loop() { +func (l *L2OutputSubmitter) subscriptionLoop() { + defer l.wg.Done() + + ticker := time.NewTicker(time.Minute) + defer ticker.Stop() + + for ; ; <-ticker.C { + select { + case <-l.ctx.Done(): + return + default: + l.subscribeL2OutputSubmitted() + + return + } + } +} + +func (l *L2OutputSubmitter) submissionLoop() { defer l.wg.Done() for ; ; <-l.submitChan { @@ -196,6 +251,21 @@ func (l *L2OutputSubmitter) loop() { } } +func (l *L2OutputSubmitter) subscribeL2OutputSubmitted() { + for { + select { + case ev := <-l.l2OutputSubmittedEventChan: + l.log.Info("watched output submitted event", "l2BlockNumber", ev.L2BlockNumber, "outputRoot", ev.OutputRoot, "outputIndex", ev.L2OutputIndex) + // if the emitted output index is greater than the termination output index, set the config to use the ValidatorManager + if ev.L2OutputIndex.Cmp(l.terminationIndex) > 0 { + l.isValManagerEnabled = true + } + case <-l.ctx.Done(): + return + } + } +} + func (l *L2OutputSubmitter) retryAfter(d time.Duration) { l.wg.Add(1) From fb4ee2491701e05c83e35820e29a9fba157a3246 Mon Sep 17 00:00:00 2001 From: sm-stack Date: Mon, 22 Apr 2024 22:27:47 +0900 Subject: [PATCH 6/8] fix(contracts): fix ValidatorPool to check termination by index --- kroma-bindings/bindings/validatorpool.go | 2 +- kroma-bindings/bindings/validatorpool_more.go | 2 +- .../contracts/contracts/L1/ValidatorPool.sol | 7 +---- .../contracts/test/ValidatorPool.t.sol | 29 ++++++++++++++----- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/kroma-bindings/bindings/validatorpool.go b/kroma-bindings/bindings/validatorpool.go index 62d6e209c..1768d238f 100644 --- a/kroma-bindings/bindings/validatorpool.go +++ b/kroma-bindings/bindings/validatorpool.go @@ -32,7 +32,7 @@ var ( // ValidatorPoolMetaData contains all meta data concerning the ValidatorPool contract. var ValidatorPoolMetaData = &bind.MetaData{ ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_l2OutputOracle\",\"type\":\"address\",\"internalType\":\"contractL2OutputOracle\"},{\"name\":\"_portal\",\"type\":\"address\",\"internalType\":\"contractKromaPortal\"},{\"name\":\"_securityCouncil\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_trustedValidator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_requiredBondAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_maxUnbond\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_roundDuration\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_terminateOutputIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"L2_ORACLE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractL2OutputOracle\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAX_UNBOND\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"PORTAL\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractKromaPortal\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"REQUIRED_BOND_AMOUNT\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint128\",\"internalType\":\"uint128\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"ROUND_DURATION\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"SECURITY_COUNCIL\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"TAX_DENOMINATOR\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint128\",\"internalType\":\"uint128\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"TAX_NUMERATOR\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint128\",\"internalType\":\"uint128\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"TERMINATE_OUTPUT_INDEX\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"TRUSTED_VALIDATOR\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"VAULT_REWARD_GAS_LIMIT\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addPendingBond\",\"inputs\":[{\"name\":\"_outputIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_challenger\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"_addr\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createBond\",\"inputs\":[{\"name\":\"_outputIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_expiresAt\",\"type\":\"uint128\",\"internalType\":\"uint128\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"deposit\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"getBond\",\"inputs\":[{\"name\":\"_outputIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structTypes.Bond\",\"components\":[{\"name\":\"amount\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"expiresAt\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getPendingBond\",\"inputs\":[{\"name\":\"_outputIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_challenger\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint128\",\"internalType\":\"uint128\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"increaseBond\",\"inputs\":[{\"name\":\"_outputIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_challenger\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"isTerminated\",\"inputs\":[{\"name\":\"_outputIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isValidator\",\"inputs\":[{\"name\":\"_addr\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"nextValidator\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"releasePendingBond\",\"inputs\":[{\"name\":\"_outputIndex\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_challenger\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_recipient\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"unbond\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"validatorCount\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"withdraw\",\"inputs\":[{\"name\":\"_amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdrawTo\",\"inputs\":[{\"name\":\"_to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"BondIncreased\",\"inputs\":[{\"name\":\"outputIndex\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"challenger\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint128\",\"indexed\":false,\"internalType\":\"uint128\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Bonded\",\"inputs\":[{\"name\":\"submitter\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"outputIndex\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"amount\",\"type\":\"uint128\",\"indexed\":false,\"internalType\":\"uint128\"},{\"name\":\"expiresAt\",\"type\":\"uint128\",\"indexed\":false,\"internalType\":\"uint128\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"uint8\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"PendingBondAdded\",\"inputs\":[{\"name\":\"outputIndex\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"challenger\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint128\",\"indexed\":false,\"internalType\":\"uint128\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"PendingBondReleased\",\"inputs\":[{\"name\":\"outputIndex\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"challenger\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint128\",\"indexed\":false,\"internalType\":\"uint128\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Unbonded\",\"inputs\":[{\"name\":\"outputIndex\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint128\",\"indexed\":false,\"internalType\":\"uint128\"}],\"anonymous\":false}]", - Bin: "0x6101806040523480156200001257600080fd5b5060405162002ea638038062002ea6833981016040819052620000359162000256565b6001600160a01b0380891660805287811660a05286811660c052851660e0526001600160801b038416610100526101208390526101608190526101408290526200007e6200008c565b5050505050505050620002e5565b600054610100900460ff1615808015620000ad5750600054600160ff909116105b80620000dd5750620000ca30620001be60201b62001b941760201c565b158015620000dd575060005460ff166001145b620001465760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156200016a576000805461ff0019166101001790555b62000174620001cd565b8015620001bb576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6001600160a01b03163b151590565b600054610100900460ff166200023a5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200013d565b60018055565b6001600160a01b0381168114620001bb57600080fd5b600080600080600080600080610100898b0312156200027457600080fd5b8851620002818162000240565b60208a0151909850620002948162000240565b60408a0151909750620002a78162000240565b60608a0151909650620002ba8162000240565b60808a015160a08b015160c08c015160e0909c01519a9d999c50979a91999098919650945092505050565b60805160a05160c05160e05161010051610120516101405161016051612aa562000401600039600081816103070152818161056801526111fe01526000818161040f0152610b8d0152600081816104e40152611fd40152600081816105ad01528181610db401528181610e35015281816115bc015281816115f401528181611c980152611e960152600081816103500152610bd80152600081816102b301528181611aaa0152611ee301526000818161023d01526124a90152600081816101cd0152818161086d01528181610af401528181610bfc0152818161114a0152818161117901528181611230015281816113ca01528181611541015281816117b90152818161209e015281816121b201526122e40152612aa56000f3fe6080604052600436106101b65760003560e01c806370a08231116100ec578063ad36d6cc1161008a578063d38dc7ee11610064578063d38dc7ee146105d7578063d8fe7642146105f7578063dd215c5d14610647578063facd743b1461066757600080fd5b8063ad36d6cc1461054b578063b7d636a51461059b578063d0e30db0146105cf57600080fd5b80638f09ade4116100c65780638f09ade4146104b2578063946765fd146104d2578063a51c9ace14610506578063ab91f1901461051b57600080fd5b806370a08231146104315780638129fc1c1461046757806382dae3aa1461047c57600080fd5b806339111af81161015957806354fd4d501161013357806354fd4d50146103725780635a544742146103c85780635df6a6bc146103e85780636641ea08146103fd57600080fd5b806339111af8146102f55780633a549046146103295780633ee4d4a31461033e57600080fd5b8063205c287811610195578063205c28781461025f5780632e1a7d4d1461028157806336086417146102a157806336b83469146102d557600080fd5b80621c2ff6146101bb5780630f43a6771461020c5780630ff754ea1461022b575b600080fd5b3480156101c757600080fd5b506101ef7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561021857600080fd5b506036545b604051908152602001610203565b34801561023757600080fd5b506101ef7f000000000000000000000000000000000000000000000000000000000000000081565b34801561026b57600080fd5b5061027f61027a36600461261b565b610687565b005b34801561028d57600080fd5b5061027f61029c366004612647565b6107ba565b3480156102ad57600080fd5b506101ef7f000000000000000000000000000000000000000000000000000000000000000081565b3480156102e157600080fd5b5061027f6102f0366004612660565b61086b565b34801561030157600080fd5b5061021d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561033557600080fd5b506101ef610adc565b34801561034a57600080fd5b506101ef7f000000000000000000000000000000000000000000000000000000000000000081565b34801561037e57600080fd5b506103bb6040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b604051610203919061270d565b3480156103d457600080fd5b5061027f6103e3366004612720565b610bfa565b3480156103f457600080fd5b5061027f610ea3565b34801561040957600080fd5b5061021d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561043d57600080fd5b5061021d61044c366004612750565b6001600160a01b031660009081526033602052604090205490565b34801561047357600080fd5b5061027f610f22565b34801561048857600080fd5b50610491601481565b6040516fffffffffffffffffffffffffffffffff9091168152602001610203565b3480156104be57600080fd5b506104916104cd366004612720565b611099565b3480156104de57600080fd5b5061021d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561051257600080fd5b50610491606481565b34801561052757600080fd5b50610532620186a081565b60405167ffffffffffffffff9091168152602001610203565b34801561055757600080fd5b5061058b610566366004612647565b7f00000000000000000000000000000000000000000000000000000000000000001090565b6040519015158152602001610203565b3480156105a757600080fd5b506104917f000000000000000000000000000000000000000000000000000000000000000081565b61027f611148565b3480156105e357600080fd5b5061027f6105f236600461278b565b6113bf565b34801561060357600080fd5b50610617610612366004612647565b611698565b6040805182516fffffffffffffffffffffffffffffffff9081168252602093840151169281019290925201610203565b34801561065357600080fd5b5061027f610662366004612720565b6117b7565b34801561067357600080fd5b5061058b610682366004612750565b611b1d565b61068f611ba3565b6001600160a01b0382166107105760405162461bcd60e51b815260206004820152603260248201527f56616c696461746f72506f6f6c3a2063616e6e6f74207769746864726177207460448201527f6f20746865207a65726f2061646472657373000000000000000000000000000060648201526084015b60405180910390fd5b61071a3382611bfc565b6000610737835a8460405180602001604052806000815250611e4e565b9050806107ac5760405162461bcd60e51b815260206004820152602260248201527f56616c696461746f72506f6f6c3a20455448207472616e73666572206661696c60448201527f65640000000000000000000000000000000000000000000000000000000000006064820152608401610707565b506107b660018055565b5050565b6107c2611ba3565b6107cc3382611bfc565b60006107e9335a8460405180602001604052806000815250611e4e565b90508061085e5760405162461bcd60e51b815260206004820152602260248201527f56616c696461746f72506f6f6c3a20455448207472616e73666572206661696c60448201527f65640000000000000000000000000000000000000000000000000000000000006064820152608401610707565b5061086860018055565b50565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e45e8f46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ed91906127b0565b6001600160a01b0316336001600160a01b0316146109735760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f72506f6f6c3a2073656e646572206973206e6f7420436f6c60448201527f6f737365756d00000000000000000000000000000000000000000000000000006064820152608401610707565b60008381526039602090815260408083206001600160a01b03861684529091529020546fffffffffffffffffffffffffffffffff1680610a1b5760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a207468652070656e64696e6720626f6e642060448201527f646f6573206e6f742065786973740000000000000000000000000000000000006064820152608401610707565b60008481526039602090815260408083206001600160a01b0387168452909152902080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169055610a7f826fffffffffffffffffffffffffffffffff8316611e6e565b6040516fffffffffffffffffffffffffffffffff821681526001600160a01b03808416919085169086907f8c95336a279406edcc768d685e8eb6667368a77d840a188144b8e3719423198f9060200160405180910390a450505050565b6038546000906001600160a01b031615610bd55760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166380446bd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7491906127cd565b9050804210610bc4576000610b898242612815565b90507f0000000000000000000000000000000000000000000000000000000000000000811115610bc2576001600160a01b039250505090565b505b50506038546001600160a01b031690565b507f000000000000000000000000000000000000000000000000000000000000000090565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e45e8f46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7c91906127b0565b6001600160a01b0316336001600160a01b031614610d025760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f72506f6f6c3a2073656e646572206973206e6f7420436f6c60448201527f6f737365756d00000000000000000000000000000000000000000000000000006064820152608401610707565b60008281526034602052604090208054427001000000000000000000000000000000009091046fffffffffffffffffffffffffffffffff161015610dae5760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a20746865206f757470757420697320616c7260448201527f656164792066696e616c697a65640000000000000000000000000000000000006064820152608401610707565b610dea827f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff16611bfc565b60008381526039602090815260408083206001600160a01b0386168085529083529281902080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff16908117909155905190815285917f2904258f32adf74dd8f23ad6f17ff50209896039c8ee3d4728ff55bd05c4cf2a910160405180910390a3505050565b6000610ead611fa2565b9050806108685760405162461bcd60e51b815260206004820152602960248201527f56616c696461746f72506f6f6c3a206e6f20626f6e6420746861742063616e2060448201527f626520756e626f6e6400000000000000000000000000000000000000000000006064820152608401610707565b600054610100900460ff1615808015610f425750600054600160ff909116105b80610f5c5750303b158015610f5c575060005460ff166001145b610fce5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610707565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561102c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61103461224a565b801561086857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b60008281526039602090815260408083206001600160a01b03851684529091528120546fffffffffffffffffffffffffffffffff16806111415760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a207468652070656e64696e6720626f6e642060448201527f646f6573206e6f742065786973740000000000000000000000000000000000006064820152608401610707565b9392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d1de856c7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663529933df6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f991906127cd565b6112247f0000000000000000000000000000000000000000000000000000000000000000600161282c565b61122e9190612844565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370872aa56040518163ffffffff1660e01b8152600401602060405180830381865afa15801561128c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b091906127cd565b6112ba919061282c565b6040518263ffffffff1660e01b81526004016112d891815260200190565b602060405180830381865afa1580156112f5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131991906127cd565b42106113b35760405162461bcd60e51b815260206004820152604260248201527f56616c696461746f72506f6f6c3a206f6e6c792063616e206465706f7369742060448201527f746f2056616c696461746f72506f6f6c206265666f7265207465726d696e617460648201527f6564000000000000000000000000000000000000000000000000000000000000608482015260a401610707565b6113bd3334611e6e565b565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461145d5760405162461bcd60e51b815260206004820152602b60248201527f56616c696461746f72506f6f6c3a2073656e646572206973206e6f74204c324f60448201527f75747075744f7261636c650000000000000000000000000000000000000000006064820152608401610707565b6000828152603460205260409020805470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16156115065760405162461bcd60e51b815260206004820152603c60248201527f56616c696461746f72506f6f6c3a20626f6e64206f662074686520676976656e60448201527f206f757470757420696e64657820616c726561647920657869737473000000006064820152608401610707565b61150e611fa2565b506040517fb0ea09a8000000000000000000000000000000000000000000000000000000008152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b0ea09a890602401602060405180830381865afa158015611590573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115b491906127b0565b90506115f2817f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff16611bfc565b7f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff9081167001000000000000000000000000000000009185169182028117845560408051918252602082019290925285916001600160a01b038416917f5ca130257b8f76f72ad2965efcbe166f3918d820e4a49956e70081ea311f97c4910160405180910390a36116926122c7565b50505050565b6040805180820190915260008082526020820152600082815260346020526040902080546fffffffffffffffffffffffffffffffff16158015906117025750805470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1615155b6117745760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f72506f6f6c3a2074686520626f6e6420646f6573206e6f7460448201527f20657869737400000000000000000000000000000000000000000000000000006064820152608401610707565b6040805180820190915290546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000090910416602082015292915050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e45e8f46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611815573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183991906127b0565b6001600160a01b0316336001600160a01b0316146118bf5760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f72506f6f6c3a2073656e646572206973206e6f7420436f6c60448201527f6f737365756d00000000000000000000000000000000000000000000000000006064820152608401610707565b60008281526034602052604090208054427001000000000000000000000000000000009091046fffffffffffffffffffffffffffffffff16101561196b5760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a20746865206f757470757420697320616c7260448201527f656164792066696e616c697a65640000000000000000000000000000000000006064820152608401610707565b60008381526039602090815260408083206001600160a01b03861684529091529020546fffffffffffffffffffffffffffffffff1680611a135760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a207468652070656e64696e6720626f6e642060448201527f646f6573206e6f742065786973740000000000000000000000000000000000006064820152608401610707565b60006064611a22601484612881565b611a2c91906128e8565b90506000611a3a8284612917565b60008781526039602090815260408083206001600160a01b038a811680865291845282852080547fffffffffffffffffffffffffffffffff000000000000000000000000000000009081169091558a549081166fffffffffffffffffffffffffffffffff91821688018216178b557f00000000000000000000000000000000000000000000000000000000000000009091168552603384529382902080548886160190559051928416835292935088917f383f9b8b5a1fc2ec555726eb895621a312042e18b764135fa12ef1a520ad30db910160405180910390a3505050505050565b6036546000908103611b3157506000919050565b6001600160a01b038216611b4757506000919050565b6001600160a01b0382166000818152603760205260409020546036805491929183908110611b7757611b77612948565b6000918252602090912001546001600160a01b0316149392505050565b6001600160a01b03163b151590565b600260015403611bf55760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610707565b6002600155565b6001600160a01b03821660009081526033602052604090205481811015611c8a5760405162461bcd60e51b8152602060048201526024808201527f56616c696461746f72506f6f6c3a20696e73756666696369656e742062616c6160448201527f6e636573000000000000000000000000000000000000000000000000000000006064820152608401610707565b611c948282612815565b90507f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff1681108015611cdb5750611cdb83611b1d565b15611e2e57603654600090611cf290600190612815565b90508015611daa576001600160a01b0384166000908152603760205260408120546036805491929184908110611d2a57611d2a612948565b600091825260209091200154603680546001600160a01b039092169250829184908110611d5957611d59612948565b600091825260208083209190910180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03948516179055929091168152603790915260409020555b6001600160a01b0384166000908152603760205260408120556036805480611dd457611dd4612977565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055019055505b6001600160a01b0390921660009081526033602052604090209190915550565b600080600080845160208601878a8af19695505050505050565b60018055565b6001600160a01b038216600090815260336020526040812054611e9290839061282c565b90507f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff168110158015611edc5750611eda83611b1d565b155b15611e2e577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031614611e2e57603680546001600160a01b03949094166000818152603760209081526040808320889055600188019094557f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b890960180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690921790915560339094529092209190915550565b60355460408051608081018252600080825260208201819052918101829052606081018290529091908290819060005b7f000000000000000000000000000000000000000000000000000000000000000081101561219d57600085815260346020526040902080546fffffffffffffffffffffffffffffffff8082169650919450700100000000000000000000000000000000900416421080159061205957506000846fffffffffffffffffffffffffffffffff16115b1561219d5760008581526034602052604080822091909155517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a25ae55790602401608060405180830381865afa1580156120ed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061211191906129a6565b91506121338260000151856fffffffffffffffffffffffffffffffff16611e6e565b81516040516fffffffffffffffffffffffffffffffff861681526001600160a01b039091169086907f7047a0fb8bfae78c0ebbd4117437945bb85240453235ac4fd2e55712eb5bf0c39060200160405180910390a361219182612495565b60019485019401611fd2565b801561223e5760358590556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663b4c302ff6121e2600188612815565b6040518263ffffffff1660e01b815260040161220091815260200190565b600060405180830381600087803b15801561221a57600080fd5b505af115801561222e573d6000803e3d6000fd5b5050505060019550505050505090565b60009550505050505090565b600054610100900460ff16611e685760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610707565b60365480158015906122db57506000603554115b1561246a5760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a25ae55760016035546123209190612815565b6040518263ffffffff1660e01b815260040161233e91815260200190565b608060405180830381865afa15801561235b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061237f91906129a6565b905060008282602001514341446001436123999190612815565b6040805160208101969096528501939093527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606092831b1691840191909152607483015240609482015260b4016040516020818303038152906040528051906020012060001c61240a9190612a49565b90506036818154811061241f5761241f612948565b600091825260209091200154603880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03909216919091179055506108689050565b603880547fffffffffffffffffffffffff000000000000000000000000000000000000000016905550565b805160608201516040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263c30af3889273420000000000000000000000000000000000000892620186a0927f21670f22000000000000000000000000000000000000000000000000000000009261253f926024016001600160a01b039290921682526fffffffffffffffffffffffffffffffff16602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b90921682526125d1939291600401612a5d565b600060405180830381600087803b1580156125eb57600080fd5b505af11580156125ff573d6000803e3d6000fd5b5050505050565b6001600160a01b038116811461086857600080fd5b6000806040838503121561262e57600080fd5b823561263981612606565b946020939093013593505050565b60006020828403121561265957600080fd5b5035919050565b60008060006060848603121561267557600080fd5b83359250602084013561268781612606565b9150604084013561269781612606565b809150509250925092565b6000815180845260005b818110156126c8576020818501810151868301820152016126ac565b818111156126da576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061114160208301846126a2565b6000806040838503121561273357600080fd5b82359150602083013561274581612606565b809150509250929050565b60006020828403121561276257600080fd5b813561114181612606565b6fffffffffffffffffffffffffffffffff8116811461086857600080fd5b6000806040838503121561279e57600080fd5b8235915060208301356127458161276d565b6000602082840312156127c257600080fd5b815161114181612606565b6000602082840312156127df57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612827576128276127e6565b500390565b6000821982111561283f5761283f6127e6565b500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561287c5761287c6127e6565b500290565b60006fffffffffffffffffffffffffffffffff808316818516818304811182151516156128b0576128b06127e6565b02949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006fffffffffffffffffffffffffffffffff8084168061290b5761290b6128b9565b92169190910492915050565b60006fffffffffffffffffffffffffffffffff83811690831681811015612940576129406127e6565b039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000608082840312156129b857600080fd5b6040516080810181811067ffffffffffffffff82111715612a02577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528251612a1081612606565b8152602083810151908201526040830151612a2a8161276d565b60408201526060830151612a3d8161276d565b60608201529392505050565b600082612a5857612a586128b9565b500690565b6001600160a01b038416815267ffffffffffffffff83166020820152606060408201526000612a8f60608301846126a2565b9594505050505056fea164736f6c634300080f000a", + Bin: "0x6101806040523480156200001257600080fd5b5060405162002d3638038062002d36833981016040819052620000359162000256565b6001600160a01b0380891660805287811660a05286811660c052851660e0526001600160801b038416610100526101208390526101608190526101408290526200007e6200008c565b5050505050505050620002e5565b600054610100900460ff1615808015620000ad5750600054600160ff909116105b80620000dd5750620000ca30620001be60201b62001a6f1760201c565b158015620000dd575060005460ff166001145b620001465760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156200016a576000805461ff0019166101001790555b62000174620001cd565b8015620001bb576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b6001600160a01b03163b151590565b600054610100900460ff166200023a5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b60648201526084016200013d565b60018055565b6001600160a01b0381168114620001bb57600080fd5b600080600080600080600080610100898b0312156200027457600080fd5b8851620002818162000240565b60208a0151909850620002948162000240565b60408a0151909750620002a78162000240565b60608a0151909650620002ba8162000240565b60808a015160a08b015160c08c015160e0909c01519a9d999c50979a91999098919650945092505050565b60805160a05160c05160e05161010051610120516101405161016051612943620003f36000396000818161030701528181610568015261114d01526000818161040f0152610b8d0152600081816104e40152611eaf0152600081816105ad01528181610db401528181610e3501528181611497015281816114cf01528181611b730152611d710152600081816103500152610bd80152600081816102b3015281816119850152611dbe01526000818161023d01526123840152600081816101cd0152818161086d01528181610af401528181610bfc01528181611175015281816112a50152818161141c0152818161169401528181611f790152818161208d01526121bf01526129436000f3fe6080604052600436106101b65760003560e01c806370a08231116100ec578063ad36d6cc1161008a578063d38dc7ee11610064578063d38dc7ee146105d7578063d8fe7642146105f7578063dd215c5d14610647578063facd743b1461066757600080fd5b8063ad36d6cc1461054b578063b7d636a51461059b578063d0e30db0146105cf57600080fd5b80638f09ade4116100c65780638f09ade4146104b2578063946765fd146104d2578063a51c9ace14610506578063ab91f1901461051b57600080fd5b806370a08231146104315780638129fc1c1461046757806382dae3aa1461047c57600080fd5b806339111af81161015957806354fd4d501161013357806354fd4d50146103725780635a544742146103c85780635df6a6bc146103e85780636641ea08146103fd57600080fd5b806339111af8146102f55780633a549046146103295780633ee4d4a31461033e57600080fd5b8063205c287811610195578063205c28781461025f5780632e1a7d4d1461028157806336086417146102a157806336b83469146102d557600080fd5b80621c2ff6146101bb5780630f43a6771461020c5780630ff754ea1461022b575b600080fd5b3480156101c757600080fd5b506101ef7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561021857600080fd5b506036545b604051908152602001610203565b34801561023757600080fd5b506101ef7f000000000000000000000000000000000000000000000000000000000000000081565b34801561026b57600080fd5b5061027f61027a3660046124f6565b610687565b005b34801561028d57600080fd5b5061027f61029c366004612522565b6107ba565b3480156102ad57600080fd5b506101ef7f000000000000000000000000000000000000000000000000000000000000000081565b3480156102e157600080fd5b5061027f6102f036600461253b565b61086b565b34801561030157600080fd5b5061021d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561033557600080fd5b506101ef610adc565b34801561034a57600080fd5b506101ef7f000000000000000000000000000000000000000000000000000000000000000081565b34801561037e57600080fd5b506103bb6040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b60405161020391906125e8565b3480156103d457600080fd5b5061027f6103e33660046125fb565b610bfa565b3480156103f457600080fd5b5061027f610ea3565b34801561040957600080fd5b5061021d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561043d57600080fd5b5061021d61044c36600461262b565b6001600160a01b031660009081526033602052604090205490565b34801561047357600080fd5b5061027f610f22565b34801561048857600080fd5b50610491601481565b6040516fffffffffffffffffffffffffffffffff9091168152602001610203565b3480156104be57600080fd5b506104916104cd3660046125fb565b611099565b3480156104de57600080fd5b5061021d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561051257600080fd5b50610491606481565b34801561052757600080fd5b50610532620186a081565b60405167ffffffffffffffff9091168152602001610203565b34801561055757600080fd5b5061058b610566366004612522565b7f00000000000000000000000000000000000000000000000000000000000000001090565b6040519015158152602001610203565b3480156105a757600080fd5b506104917f000000000000000000000000000000000000000000000000000000000000000081565b61027f611148565b3480156105e357600080fd5b5061027f6105f2366004612666565b61129a565b34801561060357600080fd5b50610617610612366004612522565b611573565b6040805182516fffffffffffffffffffffffffffffffff9081168252602093840151169281019290925201610203565b34801561065357600080fd5b5061027f6106623660046125fb565b611692565b34801561067357600080fd5b5061058b61068236600461262b565b6119f8565b61068f611a7e565b6001600160a01b0382166107105760405162461bcd60e51b815260206004820152603260248201527f56616c696461746f72506f6f6c3a2063616e6e6f74207769746864726177207460448201527f6f20746865207a65726f2061646472657373000000000000000000000000000060648201526084015b60405180910390fd5b61071a3382611ad7565b6000610737835a8460405180602001604052806000815250611d29565b9050806107ac5760405162461bcd60e51b815260206004820152602260248201527f56616c696461746f72506f6f6c3a20455448207472616e73666572206661696c60448201527f65640000000000000000000000000000000000000000000000000000000000006064820152608401610707565b506107b660018055565b5050565b6107c2611a7e565b6107cc3382611ad7565b60006107e9335a8460405180602001604052806000815250611d29565b90508061085e5760405162461bcd60e51b815260206004820152602260248201527f56616c696461746f72506f6f6c3a20455448207472616e73666572206661696c60448201527f65640000000000000000000000000000000000000000000000000000000000006064820152608401610707565b5061086860018055565b50565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e45e8f46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ed919061268b565b6001600160a01b0316336001600160a01b0316146109735760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f72506f6f6c3a2073656e646572206973206e6f7420436f6c60448201527f6f737365756d00000000000000000000000000000000000000000000000000006064820152608401610707565b60008381526039602090815260408083206001600160a01b03861684529091529020546fffffffffffffffffffffffffffffffff1680610a1b5760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a207468652070656e64696e6720626f6e642060448201527f646f6573206e6f742065786973740000000000000000000000000000000000006064820152608401610707565b60008481526039602090815260408083206001600160a01b0387168452909152902080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169055610a7f826fffffffffffffffffffffffffffffffff8316611d49565b6040516fffffffffffffffffffffffffffffffff821681526001600160a01b03808416919085169086907f8c95336a279406edcc768d685e8eb6667368a77d840a188144b8e3719423198f9060200160405180910390a450505050565b6038546000906001600160a01b031615610bd55760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166380446bd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7491906126a8565b9050804210610bc4576000610b8982426126f0565b90507f0000000000000000000000000000000000000000000000000000000000000000811115610bc2576001600160a01b039250505090565b505b50506038546001600160a01b031690565b507f000000000000000000000000000000000000000000000000000000000000000090565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e45e8f46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7c919061268b565b6001600160a01b0316336001600160a01b031614610d025760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f72506f6f6c3a2073656e646572206973206e6f7420436f6c60448201527f6f737365756d00000000000000000000000000000000000000000000000000006064820152608401610707565b60008281526034602052604090208054427001000000000000000000000000000000009091046fffffffffffffffffffffffffffffffff161015610dae5760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a20746865206f757470757420697320616c7260448201527f656164792066696e616c697a65640000000000000000000000000000000000006064820152608401610707565b610dea827f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff16611ad7565b60008381526039602090815260408083206001600160a01b0386168085529083529281902080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff16908117909155905190815285917f2904258f32adf74dd8f23ad6f17ff50209896039c8ee3d4728ff55bd05c4cf2a910160405180910390a3505050565b6000610ead611e7d565b9050806108685760405162461bcd60e51b815260206004820152602960248201527f56616c696461746f72506f6f6c3a206e6f20626f6e6420746861742063616e2060448201527f626520756e626f6e6400000000000000000000000000000000000000000000006064820152608401610707565b600054610100900460ff1615808015610f425750600054600160ff909116105b80610f5c5750303b158015610f5c575060005460ff166001145b610fce5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610707565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561102c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b611034612125565b801561086857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b60008281526039602090815260408083206001600160a01b03851684529091528120546fffffffffffffffffffffffffffffffff16806111415760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a207468652070656e64696e6720626f6e642060448201527f646f6573206e6f742065786973740000000000000000000000000000000000006064820152608401610707565b9392505050565b6111737f00000000000000000000000000000000000000000000000000000000000000006001612707565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636abcf5636040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906126a8565b1061128e5760405162461bcd60e51b815260206004820152604260248201527f56616c696461746f72506f6f6c3a206f6e6c792063616e206465706f7369742060448201527f746f2056616c696461746f72506f6f6c206265666f7265207465726d696e617460648201527f6564000000000000000000000000000000000000000000000000000000000000608482015260a401610707565b6112983334611d49565b565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146113385760405162461bcd60e51b815260206004820152602b60248201527f56616c696461746f72506f6f6c3a2073656e646572206973206e6f74204c324f60448201527f75747075744f7261636c650000000000000000000000000000000000000000006064820152608401610707565b6000828152603460205260409020805470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16156113e15760405162461bcd60e51b815260206004820152603c60248201527f56616c696461746f72506f6f6c3a20626f6e64206f662074686520676976656e60448201527f206f757470757420696e64657820616c726561647920657869737473000000006064820152608401610707565b6113e9611e7d565b506040517fb0ea09a8000000000000000000000000000000000000000000000000000000008152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b0ea09a890602401602060405180830381865afa15801561146b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148f919061268b565b90506114cd817f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff16611ad7565b7f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff9081167001000000000000000000000000000000009185169182028117845560408051918252602082019290925285916001600160a01b038416917f5ca130257b8f76f72ad2965efcbe166f3918d820e4a49956e70081ea311f97c4910160405180910390a361156d6121a2565b50505050565b6040805180820190915260008082526020820152600082815260346020526040902080546fffffffffffffffffffffffffffffffff16158015906115dd5750805470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1615155b61164f5760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f72506f6f6c3a2074686520626f6e6420646f6573206e6f7460448201527f20657869737400000000000000000000000000000000000000000000000000006064820152608401610707565b6040805180820190915290546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000090910416602082015292915050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e45e8f46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611714919061268b565b6001600160a01b0316336001600160a01b03161461179a5760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f72506f6f6c3a2073656e646572206973206e6f7420436f6c60448201527f6f737365756d00000000000000000000000000000000000000000000000000006064820152608401610707565b60008281526034602052604090208054427001000000000000000000000000000000009091046fffffffffffffffffffffffffffffffff1610156118465760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a20746865206f757470757420697320616c7260448201527f656164792066696e616c697a65640000000000000000000000000000000000006064820152608401610707565b60008381526039602090815260408083206001600160a01b03861684529091529020546fffffffffffffffffffffffffffffffff16806118ee5760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a207468652070656e64696e6720626f6e642060448201527f646f6573206e6f742065786973740000000000000000000000000000000000006064820152608401610707565b600060646118fd60148461271f565b6119079190612786565b9050600061191582846127b5565b60008781526039602090815260408083206001600160a01b038a811680865291845282852080547fffffffffffffffffffffffffffffffff000000000000000000000000000000009081169091558a549081166fffffffffffffffffffffffffffffffff91821688018216178b557f00000000000000000000000000000000000000000000000000000000000000009091168552603384529382902080548886160190559051928416835292935088917f383f9b8b5a1fc2ec555726eb895621a312042e18b764135fa12ef1a520ad30db910160405180910390a3505050505050565b6036546000908103611a0c57506000919050565b6001600160a01b038216611a2257506000919050565b6001600160a01b0382166000818152603760205260409020546036805491929183908110611a5257611a526127e6565b6000918252602090912001546001600160a01b0316149392505050565b6001600160a01b03163b151590565b600260015403611ad05760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610707565b6002600155565b6001600160a01b03821660009081526033602052604090205481811015611b655760405162461bcd60e51b8152602060048201526024808201527f56616c696461746f72506f6f6c3a20696e73756666696369656e742062616c6160448201527f6e636573000000000000000000000000000000000000000000000000000000006064820152608401610707565b611b6f82826126f0565b90507f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff1681108015611bb65750611bb6836119f8565b15611d0957603654600090611bcd906001906126f0565b90508015611c85576001600160a01b0384166000908152603760205260408120546036805491929184908110611c0557611c056127e6565b600091825260209091200154603680546001600160a01b039092169250829184908110611c3457611c346127e6565b600091825260208083209190910180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03948516179055929091168152603790915260409020555b6001600160a01b0384166000908152603760205260408120556036805480611caf57611caf612815565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055019055505b6001600160a01b0390921660009081526033602052604090209190915550565b600080600080845160208601878a8af19695505050505050565b60018055565b6001600160a01b038216600090815260336020526040812054611d6d908390612707565b90507f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff168110158015611db75750611db5836119f8565b155b15611d09577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031614611d0957603680546001600160a01b03949094166000818152603760209081526040808320889055600188019094557f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b890960180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690921790915560339094529092209190915550565b60355460408051608081018252600080825260208201819052918101829052606081018290529091908290819060005b7f000000000000000000000000000000000000000000000000000000000000000081101561207857600085815260346020526040902080546fffffffffffffffffffffffffffffffff80821696509194507001000000000000000000000000000000009004164210801590611f3457506000846fffffffffffffffffffffffffffffffff16115b156120785760008581526034602052604080822091909155517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a25ae55790602401608060405180830381865afa158015611fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fec9190612844565b915061200e8260000151856fffffffffffffffffffffffffffffffff16611d49565b81516040516fffffffffffffffffffffffffffffffff861681526001600160a01b039091169086907f7047a0fb8bfae78c0ebbd4117437945bb85240453235ac4fd2e55712eb5bf0c39060200160405180910390a361206c82612370565b60019485019401611ead565b80156121195760358590556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663b4c302ff6120bd6001886126f0565b6040518263ffffffff1660e01b81526004016120db91815260200190565b600060405180830381600087803b1580156120f557600080fd5b505af1158015612109573d6000803e3d6000fd5b5050505060019550505050505090565b60009550505050505090565b600054610100900460ff16611d435760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610707565b60365480158015906121b657506000603554115b156123455760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a25ae55760016035546121fb91906126f0565b6040518263ffffffff1660e01b815260040161221991815260200190565b608060405180830381865afa158015612236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225a9190612844565b9050600082826020015143414460014361227491906126f0565b6040805160208101969096528501939093527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606092831b1691840191909152607483015240609482015260b4016040516020818303038152906040528051906020012060001c6122e591906128e7565b9050603681815481106122fa576122fa6127e6565b600091825260209091200154603880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03909216919091179055506108689050565b603880547fffffffffffffffffffffffff000000000000000000000000000000000000000016905550565b805160608201516040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263c30af3889273420000000000000000000000000000000000000892620186a0927f21670f22000000000000000000000000000000000000000000000000000000009261241a926024016001600160a01b039290921682526fffffffffffffffffffffffffffffffff16602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b90921682526124ac9392916004016128fb565b600060405180830381600087803b1580156124c657600080fd5b505af11580156124da573d6000803e3d6000fd5b5050505050565b6001600160a01b038116811461086857600080fd5b6000806040838503121561250957600080fd5b8235612514816124e1565b946020939093013593505050565b60006020828403121561253457600080fd5b5035919050565b60008060006060848603121561255057600080fd5b833592506020840135612562816124e1565b91506040840135612572816124e1565b809150509250925092565b6000815180845260005b818110156125a357602081850181015186830182015201612587565b818111156125b5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611141602083018461257d565b6000806040838503121561260e57600080fd5b823591506020830135612620816124e1565b809150509250929050565b60006020828403121561263d57600080fd5b8135611141816124e1565b6fffffffffffffffffffffffffffffffff8116811461086857600080fd5b6000806040838503121561267957600080fd5b82359150602083013561262081612648565b60006020828403121561269d57600080fd5b8151611141816124e1565b6000602082840312156126ba57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612702576127026126c1565b500390565b6000821982111561271a5761271a6126c1565b500190565b60006fffffffffffffffffffffffffffffffff8083168185168183048111821515161561274e5761274e6126c1565b02949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006fffffffffffffffffffffffffffffffff808416806127a9576127a9612757565b92169190910492915050565b60006fffffffffffffffffffffffffffffffff838116908316818110156127de576127de6126c1565b039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60006080828403121561285657600080fd5b6040516080810181811067ffffffffffffffff821117156128a0577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405282516128ae816124e1565b81526020838101519082015260408301516128c881612648565b604082015260608301516128db81612648565b60608201529392505050565b6000826128f6576128f6612757565b500690565b6001600160a01b038416815267ffffffffffffffff8316602082015260606040820152600061292d606083018461257d565b9594505050505056fea164736f6c634300080f000a", } // ValidatorPoolABI is the input ABI used to generate the binding from. diff --git a/kroma-bindings/bindings/validatorpool_more.go b/kroma-bindings/bindings/validatorpool_more.go index ade9ad813..918e50cee 100644 --- a/kroma-bindings/bindings/validatorpool_more.go +++ b/kroma-bindings/bindings/validatorpool_more.go @@ -13,7 +13,7 @@ const ValidatorPoolStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract var ValidatorPoolStorageLayout = new(solc.StorageLayout) -var ValidatorPoolDeployedBin = "0x6080604052600436106101b65760003560e01c806370a08231116100ec578063ad36d6cc1161008a578063d38dc7ee11610064578063d38dc7ee146105d7578063d8fe7642146105f7578063dd215c5d14610647578063facd743b1461066757600080fd5b8063ad36d6cc1461054b578063b7d636a51461059b578063d0e30db0146105cf57600080fd5b80638f09ade4116100c65780638f09ade4146104b2578063946765fd146104d2578063a51c9ace14610506578063ab91f1901461051b57600080fd5b806370a08231146104315780638129fc1c1461046757806382dae3aa1461047c57600080fd5b806339111af81161015957806354fd4d501161013357806354fd4d50146103725780635a544742146103c85780635df6a6bc146103e85780636641ea08146103fd57600080fd5b806339111af8146102f55780633a549046146103295780633ee4d4a31461033e57600080fd5b8063205c287811610195578063205c28781461025f5780632e1a7d4d1461028157806336086417146102a157806336b83469146102d557600080fd5b80621c2ff6146101bb5780630f43a6771461020c5780630ff754ea1461022b575b600080fd5b3480156101c757600080fd5b506101ef7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561021857600080fd5b506036545b604051908152602001610203565b34801561023757600080fd5b506101ef7f000000000000000000000000000000000000000000000000000000000000000081565b34801561026b57600080fd5b5061027f61027a36600461261b565b610687565b005b34801561028d57600080fd5b5061027f61029c366004612647565b6107ba565b3480156102ad57600080fd5b506101ef7f000000000000000000000000000000000000000000000000000000000000000081565b3480156102e157600080fd5b5061027f6102f0366004612660565b61086b565b34801561030157600080fd5b5061021d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561033557600080fd5b506101ef610adc565b34801561034a57600080fd5b506101ef7f000000000000000000000000000000000000000000000000000000000000000081565b34801561037e57600080fd5b506103bb6040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b604051610203919061270d565b3480156103d457600080fd5b5061027f6103e3366004612720565b610bfa565b3480156103f457600080fd5b5061027f610ea3565b34801561040957600080fd5b5061021d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561043d57600080fd5b5061021d61044c366004612750565b6001600160a01b031660009081526033602052604090205490565b34801561047357600080fd5b5061027f610f22565b34801561048857600080fd5b50610491601481565b6040516fffffffffffffffffffffffffffffffff9091168152602001610203565b3480156104be57600080fd5b506104916104cd366004612720565b611099565b3480156104de57600080fd5b5061021d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561051257600080fd5b50610491606481565b34801561052757600080fd5b50610532620186a081565b60405167ffffffffffffffff9091168152602001610203565b34801561055757600080fd5b5061058b610566366004612647565b7f00000000000000000000000000000000000000000000000000000000000000001090565b6040519015158152602001610203565b3480156105a757600080fd5b506104917f000000000000000000000000000000000000000000000000000000000000000081565b61027f611148565b3480156105e357600080fd5b5061027f6105f236600461278b565b6113bf565b34801561060357600080fd5b50610617610612366004612647565b611698565b6040805182516fffffffffffffffffffffffffffffffff9081168252602093840151169281019290925201610203565b34801561065357600080fd5b5061027f610662366004612720565b6117b7565b34801561067357600080fd5b5061058b610682366004612750565b611b1d565b61068f611ba3565b6001600160a01b0382166107105760405162461bcd60e51b815260206004820152603260248201527f56616c696461746f72506f6f6c3a2063616e6e6f74207769746864726177207460448201527f6f20746865207a65726f2061646472657373000000000000000000000000000060648201526084015b60405180910390fd5b61071a3382611bfc565b6000610737835a8460405180602001604052806000815250611e4e565b9050806107ac5760405162461bcd60e51b815260206004820152602260248201527f56616c696461746f72506f6f6c3a20455448207472616e73666572206661696c60448201527f65640000000000000000000000000000000000000000000000000000000000006064820152608401610707565b506107b660018055565b5050565b6107c2611ba3565b6107cc3382611bfc565b60006107e9335a8460405180602001604052806000815250611e4e565b90508061085e5760405162461bcd60e51b815260206004820152602260248201527f56616c696461746f72506f6f6c3a20455448207472616e73666572206661696c60448201527f65640000000000000000000000000000000000000000000000000000000000006064820152608401610707565b5061086860018055565b50565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e45e8f46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ed91906127b0565b6001600160a01b0316336001600160a01b0316146109735760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f72506f6f6c3a2073656e646572206973206e6f7420436f6c60448201527f6f737365756d00000000000000000000000000000000000000000000000000006064820152608401610707565b60008381526039602090815260408083206001600160a01b03861684529091529020546fffffffffffffffffffffffffffffffff1680610a1b5760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a207468652070656e64696e6720626f6e642060448201527f646f6573206e6f742065786973740000000000000000000000000000000000006064820152608401610707565b60008481526039602090815260408083206001600160a01b0387168452909152902080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169055610a7f826fffffffffffffffffffffffffffffffff8316611e6e565b6040516fffffffffffffffffffffffffffffffff821681526001600160a01b03808416919085169086907f8c95336a279406edcc768d685e8eb6667368a77d840a188144b8e3719423198f9060200160405180910390a450505050565b6038546000906001600160a01b031615610bd55760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166380446bd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7491906127cd565b9050804210610bc4576000610b898242612815565b90507f0000000000000000000000000000000000000000000000000000000000000000811115610bc2576001600160a01b039250505090565b505b50506038546001600160a01b031690565b507f000000000000000000000000000000000000000000000000000000000000000090565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e45e8f46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7c91906127b0565b6001600160a01b0316336001600160a01b031614610d025760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f72506f6f6c3a2073656e646572206973206e6f7420436f6c60448201527f6f737365756d00000000000000000000000000000000000000000000000000006064820152608401610707565b60008281526034602052604090208054427001000000000000000000000000000000009091046fffffffffffffffffffffffffffffffff161015610dae5760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a20746865206f757470757420697320616c7260448201527f656164792066696e616c697a65640000000000000000000000000000000000006064820152608401610707565b610dea827f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff16611bfc565b60008381526039602090815260408083206001600160a01b0386168085529083529281902080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff16908117909155905190815285917f2904258f32adf74dd8f23ad6f17ff50209896039c8ee3d4728ff55bd05c4cf2a910160405180910390a3505050565b6000610ead611fa2565b9050806108685760405162461bcd60e51b815260206004820152602960248201527f56616c696461746f72506f6f6c3a206e6f20626f6e6420746861742063616e2060448201527f626520756e626f6e6400000000000000000000000000000000000000000000006064820152608401610707565b600054610100900460ff1615808015610f425750600054600160ff909116105b80610f5c5750303b158015610f5c575060005460ff166001145b610fce5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610707565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561102c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61103461224a565b801561086857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b60008281526039602090815260408083206001600160a01b03851684529091528120546fffffffffffffffffffffffffffffffff16806111415760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a207468652070656e64696e6720626f6e642060448201527f646f6573206e6f742065786973740000000000000000000000000000000000006064820152608401610707565b9392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d1de856c7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663529933df6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f991906127cd565b6112247f0000000000000000000000000000000000000000000000000000000000000000600161282c565b61122e9190612844565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370872aa56040518163ffffffff1660e01b8152600401602060405180830381865afa15801561128c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b091906127cd565b6112ba919061282c565b6040518263ffffffff1660e01b81526004016112d891815260200190565b602060405180830381865afa1580156112f5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131991906127cd565b42106113b35760405162461bcd60e51b815260206004820152604260248201527f56616c696461746f72506f6f6c3a206f6e6c792063616e206465706f7369742060448201527f746f2056616c696461746f72506f6f6c206265666f7265207465726d696e617460648201527f6564000000000000000000000000000000000000000000000000000000000000608482015260a401610707565b6113bd3334611e6e565b565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461145d5760405162461bcd60e51b815260206004820152602b60248201527f56616c696461746f72506f6f6c3a2073656e646572206973206e6f74204c324f60448201527f75747075744f7261636c650000000000000000000000000000000000000000006064820152608401610707565b6000828152603460205260409020805470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16156115065760405162461bcd60e51b815260206004820152603c60248201527f56616c696461746f72506f6f6c3a20626f6e64206f662074686520676976656e60448201527f206f757470757420696e64657820616c726561647920657869737473000000006064820152608401610707565b61150e611fa2565b506040517fb0ea09a8000000000000000000000000000000000000000000000000000000008152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b0ea09a890602401602060405180830381865afa158015611590573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115b491906127b0565b90506115f2817f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff16611bfc565b7f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff9081167001000000000000000000000000000000009185169182028117845560408051918252602082019290925285916001600160a01b038416917f5ca130257b8f76f72ad2965efcbe166f3918d820e4a49956e70081ea311f97c4910160405180910390a36116926122c7565b50505050565b6040805180820190915260008082526020820152600082815260346020526040902080546fffffffffffffffffffffffffffffffff16158015906117025750805470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1615155b6117745760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f72506f6f6c3a2074686520626f6e6420646f6573206e6f7460448201527f20657869737400000000000000000000000000000000000000000000000000006064820152608401610707565b6040805180820190915290546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000090910416602082015292915050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e45e8f46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611815573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183991906127b0565b6001600160a01b0316336001600160a01b0316146118bf5760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f72506f6f6c3a2073656e646572206973206e6f7420436f6c60448201527f6f737365756d00000000000000000000000000000000000000000000000000006064820152608401610707565b60008281526034602052604090208054427001000000000000000000000000000000009091046fffffffffffffffffffffffffffffffff16101561196b5760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a20746865206f757470757420697320616c7260448201527f656164792066696e616c697a65640000000000000000000000000000000000006064820152608401610707565b60008381526039602090815260408083206001600160a01b03861684529091529020546fffffffffffffffffffffffffffffffff1680611a135760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a207468652070656e64696e6720626f6e642060448201527f646f6573206e6f742065786973740000000000000000000000000000000000006064820152608401610707565b60006064611a22601484612881565b611a2c91906128e8565b90506000611a3a8284612917565b60008781526039602090815260408083206001600160a01b038a811680865291845282852080547fffffffffffffffffffffffffffffffff000000000000000000000000000000009081169091558a549081166fffffffffffffffffffffffffffffffff91821688018216178b557f00000000000000000000000000000000000000000000000000000000000000009091168552603384529382902080548886160190559051928416835292935088917f383f9b8b5a1fc2ec555726eb895621a312042e18b764135fa12ef1a520ad30db910160405180910390a3505050505050565b6036546000908103611b3157506000919050565b6001600160a01b038216611b4757506000919050565b6001600160a01b0382166000818152603760205260409020546036805491929183908110611b7757611b77612948565b6000918252602090912001546001600160a01b0316149392505050565b6001600160a01b03163b151590565b600260015403611bf55760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610707565b6002600155565b6001600160a01b03821660009081526033602052604090205481811015611c8a5760405162461bcd60e51b8152602060048201526024808201527f56616c696461746f72506f6f6c3a20696e73756666696369656e742062616c6160448201527f6e636573000000000000000000000000000000000000000000000000000000006064820152608401610707565b611c948282612815565b90507f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff1681108015611cdb5750611cdb83611b1d565b15611e2e57603654600090611cf290600190612815565b90508015611daa576001600160a01b0384166000908152603760205260408120546036805491929184908110611d2a57611d2a612948565b600091825260209091200154603680546001600160a01b039092169250829184908110611d5957611d59612948565b600091825260208083209190910180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03948516179055929091168152603790915260409020555b6001600160a01b0384166000908152603760205260408120556036805480611dd457611dd4612977565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055019055505b6001600160a01b0390921660009081526033602052604090209190915550565b600080600080845160208601878a8af19695505050505050565b60018055565b6001600160a01b038216600090815260336020526040812054611e9290839061282c565b90507f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff168110158015611edc5750611eda83611b1d565b155b15611e2e577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031614611e2e57603680546001600160a01b03949094166000818152603760209081526040808320889055600188019094557f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b890960180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690921790915560339094529092209190915550565b60355460408051608081018252600080825260208201819052918101829052606081018290529091908290819060005b7f000000000000000000000000000000000000000000000000000000000000000081101561219d57600085815260346020526040902080546fffffffffffffffffffffffffffffffff8082169650919450700100000000000000000000000000000000900416421080159061205957506000846fffffffffffffffffffffffffffffffff16115b1561219d5760008581526034602052604080822091909155517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a25ae55790602401608060405180830381865afa1580156120ed573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061211191906129a6565b91506121338260000151856fffffffffffffffffffffffffffffffff16611e6e565b81516040516fffffffffffffffffffffffffffffffff861681526001600160a01b039091169086907f7047a0fb8bfae78c0ebbd4117437945bb85240453235ac4fd2e55712eb5bf0c39060200160405180910390a361219182612495565b60019485019401611fd2565b801561223e5760358590556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663b4c302ff6121e2600188612815565b6040518263ffffffff1660e01b815260040161220091815260200190565b600060405180830381600087803b15801561221a57600080fd5b505af115801561222e573d6000803e3d6000fd5b5050505060019550505050505090565b60009550505050505090565b600054610100900460ff16611e685760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610707565b60365480158015906122db57506000603554115b1561246a5760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a25ae55760016035546123209190612815565b6040518263ffffffff1660e01b815260040161233e91815260200190565b608060405180830381865afa15801561235b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061237f91906129a6565b905060008282602001514341446001436123999190612815565b6040805160208101969096528501939093527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606092831b1691840191909152607483015240609482015260b4016040516020818303038152906040528051906020012060001c61240a9190612a49565b90506036818154811061241f5761241f612948565b600091825260209091200154603880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03909216919091179055506108689050565b603880547fffffffffffffffffffffffff000000000000000000000000000000000000000016905550565b805160608201516040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263c30af3889273420000000000000000000000000000000000000892620186a0927f21670f22000000000000000000000000000000000000000000000000000000009261253f926024016001600160a01b039290921682526fffffffffffffffffffffffffffffffff16602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b90921682526125d1939291600401612a5d565b600060405180830381600087803b1580156125eb57600080fd5b505af11580156125ff573d6000803e3d6000fd5b5050505050565b6001600160a01b038116811461086857600080fd5b6000806040838503121561262e57600080fd5b823561263981612606565b946020939093013593505050565b60006020828403121561265957600080fd5b5035919050565b60008060006060848603121561267557600080fd5b83359250602084013561268781612606565b9150604084013561269781612606565b809150509250925092565b6000815180845260005b818110156126c8576020818501810151868301820152016126ac565b818111156126da576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061114160208301846126a2565b6000806040838503121561273357600080fd5b82359150602083013561274581612606565b809150509250929050565b60006020828403121561276257600080fd5b813561114181612606565b6fffffffffffffffffffffffffffffffff8116811461086857600080fd5b6000806040838503121561279e57600080fd5b8235915060208301356127458161276d565b6000602082840312156127c257600080fd5b815161114181612606565b6000602082840312156127df57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612827576128276127e6565b500390565b6000821982111561283f5761283f6127e6565b500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561287c5761287c6127e6565b500290565b60006fffffffffffffffffffffffffffffffff808316818516818304811182151516156128b0576128b06127e6565b02949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006fffffffffffffffffffffffffffffffff8084168061290b5761290b6128b9565b92169190910492915050565b60006fffffffffffffffffffffffffffffffff83811690831681811015612940576129406127e6565b039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000608082840312156129b857600080fd5b6040516080810181811067ffffffffffffffff82111715612a02577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528251612a1081612606565b8152602083810151908201526040830151612a2a8161276d565b60408201526060830151612a3d8161276d565b60608201529392505050565b600082612a5857612a586128b9565b500690565b6001600160a01b038416815267ffffffffffffffff83166020820152606060408201526000612a8f60608301846126a2565b9594505050505056fea164736f6c634300080f000a" +var ValidatorPoolDeployedBin = "0x6080604052600436106101b65760003560e01c806370a08231116100ec578063ad36d6cc1161008a578063d38dc7ee11610064578063d38dc7ee146105d7578063d8fe7642146105f7578063dd215c5d14610647578063facd743b1461066757600080fd5b8063ad36d6cc1461054b578063b7d636a51461059b578063d0e30db0146105cf57600080fd5b80638f09ade4116100c65780638f09ade4146104b2578063946765fd146104d2578063a51c9ace14610506578063ab91f1901461051b57600080fd5b806370a08231146104315780638129fc1c1461046757806382dae3aa1461047c57600080fd5b806339111af81161015957806354fd4d501161013357806354fd4d50146103725780635a544742146103c85780635df6a6bc146103e85780636641ea08146103fd57600080fd5b806339111af8146102f55780633a549046146103295780633ee4d4a31461033e57600080fd5b8063205c287811610195578063205c28781461025f5780632e1a7d4d1461028157806336086417146102a157806336b83469146102d557600080fd5b80621c2ff6146101bb5780630f43a6771461020c5780630ff754ea1461022b575b600080fd5b3480156101c757600080fd5b506101ef7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561021857600080fd5b506036545b604051908152602001610203565b34801561023757600080fd5b506101ef7f000000000000000000000000000000000000000000000000000000000000000081565b34801561026b57600080fd5b5061027f61027a3660046124f6565b610687565b005b34801561028d57600080fd5b5061027f61029c366004612522565b6107ba565b3480156102ad57600080fd5b506101ef7f000000000000000000000000000000000000000000000000000000000000000081565b3480156102e157600080fd5b5061027f6102f036600461253b565b61086b565b34801561030157600080fd5b5061021d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561033557600080fd5b506101ef610adc565b34801561034a57600080fd5b506101ef7f000000000000000000000000000000000000000000000000000000000000000081565b34801561037e57600080fd5b506103bb6040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b60405161020391906125e8565b3480156103d457600080fd5b5061027f6103e33660046125fb565b610bfa565b3480156103f457600080fd5b5061027f610ea3565b34801561040957600080fd5b5061021d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561043d57600080fd5b5061021d61044c36600461262b565b6001600160a01b031660009081526033602052604090205490565b34801561047357600080fd5b5061027f610f22565b34801561048857600080fd5b50610491601481565b6040516fffffffffffffffffffffffffffffffff9091168152602001610203565b3480156104be57600080fd5b506104916104cd3660046125fb565b611099565b3480156104de57600080fd5b5061021d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561051257600080fd5b50610491606481565b34801561052757600080fd5b50610532620186a081565b60405167ffffffffffffffff9091168152602001610203565b34801561055757600080fd5b5061058b610566366004612522565b7f00000000000000000000000000000000000000000000000000000000000000001090565b6040519015158152602001610203565b3480156105a757600080fd5b506104917f000000000000000000000000000000000000000000000000000000000000000081565b61027f611148565b3480156105e357600080fd5b5061027f6105f2366004612666565b61129a565b34801561060357600080fd5b50610617610612366004612522565b611573565b6040805182516fffffffffffffffffffffffffffffffff9081168252602093840151169281019290925201610203565b34801561065357600080fd5b5061027f6106623660046125fb565b611692565b34801561067357600080fd5b5061058b61068236600461262b565b6119f8565b61068f611a7e565b6001600160a01b0382166107105760405162461bcd60e51b815260206004820152603260248201527f56616c696461746f72506f6f6c3a2063616e6e6f74207769746864726177207460448201527f6f20746865207a65726f2061646472657373000000000000000000000000000060648201526084015b60405180910390fd5b61071a3382611ad7565b6000610737835a8460405180602001604052806000815250611d29565b9050806107ac5760405162461bcd60e51b815260206004820152602260248201527f56616c696461746f72506f6f6c3a20455448207472616e73666572206661696c60448201527f65640000000000000000000000000000000000000000000000000000000000006064820152608401610707565b506107b660018055565b5050565b6107c2611a7e565b6107cc3382611ad7565b60006107e9335a8460405180602001604052806000815250611d29565b90508061085e5760405162461bcd60e51b815260206004820152602260248201527f56616c696461746f72506f6f6c3a20455448207472616e73666572206661696c60448201527f65640000000000000000000000000000000000000000000000000000000000006064820152608401610707565b5061086860018055565b50565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e45e8f46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ed919061268b565b6001600160a01b0316336001600160a01b0316146109735760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f72506f6f6c3a2073656e646572206973206e6f7420436f6c60448201527f6f737365756d00000000000000000000000000000000000000000000000000006064820152608401610707565b60008381526039602090815260408083206001600160a01b03861684529091529020546fffffffffffffffffffffffffffffffff1680610a1b5760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a207468652070656e64696e6720626f6e642060448201527f646f6573206e6f742065786973740000000000000000000000000000000000006064820152608401610707565b60008481526039602090815260408083206001600160a01b0387168452909152902080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169055610a7f826fffffffffffffffffffffffffffffffff8316611d49565b6040516fffffffffffffffffffffffffffffffff821681526001600160a01b03808416919085169086907f8c95336a279406edcc768d685e8eb6667368a77d840a188144b8e3719423198f9060200160405180910390a450505050565b6038546000906001600160a01b031615610bd55760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166380446bd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7491906126a8565b9050804210610bc4576000610b8982426126f0565b90507f0000000000000000000000000000000000000000000000000000000000000000811115610bc2576001600160a01b039250505090565b505b50506038546001600160a01b031690565b507f000000000000000000000000000000000000000000000000000000000000000090565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e45e8f46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7c919061268b565b6001600160a01b0316336001600160a01b031614610d025760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f72506f6f6c3a2073656e646572206973206e6f7420436f6c60448201527f6f737365756d00000000000000000000000000000000000000000000000000006064820152608401610707565b60008281526034602052604090208054427001000000000000000000000000000000009091046fffffffffffffffffffffffffffffffff161015610dae5760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a20746865206f757470757420697320616c7260448201527f656164792066696e616c697a65640000000000000000000000000000000000006064820152608401610707565b610dea827f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff16611ad7565b60008381526039602090815260408083206001600160a01b0386168085529083529281902080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff16908117909155905190815285917f2904258f32adf74dd8f23ad6f17ff50209896039c8ee3d4728ff55bd05c4cf2a910160405180910390a3505050565b6000610ead611e7d565b9050806108685760405162461bcd60e51b815260206004820152602960248201527f56616c696461746f72506f6f6c3a206e6f20626f6e6420746861742063616e2060448201527f626520756e626f6e6400000000000000000000000000000000000000000000006064820152608401610707565b600054610100900460ff1615808015610f425750600054600160ff909116105b80610f5c5750303b158015610f5c575060005460ff166001145b610fce5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610707565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561102c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b611034612125565b801561086857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b60008281526039602090815260408083206001600160a01b03851684529091528120546fffffffffffffffffffffffffffffffff16806111415760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a207468652070656e64696e6720626f6e642060448201527f646f6573206e6f742065786973740000000000000000000000000000000000006064820152608401610707565b9392505050565b6111737f00000000000000000000000000000000000000000000000000000000000000006001612707565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636abcf5636040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f591906126a8565b1061128e5760405162461bcd60e51b815260206004820152604260248201527f56616c696461746f72506f6f6c3a206f6e6c792063616e206465706f7369742060448201527f746f2056616c696461746f72506f6f6c206265666f7265207465726d696e617460648201527f6564000000000000000000000000000000000000000000000000000000000000608482015260a401610707565b6112983334611d49565b565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146113385760405162461bcd60e51b815260206004820152602b60248201527f56616c696461746f72506f6f6c3a2073656e646572206973206e6f74204c324f60448201527f75747075744f7261636c650000000000000000000000000000000000000000006064820152608401610707565b6000828152603460205260409020805470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16156113e15760405162461bcd60e51b815260206004820152603c60248201527f56616c696461746f72506f6f6c3a20626f6e64206f662074686520676976656e60448201527f206f757470757420696e64657820616c726561647920657869737473000000006064820152608401610707565b6113e9611e7d565b506040517fb0ea09a8000000000000000000000000000000000000000000000000000000008152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b0ea09a890602401602060405180830381865afa15801561146b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061148f919061268b565b90506114cd817f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff16611ad7565b7f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff9081167001000000000000000000000000000000009185169182028117845560408051918252602082019290925285916001600160a01b038416917f5ca130257b8f76f72ad2965efcbe166f3918d820e4a49956e70081ea311f97c4910160405180910390a361156d6121a2565b50505050565b6040805180820190915260008082526020820152600082815260346020526040902080546fffffffffffffffffffffffffffffffff16158015906115dd5750805470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1615155b61164f5760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f72506f6f6c3a2074686520626f6e6420646f6573206e6f7460448201527f20657869737400000000000000000000000000000000000000000000000000006064820152608401610707565b6040805180820190915290546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000090910416602082015292915050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639e45e8f46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611714919061268b565b6001600160a01b0316336001600160a01b03161461179a5760405162461bcd60e51b815260206004820152602660248201527f56616c696461746f72506f6f6c3a2073656e646572206973206e6f7420436f6c60448201527f6f737365756d00000000000000000000000000000000000000000000000000006064820152608401610707565b60008281526034602052604090208054427001000000000000000000000000000000009091046fffffffffffffffffffffffffffffffff1610156118465760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a20746865206f757470757420697320616c7260448201527f656164792066696e616c697a65640000000000000000000000000000000000006064820152608401610707565b60008381526039602090815260408083206001600160a01b03861684529091529020546fffffffffffffffffffffffffffffffff16806118ee5760405162461bcd60e51b815260206004820152602e60248201527f56616c696461746f72506f6f6c3a207468652070656e64696e6720626f6e642060448201527f646f6573206e6f742065786973740000000000000000000000000000000000006064820152608401610707565b600060646118fd60148461271f565b6119079190612786565b9050600061191582846127b5565b60008781526039602090815260408083206001600160a01b038a811680865291845282852080547fffffffffffffffffffffffffffffffff000000000000000000000000000000009081169091558a549081166fffffffffffffffffffffffffffffffff91821688018216178b557f00000000000000000000000000000000000000000000000000000000000000009091168552603384529382902080548886160190559051928416835292935088917f383f9b8b5a1fc2ec555726eb895621a312042e18b764135fa12ef1a520ad30db910160405180910390a3505050505050565b6036546000908103611a0c57506000919050565b6001600160a01b038216611a2257506000919050565b6001600160a01b0382166000818152603760205260409020546036805491929183908110611a5257611a526127e6565b6000918252602090912001546001600160a01b0316149392505050565b6001600160a01b03163b151590565b600260015403611ad05760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610707565b6002600155565b6001600160a01b03821660009081526033602052604090205481811015611b655760405162461bcd60e51b8152602060048201526024808201527f56616c696461746f72506f6f6c3a20696e73756666696369656e742062616c6160448201527f6e636573000000000000000000000000000000000000000000000000000000006064820152608401610707565b611b6f82826126f0565b90507f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff1681108015611bb65750611bb6836119f8565b15611d0957603654600090611bcd906001906126f0565b90508015611c85576001600160a01b0384166000908152603760205260408120546036805491929184908110611c0557611c056127e6565b600091825260209091200154603680546001600160a01b039092169250829184908110611c3457611c346127e6565b600091825260208083209190910180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03948516179055929091168152603790915260409020555b6001600160a01b0384166000908152603760205260408120556036805480611caf57611caf612815565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055019055505b6001600160a01b0390921660009081526033602052604090209190915550565b600080600080845160208601878a8af19695505050505050565b60018055565b6001600160a01b038216600090815260336020526040812054611d6d908390612707565b90507f00000000000000000000000000000000000000000000000000000000000000006fffffffffffffffffffffffffffffffff168110158015611db75750611db5836119f8565b155b15611d09577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031614611d0957603680546001600160a01b03949094166000818152603760209081526040808320889055600188019094557f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b890960180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690921790915560339094529092209190915550565b60355460408051608081018252600080825260208201819052918101829052606081018290529091908290819060005b7f000000000000000000000000000000000000000000000000000000000000000081101561207857600085815260346020526040902080546fffffffffffffffffffffffffffffffff80821696509194507001000000000000000000000000000000009004164210801590611f3457506000846fffffffffffffffffffffffffffffffff16115b156120785760008581526034602052604080822091909155517fa25ae557000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a25ae55790602401608060405180830381865afa158015611fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fec9190612844565b915061200e8260000151856fffffffffffffffffffffffffffffffff16611d49565b81516040516fffffffffffffffffffffffffffffffff861681526001600160a01b039091169086907f7047a0fb8bfae78c0ebbd4117437945bb85240453235ac4fd2e55712eb5bf0c39060200160405180910390a361206c82612370565b60019485019401611ead565b80156121195760358590556001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663b4c302ff6120bd6001886126f0565b6040518263ffffffff1660e01b81526004016120db91815260200190565b600060405180830381600087803b1580156120f557600080fd5b505af1158015612109573d6000803e3d6000fd5b5050505060019550505050505090565b60009550505050505090565b600054610100900460ff16611d435760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610707565b60365480158015906121b657506000603554115b156123455760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a25ae55760016035546121fb91906126f0565b6040518263ffffffff1660e01b815260040161221991815260200190565b608060405180830381865afa158015612236573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061225a9190612844565b9050600082826020015143414460014361227491906126f0565b6040805160208101969096528501939093527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606092831b1691840191909152607483015240609482015260b4016040516020818303038152906040528051906020012060001c6122e591906128e7565b9050603681815481106122fa576122fa6127e6565b600091825260209091200154603880547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03909216919091179055506108689050565b603880547fffffffffffffffffffffffff000000000000000000000000000000000000000016905550565b805160608201516040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263c30af3889273420000000000000000000000000000000000000892620186a0927f21670f22000000000000000000000000000000000000000000000000000000009261241a926024016001600160a01b039290921682526fffffffffffffffffffffffffffffffff16602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b90921682526124ac9392916004016128fb565b600060405180830381600087803b1580156124c657600080fd5b505af11580156124da573d6000803e3d6000fd5b5050505050565b6001600160a01b038116811461086857600080fd5b6000806040838503121561250957600080fd5b8235612514816124e1565b946020939093013593505050565b60006020828403121561253457600080fd5b5035919050565b60008060006060848603121561255057600080fd5b833592506020840135612562816124e1565b91506040840135612572816124e1565b809150509250925092565b6000815180845260005b818110156125a357602081850181015186830182015201612587565b818111156125b5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611141602083018461257d565b6000806040838503121561260e57600080fd5b823591506020830135612620816124e1565b809150509250929050565b60006020828403121561263d57600080fd5b8135611141816124e1565b6fffffffffffffffffffffffffffffffff8116811461086857600080fd5b6000806040838503121561267957600080fd5b82359150602083013561262081612648565b60006020828403121561269d57600080fd5b8151611141816124e1565b6000602082840312156126ba57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612702576127026126c1565b500390565b6000821982111561271a5761271a6126c1565b500190565b60006fffffffffffffffffffffffffffffffff8083168185168183048111821515161561274e5761274e6126c1565b02949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006fffffffffffffffffffffffffffffffff808416806127a9576127a9612757565b92169190910492915050565b60006fffffffffffffffffffffffffffffffff838116908316818110156127de576127de6126c1565b039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60006080828403121561285657600080fd5b6040516080810181811067ffffffffffffffff821117156128a0577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405282516128ae816124e1565b81526020838101519082015260408301516128c881612648565b604082015260608301516128db81612648565b60608201529392505050565b6000826128f6576128f6612757565b500690565b6001600160a01b038416815267ffffffffffffffff8316602082015260606040820152600061292d606083018461257d565b9594505050505056fea164736f6c634300080f000a" func init() { diff --git a/packages/contracts/contracts/L1/ValidatorPool.sol b/packages/contracts/contracts/L1/ValidatorPool.sol index 725188ee0..e8a957c43 100644 --- a/packages/contracts/contracts/L1/ValidatorPool.sol +++ b/packages/contracts/contracts/L1/ValidatorPool.sol @@ -231,12 +231,7 @@ contract ValidatorPool is ReentrancyGuardUpgradeable, ISemver { */ function deposit() external payable { require( - block.timestamp < - L2_ORACLE.computeL2Timestamp( - L2_ORACLE.startingBlockNumber() + - (TERMINATE_OUTPUT_INDEX + 1) * - L2_ORACLE.SUBMISSION_INTERVAL() - ), + L2_ORACLE.nextOutputIndex() < TERMINATE_OUTPUT_INDEX + 1, "ValidatorPool: only can deposit to ValidatorPool before terminated" ); diff --git a/packages/contracts/contracts/test/ValidatorPool.t.sol b/packages/contracts/contracts/test/ValidatorPool.t.sol index 51076ae3d..000857a41 100644 --- a/packages/contracts/contracts/test/ValidatorPool.t.sol +++ b/packages/contracts/contracts/test/ValidatorPool.t.sol @@ -796,13 +796,28 @@ contract ValidatorPool_SystemUpgrade_Test is ValidatorSystemUpgrade_Initializer } function test_deposit_afterSystemUpgrade_reverts() external { - vm.warp( - oracle.computeL2Timestamp( - oracle.startingBlockNumber() + - (pool.TERMINATE_OUTPUT_INDEX() + 1) * - oracle.SUBMISSION_INTERVAL() - ) - ); + vm.prank(trusted); + pool.deposit{ value: trusted.balance }(); + + bool poolTerminated; + for (uint256 i; i <= terminateOutputIndex + 1; i++) { + uint256 nextOutputIndex = oracle.nextOutputIndex(); + poolTerminated = pool.isTerminated(nextOutputIndex); + if (nextOutputIndex <= terminateOutputIndex) { + assertFalse(poolTerminated); + } else { + assertTrue(poolTerminated); + } + + warpToSubmitTime(); + uint256 nextBlockNumber = oracle.nextBlockNumber(); + bytes32 outputRoot = keccak256(abi.encode(nextBlockNumber)); + vm.prank(pool.nextValidator()); + mockOracle.addOutput(outputRoot, nextBlockNumber); + } + + vm.deal(trusted, requiredBondAmount); + vm.prank(trusted); vm.expectRevert("ValidatorPool: only can deposit to ValidatorPool before terminated"); pool.deposit{ value: requiredBondAmount }(); From e39459d3edd479b0e9ec94b925d34a654fc94dec Mon Sep 17 00:00:00 2001 From: sm-stack Date: Mon, 22 Apr 2024 22:52:47 +0900 Subject: [PATCH 7/8] fix(validator): remove inJail status in the validator client --- kroma-validator/l2_output_submitter.go | 49 +++++++++++++++++++------- kroma-validator/validator/status.go | 1 - 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/kroma-validator/l2_output_submitter.go b/kroma-validator/l2_output_submitter.go index 48b03e7f7..01ec8f1e7 100644 --- a/kroma-validator/l2_output_submitter.go +++ b/kroma-validator/l2_output_submitter.go @@ -325,21 +325,34 @@ func (l *L2OutputSubmitter) tryStartValidator(ctx context.Context) (bool, error) return false, fmt.Errorf("failed to fetch the vault status: %w", err) } - if vaultStatus == val.StatusNone || vaultStatus == val.StatusInactive || vaultStatus == val.StatusInJail || vaultStatus == val.StatusActive { - l.log.Info("vault has not started yet", "vaultStatus", vaultStatus) + if vaultStatus == val.StatusNone || vaultStatus == val.StatusInactive || vaultStatus == val.StatusActive { + l.log.Info("vault has not started yet", "currentStatus", vaultStatus) return false, nil - } else if vaultStatus == val.StatusCanStart { - data, err := l.valManagerAbi.Pack("startValidator") - if err != nil { - return false, fmt.Errorf("failed to create start validator transaction data: %w", err) - } + } - if txResponse := l.startValidatorTx(data); txResponse.Err != nil { - return false, txResponse.Err - } + if vaultStatus == val.StatusCanSubmitOutput { + l.log.Info("vault has started, no need to start again", "currentStatus", val.StatusStarted) + return false, nil + } + + if isInJail, err := l.isInJail(ctx); err != nil { + return false, err + } else if isInJail { + l.log.Warn("validator is in jail") + return false, nil + } + + data, err := l.valManagerAbi.Pack("startValidator") + if err != nil { + return false, fmt.Errorf("failed to create start validator transaction data: %w", err) + } - l.log.Info("startValidator successfully submitted") + if txResponse := l.startValidatorTx(data); txResponse.Err != nil { + return false, txResponse.Err } + + l.log.Info("startValidator successfully submitted") + return true, nil } @@ -424,7 +437,7 @@ func (l *L2OutputSubmitter) CanSubmitOutput(ctx context.Context) (bool, error) { } if vaultStatus != val.StatusCanSubmitOutput { - l.log.Warn("vault has started, but currently has not enough tokens", "vaultStatus", val.StatusStarted) + l.log.Warn("vault has started, but currently has not enough tokens", "currentStatus", val.StatusStarted) return false, nil } @@ -499,6 +512,18 @@ func (l *L2OutputSubmitter) getLeftTimeForL2Blocks(currentBlockNumber *big.Int, return waitDuration } +func (l *L2OutputSubmitter) isInJail(ctx context.Context) (bool, error) { + cCtx, cCancel := context.WithTimeout(ctx, l.cfg.NetworkTimeout) + defer cCancel() + from := l.cfg.TxManager.From() + isInJail, err := l.valManagerContract.InJail(optsutils.NewSimpleCallOpts(cCtx), from) + if err != nil { + return false, fmt.Errorf("failed to fetch the jail status: %w", err) + } + + return isInJail, nil +} + type roundInfo struct { isPublicRound bool isPriorityValidator bool diff --git a/kroma-validator/validator/status.go b/kroma-validator/validator/status.go index e7fad6a53..7a2b8b5c5 100644 --- a/kroma-validator/validator/status.go +++ b/kroma-validator/validator/status.go @@ -5,7 +5,6 @@ const ( // The other status are regarded as a challenge is in progress. StatusNone uint8 = iota StatusInactive - StatusInJail StatusActive StatusCanStart StatusStarted From c0adc232e6afa799236e69631dac131087637532 Mon Sep 17 00:00:00 2001 From: sm-stack Date: Wed, 24 Apr 2024 01:26:05 +0900 Subject: [PATCH 8/8] feat(validator): apply PR Reviews --- kroma-chain-ops/genesis/layer_one.go | 4 +- kroma-validator/challenger.go | 107 +++--- kroma-validator/config.go | 1 - kroma-validator/l2_output_submitter.go | 357 +++++++----------- kroma-validator/status.go | 10 + kroma-validator/validator/status.go | 12 - op-e2e/actions/l2_challenger.go | 2 +- op-e2e/actions/l2_validator.go | 36 +- op-e2e/actions/l2_validator_test.go | 81 ++-- ops-devnet/docker-compose.yml | 2 + .../contracts/test/ValidatorPool.t.sol | 22 +- 11 files changed, 250 insertions(+), 384 deletions(-) create mode 100644 kroma-validator/status.go delete mode 100644 kroma-validator/validator/status.go diff --git a/kroma-chain-ops/genesis/layer_one.go b/kroma-chain-ops/genesis/layer_one.go index 4c729b0cf..9a505cec2 100644 --- a/kroma-chain-ops/genesis/layer_one.go +++ b/kroma-chain-ops/genesis/layer_one.go @@ -194,7 +194,7 @@ func PostProcessL1DeveloperGenesis(stateDB *state.MemoryStateDB, deployments *L1 stateDB.SetCode(predeploys.BeaconDepositContractAddr, predeploys.BeaconDepositContractCode) //setup governance token balances on L1 - log.Info("Set GovernanceContract balance on L1") + log.Info("Set GovernanceToken balance on L1") if !stateDB.Exist(deployments.L1GovernanceTokenProxy) { return fmt.Errorf("l1GovernanceToken proxy doesn't exist at %s", deployments.L1GovernanceTokenProxy) } @@ -211,7 +211,7 @@ func PostProcessL1DeveloperGenesis(stateDB *state.MemoryStateDB, deployments *L1 val = common.BigToHash(bigVal) for _, account := range DevAccounts { addrToBytes := append(make([]byte, 12), account.Bytes()...) - addrSlot := crypto.Keccak256Hash(append(addrToBytes, slot.Bytes()[:]...)) + addrSlot := crypto.Keccak256Hash(append(addrToBytes, slot.Bytes()...)) stateDB.SetState(deployments.L1GovernanceTokenProxy, addrSlot, val) log.Info("Post process update", "name", "GovernanceToken", "address", deployments.L1GovernanceTokenProxy, "slot", addrSlot.Hex(), "afterVal", val.Hex()) diff --git a/kroma-validator/challenger.go b/kroma-validator/challenger.go index 991074211..8f21a7dac 100644 --- a/kroma-validator/challenger.go +++ b/kroma-validator/challenger.go @@ -25,7 +25,6 @@ import ( "github.com/kroma-network/kroma/kroma-bindings/bindings" chal "github.com/kroma-network/kroma/kroma-validator/challenge" "github.com/kroma-network/kroma/kroma-validator/metrics" - val "github.com/kroma-network/kroma/kroma-validator/validator" ) var deletedOutputRoot = [32]byte{} @@ -56,9 +55,7 @@ type Challenger struct { l2BlockTime *big.Int checkpoint *big.Int requiredBondAmount *big.Int - - isValManagerEnabled bool - terminationIndex *big.Int + poolTerminationIndex *big.Int l2OutputSubmittedSub ethereum.Subscription challengeCreatedSub ethereum.Subscription @@ -160,38 +157,20 @@ func (c *Challenger) InitConfig(ctx context.Context) error { } c.requiredBondAmount = requiredBondAmount - cCtx, cCancel = context.WithTimeout(ctx, c.cfg.NetworkTimeout) - defer cCancel() - nextOutputIndex, err := c.l2ooContract.NextOutputIndex(optsutils.NewSimpleCallOpts(cCtx)) - if err != nil { - return fmt.Errorf("failed to get latest output index: %w", err) - } - - cCtx, cCancel = context.WithTimeout(ctx, c.cfg.NetworkTimeout) - defer cCancel() - isTerminated, err := c.valpoolContract.IsTerminated( - optsutils.NewSimpleCallOpts(cCtx), - nextOutputIndex, - ) - if err != nil { - return fmt.Errorf("failed to whether valpool is terminated or not: %w", err) - } - c.isValManagerEnabled = isTerminated - - cCtx, cCancel = context.WithTimeout(ctx, c.cfg.NetworkTimeout) - defer cCancel() - terminationIndex, err := c.valpoolContract.TERMINATEOUTPUTINDEX(optsutils.NewSimpleCallOpts(cCtx)) - if err != nil { - return fmt.Errorf("failed to get termination index: %w", err) - } - c.terminationIndex = terminationIndex - return nil }) if err != nil { return fmt.Errorf("failed to initiate valpool config: %w", err) } + cCtx, cCancel := context.WithTimeout(ctx, c.cfg.NetworkTimeout) + defer cCancel() + poolTerminationIndex, err := c.valpoolContract.TERMINATEOUTPUTINDEX(optsutils.NewSimpleCallOpts(cCtx)) + if err != nil { + return fmt.Errorf("failed to get termination index: %w", err) + } + c.poolTerminationIndex = poolTerminationIndex + return nil } @@ -380,10 +359,6 @@ func (c *Challenger) subscribeL2OutputSubmitted() { select { case ev := <-c.l2OutputSubmittedEventChan: c.log.Info("watched output submitted event", "l2BlockNumber", ev.L2BlockNumber, "outputRoot", ev.OutputRoot, "outputIndex", ev.L2OutputIndex) - // if the emitted output index is greater than the termination output index, set the config to use the ValidatorManager - if ev.L2OutputIndex.Cmp(c.terminationIndex) > 0 { - c.isValManagerEnabled = true - } // if the emitted output index is less than or equal to the checkpoint, it is considered reorg occurred. if ev.L2OutputIndex.Cmp(c.checkpoint) <= 0 { c.wg.Add(1) @@ -479,7 +454,7 @@ func (c *Challenger) handleOutput(outputIndex *big.Int) { return } - canCreateChallenge, err := c.CanCreateChallenge(c.ctx) + canCreateChallenge, err := c.CanCreateChallenge(c.ctx, outputIndex) if err != nil { c.log.Error(err.Error()) continue @@ -586,17 +561,22 @@ func (c *Challenger) handleChallenge(outputIndex *big.Int, asserter common.Addre // if challenger if isChallenger && c.cfg.ChallengerEnabled { - // if output has been already deleted, cancel challenge to refund pending bond - if isOutputDeleted && status != chal.StatusChallengerTimeout { - tx, err := c.CancelChallenge(c.ctx, outputIndex) - if err != nil { - c.log.Error("failed to create cancel challenge tx", "err", err, "outputIndex", outputIndex) - continue - } - if err := c.submitChallengeTx(tx); err != nil { - c.log.Error("failed to submit cancel challenge tx", "err", err, "outputIndex", outputIndex) - continue + if isOutputDeleted { + // if output has been already deleted, cancel challenge to refund pending bond in ValidatorPool + if c.IsValPoolTerminated(outputIndex) && status != chal.StatusChallengerTimeout { + tx, err := c.CancelChallenge(c.ctx, outputIndex) + if err != nil { + c.log.Error("failed to create cancel challenge tx", "err", err, "outputIndex", outputIndex) + continue + } + if err := c.submitChallengeTx(tx); err != nil { + c.log.Error("failed to submit cancel challenge tx", "err", err, "outputIndex", outputIndex) + continue + } } + // if output has been already deleted, terminate handling + c.log.Info("output is already deleted when handling challenge", "outputIndex", outputIndex) + return } // if output is already finalized, terminate handling @@ -640,22 +620,27 @@ func (c *Challenger) submitChallengeTx(tx *types.Transaction) error { } // CanCreateChallenge checks if challenger is in the status that can make challenge. -func (c *Challenger) CanCreateChallenge(ctx context.Context) (bool, error) { +func (c *Challenger) CanCreateChallenge(ctx context.Context, outputIndex *big.Int) (bool, error) { cCtx, cCancel := context.WithTimeout(ctx, c.cfg.NetworkTimeout) defer cCancel() from := c.cfg.TxManager.From() - if c.isValManagerEnabled { - vaultStatus, err := c.valManagerContract.GetStatus(optsutils.NewSimpleCallOpts(cCtx), from) + if c.IsValPoolTerminated(outputIndex) { + validatorStatus, err := c.valManagerContract.GetStatus(optsutils.NewSimpleCallOpts(cCtx), from) if err != nil { - return false, fmt.Errorf("failed to fetch the vault status: %w", err) + return false, fmt.Errorf("failed to fetch the validator status: %w", err) } - if vaultStatus != val.StatusCanSubmitOutput { - c.log.Warn("vault is not in the status to make a challenge", "status", vaultStatus) + if isInJail, err := c.IsInJail(ctx); err != nil { + return false, err + } else if isInJail { + c.log.Warn("validator is in jail") return false, nil } - c.log.Info("vault status", "status", vaultStatus) + if validatorStatus != StatusActive { + c.log.Warn("validator is not in the status that can create a challenge", "status", validatorStatus) + return false, nil + } } else { balance, err := c.valpoolContract.BalanceOf(optsutils.NewSimpleCallOpts(cCtx), from) if err != nil { @@ -672,12 +657,28 @@ func (c *Challenger) CanCreateChallenge(ctx context.Context) (bool, error) { return false, nil } - c.log.Info("deposit amount", "deposit", balance) + c.log.Info("deposit amount and bond amount", "deposit", balance, "bond", c.requiredBondAmount) } return true, nil } +func (c *Challenger) IsValPoolTerminated(outputIndex *big.Int) bool { + return c.poolTerminationIndex.Cmp(outputIndex) < 0 +} + +func (c *Challenger) IsInJail(ctx context.Context) (bool, error) { + cCtx, cCancel := context.WithTimeout(ctx, c.cfg.NetworkTimeout) + defer cCancel() + from := c.cfg.TxManager.From() + isInJail, err := c.valManagerContract.InJail(optsutils.NewSimpleCallOpts(cCtx), from) + if err != nil { + return false, fmt.Errorf("failed to fetch the jail status: %w", err) + } + + return isInJail, nil +} + func (c *Challenger) IsInChallengeCreationPeriod(ctx context.Context, outputIndex *big.Int) (bool, error) { cCtx, cCancel := context.WithTimeout(ctx, c.cfg.NetworkTimeout) defer cCancel() diff --git a/kroma-validator/config.go b/kroma-validator/config.go index a2b851428..d35968a26 100644 --- a/kroma-validator/config.go +++ b/kroma-validator/config.go @@ -33,7 +33,6 @@ type Config struct { ValidatorPoolAddr common.Address ValidatorManagerAddr common.Address AssetManagerAddr common.Address - GovTokenAddr common.Address ChallengerPollInterval time.Duration NetworkTimeout time.Duration TxManager *txmgr.BufferedTxManager diff --git a/kroma-validator/l2_output_submitter.go b/kroma-validator/l2_output_submitter.go index 01ec8f1e7..d0b738848 100644 --- a/kroma-validator/l2_output_submitter.go +++ b/kroma-validator/l2_output_submitter.go @@ -5,8 +5,6 @@ import ( "context" "errors" "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/event" "math/big" _ "net/http/pprof" "sync" @@ -24,7 +22,6 @@ import ( "github.com/ethereum-optimism/optimism/op-service/watcher" "github.com/kroma-network/kroma/kroma-bindings/bindings" "github.com/kroma-network/kroma/kroma-validator/metrics" - val "github.com/kroma-network/kroma/kroma-validator/validator" ) const ( @@ -43,30 +40,25 @@ type L2OutputSubmitter struct { log log.Logger metr metrics.Metricer - l2ooContract *bindings.L2OutputOracle + l2ooContract *bindings.L2OutputOracleCaller l2ooABI *abi.ABI valpoolContract *bindings.ValidatorPoolCaller valManagerContract *bindings.ValidatorManagerCaller valManagerAbi *abi.ABI - singleRoundInterval *big.Int - l2BlockTime *big.Int - requiredBondAmount *big.Int + singleRoundInterval *big.Int + l2BlockTime *big.Int + requiredBondAmount *big.Int + poolTerminationIndex *big.Int - isValManagerEnabled bool - terminationIndex *big.Int - - outputSubmittedSub ethereum.Subscription - - submitChan chan struct{} - l2OutputSubmittedEventChan chan *bindings.L2OutputOracleOutputSubmitted + submitChan chan struct{} wg sync.WaitGroup } // NewL2OutputSubmitter creates a new L2OutputSubmitter. func NewL2OutputSubmitter(cfg Config, l log.Logger, m metrics.Metricer) (*L2OutputSubmitter, error) { - l2ooContract, err := bindings.NewL2OutputOracle(cfg.L2OutputOracleAddr, cfg.L1Client) + l2ooContract, err := bindings.NewL2OutputOracleCaller(cfg.L2OutputOracleAddr, cfg.L1Client) if err != nil { return nil, err } @@ -139,51 +131,21 @@ func (l *L2OutputSubmitter) InitConfig(ctx context.Context) error { } l.requiredBondAmount = requiredBondAmount - cCtx, cCancel = context.WithTimeout(ctx, l.cfg.NetworkTimeout) - defer cCancel() - nextOutputIndex, err := l.l2ooContract.NextOutputIndex(optsutils.NewSimpleCallOpts(cCtx)) - if err != nil { - return fmt.Errorf("failed to get latest output index: %w", err) - } - - cCtx, cCancel = context.WithTimeout(ctx, l.cfg.NetworkTimeout) - defer cCancel() - isTerminated, err := l.valpoolContract.IsTerminated( - optsutils.NewSimpleCallOpts(cCtx), - nextOutputIndex, - ) - if err != nil { - return fmt.Errorf("failed to whether valpool is terminated or not: %w", err) - } - l.isValManagerEnabled = isTerminated - - cCtx, cCancel = context.WithTimeout(ctx, l.cfg.NetworkTimeout) - defer cCancel() - terminationIndex, err := l.valpoolContract.TERMINATEOUTPUTINDEX(optsutils.NewSimpleCallOpts(cCtx)) - if err != nil { - return fmt.Errorf("failed to get termination index: %w", err) - } - l.terminationIndex = terminationIndex - return nil }) if err != nil { return fmt.Errorf("failed to initiate valpool config: %w", err) } - return nil -} - -func (l *L2OutputSubmitter) initSub() { - opts := optsutils.NewSimpleWatchOpts(l.ctx) + cCtx, cCancel := context.WithTimeout(ctx, l.cfg.NetworkTimeout) + defer cCancel() + poolTerminationIndex, err := l.valpoolContract.TERMINATEOUTPUTINDEX(optsutils.NewSimpleCallOpts(cCtx)) + if err != nil { + return fmt.Errorf("failed to get termination index: %w", err) + } + l.poolTerminationIndex = poolTerminationIndex - l.l2OutputSubmittedEventChan = make(chan *bindings.L2OutputOracleOutputSubmitted) - l.outputSubmittedSub = event.ResubscribeErr(time.Second*10, func(ctx context.Context, err error) (event.Subscription, error) { - if err != nil { - l.log.Warn("resubscribing after failed OutputSubmitted event", "err", err) - } - return l.l2ooContract.WatchOutputSubmitted(opts, l.l2OutputSubmittedEventChan, nil, nil, nil) - }) + return nil } func (l *L2OutputSubmitter) Start(ctx context.Context) error { @@ -193,52 +155,23 @@ func (l *L2OutputSubmitter) Start(ctx context.Context) error { if err := l.InitConfig(l.ctx); err != nil { return err } - l.initSub() l.wg.Add(1) - go l.subscriptionLoop() - - l.wg.Add(1) - go l.submissionLoop() + go l.loop() return nil } func (l *L2OutputSubmitter) Stop() error { - if l.outputSubmittedSub != nil { - l.outputSubmittedSub.Unsubscribe() - } - l.cancel() l.wg.Wait() - if l.l2OutputSubmittedEventChan != nil { - close(l.l2OutputSubmittedEventChan) - } close(l.submitChan) return nil } -func (l *L2OutputSubmitter) subscriptionLoop() { - defer l.wg.Done() - - ticker := time.NewTicker(time.Minute) - defer ticker.Stop() - - for ; ; <-ticker.C { - select { - case <-l.ctx.Done(): - return - default: - l.subscribeL2OutputSubmitted() - - return - } - } -} - -func (l *L2OutputSubmitter) submissionLoop() { +func (l *L2OutputSubmitter) loop() { defer l.wg.Done() for ; ; <-l.submitChan { @@ -251,21 +184,6 @@ func (l *L2OutputSubmitter) submissionLoop() { } } -func (l *L2OutputSubmitter) subscribeL2OutputSubmitted() { - for { - select { - case ev := <-l.l2OutputSubmittedEventChan: - l.log.Info("watched output submitted event", "l2BlockNumber", ev.L2BlockNumber, "outputRoot", ev.OutputRoot, "outputIndex", ev.L2OutputIndex) - // if the emitted output index is greater than the termination output index, set the config to use the ValidatorManager - if ev.L2OutputIndex.Cmp(l.terminationIndex) > 0 { - l.isValManagerEnabled = true - } - case <-l.ctx.Done(): - return - } - } -} - func (l *L2OutputSubmitter) retryAfter(d time.Duration) { l.wg.Add(1) @@ -287,27 +205,22 @@ func (l *L2OutputSubmitter) repeatSubmitL2Output(ctx context.Context) { // If it needs to wait, it will calculate how long the validator should wait and // try again after the delay. func (l *L2OutputSubmitter) trySubmitL2Output(ctx context.Context) (time.Duration, error) { - if l.isValManagerEnabled { - hasSubmittedStartTx, err := l.tryStartValidator(ctx) - if err != nil { - return l.cfg.OutputSubmitterRetryInterval, err - } - if !hasSubmittedStartTx { - return l.cfg.OutputSubmitterRetryInterval, nil - } + nextBlockNumber, err := l.FetchNextBlockNumber(ctx) + if err != nil { + return l.cfg.OutputSubmitterRetryInterval, err } - nextBlockNumber, err := l.FetchNextBlockNumber(ctx) + outputIndex, err := l.FetchNextOutputIndex(ctx) if err != nil { return l.cfg.OutputSubmitterRetryInterval, err } - calculatedWaitTime := l.CalculateWaitTime(ctx, nextBlockNumber) + calculatedWaitTime := l.CalculateWaitTime(ctx, nextBlockNumber, outputIndex) if calculatedWaitTime > 0 { return calculatedWaitTime, nil } - if err = l.doSubmitL2Output(ctx, nextBlockNumber); err != nil { + if err = l.doSubmitL2Output(ctx, nextBlockNumber, outputIndex); err != nil { return l.cfg.OutputSubmitterRetryInterval, err } @@ -315,49 +228,8 @@ func (l *L2OutputSubmitter) trySubmitL2Output(ctx context.Context) (time.Duratio return 0, nil } -// tryStartValidator checks if the validator can start and tries to start it. -func (l *L2OutputSubmitter) tryStartValidator(ctx context.Context) (bool, error) { - cCtx, cCancel := context.WithTimeout(ctx, l.cfg.NetworkTimeout) - defer cCancel() - from := l.cfg.TxManager.From() - vaultStatus, err := l.valManagerContract.GetStatus(optsutils.NewSimpleCallOpts(cCtx), from) - if err != nil { - return false, fmt.Errorf("failed to fetch the vault status: %w", err) - } - - if vaultStatus == val.StatusNone || vaultStatus == val.StatusInactive || vaultStatus == val.StatusActive { - l.log.Info("vault has not started yet", "currentStatus", vaultStatus) - return false, nil - } - - if vaultStatus == val.StatusCanSubmitOutput { - l.log.Info("vault has started, no need to start again", "currentStatus", val.StatusStarted) - return false, nil - } - - if isInJail, err := l.isInJail(ctx); err != nil { - return false, err - } else if isInJail { - l.log.Warn("validator is in jail") - return false, nil - } - - data, err := l.valManagerAbi.Pack("startValidator") - if err != nil { - return false, fmt.Errorf("failed to create start validator transaction data: %w", err) - } - - if txResponse := l.startValidatorTx(data); txResponse.Err != nil { - return false, txResponse.Err - } - - l.log.Info("startValidator successfully submitted") - - return true, nil -} - // doSubmitL2Output submits l2 Output submission transaction. -func (l *L2OutputSubmitter) doSubmitL2Output(ctx context.Context, nextBlockNumber *big.Int) error { +func (l *L2OutputSubmitter) doSubmitL2Output(ctx context.Context, nextBlockNumber *big.Int, outputIndex *big.Int) error { output, err := l.FetchOutput(ctx, nextBlockNumber) if err != nil { return err @@ -368,7 +240,7 @@ func (l *L2OutputSubmitter) doSubmitL2Output(ctx context.Context, nextBlockNumbe return fmt.Errorf("failed to create submit l2 output transaction data: %w", err) } - if txResponse := l.submitL2OutputTx(data); txResponse.Err != nil { + if txResponse := l.submitL2OutputTx(data, outputIndex); txResponse.Err != nil { return txResponse.Err } @@ -381,7 +253,7 @@ func (l *L2OutputSubmitter) doSubmitL2Output(ctx context.Context, nextBlockNumbe // CalculateWaitTime checks the conditions for submitting L2Output and calculates the required latency. // Returns time 0 if the conditions are such that submission is possible immediately. -func (l *L2OutputSubmitter) CalculateWaitTime(ctx context.Context, nextBlockNumber *big.Int) time.Duration { +func (l *L2OutputSubmitter) CalculateWaitTime(ctx context.Context, nextBlockNumber *big.Int, outputIndex *big.Int) time.Duration { defaultWaitTime := l.cfg.OutputSubmitterRetryInterval currentBlockNumber, err := l.FetchCurrentBlockNumber(ctx) @@ -389,8 +261,9 @@ func (l *L2OutputSubmitter) CalculateWaitTime(ctx context.Context, nextBlockNumb return defaultWaitTime } - canSubmitOutput, err := l.CanSubmitOutput(ctx) + canSubmitOutput, err := l.CanSubmitOutput(ctx, outputIndex) if err != nil { + l.log.Error("failed to check the validator can submit output", "err", err) return defaultWaitTime } if !canSubmitOutput { @@ -409,7 +282,7 @@ func (l *L2OutputSubmitter) CalculateWaitTime(ctx context.Context, nextBlockNumb } // Check if it's a public round, or selected for priority validator - roundInfo, err := l.fetchCurrentRound(ctx) + roundInfo, err := l.fetchCurrentRound(ctx, outputIndex) if err != nil { return defaultWaitTime } @@ -425,23 +298,36 @@ func (l *L2OutputSubmitter) CalculateWaitTime(ctx context.Context, nextBlockNumb return 0 } -// CanSubmitOutput checks if the validator can submit L2Output. -func (l *L2OutputSubmitter) CanSubmitOutput(ctx context.Context) (bool, error) { +// CanSubmitOutput checks if the validator satisfies the condition to submit L2Output. +func (l *L2OutputSubmitter) CanSubmitOutput(ctx context.Context, outputIndex *big.Int) (bool, error) { cCtx, cCancel := context.WithTimeout(ctx, l.cfg.NetworkTimeout) defer cCancel() from := l.cfg.TxManager.From() - if l.isValManagerEnabled { - vaultStatus, err := l.valManagerContract.GetStatus(optsutils.NewSimpleCallOpts(cCtx), from) + if l.IsValPoolTerminated(outputIndex) { + validatorStatus, err := l.getValidatorStatus(ctx) + if err != nil { + return false, err + } + + validatorActivated, err := l.tryActivateValidator(validatorStatus) if err != nil { - return false, fmt.Errorf("failed to fetch the vault status: %w", err) + return false, err + } + if !validatorActivated { + return false, nil } - if vaultStatus != val.StatusCanSubmitOutput { - l.log.Warn("vault has started, but currently has not enough tokens", "currentStatus", val.StatusStarted) + if validatorStatus != StatusActive { + l.log.Warn("validator has activated, but currently has not enough tokens", "currentStatus", validatorStatus) return false, nil } - l.log.Info("vault status", "status", vaultStatus) + if isInJail, err := l.isInJail(ctx); err != nil { + return false, err + } else if isInJail { + l.log.Warn("validator is in jail") + return false, nil + } } else { balance, err := l.valpoolContract.BalanceOf(optsutils.NewSimpleCallOpts(cCtx), from) if err != nil { @@ -458,12 +344,45 @@ func (l *L2OutputSubmitter) CanSubmitOutput(ctx context.Context) (bool, error) { return false, nil } - l.log.Info("deposit amount", "deposit", balance) + l.log.Info("deposit amount and bond amount", "deposit", balance, "bond", l.requiredBondAmount) } return true, nil } +// tryActivateValidator checks if the validator can activate and tries to activate it if not activated yet. +func (l *L2OutputSubmitter) tryActivateValidator(validatorStatus uint8) (bool, error) { + if validatorStatus <= StatusRegistered { + l.log.Warn("validator cannot activate yet", "currentStatus", validatorStatus) + return false, nil + } + if validatorStatus >= StatusInactive { + l.log.Info("validator has already been activated, no need to activate again", "currentStatus", validatorStatus) + return true, nil + } + data, err := l.valManagerAbi.Pack("activateValidator") + if err != nil { + return false, fmt.Errorf("failed to create activate validator transaction data: %w", err) + } + if txResponse := l.activateValidatorTx(data); txResponse.Err != nil { + return false, txResponse.Err + } + l.log.Info("validator successfully activated") + return true, nil +} + +func (l *L2OutputSubmitter) FetchNextOutputIndex(ctx context.Context) (*big.Int, error) { + cCtx, cCancel := context.WithTimeout(ctx, l.cfg.NetworkTimeout) + defer cCancel() + + outputIndex, err := l.l2ooContract.NextOutputIndex(optsutils.NewSimpleCallOpts(cCtx)) + if err != nil { + return nil, fmt.Errorf("failed to fetch next output index: %w", err) + } + + return outputIndex, nil +} + func (l *L2OutputSubmitter) FetchNextBlockNumber(ctx context.Context) (*big.Int, error) { cCtx, cCancel := context.WithTimeout(ctx, l.cfg.NetworkTimeout) defer cCancel() @@ -497,19 +416,18 @@ func (l *L2OutputSubmitter) FetchCurrentBlockNumber(ctx context.Context) (*big.I return currentBlockNumber, nil } -func (l *L2OutputSubmitter) getLeftTimeForL2Blocks(currentBlockNumber *big.Int, targetBlockNumber *big.Int) time.Duration { - l.log.Info("submission interval has not elapsed", "currentBlockNumber", currentBlockNumber, "targetBlockNumber", targetBlockNumber) - waitBlockNum := new(big.Int).Sub(targetBlockNumber, currentBlockNumber) +func (l *L2OutputSubmitter) IsValPoolTerminated(outputIndex *big.Int) bool { + return l.poolTerminationIndex.Cmp(outputIndex) < 0 +} - var waitDuration time.Duration - if waitBlockNum.Cmp(common.Big0) == -1 { - waitDuration = l.cfg.OutputSubmitterRetryInterval - } else { - waitDuration = time.Duration(new(big.Int).Mul(waitBlockNum, l.l2BlockTime).Uint64()) * time.Second +func (l *L2OutputSubmitter) getValidatorStatus(ctx context.Context) (uint8, error) { + cCtx, cCancel := context.WithTimeout(ctx, l.cfg.NetworkTimeout) + defer cCancel() + validatorStatus, err := l.valManagerContract.GetStatus(optsutils.NewSimpleCallOpts(cCtx), l.cfg.TxManager.From()) + if err != nil { + return 0, fmt.Errorf("failed to fetch the validator status: %w", err) } - - l.log.Info("wait for L2 blocks proceeding", "waitDuration", waitDuration) - return waitDuration + return validatorStatus, nil } func (l *L2OutputSubmitter) isInJail(ctx context.Context) (bool, error) { @@ -524,6 +442,21 @@ func (l *L2OutputSubmitter) isInJail(ctx context.Context) (bool, error) { return isInJail, nil } +func (l *L2OutputSubmitter) getLeftTimeForL2Blocks(currentBlockNumber *big.Int, targetBlockNumber *big.Int) time.Duration { + l.log.Info("submission interval has not elapsed", "currentBlockNumber", currentBlockNumber, "targetBlockNumber", targetBlockNumber) + waitBlockNum := new(big.Int).Sub(targetBlockNumber, currentBlockNumber) + + var waitDuration time.Duration + if waitBlockNum.Cmp(common.Big0) == -1 { + waitDuration = l.cfg.OutputSubmitterRetryInterval + } else { + waitDuration = time.Duration(new(big.Int).Mul(waitBlockNum, l.l2BlockTime).Uint64()) * time.Second + } + + l.log.Info("wait for L2 blocks proceeding", "waitDuration", waitDuration) + return waitDuration +} + type roundInfo struct { isPublicRound bool isPriorityValidator bool @@ -538,12 +471,12 @@ func (r *roundInfo) canJoinRound() bool { // fetchCurrentRound fetches next validator address from ValidatorPool or ValidatorManager contract. // It returns if current round is public round, and if selected for priority validator if it's a priority round. -func (l *L2OutputSubmitter) fetchCurrentRound(ctx context.Context) (roundInfo, error) { +func (l *L2OutputSubmitter) fetchCurrentRound(ctx context.Context, outputIndex *big.Int) (roundInfo, error) { cCtx, cCancel := context.WithTimeout(ctx, l.cfg.NetworkTimeout) defer cCancel() ri := roundInfo{canJoinPublicRound: l.cfg.OutputSubmitterAllowPublicRound} - nextValidator, err := l.getNextValidatorAddress(cCtx) + nextValidator, err := l.getNextValidatorAddress(cCtx, outputIndex) if err != nil { l.log.Error("unable to get next validator address", "err", err) ri.isPublicRound = false @@ -573,6 +506,15 @@ func (l *L2OutputSubmitter) fetchCurrentRound(ctx context.Context) (roundInfo, e return ri, nil } +// getNextValidatorAddress selects the appropriate contract and retrieves the next validator address. +func (l *L2OutputSubmitter) getNextValidatorAddress(ctx context.Context, outputIndex *big.Int) (common.Address, error) { + opts := optsutils.NewSimpleCallOpts(ctx) + if l.IsValPoolTerminated(outputIndex) { + return l.valManagerContract.NextValidator(opts) + } + return l.valpoolContract.NextValidator(opts) +} + // FetchOutput gets the output information to the corresponding block number. // It returns the output info if the output can be made, otherwise error. func (l *L2OutputSubmitter) FetchOutput(ctx context.Context, blockNumber *big.Int) (*eth.OutputResponse, error) { @@ -606,61 +548,20 @@ func SubmitL2OutputTxData(abi *abi.ABI, output *eth.OutputResponse) ([]byte, err ) } -// getNextValidatorAddress selects the appropriate contract and retrieves the next validator address. -func (l *L2OutputSubmitter) getNextValidatorAddress(ctx context.Context) (common.Address, error) { - var contract interface { - NextValidator(opts *bind.CallOpts) (common.Address, error) - } - - if l.isValManagerEnabled { - contract = l.valManagerContract - } else { - contract = l.valpoolContract - } - - return contract.NextValidator(optsutils.NewSimpleCallOpts(ctx)) -} - -// startValidatorTx creates start validator tx candidate. +// activateValidatorTx creates activate validator tx candidate. // It sends the candidate to txCandidates channel to process validator's tx candidates in order. -func (l *L2OutputSubmitter) startValidatorTx(data []byte) *txmgr.TxResponse { - gasTipCap, basefee, _, err := l.cfg.TxManager.SuggestGasPriceCaps(l.ctx) - if err != nil { - return &txmgr.TxResponse{ - Receipt: nil, - Err: fmt.Errorf("failed to get gas price info: %w", err), - } - } - gasFeeCap := txmgr.CalcGasFeeCap(basefee, gasTipCap) - - to := &l.cfg.ValidatorManagerAddr - estimatedGas, err := l.cfg.L1Client.EstimateGas(l.ctx, ethereum.CallMsg{ - From: l.cfg.TxManager.From(), - To: to, - GasFeeCap: gasFeeCap, - GasTipCap: gasTipCap, - Data: data, - }) - if err != nil { - return &txmgr.TxResponse{ - Receipt: nil, - Err: fmt.Errorf("failed to estimate gas: %w", err), - } - } - +func (l *L2OutputSubmitter) activateValidatorTx(data []byte) *txmgr.TxResponse { return l.cfg.TxManager.SendTxCandidate(l.ctx, &txmgr.TxCandidate{ - TxData: data, - To: to, - GasLimit: estimatedGas * 3 / 2, + TxData: data, + To: &l.cfg.ValidatorManagerAddr, }) - } // submitL2OutputTx creates l2 output submit tx candidate and sends it to txCandidates channel to process validator's tx candidates in order. -func (l *L2OutputSubmitter) submitL2OutputTx(data []byte) *txmgr.TxResponse { +func (l *L2OutputSubmitter) submitL2OutputTx(data []byte, outputIndex *big.Int) *txmgr.TxResponse { var name string var accessListAddr common.Address - if l.isValManagerEnabled { + if l.IsValPoolTerminated(outputIndex) { name = "ValidatorManager" accessListAddr = l.cfg.ValidatorManagerAddr } else { @@ -691,7 +592,7 @@ func (l *L2OutputSubmitter) submitL2OutputTx(data []byte) *txmgr.TxResponse { } var storageKeys []common.Hash - if l.isValManagerEnabled { + if l.IsValPoolTerminated(outputIndex) { storageKeys = []common.Hash{priorityValidatorSlot} } else { storageKeys = []common.Hash{outputIndexSlot, priorityValidatorSlot} @@ -741,7 +642,3 @@ func (l *L2OutputSubmitter) submitL2OutputTx(data []byte) *txmgr.TxResponse { func (l *L2OutputSubmitter) L2ooAbi() *abi.ABI { return l.l2ooABI } - -func (l *L2OutputSubmitter) ValManagerAbi() *abi.ABI { - return l.valManagerAbi -} diff --git a/kroma-validator/status.go b/kroma-validator/status.go new file mode 100644 index 000000000..b349b89a2 --- /dev/null +++ b/kroma-validator/status.go @@ -0,0 +1,10 @@ +package validator + +const ( + StatusNone uint8 = iota + StatusExited + StatusRegistered + StatusReady + StatusInactive + StatusActive +) diff --git a/kroma-validator/validator/status.go b/kroma-validator/validator/status.go deleted file mode 100644 index 7a2b8b5c5..000000000 --- a/kroma-validator/validator/status.go +++ /dev/null @@ -1,12 +0,0 @@ -package validator - -const ( - // StatusNone is regarded as a challenge is not in progress. - // The other status are regarded as a challenge is in progress. - StatusNone uint8 = iota - StatusInactive - StatusActive - StatusCanStart - StatusStarted - StatusCanSubmitOutput -) diff --git a/op-e2e/actions/l2_challenger.go b/op-e2e/actions/l2_challenger.go index 57ed5c49a..beeffb9a1 100644 --- a/op-e2e/actions/l2_challenger.go +++ b/op-e2e/actions/l2_challenger.go @@ -30,7 +30,7 @@ func (v *L2Validator) ActCreateChallenge(t Testing, outputIndex *big.Int) common return status == chal.StatusNone || status == chal.StatusChallengerTimeout }, "challenge is already in progress") - canCreateChallenge, err := v.challenger.CanCreateChallenge(t.Ctx()) + canCreateChallenge, err := v.challenger.CanCreateChallenge(t.Ctx(), outputIndex) require.NoError(t, err, "unable to check challenger balance") require.True(t, canCreateChallenge, "challenger not enough balance to create challenge") diff --git a/op-e2e/actions/l2_validator.go b/op-e2e/actions/l2_validator.go index 24d22a35a..01e99c513 100644 --- a/op-e2e/actions/l2_validator.go +++ b/op-e2e/actions/l2_validator.go @@ -3,6 +3,7 @@ package actions import ( "context" "crypto/ecdsa" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "math/big" "time" @@ -21,7 +22,7 @@ import ( "github.com/stretchr/testify/require" "github.com/kroma-network/kroma/kroma-bindings/bindings" - "github.com/kroma-network/kroma/kroma-validator" + validator "github.com/kroma-network/kroma/kroma-validator" validatormetrics "github.com/kroma-network/kroma/kroma-validator/metrics" ) @@ -172,7 +173,11 @@ func (v *L2Validator) sendTx(t Testing, toAddr *common.Address, txValue *big.Int func (v *L2Validator) CalculateWaitTime(t Testing) time.Duration { nextBlockNumber, err := v.l2os.FetchNextBlockNumber(t.Ctx()) require.NoError(t, err) - calculatedWaitTime := v.l2os.CalculateWaitTime(t.Ctx(), nextBlockNumber) + + outputIndex, err := v.l2os.FetchNextOutputIndex(t.Ctx()) + require.NoError(t, err) + + calculatedWaitTime := v.l2os.CalculateWaitTime(t.Ctx(), nextBlockNumber, outputIndex) return calculatedWaitTime } @@ -218,15 +223,18 @@ func (v *L2Validator) ActRegisterValidator(t Testing, assets *big.Int) { ) require.NoError(t, err) - v.sendTx(t, &v.valManagerContractAddr, common.Big0, txData, 2) + v.sendTx(t, &v.valManagerContractAddr, common.Big0, txData, 1) } -func (v *L2Validator) ActApprove(t Testing, amount uint64) { - tokenAddr := v.getGovTokenAddr(t) +func (v *L2Validator) ActApprove(t Testing, assets *big.Int) { + assetManagerContract, err := bindings.NewAssetManagerCaller(v.assetManagerContractAddr, v.cfg.L1Client) + tokenAddr, err := assetManagerContract.ASSETTOKEN(&bind.CallOpts{}) + require.NoError(t, err) + governanceTokenABI, err := bindings.GovernanceTokenMetaData.GetAbi() require.NoError(t, err) - txData, err := governanceTokenABI.Pack("approve", &v.assetManagerContractAddr, new(big.Int).SetUint64(amount)) + txData, err := governanceTokenABI.Pack("approve", &v.assetManagerContractAddr, assets) require.NoError(t, err) v.sendTx(t, &tokenAddr, common.Big0, txData, 1) @@ -239,19 +247,9 @@ func (v *L2Validator) fetchOutput(t Testing, blockNumber *big.Int) *eth.OutputRe return output } -func (v *L2Validator) getGovTokenAddr(t Testing) common.Address { - assetManagerABI, err := bindings.AssetManagerMetaData.GetAbi() - require.NoError(t, err) - - callData, err := assetManagerABI.Pack("ASSET_TOKEN") - require.NoError(t, err) - - returnData, err := v.l1.CallContract(t.Ctx(), ethereum.CallMsg{ - To: &v.assetManagerContractAddr, - Data: callData, - }, nil) +func (v *L2Validator) CheckIsValPoolTerminated(t Testing) bool { + outputIndex, err := v.l2os.FetchNextOutputIndex(t.Ctx()) require.NoError(t, err) - tokenAddr := common.BytesToAddress(returnData) - return tokenAddr + return v.l2os.IsValPoolTerminated(outputIndex) } diff --git a/op-e2e/actions/l2_validator_test.go b/op-e2e/actions/l2_validator_test.go index 7c6c0858e..226869fb2 100644 --- a/op-e2e/actions/l2_validator_test.go +++ b/op-e2e/actions/l2_validator_test.go @@ -5,13 +5,13 @@ import ( "testing" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" "github.com/stretchr/testify/require" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" - "github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/kroma-network/kroma/kroma-bindings/bindings" @@ -42,13 +42,36 @@ func TestValidatorBatchType(t *testing.T) { } } +func proceedWithBlocks(t StatefulTesting, miner *L1Miner, sequencer *L2Sequencer, batcher *L2Batcher, batcherAddr common.Address, n int) { + for i := 0; i < n; i++ { + // L1 block + miner.ActEmptyBlock(t) + // L2 block + sequencer.ActL1HeadSignal(t) + sequencer.ActL2PipelineFull(t) + sequencer.ActBuildToL1Head(t) + // submit and include in L1 + batcher.ActSubmitAll(t) + miner.includeL1Block(t, batcherAddr, 12) + // finalize the first and second L1 blocks, including the batch + miner.ActL1SafeNext(t) + miner.ActL1SafeNext(t) + miner.ActL1FinalizeNext(t) + miner.ActL1FinalizeNext(t) + // derive and see the L2 chain fully finalize + sequencer.ActL2PipelineFull(t) + sequencer.ActL1SafeSignal(t) + sequencer.ActL1FinalizedSignal(t) + } +} + func RunValidatorPoolTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { t := NewDefaultTesting(gt) dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp.DeployConfig.L2GenesisDeltaTimeOffset = deltaTimeOffset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) rollupSeqCl := sequencer.RollupClient() @@ -66,24 +89,7 @@ func RunValidatorPoolTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { AllowNonFinalized: false, }, miner.EthClient(), seqEngine.EthClient(), sequencer.RollupClient()) - // L1 block - miner.ActEmptyBlock(t) - // L2 block - sequencer.ActL1HeadSignal(t) - sequencer.ActL2PipelineFull(t) - sequencer.ActBuildToL1Head(t) - // submit and include in L1 - batcher.ActSubmitAll(t) - miner.includeL1Block(t, dp.Addresses.Batcher, 12) - // finalize the first and second L1 blocks, including the batch - miner.ActL1SafeNext(t) - miner.ActL1SafeNext(t) - miner.ActL1FinalizeNext(t) - miner.ActL1FinalizeNext(t) - // derive and see the L2 chain fully finalize - sequencer.ActL2PipelineFull(t) - sequencer.ActL1SafeSignal(t) - sequencer.ActL1FinalizedSignal(t) + proceedWithBlocks(t, miner, sequencer, batcher, dp.Addresses.Batcher, 1) // deposit bond for validator validator.ActDeposit(t, 1_000) @@ -100,7 +106,6 @@ func RunValidatorPoolTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { validator.ActSubmitL2Output(t) // include output on L1 miner.includeL1Block(t, validator.address, 12) - miner.ActEmptyBlock(t) // Check submission was successful receipt, err := miner.EthClient().TransactionReceipt(t.Ctx(), validator.LastSubmitL2OutputTx()) require.NoError(t, err) @@ -131,7 +136,7 @@ func RunValidatorManagerTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) dp.DeployConfig.L2GenesisDeltaTimeOffset = deltaTimeOffset sd := e2eutils.Setup(t, dp, defaultAlloc) - log := testlog.Logger(t, log.LvlDebug) + log := testlog.Logger(t, log.LevelDebug) miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) rollupSeqCl := sequencer.RollupClient() @@ -149,26 +154,7 @@ func RunValidatorManagerTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { AllowNonFinalized: false, }, miner.EthClient(), seqEngine.EthClient(), sequencer.RollupClient()) - for i := 0; i < 5; i++ { - // L1 block - miner.ActEmptyBlock(t) - // L2 block - sequencer.ActL1HeadSignal(t) - sequencer.ActL2PipelineFull(t) - sequencer.ActBuildToL1Head(t) - // submit and include in L1 - batcher.ActSubmitAll(t) - miner.includeL1Block(t, dp.Addresses.Batcher, 12) - // finalize the first and second L1 blocks, including the batch - miner.ActL1SafeNext(t) - miner.ActL1SafeNext(t) - miner.ActL1FinalizeNext(t) - miner.ActL1FinalizeNext(t) - // derive and see the L2 chain fully finalize - sequencer.ActL2PipelineFull(t) - sequencer.ActL1SafeSignal(t) - sequencer.ActL1FinalizedSignal(t) - } + proceedWithBlocks(t, miner, sequencer, batcher, dp.Addresses.Batcher, 6) // deposit bond for validator validator.ActDeposit(t, 1_000) @@ -179,19 +165,23 @@ func RunValidatorManagerTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { validator.ActSubmitL2Output(t) // include output on L1 miner.includeL1Block(t, validator.address, 12) - miner.ActEmptyBlock(t) // Check submission was successful receipt, err := miner.EthClient().TransactionReceipt(t.Ctx(), validator.LastSubmitL2OutputTx()) require.NoError(t, err) require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status, "submission failed") } + // Check if the ValPool is able to submit the outputs to the ValManager + isValPoolTerminated := validator.CheckIsValPoolTerminated(t) + require.True(t, isValPoolTerminated, "ValPool should be terminated") + // approve governance token - validator.ActApprove(t, 1_000) + assets := new(big.Int).SetUint64(1_000) + validator.ActApprove(t, assets) miner.includeL1Block(t, validator.address, 12) // register validator - validator.ActRegisterValidator(t, new(big.Int).SetUint64(1_000)) + validator.ActRegisterValidator(t, assets) miner.includeL1Block(t, validator.address, 12) require.Equal(t, sequencer.SyncStatus().UnsafeL2, sequencer.SyncStatus().FinalizedL2) @@ -205,7 +195,6 @@ func RunValidatorManagerTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { validator.ActSubmitL2Output(t) // include output on L1 miner.includeL1Block(t, validator.address, 12) - miner.ActEmptyBlock(t) // Check submission was successful receipt, err := miner.EthClient().TransactionReceipt(t.Ctx(), validator.LastSubmitL2OutputTx()) require.NoError(t, err) diff --git a/ops-devnet/docker-compose.yml b/ops-devnet/docker-compose.yml index b57772958..1b2d06fdc 100644 --- a/ops-devnet/docker-compose.yml +++ b/ops-devnet/docker-compose.yml @@ -232,6 +232,8 @@ services: VALIDATOR_L2OO_ADDRESS: "${L2OO_ADDRESS}" VALIDATOR_COLOSSEUM_ADDRESS: "${COLOSSEUM_ADDRESS}" VALIDATOR_VALPOOL_ADDRESS: "${VALPOOL_ADDRESS}" + VALIDATOR_VALMANAGER_ADDRESS: "${VALMANAGER_ADDRESS}" + VALIDATOR_ASSETMANAGER_ADDRESS: "${ASSETMANAGER_ADDRESS}" VALIDATOR_ALLOW_NON_FINALIZED: "true" VALIDATOR_PROVER_RPC: "0.0.0.0:0" VALIDATOR_OUTPUT_SUBMITTER_ENABLED: "false" diff --git a/packages/contracts/contracts/test/ValidatorPool.t.sol b/packages/contracts/contracts/test/ValidatorPool.t.sol index 000857a41..cfa0df616 100644 --- a/packages/contracts/contracts/test/ValidatorPool.t.sol +++ b/packages/contracts/contracts/test/ValidatorPool.t.sol @@ -796,25 +796,7 @@ contract ValidatorPool_SystemUpgrade_Test is ValidatorSystemUpgrade_Initializer } function test_deposit_afterSystemUpgrade_reverts() external { - vm.prank(trusted); - pool.deposit{ value: trusted.balance }(); - - bool poolTerminated; - for (uint256 i; i <= terminateOutputIndex + 1; i++) { - uint256 nextOutputIndex = oracle.nextOutputIndex(); - poolTerminated = pool.isTerminated(nextOutputIndex); - if (nextOutputIndex <= terminateOutputIndex) { - assertFalse(poolTerminated); - } else { - assertTrue(poolTerminated); - } - - warpToSubmitTime(); - uint256 nextBlockNumber = oracle.nextBlockNumber(); - bytes32 outputRoot = keccak256(abi.encode(nextBlockNumber)); - vm.prank(pool.nextValidator()); - mockOracle.addOutput(outputRoot, nextBlockNumber); - } + test_isTerminated_succeeds(); vm.deal(trusted, requiredBondAmount); @@ -823,7 +805,7 @@ contract ValidatorPool_SystemUpgrade_Test is ValidatorSystemUpgrade_Initializer pool.deposit{ value: requiredBondAmount }(); } - function test_isTerminated_succeeds() external { + function test_isTerminated_succeeds() public { vm.prank(trusted); pool.deposit{ value: trusted.balance }();