Skip to content

Commit d8da2ad

Browse files
committed
Merge branch 'main' into use-official-foundry
2 parents 04d6f44 + 8a8f78d commit d8da2ad

File tree

10 files changed

+111
-19
lines changed

10 files changed

+111
-19
lines changed

abi-bindings/go/validator-manager/ERC20TokenStakingManager/ERC20TokenStakingManager.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

abi-bindings/go/validator-manager/NativeTokenStakingManager/NativeTokenStakingManager.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

abi-bindings/go/validator-manager/ValidatorManager/ValidatorManager.go

Lines changed: 23 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Migrating From V1 Validator Manager Contracts
2+
3+
The V1 Validator Manager contracts are implemented as a single deployed contract consisting of multiple contracts related through inheritance. The V2 Validator Manager, on the other hand, may be consist of multiple deployed contracts that interact via external function calls.
4+
5+
## Migrating Proof-of-Authority
6+
7+
In the V2 contracts, Proof-of-Authority validator management is implemented fully in `ValidatorManager`, so there is no need to deploy a separate contract (contrast with the Proof-of-Stake case, which requires a standalone `StakingManager` deployment). Additionally, both the V1 `PoAValidatorManager` and the V2 `ValidatorManager` are `Ownable`, meaning that the V1 `PoAValidatorManager` owner will persist after upgrading to a V2 `ValidatorManager`. Migrating from a V1 to V2 therefore only requires migrating the state variables that track validators. The helper method `migrateFromV1` is provided for this purpose. The general steps are as follows:
8+
9+
1. Upgrade the proxy contract's implementation to a newly deployed V2 `ValidatorManager` using standard methods
10+
2. For each validator (active or expired), call `migrateFromV1` with its `validationID`. The `receivedNonce` argument can be set to 0, since V1 `PoAValidatorManager`s do not support weight changes.
11+
12+
Some notes on this process:
13+
- `migrateFromV1` may only be called once per `validationID`. Any active validators will not be able to be removed until they are migrated.
14+
- It is up to the contract owner to track all of the `validationID`s to be migrated. This is because Solidity mappings are not iterable, so there is no getter to retreive all `validationID`s as a batch.
15+
16+
## Migrating Proof-of-Stake
17+
18+
**Migrating from a V1 `PoSValidatorManager` deployment to a V2 Proof-of-Stake Validator Manager is not supported.**
19+
20+
V2 Proof-of-Stake Validator Managers consist of two deployed contracts: an instance of a concrete implementation of `StakingManager`, and an instance of a `ValidatorManager`. Because `StakingManager` is a standalone contract that does not share state with `ValidatorManager`, migrating from a V1 `PoSValidatorManager` to a V2 `StakingManager` would require replicating state from one contract to another.

contracts/validator-manager/ValidatorManager.sol

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,17 @@ struct ValidatorManagerSettings {
4848
uint8 maximumChurnPercentage;
4949
}
5050

