From 6ecadb7b29fd4023c25f912724664be8c65867df Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Tue, 30 Jul 2024 13:45:17 -0400 Subject: [PATCH 01/27] export StakingManagerSettings --- contracts/src/staking/StakingManager.sol | 21 ++++--------------- .../staking/interfaces/IStakingManager.sol | 20 ++++++++++++++++++ 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/contracts/src/staking/StakingManager.sol b/contracts/src/staking/StakingManager.sol index e0d5716aa..41184eb05 100644 --- a/contracts/src/staking/StakingManager.sol +++ b/contracts/src/staking/StakingManager.sol @@ -5,7 +5,10 @@ pragma solidity 0.8.25; -import {IStakingManager} from "./interfaces/IStakingManager.sol"; +import { + IStakingManager, + StakingManagerSettings +} from "./interfaces/IStakingManager.sol"; import { WarpMessage, IWarpMessenger @@ -77,22 +80,6 @@ abstract contract StakingManager is ReentrancyGuard, IStakingManager { } } - struct InitialStakerInfo { - StakingMessages.ValidationInfo validationInfo; - address owner; - } - - struct StakingManagerSettings { - bytes32 pChainBlockchainID; - bytes32 subnetID; - uint256 minimumStakeAmount; - uint256 maximumStakeAmount; - uint64 minimumStakeDuration; - uint8 maximumHourlyChurn; - InitialStakerInfo[] initialStakers; - IRewardCalculator rewardCalculator; - } - function initialize(StakingManagerSettings calldata settings) public { StakingManagerStorage storage $ = _getTokenHomeStorage(); $._warpMessenger = IWarpMessenger(0x0200000000000000000000000000000000000005); diff --git a/contracts/src/staking/interfaces/IStakingManager.sol b/contracts/src/staking/interfaces/IStakingManager.sol index 963e31587..1a81dc669 100644 --- a/contracts/src/staking/interfaces/IStakingManager.sol +++ b/contracts/src/staking/interfaces/IStakingManager.sol @@ -5,6 +5,26 @@ pragma solidity 0.8.25; +import {StakingMessages} from "../StakingMessages.sol"; +import {IRewardCalculator} from "./IRewardCalculator.sol"; + + +struct InitialStakerInfo { + StakingMessages.ValidationInfo validationInfo; + address owner; +} + +struct StakingManagerSettings { + bytes32 pChainBlockchainID; + bytes32 subnetID; + uint256 minimumStakeAmount; + uint256 maximumStakeAmount; + uint64 minimumStakeDuration; + uint8 maximumHourlyChurn; + InitialStakerInfo[] initialStakers; + IRewardCalculator rewardCalculator; +} + interface IStakingManager { /** * @notice Emitted when a new validation period is created by stake being locked in the manager contract. From 36a8e0fed4b87274ebccf9fff83d4950392f6b55 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Tue, 30 Jul 2024 13:45:37 -0400 Subject: [PATCH 02/27] unit test skeleton --- .../NativeTokenStakingManagerTests.t.sol | 41 +++++++++++++ .../staking/tests/StakingManagerTests.t.sol | 58 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol create mode 100644 contracts/src/staking/tests/StakingManagerTests.t.sol diff --git a/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol new file mode 100644 index 000000000..2efafcb0a --- /dev/null +++ b/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -0,0 +1,41 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {Test} from "forge-std/Test.sol"; +import {StakingManagerTest} from "./StakingManagerTests.t.sol"; +import {NativeTokenStakingManager} from "../NativeTokenStakingManager.sol"; +import { + StakingManagerSettings, + InitialStakerInfo +} from "../interfaces/IStakingManager.sol"; +import { + IRewardCalculator +} from "../interfaces/IRewardCalculator.sol"; + +contract NativeTokenStakingManagerTest is StakingManagerTest { + NativeTokenStakingManager public nativeTokenStakingManager; + + function setup() public override { + StakingManagerTest.setup(); + nativeTokenStakingManager = new NativeTokenStakingManager(); + // TODONOW: Use real values + nativeTokenStakingManager.initialize( + StakingManagerSettings({ + pChainBlockchainID: "P-Chain", + subnetID: "X", + minimumStakeAmount: 1000, + maximumStakeAmount: 1000000, + minimumStakeDuration: 24 hours, + maximumHourlyChurn: 10, + initialStakers: new InitialStakerInfo[](0), + rewardCalculator: IRewardCalculator(address(0)) + }) + ); + } + + function testInitializeValidatorRegistration() public {} +} \ No newline at end of file diff --git a/contracts/src/staking/tests/StakingManagerTests.t.sol b/contracts/src/staking/tests/StakingManagerTests.t.sol new file mode 100644 index 000000000..4696b0eed --- /dev/null +++ b/contracts/src/staking/tests/StakingManagerTests.t.sol @@ -0,0 +1,58 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {Test} from "forge-std/Test.sol"; +import { + StakingManager +} from "../StakingManager.sol"; +import { + IStakingManager +} from "../interfaces/IStakingManager.sol"; + +abstract contract StakingManagerTest is Test { + IStakingManager public stakingManager; + + event ValidationPeriodCreated( + bytes32 indexed validationID, + bytes32 indexed nodeID, + bytes32 indexed registerValidationMessageID, + uint256 weight, + uint64 registrationExpiry + ); + + event ValidationPeriodRegistered( + bytes32 indexed validationID, uint256 stakeAmount, uint256 timestamp + ); + + event ValidatorRemovalInitialized( + bytes32 indexed validationID, + bytes32 indexed setWeightMessageID, + uint256 stakeAmount, + uint256 endTime, + uint64 uptime + ); + + event ValidationPeriodEnded(bytes32 indexed validationID); + + function setup() public virtual {} + + function testProvideInitialStake() public {} + + function testResendRegisterValidatorMessage() public {} + + function testCompleteValidatorRegistration() public {} + + function testInitializeEndValidation() public {} + + function testResendEndValidation() public {} + + function testCompleteEndValidation() public {} + + function testValueToWeight() public {} + + function testWeightToValue() public {} +} \ No newline at end of file From 4eff3199687845dfc914cfd818b12315bc923238 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Tue, 30 Jul 2024 13:46:14 -0400 Subject: [PATCH 03/27] format --- contracts/src/staking/StakingManager.sol | 5 +---- contracts/src/staking/interfaces/IStakingManager.sol | 1 - .../tests/NativeTokenStakingManagerTests.t.sol | 11 +++-------- contracts/src/staking/tests/StakingManagerTests.t.sol | 10 +++------- 4 files changed, 7 insertions(+), 20 deletions(-) diff --git a/contracts/src/staking/StakingManager.sol b/contracts/src/staking/StakingManager.sol index 41184eb05..4b0210415 100644 --- a/contracts/src/staking/StakingManager.sol +++ b/contracts/src/staking/StakingManager.sol @@ -5,10 +5,7 @@ pragma solidity 0.8.25; -import { - IStakingManager, - StakingManagerSettings -} from "./interfaces/IStakingManager.sol"; +import {IStakingManager, StakingManagerSettings} from "./interfaces/IStakingManager.sol"; import { WarpMessage, IWarpMessenger diff --git a/contracts/src/staking/interfaces/IStakingManager.sol b/contracts/src/staking/interfaces/IStakingManager.sol index 1a81dc669..f15864f48 100644 --- a/contracts/src/staking/interfaces/IStakingManager.sol +++ b/contracts/src/staking/interfaces/IStakingManager.sol @@ -8,7 +8,6 @@ pragma solidity 0.8.25; import {StakingMessages} from "../StakingMessages.sol"; import {IRewardCalculator} from "./IRewardCalculator.sol"; - struct InitialStakerInfo { StakingMessages.ValidationInfo validationInfo; address owner; diff --git a/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol index 2efafcb0a..6922eead8 100644 --- a/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -8,13 +8,8 @@ pragma solidity 0.8.25; import {Test} from "forge-std/Test.sol"; import {StakingManagerTest} from "./StakingManagerTests.t.sol"; import {NativeTokenStakingManager} from "../NativeTokenStakingManager.sol"; -import { - StakingManagerSettings, - InitialStakerInfo -} from "../interfaces/IStakingManager.sol"; -import { - IRewardCalculator -} from "../interfaces/IRewardCalculator.sol"; +import {StakingManagerSettings, InitialStakerInfo} from "../interfaces/IStakingManager.sol"; +import {IRewardCalculator} from "../interfaces/IRewardCalculator.sol"; contract NativeTokenStakingManagerTest is StakingManagerTest { NativeTokenStakingManager public nativeTokenStakingManager; @@ -38,4 +33,4 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { } function testInitializeValidatorRegistration() public {} -} \ No newline at end of file +} diff --git a/contracts/src/staking/tests/StakingManagerTests.t.sol b/contracts/src/staking/tests/StakingManagerTests.t.sol index 4696b0eed..0a1d510c7 100644 --- a/contracts/src/staking/tests/StakingManagerTests.t.sol +++ b/contracts/src/staking/tests/StakingManagerTests.t.sol @@ -6,12 +6,8 @@ pragma solidity 0.8.25; import {Test} from "forge-std/Test.sol"; -import { - StakingManager -} from "../StakingManager.sol"; -import { - IStakingManager -} from "../interfaces/IStakingManager.sol"; +import {StakingManager} from "../StakingManager.sol"; +import {IStakingManager} from "../interfaces/IStakingManager.sol"; abstract contract StakingManagerTest is Test { IStakingManager public stakingManager; @@ -55,4 +51,4 @@ abstract contract StakingManagerTest is Test { function testValueToWeight() public {} function testWeightToValue() public {} -} \ No newline at end of file +} From 8154fc594e437884dc1d80c01ce09f53a06643cc Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Wed, 31 Jul 2024 11:40:16 -0400 Subject: [PATCH 04/27] call initialize from ctr --- .../src/staking/NativeTokenStakingManager.sol | 6 ++++++ contracts/src/staking/StakingManager.sol | 14 +++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/contracts/src/staking/NativeTokenStakingManager.sol b/contracts/src/staking/NativeTokenStakingManager.sol index 020d96c0c..515cd0142 100644 --- a/contracts/src/staking/NativeTokenStakingManager.sol +++ b/contracts/src/staking/NativeTokenStakingManager.sol @@ -8,9 +8,15 @@ pragma solidity 0.8.25; import {INativeTokenStakingManager} from "./interfaces/INativeTokenStakingManager.sol"; import {Address} from "@openzeppelin/contracts@5.0.2/utils/Address.sol"; import {StakingManager} from "./StakingManager.sol"; +import {StakingManagerSettings} from "./interfaces/IStakingManager.sol"; contract NativeTokenStakingManager is StakingManager, INativeTokenStakingManager { using Address for address payable; + + constructor(StakingManagerSettings memory settings) { + StakingManager.initialize(settings); + } + /** * @notice Begins the validator registration process. Locks the provided native asset in the contract as the stake. * @param nodeID The node ID of the validator being registered. diff --git a/contracts/src/staking/StakingManager.sol b/contracts/src/staking/StakingManager.sol index 4b0210415..bb40f345d 100644 --- a/contracts/src/staking/StakingManager.sol +++ b/contracts/src/staking/StakingManager.sol @@ -77,7 +77,7 @@ abstract contract StakingManager is ReentrancyGuard, IStakingManager { } } - function initialize(StakingManagerSettings calldata settings) public { + function initialize(StakingManagerSettings memory settings) public { StakingManagerStorage storage $ = _getTokenHomeStorage(); $._warpMessenger = IWarpMessenger(0x0200000000000000000000000000000000000005); $._pChainBlockchainID = settings.pChainBlockchainID; @@ -112,11 +112,15 @@ abstract contract StakingManager is ReentrancyGuard, IStakingManager { * @notice Modifier to ensure that the initial stake has been provided. */ modifier onlyWhenInitialStakeProvided() { - StakingManagerStorage storage $ = _getTokenHomeStorage(); - require($._remainingInitialStake > 0, "StakingManager: Initial stake not provided"); + require(initialStakeProvided(), "StakingManager: Initial stake not provided"); _; } + function initialStakeProvided() public view returns (bool) { + StakingManagerStorage storage $ = _getTokenHomeStorage(); + return $._remainingInitialStake == 0; + } + /** * @notice Called to provide initial stake amount for original validators added prior to the contract's initialization. */ @@ -408,6 +412,10 @@ abstract contract StakingManager is ReentrancyGuard, IStakingManager { */ function _checkAndUpdateChurnTracker(uint64 amount) private { StakingManagerStorage storage $ = _getTokenHomeStorage(); + if ($._maximumHourlyChurn == 0) { + return; + } + ValidatorChrunPeriod storage churnTracker = $._churnTracker; uint256 currentTime = block.timestamp; if (currentTime - churnTracker.startedAt >= 1 hours) { From dbc031a845dd2cd51d8e516154dc557ce4dfb4af Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Wed, 31 Jul 2024 11:40:55 -0400 Subject: [PATCH 05/27] init vdr registration test --- .../NativeTokenStakingManagerTests.t.sol | 64 +++++++++++++++---- .../staking/tests/StakingManagerTests.t.sol | 41 +++++++++--- 2 files changed, 85 insertions(+), 20 deletions(-) diff --git a/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol index 6922eead8..87fe39870 100644 --- a/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -10,27 +10,67 @@ import {StakingManagerTest} from "./StakingManagerTests.t.sol"; import {NativeTokenStakingManager} from "../NativeTokenStakingManager.sol"; import {StakingManagerSettings, InitialStakerInfo} from "../interfaces/IStakingManager.sol"; import {IRewardCalculator} from "../interfaces/IRewardCalculator.sol"; +import {IWarpMessenger} from "../StakingManager.sol"; +import {StakingMessages} from "../StakingMessages.sol"; contract NativeTokenStakingManagerTest is StakingManagerTest { - NativeTokenStakingManager public nativeTokenStakingManager; + NativeTokenStakingManager public app; - function setup() public override { - StakingManagerTest.setup(); - nativeTokenStakingManager = new NativeTokenStakingManager(); - // TODONOW: Use real values - nativeTokenStakingManager.initialize( + function setUp() public override { + // Construct the object under test + app = new NativeTokenStakingManager( StakingManagerSettings({ - pChainBlockchainID: "P-Chain", - subnetID: "X", - minimumStakeAmount: 1000, - maximumStakeAmount: 1000000, + pChainBlockchainID: P_CHAIN_BLOCKCHAIN_ID, + subnetID: DEFAULT_SUBNET_ID, + minimumStakeAmount: 20, + maximumStakeAmount: 1e10, minimumStakeDuration: 24 hours, - maximumHourlyChurn: 10, + maximumHourlyChurn: 0, initialStakers: new InitialStakerInfo[](0), rewardCalculator: IRewardCalculator(address(0)) }) ); + stakingManager = app; + + // Setup the test + StakingManagerTest.setUp(); + } + + function testInitializeValidatorRegistrationSuccess() public { + (bytes32 validationID, ) = StakingMessages.packValidationInfo( + StakingMessages.ValidationInfo({ + nodeID: DEFAULT_NODE_ID, + subnetID: DEFAULT_SUBNET_ID, + weight: 1e6, + registrationExpiry: DEFAULT_EXPIRY, + signature: DEFAULT_ED25519_SIGNATURE + }) + ); + + vm.warp(DEFAULT_EXPIRY-1); + + vm.mockCall( + WARP_PRECOMPILE_ADDRESS, + abi.encode(IWarpMessenger.sendWarpMessage.selector), + abi.encode(bytes32(0)) + ); + // TODO: construct the expected message in the same way as the contract + // vm.expectCall( + // WARP_PRECOMPILE_ADDRESS, + // abi.encodeCall(IWarpMessenger.sendWarpMessage, (abi.encode(expectedMessage))) + // ); + vm.expectEmit(true, true, true, true, address(app)); + emit ValidationPeriodCreated(validationID, DEFAULT_NODE_ID, bytes32(0), 1e6, DEFAULT_EXPIRY); + + app.initializeValidatorRegistration{value: 1e18}( + DEFAULT_NODE_ID, + DEFAULT_EXPIRY, + DEFAULT_ED25519_SIGNATURE + ); } - function testInitializeValidatorRegistration() public {} + function testInitializeValidatorRegistrationExcessiveChurn() public {} + function testInitializeValidatorRegistrationInsufficientStake() public {} + function testInitializeValidatorRegistrationExcessiveStake() public {} + function testInitializeValidatorRegistrationInsufficientDuration() public {} } diff --git a/contracts/src/staking/tests/StakingManagerTests.t.sol b/contracts/src/staking/tests/StakingManagerTests.t.sol index 0a1d510c7..94b248cd0 100644 --- a/contracts/src/staking/tests/StakingManagerTests.t.sol +++ b/contracts/src/staking/tests/StakingManagerTests.t.sol @@ -7,10 +7,21 @@ pragma solidity 0.8.25; import {Test} from "forge-std/Test.sol"; import {StakingManager} from "../StakingManager.sol"; -import {IStakingManager} from "../interfaces/IStakingManager.sol"; abstract contract StakingManagerTest is Test { - IStakingManager public stakingManager; + bytes32 public constant P_CHAIN_BLOCKCHAIN_ID = + bytes32(hex"0000000000000000000000000000000000000000000000000000000000000000"); + bytes32 public constant DEFAULT_SUBNET_ID = + bytes32(hex"1234567812345678123456781234567812345678123456781234567812345678"); + bytes32 public constant DEFAULT_NODE_ID = + bytes32(hex"1234567812345678123456781234567812345678123456781234567812345678"); + uint64 public constant DEFAULT_EXPIRY = 1000; + bytes public constant DEFAULT_ED25519_SIGNATURE = + bytes(hex"12345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678"); + address public constant WARP_PRECOMPILE_ADDRESS = 0x0200000000000000000000000000000000000005; + + + StakingManager public stakingManager; event ValidationPeriodCreated( bytes32 indexed validationID, @@ -34,9 +45,7 @@ abstract contract StakingManagerTest is Test { event ValidationPeriodEnded(bytes32 indexed validationID); - function setup() public virtual {} - - function testProvideInitialStake() public {} + function setUp() public virtual {} function testResendRegisterValidatorMessage() public {} @@ -48,7 +57,23 @@ abstract contract StakingManagerTest is Test { function testCompleteEndValidation() public {} - function testValueToWeight() public {} - - function testWeightToValue() public {} + function testValueToWeight() public { + uint64 w1 = stakingManager.valueToWeight(1e12); + uint64 w2 = stakingManager.valueToWeight(1e18); + uint64 w3 = stakingManager.valueToWeight(1e27); + + assertEq(w1, 1); + assertEq(w2, 1e6); + assertEq(w3, 1e15); + } + + function testWeightToValue() public { + uint256 v1 = stakingManager.weightToValue(1); + uint256 v2 = stakingManager.weightToValue(1e6); + uint256 v3 = stakingManager.weightToValue(1e15); + + assertEq(v1, 1e12); + assertEq(v2, 1e18); + assertEq(v3, 1e27); + } } From 0a29c4379512c3fa18b8a8beed6bb01a38140a05 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Wed, 31 Jul 2024 12:07:37 -0400 Subject: [PATCH 06/27] resend register vdr test --- .../NativeTokenStakingManagerTests.t.sol | 83 +++++++++++++++---- .../staking/tests/StakingManagerTests.t.sol | 10 --- 2 files changed, 67 insertions(+), 26 deletions(-) diff --git a/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol index 87fe39870..e4a9e4b5e 100644 --- a/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -37,13 +37,69 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { } function testInitializeValidatorRegistrationSuccess() public { - (bytes32 validationID, ) = StakingMessages.packValidationInfo( + _setUpInitializeValidatorRegistration( + DEFAULT_NODE_ID, + DEFAULT_SUBNET_ID, + 1e6, + DEFAULT_EXPIRY, + DEFAULT_ED25519_SIGNATURE + ); + } + + function testInitializeValidatorRegistrationExcessiveChurn() public {} + function testInitializeValidatorRegistrationInsufficientStake() public {} + function testInitializeValidatorRegistrationExcessiveStake() public {} + function testInitializeValidatorRegistrationInsufficientDuration() public {} + + // The following tests call functions that are implemented in StakingManager, but access state that's + // only set in NativeTokenStakingManager. Therefore we call them via the concrete type, rather than a + // reference to the abstract type. + function testResendRegisterValidatorMessage() public { + bytes32 validationID = _setUpInitializeValidatorRegistration( + DEFAULT_NODE_ID, + DEFAULT_SUBNET_ID, + 1e6, + DEFAULT_EXPIRY, + DEFAULT_ED25519_SIGNATURE + ); + vm.mockCall( + WARP_PRECOMPILE_ADDRESS, + abi.encode(IWarpMessenger.sendWarpMessage.selector), + abi.encode(bytes32(0)) + ); + // TODO: construct the expected message in the same way as the contract + // vm.expectCall( + // WARP_PRECOMPILE_ADDRESS, + // abi.encodeCall(IWarpMessenger.sendWarpMessage, (abi.encode(expectedMessage))) + // ); + app.resendRegisterValidatorMessage(validationID); + } + + function testCompleteValidatorRegistration() public {} + + function testInitializeEndValidation() public {} + + function testInitializeEndValidationWithUptimeProof() public {} + + function testResendEndValidation() public {} + + function testCompleteEndValidation() public {} + + // Helpers + function _setUpInitializeValidatorRegistration( + bytes32 nodeID, + bytes32 subnetID, + uint64 weight, + uint64 registrationExpiry, + bytes memory signature + ) internal returns (bytes32 validationID){ + (validationID, ) = StakingMessages.packValidationInfo( StakingMessages.ValidationInfo({ - nodeID: DEFAULT_NODE_ID, - subnetID: DEFAULT_SUBNET_ID, - weight: 1e6, - registrationExpiry: DEFAULT_EXPIRY, - signature: DEFAULT_ED25519_SIGNATURE + nodeID: nodeID, + subnetID: subnetID, + weight: weight, + registrationExpiry: registrationExpiry, + signature: signature }) ); @@ -60,17 +116,12 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { // abi.encodeCall(IWarpMessenger.sendWarpMessage, (abi.encode(expectedMessage))) // ); vm.expectEmit(true, true, true, true, address(app)); - emit ValidationPeriodCreated(validationID, DEFAULT_NODE_ID, bytes32(0), 1e6, DEFAULT_EXPIRY); + emit ValidationPeriodCreated(validationID, DEFAULT_NODE_ID, bytes32(0), weight, DEFAULT_EXPIRY); - app.initializeValidatorRegistration{value: 1e18}( - DEFAULT_NODE_ID, - DEFAULT_EXPIRY, - DEFAULT_ED25519_SIGNATURE + app.initializeValidatorRegistration{value: app.weightToValue(weight)}( + nodeID, + registrationExpiry, + signature ); } - - function testInitializeValidatorRegistrationExcessiveChurn() public {} - function testInitializeValidatorRegistrationInsufficientStake() public {} - function testInitializeValidatorRegistrationExcessiveStake() public {} - function testInitializeValidatorRegistrationInsufficientDuration() public {} } diff --git a/contracts/src/staking/tests/StakingManagerTests.t.sol b/contracts/src/staking/tests/StakingManagerTests.t.sol index 94b248cd0..339581293 100644 --- a/contracts/src/staking/tests/StakingManagerTests.t.sol +++ b/contracts/src/staking/tests/StakingManagerTests.t.sol @@ -47,16 +47,6 @@ abstract contract StakingManagerTest is Test { function setUp() public virtual {} - function testResendRegisterValidatorMessage() public {} - - function testCompleteValidatorRegistration() public {} - - function testInitializeEndValidation() public {} - - function testResendEndValidation() public {} - - function testCompleteEndValidation() public {} - function testValueToWeight() public { uint64 w1 = stakingManager.valueToWeight(1e12); uint64 w2 = stakingManager.valueToWeight(1e18); From a6f2949aa9376882ca8b050d620108d6039c758b Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Wed, 31 Jul 2024 12:11:54 -0400 Subject: [PATCH 07/27] format --- .../src/staking/NativeTokenStakingManager.sol | 1 - .../NativeTokenStakingManagerTests.t.sol | 28 +++++++------------ .../staking/tests/StakingManagerTests.t.sol | 6 ++-- 3 files changed, 13 insertions(+), 22 deletions(-) diff --git a/contracts/src/staking/NativeTokenStakingManager.sol b/contracts/src/staking/NativeTokenStakingManager.sol index 515cd0142..59e6310c9 100644 --- a/contracts/src/staking/NativeTokenStakingManager.sol +++ b/contracts/src/staking/NativeTokenStakingManager.sol @@ -28,7 +28,6 @@ contract NativeTokenStakingManager is StakingManager, INativeTokenStakingManager * The signature field will be validated by the P-Chain. Implementations may choose to validate that the signature * field is well-formed but it is not required. */ - function initializeValidatorRegistration( bytes32 nodeID, uint64 registrationExpiry, diff --git a/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol index e4a9e4b5e..c32759c7f 100644 --- a/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -38,11 +38,7 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { function testInitializeValidatorRegistrationSuccess() public { _setUpInitializeValidatorRegistration( - DEFAULT_NODE_ID, - DEFAULT_SUBNET_ID, - 1e6, - DEFAULT_EXPIRY, - DEFAULT_ED25519_SIGNATURE + DEFAULT_NODE_ID, DEFAULT_SUBNET_ID, 1e6, DEFAULT_EXPIRY, DEFAULT_ED25519_SIGNATURE ); } @@ -56,11 +52,7 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { // reference to the abstract type. function testResendRegisterValidatorMessage() public { bytes32 validationID = _setUpInitializeValidatorRegistration( - DEFAULT_NODE_ID, - DEFAULT_SUBNET_ID, - 1e6, - DEFAULT_EXPIRY, - DEFAULT_ED25519_SIGNATURE + DEFAULT_NODE_ID, DEFAULT_SUBNET_ID, 1e6, DEFAULT_EXPIRY, DEFAULT_ED25519_SIGNATURE ); vm.mockCall( WARP_PRECOMPILE_ADDRESS, @@ -92,8 +84,8 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { uint64 weight, uint64 registrationExpiry, bytes memory signature - ) internal returns (bytes32 validationID){ - (validationID, ) = StakingMessages.packValidationInfo( + ) internal returns (bytes32 validationID) { + (validationID,) = StakingMessages.packValidationInfo( StakingMessages.ValidationInfo({ nodeID: nodeID, subnetID: subnetID, @@ -103,8 +95,8 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { }) ); - vm.warp(DEFAULT_EXPIRY-1); - + vm.warp(DEFAULT_EXPIRY - 1); + vm.mockCall( WARP_PRECOMPILE_ADDRESS, abi.encode(IWarpMessenger.sendWarpMessage.selector), @@ -116,12 +108,12 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { // abi.encodeCall(IWarpMessenger.sendWarpMessage, (abi.encode(expectedMessage))) // ); vm.expectEmit(true, true, true, true, address(app)); - emit ValidationPeriodCreated(validationID, DEFAULT_NODE_ID, bytes32(0), weight, DEFAULT_EXPIRY); + emit ValidationPeriodCreated( + validationID, DEFAULT_NODE_ID, bytes32(0), weight, DEFAULT_EXPIRY + ); app.initializeValidatorRegistration{value: app.weightToValue(weight)}( - nodeID, - registrationExpiry, - signature + nodeID, registrationExpiry, signature ); } } diff --git a/contracts/src/staking/tests/StakingManagerTests.t.sol b/contracts/src/staking/tests/StakingManagerTests.t.sol index 339581293..51f7c6fdf 100644 --- a/contracts/src/staking/tests/StakingManagerTests.t.sol +++ b/contracts/src/staking/tests/StakingManagerTests.t.sol @@ -16,11 +16,11 @@ abstract contract StakingManagerTest is Test { bytes32 public constant DEFAULT_NODE_ID = bytes32(hex"1234567812345678123456781234567812345678123456781234567812345678"); uint64 public constant DEFAULT_EXPIRY = 1000; - bytes public constant DEFAULT_ED25519_SIGNATURE = - bytes(hex"12345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678"); + bytes public constant DEFAULT_ED25519_SIGNATURE = bytes( + hex"12345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678" + ); address public constant WARP_PRECOMPILE_ADDRESS = 0x0200000000000000000000000000000000000005; - StakingManager public stakingManager; event ValidationPeriodCreated( From d84f8ee6e286c7eeec2a5be15bac1e2cf9d0c3b5 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Wed, 31 Jul 2024 14:56:46 -0400 Subject: [PATCH 08/27] wip --- .../src/staking/tests/NativeTokenStakingManagerTests.t.sol | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol index c32759c7f..827cb1ab7 100644 --- a/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -73,7 +73,9 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { function testInitializeEndValidationWithUptimeProof() public {} - function testResendEndValidation() public {} + function testResendEndValidation() public { + // TODO: implement + } function testCompleteEndValidation() public {} @@ -116,4 +118,6 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { nodeID, registrationExpiry, signature ); } + + function _setUpCompleteValidatorRegistration() internal {} } From 304bec65fc9405a58fab0ea2e54b6b3cbffe512d Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Thu, 1 Aug 2024 09:46:51 -0400 Subject: [PATCH 09/27] move files --- .../staking/tests/NativeTokenStakingManagerTests.t.sol | 2 +- contracts/{src => }/staking/tests/StakingManagerTests.t.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename contracts/{src => }/staking/tests/NativeTokenStakingManagerTests.t.sol (99%) rename contracts/{src => }/staking/tests/StakingManagerTests.t.sol (98%) diff --git a/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol similarity index 99% rename from contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol rename to contracts/staking/tests/NativeTokenStakingManagerTests.t.sol index 827cb1ab7..293e78e4a 100644 --- a/contracts/src/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -5,7 +5,7 @@ pragma solidity 0.8.25; -import {Test} from "forge-std/Test.sol"; +import {Test} from "@forge-std/Test.sol"; import {StakingManagerTest} from "./StakingManagerTests.t.sol"; import {NativeTokenStakingManager} from "../NativeTokenStakingManager.sol"; import {StakingManagerSettings, InitialStakerInfo} from "../interfaces/IStakingManager.sol"; diff --git a/contracts/src/staking/tests/StakingManagerTests.t.sol b/contracts/staking/tests/StakingManagerTests.t.sol similarity index 98% rename from contracts/src/staking/tests/StakingManagerTests.t.sol rename to contracts/staking/tests/StakingManagerTests.t.sol index 51f7c6fdf..8265ac848 100644 --- a/contracts/src/staking/tests/StakingManagerTests.t.sol +++ b/contracts/staking/tests/StakingManagerTests.t.sol @@ -5,7 +5,7 @@ pragma solidity 0.8.25; -import {Test} from "forge-std/Test.sol"; +import {Test} from "@forge-std/Test.sol"; import {StakingManager} from "../StakingManager.sol"; abstract contract StakingManagerTest is Test { From 1c1985f56704b8c51cf38ec53c13b30a330d00e7 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Thu, 1 Aug 2024 10:46:51 -0400 Subject: [PATCH 10/27] full pack/unpack parity --- contracts/staking/StakingMessages.sol | 194 +++++++++++++++++++++++++- 1 file changed, 192 insertions(+), 2 deletions(-) diff --git a/contracts/staking/StakingMessages.sol b/contracts/staking/StakingMessages.sol index 3d6698b89..31e455263 100644 --- a/contracts/staking/StakingMessages.sol +++ b/contracts/staking/StakingMessages.sol @@ -47,6 +47,9 @@ library StakingMessages { * +-----------+----------+-----------+ * | 148 bytes | * +-----------+ + * + * @param valiationInfo The information to pack into the message. + * @return The validationID and the packed message. */ function packRegisterSubnetValidatorMessage(ValidationInfo memory valiationInfo) internal @@ -70,7 +73,70 @@ library StakingMessages { } /** - * @notice Unpacks a byte array as a RegisterSubnetValidator message. + * @notice Unpacks a byte array as a RegisterSubnetValidatorMessage message. + * The message format specification is the same as the one used in above for packing. + * + * @param input The byte array to unpack. + * @return the unpacked ValidationInfo. + */ + function unpackRegisterSubnetValidatorMessage(bytes memory input) + internal + pure + returns (ValidationInfo memory) + { + require(input.length == 148, "StakingMessages: Invalid message length"); + + // Unpack the type ID + uint32 typeID; + for (uint256 i; i < 4; ++i) { + typeID |= uint32(uint8(input[i])) << uint32((8 * (3 - i))); + } + require( + typeID == SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID, + "StakingMessages: Invalid message type" + ); + + // Unpack the subnet ID + bytes32 subnetID; + for (uint256 i; i < 32; ++i) { + subnetID |= bytes32(uint256(uint8(input[i + 4])) << (8 * (31 - i))); + } + + // Unpack the node ID + bytes32 nodeID; + for (uint256 i; i < 32; ++i) { + nodeID |= bytes32(uint256(uint8(input[i + 36])) << (8 * (31 - i))); + } + + // Unpack the weight + uint64 weight; + for (uint256 i; i < 8; ++i) { + weight |= uint64(uint8(input[i + 68])) << uint64((8 * (7 - i))); + } + + // Unpack the expiry + uint64 expiry; + for (uint256 i; i < 8; ++i) { + expiry |= uint64(uint8(input[i + 76])) << uint64((8 * (7 - i))); + } + + // Unpack the signature + bytes memory signature = new bytes(64); + for (uint256 i; i < 64; ++i) { + signature[i] = input[i + 84]; + } + + return ValidationInfo({ + subnetID: subnetID, + nodeID: nodeID, + weight: weight, + registrationExpiry: expiry, + signature: signature + }); + } + + /** + * @notice Packs a SubnetValidatorRegistrationMessage into a byte array. * The message format specification is: * +--------------+----------+----------+ * | typeID : uint32 | 4 bytes | @@ -81,6 +147,35 @@ library StakingMessages { * +--------------+----------+----------+ * | 37 bytes | * +----------+ + * + * @param validationID The ID of the validation period. + * @param valid true if the validation period was registered, false if it was not and never will be. + * @return The packed message. + * + */ + function packSubnetValidatorRegistrationMessage( + bytes32 validationID, + bool valid + ) internal pure returns (bytes memory) { + bytes memory res = new bytes(37); + // Pack the type ID. + for (uint256 i; i < 4; ++i) { + res[i] = bytes1(uint8(SUBNET_VALIDATOR_REGISTRATION_MESSAGE_TYPE_ID >> (8 * (3 - i)))); + } + // Pack the validation ID. + for (uint256 i; i < 32; ++i) { + res[i + 4] = bytes1(uint8(uint256(validationID >> (8 * (31 - i))))); + } + // Pack the validity. + res[36] = bytes1(valid ? 1 : 0); + return res; + } + + /** + * @notice Unpacks a byte array as a SubnetValidatorRegistrationMessage message. + * The message format specification is the same as the one used in above for packing. + * + * @param input The byte array to unpack. * @return The validationID and whether or the validation period was registered * or is not a validator and never will be a validator to do the expiry time passing. */ @@ -127,6 +222,11 @@ library StakingMessages { * +--------------+----------+----------+ * | 52 bytes | * +----------+ + * + * @param validationID The ID of the validation period. + * @param nonce The nonce of the validation ID. + * @param weight The new weight of the validator. + * @return The packed message. */ function packSetSubnetValidatorWeightMessage( bytes32 validationID, @@ -156,6 +256,9 @@ library StakingMessages { /** * @notice Unpacks a byte array as a SetSubnetValidatorWeight message. * The message format specification is the same as the one used in above for packing. + * + * @param input The byte array to unpack. + * @return The validationID, nonce, and weight. */ function unpackSetSubnetValidatorWeightMessage(bytes memory input) internal @@ -196,7 +299,7 @@ library StakingMessages { } /** - * @notice Unpacks a byte array as a ValidationUptimeMessage. + * @notice Packs a ValidationUptimeMessage into a byte array. * The message format specification is: * +--------------+----------+----------+ * | typeID : uint32 | 4 bytes | @@ -207,6 +310,37 @@ library StakingMessages { * +--------------+----------+----------+ * | 44 bytes | * +----------+ + * + * @param validationID The ID of the validation period. + * @param uptime The uptime of the validator. + * @return The packed message. + */ + function packValidationUptimeMessage( + bytes32 validationID, + uint64 uptime + ) internal pure returns (bytes memory) { + bytes memory res = new bytes(44); + // Pack the type ID. + for (uint256 i; i < 4; ++i) { + res[i] = bytes1(uint8(VALIDATION_UPTIME_MESSAGE_TYPE_ID >> (8 * (3 - i)))); + } + // Pack the validation ID. + for (uint256 i; i < 32; ++i) { + res[i + 4] = bytes1(uint8(uint256(validationID >> (8 * (31 - i))))); + } + // Pack the uptime. + for (uint256 i; i < 8; ++i) { + res[i + 36] = bytes1(uint8(uptime >> (8 * (7 - i)))); + } + return res; + } + + /** + * @notice Unpacks a byte array as a ValidationUptimeMessage. + * The message format specification is the same as the one used in above for packing. + * + * @param input The byte array to unpack. + * @return The validationID and uptime. */ function unpackValidationUptimeMessage(bytes memory input) internal @@ -256,6 +390,9 @@ library StakingMessages { * +-----------+----------+-----------+ * | 144 bytes | * +-----------+ + * + * @param validationInfo The information to pack. + * @return The validationID and the packed data. */ function packValidationInfo(ValidationInfo memory validationInfo) internal @@ -286,4 +423,57 @@ library StakingMessages { } return (sha256(res), res); } + + /** + * @notice Unpacks a byte array as a ValidationInfo. + * The message format specification is the same as the one used in above for packing. + * + * @param input The byte array to unpack. + * @return The unpacked ValidationInfo. + */ + function unpackValidationInfo(bytes memory input) + internal + pure + returns (ValidationInfo memory) + { + require(input.length == 144, "StakingMessages: Invalid message length"); + + // Unpack the subnetID + bytes32 subnetID; + for (uint256 i; i < 32; ++i) { + subnetID |= bytes32(uint256(uint8(input[i])) << (8 * (31 - i))); + } + + // Unpack the nodeID + bytes32 nodeID; + for (uint256 i; i < 32; ++i) { + nodeID |= bytes32(uint256(uint8(input[i + 32])) << (8 * (31 - i))); + } + + // Unpack the weight + uint64 weight; + for (uint256 i; i < 8; ++i) { + weight |= uint64(uint8(input[i + 64])) << uint64((8 * (7 - i))); + } + + // Unpack the registration expiry + uint64 expiry; + for (uint256 i; i < 8; ++i) { + expiry |= uint64(uint8(input[i + 72])) << uint64((8 * (7 - i))); + } + + // Unpack the signature + bytes memory signature = new bytes(64); + for (uint256 i; i < 64; ++i) { + signature[i] = input[i + 80]; + } + + return ValidationInfo({ + subnetID: subnetID, + nodeID: nodeID, + weight: weight, + registrationExpiry: expiry, + signature: signature + }); + } } From 4d4ed7d89e531570d763dfb3a481ebce64b6a568 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Thu, 1 Aug 2024 10:47:08 -0400 Subject: [PATCH 11/27] staking messages tests --- .../staking/tests/StakingMessagesTests.t.sol | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 contracts/staking/tests/StakingMessagesTests.t.sol diff --git a/contracts/staking/tests/StakingMessagesTests.t.sol b/contracts/staking/tests/StakingMessagesTests.t.sol new file mode 100644 index 000000000..e41e38692 --- /dev/null +++ b/contracts/staking/tests/StakingMessagesTests.t.sol @@ -0,0 +1,94 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.25; + +import {Test} from "@forge-std/Test.sol"; +import {StakingMessages} from "../StakingMessages.sol"; + +contract StakingMessagesTest is Test { + bytes32 public constant DEFAULT_SUBNET_ID = + bytes32(hex"1234567812345678123456781234567812345678123456781234567812345678"); + bytes32 public constant DEFAULT_NODE_ID = + bytes32(hex"1234567812345678123456781234567812345678123456781234567812345678"); + uint64 public constant DEFAULT_EXPIRY = 1000; + bytes public constant DEFAULT_ED25519_SIGNATURE = bytes( + hex"12345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678" + ); + uint64 public constant DEFAULT_WEIGHT = 1e6; + bytes32 public constant DEFAULT_VALIDATION_ID = + bytes32(hex"1234567812345678123456781234567812345678123456781234567812345678"); + + function testRegisterSubnetValidatorMessage() public pure { + (bytes32 validationID, bytes memory packed) = StakingMessages + .packRegisterSubnetValidatorMessage( + StakingMessages.ValidationInfo({ + subnetID: DEFAULT_SUBNET_ID, + nodeID: DEFAULT_NODE_ID, + weight: DEFAULT_WEIGHT, + registrationExpiry: DEFAULT_EXPIRY, + signature: DEFAULT_ED25519_SIGNATURE + }) + ); + + StakingMessages.ValidationInfo memory info = + StakingMessages.unpackRegisterSubnetValidatorMessage(packed); + assertEq(info.subnetID, DEFAULT_SUBNET_ID); + assertEq(info.nodeID, DEFAULT_NODE_ID); + assertEq(info.weight, DEFAULT_WEIGHT); + assertEq(info.registrationExpiry, DEFAULT_EXPIRY); + assertEq(info.signature, DEFAULT_ED25519_SIGNATURE); + + (bytes32 recoveredID,) = StakingMessages.packValidationInfo(info); + assertEq(recoveredID, validationID); + } + + function testSubnetValidatorRegistrationMessage() public pure { + bytes memory packed = + StakingMessages.packSubnetValidatorRegistrationMessage(DEFAULT_VALIDATION_ID, true); + (bytes32 validationID, bool valid) = + StakingMessages.unpackSubnetValidatorRegistrationMessage(packed); + assertEq(validationID, DEFAULT_VALIDATION_ID); + assert(valid); + } + + function testSetSubnetValidatorWeightMessage() public pure { + bytes memory packed = StakingMessages.packSetSubnetValidatorWeightMessage( + DEFAULT_VALIDATION_ID, 100, DEFAULT_WEIGHT + ); + (bytes32 validationID, uint64 nonce, uint64 weight) = + StakingMessages.unpackSetSubnetValidatorWeightMessage(packed); + assertEq(validationID, DEFAULT_VALIDATION_ID); + assertEq(nonce, 100); + assertEq(weight, DEFAULT_WEIGHT); + } + + function testValidationUptimeMessage() public pure { + bytes memory packed = + StakingMessages.packValidationUptimeMessage(DEFAULT_VALIDATION_ID, 100); + (bytes32 validationID, uint64 uptime) = + StakingMessages.unpackValidationUptimeMessage(packed); + assertEq(validationID, DEFAULT_VALIDATION_ID); + assertEq(uptime, 100); + } + + function testValidationInfo() public pure { + (, bytes memory packed) = StakingMessages.packValidationInfo( + StakingMessages.ValidationInfo({ + subnetID: DEFAULT_SUBNET_ID, + nodeID: DEFAULT_NODE_ID, + weight: DEFAULT_WEIGHT, + registrationExpiry: DEFAULT_EXPIRY, + signature: DEFAULT_ED25519_SIGNATURE + }) + ); + StakingMessages.ValidationInfo memory info = StakingMessages.unpackValidationInfo(packed); + assertEq(info.subnetID, DEFAULT_SUBNET_ID); + assertEq(info.nodeID, DEFAULT_NODE_ID); + assertEq(info.weight, DEFAULT_WEIGHT); + assertEq(info.registrationExpiry, DEFAULT_EXPIRY); + assertEq(info.signature, DEFAULT_ED25519_SIGNATURE); + } +} From 23089c01c35e2f4faf25d09b5e5181f8f70146d2 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Thu, 1 Aug 2024 10:47:44 -0400 Subject: [PATCH 12/27] restrict to view --- contracts/staking/tests/StakingManagerTests.t.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/staking/tests/StakingManagerTests.t.sol b/contracts/staking/tests/StakingManagerTests.t.sol index 8265ac848..33a21890c 100644 --- a/contracts/staking/tests/StakingManagerTests.t.sol +++ b/contracts/staking/tests/StakingManagerTests.t.sol @@ -47,7 +47,7 @@ abstract contract StakingManagerTest is Test { function setUp() public virtual {} - function testValueToWeight() public { + function testValueToWeight() public view { uint64 w1 = stakingManager.valueToWeight(1e12); uint64 w2 = stakingManager.valueToWeight(1e18); uint64 w3 = stakingManager.valueToWeight(1e27); @@ -57,7 +57,7 @@ abstract contract StakingManagerTest is Test { assertEq(w3, 1e15); } - function testWeightToValue() public { + function testWeightToValue() public view { uint256 v1 = stakingManager.weightToValue(1); uint256 v2 = stakingManager.weightToValue(1e6); uint256 v3 = stakingManager.weightToValue(1e15); From a80ac9c5b8a626f96b209dfa31b7b42801b283f2 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Thu, 1 Aug 2024 11:32:25 -0400 Subject: [PATCH 13/27] complete vdr registration test --- .../NativeTokenStakingManagerTests.t.sol | 66 ++++++++++++++++--- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol index 293e78e4a..16b1bf2d0 100644 --- a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -10,7 +10,7 @@ import {StakingManagerTest} from "./StakingManagerTests.t.sol"; import {NativeTokenStakingManager} from "../NativeTokenStakingManager.sol"; import {StakingManagerSettings, InitialStakerInfo} from "../interfaces/IStakingManager.sol"; import {IRewardCalculator} from "../interfaces/IRewardCalculator.sol"; -import {IWarpMessenger} from "../StakingManager.sol"; +import {IWarpMessenger, WarpMessage} from "../StakingManager.sol"; import {StakingMessages} from "../StakingMessages.sol"; contract NativeTokenStakingManagerTest is StakingManagerTest { @@ -42,10 +42,18 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { ); } - function testInitializeValidatorRegistrationExcessiveChurn() public {} - function testInitializeValidatorRegistrationInsufficientStake() public {} - function testInitializeValidatorRegistrationExcessiveStake() public {} - function testInitializeValidatorRegistrationInsufficientDuration() public {} + function testInitializeValidatorRegistrationExcessiveChurn() public { + // TODO: implement + } + function testInitializeValidatorRegistrationInsufficientStake() public { + // TODO: implement + } + function testInitializeValidatorRegistrationExcessiveStake() public { + // TODO: implement + } + function testInitializeValidatorRegistrationInsufficientDuration() public { + // TODO: implement + } // The following tests call functions that are implemented in StakingManager, but access state that's // only set in NativeTokenStakingManager. Therefore we call them via the concrete type, rather than a @@ -67,17 +75,57 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { app.resendRegisterValidatorMessage(validationID); } - function testCompleteValidatorRegistration() public {} + function testCompleteValidatorRegistration() public { + bytes32 validationID = _setUpInitializeValidatorRegistration( + DEFAULT_NODE_ID, DEFAULT_SUBNET_ID, 1e6, DEFAULT_EXPIRY, DEFAULT_ED25519_SIGNATURE + ); + bytes memory subnetValidatorRegistrationMessage = StakingMessages.packSubnetValidatorRegistrationMessage( + validationID, + true + ); + vm.mockCall( + WARP_PRECOMPILE_ADDRESS, + abi.encodeWithSelector(IWarpMessenger.getVerifiedWarpMessage.selector, uint32(0)), + abi.encode( + WarpMessage({ + sourceChainID: P_CHAIN_BLOCKCHAIN_ID, + originSenderAddress: address(0), + payload: subnetValidatorRegistrationMessage + }), + true + ) + ); + vm.expectCall( + WARP_PRECOMPILE_ADDRESS, + abi.encodeCall(IWarpMessenger.getVerifiedWarpMessage, 0) + ); + + vm.warp(1000); + vm.expectEmit(true, true, true, true, address(app)); + emit ValidationPeriodRegistered(validationID, 1e6, 1000); - function testInitializeEndValidation() public {} + app.completeValidatorRegistration(0); + } + + function testInitializeEndValidation() public { + // TODO: implement + } - function testInitializeEndValidationWithUptimeProof() public {} + function testInitializeEndValidationWithUptimeProof() public { + // TODO: implement + } function testResendEndValidation() public { // TODO: implement } - function testCompleteEndValidation() public {} + function testCompleteEndValidation() public { + // TODO: implement + } + + function testCompleteEndValidationSetWeightMessageType() public { + // TODO: implement + } // Helpers function _setUpInitializeValidatorRegistration( From f8fc4d5c5b3ecc8cac317edece3e1f82431cf922 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Thu, 1 Aug 2024 11:32:49 -0400 Subject: [PATCH 14/27] format --- .../tests/NativeTokenStakingManagerTests.t.sol | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol index 16b1bf2d0..6e58dc1b3 100644 --- a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -75,14 +75,12 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { app.resendRegisterValidatorMessage(validationID); } - function testCompleteValidatorRegistration() public { + function testCompleteValidatorRegistration() public { bytes32 validationID = _setUpInitializeValidatorRegistration( DEFAULT_NODE_ID, DEFAULT_SUBNET_ID, 1e6, DEFAULT_EXPIRY, DEFAULT_ED25519_SIGNATURE ); - bytes memory subnetValidatorRegistrationMessage = StakingMessages.packSubnetValidatorRegistrationMessage( - validationID, - true - ); + bytes memory subnetValidatorRegistrationMessage = + StakingMessages.packSubnetValidatorRegistrationMessage(validationID, true); vm.mockCall( WARP_PRECOMPILE_ADDRESS, abi.encodeWithSelector(IWarpMessenger.getVerifiedWarpMessage.selector, uint32(0)), @@ -96,10 +94,9 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { ) ); vm.expectCall( - WARP_PRECOMPILE_ADDRESS, - abi.encodeCall(IWarpMessenger.getVerifiedWarpMessage, 0) + WARP_PRECOMPILE_ADDRESS, abi.encodeCall(IWarpMessenger.getVerifiedWarpMessage, 0) ); - + vm.warp(1000); vm.expectEmit(true, true, true, true, address(app)); emit ValidationPeriodRegistered(validationID, 1e6, 1000); From cf1e444c50eda1931c70e901f5cdead5295e9e0d Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Thu, 1 Aug 2024 14:50:46 -0400 Subject: [PATCH 15/27] init end vdr test --- .../NativeTokenStakingManagerTests.t.sol | 90 +++++++++++++------ 1 file changed, 65 insertions(+), 25 deletions(-) diff --git a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol index 6e58dc1b3..8669c2894 100644 --- a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -76,39 +76,45 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { } function testCompleteValidatorRegistration() public { - bytes32 validationID = _setUpInitializeValidatorRegistration( - DEFAULT_NODE_ID, DEFAULT_SUBNET_ID, 1e6, DEFAULT_EXPIRY, DEFAULT_ED25519_SIGNATURE - ); - bytes memory subnetValidatorRegistrationMessage = - StakingMessages.packSubnetValidatorRegistrationMessage(validationID, true); + _setUpCompleteValidatorRegistration({ + nodeID: DEFAULT_NODE_ID, + subnetID: DEFAULT_SUBNET_ID, + weight: 1e6, + registrationExpiry: DEFAULT_EXPIRY, + signature: DEFAULT_ED25519_SIGNATURE, + registrationTimestamp: 1000 + }); + } + + function testInitializeEndValidation() public { + bytes32 validationID = _setUpCompleteValidatorRegistration({ + nodeID: DEFAULT_NODE_ID, + subnetID: DEFAULT_SUBNET_ID, + weight: 1e6, + registrationExpiry: DEFAULT_EXPIRY, + signature: DEFAULT_ED25519_SIGNATURE, + registrationTimestamp: 1000 + }); + + vm.warp(2000); vm.mockCall( WARP_PRECOMPILE_ADDRESS, - abi.encodeWithSelector(IWarpMessenger.getVerifiedWarpMessage.selector, uint32(0)), - abi.encode( - WarpMessage({ - sourceChainID: P_CHAIN_BLOCKCHAIN_ID, - originSenderAddress: address(0), - payload: subnetValidatorRegistrationMessage - }), - true - ) - ); - vm.expectCall( - WARP_PRECOMPILE_ADDRESS, abi.encodeCall(IWarpMessenger.getVerifiedWarpMessage, 0) + abi.encode(IWarpMessenger.sendWarpMessage.selector), + abi.encode(bytes32(0)) ); - - vm.warp(1000); vm.expectEmit(true, true, true, true, address(app)); - emit ValidationPeriodRegistered(validationID, 1e6, 1000); - - app.completeValidatorRegistration(0); + emit ValidatorRemovalInitialized( + validationID, bytes32(0), 1e6, 2000 , 0 + ); + + app.initializeEndValidation(validationID, false, 0); } - function testInitializeEndValidation() public { + function testInitializeEndValidationWithUptimeProof() public { // TODO: implement } - function testInitializeEndValidationWithUptimeProof() public { + function testInitializeEndValidationExcessiveChurn() public { // TODO: implement } @@ -164,5 +170,39 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { ); } - function _setUpCompleteValidatorRegistration() internal {} + function _setUpCompleteValidatorRegistration( + bytes32 nodeID, + bytes32 subnetID, + uint64 weight, + uint64 registrationExpiry, + bytes memory signature, + uint64 registrationTimestamp + ) internal returns (bytes32 validationID) { + validationID = _setUpInitializeValidatorRegistration( + nodeID, subnetID, weight, registrationExpiry, signature + ); + bytes memory subnetValidatorRegistrationMessage = + StakingMessages.packSubnetValidatorRegistrationMessage(validationID, true); + vm.mockCall( + WARP_PRECOMPILE_ADDRESS, + abi.encodeWithSelector(IWarpMessenger.getVerifiedWarpMessage.selector, uint32(0)), + abi.encode( + WarpMessage({ + sourceChainID: P_CHAIN_BLOCKCHAIN_ID, + originSenderAddress: address(0), + payload: subnetValidatorRegistrationMessage + }), + true + ) + ); + vm.expectCall( + WARP_PRECOMPILE_ADDRESS, abi.encodeCall(IWarpMessenger.getVerifiedWarpMessage, 0) + ); + + vm.warp(registrationTimestamp); + vm.expectEmit(true, true, true, true, address(app)); + emit ValidationPeriodRegistered(validationID, weight, registrationTimestamp); + + app.completeValidatorRegistration(0); + } } From 6ea330ff616145ede87a4379d8fdb8eb8f20fb50 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Thu, 1 Aug 2024 15:06:19 -0400 Subject: [PATCH 16/27] resent init vdr end test --- .../NativeTokenStakingManagerTests.t.sol | 81 ++++++++++++++----- 1 file changed, 60 insertions(+), 21 deletions(-) diff --git a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol index 8669c2894..f6b60787c 100644 --- a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -87,27 +87,15 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { } function testInitializeEndValidation() public { - bytes32 validationID = _setUpCompleteValidatorRegistration({ - nodeID: DEFAULT_NODE_ID, - subnetID: DEFAULT_SUBNET_ID, - weight: 1e6, - registrationExpiry: DEFAULT_EXPIRY, - signature: DEFAULT_ED25519_SIGNATURE, - registrationTimestamp: 1000 + _setUpInitializeEndValidation({ + nodeID: DEFAULT_NODE_ID, + subnetID: DEFAULT_SUBNET_ID, + weight: 1e6, + registrationExpiry: DEFAULT_EXPIRY, + signature: DEFAULT_ED25519_SIGNATURE, + registrationTimestamp: 1000, + completionTimestamp: 2000 }); - - vm.warp(2000); - vm.mockCall( - WARP_PRECOMPILE_ADDRESS, - abi.encode(IWarpMessenger.sendWarpMessage.selector), - abi.encode(bytes32(0)) - ); - vm.expectEmit(true, true, true, true, address(app)); - emit ValidatorRemovalInitialized( - validationID, bytes32(0), 1e6, 2000 , 0 - ); - - app.initializeEndValidation(validationID, false, 0); } function testInitializeEndValidationWithUptimeProof() public { @@ -119,7 +107,26 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { } function testResendEndValidation() public { - // TODO: implement + bytes32 validationID = _setUpInitializeEndValidation({ + nodeID: DEFAULT_NODE_ID, + subnetID: DEFAULT_SUBNET_ID, + weight: 1e6, + registrationExpiry: DEFAULT_EXPIRY, + signature: DEFAULT_ED25519_SIGNATURE, + registrationTimestamp: 1000, + completionTimestamp: 2000 + }); + vm.mockCall( + WARP_PRECOMPILE_ADDRESS, + abi.encode(IWarpMessenger.sendWarpMessage.selector), + abi.encode(bytes32(0)) + ); + // TODO: construct the expected message in the same way as the contract + // vm.expectCall( + // WARP_PRECOMPILE_ADDRESS, + // abi.encodeCall(IWarpMessenger.sendWarpMessage, (abi.encode(expectedMessage))) + // ); + app.resendEndValidatorMessage(validationID); } function testCompleteEndValidation() public { @@ -205,4 +212,36 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { app.completeValidatorRegistration(0); } + + function _setUpInitializeEndValidation( + bytes32 nodeID, + bytes32 subnetID, + uint64 weight, + uint64 registrationExpiry, + bytes memory signature, + uint64 registrationTimestamp, + uint64 completionTimestamp + ) internal returns (bytes32 validationID) { + validationID = _setUpCompleteValidatorRegistration({ + nodeID: nodeID, + subnetID: subnetID, + weight: weight, + registrationExpiry: registrationExpiry, + signature: signature, + registrationTimestamp: registrationTimestamp + }); + + vm.warp(completionTimestamp); + vm.mockCall( + WARP_PRECOMPILE_ADDRESS, + abi.encode(IWarpMessenger.sendWarpMessage.selector), + abi.encode(bytes32(0)) + ); + vm.expectEmit(true, true, true, true, address(app)); + emit ValidatorRemovalInitialized( + validationID, bytes32(0), weight, completionTimestamp , 0 + ); + + app.initializeEndValidation(validationID, false, 0); + } } From e728e2ff4a9b6e42d286f169a79fa780a5217a0a Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Thu, 1 Aug 2024 15:49:01 -0400 Subject: [PATCH 17/27] emit validation period ended --- contracts/staking/StakingManager.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/staking/StakingManager.sol b/contracts/staking/StakingManager.sol index 17b3e0395..3a2d71435 100644 --- a/contracts/staking/StakingManager.sol +++ b/contracts/staking/StakingManager.sol @@ -413,6 +413,7 @@ abstract contract StakingManager is Context, ReentrancyGuard, IStakingManager { // Calculate the reward for the validator. // Emit event. + emit ValidationPeriodEnded(validationID); } /** From 5343d39c097092cffed45d743f43d2498ed924f6 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Thu, 1 Aug 2024 15:49:13 -0400 Subject: [PATCH 18/27] complete validation test --- .../NativeTokenStakingManagerTests.t.sol | 66 ++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol index f6b60787c..022e38682 100644 --- a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -130,11 +130,73 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { } function testCompleteEndValidation() public { - // TODO: implement + bytes32 validationID = _setUpInitializeEndValidation({ + nodeID: DEFAULT_NODE_ID, + subnetID: DEFAULT_SUBNET_ID, + weight: 1e6, + registrationExpiry: DEFAULT_EXPIRY, + signature: DEFAULT_ED25519_SIGNATURE, + registrationTimestamp: 1000, + completionTimestamp: 2000 + }); + + bytes memory subnetValidatorRegistrationMessage = + StakingMessages.packSubnetValidatorRegistrationMessage(validationID, false); + vm.mockCall( + WARP_PRECOMPILE_ADDRESS, + abi.encodeWithSelector(IWarpMessenger.getVerifiedWarpMessage.selector, uint32(0)), + abi.encode( + WarpMessage({ + sourceChainID: P_CHAIN_BLOCKCHAIN_ID, + originSenderAddress: address(0), + payload: subnetValidatorRegistrationMessage + }), + true + ) + ); + vm.expectCall( + WARP_PRECOMPILE_ADDRESS, abi.encodeCall(IWarpMessenger.getVerifiedWarpMessage, 0) + ); + + vm.expectEmit(true, true, true, true, address(app)); + emit ValidationPeriodEnded(validationID); + + app.completeEndValidation(0, false); } function testCompleteEndValidationSetWeightMessageType() public { - // TODO: implement + bytes32 validationID = _setUpInitializeEndValidation({ + nodeID: DEFAULT_NODE_ID, + subnetID: DEFAULT_SUBNET_ID, + weight: 1e6, + registrationExpiry: DEFAULT_EXPIRY, + signature: DEFAULT_ED25519_SIGNATURE, + registrationTimestamp: 1000, + completionTimestamp: 2000 + }); + + bytes memory setSubnetValidatorWeightMessage = + StakingMessages.packSetSubnetValidatorWeightMessage(validationID, 1, 0); + vm.mockCall( + WARP_PRECOMPILE_ADDRESS, + abi.encodeWithSelector(IWarpMessenger.getVerifiedWarpMessage.selector, uint32(0)), + abi.encode( + WarpMessage({ + sourceChainID: P_CHAIN_BLOCKCHAIN_ID, + originSenderAddress: address(0), + payload: setSubnetValidatorWeightMessage + }), + true + ) + ); + vm.expectCall( + WARP_PRECOMPILE_ADDRESS, abi.encodeCall(IWarpMessenger.getVerifiedWarpMessage, 0) + ); + + vm.expectEmit(true, true, true, true, address(app)); + emit ValidationPeriodEnded(validationID); + + app.completeEndValidation(0, true); } // Helpers From 5df9ae389c1d66f0360c2f40a954250fb527f274 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Thu, 1 Aug 2024 15:50:08 -0400 Subject: [PATCH 19/27] format --- .../NativeTokenStakingManagerTests.t.sol | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol index 022e38682..0f5f4e0ad 100644 --- a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -77,11 +77,11 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { function testCompleteValidatorRegistration() public { _setUpCompleteValidatorRegistration({ - nodeID: DEFAULT_NODE_ID, - subnetID: DEFAULT_SUBNET_ID, - weight: 1e6, - registrationExpiry: DEFAULT_EXPIRY, - signature: DEFAULT_ED25519_SIGNATURE, + nodeID: DEFAULT_NODE_ID, + subnetID: DEFAULT_SUBNET_ID, + weight: 1e6, + registrationExpiry: DEFAULT_EXPIRY, + signature: DEFAULT_ED25519_SIGNATURE, registrationTimestamp: 1000 }); } @@ -107,7 +107,7 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { } function testResendEndValidation() public { - bytes32 validationID = _setUpInitializeEndValidation({ + bytes32 validationID = _setUpInitializeEndValidation({ nodeID: DEFAULT_NODE_ID, subnetID: DEFAULT_SUBNET_ID, weight: 1e6, @@ -285,11 +285,11 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { uint64 completionTimestamp ) internal returns (bytes32 validationID) { validationID = _setUpCompleteValidatorRegistration({ - nodeID: nodeID, - subnetID: subnetID, - weight: weight, - registrationExpiry: registrationExpiry, - signature: signature, + nodeID: nodeID, + subnetID: subnetID, + weight: weight, + registrationExpiry: registrationExpiry, + signature: signature, registrationTimestamp: registrationTimestamp }); @@ -300,10 +300,8 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { abi.encode(bytes32(0)) ); vm.expectEmit(true, true, true, true, address(app)); - emit ValidatorRemovalInitialized( - validationID, bytes32(0), weight, completionTimestamp , 0 - ); - + emit ValidatorRemovalInitialized(validationID, bytes32(0), weight, completionTimestamp, 0); + app.initializeEndValidation(validationID, false, 0); } } From 3480ed94f63e4f5c671daf204b10f093e68ab19b Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Thu, 1 Aug 2024 16:14:51 -0400 Subject: [PATCH 20/27] add expected warp msgs --- .../NativeTokenStakingManagerTests.t.sol | 52 +++++++++++++------ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol index 0f5f4e0ad..8f4369fc3 100644 --- a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -62,16 +62,25 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { bytes32 validationID = _setUpInitializeValidatorRegistration( DEFAULT_NODE_ID, DEFAULT_SUBNET_ID, 1e6, DEFAULT_EXPIRY, DEFAULT_ED25519_SIGNATURE ); + (, bytes memory registerSubnetValidatorMessage) = StakingMessages + .packRegisterSubnetValidatorMessage( + StakingMessages.ValidationInfo({ + subnetID: DEFAULT_SUBNET_ID, + nodeID: DEFAULT_NODE_ID, + weight: 1e6, + registrationExpiry: DEFAULT_EXPIRY, + signature: DEFAULT_ED25519_SIGNATURE + }) + ); vm.mockCall( WARP_PRECOMPILE_ADDRESS, abi.encode(IWarpMessenger.sendWarpMessage.selector), abi.encode(bytes32(0)) ); - // TODO: construct the expected message in the same way as the contract - // vm.expectCall( - // WARP_PRECOMPILE_ADDRESS, - // abi.encodeCall(IWarpMessenger.sendWarpMessage, (abi.encode(expectedMessage))) - // ); + vm.expectCall( + WARP_PRECOMPILE_ADDRESS, + abi.encodeCall(IWarpMessenger.sendWarpMessage, registerSubnetValidatorMessage) + ); app.resendRegisterValidatorMessage(validationID); } @@ -116,16 +125,18 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { registrationTimestamp: 1000, completionTimestamp: 2000 }); + bytes memory setValidatorWeightPayload = StakingMessages.packSetSubnetValidatorWeightMessage( + validationID, 0, 0 + ); vm.mockCall( WARP_PRECOMPILE_ADDRESS, abi.encode(IWarpMessenger.sendWarpMessage.selector), abi.encode(bytes32(0)) ); - // TODO: construct the expected message in the same way as the contract - // vm.expectCall( - // WARP_PRECOMPILE_ADDRESS, - // abi.encodeCall(IWarpMessenger.sendWarpMessage, (abi.encode(expectedMessage))) - // ); + vm.expectCall( + WARP_PRECOMPILE_ADDRESS, + abi.encodeCall(IWarpMessenger.sendWarpMessage, setValidatorWeightPayload) + ); app.resendEndValidatorMessage(validationID); } @@ -216,19 +227,26 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { signature: signature }) ); - + (, bytes memory registerSubnetValidatorMessage) = StakingMessages + .packRegisterSubnetValidatorMessage( + StakingMessages.ValidationInfo({ + subnetID: subnetID, + nodeID: nodeID, + weight: weight, + registrationExpiry: registrationExpiry, + signature: signature + }) + ); vm.warp(DEFAULT_EXPIRY - 1); - vm.mockCall( WARP_PRECOMPILE_ADDRESS, abi.encode(IWarpMessenger.sendWarpMessage.selector), abi.encode(bytes32(0)) ); - // TODO: construct the expected message in the same way as the contract - // vm.expectCall( - // WARP_PRECOMPILE_ADDRESS, - // abi.encodeCall(IWarpMessenger.sendWarpMessage, (abi.encode(expectedMessage))) - // ); + vm.expectCall( + WARP_PRECOMPILE_ADDRESS, + abi.encodeCall(IWarpMessenger.sendWarpMessage, registerSubnetValidatorMessage) + ); vm.expectEmit(true, true, true, true, address(app)); emit ValidationPeriodCreated( validationID, DEFAULT_NODE_ID, bytes32(0), weight, DEFAULT_EXPIRY From 0087c0790a02fb67293525044902ea4a36c47e25 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Thu, 1 Aug 2024 16:38:39 -0400 Subject: [PATCH 21/27] lint --- .../tests/NativeTokenStakingManagerTests.t.sol | 13 ++++++------- contracts/staking/tests/StakingManagerTests.t.sol | 2 -- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol index 8f4369fc3..cb25e2762 100644 --- a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -5,7 +5,6 @@ pragma solidity 0.8.25; -import {Test} from "@forge-std/Test.sol"; import {StakingManagerTest} from "./StakingManagerTests.t.sol"; import {NativeTokenStakingManager} from "../NativeTokenStakingManager.sol"; import {StakingManagerSettings, InitialStakerInfo} from "../interfaces/IStakingManager.sol"; @@ -13,6 +12,8 @@ import {IRewardCalculator} from "../interfaces/IRewardCalculator.sol"; import {IWarpMessenger, WarpMessage} from "../StakingManager.sol"; import {StakingMessages} from "../StakingMessages.sol"; +// TODO: Remove this once all unit tests implemented +// solhint-disable no-empty-blocks contract NativeTokenStakingManagerTest is StakingManagerTest { NativeTokenStakingManager public app; @@ -31,9 +32,6 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { }) ); stakingManager = app; - - // Setup the test - StakingManagerTest.setUp(); } function testInitializeValidatorRegistrationSuccess() public { @@ -125,9 +123,8 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { registrationTimestamp: 1000, completionTimestamp: 2000 }); - bytes memory setValidatorWeightPayload = StakingMessages.packSetSubnetValidatorWeightMessage( - validationID, 0, 0 - ); + bytes memory setValidatorWeightPayload = + StakingMessages.packSetSubnetValidatorWeightMessage(validationID, 0, 0); vm.mockCall( WARP_PRECOMPILE_ADDRESS, abi.encode(IWarpMessenger.sendWarpMessage.selector), @@ -323,3 +320,5 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { app.initializeEndValidation(validationID, false, 0); } } +// TODO: Remove this once all unit tests implemented +// solhint-enable no-empty-blocks diff --git a/contracts/staking/tests/StakingManagerTests.t.sol b/contracts/staking/tests/StakingManagerTests.t.sol index 33a21890c..71cf47210 100644 --- a/contracts/staking/tests/StakingManagerTests.t.sol +++ b/contracts/staking/tests/StakingManagerTests.t.sol @@ -45,8 +45,6 @@ abstract contract StakingManagerTest is Test { event ValidationPeriodEnded(bytes32 indexed validationID); - function setUp() public virtual {} - function testValueToWeight() public view { uint64 w1 = stakingManager.valueToWeight(1e12); uint64 w2 = stakingManager.valueToWeight(1e18); From 4a15a81154ea46cc46eaec2bb07797a5c5365892 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Thu, 1 Aug 2024 16:41:47 -0400 Subject: [PATCH 22/27] build fix --- contracts/staking/tests/NativeTokenStakingManagerTests.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol index cb25e2762..2692cc208 100644 --- a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -17,7 +17,7 @@ import {StakingMessages} from "../StakingMessages.sol"; contract NativeTokenStakingManagerTest is StakingManagerTest { NativeTokenStakingManager public app; - function setUp() public override { + function setUp() public virtual { // Construct the object under test app = new NativeTokenStakingManager( StakingManagerSettings({ From 050bbb031a214539b2b3146ee1e043e4db27b213 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Fri, 2 Aug 2024 13:34:44 -0400 Subject: [PATCH 23/27] default constants --- .../NativeTokenStakingManagerTests.t.sol | 42 +++++++++---------- .../staking/tests/StakingManagerTests.t.sol | 10 ++++- .../staking/tests/StakingMessagesTests.t.sol | 6 +-- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol index 2692cc208..4a44b8e53 100644 --- a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -23,10 +23,10 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { StakingManagerSettings({ pChainBlockchainID: P_CHAIN_BLOCKCHAIN_ID, subnetID: DEFAULT_SUBNET_ID, - minimumStakeAmount: 20, - maximumStakeAmount: 1e10, - minimumStakeDuration: 24 hours, - maximumHourlyChurn: 0, + minimumStakeAmount: DEFAULT_MINIMUM_STAKE, + maximumStakeAmount: DEFAULT_MAXIMUM_STAKE, + minimumStakeDuration: DEFAULT_MINIMUM_STAKE_DURATION, + maximumHourlyChurn: DEFAULT_MAXIMUM_HOURLY_CHURN, initialStakers: new InitialStakerInfo[](0), rewardCalculator: IRewardCalculator(address(0)) }) @@ -36,7 +36,7 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { function testInitializeValidatorRegistrationSuccess() public { _setUpInitializeValidatorRegistration( - DEFAULT_NODE_ID, DEFAULT_SUBNET_ID, 1e6, DEFAULT_EXPIRY, DEFAULT_ED25519_SIGNATURE + DEFAULT_NODE_ID, DEFAULT_SUBNET_ID, DEFAULT_WEIGHT, DEFAULT_EXPIRY, DEFAULT_ED25519_SIGNATURE ); } @@ -58,14 +58,14 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { // reference to the abstract type. function testResendRegisterValidatorMessage() public { bytes32 validationID = _setUpInitializeValidatorRegistration( - DEFAULT_NODE_ID, DEFAULT_SUBNET_ID, 1e6, DEFAULT_EXPIRY, DEFAULT_ED25519_SIGNATURE + DEFAULT_NODE_ID, DEFAULT_SUBNET_ID, DEFAULT_WEIGHT, DEFAULT_EXPIRY, DEFAULT_ED25519_SIGNATURE ); (, bytes memory registerSubnetValidatorMessage) = StakingMessages .packRegisterSubnetValidatorMessage( StakingMessages.ValidationInfo({ subnetID: DEFAULT_SUBNET_ID, nodeID: DEFAULT_NODE_ID, - weight: 1e6, + weight: DEFAULT_WEIGHT, registrationExpiry: DEFAULT_EXPIRY, signature: DEFAULT_ED25519_SIGNATURE }) @@ -86,10 +86,10 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { _setUpCompleteValidatorRegistration({ nodeID: DEFAULT_NODE_ID, subnetID: DEFAULT_SUBNET_ID, - weight: 1e6, + weight: DEFAULT_WEIGHT, registrationExpiry: DEFAULT_EXPIRY, signature: DEFAULT_ED25519_SIGNATURE, - registrationTimestamp: 1000 + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP }); } @@ -97,11 +97,11 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { _setUpInitializeEndValidation({ nodeID: DEFAULT_NODE_ID, subnetID: DEFAULT_SUBNET_ID, - weight: 1e6, + weight: DEFAULT_WEIGHT, registrationExpiry: DEFAULT_EXPIRY, signature: DEFAULT_ED25519_SIGNATURE, - registrationTimestamp: 1000, - completionTimestamp: 2000 + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP, + completionTimestamp: DEFAULT_COMPLETION_TIMESTAMP }); } @@ -117,11 +117,11 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { bytes32 validationID = _setUpInitializeEndValidation({ nodeID: DEFAULT_NODE_ID, subnetID: DEFAULT_SUBNET_ID, - weight: 1e6, + weight: DEFAULT_WEIGHT, registrationExpiry: DEFAULT_EXPIRY, signature: DEFAULT_ED25519_SIGNATURE, - registrationTimestamp: 1000, - completionTimestamp: 2000 + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP, + completionTimestamp: DEFAULT_COMPLETION_TIMESTAMP }); bytes memory setValidatorWeightPayload = StakingMessages.packSetSubnetValidatorWeightMessage(validationID, 0, 0); @@ -141,11 +141,11 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { bytes32 validationID = _setUpInitializeEndValidation({ nodeID: DEFAULT_NODE_ID, subnetID: DEFAULT_SUBNET_ID, - weight: 1e6, + weight: DEFAULT_WEIGHT, registrationExpiry: DEFAULT_EXPIRY, signature: DEFAULT_ED25519_SIGNATURE, - registrationTimestamp: 1000, - completionTimestamp: 2000 + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP, + completionTimestamp: DEFAULT_COMPLETION_TIMESTAMP }); bytes memory subnetValidatorRegistrationMessage = @@ -176,11 +176,11 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { bytes32 validationID = _setUpInitializeEndValidation({ nodeID: DEFAULT_NODE_ID, subnetID: DEFAULT_SUBNET_ID, - weight: 1e6, + weight: DEFAULT_WEIGHT, registrationExpiry: DEFAULT_EXPIRY, signature: DEFAULT_ED25519_SIGNATURE, - registrationTimestamp: 1000, - completionTimestamp: 2000 + registrationTimestamp: DEFAULT_REGISTRATION_TIMESTAMP, + completionTimestamp: DEFAULT_COMPLETION_TIMESTAMP }); bytes memory setSubnetValidatorWeightMessage = diff --git a/contracts/staking/tests/StakingManagerTests.t.sol b/contracts/staking/tests/StakingManagerTests.t.sol index 71cf47210..910f63561 100644 --- a/contracts/staking/tests/StakingManagerTests.t.sol +++ b/contracts/staking/tests/StakingManagerTests.t.sol @@ -15,12 +15,20 @@ abstract contract StakingManagerTest is Test { bytes32(hex"1234567812345678123456781234567812345678123456781234567812345678"); bytes32 public constant DEFAULT_NODE_ID = bytes32(hex"1234567812345678123456781234567812345678123456781234567812345678"); - uint64 public constant DEFAULT_EXPIRY = 1000; bytes public constant DEFAULT_ED25519_SIGNATURE = bytes( hex"12345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678" ); address public constant WARP_PRECOMPILE_ADDRESS = 0x0200000000000000000000000000000000000005; + uint64 public constant DEFAULT_WEIGHT = 1e6; + uint256 public constant DEFAULT_MINIMUM_STAKE = 20; + uint256 public constant DEFAULT_MAXIMUM_STAKE = 1e10; + uint64 public constant DEFAULT_MINIMUM_STAKE_DURATION = 24 hours; + uint8 public constant DEFAULT_MAXIMUM_HOURLY_CHURN = 0; + uint64 public constant DEFAULT_EXPIRY = 1000; + uint64 public constant DEFAULT_REGISTRATION_TIMESTAMP = 1000; + uint64 public constant DEFAULT_COMPLETION_TIMESTAMP = 2000; + StakingManager public stakingManager; event ValidationPeriodCreated( diff --git a/contracts/staking/tests/StakingMessagesTests.t.sol b/contracts/staking/tests/StakingMessagesTests.t.sol index e41e38692..3ecf2deec 100644 --- a/contracts/staking/tests/StakingMessagesTests.t.sol +++ b/contracts/staking/tests/StakingMessagesTests.t.sol @@ -12,14 +12,14 @@ contract StakingMessagesTest is Test { bytes32 public constant DEFAULT_SUBNET_ID = bytes32(hex"1234567812345678123456781234567812345678123456781234567812345678"); bytes32 public constant DEFAULT_NODE_ID = - bytes32(hex"1234567812345678123456781234567812345678123456781234567812345678"); - uint64 public constant DEFAULT_EXPIRY = 1000; + bytes32(hex"1234567812345678123456781234567812345678123456781234567812345678"); bytes public constant DEFAULT_ED25519_SIGNATURE = bytes( hex"12345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678" ); - uint64 public constant DEFAULT_WEIGHT = 1e6; bytes32 public constant DEFAULT_VALIDATION_ID = bytes32(hex"1234567812345678123456781234567812345678123456781234567812345678"); + uint64 public constant DEFAULT_WEIGHT = 1e6; + uint64 public constant DEFAULT_EXPIRY = 1000; function testRegisterSubnetValidatorMessage() public pure { (bytes32 validationID, bytes memory packed) = StakingMessages From 5b59a1fb207b11d5915a132394e2e84e8ff8bec9 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Fri, 2 Aug 2024 13:49:54 -0400 Subject: [PATCH 24/27] warp precompile mock helpers --- .../NativeTokenStakingManagerTests.t.sol | 102 ++++++------------ 1 file changed, 34 insertions(+), 68 deletions(-) diff --git a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol index 4a44b8e53..a60fff4da 100644 --- a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -70,15 +70,7 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { signature: DEFAULT_ED25519_SIGNATURE }) ); - vm.mockCall( - WARP_PRECOMPILE_ADDRESS, - abi.encode(IWarpMessenger.sendWarpMessage.selector), - abi.encode(bytes32(0)) - ); - vm.expectCall( - WARP_PRECOMPILE_ADDRESS, - abi.encodeCall(IWarpMessenger.sendWarpMessage, registerSubnetValidatorMessage) - ); + _mockSendWarpMessage(registerSubnetValidatorMessage, bytes32(0)); app.resendRegisterValidatorMessage(validationID); } @@ -125,15 +117,7 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { }); bytes memory setValidatorWeightPayload = StakingMessages.packSetSubnetValidatorWeightMessage(validationID, 0, 0); - vm.mockCall( - WARP_PRECOMPILE_ADDRESS, - abi.encode(IWarpMessenger.sendWarpMessage.selector), - abi.encode(bytes32(0)) - ); - vm.expectCall( - WARP_PRECOMPILE_ADDRESS, - abi.encodeCall(IWarpMessenger.sendWarpMessage, setValidatorWeightPayload) - ); + _mockSendWarpMessage(setValidatorWeightPayload, bytes32(0)); app.resendEndValidatorMessage(validationID); } @@ -150,21 +134,8 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { bytes memory subnetValidatorRegistrationMessage = StakingMessages.packSubnetValidatorRegistrationMessage(validationID, false); - vm.mockCall( - WARP_PRECOMPILE_ADDRESS, - abi.encodeWithSelector(IWarpMessenger.getVerifiedWarpMessage.selector, uint32(0)), - abi.encode( - WarpMessage({ - sourceChainID: P_CHAIN_BLOCKCHAIN_ID, - originSenderAddress: address(0), - payload: subnetValidatorRegistrationMessage - }), - true - ) - ); - vm.expectCall( - WARP_PRECOMPILE_ADDRESS, abi.encodeCall(IWarpMessenger.getVerifiedWarpMessage, 0) - ); + + _mockGetVerifiedWarpMessage(subnetValidatorRegistrationMessage, true); vm.expectEmit(true, true, true, true, address(app)); emit ValidationPeriodEnded(validationID); @@ -185,6 +156,17 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { bytes memory setSubnetValidatorWeightMessage = StakingMessages.packSetSubnetValidatorWeightMessage(validationID, 1, 0); + + _mockGetVerifiedWarpMessage(setSubnetValidatorWeightMessage, true); + + vm.expectEmit(true, true, true, true, address(app)); + emit ValidationPeriodEnded(validationID); + + app.completeEndValidation(0, true); + } + + // Helpers + function _mockGetVerifiedWarpMessage(bytes memory expectedPayload, bool valid) internal { vm.mockCall( WARP_PRECOMPILE_ADDRESS, abi.encodeWithSelector(IWarpMessenger.getVerifiedWarpMessage.selector, uint32(0)), @@ -192,22 +174,28 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { WarpMessage({ sourceChainID: P_CHAIN_BLOCKCHAIN_ID, originSenderAddress: address(0), - payload: setSubnetValidatorWeightMessage + payload: expectedPayload }), - true + valid ) ); vm.expectCall( WARP_PRECOMPILE_ADDRESS, abi.encodeCall(IWarpMessenger.getVerifiedWarpMessage, 0) ); + } - vm.expectEmit(true, true, true, true, address(app)); - emit ValidationPeriodEnded(validationID); - - app.completeEndValidation(0, true); + function _mockSendWarpMessage(bytes memory payload, bytes32 expectedMessageID) internal { + vm.mockCall( + WARP_PRECOMPILE_ADDRESS, + abi.encode(IWarpMessenger.sendWarpMessage.selector), + abi.encode(expectedMessageID) + ); + vm.expectCall( + WARP_PRECOMPILE_ADDRESS, + abi.encodeCall(IWarpMessenger.sendWarpMessage, payload) + ); } - // Helpers function _setUpInitializeValidatorRegistration( bytes32 nodeID, bytes32 subnetID, @@ -235,15 +223,7 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { }) ); vm.warp(DEFAULT_EXPIRY - 1); - vm.mockCall( - WARP_PRECOMPILE_ADDRESS, - abi.encode(IWarpMessenger.sendWarpMessage.selector), - abi.encode(bytes32(0)) - ); - vm.expectCall( - WARP_PRECOMPILE_ADDRESS, - abi.encodeCall(IWarpMessenger.sendWarpMessage, registerSubnetValidatorMessage) - ); + _mockSendWarpMessage(registerSubnetValidatorMessage, bytes32(0)); vm.expectEmit(true, true, true, true, address(app)); emit ValidationPeriodCreated( validationID, DEFAULT_NODE_ID, bytes32(0), weight, DEFAULT_EXPIRY @@ -267,21 +247,8 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { ); bytes memory subnetValidatorRegistrationMessage = StakingMessages.packSubnetValidatorRegistrationMessage(validationID, true); - vm.mockCall( - WARP_PRECOMPILE_ADDRESS, - abi.encodeWithSelector(IWarpMessenger.getVerifiedWarpMessage.selector, uint32(0)), - abi.encode( - WarpMessage({ - sourceChainID: P_CHAIN_BLOCKCHAIN_ID, - originSenderAddress: address(0), - payload: subnetValidatorRegistrationMessage - }), - true - ) - ); - vm.expectCall( - WARP_PRECOMPILE_ADDRESS, abi.encodeCall(IWarpMessenger.getVerifiedWarpMessage, 0) - ); + + _mockGetVerifiedWarpMessage(subnetValidatorRegistrationMessage, true); vm.warp(registrationTimestamp); vm.expectEmit(true, true, true, true, address(app)); @@ -309,11 +276,10 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { }); vm.warp(completionTimestamp); - vm.mockCall( - WARP_PRECOMPILE_ADDRESS, - abi.encode(IWarpMessenger.sendWarpMessage.selector), - abi.encode(bytes32(0)) + bytes memory setValidatorWeightPayload = StakingMessages.packSetSubnetValidatorWeightMessage( + validationID, 0, 0 ); + _mockSendWarpMessage(setValidatorWeightPayload, bytes32(0)); vm.expectEmit(true, true, true, true, address(app)); emit ValidatorRemovalInitialized(validationID, bytes32(0), weight, completionTimestamp, 0); From 85fb6abeca50d6aa571c912b74a9988f293d728d Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Fri, 2 Aug 2024 13:54:16 -0400 Subject: [PATCH 25/27] format --- .../NativeTokenStakingManagerTests.t.sol | 24 ++++++++++++------- .../staking/tests/StakingMessagesTests.t.sol | 2 +- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol index a60fff4da..a892ae1a3 100644 --- a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -36,7 +36,11 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { function testInitializeValidatorRegistrationSuccess() public { _setUpInitializeValidatorRegistration( - DEFAULT_NODE_ID, DEFAULT_SUBNET_ID, DEFAULT_WEIGHT, DEFAULT_EXPIRY, DEFAULT_ED25519_SIGNATURE + DEFAULT_NODE_ID, + DEFAULT_SUBNET_ID, + DEFAULT_WEIGHT, + DEFAULT_EXPIRY, + DEFAULT_ED25519_SIGNATURE ); } @@ -58,7 +62,11 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { // reference to the abstract type. function testResendRegisterValidatorMessage() public { bytes32 validationID = _setUpInitializeValidatorRegistration( - DEFAULT_NODE_ID, DEFAULT_SUBNET_ID, DEFAULT_WEIGHT, DEFAULT_EXPIRY, DEFAULT_ED25519_SIGNATURE + DEFAULT_NODE_ID, + DEFAULT_SUBNET_ID, + DEFAULT_WEIGHT, + DEFAULT_EXPIRY, + DEFAULT_ED25519_SIGNATURE ); (, bytes memory registerSubnetValidatorMessage) = StakingMessages .packRegisterSubnetValidatorMessage( @@ -134,7 +142,7 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { bytes memory subnetValidatorRegistrationMessage = StakingMessages.packSubnetValidatorRegistrationMessage(validationID, false); - + _mockGetVerifiedWarpMessage(subnetValidatorRegistrationMessage, true); vm.expectEmit(true, true, true, true, address(app)); @@ -191,8 +199,7 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { abi.encode(expectedMessageID) ); vm.expectCall( - WARP_PRECOMPILE_ADDRESS, - abi.encodeCall(IWarpMessenger.sendWarpMessage, payload) + WARP_PRECOMPILE_ADDRESS, abi.encodeCall(IWarpMessenger.sendWarpMessage, payload) ); } @@ -247,7 +254,7 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { ); bytes memory subnetValidatorRegistrationMessage = StakingMessages.packSubnetValidatorRegistrationMessage(validationID, true); - + _mockGetVerifiedWarpMessage(subnetValidatorRegistrationMessage, true); vm.warp(registrationTimestamp); @@ -276,9 +283,8 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { }); vm.warp(completionTimestamp); - bytes memory setValidatorWeightPayload = StakingMessages.packSetSubnetValidatorWeightMessage( - validationID, 0, 0 - ); + bytes memory setValidatorWeightPayload = + StakingMessages.packSetSubnetValidatorWeightMessage(validationID, 0, 0); _mockSendWarpMessage(setValidatorWeightPayload, bytes32(0)); vm.expectEmit(true, true, true, true, address(app)); emit ValidatorRemovalInitialized(validationID, bytes32(0), weight, completionTimestamp, 0); diff --git a/contracts/staking/tests/StakingMessagesTests.t.sol b/contracts/staking/tests/StakingMessagesTests.t.sol index 3ecf2deec..4b3b44dd9 100644 --- a/contracts/staking/tests/StakingMessagesTests.t.sol +++ b/contracts/staking/tests/StakingMessagesTests.t.sol @@ -12,7 +12,7 @@ contract StakingMessagesTest is Test { bytes32 public constant DEFAULT_SUBNET_ID = bytes32(hex"1234567812345678123456781234567812345678123456781234567812345678"); bytes32 public constant DEFAULT_NODE_ID = - bytes32(hex"1234567812345678123456781234567812345678123456781234567812345678"); + bytes32(hex"1234567812345678123456781234567812345678123456781234567812345678"); bytes public constant DEFAULT_ED25519_SIGNATURE = bytes( hex"12345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678123456781234567812345678" ); From 361ce6010f4ce3d85f8951ca26122df21c2a5a61 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Mon, 5 Aug 2024 09:42:22 -0500 Subject: [PATCH 26/27] icm initializable --- .../staking/tests/NativeTokenStakingManagerTests.t.sol | 9 +++++---- contracts/utilities/ICMInitializable.sol | 10 ++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 contracts/utilities/ICMInitializable.sol diff --git a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol index a892ae1a3..0a76c5572 100644 --- a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -11,6 +11,8 @@ import {StakingManagerSettings, InitialStakerInfo} from "../interfaces/IStakingM import {IRewardCalculator} from "../interfaces/IRewardCalculator.sol"; import {IWarpMessenger, WarpMessage} from "../StakingManager.sol"; import {StakingMessages} from "../StakingMessages.sol"; +import {ICMInitializable} from "../../utilities/ICMInitializable.sol"; + // TODO: Remove this once all unit tests implemented // solhint-disable no-empty-blocks @@ -19,8 +21,8 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { function setUp() public virtual { // Construct the object under test - app = new NativeTokenStakingManager( - StakingManagerSettings({ + app = new NativeTokenStakingManager(ICMInitializable.Allowed); + app.initialize(StakingManagerSettings({ pChainBlockchainID: P_CHAIN_BLOCKCHAIN_ID, subnetID: DEFAULT_SUBNET_ID, minimumStakeAmount: DEFAULT_MINIMUM_STAKE, @@ -29,8 +31,7 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { maximumHourlyChurn: DEFAULT_MAXIMUM_HOURLY_CHURN, initialStakers: new InitialStakerInfo[](0), rewardCalculator: IRewardCalculator(address(0)) - }) - ); + })); stakingManager = app; } diff --git a/contracts/utilities/ICMInitializable.sol b/contracts/utilities/ICMInitializable.sol new file mode 100644 index 000000000..9e9c1ae88 --- /dev/null +++ b/contracts/utilities/ICMInitializable.sol @@ -0,0 +1,10 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem +pragma solidity 0.8.25; + +enum ICMInitializable { + Allowed, + Disallowed +} From 9735935fef1b5c48f349f545b3203325540eca10 Mon Sep 17 00:00:00 2001 From: cam-schultz Date: Mon, 5 Aug 2024 09:42:57 -0500 Subject: [PATCH 27/27] format --- .../staking/tests/NativeTokenStakingManagerTests.t.sol | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol index 0a76c5572..b58b4f918 100644 --- a/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol +++ b/contracts/staking/tests/NativeTokenStakingManagerTests.t.sol @@ -13,7 +13,6 @@ import {IWarpMessenger, WarpMessage} from "../StakingManager.sol"; import {StakingMessages} from "../StakingMessages.sol"; import {ICMInitializable} from "../../utilities/ICMInitializable.sol"; - // TODO: Remove this once all unit tests implemented // solhint-disable no-empty-blocks contract NativeTokenStakingManagerTest is StakingManagerTest { @@ -22,7 +21,8 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { function setUp() public virtual { // Construct the object under test app = new NativeTokenStakingManager(ICMInitializable.Allowed); - app.initialize(StakingManagerSettings({ + app.initialize( + StakingManagerSettings({ pChainBlockchainID: P_CHAIN_BLOCKCHAIN_ID, subnetID: DEFAULT_SUBNET_ID, minimumStakeAmount: DEFAULT_MINIMUM_STAKE, @@ -31,7 +31,8 @@ contract NativeTokenStakingManagerTest is StakingManagerTest { maximumHourlyChurn: DEFAULT_MAXIMUM_HOURLY_CHURN, initialStakers: new InitialStakerInfo[](0), rewardCalculator: IRewardCalculator(address(0)) - })); + }) + ); stakingManager = app; }