From 1b2a5e38c6ab558545a94f7af41a9d2029af4f17 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 17 May 2024 13:09:43 +0200 Subject: [PATCH 01/10] new migrartion --- .../v2/storage/NodeOperatorFeesStorage.sol | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/contracts/v2/storage/NodeOperatorFeesStorage.sol b/contracts/v2/storage/NodeOperatorFeesStorage.sol index b42e10d0..1b8b122e 100644 --- a/contracts/v2/storage/NodeOperatorFeesStorage.sol +++ b/contracts/v2/storage/NodeOperatorFeesStorage.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.16; import {HubDependent} from "../../v1/abstract/HubDependent.sol"; +import {StakingStorage} from "../../v1/storage/StakingStorage.sol"; import {Named} from "../../v1/interface/Named.sol"; import {Versioned} from "../../v1/interface/Versioned.sol"; import {NodeOperatorErrors} from "../errors/NodeOperatorErrors.sol"; @@ -14,14 +15,15 @@ contract NodeOperatorFeesStorage is Named, Versioned, HubDependent { bool private _delayFreePeriodSet; uint256 public delayFreePeriodEnd; - uint256 public migrationPeriodEnd; + + address public oldNOFSAddress; // identityId => OperatorFee[] mapping(uint72 => NodeOperatorStructs.OperatorFee[]) public operatorFees; // solhint-disable-next-line no-empty-blocks - constructor(address hubAddress, uint256 migrationPeriodEnd_) HubDependent(hubAddress) { - migrationPeriodEnd = migrationPeriodEnd_; + constructor(address hubAddress, address _oldNOFSAddress) HubDependent(hubAddress) { + oldNOFSAddress = _oldNOFSAddress; } modifier onlyOnce() { @@ -30,11 +32,6 @@ contract NodeOperatorFeesStorage is Named, Versioned, HubDependent { _delayFreePeriodSet = true; } - modifier timeLimited() { - require(block.timestamp < migrationPeriodEnd, "Migration period has ended"); - _; - } - function name() external pure virtual override returns (string memory) { return _NAME; } @@ -43,12 +40,30 @@ contract NodeOperatorFeesStorage is Named, Versioned, HubDependent { return _VERSION; } - function migrateOldOperatorFees( - NodeOperatorStructs.OperatorFees[] memory legacyFees - ) external onlyHubOwner timeLimited { - for (uint i; i < legacyFees.length; ) { - operatorFees[legacyFees[i].identityId] = legacyFees[i].fees; - + function operatorFeeMigration(uint72[] calldata identityIds) external { + NodeOperatorFeesStorage oldNOFS = NodeOperatorFeesStorage(oldNOFSAddress); + StakingStorage ss = StakingStorage(hub.getContractAddress("StakingStorage")); + for (uint72 i; i < identityIds.length; ) { + NodeOperatorStructs.OperatorFee[] memory oldOperatorFees = oldNOFS.getOperatorFees(identityIds[i]); + // If there operator fee on oldNOFS that means it was migrated + if (oldOperatorFees.length != 0) { + operatorFees[identityIds[i]] = oldOperatorFees; + } + // oldOperatorFees.lenght == 0 + // This happens when node wasn't in sharding table or + // It was 0 on old contract it wasn't pushed to contract + // Could there be problem if we pushe it as 0, will this be problem in logic + else { + uint96 feePercentage96 = ss.operatorFees(identityIds[i]); + require(feePercentage96 <= type(uint8).max, "Fee percentage exceeds uint8 range"); + uint8 feePercentage = uint8(feePercentage96); + operatorFees[identityIds[i]].push( + NodeOperatorStructs.OperatorFee({ + feePercentage: feePercentage, + effectiveDate: uint248(block.timestamp) + }) + ); + } unchecked { i++; } From 9f1e1f4666a5e936ba1c38ecb03a6b61e4778b29 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 17 May 2024 13:57:55 +0200 Subject: [PATCH 02/10] Add ABIs --- abi/NodeOperatorFeesStorage.json | 64 ++++++------------- abi/Profile.json | 13 ++++ contracts/v1/Profile.sol | 6 +- .../v2/storage/NodeOperatorFeesStorage.sol | 8 +-- 4 files changed, 39 insertions(+), 52 deletions(-) diff --git a/abi/NodeOperatorFeesStorage.json b/abi/NodeOperatorFeesStorage.json index a5a47309..d9b4935a 100644 --- a/abi/NodeOperatorFeesStorage.json +++ b/abi/NodeOperatorFeesStorage.json @@ -7,9 +7,9 @@ "type": "address" }, { - "internalType": "uint256", - "name": "migrationPeriodEnd_", - "type": "uint256" + "internalType": "address", + "name": "_oldNOFSAddress", + "type": "address" } ], "stateMutability": "nonpayable", @@ -542,66 +542,42 @@ "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "name", + "outputs": [ { - "components": [ - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - }, - { - "components": [ - { - "internalType": "uint8", - "name": "feePercentage", - "type": "uint8" - }, - { - "internalType": "uint248", - "name": "effectiveDate", - "type": "uint248" - } - ], - "internalType": "struct NodeOperatorStructs.OperatorFee[]", - "name": "fees", - "type": "tuple[]" - } - ], - "internalType": "struct NodeOperatorStructs.OperatorFees[]", - "name": "legacyFees", - "type": "tuple[]" + "internalType": "string", + "name": "", + "type": "string" } ], - "name": "migrateOldOperatorFees", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "pure", "type": "function" }, { "inputs": [], - "name": "migrationPeriodEnd", + "name": "oldNOFSAddress", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "name", - "outputs": [ + "inputs": [ { - "internalType": "string", - "name": "", - "type": "string" + "internalType": "uint72[]", + "name": "identityIds", + "type": "uint72[]" } ], - "stateMutability": "pure", + "name": "operatorFeeMigration", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { diff --git a/abi/Profile.json b/abi/Profile.json index 5826a464..c206bd10 100644 --- a/abi/Profile.json +++ b/abi/Profile.json @@ -356,6 +356,19 @@ "stateMutability": "pure", "type": "function" }, + { + "inputs": [], + "name": "nodeOperatorFeesStorage", + "outputs": [ + { + "internalType": "contract NodeOperatorFeesStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "parametersStorage", diff --git a/contracts/v1/Profile.sol b/contracts/v1/Profile.sol index 1ecffd3f..15c59375 100644 --- a/contracts/v1/Profile.sol +++ b/contracts/v1/Profile.sol @@ -10,6 +10,7 @@ import {ParametersStorage} from "./storage/ParametersStorage.sol"; import {ProfileStorage} from "./storage/ProfileStorage.sol"; import {StakingStorage} from "./storage/StakingStorage.sol"; import {Staking} from "./Staking.sol"; +import {NodeOperatorFeesStorage} from "../v2/storage/NodeOperatorFeesStorage.sol"; import {WhitelistStorage} from "./storage/WhitelistStorage.sol"; import {ContractStatus} from "./abstract/ContractStatus.sol"; import {Initializable} from "./interface/Initializable.sol"; @@ -43,6 +44,7 @@ contract Profile is Named, Versioned, ContractStatus, Initializable { ParametersStorage public parametersStorage; ProfileStorage public profileStorage; WhitelistStorage public whitelistStorage; + NodeOperatorFeesStorage public nodeOperatorFeesStorage; // solhint-disable-next-line no-empty-blocks constructor(address hubAddress) ContractStatus(hubAddress) {} @@ -76,6 +78,7 @@ contract Profile is Named, Versioned, ContractStatus, Initializable { parametersStorage = ParametersStorage(hub.getContractAddress("ParametersStorage")); profileStorage = ProfileStorage(hub.getContractAddress("ProfileStorage")); whitelistStorage = WhitelistStorage(hub.getContractAddress("WhitelistStorage")); + nodeOperatorFeesStorage = NodeOperatorFeesStorage(hub.getContractAddress("NodeOperatorFeesStorage")); } function name() external pure virtual override returns (string memory) { @@ -96,6 +99,7 @@ contract Profile is Named, Versioned, ContractStatus, Initializable { ) external onlyWhitelisted { IdentityStorage ids = identityStorage; ProfileStorage ps = profileStorage; + NodeOperatorFeesStorage nofs = nodeOperatorFeesStorage; Identity id = identityContract; if (ids.getIdentityId(msg.sender) != 0) { @@ -136,7 +140,7 @@ contract Profile is Named, Versioned, ContractStatus, Initializable { ps.createProfile(identityId, nodeId, address(sharesContract)); _setAvailableNodeAddresses(identityId); - stakingStorage.setOperatorFee(identityId, initialOperatorFee); + nofs.addOperatorFee(identityId, initialOperatorFee, uint248(block.timestamp)); emit ProfileCreated(identityId, nodeId, adminWallet, address(sharesContract), initialOperatorFee); } diff --git a/contracts/v2/storage/NodeOperatorFeesStorage.sol b/contracts/v2/storage/NodeOperatorFeesStorage.sol index 1b8b122e..613db9ef 100644 --- a/contracts/v2/storage/NodeOperatorFeesStorage.sol +++ b/contracts/v2/storage/NodeOperatorFeesStorage.sol @@ -45,15 +45,9 @@ contract NodeOperatorFeesStorage is Named, Versioned, HubDependent { StakingStorage ss = StakingStorage(hub.getContractAddress("StakingStorage")); for (uint72 i; i < identityIds.length; ) { NodeOperatorStructs.OperatorFee[] memory oldOperatorFees = oldNOFS.getOperatorFees(identityIds[i]); - // If there operator fee on oldNOFS that means it was migrated if (oldOperatorFees.length != 0) { operatorFees[identityIds[i]] = oldOperatorFees; - } - // oldOperatorFees.lenght == 0 - // This happens when node wasn't in sharding table or - // It was 0 on old contract it wasn't pushed to contract - // Could there be problem if we pushe it as 0, will this be problem in logic - else { + } else { uint96 feePercentage96 = ss.operatorFees(identityIds[i]); require(feePercentage96 <= type(uint8).max, "Fee percentage exceeds uint8 range"); uint8 feePercentage = uint8(feePercentage96); From d54481ee9546bffcac3c9f19a4f2f6c62c56a0c4 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 17 May 2024 13:59:10 +0200 Subject: [PATCH 03/10] Change revert message --- contracts/v2/storage/NodeOperatorFeesStorage.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/v2/storage/NodeOperatorFeesStorage.sol b/contracts/v2/storage/NodeOperatorFeesStorage.sol index 613db9ef..c1752219 100644 --- a/contracts/v2/storage/NodeOperatorFeesStorage.sol +++ b/contracts/v2/storage/NodeOperatorFeesStorage.sol @@ -49,7 +49,7 @@ contract NodeOperatorFeesStorage is Named, Versioned, HubDependent { operatorFees[identityIds[i]] = oldOperatorFees; } else { uint96 feePercentage96 = ss.operatorFees(identityIds[i]); - require(feePercentage96 <= type(uint8).max, "Fee percentage exceeds uint8 range"); + require(feePercentage96 <= type(uint8).max, "Fee exceeds uint8 range"); uint8 feePercentage = uint8(feePercentage96); operatorFees[identityIds[i]].push( NodeOperatorStructs.OperatorFee({ From d79e09983eb6a97338cb3ebcdbeca7bb6606658b Mon Sep 17 00:00:00 2001 From: NZT48 Date: Fri, 17 May 2024 15:42:29 +0200 Subject: [PATCH 04/10] Deployed NodeOperatorFeeChange contract on NeuroWeb --- deployments/otp_mainnet_contracts.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/deployments/otp_mainnet_contracts.json b/deployments/otp_mainnet_contracts.json index f8a8b700..e9f94a4e 100644 --- a/deployments/otp_mainnet_contracts.json +++ b/deployments/otp_mainnet_contracts.json @@ -197,13 +197,13 @@ "deployed": true }, "NodeOperatorFeesStorage": { - "evmAddress": "0x030d086a005F2e5AB99D7a0a73c0a7C92028640b", - "substrateAddress": "5EMjsczLnayCy2aw6rNrJh76pxZqZgtfSban41RzmYmNzfgo", + "evmAddress": "0x9037eAAc6B3F496Bd6C79b08333876D84940F705", + "substrateAddress": "5EMjsczq5BcomErdwXuXbYxJ9bZd7cp7vvm3tfv81Z8531c6", "version": "2.0.0", - "gitBranch": "main", - "gitCommitHash": "cdd09025ee035eb72c4322639cefe1848dd90ecb", - "deploymentBlock": 4785998, - "deploymentTimestamp": 1713972219931, + "gitBranch": "operatorFee-fixes", + "gitCommitHash": "d54481ee9546bffcac3c9f19a4f2f6c62c56a0c4", + "deploymentBlock": 4946307, + "deploymentTimestamp": 1715951095745, "deployed": true }, "Staking": { From 63e8ce3dfa370844af8318182890ba23976f7daf Mon Sep 17 00:00:00 2001 From: NZT48 Date: Mon, 20 May 2024 15:32:57 +0200 Subject: [PATCH 05/10] Update deployment script for NOFS --- .../028_deploy_node_operator_fees_storage.ts | 123 +----------------- 1 file changed, 5 insertions(+), 118 deletions(-) diff --git a/deploy/028_deploy_node_operator_fees_storage.ts b/deploy/028_deploy_node_operator_fees_storage.ts index b10b82fa..e32f1928 100644 --- a/deploy/028_deploy_node_operator_fees_storage.ts +++ b/deploy/028_deploy_node_operator_fees_storage.ts @@ -1,8 +1,6 @@ import { DeployFunction } from 'hardhat-deploy/types'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; -import { ShardingTableStructsV1 } from '../typechain/contracts/v2/ShardingTable.sol/ShardingTableV2'; - const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const isDeployed = hre.helpers.isDeployed('NodeOperatorFeesStorage'); @@ -10,126 +8,15 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { return; } - const oldOperatorFees = []; - const timestampNow = (await hre.ethers.provider.getBlock('latest')).timestamp; - - const { deployer } = await hre.getNamedAccounts(); - - let shardingTableABI; - let shardingTableAddress; - if (Object.keys(hre.helpers.contractDeployments.contracts).includes('OldShardingTable')) { - shardingTableABI = hre.helpers.getAbi('ShardingTable'); - shardingTableAddress = hre.helpers.contractDeployments.contracts['OldShardingTable'].evmAddress; - delete hre.helpers.contractDeployments.contracts['OldShardingTable']; - console.log(`Found V1 ShardingTable address: ${shardingTableAddress}`); - } else { - shardingTableABI = hre.helpers.getAbi('ShardingTableV2'); - shardingTableAddress = hre.helpers.contractDeployments.contracts['ShardingTable'].evmAddress; - console.log(`Found V2 ShardingTable address: ${shardingTableAddress}`); - } - const ShardingTable = await hre.ethers.getContractAt(shardingTableABI, shardingTableAddress, deployer); - - const stakingStorageAddress = hre.helpers.contractDeployments.contracts['StakingStorage'].evmAddress; - const StakingStorage = await hre.ethers.getContractAt('StakingStorage', stakingStorageAddress, deployer); - - const nofcsAddress = hre.helpers.contractDeployments.contracts['NodeOperatorFeeChangesStorage']?.evmAddress; - let nofcs = null; - if (nofcsAddress) { - const abi = hre.helpers.getAbi('LegacyNodeOperatorFeeChangesStorage'); - nofcs = await hre.ethers.getContractAt(abi, nofcsAddress, deployer); - } - - console.log(`Getting list of nodes in Sharding Table...`); - const nodes: ShardingTableStructsV1.NodeInfoStructOutput[] = await ShardingTable['getShardingTable()'](); - const identityIds = nodes.map((node) => node.identityId); - - console.log(`Starting migration of the old operator fees...`); - for (const identityId of identityIds) { - console.log(`--------------------------------------------------------`); - console.log(`IdentityId: ${identityId}`); - - const operatorFees = []; - - const activeOperatorFeePercentage = await StakingStorage.operatorFees(identityId); - - console.log(`Active operatorFee in the StakingStorage: ${activeOperatorFeePercentage.toString()}%`); - - if (!activeOperatorFeePercentage.eq(0)) { - operatorFees.push({ - feePercentage: activeOperatorFeePercentage, - effectiveDate: timestampNow, - }); - } - - if (nofcs !== null) { - const pendingOperatorFee = await nofcs.operatorFeeChangeRequests(identityId); + const nodeOperatorFeesStorageAddress = + hre.helpers.contractDeployments.contracts['NodeOperatorFeesStorage'].evmAddress; - console.log(`Pending operatorFee in the NodeOperatorFeeChangesStorage: ${pendingOperatorFee.newFee.toString()}%`); - - if (!pendingOperatorFee.timestamp.eq(0)) { - if (pendingOperatorFee.timestamp < operatorFees[0].effectiveDate) { - operatorFees[0].effectiveDate = pendingOperatorFee.timestamp - 1; - } - - operatorFees.push({ - feePercentage: pendingOperatorFee.newFee, - effectiveDate: pendingOperatorFee.timestamp, - }); - } - } - - console.log(`--------------------------------------------------------`); - - if (operatorFees.length > 0) { - oldOperatorFees.push({ - identityId, - fees: operatorFees, - }); - } - } - - delete hre.helpers.contractDeployments.contracts['NodeOperatorFeeChangesStorage']; - - console.log(`Full list of migrated operator fees: ${JSON.stringify(oldOperatorFees)}`); - - const NodeOperatorFeesStorage = await hre.helpers.deploy({ + await hre.helpers.deploy({ newContractName: 'NodeOperatorFeesStorage', - additionalArgs: [timestampNow + 86400], + additionalArgs: [nodeOperatorFeesStorageAddress], // Old NOFS }); - - const chunkSize = 10; - const encodedDataArray: string[] = oldOperatorFees.reduce((acc, _, currentIndex, array) => { - if (currentIndex % chunkSize === 0) { - // Encode and push the function data for a slice of the array - acc.push( - NodeOperatorFeesStorage.interface.encodeFunctionData('migrateOldOperatorFees', [ - array.slice(currentIndex, currentIndex + chunkSize), - ]), - ); - } - return acc; - }, []); - - if (hre.network.config.environment === 'development') { - const { deployer } = await hre.getNamedAccounts(); - - const hubControllerAddress = hre.helpers.contractDeployments.contracts['HubController'].evmAddress; - const HubController = await hre.ethers.getContractAt('HubController', hubControllerAddress, deployer); - - for (let i = 0; i < encodedDataArray.length; i++) { - const migrateOldOperatorFeesTx = await HubController.forwardCall( - NodeOperatorFeesStorage.address, - encodedDataArray[i], - ); - await migrateOldOperatorFeesTx.wait(); - } - } else { - for (let i = 0; i < encodedDataArray.length; i++) { - hre.helpers.setParametersEncodedData.push(['NodeOperatorFeesStorage', [encodedDataArray[i]]]); - } - } }; export default func; func.tags = ['NodeOperatorFeesStorage', 'v2']; -func.dependencies = ['HubV2', 'StakingStorage', 'ShardingTableV2']; +func.dependencies = ['HubV2', 'StakingStorage']; From 0d569a972e2ff59cd294a2ce5f3308577022e4b8 Mon Sep 17 00:00:00 2001 From: NZT48 Date: Wed, 22 May 2024 11:48:44 +0200 Subject: [PATCH 06/10] Bump version to Profile and NOFS contracts --- contracts/v1/Profile.sol | 2 +- contracts/v2/storage/NodeOperatorFeesStorage.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/v1/Profile.sol b/contracts/v1/Profile.sol index 15c59375..cc89da4a 100644 --- a/contracts/v1/Profile.sol +++ b/contracts/v1/Profile.sol @@ -34,7 +34,7 @@ contract Profile is Named, Versioned, ContractStatus, Initializable { event AskUpdated(uint72 indexed identityId, bytes nodeId, uint96 ask); string private constant _NAME = "Profile"; - string private constant _VERSION = "1.1.1"; + string private constant _VERSION = "1.1.2"; HashingProxy public hashingProxy; Identity public identityContract; diff --git a/contracts/v2/storage/NodeOperatorFeesStorage.sol b/contracts/v2/storage/NodeOperatorFeesStorage.sol index c1752219..60cd53e9 100644 --- a/contracts/v2/storage/NodeOperatorFeesStorage.sol +++ b/contracts/v2/storage/NodeOperatorFeesStorage.sol @@ -11,7 +11,7 @@ import {NodeOperatorStructs} from "../structs/NodeOperatorStructs.sol"; contract NodeOperatorFeesStorage is Named, Versioned, HubDependent { string private constant _NAME = "NodeOperatorFeesStorage"; - string private constant _VERSION = "2.0.0"; + string private constant _VERSION = "2.0.1"; bool private _delayFreePeriodSet; uint256 public delayFreePeriodEnd; From cc6826bfbcd097f6ff27c146eb7421ab4c6839ca Mon Sep 17 00:00:00 2001 From: NZT48 Date: Wed, 22 May 2024 11:49:08 +0200 Subject: [PATCH 07/10] NeuroWeb profile contract changed --- deployments/otp_mainnet_contracts.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/deployments/otp_mainnet_contracts.json b/deployments/otp_mainnet_contracts.json index e9f94a4e..6b0cedb8 100644 --- a/deployments/otp_mainnet_contracts.json +++ b/deployments/otp_mainnet_contracts.json @@ -68,13 +68,13 @@ "deployed": true }, "Profile": { - "evmAddress": "0x8453855ED7a42d98F0abCbEDBD61ac082c5337B5", - "substrateAddress": "5EMjsczngyeEYRQVCDxeLthH85Upcsiw3G663SnzQsPuNpc9", - "version": "1.1.1", - "gitBranch": "main", - "gitCommitHash": "cdd09025ee035eb72c4322639cefe1848dd90ecb", - "deploymentBlock": 4786001, - "deploymentTimestamp": 1713972267333, + "evmAddress": "0xDfB94C5021B1684A83001734c3cFd733415d9CcD", + "substrateAddress": "5EMjsd171Acgqe4PrafYj2BStycTBUqfSs2xX1QYGE1f3Ju6", + "version": "1.1.2", + "gitBranch": "operatorFee-fixes", + "gitCommitHash": "63e8ce3dfa370844af8318182890ba23976f7daf", + "deploymentBlock": 4973043, + "deploymentTimestamp": 1716277322852, "deployed": true }, "ProfileStorage": { From 58d255f64410d566f7be9ccc775c02c9f721168f Mon Sep 17 00:00:00 2001 From: NZT48 Date: Wed, 22 May 2024 23:30:50 +0200 Subject: [PATCH 08/10] Gnosis mainnet profile and Nofs redeployed --- deployments/gnosis_mainnet_contracts.json | 24 +++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/deployments/gnosis_mainnet_contracts.json b/deployments/gnosis_mainnet_contracts.json index db20c6b9..5f9963cd 100644 --- a/deployments/gnosis_mainnet_contracts.json +++ b/deployments/gnosis_mainnet_contracts.json @@ -210,12 +210,12 @@ "deployed": true }, "Profile": { - "evmAddress": "0x5deb369B8C0930853cD192d85f1389151e009CF4", - "version": "1.1.1", - "gitBranch": "main", - "gitCommitHash": "26881f1a79eaf41f13d1c48a2c5952d0a1d14274", - "deploymentBlock": 32446897, - "deploymentTimestamp": 1707908838740, + "evmAddress": "0x5a1114614b7790849B38198A289FA8d41C42cc24", + "version": "1.1.2", + "gitBranch": "operatorFee-fixes", + "gitCommitHash": "63e8ce3dfa370844af8318182890ba23976f7daf", + "deploymentBlock": 34057405, + "deploymentTimestamp": 1716290847473, "deployed": true }, "CommitManagerV1": { @@ -273,12 +273,12 @@ "deployed": true }, "NodeOperatorFeesStorage": { - "evmAddress": "0x5adAC1b63407C490aC0Fb80E85CE7014101c8610", - "version": "2.0.0", - "gitBranch": "mainnet-deployment/4.2.7", - "gitCommitHash": "8839a0e5c92a413b06d20fa15335950bb625f890", - "deploymentBlock": 33619390, - "deploymentTimestamp": 1714031946358, + "evmAddress": "0x9e676656c84AFFa2C13465e07fC9E635AC46c16B", + "version": "2.0.1", + "gitBranch": "operatorFee-fixes", + "gitCommitHash": "63e8ce3dfa370844af8318182890ba23976f7daf", + "deploymentBlock": 34057403, + "deploymentTimestamp": 1716290841668, "deployed": true } } From 38d7bc4595f2ff59bf0d3d11efd291241ecc992f Mon Sep 17 00:00:00 2001 From: Uladzislau Hubar Date: Tue, 28 May 2024 14:00:17 +0200 Subject: [PATCH 09/10] Reverted back and reworked migration script for node operator fees --- abi/NodeOperatorFeesStorage.json | 64 ++++--- .../v2/storage/NodeOperatorFeesStorage.sol | 39 ++-- .../028_deploy_node_operator_fees_storage.ts | 166 +++++++++++++++++- deployments/gnosis_mainnet_contracts.json | 8 +- deployments/otp_mainnet_contracts.json | 5 +- 5 files changed, 228 insertions(+), 54 deletions(-) diff --git a/abi/NodeOperatorFeesStorage.json b/abi/NodeOperatorFeesStorage.json index d9b4935a..a5a47309 100644 --- a/abi/NodeOperatorFeesStorage.json +++ b/abi/NodeOperatorFeesStorage.json @@ -7,9 +7,9 @@ "type": "address" }, { - "internalType": "address", - "name": "_oldNOFSAddress", - "type": "address" + "internalType": "uint256", + "name": "migrationPeriodEnd_", + "type": "uint256" } ], "stateMutability": "nonpayable", @@ -542,42 +542,66 @@ "type": "function" }, { - "inputs": [], - "name": "name", - "outputs": [ + "inputs": [ { - "internalType": "string", - "name": "", - "type": "string" + "components": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "components": [ + { + "internalType": "uint8", + "name": "feePercentage", + "type": "uint8" + }, + { + "internalType": "uint248", + "name": "effectiveDate", + "type": "uint248" + } + ], + "internalType": "struct NodeOperatorStructs.OperatorFee[]", + "name": "fees", + "type": "tuple[]" + } + ], + "internalType": "struct NodeOperatorStructs.OperatorFees[]", + "name": "legacyFees", + "type": "tuple[]" } ], - "stateMutability": "pure", + "name": "migrateOldOperatorFees", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], - "name": "oldNOFSAddress", + "name": "migrationPeriodEnd", "outputs": [ { - "internalType": "address", + "internalType": "uint256", "name": "", - "type": "address" + "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "name", + "outputs": [ { - "internalType": "uint72[]", - "name": "identityIds", - "type": "uint72[]" + "internalType": "string", + "name": "", + "type": "string" } ], - "name": "operatorFeeMigration", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "pure", "type": "function" }, { diff --git a/contracts/v2/storage/NodeOperatorFeesStorage.sol b/contracts/v2/storage/NodeOperatorFeesStorage.sol index 60cd53e9..77545773 100644 --- a/contracts/v2/storage/NodeOperatorFeesStorage.sol +++ b/contracts/v2/storage/NodeOperatorFeesStorage.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.16; import {HubDependent} from "../../v1/abstract/HubDependent.sol"; -import {StakingStorage} from "../../v1/storage/StakingStorage.sol"; import {Named} from "../../v1/interface/Named.sol"; import {Versioned} from "../../v1/interface/Versioned.sol"; import {NodeOperatorErrors} from "../errors/NodeOperatorErrors.sol"; @@ -11,19 +10,17 @@ import {NodeOperatorStructs} from "../structs/NodeOperatorStructs.sol"; contract NodeOperatorFeesStorage is Named, Versioned, HubDependent { string private constant _NAME = "NodeOperatorFeesStorage"; - string private constant _VERSION = "2.0.1"; + string private constant _VERSION = "2.0.2"; bool private _delayFreePeriodSet; uint256 public delayFreePeriodEnd; - - address public oldNOFSAddress; + uint256 public migrationPeriodEnd; // identityId => OperatorFee[] mapping(uint72 => NodeOperatorStructs.OperatorFee[]) public operatorFees; - // solhint-disable-next-line no-empty-blocks - constructor(address hubAddress, address _oldNOFSAddress) HubDependent(hubAddress) { - oldNOFSAddress = _oldNOFSAddress; + constructor(address hubAddress, uint256 migrationPeriodEnd_) HubDependent(hubAddress) { + migrationPeriodEnd = migrationPeriodEnd_; } modifier onlyOnce() { @@ -32,6 +29,11 @@ contract NodeOperatorFeesStorage is Named, Versioned, HubDependent { _delayFreePeriodSet = true; } + modifier timeLimited() { + require(block.timestamp < migrationPeriodEnd, "Migration period has ended"); + _; + } + function name() external pure virtual override returns (string memory) { return _NAME; } @@ -40,24 +42,11 @@ contract NodeOperatorFeesStorage is Named, Versioned, HubDependent { return _VERSION; } - function operatorFeeMigration(uint72[] calldata identityIds) external { - NodeOperatorFeesStorage oldNOFS = NodeOperatorFeesStorage(oldNOFSAddress); - StakingStorage ss = StakingStorage(hub.getContractAddress("StakingStorage")); - for (uint72 i; i < identityIds.length; ) { - NodeOperatorStructs.OperatorFee[] memory oldOperatorFees = oldNOFS.getOperatorFees(identityIds[i]); - if (oldOperatorFees.length != 0) { - operatorFees[identityIds[i]] = oldOperatorFees; - } else { - uint96 feePercentage96 = ss.operatorFees(identityIds[i]); - require(feePercentage96 <= type(uint8).max, "Fee exceeds uint8 range"); - uint8 feePercentage = uint8(feePercentage96); - operatorFees[identityIds[i]].push( - NodeOperatorStructs.OperatorFee({ - feePercentage: feePercentage, - effectiveDate: uint248(block.timestamp) - }) - ); - } + function migrateOldOperatorFees( + NodeOperatorStructs.OperatorFees[] memory legacyFees + ) external onlyHubOwner timeLimited { + for (uint i; i < legacyFees.length; ) { + operatorFees[legacyFees[i].identityId] = legacyFees[i].fees; unchecked { i++; } diff --git a/deploy/028_deploy_node_operator_fees_storage.ts b/deploy/028_deploy_node_operator_fees_storage.ts index e32f1928..d90c5649 100644 --- a/deploy/028_deploy_node_operator_fees_storage.ts +++ b/deploy/028_deploy_node_operator_fees_storage.ts @@ -1,22 +1,178 @@ +import { BigNumberish } from 'ethers'; import { DeployFunction } from 'hardhat-deploy/types'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { NodeOperatorStructs } from '../typechain/contracts/v2/storage/NodeOperatorFeesStorage'; + const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const isDeployed = hre.helpers.isDeployed('NodeOperatorFeesStorage'); + const isMigration = hre.helpers.contractDeployments.contracts['NodeOperatorFeesStorage']?.migration || false; - if (isDeployed) { + if (isDeployed && !isMigration) { return; } - const nodeOperatorFeesStorageAddress = + const oldOperatorFees = []; + const timestampNow = (await hre.ethers.provider.getBlock('latest')).timestamp; + + const { deployer } = await hre.getNamedAccounts(); + + const oldNodeOperatorFeesStorageAddress = hre.helpers.contractDeployments.contracts['NodeOperatorFeesStorage'].evmAddress; + const OldNodeOperatorFeesStorage = await hre.ethers.getContractAt( + 'NodeOperatorFeesStorage', + oldNodeOperatorFeesStorageAddress, + ); + + const nofcsAddress = hre.helpers.contractDeployments.contracts['NodeOperatorFeeChangesStorage']?.evmAddress; + let nofcs = null; + if (nofcsAddress) { + const abi = hre.helpers.getAbi('LegacyNodeOperatorFeeChangesStorage'); + nofcs = await hre.ethers.getContractAt(abi, nofcsAddress, deployer); + } + + const stakingStorageAddress = hre.helpers.contractDeployments.contracts['StakingStorage'].evmAddress; + const StakingStorage = await hre.ethers.getContractAt('StakingStorage', stakingStorageAddress, deployer); + + const storageLayout = { + astId: 1238, + contract: 'IdentityStorageFlattened.sol:IdentityStorage', + label: '_identityId', + offset: 20, + slot: 0, + type: 't_uint72', + }; + const storageVariableType = { + t_uint72: { + encoding: 'inplace', + label: 'uint72', + numberOfBytes: 9, + }, + }; + + console.log('Getting current next identityId from IdentityStorage...'); + const storageSlot = await hre.ethers.provider.getStorageAt( + hre.helpers.contractDeployments.contracts['IdentityStorage'].evmAddress, + 0, + ); + const variableSlot = storageSlot.slice( + storageSlot.length - + 2 * + (storageLayout.offset + + storageVariableType[storageLayout.type as keyof typeof storageVariableType].numberOfBytes), + storageSlot.length - storageLayout.offset * 2, + ); + console.log(`Storage slot ${storageLayout.slot}: ${storageSlot}`); + console.log(`Variable slot: ${variableSlot}`); + const nextIdentityId = parseInt(variableSlot, 16); + console.log(`Current next identityId: ${nextIdentityId}`); + + console.log(`Starting migration of the old operator fees... Latest identityId: ${nextIdentityId - 1}`); + for (let identityId = 1; identityId < nextIdentityId; identityId++) { + console.log(`--------------------------------------------------------`); + console.log(`IdentityId: ${identityId}`); + + const operatorFees: NodeOperatorStructs.OperatorFeeStruct[] = []; + + const oldContractOperatorFees = await OldNodeOperatorFeesStorage.getOperatorFees(identityId); + + console.log(`Old operatorFees in the old NodeOperatorFeesStorage: ${JSON.stringify(oldContractOperatorFees)}`); + + if (oldContractOperatorFees.length != 0) { + oldOperatorFees.push({ + identityId, + fees: oldContractOperatorFees.map((x: BigNumberish[]) => { + return { feePercentage: x[0], effectiveDate: x[1] }; + }), + }); + continue; + } + + const activeOperatorFeePercentage = await StakingStorage.operatorFees(identityId); + + console.log(`Active operatorFee in the StakingStorage: ${activeOperatorFeePercentage.toString()}%`); - await hre.helpers.deploy({ + if (!activeOperatorFeePercentage.eq(0)) { + operatorFees.push({ + feePercentage: activeOperatorFeePercentage, + effectiveDate: timestampNow, + }); + } + + if (nofcs !== null) { + const pendingOperatorFee = await nofcs.operatorFeeChangeRequests(identityId); + + console.log(`Pending operatorFee in the NodeOperatorFeeChangesStorage: ${pendingOperatorFee.newFee.toString()}%`); + + if (!pendingOperatorFee.timestamp.eq(0)) { + if (operatorFees.length > 0 && pendingOperatorFee.timestamp < operatorFees[0].effectiveDate) { + operatorFees[0].effectiveDate = pendingOperatorFee.timestamp - 1; + } + + operatorFees.push({ + feePercentage: pendingOperatorFee.newFee, + effectiveDate: pendingOperatorFee.timestamp, + }); + } + } + + console.log(`--------------------------------------------------------`); + + if (operatorFees.length > 0) { + oldOperatorFees.push({ + identityId, + fees: operatorFees, + }); + } else { + oldOperatorFees.push({ + identityId, + fees: [{ feePercentage: 0, effectiveDate: timestampNow }], + }); + } + } + + delete hre.helpers.contractDeployments.contracts['NodeOperatorFeeChangesStorage']; + + console.log(`Full list of migrated operator fees: ${JSON.stringify(oldOperatorFees)}`); + + const NodeOperatorFeesStorage = await hre.helpers.deploy({ newContractName: 'NodeOperatorFeesStorage', - additionalArgs: [nodeOperatorFeesStorageAddress], // Old NOFS + additionalArgs: [timestampNow + 86400], }); + + const chunkSize = 10; + const encodedDataArray: string[] = oldOperatorFees.reduce((acc, _, currentIndex, array) => { + if (currentIndex % chunkSize === 0) { + // Encode and push the function data for a slice of the array + acc.push( + NodeOperatorFeesStorage.interface.encodeFunctionData('migrateOldOperatorFees', [ + array.slice(currentIndex, currentIndex + chunkSize), + ]), + ); + } + return acc; + }, []); + + if (hre.network.config.environment === 'development') { + const { deployer } = await hre.getNamedAccounts(); + + const hubControllerAddress = hre.helpers.contractDeployments.contracts['HubController'].evmAddress; + const HubController = await hre.ethers.getContractAt('HubController', hubControllerAddress, deployer); + + for (let i = 0; i < encodedDataArray.length; i++) { + const migrateOldOperatorFeesTx = await HubController.forwardCall( + NodeOperatorFeesStorage.address, + encodedDataArray[i], + ); + await migrateOldOperatorFeesTx.wait(); + } + } else { + for (let i = 0; i < encodedDataArray.length; i++) { + hre.helpers.setParametersEncodedData.push(['NodeOperatorFeesStorage', [encodedDataArray[i]]]); + } + } }; export default func; func.tags = ['NodeOperatorFeesStorage', 'v2']; -func.dependencies = ['HubV2', 'StakingStorage']; +func.dependencies = ['HubV2', 'ContentAssetStorageV2', 'StakingStorage', 'ShardingTableV2']; diff --git a/deployments/gnosis_mainnet_contracts.json b/deployments/gnosis_mainnet_contracts.json index 5f9963cd..e6914b4f 100644 --- a/deployments/gnosis_mainnet_contracts.json +++ b/deployments/gnosis_mainnet_contracts.json @@ -273,13 +273,17 @@ "deployed": true }, "NodeOperatorFeesStorage": { - "evmAddress": "0x9e676656c84AFFa2C13465e07fC9E635AC46c16B", + "evmAddress": "0x5adAC1b63407C490aC0Fb80E85CE7014101c8610", "version": "2.0.1", "gitBranch": "operatorFee-fixes", "gitCommitHash": "63e8ce3dfa370844af8318182890ba23976f7daf", "deploymentBlock": 34057403, "deploymentTimestamp": 1716290841668, - "deployed": true + "deployed": false, + "migration": true + }, + "NodeOperatorFeeChangesStorage": { + "evmAddress": "0x1DB35c492dfe89AF6e808c3c85B694983Bb372c9" } } } diff --git a/deployments/otp_mainnet_contracts.json b/deployments/otp_mainnet_contracts.json index 6b0cedb8..699bef8f 100644 --- a/deployments/otp_mainnet_contracts.json +++ b/deployments/otp_mainnet_contracts.json @@ -197,14 +197,15 @@ "deployed": true }, "NodeOperatorFeesStorage": { - "evmAddress": "0x9037eAAc6B3F496Bd6C79b08333876D84940F705", + "evmAddress": "0x030d086a005F2e5AB99D7a0a73c0a7C92028640b", "substrateAddress": "5EMjsczq5BcomErdwXuXbYxJ9bZd7cp7vvm3tfv81Z8531c6", "version": "2.0.0", "gitBranch": "operatorFee-fixes", "gitCommitHash": "d54481ee9546bffcac3c9f19a4f2f6c62c56a0c4", "deploymentBlock": 4946307, "deploymentTimestamp": 1715951095745, - "deployed": true + "deployed": false, + "migration": true }, "Staking": { "evmAddress": "0x02706Bc98204E4652Cb003B766F8E676eEF65Af5", From 34e65dacaf586ba84ea51bd13188d79792c29149 Mon Sep 17 00:00:00 2001 From: Uladzislau Hubar Date: Thu, 30 May 2024 12:02:08 +0200 Subject: [PATCH 10/10] Updated NodeOperatorFeesStorage migration function and deployment script, deployed contracts on Gnosis/Neuroweb --- .../v2/storage/NodeOperatorFeesStorage.sol | 6 +- .../028_deploy_node_operator_fees_storage.ts | 132 +++++++++++------- deployments/gnosis_mainnet_contracts.json | 18 +-- deployments/otp_mainnet_contracts.json | 17 ++- 4 files changed, 98 insertions(+), 75 deletions(-) diff --git a/contracts/v2/storage/NodeOperatorFeesStorage.sol b/contracts/v2/storage/NodeOperatorFeesStorage.sol index 77545773..566f88cd 100644 --- a/contracts/v2/storage/NodeOperatorFeesStorage.sol +++ b/contracts/v2/storage/NodeOperatorFeesStorage.sol @@ -42,10 +42,10 @@ contract NodeOperatorFeesStorage is Named, Versioned, HubDependent { return _VERSION; } - function migrateOldOperatorFees( - NodeOperatorStructs.OperatorFees[] memory legacyFees - ) external onlyHubOwner timeLimited { + function migrateOldOperatorFees(NodeOperatorStructs.OperatorFees[] memory legacyFees) external timeLimited { for (uint i; i < legacyFees.length; ) { + require(operatorFees[legacyFees[i].identityId].length == 0); + operatorFees[legacyFees[i].identityId] = legacyFees[i].fees; unchecked { i++; diff --git a/deploy/028_deploy_node_operator_fees_storage.ts b/deploy/028_deploy_node_operator_fees_storage.ts index d90c5649..f2d38329 100644 --- a/deploy/028_deploy_node_operator_fees_storage.ts +++ b/deploy/028_deploy_node_operator_fees_storage.ts @@ -2,8 +2,6 @@ import { BigNumberish } from 'ethers'; import { DeployFunction } from 'hardhat-deploy/types'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; -import { NodeOperatorStructs } from '../typechain/contracts/v2/storage/NodeOperatorFeesStorage'; - const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const isDeployed = hre.helpers.isDeployed('NodeOperatorFeesStorage'); const isMigration = hre.helpers.contractDeployments.contracts['NodeOperatorFeesStorage']?.migration || false; @@ -72,48 +70,92 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { console.log(`--------------------------------------------------------`); console.log(`IdentityId: ${identityId}`); - const operatorFees: NodeOperatorStructs.OperatorFeeStruct[] = []; + let operatorFees: { feePercentage: BigNumberish; effectiveDate: number }[] = []; const oldContractOperatorFees = await OldNodeOperatorFeesStorage.getOperatorFees(identityId); console.log(`Old operatorFees in the old NodeOperatorFeesStorage: ${JSON.stringify(oldContractOperatorFees)}`); if (oldContractOperatorFees.length != 0) { - oldOperatorFees.push({ - identityId, - fees: oldContractOperatorFees.map((x: BigNumberish[]) => { - return { feePercentage: x[0], effectiveDate: x[1] }; - }), + const fees = oldContractOperatorFees.map((x: BigNumberish[]) => { + return { feePercentage: x[0], effectiveDate: Number(x[1].toString()) }; }); - continue; + + if (hre.network.name.startsWith('gnosis')) { + operatorFees = operatorFees.concat(fees); + } else { + oldOperatorFees.push({ + identityId, + fees, + }); + continue; + } } - const activeOperatorFeePercentage = await StakingStorage.operatorFees(identityId); + let stakingStorageSource = false; + if (operatorFees.length == 0) { + const activeOperatorFeePercentage = await StakingStorage.operatorFees(identityId); - console.log(`Active operatorFee in the StakingStorage: ${activeOperatorFeePercentage.toString()}%`); + console.log(`Active operatorFee in the StakingStorage: ${activeOperatorFeePercentage.toString()}%`); - if (!activeOperatorFeePercentage.eq(0)) { - operatorFees.push({ - feePercentage: activeOperatorFeePercentage, - effectiveDate: timestampNow, - }); + if (!activeOperatorFeePercentage.eq(0)) { + operatorFees.push({ + feePercentage: activeOperatorFeePercentage, + effectiveDate: timestampNow, + }); + stakingStorageSource = true; + } } if (nofcs !== null) { const pendingOperatorFee = await nofcs.operatorFeeChangeRequests(identityId); + if (Number(pendingOperatorFee.timestamp.toString() == 0)) { + if (operatorFees.length > 0) { + oldOperatorFees.push({ + identityId, + fees: operatorFees, + }); + } else { + oldOperatorFees.push({ + identityId, + fees: [{ feePercentage: 0, effectiveDate: timestampNow }], + }); + } + continue; + } + console.log(`Pending operatorFee in the NodeOperatorFeeChangesStorage: ${pendingOperatorFee.newFee.toString()}%`); - if (!pendingOperatorFee.timestamp.eq(0)) { - if (operatorFees.length > 0 && pendingOperatorFee.timestamp < operatorFees[0].effectiveDate) { - operatorFees[0].effectiveDate = pendingOperatorFee.timestamp - 1; - } + const exists = operatorFees.some( + (obj) => + Number(obj.feePercentage.toString()) === Number(pendingOperatorFee.newFee.toString()) && + Number(obj.effectiveDate.toString()) === Number(pendingOperatorFee.timestamp.toString()), + ); - operatorFees.push({ - feePercentage: pendingOperatorFee.newFee, - effectiveDate: pendingOperatorFee.timestamp, + if (exists) { + console.log(`Pending operatorFee is already a part of the fees array from old NodeOperatorFeesStorage`); + oldOperatorFees.push({ + identityId, + fees: operatorFees, }); + continue; + } + + if ( + (stakingStorageSource && + Number(pendingOperatorFee.timestamp.toString()) < Number(operatorFees[0].effectiveDate.toString())) || + (operatorFees.length == 1 && Number(operatorFees[0].effectiveDate.toString()) == 1716291685) + ) { + operatorFees[0].effectiveDate = Number(pendingOperatorFee.timestamp.toString()) - 1; } + + operatorFees.push({ + feePercentage: pendingOperatorFee.newFee, + effectiveDate: Number(pendingOperatorFee.timestamp.toString()), + }); + + operatorFees.sort((a, b) => a.effectiveDate - b.effectiveDate); } console.log(`--------------------------------------------------------`); @@ -141,35 +183,21 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { }); const chunkSize = 10; - const encodedDataArray: string[] = oldOperatorFees.reduce((acc, _, currentIndex, array) => { - if (currentIndex % chunkSize === 0) { - // Encode and push the function data for a slice of the array - acc.push( - NodeOperatorFeesStorage.interface.encodeFunctionData('migrateOldOperatorFees', [ - array.slice(currentIndex, currentIndex + chunkSize), - ]), - ); - } - return acc; - }, []); - - if (hre.network.config.environment === 'development') { - const { deployer } = await hre.getNamedAccounts(); - - const hubControllerAddress = hre.helpers.contractDeployments.contracts['HubController'].evmAddress; - const HubController = await hre.ethers.getContractAt('HubController', hubControllerAddress, deployer); - - for (let i = 0; i < encodedDataArray.length; i++) { - const migrateOldOperatorFeesTx = await HubController.forwardCall( - NodeOperatorFeesStorage.address, - encodedDataArray[i], - ); - await migrateOldOperatorFeesTx.wait(); - } - } else { - for (let i = 0; i < encodedDataArray.length; i++) { - hre.helpers.setParametersEncodedData.push(['NodeOperatorFeesStorage', [encodedDataArray[i]]]); - } + const totalChunks = Math.ceil(oldOperatorFees.length / chunkSize); + + console.log(`Starting migration of operator fees for ${oldOperatorFees.length} nodes...`); + for (let i = 0; i < oldOperatorFees.length; i += chunkSize) { + const chunk = oldOperatorFees.slice(i, i + chunkSize); + const chunkNumber = Math.floor(i / chunkSize) + 1; + const percentageDone = ((chunkNumber / totalChunks) * 100).toFixed(2); + console.log( + `Processing chunk ${chunkNumber} out of ${totalChunks} (starting at index ${i}):`, + JSON.stringify(chunk), + ); + console.log(`Percentage done: ${percentageDone}%`); + + const tx = await NodeOperatorFeesStorage.migrateOldOperatorFees(chunk); + await tx.wait(); } }; diff --git a/deployments/gnosis_mainnet_contracts.json b/deployments/gnosis_mainnet_contracts.json index e6914b4f..16e8d99a 100644 --- a/deployments/gnosis_mainnet_contracts.json +++ b/deployments/gnosis_mainnet_contracts.json @@ -273,17 +273,13 @@ "deployed": true }, "NodeOperatorFeesStorage": { - "evmAddress": "0x5adAC1b63407C490aC0Fb80E85CE7014101c8610", - "version": "2.0.1", - "gitBranch": "operatorFee-fixes", - "gitCommitHash": "63e8ce3dfa370844af8318182890ba23976f7daf", - "deploymentBlock": 34057403, - "deploymentTimestamp": 1716290841668, - "deployed": false, - "migration": true - }, - "NodeOperatorFeeChangesStorage": { - "evmAddress": "0x1DB35c492dfe89AF6e808c3c85B694983Bb372c9" + "evmAddress": "0x2F2031A35dE9297f2372569551F8682E818C4943", + "version": "2.0.2", + "gitBranch": "operatorFee-fixes-2", + "gitCommitHash": "38d7bc4595f2ff59bf0d3d11efd291241ecc992f", + "deploymentBlock": 34206991, + "deploymentTimestamp": 1717062353134, + "deployed": true } } } diff --git a/deployments/otp_mainnet_contracts.json b/deployments/otp_mainnet_contracts.json index 699bef8f..1fa4778a 100644 --- a/deployments/otp_mainnet_contracts.json +++ b/deployments/otp_mainnet_contracts.json @@ -197,15 +197,14 @@ "deployed": true }, "NodeOperatorFeesStorage": { - "evmAddress": "0x030d086a005F2e5AB99D7a0a73c0a7C92028640b", - "substrateAddress": "5EMjsczq5BcomErdwXuXbYxJ9bZd7cp7vvm3tfv81Z8531c6", - "version": "2.0.0", - "gitBranch": "operatorFee-fixes", - "gitCommitHash": "d54481ee9546bffcac3c9f19a4f2f6c62c56a0c4", - "deploymentBlock": 4946307, - "deploymentTimestamp": 1715951095745, - "deployed": false, - "migration": true + "evmAddress": "0xe761209C8598a933b0F2CE3BdA11a9850Ca320BA", + "substrateAddress": "5EMjsd18Y8u6kqeznzaNcWNy4XpuX6TJTqvxsPRstGK1FMJb", + "version": "2.0.2", + "gitBranch": "operatorFee-fixes-2", + "gitCommitHash": "38d7bc4595f2ff59bf0d3d11efd291241ecc992f", + "deploymentBlock": 5035511, + "deploymentTimestamp": 1717062664410, + "deployed": true }, "Staking": { "evmAddress": "0x02706Bc98204E4652Cb003B766F8E676eEF65Af5",