51+
/// @dev Legacy struct used to migrate from V1 contracts
52+
struct ValidatorLegacy {
53+
ValidatorStatus status;
54+
bytes nodeID;
55+
uint64 startingWeight;
56+
uint64 messageNonce;
57+
uint64 weight;
58+
uint64 startedAt;
59+
uint64 endedAt;
60+
}
61+
5162
/**
5263
* @dev Implementation of the {ACP99Manager} abstract contract.
5364
*
@@ -67,12 +78,14 @@ contract ValidatorManager is Initializable, OwnableUpgradeable, ACP99Manager {
6778
ValidatorChurnPeriod _churnTracker;
6879
/// @notice Maps the validationID to the registration message such that the message can be re-sent if needed.
6980
mapping(bytes32 => bytes) _pendingRegisterValidationMessages;
70-
/// @notice Maps the validationID to the validator information.
71-
mapping(bytes32 => Validator) _validationPeriods;
81+
/// @notice Legacy storage for V1 validators.
82+
mapping(bytes32 => ValidatorLegacy) _validationPeriodsLegacy;
7283
/// @notice Maps the nodeID to the validationID for validation periods that have not ended.
7384
mapping(bytes => bytes32) _registeredValidators;
7485
/// @notice Boolean that indicates if the initial validator set has been set.
7586
bool _initializedValidatorSet;
87+
/// @notice Maps the validationID to the validator information.
88+
mapping(bytes32 => Validator) _validationPeriods;
7689
}
7790
// solhint-enable private-vars-leading-underscore
7891

@@ -140,6 +153,36 @@ contract ValidatorManager is Initializable, OwnableUpgradeable, ACP99Manager {
140153
}
141154
}
142155

156+
/**
157+
* @notice Migrates a validator from the V1 contract to the V2 contract.
158+
* @param validationID The ID of the validation period to migrate.
159+
* @param receivedNonce The latest nonce received from the P-Chain.
160+
*/
161+
function migrateFromV1(bytes32 validationID, uint32 receivedNonce) external {
162+
ValidatorManagerStorage storage $ = _getValidatorManagerStorage();
163+
ValidatorLegacy storage legacy = $._validationPeriodsLegacy[validationID];
164+
if (legacy.status == ValidatorStatus.Unknown) {
165+
revert InvalidValidationID(validationID);
166+
}
167+
if (receivedNonce > legacy.messageNonce) {
168+
revert InvalidNonce(receivedNonce);
169+
}
170+
171+
$._validationPeriods[validationID] = Validator({
172+
status: legacy.status,
173+
nodeID: legacy.nodeID,
174+
startingWeight: legacy.startingWeight,
175+
sentNonce: legacy.messageNonce,
176+
receivedNonce: receivedNonce,
177+
weight: legacy.weight,
178+
startTime: legacy.startedAt,
179+
endTime: legacy.endedAt
180+
});
181+
182+
// Set the legacy status to unknown to disallow future migrations.
183+
$._validationPeriodsLegacy[validationID].status = ValidatorStatus.Unknown;
184+
}
185+
143186
function initialize(
144187
ValidatorManagerSettings calldata settings
145188
) external initializer {

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ module github.com/ava-labs/icm-contracts
33
go 1.23.6
44

55
require (
6-
github.com/ava-labs/avalanchego v1.12.2
6+
github.com/ava-labs/avalanchego v1.12.3-0.20250302035717-8bd7a2c4cc81
77
github.com/supranational/blst v0.3.13 // indirect
88
)
99

1010
require (
11-
github.com/ava-labs/subnet-evm v0.7.1
11+
github.com/ava-labs/subnet-evm v0.7.2
1212
github.com/ethereum/go-ethereum v1.13.14
1313
github.com/onsi/ginkgo/v2 v2.23.0
1414
github.com/onsi/gomega v1.36.2
@@ -24,7 +24,7 @@ require (
2424
github.com/DataDog/zstd v1.5.2 // indirect
2525
github.com/NYTimes/gziphandler v1.1.1 // indirect
2626
github.com/VictoriaMetrics/fastcache v1.12.1 // indirect
27-
github.com/ava-labs/coreth v0.14.1-rc.1 // indirect
27+
github.com/ava-labs/coreth v0.14.1-rc.1.0.20250219185827-6a9db205a450 // indirect
2828
github.com/beorn7/perks v1.0.1 // indirect
2929
github.com/bits-and-blooms/bitset v1.10.0 // indirect
3030
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect

go.sum

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,12 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax
5858
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
5959
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
6060
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
61-
github.com/ava-labs/avalanchego v1.12.2 h1:vZroUgB5xMMczDQnw9etDD1XhZsejFlKky+ZZv8wOKc=
62-
github.com/ava-labs/avalanchego v1.12.2/go.mod h1:uEDLbAUPcGCfDWW680rVfysEofUe/jWte5qQk0j5hMs=
63-
github.com/ava-labs/coreth v0.14.1-rc.1 h1:U72XlRm/fKyASmjThsWzfO/ZRvu1kaONFaX+KdJNxIc=
64-
github.com/ava-labs/coreth v0.14.1-rc.1/go.mod h1:lxDSXLcrszMo0N/PVJzfZ//H+bRwXF/KQWtpEYgXZqM=
65-
github.com/ava-labs/subnet-evm v0.7.1 h1:wXau+6Aj24hqqlN3wY14OKB4GJobWFhM3MzqFhg3WeU=
66-
github.com/ava-labs/subnet-evm v0.7.1/go.mod h1:jpAX6cNfMuUyoeP2/l9Z0ojDy2K/XbZq5y+E0jPXy38=
61+
github.com/ava-labs/avalanchego v1.12.3-0.20250302035717-8bd7a2c4cc81 h1:ZEmNsuAIIICSu1aUCOk1/iSwDaz9d9AhmpcozQrSXcU=
62+
github.com/ava-labs/avalanchego v1.12.3-0.20250302035717-8bd7a2c4cc81/go.mod h1:DfZ1/FHFxr1XnpDMfbMmex8bKxAtIISCGASdMUNFXtY=
63+
github.com/ava-labs/coreth v0.14.1-rc.1.0.20250219185827-6a9db205a450 h1:xSoL6plkPrb2w21v4JRnQg3BIJSg2svBHXyil09RMAg=
64+
github.com/ava-labs/coreth v0.14.1-rc.1.0.20250219185827-6a9db205a450/go.mod h1:AEQcF8MWrKH0sS114wEZlkSfeGF5F66xTbQYqqimNLI=
65+
github.com/ava-labs/subnet-evm v0.7.2 h1:AxmXT9tmuxmUi+hDqtoS0OVi0zi8fPqPcoQ7yjZ6FZQ=
66+
github.com/ava-labs/subnet-evm v0.7.2/go.mod h1:4ZWBSj9JALAtaUOPrI1P78C6vBMUpK0iiD6zaA9K2VA=
6767
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
6868
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
6969
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=

scripts/versions.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ SUBNET_EVM_VERSION=${SUBNET_EVM_VERSION:-$(extract_commit "$(getDepVersion githu
4040

4141

4242
# Set golangci-lint version
43-
GOLANGCI_LINT_VERSION=${GOLANGCI_LINT_VERSION:-'v1.64'}
43+
GOLANGCI_LINT_VERSION=${GOLANGCI_LINT_VERSION:-'v1.64.5'}
4444

4545
# Extract the Solidity version from foundry.toml
4646
SOLIDITY_VERSION=$(awk -F"'" '/^solc_version/ {print $2}' $ICM_CONTRACTS_PATH/foundry.toml)

tests/network/network.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,10 @@ func (n *LocalNetwork) GetL1Info(subnetID ids.ID) interfaces.L1TestInfo {
433433
if l1.SubnetID == subnetID {
434434
var nodeURIs []string
435435
for _, nodeID := range l1.ValidatorIDs {
436-
uri, err := n.Network.GetURIForNodeID(nodeID)
436+
node, err := n.Network.GetNode(nodeID)
437+
Expect(err).Should(BeNil())
438+
439+
uri, _, err := node.GetLocalURI(context.Background())
437440
Expect(err).Should(BeNil())
438441

439442
nodeURIs = append(nodeURIs, uri)
@@ -468,7 +471,10 @@ func (n *LocalNetwork) GetL1Infos() []interfaces.L1TestInfo {
468471
for i, l1 := range n.Network.Subnets {
469472
var nodeURIs []string
470473
for _, nodeID := range l1.ValidatorIDs {
471-
uri, err := n.Network.GetURIForNodeID(nodeID)
474+
node, err := n.Network.GetNode(nodeID)
475+
Expect(err).Should(BeNil())
476+
477+
uri, _, err := node.GetLocalURI(context.Background())
472478
Expect(err).Should(BeNil())
473479

474480
nodeURIs = append(nodeURIs, uri)

tests/utils/chain.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,9 @@ func SetupProposerVM(ctx context.Context, fundedKey *ecdsa.PrivateKey, network *
652652

653653
chainID := l1Details.Chains[0].ChainID
654654

655-
nodeURI, err := network.GetURIForNodeID(l1Details.ValidatorIDs[0])
655+
node, err := network.GetNode(l1Details.ValidatorIDs[0])
656+
Expect(err).Should(BeNil())
657+
nodeURI, _, err := node.GetLocalURI(context.Background())
656658
Expect(err).Should(BeNil())
657659
uri := HttpToWebsocketURI(nodeURI, chainID.String())
658660

0 commit comments

Comments
 (0)