From 39ada60cb547eab081f55b1d51844d09d6c2e3c9 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 14 Jan 2025 15:00:50 +0100 Subject: [PATCH 001/153] Naive imeplementation of owenr check --- contracts/paranets/Paranet.sol | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 884e6257..4984ac52 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -8,6 +8,7 @@ import {ParanetsRegistry} from "../storage/paranets/ParanetsRegistry.sol"; import {ParanetServicesRegistry} from "../storage/paranets/ParanetServicesRegistry.sol"; import {ProfileStorage} from "../storage/ProfileStorage.sol"; import {IdentityStorage} from "../storage/IdentityStorage.sol"; +import {KnowledgeCollectionStorage} from "../storage/KnowledgeCollectionStorage.sol"; import {ContractStatus} from "../abstract/ContractStatus.sol"; import {IInitializable} from "../interfaces/IInitializable.sol"; import {INamed} from "../interfaces/INamed.sol"; @@ -1065,13 +1066,32 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { } function _checkKnowledgeAssetOwner( - address knowledgeAssetStorageContract, - uint256 knowledgeAssetTokenId + address knowledgeCollectionStorageContractAddress, + uint256 knowledgeCollectionId ) internal view virtual { - require(hub.isAssetStorage(knowledgeAssetStorageContract), "Given address isn't KA Storage"); - require( - IERC721(knowledgeAssetStorageContract).ownerOf(knowledgeAssetTokenId) == msg.sender, - "Caller isn't the owner of the KA" + // Validate the provided address is a Knowledge Asset Storage contract + require(hub.isAssetStorage(knowledgeCollectionStorageContractAddress), "Given address isn't KA Storage"); + + // Create a KnowledgeCollectionStorage instance + KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage( + knowledgeCollectionStorageContractAddress ); + + // Determine the range of token IDs in the knowledge collection + uint256 startTokenId = (knowledgeCollectionId - 1) * + knowledgeCollectionStorage.knowledgeCollectionMaxSize() + + 1; // _startTokenId() + uint256 endTokenId = startTokenId + + knowledgeCollectionStorage.knowledgeCollections(knowledgeCollectionId).minted; + + for (uint256 tokenId = startTokenId; tokenId < endTokenId; tokenId++) { + // Skip burned tokens + if (knowledgeCollectionStorage.isKnowledgeAssetBurned(tokenId)) { + continue; + } + + // Ensure the caller owns all active tokens + require(knowledgeCollectionStorage.isOwnerOf(msg.sender, tokenId), "Caller isn't the owner of the KC"); + } } } From c73f36cb8a4db84028eff7f82e2cb0b2ecb0ebdb Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 14 Jan 2025 15:36:51 +0100 Subject: [PATCH 002/153] More optimal _checkKnowledgeCollectionOwner function --- contracts/paranets/Paranet.sol | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 4984ac52..3815c6d0 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -129,7 +129,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { constructor(address hubAddress) ContractStatus(hubAddress) {} modifier onlyKnowledgeAssetOwner(address knowledgeAssetStorageContract, uint256 knowledgeAssetTokenId) { - _checkKnowledgeAssetOwner(knowledgeAssetStorageContract, knowledgeAssetTokenId); + _checkKnowledgeCollectionOwner(knowledgeAssetStorageContract, knowledgeAssetTokenId); _; } @@ -467,7 +467,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); } - _checkKnowledgeAssetOwner(services[i].knowledgeAssetStorageContract, services[i].tokenId); + _checkKnowledgeCollectionOwner(services[i].knowledgeAssetStorageContract, services[i].tokenId); if ( pr.isServiceImplemented( @@ -1056,42 +1056,40 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { (address paranetKAStorageContract, uint256 paranetKATokenId) = paranetsRegistry.getParanetKnowledgeAssetLocator( paranetId ); - _checkKnowledgeAssetOwner(paranetKAStorageContract, paranetKATokenId); + _checkKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId); } function _checkParanetServiceOperator(bytes32 paranetServiceId) internal view virtual { (address paranetServiceKAStorageContract, uint256 paranetServiceKATokenId) = paranetServicesRegistry .getParanetServiceKnowledgeAssetLocator(paranetServiceId); - _checkKnowledgeAssetOwner(paranetServiceKAStorageContract, paranetServiceKATokenId); + _checkKnowledgeCollectionOwner(paranetServiceKAStorageContract, paranetServiceKATokenId); } - function _checkKnowledgeAssetOwner( + function _checkKnowledgeCollectionOwner( address knowledgeCollectionStorageContractAddress, uint256 knowledgeCollectionId ) internal view virtual { - // Validate the provided address is a Knowledge Asset Storage contract require(hub.isAssetStorage(knowledgeCollectionStorageContractAddress), "Given address isn't KA Storage"); - // Create a KnowledgeCollectionStorage instance KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage( knowledgeCollectionStorageContractAddress ); - // Determine the range of token IDs in the knowledge collection + uint256 minted = knowledgeCollectionStorage.knowledgeCollections[collectionId].minted; + uint256 burnedCount = knowledgeCollectionStorage.knowledgeCollections[collectionId].burned.length; + uint256 activeCount = minted - burnedCount; + require(activeCount != 0, "No KAs in collection"); + uint256 startTokenId = (knowledgeCollectionId - 1) * knowledgeCollectionStorage.knowledgeCollectionMaxSize() + 1; // _startTokenId() - uint256 endTokenId = startTokenId + - knowledgeCollectionStorage.knowledgeCollections(knowledgeCollectionId).minted; - for (uint256 tokenId = startTokenId; tokenId < endTokenId; tokenId++) { - // Skip burned tokens - if (knowledgeCollectionStorage.isKnowledgeAssetBurned(tokenId)) { - continue; - } + uint256 ownedCountInRange = knowledgeCollectionStorage.balanceOf( + msg.sender, + startTokenId, + minted + burnedCount + ); - // Ensure the caller owns all active tokens - require(knowledgeCollectionStorage.isOwnerOf(msg.sender, tokenId), "Caller isn't the owner of the KC"); - } + require(ownedCountInRange == activeCount, "Caller isn't the owner of the KC"); } } From 8a7eaf36acaeb64e0318e6b694a2c331f699801e Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 14 Jan 2025 16:39:33 +0100 Subject: [PATCH 003/153] Enable submitKnowledgeAsset --- contracts/paranets/Paranet.sol | 232 ++++++++++++++++----------------- 1 file changed, 113 insertions(+), 119 deletions(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 3815c6d0..a3bedd31 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -83,11 +83,11 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { string newParanetServiceDescription, address[] newParanetServiceAddresses ); - event KnowledgeAssetSubmittedToParanet( - address indexed paranetKAStorageContract, - uint256 indexed paranetKATokenId, - address indexed knowledgeAssetStorageContract, - uint256 knowledgeAssetTokenId + event KnowledgeCollectionSubmittedToParanet( + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, + address indexed knowledgeCollectionStorageContract, + uint256 knowledgeCollectionId ); event ParanetCuratedMinerAdded( address indexed paranetKAStorageContract, @@ -128,7 +128,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // solhint-disable-next-line no-empty-blocks constructor(address hubAddress) ContractStatus(hubAddress) {} - modifier onlyKnowledgeAssetOwner(address knowledgeAssetStorageContract, uint256 knowledgeAssetTokenId) { + modifier onlyKnowledgeCollectionOwner(address knowledgeAssetStorageContract, uint256 knowledgeAssetTokenId) { _checkKnowledgeCollectionOwner(knowledgeAssetStorageContract, knowledgeAssetTokenId); _; } @@ -161,7 +161,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { string calldata paranetDescription, ParanetLib.NodesAccessPolicy nodesAccessPolicy, ParanetLib.MinersAccessPolicy minersAccessPolicy - ) external onlyKnowledgeAssetOwner(paranetKAStorageContract, paranetKATokenId) returns (bytes32) { + ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) returns (bytes32) { ParanetsRegistry pr = paranetsRegistry; bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); @@ -197,7 +197,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 paranetKATokenId, string calldata paranetName, string calldata paranetDescription - ) external onlyKnowledgeAssetOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); @@ -216,7 +216,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { address paranetKAStorageContract, uint256 paranetKATokenId, uint72[] calldata identityIds - ) external onlyKnowledgeAssetOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; ProfileStorage ps = profileStorage; @@ -259,7 +259,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { address paranetKAStorageContract, uint256 paranetKATokenId, uint72[] calldata identityIds - ) external onlyKnowledgeAssetOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); @@ -343,7 +343,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { address paranetKAStorageContract, uint256 paranetKATokenId, uint72 identityId - ) external onlyKnowledgeAssetOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); @@ -395,7 +395,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { address paranetKAStorageContract, uint256 paranetKATokenId, uint72 identityId - ) external onlyKnowledgeAssetOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); @@ -445,7 +445,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { address paranetKAStorageContract, uint256 paranetKATokenId, ParanetLib.UniversalAssetLocator[] calldata services - ) external onlyKnowledgeAssetOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; ParanetServicesRegistry psr = paranetServicesRegistry; @@ -505,7 +505,11 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { string calldata paranetServiceName, string calldata paranetServiceDescription, address[] calldata paranetServiceAddresses - ) external onlyKnowledgeAssetOwner(paranetServiceKAStorageContract, paranetServiceKATokenId) returns (bytes32) { + ) + external + onlyKnowledgeCollectionOwner(paranetServiceKAStorageContract, paranetServiceKATokenId) + returns (bytes32) + { ParanetServicesRegistry psr = paranetServicesRegistry; bytes32 paranetServiceId = keccak256( @@ -543,7 +547,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { string calldata paranetServiceName, string calldata paranetServiceDescription, address[] calldata paranetServiceAddresses - ) external onlyKnowledgeAssetOwner(paranetServiceKAStorageContract, paranetServiceKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetServiceKAStorageContract, paranetServiceKATokenId) { ParanetServicesRegistry psr = paranetServicesRegistry; bytes32 paranetServiceId = keccak256( @@ -571,7 +575,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { address paranetKAStorageContract, uint256 paranetKATokenId, address[] calldata minerAddresses - ) external onlyKnowledgeAssetOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; @@ -614,7 +618,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { address paranetKAStorageContract, uint256 paranetKATokenId, address[] calldata minerAddresses - ) external onlyKnowledgeAssetOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); @@ -691,7 +695,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { address paranetKAStorageContract, uint256 paranetKATokenId, address minerAddress - ) external onlyKnowledgeAssetOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); @@ -742,7 +746,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { address paranetKAStorageContract, uint256 paranetKATokenId, address minerAddress - ) external onlyKnowledgeAssetOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); @@ -843,83 +847,73 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // return knowledgeAssetTokenId; // } - // function submitKnowledgeAsset( - // address paranetKAStorageContract, - // uint256 paranetKATokenId, - // address knowledgeAssetStorageContract, - // uint256 knowledgeAssetTokenId - // ) external onlyKnowledgeAssetOwner(knowledgeAssetStorageContract, knowledgeAssetTokenId) { - // ParanetsRegistry pr = paranetsRegistry; - // bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); + function submitKnowledgeAsset( + address paranetKCStorageContract, + uint256 paranetKnowledgeCollectionId, + address knowledgeCollectionStorageContract, + uint256 knowledgeCollectionId + ) external onlyKnowledgeCollectionOwner(knowledgeCollectionStorageContract, knowledgeCollectionId) { + ParanetsRegistry pr = paranetsRegistry; + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionId)); - // if (!pr.paranetExists(paranetId)) { - // revert ParanetLib.ParanetDoesntExist(paranetKAStorageContract, paranetKATokenId); - // } + if (!pr.paranetExists(paranetId)) { + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKnowledgeCollectionId); + } - // ParanetLib.MinersAccessPolicy minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); + ParanetLib.MinersAccessPolicy minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); - // // Check if paranet is curated and if knowledge miner is whitelisted - // if ( - // minersAccessPolicy == ParanetLib.MinersAccessPolicy.CURATED && - // !pr.isKnowledgeMinerRegistered(paranetId, msg.sender) - // ) { - // revert ParanetLib.ParanetCuratedMinerDoesntExist(paranetId, msg.sender); - // } else if (minersAccessPolicy == ParanetLib.MinersAccessPolicy.OPEN) { - // // Check if Knowledge Miner has profile - // // If not: Create a profile - // if (!paranetKnowledgeMinersRegistry.knowledgeMinerExists(msg.sender)) { - // paranetKnowledgeMinersRegistry.registerKnowledgeMiner(msg.sender); - // } - - // // Check if Knowledge Miner is registered on paranet - // if (!pr.isKnowledgeMinerRegistered(paranetId, msg.sender)) { - // pr.addKnowledgeMiner(paranetId, msg.sender); - // } - // } + // Check if paranet is curated and if knowledge miner is whitelisted + if ( + minersAccessPolicy == ParanetLib.MinersAccessPolicy.CURATED && + !pr.isKnowledgeMinerRegistered(paranetId, msg.sender) + ) { + revert ParanetLib.ParanetCuratedMinerDoesntExist(paranetId, msg.sender); + } else if (minersAccessPolicy == ParanetLib.MinersAccessPolicy.OPEN) { + // Check if Knowledge Miner has profile + // If not: Create a profile + if (!paranetKnowledgeMinersRegistry.knowledgeMinerExists(msg.sender)) { + paranetKnowledgeMinersRegistry.registerKnowledgeMiner(msg.sender); + } - // if ( - // paranetKnowledgeAssetsRegistry.isParanetKnowledgeAsset( - // keccak256(abi.encodePacked(knowledgeAssetStorageContract, knowledgeAssetTokenId)) - // ) - // ) { - // revert ParanetLib.KnowledgeAssetIsAPartOfOtherParanet( - // knowledgeAssetStorageContract, - // knowledgeAssetTokenId, - // paranetKnowledgeAssetsRegistry.getParanetId( - // keccak256(abi.encodePacked(knowledgeAssetStorageContract, knowledgeAssetTokenId)) - // ) - // ); - // } + // Check if Knowledge Miner is registered on paranet + if (!pr.isKnowledgeMinerRegistered(paranetId, msg.sender)) { + pr.addKnowledgeMiner(paranetId, msg.sender); + } + } - // uint96 remainingTokenAmount = serviceAgreementStorageProxy.getAgreementTokenAmount( - // hashingProxy.callHashFunction( - // HASH_FUNCTION_ID, - // abi.encodePacked( - // address(contentAssetStorage), - // knowledgeAssetTokenId, - // abi.encodePacked( - // address(contentAssetStorage), - // contentAssetStorage.getAssertionIdByIndex(knowledgeAssetTokenId, 0) - // ) - // ) - // ) - // ); + if ( + paranetKnowledgeAssetsRegistry.isParanetKnowledgeAsset( + keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionId)) + ) + ) { + revert ParanetLib.KnowledgeAssetIsAPartOfOtherParanet( + knowledgeCollectionStorageContract, + knowledgeCollectionId, + paranetKnowledgeAssetsRegistry.getParanetId( + keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionId)) + ) + ); + } + // Is this correct way to do this + uint96 remainingTokenAmount = KnowledgeCollectionStorage(knowledgeCollectionStorageContract).getTokenAmount( + knowledgeCollectionId + ); - // _updateSubmittedKnowledgeAssetMetadata( - // paranetKAStorageContract, - // paranetKATokenId, - // knowledgeAssetStorageContract, - // knowledgeAssetTokenId, - // remainingTokenAmount - // ); + _updateSubmittedKnowledgeAssetMetadata( + paranetKCStorageContract, + paranetKnowledgeCollectionId, + knowledgeCollectionStorageContract, + knowledgeCollectionId, + remainingTokenAmount + ); - // emit KnowledgeAssetSubmittedToParanet( - // paranetKAStorageContract, - // paranetKATokenId, - // knowledgeAssetStorageContract, - // knowledgeAssetTokenId - // ); - // } + emit KnowledgeCollectionSubmittedToParanet( + paranetKCStorageContract, + paranetKnowledgeCollectionId, + knowledgeCollectionStorageContract, + knowledgeCollectionId + ); + } // function processUpdatedKnowledgeAssetStatesMetadata( // address paranetKAStorageContract, @@ -935,38 +929,38 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // ); // } - // function _updateSubmittedKnowledgeAssetMetadata( - // address paranetKAStorageContract, - // uint256 paranetKATokenId, - // address knowledgeAssetStorageContract, - // uint256 knowledgeAssetTokenId, - // uint96 tokenAmount - // ) internal { - // ParanetsRegistry pr = paranetsRegistry; - // ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; + function _updateSubmittedKnowledgeAssetMetadata( + address paranetKAStorageContract, + uint256 paranetKATokenId, + address knowledgeAssetStorageContract, + uint256 knowledgeAssetTokenId, + uint96 tokenAmount + ) internal { + ParanetsRegistry pr = paranetsRegistry; + ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; - // bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); - // bytes32 knowledgeAssetId = keccak256(abi.encodePacked(knowledgeAssetStorageContract, knowledgeAssetTokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); + bytes32 knowledgeAssetId = keccak256(abi.encodePacked(knowledgeAssetStorageContract, knowledgeAssetTokenId)); - // // Add Knowledge Asset to the KnowledgeAssetsRegistry - // paranetKnowledgeAssetsRegistry.addKnowledgeAsset( - // paranetId, - // knowledgeAssetStorageContract, - // knowledgeAssetTokenId, - // msg.sender - // ); + // Add Knowledge Asset to the KnowledgeAssetsRegistry + paranetKnowledgeAssetsRegistry.addKnowledgeAsset( + paranetId, + knowledgeAssetStorageContract, + knowledgeAssetTokenId, + msg.sender + ); - // // Add Knowledge Asset Metadata to the ParanetsRegistry - // pr.addKnowledgeAsset(paranetId, knowledgeAssetId); - // pr.addCumulativeKnowledgeValue(paranetId, tokenAmount); + // Add Knowledge Asset Metadata to the ParanetsRegistry + pr.addKnowledgeAsset(paranetId, knowledgeAssetId); + pr.addCumulativeKnowledgeValue(paranetId, tokenAmount); - // // Add Knowledge Asset Metadata to the KnowledgeMinersRegistry - // pkmr.addSubmittedKnowledgeAsset(msg.sender, paranetId, knowledgeAssetId); - // pkmr.addCumulativeTracSpent(msg.sender, paranetId, tokenAmount); - // pkmr.addUnrewardedTracSpent(msg.sender, paranetId, tokenAmount); - // pkmr.incrementTotalSubmittedKnowledgeAssetsCount(msg.sender); - // pkmr.addTotalTracSpent(msg.sender, tokenAmount); - // } + // Add Knowledge Asset Metadata to the KnowledgeMinersRegistry + pkmr.addSubmittedKnowledgeAsset(msg.sender, paranetId, knowledgeAssetId); + pkmr.addCumulativeTracSpent(msg.sender, paranetId, tokenAmount); + pkmr.addUnrewardedTracSpent(msg.sender, paranetId, tokenAmount); + pkmr.incrementTotalSubmittedKnowledgeAssetsCount(msg.sender); + pkmr.addTotalTracSpent(msg.sender, tokenAmount); + } // function _processUpdatedKnowledgeAssetStatesMetadata( // bytes32 paranetId, @@ -1075,8 +1069,8 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { knowledgeCollectionStorageContractAddress ); - uint256 minted = knowledgeCollectionStorage.knowledgeCollections[collectionId].minted; - uint256 burnedCount = knowledgeCollectionStorage.knowledgeCollections[collectionId].burned.length; + uint256 minted = knowledgeCollectionStorage.knowledgeCollections[knowledgeCollectionId].minted; + uint256 burnedCount = knowledgeCollectionStorage.knowledgeCollections[knowledgeCollectionId].burned.length; uint256 activeCount = minted - burnedCount; require(activeCount != 0, "No KAs in collection"); From 1587741e856dafdbc84100b2bf9423baadd8713d Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 14 Jan 2025 16:44:17 +0100 Subject: [PATCH 004/153] Rewrite mintet and burned count getting --- contracts/paranets/Paranet.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index a3bedd31..21c9f40c 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -1069,8 +1069,8 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { knowledgeCollectionStorageContractAddress ); - uint256 minted = knowledgeCollectionStorage.knowledgeCollections[knowledgeCollectionId].minted; - uint256 burnedCount = knowledgeCollectionStorage.knowledgeCollections[knowledgeCollectionId].burned.length; + uint256 minted = knowledgeCollectionStorage.getMinted(knowledgeCollectionId); + uint256 burnedCount = knowledgeCollectionStorage.getBurnedAmount(knowledgeCollectionId); uint256 activeCount = minted - burnedCount; require(activeCount != 0, "No KAs in collection"); From 742b51fe299af0395dd2f4b8bf47ced3e694f6a2 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 15 Jan 2025 13:56:24 +0100 Subject: [PATCH 005/153] change text --- contracts/paranets/Paranet.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 21c9f40c..ed33c5e3 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -882,7 +882,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { } if ( - paranetKnowledgeAssetsRegistry.isParanetKnowledgeAsset( + -paranetKnowledgeAssetsRegistry.isParanetKnowledgeAsset( keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionId)) ) ) { @@ -1072,7 +1072,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 minted = knowledgeCollectionStorage.getMinted(knowledgeCollectionId); uint256 burnedCount = knowledgeCollectionStorage.getBurnedAmount(knowledgeCollectionId); uint256 activeCount = minted - burnedCount; - require(activeCount != 0, "No KAs in collection"); + require(activeCount != 0, "No KAs in Collection"); uint256 startTokenId = (knowledgeCollectionId - 1) * knowledgeCollectionStorage.knowledgeCollectionMaxSize() + From a78a28cc46e82f1542b46331d15fc6f1bf49f198 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 15 Jan 2025 13:56:49 +0100 Subject: [PATCH 006/153] Fix typo --- contracts/paranets/Paranet.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index ed33c5e3..fe57d8fe 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -882,7 +882,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { } if ( - -paranetKnowledgeAssetsRegistry.isParanetKnowledgeAsset( + paranetKnowledgeAssetsRegistry.isParanetKnowledgeAsset( keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionId)) ) ) { From 958aaa2194b18f4fb8b8b51962d044c2bc78bb2b Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 15 Jan 2025 14:11:00 +0100 Subject: [PATCH 007/153] Update ParanetknowledgeCollectionIdRegistry --- abi/ParanetKnowledgeAssetsRegistry.json | 2 +- contracts/libraries/ParanetLib.sol | 6 +- .../ParanetKnowledgeAssetsRegistry.sol | 75 ++++++++++--------- 3 files changed, 42 insertions(+), 41 deletions(-) diff --git a/abi/ParanetKnowledgeAssetsRegistry.json b/abi/ParanetKnowledgeAssetsRegistry.json index 817138b6..92c68f87 100644 --- a/abi/ParanetKnowledgeAssetsRegistry.json +++ b/abi/ParanetKnowledgeAssetsRegistry.json @@ -68,7 +68,7 @@ "type": "bytes32" } ], - "name": "getKnowledgeAssetLocator", + "name": "getKnowledgeCollectionLocator", "outputs": [ { "internalType": "address", diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index 8c5c4c18..d2c0987b 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -135,9 +135,9 @@ library ParanetLib { uint256 totalSubmittedKnowledgeAssetsCount; } - struct KnowledgeAsset { - address knowledgeAssetStorageContract; - uint256 tokenId; + struct KnolwedgeCollection { + address knowledgeCollectionStorageContract; + uint256 knowledgeCollectionTokenId; address minerAddress; bytes32 paranetId; } diff --git a/contracts/storage/paranets/ParanetKnowledgeAssetsRegistry.sol b/contracts/storage/paranets/ParanetKnowledgeAssetsRegistry.sol index 2d6043fe..b831b3ca 100644 --- a/contracts/storage/paranets/ParanetKnowledgeAssetsRegistry.sol +++ b/contracts/storage/paranets/ParanetKnowledgeAssetsRegistry.sol @@ -7,12 +7,12 @@ import {INamed} from "../../interfaces/INamed.sol"; import {IVersioned} from "../../interfaces/IVersioned.sol"; import {ParanetLib} from "../../libraries/ParanetLib.sol"; -contract ParanetKnowledgeAssetsRegistry is INamed, IVersioned, HubDependent { - string private constant _NAME = "ParanetKnowledgeAssetsRegistry"; - string private constant _VERSION = "1.0.0"; +contract ParanetknowledgeCollectionIdRegistry is INamed, IVersioned, HubDependent { + string private constant _NAME = "ParanetknowledgeCollectionIdRegistry"; + string private constant _VERSION = "1.0.1"; // Knowledge Asset ID => Knowledge Asset On Paranet - mapping(bytes32 => ParanetLib.KnowledgeAsset) internal knowledgeAssets; + mapping(bytes32 => ParanetLib.KnolwedgeCollection) internal knolwedgeCollections; // solhint-disable-next-line no-empty-blocks constructor(address hubAddress) HubDependent(hubAddress) {} @@ -25,63 +25,64 @@ contract ParanetKnowledgeAssetsRegistry is INamed, IVersioned, HubDependent { return _VERSION; } - function addKnowledgeAsset( + function addKnowledgeCollection( bytes32 paranetId, - address knowledgeAssetStorageContract, - uint256 tokenId, + address knowledgeCollectionStorageContract, + uint256 knowledgeCollectionTokenId, address miner ) external onlyContracts returns (bytes32) { - knowledgeAssets[keccak256(abi.encodePacked(knowledgeAssetStorageContract, tokenId))] = ParanetLib - .KnowledgeAsset({ - knowledgeAssetStorageContract: knowledgeAssetStorageContract, - tokenId: tokenId, - minerAddress: miner, - paranetId: paranetId - }); - - return keccak256(abi.encodePacked(knowledgeAssetStorageContract, tokenId)); + knolwedgeCollections[ + keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)) + ] = ParanetLib.KnolwedgeCollection({ + knowledgeCollectionStorageContract: knowledgeCollectionStorageContract, + knowledgeCollectionTokenId: knowledgeCollectionTokenId, + minerAddress: miner, + paranetId: paranetId + }); + + return keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)); } - function removeKnowledgeAsset(bytes32 knowledgeAssetId) external onlyContracts { - delete knowledgeAssets[knowledgeAssetId]; + function removeKnowledgeCollection(bytes32 knowledgeCollectionId) external onlyContracts { + delete knolwedgeCollections[knowledgeCollectionId]; } - function isParanetKnowledgeAsset(bytes32 knowledgeAssetId) external view returns (bool) { + function isParanetKnowledgeCollection(bytes32 knolwedgeCollectionId) external view returns (bool) { return keccak256( abi.encodePacked( - knowledgeAssets[knowledgeAssetId].knowledgeAssetStorageContract, - knowledgeAssets[knowledgeAssetId].tokenId + knolwedgeCollections[knolwedgeCollectionId].knowledgeCollectionStorageContract, + knolwedgeCollections[knolwedgeCollectionId].knowledgeCollectionTokenId ) - ) == knowledgeAssetId; + ) == knolwedgeCollectionId; } - function getKnowledgeAssetObject( - bytes32 knowledgeAssetId - ) external view returns (ParanetLib.KnowledgeAsset memory) { - return knowledgeAssets[knowledgeAssetId]; + function getKnowledgeCollectionObject( + bytes32 knolwedgeCollectionId + ) external view returns (ParanetLib.KnolwedgeCollection memory) { + return knolwedgeCollections[knolwedgeCollectionId]; } - function getKnowledgeAssetLocator(bytes32 knowledgeAssetId) external view returns (address, uint256) { + function getKnowledgeCollectionLocator(bytes32 knowledgeCollectionId) external view returns (address, uint256) { return ( - knowledgeAssets[knowledgeAssetId].knowledgeAssetStorageContract, - knowledgeAssets[knowledgeAssetId].tokenId + knolwedgeCollections[knowledgeCollectionId].knowledgeCollectionStorageContract, + knolwedgeCollections[knowledgeCollectionId].knowledgeCollectionTokenId ); } - function getMinerAddress(bytes32 knowledgeAssetId) external view returns (address) { - return knowledgeAssets[knowledgeAssetId].minerAddress; + function getMinerAddress(bytes32 knowledgeCollectionId) external view returns (address) { + return knolwedgeCollections[knowledgeCollectionId].minerAddress; } - function setMinerAddress(bytes32 knowledgeAssetId, address minerAddress) external onlyContracts { - knowledgeAssets[knowledgeAssetId].minerAddress = minerAddress; + function setMinerAddress(bytes32 knowledgeCollectionId, address minerAddress) external onlyContracts { + knolwedgeCollections[knowledgeCollectionId].minerAddress = minerAddress; } - function getParanetId(bytes32 knowledgeAssetId) external view returns (bytes32) { - return knowledgeAssets[knowledgeAssetId].paranetId; + function getParanetId(bytes32 knowledgeCollectionId) external view returns (bytes32) { + return knolwedgeCollections[knowledgeCollectionId].paranetId; } - function setParanetId(bytes32 knowledgeAssetId, bytes32 paranetId) external onlyContracts { - knowledgeAssets[knowledgeAssetId].paranetId = paranetId; + function setParanetId(bytes32 knowledgeCollectionId, bytes32 paranetId) external onlyContracts { + knolwedgeCollections[knowledgeCollectionId].paranetId = paranetId; } } From 706d4550c416b94592f1a780be588f6c6a26dd50 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 15 Jan 2025 16:23:54 +0100 Subject: [PATCH 008/153] Rename asset to collection --- contracts/libraries/ParanetLib.sol | 66 +-- contracts/paranets/Paranet.sol | 464 +++++++++--------- .../paranets/ParanetIncentivesPoolFactory.sol | 45 +- .../paranets/ParanetNeuroIncentivesPool.sol | 7 +- .../ParanetKnowledgeMinersRegistry.sol | 168 +++---- .../paranets/ParanetServicesRegistry.sol | 28 +- ... ParanetknowledgeCollectionIdRegistry.sol} | 2 +- .../storage/paranets/ParanetsRegistry.sol | 133 ++--- 8 files changed, 467 insertions(+), 446 deletions(-) rename contracts/storage/paranets/{ParanetKnowledgeAssetsRegistry.sol => ParanetknowledgeCollectionIdRegistry.sol} (98%) diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index d2c0987b..65ac1251 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -11,8 +11,8 @@ library ParanetLib { uint16 constant MAX_CUMULATIVE_VOTERS_WEIGHT = 10 ** 4; struct UniversalAssetLocator { - address knowledgeAssetStorageContract; - uint256 tokenId; + address knowledgeCollectionStorageContract; + uint256 knolwedgeCollectionTokenId; } enum NodesAccessPolicy { @@ -25,7 +25,7 @@ library ParanetLib { CURATED } - enum KnowledgeAssetsAccessPolicy { + enum KnowledgeCollectionsAccessPolicy { OPEN } @@ -56,13 +56,13 @@ library ParanetLib { } struct Paranet { - address paranetKAStorageContract; - uint256 paranetKATokenId; + address paranetKCStorageContract; + uint256 paranetKCTokenId; string name; string description; NodesAccessPolicy nodesAccessPolicy; MinersAccessPolicy minersAccessPolicy; - KnowledgeAssetsAccessPolicy knowledgeAssetsAccessPolicy; + KnowledgeCollectionsAccessPolicy knowledgeCollectionsAccessPolicy; uint96 cumulativeKnowledgeValue; UnorderedNamedContractDynamicSet.Set incentivesPools; Node[] curatedNodes; @@ -84,13 +84,13 @@ library ParanetLib { } struct ParanetMetadata { - address paranetKAStorageContract; - uint256 paranetKATokenId; + address paranetKCStorageContract; + uint256 paranetKCTokenId; string name; string description; NodesAccessPolicy nodesAccessPolicy; MinersAccessPolicy minersAccessPolicy; - KnowledgeAssetsAccessPolicy knowledgeAssetsAccessPolicy; + KnowledgeCollectionsAccessPolicy knowledgeCollectonsAccessPolicy; uint96 cumulativeKnowledgeValue; } @@ -100,8 +100,8 @@ library ParanetLib { } struct ParanetService { - address paranetServiceKAStorageContract; - uint256 paranetServiceKATokenId; + address paranetServiceKCStorageContract; + uint256 paranetServiceKCTokenId; string name; string description; address[] paranetServiceAddresses; @@ -109,8 +109,8 @@ library ParanetLib { } struct ParanetServiceMetadata { - address paranetServiceKAStorageContract; - uint256 paranetServiceKATokenId; + address paranetServiceKCStorageContract; + uint256 paranetServiceKCTokenId; string name; string description; address[] paranetServiceAddresses; @@ -119,11 +119,11 @@ library ParanetLib { struct KnowledgeMiner { address addr; uint96 totalTracSpent; - uint256 totalSubmittedKnowledgeAssetsCount; - mapping(bytes32 => bytes32[]) submittedKnowledgeAssets; - mapping(bytes32 => mapping(bytes32 => uint256)) submittedKnowledgeAssetsIndexes; - mapping(bytes32 => UpdatingKnowledgeAssetState[]) updatingKnowledgeAssetStates; - mapping(bytes32 => mapping(bytes32 => uint256)) updatingKnowledgeAssetStateIndexes; + uint256 totalSubmittedKnowledgeCollectionCount; + mapping(bytes32 => bytes32[]) submittedKnowledgeCollections; + mapping(bytes32 => mapping(bytes32 => uint256)) submittedKnowledgeACollectionIndexes; + mapping(bytes32 => UpdatingKnowledgeCollectionState[]) updatingKnowledgeCollectionStates; + mapping(bytes32 => mapping(bytes32 => uint256)) updatingKnowledgeCollectionStateIndexes; mapping(bytes32 => uint96) cumulativeTracSpent; mapping(bytes32 => uint96) unrewardedTracSpent; mapping(bytes32 => uint256) cumulativeAwardedNeuro; @@ -132,7 +132,7 @@ library ParanetLib { struct KnowledgeMinerMetadata { address addr; uint96 totalTracSpent; - uint256 totalSubmittedKnowledgeAssetsCount; + uint256 totalSubmittedKnowledgeCollectionsCount; } struct KnolwedgeCollection { @@ -142,8 +142,8 @@ library ParanetLib { bytes32 paranetId; } - struct UpdatingKnowledgeAssetState { - address knowledgeAssetStorageContract; + struct UpdatingKnowledgeCollectionState { + address knowledgeCollectionStorageContract; uint256 tokenId; bytes32 assertionId; uint96 updateTokenAmount; @@ -171,7 +171,10 @@ library ParanetLib { uint256 claimedNeuro; } - error ParanetHasAlreadyBeenRegistered(address knowledgeAssetStorageAddress, uint256 tokenId); + error ParanetHasAlreadyBeenRegistered( + address knowledgeCollectionStorageAddress, + uint256 knowledgeCollectionTokenId + ); error InvalidParanetNodesAccessPolicy( ParanetLib.NodesAccessPolicy[] expectedAccessPolicies, ParanetLib.NodesAccessPolicy actualAccessPolicy @@ -197,17 +200,20 @@ library ParanetLib { ); error ParanetCuratedMinerAccessRequestDoesntExist(bytes32 paranetId, address miner); error ParanetIncentivesPoolAlreadyExists( - address knowledgeAssetStorageAddress, - uint256 tokenId, + address knowledgeCollectionStorageAddress, + uint256 knowledgeCollectionTokenId, string poolType, address poolAddress ); - error ParanetDoesntExist(address knowledgeAssetStorageAddress, uint256 tokenId); - error ParanetServiceHasAlreadyBeenRegistered(address knowledgeAssetStorageAddress, uint256 tokenId); - error ParanetServiceDoesntExist(address knowledgeAssetStorageAddress, uint256 tokenId); - error KnowledgeAssetIsAPartOfOtherParanet( - address paranetKnowledgeAssetStorageContract, - uint256 paranetTokenId, + error ParanetDoesntExist(address knowledgeCollectionStorageAddress, uint256 knowledgeCollectionTokenId); + error ParanetServiceHasAlreadyBeenRegistered( + address knowledgeCollectionStorageAddress, + uint256 knowledgeCollectionTokenId + ); + error ParanetServiceDoesntExist(address knowledgeCollectionStorageAddress, uint256 knowledgeCollectionTokenId); + error KnowledgeCollectionIsAPartOfOtherParanet( + address paranetKnowledgeCollectionStorageAddress, + uint256 paranetKnowledgeCollectionTokenId, bytes32 paranetId ); error NoRewardAvailable(bytes32 paranetId, address claimer); diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index fe57d8fe..2f2b61bc 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.20; -import {ParanetKnowledgeAssetsRegistry} from "../storage/paranets/ParanetKnowledgeAssetsRegistry.sol"; +import {ParanetKnowledgeCollectionsRegistry} from "../storage/paranets/ParanetKnowledgeCollectionRegistry.sol"; import {ParanetKnowledgeMinersRegistry} from "../storage/paranets/ParanetKnowledgeMinersRegistry.sol"; import {ParanetsRegistry} from "../storage/paranets/ParanetsRegistry.sol"; import {ParanetServicesRegistry} from "../storage/paranets/ParanetServicesRegistry.sol"; @@ -19,66 +19,66 @@ import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { event ParanetRegistered( - address indexed paranetKAStorageContract, - uint256 indexed paranetKATokenId, + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, string paranetName, string paranetDescription, ParanetLib.NodesAccessPolicy nodesAccessPolicy, ParanetLib.MinersAccessPolicy minersAccessPolicy, - ParanetLib.KnowledgeAssetsAccessPolicy knowledgeAssetsAccessPolicy + ParanetLib.KnowledgeCollectionsAccessPolicy knowledgeCollectionsAccessPolicy ); event ParanetCuratedNodeAdded( - address indexed paranetKAStorageContract, - uint256 indexed paranetKATokenId, + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, uint72 identityId ); event ParanetCuratedNodeRemoved( - address indexed paranetKAStorageContract, - uint256 indexed paranetKATokenId, + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, uint72 identityId ); event ParanetCuratedNodeJoinRequestCreated( - address indexed paranetKAStorageContract, - uint256 indexed paranetKATokenId, + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, uint72 identityId ); event ParanetCuratedNodeJoinRequestAccepted( - address indexed paranetKAStorageContract, - uint256 indexed paranetKATokenId, + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, uint72 identityId ); event ParanetCuratedNodeJoinRequestRejected( - address indexed paranetKAStorageContract, - uint256 indexed paranetKATokenId, + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, uint72 identityId ); event ParanetIncetivesPoolDeployed( - address indexed paranetKAStorageContract, - uint256 indexed paranetKATokenId, + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, ParanetLib.IncentivesPool incentivesPool ); event ParanetMetadataUpdated( - address indexed paranetKAStorageContract, - uint256 indexed paranetKATokenId, + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, string newParanetName, string newParanetDescription ); event ParanetServiceAdded( - address indexed paranetKAStorageContract, - uint256 indexed paranetKATokenId, - address indexed paranetServiceKAStorageContract, - uint256 paranetServiceKATokenId + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, + address indexed paranetServiceKCStorageContract, + uint256 paranetServiceKCTokenId ); event ParanetServiceRegistered( - address indexed paranetServiceKAStorageContract, - uint256 indexed paranetServiceKATokenId, + address indexed paranetServiceKCStorageContract, + uint256 indexed paranetServiceKCTokenId, string paranetServiceName, string paranetServiceDescription, address[] paranetServiceAddresses ); event ParanetServiceMetadataUpdated( - address indexed paranetServiceKAStorageContract, - uint256 indexed paranetServiceKATokenId, + address indexed paranetServiceKCStorageContract, + uint256 indexed paranetServiceKCTokenId, string newParanetServiceName, string newParanetServiceDescription, address[] newParanetServiceAddresses @@ -90,28 +90,28 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 knowledgeCollectionId ); event ParanetCuratedMinerAdded( - address indexed paranetKAStorageContract, - uint256 indexed paranetKATokenId, + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, address minerAddress ); event ParanetCuratedMinerRemoved( - address indexed paranetKAStorageContract, - uint256 indexed paranetKATokenId, + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, address minerAddress ); event ParanetCuratedMinerAccessRequestCreated( - address indexed paranetKAStorageContract, - uint256 indexed paranetKATokenId, + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, address minerAddress ); event ParanetCuratedMinerAccessRequestAccepted( - address indexed paranetKAStorageContract, - uint256 indexed paranetKATokenId, + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, address minerAddress ); event ParanetCuratedMinerAccessRequestRejected( - address indexed paranetKAStorageContract, - uint256 indexed paranetKATokenId, + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, address minerAddress ); @@ -121,15 +121,18 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ParanetsRegistry public paranetsRegistry; ParanetServicesRegistry public paranetServicesRegistry; ParanetKnowledgeMinersRegistry public paranetKnowledgeMinersRegistry; - ParanetKnowledgeAssetsRegistry public paranetKnowledgeAssetsRegistry; + ParanetKnowledgeCollectionsRegistry public paranetKnowledgeCollectionsRegistry; ProfileStorage public profileStorage; IdentityStorage public identityStorage; // solhint-disable-next-line no-empty-blocks constructor(address hubAddress) ContractStatus(hubAddress) {} - modifier onlyKnowledgeCollectionOwner(address knowledgeAssetStorageContract, uint256 knowledgeAssetTokenId) { - _checkKnowledgeCollectionOwner(knowledgeAssetStorageContract, knowledgeAssetTokenId); + modifier onlyKnowledgeCollectionOwner( + address knowledgeCollectionStorageContract, + uint256 knowledgeCollectionTokenId + ) { + _checkKnowledgeCollectionOwner(knowledgeCollectionStorageContract, knowledgeCollectionTokenId); _; } @@ -141,8 +144,8 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { paranetKnowledgeMinersRegistry = ParanetKnowledgeMinersRegistry( hub.getContractAddress("ParanetKnowledgeMinersRegistry") ); - paranetKnowledgeAssetsRegistry = ParanetKnowledgeAssetsRegistry( - hub.getContractAddress("ParanetKnowledgeAssetsRegistry") + paranetKnowledgeCollectionsRegistry = ParanetKnowledgeCollectionsRegistry( + hub.getContractAddress("ParanetKnowledgeCollectionsRegistry") ); } @@ -155,75 +158,75 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { } function registerParanet( - address paranetKAStorageContract, - uint256 paranetKATokenId, + address paranetKCStorageContract, + uint256 paranetKCTokenId, string calldata paranetName, string calldata paranetDescription, ParanetLib.NodesAccessPolicy nodesAccessPolicy, ParanetLib.MinersAccessPolicy minersAccessPolicy - ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) returns (bytes32) { + ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) returns (bytes32) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); if (pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetHasAlreadyBeenRegistered(paranetKAStorageContract, paranetKATokenId); + revert ParanetLib.ParanetHasAlreadyBeenRegistered(paranetKCStorageContract, paranetKCTokenId); } emit ParanetRegistered( - paranetKAStorageContract, - paranetKATokenId, + paranetKCStorageContract, + paranetKCTokenId, paranetName, paranetDescription, nodesAccessPolicy, minersAccessPolicy, - ParanetLib.KnowledgeAssetsAccessPolicy.OPEN + ParanetLib.KnowledgeCollectionsAccessPolicy.OPEN ); return pr.registerParanet( - paranetKAStorageContract, - paranetKATokenId, + paranetKCStorageContract, + paranetKCTokenId, paranetName, paranetDescription, nodesAccessPolicy, minersAccessPolicy, - ParanetLib.KnowledgeAssetsAccessPolicy.OPEN + ParanetLib.KnowledgeCollectionsAccessPolicy.OPEN ); } function updateParanetMetadata( - address paranetKAStorageContract, - uint256 paranetKATokenId, + address paranetKCStorageContract, + uint256 paranetKCTokenId, string calldata paranetName, string calldata paranetDescription - ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKAStorageContract, paranetKATokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); } pr.setName(paranetId, paranetName); pr.setDescription(paranetId, paranetDescription); - emit ParanetMetadataUpdated(paranetKAStorageContract, paranetKATokenId, paranetName, paranetDescription); + emit ParanetMetadataUpdated(paranetKCStorageContract, paranetKCTokenId, paranetName, paranetDescription); } function addParanetCuratedNodes( - address paranetKAStorageContract, - uint256 paranetKATokenId, + address paranetKCStorageContract, + uint256 paranetKCTokenId, uint72[] calldata identityIds - ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { ParanetsRegistry pr = paranetsRegistry; ProfileStorage ps = profileStorage; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKAStorageContract, paranetKATokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); } if (pr.getNodesAccessPolicy(paranetId) != ParanetLib.NodesAccessPolicy.CURATED) { @@ -247,7 +250,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pr.addCuratedNode(paranetId, identityIds[i], ps.getNodeId(identityIds[i])); - emit ParanetCuratedNodeAdded(paranetKAStorageContract, paranetKATokenId, identityIds[i]); + emit ParanetCuratedNodeAdded(paranetKCStorageContract, paranetKCTokenId, identityIds[i]); unchecked { i++; @@ -256,16 +259,16 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { } function removeParanetCuratedNodes( - address paranetKAStorageContract, - uint256 paranetKATokenId, + address paranetKCStorageContract, + uint256 paranetKCTokenId, uint72[] calldata identityIds - ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKAStorageContract, paranetKATokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); } if (pr.getNodesAccessPolicy(paranetId) != ParanetLib.NodesAccessPolicy.CURATED) { @@ -285,7 +288,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pr.removeCuratedNode(paranetId, identityIds[i]); - emit ParanetCuratedNodeRemoved(paranetKAStorageContract, paranetKATokenId, identityIds[i]); + emit ParanetCuratedNodeRemoved(paranetKCStorageContract, paranetKCTokenId, identityIds[i]); unchecked { i++; @@ -293,13 +296,13 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { } } - function requestParanetCuratedNodeAccess(address paranetKAStorageContract, uint256 paranetKATokenId) external { + function requestParanetCuratedNodeAccess(address paranetKCStorageContract, uint256 paranetKCTokenId) external { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKAStorageContract, paranetKATokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); } if (pr.getNodesAccessPolicy(paranetId) != ParanetLib.NodesAccessPolicy.CURATED) { @@ -336,20 +339,20 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pr.addNodeJoinRequest(paranetId, identityId, ParanetLib.RequestStatus.PENDING); - emit ParanetCuratedNodeJoinRequestCreated(paranetKAStorageContract, paranetKATokenId, identityId); + emit ParanetCuratedNodeJoinRequestCreated(paranetKCStorageContract, paranetKCTokenId, identityId); } function approveCuratedNode( - address paranetKAStorageContract, - uint256 paranetKATokenId, + address paranetKCStorageContract, + uint256 paranetKCTokenId, uint72 identityId - ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKAStorageContract, paranetKATokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); } if (pr.getNodesAccessPolicy(paranetId) != ParanetLib.NodesAccessPolicy.CURATED) { @@ -387,21 +390,21 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); pr.addCuratedNode(paranetId, identityId, profileStorage.getNodeId(identityId)); - emit ParanetCuratedNodeJoinRequestAccepted(paranetKAStorageContract, paranetKATokenId, identityId); - emit ParanetCuratedNodeAdded(paranetKAStorageContract, paranetKATokenId, identityId); + emit ParanetCuratedNodeJoinRequestAccepted(paranetKCStorageContract, paranetKCTokenId, identityId); + emit ParanetCuratedNodeAdded(paranetKCStorageContract, paranetKCTokenId, identityId); } function rejectCuratedNode( - address paranetKAStorageContract, - uint256 paranetKATokenId, + address paranetKCStorageContract, + uint256 paranetKCTokenId, uint72 identityId - ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKAStorageContract, paranetKATokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); } if (pr.getNodesAccessPolicy(paranetId) != ParanetLib.NodesAccessPolicy.CURATED) { @@ -438,58 +441,58 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ParanetLib.RequestStatus.REJECTED ); - emit ParanetCuratedNodeJoinRequestRejected(paranetKAStorageContract, paranetKATokenId, identityId); + emit ParanetCuratedNodeJoinRequestRejected(paranetKCStorageContract, paranetKCTokenId, identityId); } function addParanetServices( - address paranetKAStorageContract, - uint256 paranetKATokenId, - ParanetLib.UniversalAssetLocator[] calldata services - ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { + address paranetKCStorageContract, + uint256 paranetKCTokenId, + ParanetLib.UniversalCollectionLocator[] calldata services + ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { ParanetsRegistry pr = paranetsRegistry; ParanetServicesRegistry psr = paranetServicesRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKAStorageContract, paranetKATokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); } for (uint256 i; i < services.length; ) { if ( !psr.paranetServiceExists( - keccak256(abi.encodePacked(services[i].knowledgeAssetStorageContract, services[i].tokenId)) + keccak256(abi.encodePacked(services[i].knowledgeCollectionStorageContract, services[i].tokenId)) ) ) { revert ParanetLib.ParanetServiceDoesntExist( - services[i].knowledgeAssetStorageContract, + services[i].knowledgeCollectionStorageContract, services[i].tokenId ); } - _checkKnowledgeCollectionOwner(services[i].knowledgeAssetStorageContract, services[i].tokenId); + _checkKnowledgeCollectionOwner(services[i].knowledgeCollectionStorageContract, services[i].tokenId); if ( pr.isServiceImplemented( paranetId, - keccak256(abi.encodePacked(services[i].knowledgeAssetStorageContract, services[i].tokenId)) + keccak256(abi.encodePacked(services[i].knowledgeCollectionStorageContract, services[i].tokenId)) ) ) { revert ParanetLib.ParanetServiceHasAlreadyBeenAdded( paranetId, - keccak256(abi.encodePacked(services[i].knowledgeAssetStorageContract, services[i].tokenId)) + keccak256(abi.encodePacked(services[i].knowledgeCollectionStorageContract, services[i].tokenId)) ); } pr.addService( paranetId, - keccak256(abi.encodePacked(services[i].knowledgeAssetStorageContract, services[i].tokenId)) + keccak256(abi.encodePacked(services[i].knowledgeCollectionStorageContract, services[i].tokenId)) ); emit ParanetServiceAdded( - paranetKAStorageContract, - paranetKATokenId, - services[i].knowledgeAssetStorageContract, + paranetKCStorageContract, + paranetKCTokenId, + services[i].knowledgeCollectionStorageContract, services[i].tokenId ); @@ -500,32 +503,32 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { } function registerParanetService( - address paranetServiceKAStorageContract, - uint256 paranetServiceKATokenId, + address paranetServiceKCStorageContract, + uint256 paranetServiceKCTokenId, string calldata paranetServiceName, string calldata paranetServiceDescription, address[] calldata paranetServiceAddresses ) external - onlyKnowledgeCollectionOwner(paranetServiceKAStorageContract, paranetServiceKATokenId) + onlyKnowledgeCollectionOwner(paranetServiceKCStorageContract, paranetServiceKCTokenId) returns (bytes32) { ParanetServicesRegistry psr = paranetServicesRegistry; bytes32 paranetServiceId = keccak256( - abi.encodePacked(paranetServiceKAStorageContract, paranetServiceKATokenId) + abi.encodePacked(paranetServiceKCStorageContract, paranetServiceKCTokenId) ); if (psr.paranetServiceExists(paranetServiceId)) { revert ParanetLib.ParanetServiceHasAlreadyBeenRegistered( - paranetServiceKAStorageContract, - paranetServiceKATokenId + paranetServiceKCStorageContract, + paranetServiceKCTokenId ); } emit ParanetServiceRegistered( - paranetServiceKAStorageContract, - paranetServiceKATokenId, + paranetServiceKCStorageContract, + paranetServiceKCTokenId, paranetServiceName, paranetServiceDescription, paranetServiceAddresses @@ -533,8 +536,8 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { return psr.registerParanetService( - paranetServiceKAStorageContract, - paranetServiceKATokenId, + paranetServiceKCStorageContract, + paranetServiceKCTokenId, paranetServiceName, paranetServiceDescription, paranetServiceAddresses @@ -542,20 +545,20 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { } function updateParanetServiceMetadata( - address paranetServiceKAStorageContract, - uint256 paranetServiceKATokenId, + address paranetServiceKCStorageContract, + uint256 paranetServiceKCTokenId, string calldata paranetServiceName, string calldata paranetServiceDescription, address[] calldata paranetServiceAddresses - ) external onlyKnowledgeCollectionOwner(paranetServiceKAStorageContract, paranetServiceKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetServiceKCStorageContract, paranetServiceKCTokenId) { ParanetServicesRegistry psr = paranetServicesRegistry; bytes32 paranetServiceId = keccak256( - abi.encodePacked(paranetServiceKAStorageContract, paranetServiceKATokenId) + abi.encodePacked(paranetServiceKCStorageContract, paranetServiceKCTokenId) ); if (!psr.paranetServiceExists(paranetServiceId)) { - revert ParanetLib.ParanetServiceDoesntExist(paranetServiceKAStorageContract, paranetServiceKATokenId); + revert ParanetLib.ParanetServiceDoesntExist(paranetServiceKCStorageContract, paranetServiceKCTokenId); } psr.setName(paranetServiceId, paranetServiceName); @@ -563,8 +566,8 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { psr.setParanetServiceAddresses(paranetServiceId, paranetServiceAddresses); emit ParanetServiceMetadataUpdated( - paranetServiceKAStorageContract, - paranetServiceKATokenId, + paranetServiceKCStorageContract, + paranetServiceKCTokenId, paranetServiceName, paranetServiceDescription, paranetServiceAddresses @@ -572,17 +575,17 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { } function addParanetCuratedMiners( - address paranetKAStorageContract, - uint256 paranetKATokenId, + address paranetKCStorageContract, + uint256 paranetKCTokenId, address[] calldata minerAddresses - ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { ParanetsRegistry pr = paranetsRegistry; ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKAStorageContract, paranetKATokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); } if (pr.getMinersAccessPolicy(paranetId) != ParanetLib.MinersAccessPolicy.CURATED) { @@ -606,7 +609,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pr.addKnowledgeMiner(paranetId, minerAddresses[i]); - emit ParanetCuratedMinerAdded(paranetKAStorageContract, paranetKATokenId, minerAddresses[i]); + emit ParanetCuratedMinerAdded(paranetKCStorageContract, paranetKCTokenId, minerAddresses[i]); unchecked { i++; @@ -615,16 +618,16 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { } function removeParanetCuratedMiners( - address paranetKAStorageContract, - uint256 paranetKATokenId, + address paranetKCStorageContract, + uint256 paranetKCTokenId, address[] calldata minerAddresses - ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKAStorageContract, paranetKATokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); } if (pr.getMinersAccessPolicy(paranetId) != ParanetLib.MinersAccessPolicy.CURATED) { @@ -644,7 +647,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pr.removeKnowledgeMiner(paranetId, minerAddresses[i]); - emit ParanetCuratedMinerRemoved(paranetKAStorageContract, paranetKATokenId, minerAddresses[i]); + emit ParanetCuratedMinerRemoved(paranetKCStorageContract, paranetKCTokenId, minerAddresses[i]); unchecked { i++; @@ -652,13 +655,13 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { } } - function requestParanetCuratedMinerAccess(address paranetKAStorageContract, uint256 paranetKATokenId) external { + function requestParanetCuratedMinerAccess(address paranetKCStorageContract, uint256 paranetKCTokenId) external { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKAStorageContract, paranetKATokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); } if (pr.getMinersAccessPolicy(paranetId) != ParanetLib.MinersAccessPolicy.CURATED) { @@ -688,20 +691,20 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pr.addKnowledgeMinerAccessRequest(paranetId, msg.sender, ParanetLib.RequestStatus.PENDING); - emit ParanetCuratedMinerAccessRequestCreated(paranetKAStorageContract, paranetKATokenId, msg.sender); + emit ParanetCuratedMinerAccessRequestCreated(paranetKCStorageContract, paranetKCTokenId, msg.sender); } function approveCuratedMiner( - address paranetKAStorageContract, - uint256 paranetKATokenId, + address paranetKCStorageContract, + uint256 paranetKCTokenId, address minerAddress - ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKAStorageContract, paranetKATokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); } if (pr.getMinersAccessPolicy(paranetId) != ParanetLib.MinersAccessPolicy.CURATED) { @@ -738,21 +741,21 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); pr.addKnowledgeMiner(paranetId, minerAddress); - emit ParanetCuratedMinerAccessRequestAccepted(paranetKAStorageContract, paranetKATokenId, minerAddress); - emit ParanetCuratedMinerAdded(paranetKAStorageContract, paranetKATokenId, minerAddress); + emit ParanetCuratedMinerAccessRequestAccepted(paranetKCStorageContract, paranetKCTokenId, minerAddress); + emit ParanetCuratedMinerAdded(paranetKCStorageContract, paranetKCTokenId, minerAddress); } function rejectCuratedMiner( - address paranetKAStorageContract, - uint256 paranetKATokenId, + address paranetKCStorageContract, + uint256 paranetKCTokenId, address minerAddress - ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKAStorageContract, paranetKATokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); } if (pr.getMinersAccessPolicy(paranetId) != ParanetLib.MinersAccessPolicy.CURATED) { @@ -788,21 +791,21 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ParanetLib.RequestStatus.REJECTED ); - emit ParanetCuratedMinerAccessRequestRejected(paranetKAStorageContract, paranetKATokenId, minerAddress); + emit ParanetCuratedMinerAccessRequestRejected(paranetKCStorageContract, paranetKCTokenId, minerAddress); } - // function mintKnowledgeAsset( - // address paranetKAStorageContract, - // uint256 paranetKATokenId, - // ContentAssetStructs.AssetInputArgs calldata knowledgeAssetArgs + // function mintKnowledgeCollection( + // address paranetKCStorageContract, + // uint256 paranetKCTokenId, + // ContentCollectionStructs.CollectionInputArgs calldata knowledgeCollectionArgs // ) external returns (uint256) { // ParanetsRegistry pr = paranetsRegistry; - // bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); + // bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); // // Check if Paranet exists // // If not: Throw an error // if (!pr.paranetExists(paranetId)) { - // revert ParanetLib.ParanetDoesntExist(paranetKAStorageContract, paranetKATokenId); + // revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); // } // ParanetLib.MinersAccessPolicy minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); @@ -826,28 +829,28 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // } // } - // // Mint Knowledge Asset - // uint256 knowledgeAssetTokenId = contentAsset.createAssetFromContract(msg.sender, knowledgeAssetArgs); + // // Mint Knowledge Collection + // uint256 knowledgeCollectionTokenId = contentCollection.createCollectionFromContract(msg.sender, knowledgeCollectionArgs); - // _updateSubmittedKnowledgeAssetMetadata( - // paranetKAStorageContract, - // paranetKATokenId, - // address(contentAssetStorage), - // knowledgeAssetTokenId, - // knowledgeAssetArgs.tokenAmount + // _updateSubmittedKnowledgeCollectionMetadata( + // paranetKCStorageContract, + // paranetKCTokenId, + // address(contentCollectionStorage), + // knowledgeCollectionTokenId, + // knowledgeCollectionArgs.tokenAmount // ); - // emit KnowledgeAssetSubmittedToParanet( - // paranetKAStorageContract, - // paranetKATokenId, - // address(contentAssetStorage), - // knowledgeAssetTokenId + // emit KnowledgeCollectionSubmittedToParanet( + // paranetKCStorageContract, + // paranetKCTokenId, + // address(contentCollectionStorage), + // knowledgeCollectionTokenId // ); - // return knowledgeAssetTokenId; + // return knowledgeCollectionTokenId; // } - function submitKnowledgeAsset( + function submitKnowledgeCollection( address paranetKCStorageContract, uint256 paranetKnowledgeCollectionId, address knowledgeCollectionStorageContract, @@ -882,14 +885,14 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { } if ( - paranetKnowledgeAssetsRegistry.isParanetKnowledgeAsset( + paranetKnowledgeCollectionsRegistry.isParanetKnowledgeCollection( keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionId)) ) ) { - revert ParanetLib.KnowledgeAssetIsAPartOfOtherParanet( + revert ParanetLib.KnowledgeCollectionIsAPartOfOtherParanet( knowledgeCollectionStorageContract, knowledgeCollectionId, - paranetKnowledgeAssetsRegistry.getParanetId( + paranetKnowledgeCollectionsRegistry.getParanetId( keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionId)) ) ); @@ -899,7 +902,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { knowledgeCollectionId ); - _updateSubmittedKnowledgeAssetMetadata( + _updateSubmittedKnowledgeCollectionMetadata( paranetKCStorageContract, paranetKnowledgeCollectionId, knowledgeCollectionStorageContract, @@ -915,99 +918,101 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); } - // function processUpdatedKnowledgeAssetStatesMetadata( - // address paranetKAStorageContract, - // uint256 paranetKATokenId, + // function processUpdatedKnowledgeCollectionStatesMetadata( + // address paranetKCStorageContract, + // uint256 paranetKCTokenId, // uint256 start, // uint256 end // ) external { - // bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); + // bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); - // _processUpdatedKnowledgeAssetStatesMetadata( + // _processUpdatedKnowledgeCollectionStatesMetadata( // paranetId, - // paranetKnowledgeMinersRegistry.getUpdatingKnowledgeAssetStates(msg.sender, paranetId, start, end) + // paranetKnowledgeMinersRegistry.getUpdatingKnowledgeCollectionStates(msg.sender, paranetId, start, end) // ); // } - function _updateSubmittedKnowledgeAssetMetadata( - address paranetKAStorageContract, - uint256 paranetKATokenId, - address knowledgeAssetStorageContract, - uint256 knowledgeAssetTokenId, + function _updateSubmittedKnowledgeCollectionMetadata( + address paranetKCStorageContract, + uint256 paranetKCTokenId, + address knowledgeCollectionStorageContract, + uint256 knowledgeCollectionTokenId, uint96 tokenAmount ) internal { ParanetsRegistry pr = paranetsRegistry; ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)); - bytes32 knowledgeAssetId = keccak256(abi.encodePacked(knowledgeAssetStorageContract, knowledgeAssetTokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); + bytes32 knowledgeCollectionId = keccak256( + abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) + ); - // Add Knowledge Asset to the KnowledgeAssetsRegistry - paranetKnowledgeAssetsRegistry.addKnowledgeAsset( + // Add Knowledge Collection to the KnowledgeCollectionsRegistry + paranetKnowledgeCollectionsRegistry.addKnowledgeCollection( paranetId, - knowledgeAssetStorageContract, - knowledgeAssetTokenId, + knowledgeCollectionStorageContract, + knowledgeCollectionTokenId, msg.sender ); - // Add Knowledge Asset Metadata to the ParanetsRegistry - pr.addKnowledgeAsset(paranetId, knowledgeAssetId); + // Add Knowledge Collection Metadata to the ParanetsRegistry + pr.addKnowledgeCollection(paranetId, knowledgeCollectionId); pr.addCumulativeKnowledgeValue(paranetId, tokenAmount); - // Add Knowledge Asset Metadata to the KnowledgeMinersRegistry - pkmr.addSubmittedKnowledgeAsset(msg.sender, paranetId, knowledgeAssetId); + // Add Knowledge Collection Metadata to the KnowledgeMinersRegistry + pkmr.addSubmittedKnowledgeCollection(msg.sender, paranetId, knowledgeCollectionId); pkmr.addCumulativeTracSpent(msg.sender, paranetId, tokenAmount); pkmr.addUnrewardedTracSpent(msg.sender, paranetId, tokenAmount); - pkmr.incrementTotalSubmittedKnowledgeAssetsCount(msg.sender); + pkmr.incrementTotalSubmittedKnowledgeCollectionsCount(msg.sender); pkmr.addTotalTracSpent(msg.sender, tokenAmount); } - // function _processUpdatedKnowledgeAssetStatesMetadata( + // function _processUpdatedKnowledgeCollectionStatesMetadata( // bytes32 paranetId, - // ParanetLib.UpdatingKnowledgeAssetState[] memory updatingKnowledgeAssetStates + // ParanetLib.UpdatingKnowledgeCollectionState[] memory updatingKnowledgeCollectionStates // ) internal { // ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; // ParanetsRegistry pr = paranetsRegistry; - // ContentAsset ca = contentAsset; + // ContentCollection ca = contentCollection; - // for (uint i; i < updatingKnowledgeAssetStates.length; ) { - // _checkKnowledgeAssetOwner( - // updatingKnowledgeAssetStates[i].knowledgeAssetStorageContract, - // updatingKnowledgeAssetStates[i].tokenId + // for (uint i; i < updatingKnowledgeCollectionStates.length; ) { + // _checkKnowledgeCollectionOwner( + // updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract, + // updatingKnowledgeCollectionStates[i].tokenId // ); // bool continueOuterLoop = false; - // bytes32[] memory assertionIds = ContentAssetStorage( - // updatingKnowledgeAssetStates[i].knowledgeAssetStorageContract - // ).getAssertionIds(updatingKnowledgeAssetStates[i].tokenId); + // bytes32[] memory assertionIds = ContentCollectionStorage( + // updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract + // ).getAssertionIds(updatingKnowledgeCollectionStates[i].tokenId); // for (uint j = assertionIds.length; j > 0; ) { - // if (assertionIds[j - 1] == updatingKnowledgeAssetStates[i].assertionId) { - // // Add Knowledge Asset Token Amount Metadata to the ParanetsRegistry - // pr.addCumulativeKnowledgeValue(paranetId, updatingKnowledgeAssetStates[i].updateTokenAmount); + // if (assertionIds[j - 1] == updatingKnowledgeCollectionStates[i].assertionId) { + // // Add Knowledge Collection Token Amount Metadata to the ParanetsRegistry + // pr.addCumulativeKnowledgeValue(paranetId, updatingKnowledgeCollectionStates[i].updateTokenAmount); - // // Add Knowledge Asset Token Amount Metadata to the KnowledgeMinersRegistry + // // Add Knowledge Collection Token Amount Metadata to the KnowledgeMinersRegistry // pkmr.addCumulativeTracSpent( // msg.sender, // paranetId, - // updatingKnowledgeAssetStates[i].updateTokenAmount + // updatingKnowledgeCollectionStates[i].updateTokenAmount // ); // pkmr.addUnrewardedTracSpent( // msg.sender, // paranetId, - // updatingKnowledgeAssetStates[i].updateTokenAmount + // updatingKnowledgeCollectionStates[i].updateTokenAmount // ); - // pkmr.addTotalTracSpent(msg.sender, updatingKnowledgeAssetStates[i].updateTokenAmount); + // pkmr.addTotalTracSpent(msg.sender, updatingKnowledgeCollectionStates[i].updateTokenAmount); - // pkmr.removeUpdatingKnowledgeAssetState( + // pkmr.removeUpdatingKnowledgeCollectionState( // msg.sender, // paranetId, // keccak256( // abi.encodePacked( - // updatingKnowledgeAssetStates[i].knowledgeAssetStorageContract, - // updatingKnowledgeAssetStates[i].tokenId, - // updatingKnowledgeAssetStates[i].assertionId + // updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract, + // updatingKnowledgeCollectionStates[i].tokenId, + // updatingKnowledgeCollectionStates[i].assertionId // ) // ) // ); @@ -1029,15 +1034,15 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // continue; // } - // try ca.cancelAssetStateUpdateFromContract(updatingKnowledgeAssetStates[i].tokenId) { - // pkmr.removeUpdatingKnowledgeAssetState( + // try ca.cancelCollectionStateUpdateFromContract(updatingKnowledgeCollectionStates[i].tokenId) { + // pkmr.removeUpdatingKnowledgeCollectionState( // msg.sender, // paranetId, // keccak256( // abi.encodePacked( - // updatingKnowledgeAssetStates[i].knowledgeAssetStorageContract, - // updatingKnowledgeAssetStates[i].tokenId, - // updatingKnowledgeAssetStates[i].assertionId + // updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract, + // updatingKnowledgeCollectionStates[i].tokenId, + // updatingKnowledgeCollectionStates[i].assertionId // ) // ) // ); @@ -1047,23 +1052,22 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // } function _checkParanetOperator(bytes32 paranetId) internal view virtual { - (address paranetKAStorageContract, uint256 paranetKATokenId) = paranetsRegistry.getParanetKnowledgeAssetLocator( - paranetId - ); - _checkKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId); + (address paranetKCStorageContract, uint256 paranetKCTokenId) = paranetsRegistry + .getParanetKnowledgeCollectionLocator(paranetId); + _checkKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId); } function _checkParanetServiceOperator(bytes32 paranetServiceId) internal view virtual { - (address paranetServiceKAStorageContract, uint256 paranetServiceKATokenId) = paranetServicesRegistry - .getParanetServiceKnowledgeAssetLocator(paranetServiceId); - _checkKnowledgeCollectionOwner(paranetServiceKAStorageContract, paranetServiceKATokenId); + (address paranetServiceKCStorageContract, uint256 paranetServiceKCTokenId) = paranetServicesRegistry + .getParanetServiceKnowledgeCollectionLocator(paranetServiceId); + _checkKnowledgeCollectionOwner(paranetServiceKCStorageContract, paranetServiceKCTokenId); } function _checkKnowledgeCollectionOwner( address knowledgeCollectionStorageContractAddress, uint256 knowledgeCollectionId ) internal view virtual { - require(hub.isAssetStorage(knowledgeCollectionStorageContractAddress), "Given address isn't KA Storage"); + require(hub.isCollectionStorage(knowledgeCollectionStorageContractAddress), "Given address isn't KC Storage"); KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage( knowledgeCollectionStorageContractAddress @@ -1072,7 +1076,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 minted = knowledgeCollectionStorage.getMinted(knowledgeCollectionId); uint256 burnedCount = knowledgeCollectionStorage.getBurnedAmount(knowledgeCollectionId); uint256 activeCount = minted - burnedCount; - require(activeCount != 0, "No KAs in Collection"); + require(activeCount != 0, "No KCs in Collection"); uint256 startTokenId = (knowledgeCollectionId - 1) * knowledgeCollectionStorage.knowledgeCollectionMaxSize() + diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index 2708a19d..7ab7a301 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -14,8 +14,8 @@ import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IInitializable { event ParanetIncetivesPoolDeployed( - address indexed paranetKAStorageContract, - uint256 indexed paranetKATokenId, + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, ParanetLib.IncentivesPool incentivesPool ); @@ -27,8 +27,11 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn // solhint-disable-next-line no-empty-blocks constructor(address hubAddress) ContractStatus(hubAddress) {} - modifier onlyKnowledgeAssetOwner(address knowledgeAssetStorageContract, uint256 knowledgeAssetTokenId) { - _checkKnowledgeAssetOwner(knowledgeAssetStorageContract, knowledgeAssetTokenId); + modifier onlyKnowledgeCollectionOwner( + address knowledgeCollectionStorageContract, + uint256 knowledgeCollectionTokenId + ) { + _checkKnowledgeCollectionOwner(knowledgeCollectionStorageContract, knowledgeCollectionTokenId); _; } @@ -45,27 +48,27 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn } function deployNeuroIncentivesPool( - address paranetKAStorageContract, - uint256 paranetKATokenId, + address paranetKCStorageContract, + uint256 paranetKCTokenId, uint256 tracToNeuroEmissionMultiplier, uint16 paranetOperatorRewardPercentage, uint16 paranetIncentivizationProposalVotersRewardPercentage - ) external onlyKnowledgeAssetOwner(paranetKAStorageContract, paranetKATokenId) returns (address) { + ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) returns (address) { Hub h = hub; ParanetsRegistry pr = paranetsRegistry; if ( pr.hasIncentivesPoolByType( - keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)), + keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)), "Neuroweb" ) ) { revert ParanetLib.ParanetIncentivesPoolAlreadyExists( - paranetKAStorageContract, - paranetKATokenId, + paranetKCStorageContract, + paranetKCTokenId, "Neuroweb", pr.getIncentivesPoolAddress( - keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)), + keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)), "Neuroweb" ) ); @@ -75,35 +78,35 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn address(h), h.getContractAddress("ParanetsRegistry"), h.getContractAddress("ParanetKnowledgeMinersRegistry"), - keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)), + keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)), tracToNeuroEmissionMultiplier, paranetOperatorRewardPercentage, paranetIncentivizationProposalVotersRewardPercentage ); pr.setIncentivesPoolAddress( - keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)), + keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)), "Neuroweb", address(incentivesPool) ); emit ParanetIncetivesPoolDeployed( - paranetKAStorageContract, - paranetKATokenId, + paranetKCStorageContract, + paranetKCTokenId, ParanetLib.IncentivesPool({poolType: "Neuroweb", addr: address(incentivesPool)}) ); return address(incentivesPool); } - function _checkKnowledgeAssetOwner( - address knowledgeAssetStorageContract, - uint256 knowledgeAssetTokenId + function _checkKnowledgeCollectionOwner( + address knowledgeCollectionStorageContract, + uint256 knowledgeCollectionTokenId ) internal view virtual { - require(hub.isAssetStorage(knowledgeAssetStorageContract), "Given address isn't KA Storage"); + require(hub.isCollectionStorage(knowledgeCollectionStorageContract), "Given address isn't KC Storage"); require( - IERC721(knowledgeAssetStorageContract).ownerOf(knowledgeAssetTokenId) == msg.sender, - "Caller isn't the owner of the KA" + IERC721(knowledgeCollectionStorageContract).ownerOf(knowledgeCollectionTokenId) == msg.sender, + "Caller isn't the owner of the KC" ); } } diff --git a/contracts/paranets/ParanetNeuroIncentivesPool.sol b/contracts/paranets/ParanetNeuroIncentivesPool.sol index 43af89a5..aced232d 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPool.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPool.sol @@ -244,11 +244,10 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { } function isParanetOperator(address addr) public view returns (bool) { - (address paranetKAStorageContract, uint256 paranetKATokenId) = paranetsRegistry.getParanetKnowledgeAssetLocator( - parentParanetId - ); + (address paranetKCStorageContract, uint256 paranetKCTokenId) = paranetsRegistry + .getParanetKnowledgeCollectionLocator(parentParanetId); - return IERC721(paranetKAStorageContract).ownerOf(paranetKATokenId) == addr; + return IERC721(paranetKCStorageContract).ownerOf(paranetKCTokenId) == addr; } function isProposalVoter(address addr) public view returns (bool) { diff --git a/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol b/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol index adb8682d..fb18e3e0 100644 --- a/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol +++ b/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol @@ -56,7 +56,7 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { ParanetLib.KnowledgeMinerMetadata({ addr: addr, totalTracSpent: knowledgeMiners[addr].totalTracSpent, - totalSubmittedKnowledgeAssetsCount: knowledgeMiners[addr].totalSubmittedKnowledgeAssetsCount + totalSubmittedKnowledgeCollectionsCount: knowledgeMiners[addr].totalSubmittedKnowledgeCollectionsCount }); } @@ -76,71 +76,74 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { knowledgeMiners[miner].totalTracSpent -= subtractedTracSpent; } - function getTotalSubmittedKnowledgeAssetsCount(address miner) external view returns (uint256) { - return knowledgeMiners[miner].totalSubmittedKnowledgeAssetsCount; + function getTotalSubmittedKnowledgeCollectionsCount(address miner) external view returns (uint256) { + return knowledgeMiners[miner].totalSubmittedKnowledgeCollectionsCount; } - function setTotalSubmittedKnowledgeAssetsCount( + function setTotalSubmittedKnowledgeCollectionsCount( address miner, - uint256 totalSubmittedKnowledgeAssetsCount + uint256 totalSubmittedKnowledgeCollectionsCount ) external onlyContracts { - knowledgeMiners[miner].totalSubmittedKnowledgeAssetsCount = totalSubmittedKnowledgeAssetsCount; + knowledgeMiners[miner].totalSubmittedKnowledgeCollectionsCount = totalSubmittedKnowledgeCollectionsCount; } - function incrementTotalSubmittedKnowledgeAssetsCount(address miner) external onlyContracts { + function incrementTotalSubmittedKnowledgeCollectionsCount(address miner) external onlyContracts { unchecked { - knowledgeMiners[miner].totalSubmittedKnowledgeAssetsCount++; + knowledgeMiners[miner].totalSubmittedKnowledgeCollectionsCount++; } } - function decrementTotalSubmittedKnowledgeAssetsCount(address miner) external onlyContracts { + function decrementTotalSubmittedKnowledgeCollectionsCount(address miner) external onlyContracts { unchecked { - knowledgeMiners[miner].totalSubmittedKnowledgeAssetsCount--; + knowledgeMiners[miner].totalSubmittedKnowledgeCollectionsCount--; } } - function addSubmittedKnowledgeAsset( + function addSubmittedKnowledgeCollection( address miner, bytes32 paranetId, - bytes32 knowledgeAssetId + bytes32 knowledgeCollectionId ) external onlyContracts { - knowledgeMiners[miner].submittedKnowledgeAssetsIndexes[paranetId][knowledgeAssetId] = knowledgeMiners[miner] - .submittedKnowledgeAssets[paranetId] - .length; - knowledgeMiners[miner].submittedKnowledgeAssets[paranetId].push(knowledgeAssetId); + knowledgeMiners[miner].submittedKnowledgeCollectionsIndexes[paranetId][knowledgeCollectionId] = knowledgeMiners[ + miner + ].submittedKnowledgeCollections[paranetId].length; + knowledgeMiners[miner].submittedKnowledgeCollections[paranetId].push(knowledgeCollectionId); } - function removeSubmittedKnowledgeAsset( + function removeSubmittedKnowledgeCollection( address miner, bytes32 paranetId, - bytes32 knowledgeAssetId + bytes32 knowledgeCollectionId ) external onlyContracts { // 1. Move the last element to the slot of the element to remove - knowledgeMiners[miner].submittedKnowledgeAssets[paranetId][ - knowledgeMiners[miner].submittedKnowledgeAssetsIndexes[paranetId][knowledgeAssetId] - ] = knowledgeMiners[miner].submittedKnowledgeAssets[paranetId][ - knowledgeMiners[miner].submittedKnowledgeAssets[paranetId].length - 1 + knowledgeMiners[miner].submittedKnowlCollections[paranetId][ + knowledgeMiners[miner].submittedKnowledgeCollectionsIndexes[paranetId][knowledgeCollectionId] + ] = knowledgeMiners[miner].submittedKnowledgeCollections[paranetId][ + knowledgeMiners[miner].submittedKnowledgeCollections[paranetId].length - 1 ]; // 2. Update the index of the moved element - knowledgeMiners[miner].submittedKnowledgeAssetsIndexes[paranetId][ - knowledgeMiners[miner].submittedKnowledgeAssets[paranetId][ - knowledgeMiners[miner].submittedKnowledgeAssets[paranetId].length - 1 + knowledgeMiners[miner].submittedKnowledgeACollectionIndexes[paranetId][ + knowledgeMiners[miner].submittedKnowledgeCollections[paranetId][ + knowledgeMiners[miner].submittedKnowledgeCollections[paranetId].length - 1 ] - ] = knowledgeMiners[miner].submittedKnowledgeAssetsIndexes[paranetId][knowledgeAssetId]; + ] = knowledgeMiners[miner].submittedKnowledgeCollectionsIndexes[paranetId][knowledgeCollectionId]; // 3. Remove the last element from the array - knowledgeMiners[miner].submittedKnowledgeAssets[paranetId].pop(); + knowledgeMiners[miner].submittedKnowledgeCollections[paranetId].pop(); // 4. Delete the index of the removed element - delete knowledgeMiners[miner].submittedKnowledgeAssetsIndexes[paranetId][knowledgeAssetId]; + delete knowledgeMiners[miner].submittedKnowledgeCollectionsIndexes[paranetId][knowledgeCollectionId]; } - function getSubmittedKnowledgeAssets(address miner, bytes32 paranetId) external view returns (bytes32[] memory) { - return knowledgeMiners[miner].submittedKnowledgeAssets[paranetId]; + function getSubmittedKnowledgeCollections( + address miner, + bytes32 paranetId + ) external view returns (bytes32[] memory) { + return knowledgeMiners[miner].submittedKnowledgeCollections[paranetId]; } - function getSubmittedKnowledgeAssets( + function getSubmittedKnowledgeCollections( address miner, bytes32 paranetId, uint256 start, @@ -148,13 +151,13 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { ) external view returns (bytes32[] memory) { require(start <= end, "Start should be <= End"); require( - end <= knowledgeMiners[miner].submittedKnowledgeAssets[paranetId].length, + end <= knowledgeMiners[miner].submittedKnowledgeCollections[paranetId].length, "End should be <= length of Array" ); bytes32[] memory slice = new bytes32[](end - start); for (uint256 i; i < slice.length; ) { - slice[i] = knowledgeMiners[miner].submittedKnowledgeAssets[paranetId][i]; + slice[i] = knowledgeMiners[miner].submittedKnowledgeCollections[paranetId][i]; unchecked { i++; @@ -164,91 +167,92 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { return slice; } - function addUpdatingKnowledgeAssetState( + function addUpdatingKnowledgeCollectionState( address miner, bytes32 paranetId, - address knowledgeAssetStorageContract, - uint256 tokenId, - bytes32 assertionId, + address knowledgeCollectionStorageContract, + uint256 knowledgeCollectionTokenId, + bytes32 assertionId, // Should this be renamed uint96 updateTokenAmount ) external onlyContracts { - knowledgeMiners[miner].updatingKnowledgeAssetStateIndexes[paranetId][ - keccak256(abi.encodePacked(knowledgeAssetStorageContract, tokenId, assertionId)) - ] = knowledgeMiners[miner].updatingKnowledgeAssetStates[paranetId].length; - - knowledgeMiners[miner].updatingKnowledgeAssetStates[paranetId].push( - ParanetLib.UpdatingKnowledgeAssetState({ - knowledgeAssetStorageContract: knowledgeAssetStorageContract, - tokenId: tokenId, + knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][ + keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId, assertionId)) + ] = knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].length; + + knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].push( + ParanetLib.UpdatingKnowledgeCollectionState({ + knowledgeCollectionStorageContract: knowledgeCollectionStorageContract, + knowledgeCollectionTokenId: knowledgeCollectionTokenId, assertionId: assertionId, updateTokenAmount: updateTokenAmount }) ); } - function removeUpdatingKnowledgeAssetState( + // What to do with updating this has to be reworked + function removeUpdatingKnowledgeCollectionState( address miner, bytes32 paranetId, - bytes32 knowledgeAssetStateId + bytes32 knowledgeCollectionStateId ) external onlyContracts { // 1. Move the last element to the slot of the element to remove - knowledgeMiners[miner].updatingKnowledgeAssetStates[paranetId][ - knowledgeMiners[miner].updatingKnowledgeAssetStateIndexes[paranetId][knowledgeAssetStateId] - ] = knowledgeMiners[miner].updatingKnowledgeAssetStates[paranetId][ - knowledgeMiners[miner].updatingKnowledgeAssetStates[paranetId].length - 1 + knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId][ + knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId] + ] = knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId][ + knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].length - 1 ]; // 2. Update the index of the moved element - knowledgeMiners[miner].updatingKnowledgeAssetStateIndexes[paranetId][ + knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][ keccak256( abi.encodePacked( knowledgeMiners[miner] - .updatingKnowledgeAssetStates[paranetId][ - knowledgeMiners[miner].updatingKnowledgeAssetStates[paranetId].length - 1 - ].knowledgeAssetStorageContract, + .updatingKnowledgeCollectionStates[paranetId][ + knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].length - 1 + ].knowledgeCollectionStorageContract, knowledgeMiners[miner] - .updatingKnowledgeAssetStates[paranetId][ - knowledgeMiners[miner].updatingKnowledgeAssetStates[paranetId].length - 1 + .updatingKnowledgeCollectionStates[paranetId][ + knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].length - 1 ].tokenId, knowledgeMiners[miner] - .updatingKnowledgeAssetStates[paranetId][ - knowledgeMiners[miner].updatingKnowledgeAssetStates[paranetId].length - 1 + .updatingKnowledgeCollectionStates[paranetId][ + knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].length - 1 ].assertionId ) ) - ] = knowledgeMiners[miner].updatingKnowledgeAssetStateIndexes[paranetId][knowledgeAssetStateId]; + ] = knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId]; // 3. Remove the last element from the array - knowledgeMiners[miner].updatingKnowledgeAssetStates[paranetId].pop(); + knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].pop(); // 4. Delete the index of the removed element - delete knowledgeMiners[miner].updatingKnowledgeAssetStateIndexes[paranetId][knowledgeAssetStateId]; + delete knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId]; } - function getUpdatingKnowledgeAssetStates( + function getUpdatingKnowledgeCollectionStates( address miner, bytes32 paranetId - ) external view returns (ParanetLib.UpdatingKnowledgeAssetState[] memory) { - return knowledgeMiners[miner].updatingKnowledgeAssetStates[paranetId]; + ) external view returns (ParanetLib.UpdatingKnowledgeCollectionState[] memory) { + return knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId]; } - function getUpdatingKnowledgeAssetStates( + function getUpdatingKnowledgeCollectionStates( address miner, bytes32 paranetId, uint256 start, uint256 end - ) external view returns (ParanetLib.UpdatingKnowledgeAssetState[] memory) { + ) external view returns (ParanetLib.UpdatingKnowledgeCollectionState[] memory) { require(start <= end, "Start should be <= End"); require( - end <= knowledgeMiners[miner].updatingKnowledgeAssetStates[paranetId].length, + end <= knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].length, "End should be <= length of Array" ); - ParanetLib.UpdatingKnowledgeAssetState[] memory slice = new ParanetLib.UpdatingKnowledgeAssetState[]( + ParanetLib.UpdatingKnowledgeCollectionState[] memory slice = new ParanetLib.UpdatingKnowledgeCollectionState[]( end - start ); for (uint256 i; i < slice.length; ) { - slice[i] = knowledgeMiners[miner].updatingKnowledgeAssetStates[paranetId][i]; + slice[i] = knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId][i]; unchecked { i++; @@ -258,39 +262,39 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { return slice; } - function setUpdatingKnowledgeAssetUpdateTokenAmount( + function setUpdatingKnowledgeCollectionUpdateTokenAmount( address miner, bytes32 paranetId, - bytes32 knowledgeAssetStateId, + bytes32 knowledgeCollectionStateId, uint96 updateTokenAmount ) external onlyContracts { knowledgeMiners[miner] - .updatingKnowledgeAssetStates[paranetId][ - knowledgeMiners[miner].updatingKnowledgeAssetStateIndexes[paranetId][knowledgeAssetStateId] + .updatingKnowledgeCollectionStates[paranetId][ + knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId] ].updateTokenAmount = updateTokenAmount; } - function addUpdatingKnowledgeAssetUpdateTokenAmount( + function addUpdatingKnowledgeCollectionUpdateTokenAmount( address miner, bytes32 paranetId, - bytes32 knowledgeAssetStateId, + bytes32 knowledgeCollectionStateId, uint96 addedUpdateTokenAmount ) external onlyContracts { knowledgeMiners[miner] - .updatingKnowledgeAssetStates[paranetId][ - knowledgeMiners[miner].updatingKnowledgeAssetStateIndexes[paranetId][knowledgeAssetStateId] + .updatingKnowledgeCollectionStates[paranetId][ + knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId] ].updateTokenAmount += addedUpdateTokenAmount; } - function subUpdatingKnowledgeAssetUpdateTokenAmount( + function subUpdatingKnowledgeCollectionUpdateTokenAmount( address miner, bytes32 paranetId, - bytes32 knowledgeAssetStateId, + bytes32 knowledgeCollectionStateId, uint96 subtractedUpdateTokenAmount ) external onlyContracts { knowledgeMiners[miner] - .updatingKnowledgeAssetStates[paranetId][ - knowledgeMiners[miner].updatingKnowledgeAssetStateIndexes[paranetId][knowledgeAssetStateId] + .updatingKnowledgeCollectionStates[paranetId][ + knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId] ].updateTokenAmount -= subtractedUpdateTokenAmount; } diff --git a/contracts/storage/paranets/ParanetServicesRegistry.sol b/contracts/storage/paranets/ParanetServicesRegistry.sol index 60ff380a..1776d82b 100644 --- a/contracts/storage/paranets/ParanetServicesRegistry.sol +++ b/contracts/storage/paranets/ParanetServicesRegistry.sol @@ -26,18 +26,18 @@ contract ParanetServicesRegistry is INamed, IVersioned, HubDependent { } function registerParanetService( - address paranetServiceKAStorageContract, - uint256 paranetServiceKATokenId, + address paranetServiceKCStorageContract, + uint256 paranetServiceKCTokenId, string calldata paranetServiceName, string calldata paranetServiceDescription, address[] calldata paranetServiceAddresses ) external onlyContracts returns (bytes32) { ParanetLib.ParanetService storage paranetService = paranetServices[ - keccak256(abi.encodePacked(paranetServiceKAStorageContract, paranetServiceKATokenId)) + keccak256(abi.encodePacked(paranetServiceKCStorageContract, paranetServiceKCTokenId)) ]; - paranetService.paranetServiceKAStorageContract = paranetServiceKAStorageContract; - paranetService.paranetServiceKATokenId = paranetServiceKATokenId; + paranetService.paranetServiceKCStorageContract = paranetServiceKCStorageContract; + paranetService.paranetServiceKCTokenId = paranetServiceKCTokenId; paranetService.name = paranetServiceName; paranetService.description = paranetServiceDescription; paranetService.paranetServiceAddresses = paranetServiceAddresses; @@ -50,7 +50,7 @@ contract ParanetServicesRegistry is INamed, IVersioned, HubDependent { } } - return keccak256(abi.encodePacked(paranetServiceKAStorageContract, paranetServiceKATokenId)); + return keccak256(abi.encodePacked(paranetServiceKCStorageContract, paranetServiceKCTokenId)); } function deleteParanetService(bytes32 paranetServiceId) external onlyContracts { @@ -61,8 +61,8 @@ contract ParanetServicesRegistry is INamed, IVersioned, HubDependent { return keccak256( abi.encodePacked( - paranetServices[paranetServiceId].paranetServiceKAStorageContract, - paranetServices[paranetServiceId].paranetServiceKATokenId + paranetServices[paranetServiceId].paranetServiceKCStorageContract, + paranetServices[paranetServiceId].paranetServiceKCTokenId ) ) == paranetServiceId; } @@ -72,18 +72,20 @@ contract ParanetServicesRegistry is INamed, IVersioned, HubDependent { ) external view returns (ParanetLib.ParanetServiceMetadata memory) { return ParanetLib.ParanetServiceMetadata({ - paranetServiceKAStorageContract: paranetServices[paranetServiceId].paranetServiceKAStorageContract, - paranetServiceKATokenId: paranetServices[paranetServiceId].paranetServiceKATokenId, + paranetServiceKCStorageContract: paranetServices[paranetServiceId].paranetServiceKCStorageContract, + paranetServiceKCTokenId: paranetServices[paranetServiceId].paranetServiceKCTokenId, name: paranetServices[paranetServiceId].name, description: paranetServices[paranetServiceId].description, paranetServiceAddresses: paranetServices[paranetServiceId].paranetServiceAddresses }); } - function getParanetServiceKnowledgeAssetLocator(bytes32 paranetServiceId) external view returns (address, uint256) { + function getParanetServiceKnowledgeCollectionLocator( + bytes32 paranetServiceId + ) external view returns (address, uint256) { return ( - paranetServices[paranetServiceId].paranetServiceKAStorageContract, - paranetServices[paranetServiceId].paranetServiceKATokenId + paranetServices[paranetServiceId].paranetServiceKCStorageContract, + paranetServices[paranetServiceId].paranetServiceKCTokenId ); } diff --git a/contracts/storage/paranets/ParanetKnowledgeAssetsRegistry.sol b/contracts/storage/paranets/ParanetknowledgeCollectionIdRegistry.sol similarity index 98% rename from contracts/storage/paranets/ParanetKnowledgeAssetsRegistry.sol rename to contracts/storage/paranets/ParanetknowledgeCollectionIdRegistry.sol index b831b3ca..38dfddd9 100644 --- a/contracts/storage/paranets/ParanetKnowledgeAssetsRegistry.sol +++ b/contracts/storage/paranets/ParanetknowledgeCollectionIdRegistry.sol @@ -11,7 +11,7 @@ contract ParanetknowledgeCollectionIdRegistry is INamed, IVersioned, HubDependen string private constant _NAME = "ParanetknowledgeCollectionIdRegistry"; string private constant _VERSION = "1.0.1"; - // Knowledge Asset ID => Knowledge Asset On Paranet + // Knowledge Collection ID => Knowledge Collection On Paranet mapping(bytes32 => ParanetLib.KnolwedgeCollection) internal knolwedgeCollections; // solhint-disable-next-line no-empty-blocks diff --git a/contracts/storage/paranets/ParanetsRegistry.sol b/contracts/storage/paranets/ParanetsRegistry.sol index 558b5ae9..a1ea61da 100644 --- a/contracts/storage/paranets/ParanetsRegistry.sol +++ b/contracts/storage/paranets/ParanetsRegistry.sol @@ -29,27 +29,27 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { } function registerParanet( - address knowledgeAssetStorageContract, - uint256 tokenId, + address knowledgeCollectionStorageContract, + uint256 knowledgeCollectionTokenId, string calldata paranetName, string calldata paranetDescription, ParanetLib.NodesAccessPolicy nodesAccessPolicy, ParanetLib.MinersAccessPolicy minersAccessPolicy, - ParanetLib.KnowledgeAssetsAccessPolicy knowledgeAssetsAccessPolicy + ParanetLib.KnowledgeCollectionsAccessPolicy knowledgeColletionsAccessPolicy ) external onlyContracts returns (bytes32) { ParanetLib.Paranet storage paranet = paranets[ - keccak256(abi.encodePacked(knowledgeAssetStorageContract, tokenId)) + keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)) ]; - paranet.paranetKAStorageContract = knowledgeAssetStorageContract; - paranet.paranetKATokenId = tokenId; + paranet.paranetKCStorageContract = knowledgeCollectionStorageContract; + paranet.paranetKCTokenId = knowledgeCollectionTokenId; paranet.name = paranetName; paranet.description = paranetDescription; paranet.nodesAccessPolicy = nodesAccessPolicy; paranet.minersAccessPolicy = minersAccessPolicy; - paranet.knowledgeAssetsAccessPolicy = knowledgeAssetsAccessPolicy; + paranet.knowledgeCollectionsAccessPolicy = knowledgeColletionsAccessPolicy; - return keccak256(abi.encodePacked(knowledgeAssetStorageContract, tokenId)); + return keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)); } function deleteParanet(bytes32 paranetId) external onlyContracts { @@ -59,7 +59,7 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { function paranetExists(bytes32 paranetId) external view returns (bool) { return keccak256( - abi.encodePacked(paranets[paranetId].paranetKAStorageContract, paranets[paranetId].paranetKATokenId) + abi.encodePacked(paranets[paranetId].paranetKCStorageContract, paranets[paranetId].paranetKCTokenId) ) == paranetId; } @@ -68,19 +68,19 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { return ParanetLib.ParanetMetadata({ - paranetKAStorageContract: paranet.paranetKAStorageContract, - paranetKATokenId: paranet.paranetKATokenId, + paranetKCStorageContract: paranet.paranetKCStorageContract, + paranetKCTokenId: paranet.paranetKCTokenId, name: paranet.name, description: paranet.description, nodesAccessPolicy: paranet.nodesAccessPolicy, minersAccessPolicy: paranet.minersAccessPolicy, - knowledgeAssetsAccessPolicy: paranet.knowledgeAssetsAccessPolicy, + knowledgeCollectionsAccessPolicy: paranet.knowledgeCollectionsAccessPolicy, cumulativeKnowledgeValue: paranet.cumulativeKnowledgeValue }); } - function getParanetKnowledgeAssetLocator(bytes32 paranetId) external view returns (address, uint256) { - return (paranets[paranetId].paranetKAStorageContract, paranets[paranetId].paranetKATokenId); + function getParanetKnowledgeCollectionLocator(bytes32 paranetId) external view returns (address, uint256) { + return (paranets[paranetId].paranetKCStorageContract, paranets[paranetId].paranetKCTokenId); } function getName(bytes32 paranetId) external view returns (string memory) { @@ -121,17 +121,17 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { paranets[paranetId].minersAccessPolicy = minersAccessPolicy; } - function getKnowledgeAssetsAccessPolicy( + function getKnowledgeCollectionsAccessPolicy( bytes32 paranetId - ) external view returns (ParanetLib.KnowledgeAssetsAccessPolicy) { - return paranets[paranetId].knowledgeAssetsAccessPolicy; + ) external view returns (ParanetLib.KnowledgeCollectionsAccessPolicy) { + return paranets[paranetId].getKnowledgeCollectionsAccessPolicy; } - function setKnowledgeAssetsAccessPolicy( + function setKnowledgeCollectionsAccessPolicy( bytes32 paranetId, - ParanetLib.KnowledgeAssetsAccessPolicy knowledgeAssetsAccessPolicy + ParanetLib.KnowledgeCollectionAccessPolicy knowledgeCollectionAccessPolicy ) external onlyContracts { - paranets[paranetId].knowledgeAssetsAccessPolicy = knowledgeAssetsAccessPolicy; + paranets[paranetId].knowledgeCollectionAccessPolicy = knowledgeCollectionAccessPolicy; } function addNodeJoinRequest( @@ -408,95 +408,98 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { return paranets[paranetId].paranetKnowledgeMinerAccessRequests[miner].length; } - function addKnowledgeAsset(bytes32 paranetId, bytes32 knowledgeAssetId) external onlyContracts { - paranets[paranetId].registeredKnowledgeAssetsIndexes[knowledgeAssetId] = paranets[paranetId] - .knowledgeAssets + function addKnowledgeCollecton(bytes32 paranetId, bytes32 knowledgeCollectionId) external onlyContracts { + paranets[paranetId].registeredKnowledgeCollectionsIndexes[knowledgeCollectionId] = paranets[paranetId] + .knowledgeCollections .length; - paranets[paranetId].knowledgeAssets.push(knowledgeAssetId); + paranets[paranetId].knowledgeCollections.push(knowledgeCollectionId); } - function removeKnowledgeAsset(bytes32 paranetId, bytes32 knowledgeAssetId) external onlyContracts { - paranets[paranetId].knowledgeAssets[ - paranets[paranetId].registeredKnowledgeAssetsIndexes[knowledgeAssetId] - ] = paranets[paranetId].knowledgeAssets[paranets[paranetId].knowledgeAssets.length - 1]; - paranets[paranetId].registeredKnowledgeAssetsIndexes[ - paranets[paranetId].knowledgeAssets[paranets[paranetId].knowledgeAssets.length - 1] - ] = paranets[paranetId].registeredKnowledgeAssetsIndexes[knowledgeAssetId]; + function removeKnowledgeCollection(bytes32 paranetId, bytes32 knowledgeCollectionId) external onlyContracts { + paranets[paranetId].knowledgeCollections[ + paranets[paranetId].registeredKnowledgeCollectionsIndexes[knowledgeCollectionId] + ] = paranets[paranetId].knowledgeCollections[paranets[paranetId].knowledgeCollections.length - 1]; + paranets[paranetId].registeredKnowledgeCollectionsIndexes[ + paranets[paranetId].knowledgeCollections[paranets[paranetId].knowledgeCollections.length - 1] + ] = paranets[paranetId].registeredKnowledgeCollectionsIndexes[knowledgeCollectionId]; - delete paranets[paranetId].registeredKnowledgeAssetsIndexes[knowledgeAssetId]; - paranets[paranetId].knowledgeAssets.pop(); + delete paranets[paranetId].registeredKnowledgeCollectionsIndexes[knowledgeCollectionId]; + paranets[paranetId].knowledgeCollections.pop(); } - function getKnowledgeAssets(bytes32 paranetId) external view returns (bytes32[] memory) { - return paranets[paranetId].knowledgeAssets; + function getKnowledgeCollections(bytes32 paranetId) external view returns (bytes32[] memory) { + return paranets[paranetId].knowledgeCollections; } - function getKnowledgeAssetsWithPagination( + function getKnowledgeCollectionsWithPagination( bytes32 paranetId, uint256 offset, uint256 limit ) external view returns (bytes32[] memory) { - if (offset >= paranets[paranetId].knowledgeAssets.length) { + if (offset >= paranets[paranetId].knowledgeCollections.length) { return new bytes32[](0); } - uint256 fetchCount = (offset + limit > paranets[paranetId].knowledgeAssets.length) - ? paranets[paranetId].knowledgeAssets.length - offset + uint256 fetchCount = (offset + limit > paranets[paranetId].knowledgeCollections.length) + ? paranets[paranetId].knowledgeCollections.length - offset : limit; - bytes32[] memory knowledgeAssets = new bytes32[](fetchCount); + bytes32[] memory knowledgeCollections = new bytes32[](fetchCount); for (uint256 i = 0; i < fetchCount; i++) { - knowledgeAssets[i] = paranets[paranetId].knowledgeAssets[offset + i]; + knowledgeCollections[i] = paranets[paranetId].knowledgeCollections[offset + i]; } - return knowledgeAssets; + return knowledgeCollections; } - function getKnowledgeAssetsStartingFromKnowledgeAssetId( + function getKnowledgeCollectionsStartingFromKnowlCollectionId( bytes32 paranetId, - bytes32 knowledgeAssetId, + bytes32 knowledgeCollectionId, uint256 limit ) external view returns (bytes32[] memory) { if ( - paranets[paranetId].knowledgeAssets[ - paranets[paranetId].registeredKnowledgeAssetsIndexes[knowledgeAssetId] - ] != knowledgeAssetId + paranets[paranetId].knowledgeCollections[ + paranets[paranetId].registeredKnowledgeCollectionsIndexes[knowledgeCollectionId] + ] != knowledgeCollectionId ) { - revert("Invalid starting KA"); + revert("Invalid starting KC"); } if ( - paranets[paranetId].registeredKnowledgeAssetsIndexes[knowledgeAssetId] >= - paranets[paranetId].knowledgeAssets.length + paranets[paranetId].registeredKnowledgeCollectionsIndexes[knowledgeCollectionId] >= + paranets[paranetId].knowledgeCollections.length ) { return new bytes32[](0); } - uint256 fetchCount = (paranets[paranetId].registeredKnowledgeAssetsIndexes[knowledgeAssetId] + limit > - paranets[paranetId].knowledgeAssets.length) - ? paranets[paranetId].knowledgeAssets.length - - paranets[paranetId].registeredKnowledgeAssetsIndexes[knowledgeAssetId] + uint256 fetchCount = (paranets[paranetId].registeredKnowledgeCollectionsIndexes[knowledgeCollectionId] + limit > + paranets[paranetId].knowledgCollections.length) + ? paranets[paranetId].knowledgCollections.length - + paranets[paranetId].registeredKnowledgeCollectionsIndexes[knowledgeCollectionId] : limit; - bytes32[] memory knowledgeAssets = new bytes32[](fetchCount); + bytes32[] memory knowledgeCollections = new bytes32[](fetchCount); for (uint256 i = 0; i < fetchCount; i++) { - knowledgeAssets[i] = paranets[paranetId].knowledgeAssets[ - paranets[paranetId].registeredKnowledgeAssetsIndexes[knowledgeAssetId] + i + knowledgeCollections[i] = paranets[paranetId].knowledgeCollections[ + paranets[paranetId].registeredKnowledgeCollectionsIndexes[knowledgeCollectionId] + i ]; } - return knowledgeAssets; + return knowledgeCollections; } - function getKnowledgeAssetsCount(bytes32 paranetId) external view returns (uint256) { - return paranets[paranetId].knowledgeAssets.length; + function getKnowledgeCollectionsCount(bytes32 paranetId) external view returns (uint256) { + return paranets[paranetId].knowledgeCollections.length; } - function isKnowledgeAssetRegistered(bytes32 paranetId, bytes32 knowledgeAssetId) external view returns (bool) { - return (paranets[paranetId].knowledgeAssets.length != 0 && - paranets[paranetId].knowledgeAssets[ - paranets[paranetId].registeredKnowledgeAssetsIndexes[knowledgeAssetId] + function isKnowledgeCollectionRegistered( + bytes32 paranetId, + bytes32 knowledgeCollectionId + ) external view returns (bool) { + return (paranets[paranetId].knowledgeCollections.length != 0 && + paranets[paranetId].knowledgeCollections[ + paranets[paranetId].registeredKnowledgeCollectionsIndexes[knowledgeCollectionId] ] == - knowledgeAssetId); + knowledgeCollectionId); } } From e261fb85715a6bb6d287827aa6e6049271742e7e Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 15 Jan 2025 16:34:50 +0100 Subject: [PATCH 009/153] Rename fix typos --- contracts/libraries/ParanetLib.sol | 10 +++++----- contracts/paranets/Paranet.sol | 2 +- ...ry.sol => ParanetKnowledgeCollectionsRegistry.sol} | 2 +- contracts/storage/paranets/ParanetsRegistry.sol | 11 +++++------ 4 files changed, 12 insertions(+), 13 deletions(-) rename contracts/storage/paranets/{ParanetknowledgeCollectionIdRegistry.sol => ParanetKnowledgeCollectionsRegistry.sol} (97%) diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index 65ac1251..1c317e5a 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -10,7 +10,7 @@ library ParanetLib { uint16 constant PERCENTAGE_SCALING_FACTOR = 10 ** 4; uint16 constant MAX_CUMULATIVE_VOTERS_WEIGHT = 10 ** 4; - struct UniversalAssetLocator { + struct UniversalCollectionLocator { address knowledgeCollectionStorageContract; uint256 knolwedgeCollectionTokenId; } @@ -78,9 +78,9 @@ library ParanetLib { mapping(address => uint256) registeredKnowledgeMinersIndexes; // Knowledge Miner address => Requests Array mapping(address => ParanetKnowledgeMinerAccessRequest[]) paranetKnowledgeMinerAccessRequests; - bytes32[] knowledgeAssets; - // Knowledge Asset ID => Index in the array - mapping(bytes32 => uint256) registeredKnowledgeAssetsIndexes; + bytes32[] knowledgeCollections; + // Knowledge Collection ID => Index in the array + mapping(bytes32 => uint256) registeredKnowledgeCollectionsIndexes; } struct ParanetMetadata { @@ -90,7 +90,7 @@ library ParanetLib { string description; NodesAccessPolicy nodesAccessPolicy; MinersAccessPolicy minersAccessPolicy; - KnowledgeCollectionsAccessPolicy knowledgeCollectonsAccessPolicy; + KnowledgeCollectionsAccessPolicy knowledgeCollectionsAccessPolicy; uint96 cumulativeKnowledgeValue; } diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 2f2b61bc..0e51ae41 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.20; -import {ParanetKnowledgeCollectionsRegistry} from "../storage/paranets/ParanetKnowledgeCollectionRegistry.sol"; +import {ParanetKnowledgeCollectionsRegistry} from "../storage/paranets/ParanetKnowledgeCollectionsRegistry.sol"; import {ParanetKnowledgeMinersRegistry} from "../storage/paranets/ParanetKnowledgeMinersRegistry.sol"; import {ParanetsRegistry} from "../storage/paranets/ParanetsRegistry.sol"; import {ParanetServicesRegistry} from "../storage/paranets/ParanetServicesRegistry.sol"; diff --git a/contracts/storage/paranets/ParanetknowledgeCollectionIdRegistry.sol b/contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol similarity index 97% rename from contracts/storage/paranets/ParanetknowledgeCollectionIdRegistry.sol rename to contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol index 38dfddd9..ee1b934c 100644 --- a/contracts/storage/paranets/ParanetknowledgeCollectionIdRegistry.sol +++ b/contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol @@ -7,7 +7,7 @@ import {INamed} from "../../interfaces/INamed.sol"; import {IVersioned} from "../../interfaces/IVersioned.sol"; import {ParanetLib} from "../../libraries/ParanetLib.sol"; -contract ParanetknowledgeCollectionIdRegistry is INamed, IVersioned, HubDependent { +contract ParanetKnowledgeCollectionsRegistry is INamed, IVersioned, HubDependent { string private constant _NAME = "ParanetknowledgeCollectionIdRegistry"; string private constant _VERSION = "1.0.1"; diff --git a/contracts/storage/paranets/ParanetsRegistry.sol b/contracts/storage/paranets/ParanetsRegistry.sol index a1ea61da..829f1246 100644 --- a/contracts/storage/paranets/ParanetsRegistry.sol +++ b/contracts/storage/paranets/ParanetsRegistry.sol @@ -65,7 +65,6 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { function getParanetMetadata(bytes32 paranetId) external view returns (ParanetLib.ParanetMetadata memory) { ParanetLib.Paranet storage paranet = paranets[paranetId]; - return ParanetLib.ParanetMetadata({ paranetKCStorageContract: paranet.paranetKCStorageContract, @@ -124,14 +123,14 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { function getKnowledgeCollectionsAccessPolicy( bytes32 paranetId ) external view returns (ParanetLib.KnowledgeCollectionsAccessPolicy) { - return paranets[paranetId].getKnowledgeCollectionsAccessPolicy; + return paranets[paranetId].knowledgeCollectionsAccessPolicy; } function setKnowledgeCollectionsAccessPolicy( bytes32 paranetId, - ParanetLib.KnowledgeCollectionAccessPolicy knowledgeCollectionAccessPolicy + ParanetLib.KnowledgeCollectionsAccessPolicy knowledgeCollectionsAccessPolicy ) external onlyContracts { - paranets[paranetId].knowledgeCollectionAccessPolicy = knowledgeCollectionAccessPolicy; + paranets[paranetId].knowledgeCollectionsAccessPolicy = knowledgeCollectionsAccessPolicy; } function addNodeJoinRequest( @@ -473,8 +472,8 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { } uint256 fetchCount = (paranets[paranetId].registeredKnowledgeCollectionsIndexes[knowledgeCollectionId] + limit > - paranets[paranetId].knowledgCollections.length) - ? paranets[paranetId].knowledgCollections.length - + paranets[paranetId].knowledgeCollections.length) + ? paranets[paranetId].knowledgeCollections.length - paranets[paranetId].registeredKnowledgeCollectionsIndexes[knowledgeCollectionId] : limit; bytes32[] memory knowledgeCollections = new bytes32[](fetchCount); From 53826dc61721ff4ee8480d158dcb38e7ff3aacf7 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Thu, 16 Jan 2025 14:14:11 +0100 Subject: [PATCH 010/153] Fix renaming --- contracts/libraries/ParanetLib.sol | 10 +- contracts/paranets/Paranet.sol | 2 +- .../ParanetKnowledgeMinersRegistry.sol | 142 +++++++++--------- 3 files changed, 77 insertions(+), 77 deletions(-) diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index 1c317e5a..7ad7fc42 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -119,11 +119,11 @@ library ParanetLib { struct KnowledgeMiner { address addr; uint96 totalTracSpent; - uint256 totalSubmittedKnowledgeCollectionCount; + uint256 totalSubmittedKnowledgeCollectionsCount; mapping(bytes32 => bytes32[]) submittedKnowledgeCollections; - mapping(bytes32 => mapping(bytes32 => uint256)) submittedKnowledgeACollectionIndexes; - mapping(bytes32 => UpdatingKnowledgeCollectionState[]) updatingKnowledgeCollectionStates; - mapping(bytes32 => mapping(bytes32 => uint256)) updatingKnowledgeCollectionStateIndexes; + mapping(bytes32 => mapping(bytes32 => uint256)) submittedKnowledgeCollectionsIndexes; + mapping(bytes32 => UpdatingKnowledgeCollectionState[]) updatingKnowledgeCollectionsStates; + mapping(bytes32 => mapping(bytes32 => uint256)) updatingKnowledgeCollectionsStateIndexes; mapping(bytes32 => uint96) cumulativeTracSpent; mapping(bytes32 => uint96) unrewardedTracSpent; mapping(bytes32 => uint256) cumulativeAwardedNeuro; @@ -144,7 +144,7 @@ library ParanetLib { struct UpdatingKnowledgeCollectionState { address knowledgeCollectionStorageContract; - uint256 tokenId; + uint256 knowledgeCollectionTokenId; bytes32 assertionId; uint96 updateTokenAmount; } diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 0e51ae41..528fe918 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -1067,7 +1067,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { address knowledgeCollectionStorageContractAddress, uint256 knowledgeCollectionId ) internal view virtual { - require(hub.isCollectionStorage(knowledgeCollectionStorageContractAddress), "Given address isn't KC Storage"); + require(hub.isAssetStorage(knowledgeCollectionStorageContractAddress), "Given address isn't KC Storage"); KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage( knowledgeCollectionStorageContractAddress diff --git a/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol b/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol index fb18e3e0..06e7af57 100644 --- a/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol +++ b/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol @@ -116,14 +116,14 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { bytes32 knowledgeCollectionId ) external onlyContracts { // 1. Move the last element to the slot of the element to remove - knowledgeMiners[miner].submittedKnowlCollections[paranetId][ + knowledgeMiners[miner].submittedKnowledgeCollections[paranetId][ knowledgeMiners[miner].submittedKnowledgeCollectionsIndexes[paranetId][knowledgeCollectionId] ] = knowledgeMiners[miner].submittedKnowledgeCollections[paranetId][ knowledgeMiners[miner].submittedKnowledgeCollections[paranetId].length - 1 ]; // 2. Update the index of the moved element - knowledgeMiners[miner].submittedKnowledgeACollectionIndexes[paranetId][ + knowledgeMiners[miner].submittedKnowledgeCollectionsIndexes[paranetId][ knowledgeMiners[miner].submittedKnowledgeCollections[paranetId][ knowledgeMiners[miner].submittedKnowledgeCollections[paranetId].length - 1 ] @@ -175,11 +175,11 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { bytes32 assertionId, // Should this be renamed uint96 updateTokenAmount ) external onlyContracts { - knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][ + knowledgeMiners[miner].updatingKnowledgeCollectionsStateIndexes[paranetId][ keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId, assertionId)) - ] = knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].length; + ] = knowledgeMiners[miner].updatingKnowledgeCollectionsStates[paranetId].length; - knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].push( + knowledgeMiners[miner].updatingKnowledgeCollectionsStates[paranetId].push( ParanetLib.UpdatingKnowledgeCollectionState({ knowledgeCollectionStorageContract: knowledgeCollectionStorageContract, knowledgeCollectionTokenId: knowledgeCollectionTokenId, @@ -190,50 +190,50 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { } // What to do with updating this has to be reworked - function removeUpdatingKnowledgeCollectionState( - address miner, - bytes32 paranetId, - bytes32 knowledgeCollectionStateId - ) external onlyContracts { - // 1. Move the last element to the slot of the element to remove - knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId][ - knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId] - ] = knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId][ - knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].length - 1 - ]; - - // 2. Update the index of the moved element - knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][ - keccak256( - abi.encodePacked( - knowledgeMiners[miner] - .updatingKnowledgeCollectionStates[paranetId][ - knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].length - 1 - ].knowledgeCollectionStorageContract, - knowledgeMiners[miner] - .updatingKnowledgeCollectionStates[paranetId][ - knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].length - 1 - ].tokenId, - knowledgeMiners[miner] - .updatingKnowledgeCollectionStates[paranetId][ - knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].length - 1 - ].assertionId - ) - ) - ] = knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId]; - - // 3. Remove the last element from the array - knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].pop(); - - // 4. Delete the index of the removed element - delete knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId]; - } + // function removeUpdatingKnowledgeCollectionState( + // address miner, + // bytes32 paranetId, + // bytes32 knowledgeCollectionStateId + // ) external onlyContracts { + // // 1. Move the last element to the slot of the element to remove + // knowledgeMiners[miner].updatingKnowledgeCollectionsStates[paranetId][ + // knowledgeMiners[miner].updatingKnowledgeCollectionsStates[paranetId][knowledgeCollectionStateId] + // ] = knowledgeMiners[miner].updatingKnowledgeCollectionsStates[paranetId][ + // knowledgeMiners[miner].updatingKnowledgeCollectionsStates[paranetId].length - 1 + // ]; + + // // 2. Update the index of the moved element + // knowledgeMiners[miner].updatingKnowledgeCollectionsStateIndexes[paranetId][ + // keccak256( + // abi.encodePacked( + // knowledgeMiners[miner] + // .updatingKnowledgeCollectionStates[paranetId][ + // knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].length - 1 + // ].knowledgeCollectionStorageContract, + // knowledgeMiners[miner] + // .updatingKnowledgeCollectionStates[paranetId][ + // knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].length - 1 + // ].tokenId, + // knowledgeMiners[miner] + // .updatingKnowledgeCollectionStates[paranetId][ + // knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].length - 1 + // ].assertionId + // ) + // ) + // ] = knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId]; + + // // 3. Remove the last element from the array + // knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].pop(); + + // // 4. Delete the index of the removed element + // delete knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId]; + // } function getUpdatingKnowledgeCollectionStates( address miner, bytes32 paranetId ) external view returns (ParanetLib.UpdatingKnowledgeCollectionState[] memory) { - return knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId]; + return knowledgeMiners[miner].updatingKnowledgeCollectionsStates[paranetId]; } function getUpdatingKnowledgeCollectionStates( @@ -244,7 +244,7 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { ) external view returns (ParanetLib.UpdatingKnowledgeCollectionState[] memory) { require(start <= end, "Start should be <= End"); require( - end <= knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].length, + end <= knowledgeMiners[miner].updatingKnowledgeCollectionsStates[paranetId].length, "End should be <= length of Array" ); @@ -252,7 +252,7 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { end - start ); for (uint256 i; i < slice.length; ) { - slice[i] = knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId][i]; + slice[i] = knowledgeMiners[miner].updatingKnowledgeCollectionsStates[paranetId][i]; unchecked { i++; @@ -262,29 +262,29 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { return slice; } - function setUpdatingKnowledgeCollectionUpdateTokenAmount( - address miner, - bytes32 paranetId, - bytes32 knowledgeCollectionStateId, - uint96 updateTokenAmount - ) external onlyContracts { - knowledgeMiners[miner] - .updatingKnowledgeCollectionStates[paranetId][ - knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId] - ].updateTokenAmount = updateTokenAmount; - } - - function addUpdatingKnowledgeCollectionUpdateTokenAmount( - address miner, - bytes32 paranetId, - bytes32 knowledgeCollectionStateId, - uint96 addedUpdateTokenAmount - ) external onlyContracts { - knowledgeMiners[miner] - .updatingKnowledgeCollectionStates[paranetId][ - knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId] - ].updateTokenAmount += addedUpdateTokenAmount; - } + // function setUpdatingKnowledgeCollectionUpdateTokenAmount( + // address miner, + // bytes32 paranetId, + // bytes32 knowledgeCollectionStateId, + // uint96 updateTokenAmount + // ) external onlyContracts { + // knowledgeMiners[miner] + // .updatingKnowledgeCollectionsStates[paranetId][ + // knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId] + // ].updateTokenAmount = updateTokenAmount; + // } + + // function addUpdatingKnowledgeCollectionUpdateTokenAmount( + // address miner, + // bytes32 paranetId, + // bytes32 knowledgeCollectionStateId, + // uint96 addedUpdateTokenAmount + // ) external onlyContracts { + // knowledgeMiners[miner] + // .updatingKnowledgeCollectionsStates[paranetId][ + // knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId] + // ].updateTokenAmount += addedUpdateTokenAmount; + // } function subUpdatingKnowledgeCollectionUpdateTokenAmount( address miner, @@ -293,8 +293,8 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { uint96 subtractedUpdateTokenAmount ) external onlyContracts { knowledgeMiners[miner] - .updatingKnowledgeCollectionStates[paranetId][ - knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId] + .updatingKnowledgeCollectionsStates[paranetId][ + knowledgeMiners[miner].updatingKnowledgeCollectionsStateIndexes[paranetId][knowledgeCollectionStateId] ].updateTokenAmount -= subtractedUpdateTokenAmount; } From 3e7489470ee42f961044ca484a176261aa808c38 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Thu, 16 Jan 2025 14:50:52 +0100 Subject: [PATCH 011/153] fixes --- contracts/libraries/ParanetLib.sol | 2 +- contracts/paranets/Paranet.sol | 39 ++++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index 7ad7fc42..4a011a80 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -12,7 +12,7 @@ library ParanetLib { struct UniversalCollectionLocator { address knowledgeCollectionStorageContract; - uint256 knolwedgeCollectionTokenId; + uint256 knowledgeCollectionTokenId; } enum NodesAccessPolicy { diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 528fe918..d3392c11 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -461,39 +461,62 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { for (uint256 i; i < services.length; ) { if ( !psr.paranetServiceExists( - keccak256(abi.encodePacked(services[i].knowledgeCollectionStorageContract, services[i].tokenId)) + keccak256( + abi.encodePacked( + services[i].knowledgeCollectionStorageContract, + services[i].knowledgeCollectionTokenId + ) + ) ) ) { revert ParanetLib.ParanetServiceDoesntExist( services[i].knowledgeCollectionStorageContract, - services[i].tokenId + services[i].knowledgeCollectionTokenId ); } - _checkKnowledgeCollectionOwner(services[i].knowledgeCollectionStorageContract, services[i].tokenId); + _checkKnowledgeCollectionOwner( + services[i].knowledgeCollectionStorageContract, + services[i].knowledgeCollectionTokenId + ); if ( pr.isServiceImplemented( paranetId, - keccak256(abi.encodePacked(services[i].knowledgeCollectionStorageContract, services[i].tokenId)) + keccak256( + abi.encodePacked( + services[i].knowledgeCollectionStorageContract, + services[i].knowledgeCollectionTokenId + ) + ) ) ) { revert ParanetLib.ParanetServiceHasAlreadyBeenAdded( paranetId, - keccak256(abi.encodePacked(services[i].knowledgeCollectionStorageContract, services[i].tokenId)) + keccak256( + abi.encodePacked( + services[i].knowledgeCollectionStorageContract, + services[i].knowledgeCollectionTokenId + ) + ) ); } pr.addService( paranetId, - keccak256(abi.encodePacked(services[i].knowledgeCollectionStorageContract, services[i].tokenId)) + keccak256( + abi.encodePacked( + services[i].knowledgeCollectionStorageContract, + services[i].knowledgeCollectionTokenId + ) + ) ); emit ParanetServiceAdded( paranetKCStorageContract, paranetKCTokenId, services[i].knowledgeCollectionStorageContract, - services[i].tokenId + services[i].knowledgeCollectionTokenId ); unchecked { @@ -956,7 +979,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); // Add Knowledge Collection Metadata to the ParanetsRegistry - pr.addKnowledgeCollection(paranetId, knowledgeCollectionId); + pr.addKnowledgeCollection(paranetId, knowledgeCollectionId); // ??? pr.addCumulativeKnowledgeValue(paranetId, tokenAmount); // Add Knowledge Collection Metadata to the KnowledgeMinersRegistry From a214adf19e674e0b70028ada2746c98b138f3a04 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Thu, 16 Jan 2025 14:52:13 +0100 Subject: [PATCH 012/153] Fix _updateSubmittedKnowledgeCollectionMetadata --- contracts/paranets/Paranet.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index d3392c11..e9b1e11a 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -979,7 +979,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); // Add Knowledge Collection Metadata to the ParanetsRegistry - pr.addKnowledgeCollection(paranetId, knowledgeCollectionId); // ??? + pr.addKnowledgeCollecton(paranetId, knowledgeCollectionId); pr.addCumulativeKnowledgeValue(paranetId, tokenAmount); // Add Knowledge Collection Metadata to the KnowledgeMinersRegistry From f4cb2ebde063f099bba8d5259a8595402c7ed480 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 17 Jan 2025 12:31:23 +0100 Subject: [PATCH 013/153] Make paranet easier to count and discover --- .../storage/paranets/ParanetsRegistry.sol | 69 +++++++++++++++++-- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/contracts/storage/paranets/ParanetsRegistry.sol b/contracts/storage/paranets/ParanetsRegistry.sol index 829f1246..8917f7c8 100644 --- a/contracts/storage/paranets/ParanetsRegistry.sol +++ b/contracts/storage/paranets/ParanetsRegistry.sol @@ -12,8 +12,11 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { using UnorderedNamedContractDynamicSet for UnorderedNamedContractDynamicSet.Set; string private constant _NAME = "ParanetsRegistry"; - string private constant _VERSION = "1.0.0"; + string private constant _VERSION = "1.0.1"; + bytes32[] private paranetIds; + + mapping(bytes32 => uint256) internal paranetIdsMapping; // Paranet ID => Paranet Object mapping(bytes32 => ParanetLib.Paranet) internal paranets; @@ -37,9 +40,9 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { ParanetLib.MinersAccessPolicy minersAccessPolicy, ParanetLib.KnowledgeCollectionsAccessPolicy knowledgeColletionsAccessPolicy ) external onlyContracts returns (bytes32) { - ParanetLib.Paranet storage paranet = paranets[ - keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)) - ]; + bytes32 paranetId = keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)); + + ParanetLib.Paranet storage paranet = paranets[paranetId]; paranet.paranetKCStorageContract = knowledgeCollectionStorageContract; paranet.paranetKCTokenId = knowledgeCollectionTokenId; @@ -49,11 +52,25 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { paranet.minersAccessPolicy = minersAccessPolicy; paranet.knowledgeCollectionsAccessPolicy = knowledgeColletionsAccessPolicy; + paranetIds.push(paranetId); + paranetIdsMapping[paranetId] = paranetIds.length - 1; + return keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)); } function deleteParanet(bytes32 paranetId) external onlyContracts { delete paranets[paranetId]; + uint256 indexToRemove = paranetIdsMapping[paranetId]; + uint256 lastIndex = paranetIds.length - 1; + if (indexToRemove != lastIndex) { + bytes32 lastParanetId = paranetIds[lastIndex]; + + paranetIds[indexToRemove] = lastParanetId; + paranetIdsMapping[lastParanetId] = indexToRemove; + } + + paranetIds.pop(); + delete paranetIdsMapping[paranetId]; } function paranetExists(bytes32 paranetId) external view returns (bool) { @@ -501,4 +518,48 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { ] == knowledgeCollectionId); } + + function getParanetsCount() external view returns (uint256) { + return paranetIds.length; + } + + function getParanetIdAtIndex(uint256 index) external view returns (bytes32) { + require(index < paranetIds.length, "Index out of range"); + return paranetIds[index]; + } + + function getAllParanetIds() external view returns (bytes32[] memory) { + return paranetIds; + } + + function getParanetIds(uint256 offset, uint256 limit) external view returns (bytes32[] memory) { + // If offset is past the end of the array, return an empty array + if (offset >= paranetIds.length) { + return new bytes32[](0); + } + + uint256 end = offset + limit; + if (end > paranetIds.length) { + end = paranetIds.length; + } + + bytes32[] memory ids = new bytes32[](end - offset); + + for (uint256 i = offset; i < end; i++) { + ids[i - offset] = paranetIds[i]; + } + + return ids; + } + + function getParanetIdsMapping(bytes32 paranetId) external view returns (uint256) { + require( + keccak256( + abi.encodePacked(paranets[paranetId].paranetKCStorageContract, paranets[paranetId].paranetKCTokenId) + ) == paranetId, + "Paranet not found" + ); + + return paranetIdsMapping[paranetId]; + } } From d7f28e6bfebd0378626d915b34171781642e3924 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 17 Jan 2025 13:23:06 +0100 Subject: [PATCH 014/153] Add getKnowledgeCollectionLocators batch getter --- .../ParanetKnowledgeCollectionsRegistry.sol | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol b/contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol index ee1b934c..2afab151 100644 --- a/contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol +++ b/contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol @@ -70,6 +70,25 @@ contract ParanetKnowledgeCollectionsRegistry is INamed, IVersioned, HubDependent ); } + function getKnowledgeCollectionLocators( + bytes32[] calldata knowledgeCollectionIds + ) external view returns (ParanetLib.UniversalCollectionLocator[] memory) { + uint256 length = knowledgeCollectionIds.length; + + ParanetLib.UniversalCollectionLocator[] memory locators = new ParanetLib.UniversalCollectionLocator[](length); + + for (uint256 i = 0; i < length; i++) { + bytes32 id = knowledgeCollectionIds[i]; + + locators[i] = ParanetLib.UniversalCollectionLocator({ + knowledgeCollectionStorageContract: knolwedgeCollections[id].knowledgeCollectionStorageContract, + knowledgeCollectionTokenId: knolwedgeCollections[id].knowledgeCollectionTokenId + }); + } + + return locators; + } + function getMinerAddress(bytes32 knowledgeCollectionId) external view returns (address) { return knolwedgeCollections[knowledgeCollectionId].minerAddress; } From faf755168b223b930acd68fe168ea3889a9e764f Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 17 Jan 2025 13:53:02 +0100 Subject: [PATCH 015/153] getKnowledgeCollectionLocatorsWithPagination --- contracts/paranets/Paranet.sol | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index e9b1e11a..bc3bd186 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -817,6 +817,20 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { emit ParanetCuratedMinerAccessRequestRejected(paranetKCStorageContract, paranetKCTokenId, minerAddress); } + function getKnowledgeCollectionLocatorsWithPagination( + bytes32 paranetId, + uint256 offset, + uint256 limit + ) external view returns (ParanetLib.UniversalCollectionLocator[] memory) { + ParanetsRegistry pr = paranetsRegistry; + + bytes32[] memory knowledgeCollections = pr.getKnowledgeCollectionsWithPagination(paranetId, offset, limit); + + ParanetKnowledgeCollectionsRegistry pkcr = paranetKnowledgeCollectionsRegistry; + + return pkcr.getKnowledgeCollectionLocators(knowledgeCollections); + } + // function mintKnowledgeCollection( // address paranetKCStorageContract, // uint256 paranetKCTokenId, From 50aa4677edff036586f4c137bb439043ecdbf9d0 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 17 Jan 2025 14:29:07 +0100 Subject: [PATCH 016/153] Update ParanetNeuroIncentivesPool & ParanetIncentivesPoolFactory --- .../paranets/ParanetIncentivesPoolFactory.sol | 65 ++++++++++++------- .../paranets/ParanetNeuroIncentivesPool.sol | 23 ++++++- 2 files changed, 64 insertions(+), 24 deletions(-) diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index 7ab7a301..09c5c15c 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -5,6 +5,7 @@ pragma solidity ^0.8.20; import {Hub} from "../storage/Hub.sol"; import {ParanetsRegistry} from "../storage/paranets/ParanetsRegistry.sol"; import {ParanetNeuroIncentivesPool} from "./ParanetNeuroIncentivesPool.sol"; +import {KnowledgeCollectionStorage} from "../storage/KnowledgeCollectionStorage.sol"; import {ContractStatus} from "../abstract/ContractStatus.sol"; import {IInitializable} from "../interfaces/IInitializable.sol"; import {INamed} from "../interfaces/INamed.sol"; @@ -48,65 +49,85 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn } function deployNeuroIncentivesPool( - address paranetKCStorageContract, - uint256 paranetKCTokenId, + bool isNativeReward, + address paranetKAStorageContract, + uint256 paranetKATokenId, uint256 tracToNeuroEmissionMultiplier, uint16 paranetOperatorRewardPercentage, uint16 paranetIncentivizationProposalVotersRewardPercentage - ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) returns (address) { + ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) returns (address) { Hub h = hub; ParanetsRegistry pr = paranetsRegistry; + string memory incentivesPoolType = isNativeReward ? "Neuroweb" : "NeurowebERC20"; if ( pr.hasIncentivesPoolByType( - keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)), - "Neuroweb" + keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)), + incentivesPoolType ) ) { revert ParanetLib.ParanetIncentivesPoolAlreadyExists( - paranetKCStorageContract, - paranetKCTokenId, - "Neuroweb", + paranetKAStorageContract, + paranetKATokenId, + incentivesPoolType, pr.getIncentivesPoolAddress( - keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)), - "Neuroweb" + keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)), + incentivesPoolType ) ); } ParanetNeuroIncentivesPool incentivesPool = new ParanetNeuroIncentivesPool( address(h), + isNativeReward ? address(0) : h.getContractAddress(incentivesPoolType), h.getContractAddress("ParanetsRegistry"), h.getContractAddress("ParanetKnowledgeMinersRegistry"), - keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)), + keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)), tracToNeuroEmissionMultiplier, paranetOperatorRewardPercentage, paranetIncentivizationProposalVotersRewardPercentage ); pr.setIncentivesPoolAddress( - keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)), - "Neuroweb", + keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)), + incentivesPoolType, address(incentivesPool) ); emit ParanetIncetivesPoolDeployed( - paranetKCStorageContract, - paranetKCTokenId, - ParanetLib.IncentivesPool({poolType: "Neuroweb", addr: address(incentivesPool)}) + paranetKAStorageContract, + paranetKATokenId, + ParanetLib.IncentivesPool({poolType: incentivesPoolType, addr: address(incentivesPool)}) ); return address(incentivesPool); } function _checkKnowledgeCollectionOwner( - address knowledgeCollectionStorageContract, - uint256 knowledgeCollectionTokenId + address knowledgeCollectionStorageContractAddress, + uint256 knowledgeCollectionId ) internal view virtual { - require(hub.isCollectionStorage(knowledgeCollectionStorageContract), "Given address isn't KC Storage"); - require( - IERC721(knowledgeCollectionStorageContract).ownerOf(knowledgeCollectionTokenId) == msg.sender, - "Caller isn't the owner of the KC" + require(hub.isAssetStorage(knowledgeCollectionStorageContractAddress), "Given address isn't KC Storage"); + + KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage( + knowledgeCollectionStorageContractAddress + ); + + uint256 minted = knowledgeCollectionStorage.getMinted(knowledgeCollectionId); + uint256 burnedCount = knowledgeCollectionStorage.getBurnedAmount(knowledgeCollectionId); + uint256 activeCount = minted - burnedCount; + require(activeCount != 0, "No KCs in Collection"); + + uint256 startTokenId = (knowledgeCollectionId - 1) * + knowledgeCollectionStorage.knowledgeCollectionMaxSize() + + 1; // _startTokenId() + + uint256 ownedCountInRange = knowledgeCollectionStorage.balanceOf( + msg.sender, + startTokenId, + minted + burnedCount ); + + require(ownedCountInRange == activeCount, "Caller isn't the owner of the KC"); } } diff --git a/contracts/paranets/ParanetNeuroIncentivesPool.sol b/contracts/paranets/ParanetNeuroIncentivesPool.sol index aced232d..51303c2e 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPool.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPool.sol @@ -4,11 +4,12 @@ pragma solidity ^0.8.20; import {ParanetKnowledgeMinersRegistry} from "../storage/paranets/ParanetKnowledgeMinersRegistry.sol"; import {ParanetsRegistry} from "../storage/paranets/ParanetsRegistry.sol"; +import {KnowledgeCollectionStorage} from "../storage/KnowledgeCollectionStorage.sol"; import {Hub} from "../storage/Hub.sol"; import {INamed} from "../interfaces/INamed.sol"; import {IVersioned} from "../interfaces/IVersioned.sol"; import {ParanetLib} from "../libraries/ParanetLib.sol"; -import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; contract ParanetNeuroIncentivesPool is INamed, IVersioned { @@ -23,6 +24,7 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { string private constant _VERSION = "1.0.0"; Hub public hub; + IERC20 public token; ParanetsRegistry public paranetsRegistry; ParanetKnowledgeMinersRegistry public paranetKnowledgeMinersRegistry; @@ -66,6 +68,7 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { // solhint-disable-next-line no-empty-blocks constructor( address hubAddress, + address rewardTokenAddress, address paranetsRegistryAddress, address knowledgeMinersRegistryAddress, bytes32 paranetId, @@ -80,6 +83,9 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { ); hub = Hub(hubAddress); + if (rewardTokenAddress != address(0)) { + token = IERC20(rewardTokenAddress); + } paranetsRegistry = ParanetsRegistry(paranetsRegistryAddress); paranetKnowledgeMinersRegistry = ParanetKnowledgeMinersRegistry(knowledgeMinersRegistryAddress); @@ -247,7 +253,20 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { (address paranetKCStorageContract, uint256 paranetKCTokenId) = paranetsRegistry .getParanetKnowledgeCollectionLocator(parentParanetId); - return IERC721(paranetKCStorageContract).ownerOf(paranetKCTokenId) == addr; + KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage(paranetKCStorageContract); + + uint256 minted = knowledgeCollectionStorage.getMinted(paranetKCTokenId); + uint256 burnedCount = knowledgeCollectionStorage.getBurnedAmount(paranetKCTokenId); + uint256 activeCount = minted - burnedCount; + if (activeCount == 0) { + return false; + } + + uint256 startTokenId = (paranetKCTokenId - 1) * knowledgeCollectionStorage.knowledgeCollectionMaxSize() + 1; // _startTokenId() + + uint256 ownedCountInRange = knowledgeCollectionStorage.balanceOf(addr, startTokenId, minted + burnedCount); + + return ownedCountInRange == activeCount; } function isProposalVoter(address addr) public view returns (bool) { From c08c20c3703fee67d85536673efe0ae6133688f7 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 17 Jan 2025 14:29:32 +0100 Subject: [PATCH 017/153] Remove unused import from ParanetIncentivesPoolFactory --- contracts/paranets/ParanetIncentivesPoolFactory.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index 09c5c15c..b575bfdd 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -11,7 +11,6 @@ import {IInitializable} from "../interfaces/IInitializable.sol"; import {INamed} from "../interfaces/INamed.sol"; import {IVersioned} from "../interfaces/IVersioned.sol"; import {ParanetLib} from "../libraries/ParanetLib.sol"; -import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IInitializable { event ParanetIncetivesPoolDeployed( From c631a53a118ea32dc3acdcb7d78063d3bd7e3a0d Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 17 Jan 2025 14:40:37 +0100 Subject: [PATCH 018/153] Update KnowledgeCollection with paranet features --- contracts/KnowledgeCollection.sol | 61 +++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/contracts/KnowledgeCollection.sol b/contracts/KnowledgeCollection.sol index 1b0fd093..81de6dfd 100644 --- a/contracts/KnowledgeCollection.sol +++ b/contracts/KnowledgeCollection.sol @@ -10,6 +10,9 @@ import {KnowledgeCollectionStorage} from "./storage/KnowledgeCollectionStorage.s import {ShardingTableStorage} from "./storage/ShardingTableStorage.sol"; import {IdentityStorage} from "./storage/IdentityStorage.sol"; import {ParametersStorage} from "./storage/ParametersStorage.sol"; +import {ParanetKnowledgeCollectionsRegistry} from "./storage/paranets/ParanetKnowledgeCollectionsRegistry.sol"; +import {ParanetKnowledgeMinersRegistry} from "./storage/paranets/ParanetKnowledgeMinersRegistry.sol"; +import {ParanetsRegistry} from "./storage/paranets/ParanetsRegistry.sol"; import {KnowledgeCollectionLib} from "./libraries/KnowledgeCollectionLib.sol"; import {TokenLib} from "./libraries/TokenLib.sol"; import {IdentityLib} from "./libraries/IdentityLib.sol"; @@ -28,6 +31,9 @@ contract KnowledgeCollection is INamed, IVersioned, ContractStatus, IInitializab AskStorage public askStorage; EpochStorage public epochStorage; PaymasterManager public paymasterManager; + ParanetKnowledgeCollectionsRegistry public paranetKnowledgeCollectionsRegistry; + ParanetKnowledgeMinersRegistry public paranetKnowledgeMinersRegistry; + ParanetsRegistry public paranetsRegistry; KnowledgeCollectionStorage public knowledgeCollectionStorage; Chronos public chronos; ShardingTableStorage public shardingTableStorage; @@ -41,6 +47,13 @@ contract KnowledgeCollection is INamed, IVersioned, ContractStatus, IInitializab askStorage = AskStorage(hub.getContractAddress("AskStorage")); epochStorage = EpochStorage(hub.getContractAddress("EpochStorageV8")); paymasterManager = PaymasterManager(hub.getContractAddress("PaymasterManager")); + paranetKnowledgeCollectionsRegistry = ParanetKnowledgeCollectionsRegistry( + hub.getContractAddress("paranetKnowledgeCollectionsRegistry") + ); + paranetKnowledgeMinersRegistry = ParanetKnowledgeMinersRegistry( + hub.getContractAddress("ParanetKnowledgeMinersRegistry") + ); + paranetsRegistry = ParanetsRegistry(hub.getContractAddress("ParanetsRegistry")); knowledgeCollectionStorage = KnowledgeCollectionStorage( hub.getAssetStorageAddress("KnowledgeCollectionStorage") ); @@ -167,6 +180,22 @@ contract KnowledgeCollection is INamed, IVersioned, ContractStatus, IInitializab es.addEpochProducedKnowledgeValue(publisherNodeIdentityId, currentEpoch, tokenAmount); _addTokens(tokenAmount, paymaster); + + ParanetKnowledgeCollectionsRegistry pkar = paranetKnowledgeCollectionsRegistry; + + if (pkar.isParanetKnowledgeCollection(keccak256(abi.encodePacked(address(kcs), id)))) { + ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; + + bytes32 paranetId = pkar.getParanetId(keccak256(abi.encodePacked(address(kcs), id))); + + // Add Knowledge Asset Token Amount Metadata to the ParanetsRegistry + paranetsRegistry.addCumulativeKnowledgeValue(paranetId, tokenAmount); + + // Add Knowledge Asset Token Amount Metadata to the KnowledgeMinersRegistry + pkmr.addCumulativeTracSpent(msg.sender, paranetId, tokenAmount); + pkmr.addUnrewardedTracSpent(msg.sender, paranetId, tokenAmount); + pkmr.addTotalTracSpent(msg.sender, tokenAmount); + } } function extendKnowledgeCollectionLifetime( @@ -192,6 +221,22 @@ contract KnowledgeCollection is INamed, IVersioned, ContractStatus, IInitializab epochStorage.addTokensToEpochRange(1, endEpoch, endEpoch + epochs, tokenAmount); _addTokens(tokenAmount, paymaster); + + ParanetKnowledgeCollectionsRegistry pkar = paranetKnowledgeCollectionsRegistry; + + if (pkar.isParanetKnowledgeCollection(keccak256(abi.encodePacked(address(kcs), id)))) { + ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; + + bytes32 paranetId = pkar.getParanetId(keccak256(abi.encodePacked(address(kcs), id))); + + // Add Knowledge Asset Token Amount Metadata to the ParanetsRegistry + paranetsRegistry.addCumulativeKnowledgeValue(paranetId, tokenAmount); + + // Add Knowledge Asset Token Amount Metadata to the KnowledgeMinersRegistry + pkmr.addCumulativeTracSpent(msg.sender, paranetId, tokenAmount); + pkmr.addUnrewardedTracSpent(msg.sender, paranetId, tokenAmount); + pkmr.addTotalTracSpent(msg.sender, tokenAmount); + } } function increaseKnowledgeCollectionTokenAmount(uint256 id, uint96 tokenAmount, address paymaster) external { @@ -213,6 +258,22 @@ contract KnowledgeCollection is INamed, IVersioned, ContractStatus, IInitializab epochStorage.addTokensToEpochRange(1, currentEpoch, endEpoch, tokenAmount); _addTokens(tokenAmount, paymaster); + + ParanetKnowledgeCollectionsRegistry pkar = paranetKnowledgeCollectionsRegistry; + + if (pkar.isParanetKnowledgeCollection(keccak256(abi.encodePacked(address(kcs), id)))) { + ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; + + bytes32 paranetId = pkar.getParanetId(keccak256(abi.encodePacked(address(kcs), id))); + + // Add Knowledge Asset Token Amount Metadata to the ParanetsRegistry + paranetsRegistry.addCumulativeKnowledgeValue(paranetId, tokenAmount); + + // Add Knowledge Asset Token Amount Metadata to the KnowledgeMinersRegistry + pkmr.addCumulativeTracSpent(msg.sender, paranetId, tokenAmount); + pkmr.addUnrewardedTracSpent(msg.sender, paranetId, tokenAmount); + pkmr.addTotalTracSpent(msg.sender, tokenAmount); + } } function _verifySignatures( From 5d413c1a5a4d02be261bebdf0be159ec06cf8cf1 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 17 Jan 2025 16:09:36 +0100 Subject: [PATCH 019/153] Implement suggested changes from review --- contracts/KnowledgeCollection.sol | 17 ++++---- contracts/libraries/ParanetLib.sol | 2 +- .../paranets/ParanetIncentivesPoolFactory.sol | 22 +++++----- .../ParanetKnowledgeCollectionsRegistry.sol | 41 +++++++++---------- .../paranets/ParanetServicesRegistry.sol | 9 ++-- .../storage/paranets/ParanetsRegistry.sol | 2 +- 6 files changed, 45 insertions(+), 48 deletions(-) diff --git a/contracts/KnowledgeCollection.sol b/contracts/KnowledgeCollection.sol index 81de6dfd..4b9ebcfb 100644 --- a/contracts/KnowledgeCollection.sol +++ b/contracts/KnowledgeCollection.sol @@ -48,7 +48,7 @@ contract KnowledgeCollection is INamed, IVersioned, ContractStatus, IInitializab epochStorage = EpochStorage(hub.getContractAddress("EpochStorageV8")); paymasterManager = PaymasterManager(hub.getContractAddress("PaymasterManager")); paranetKnowledgeCollectionsRegistry = ParanetKnowledgeCollectionsRegistry( - hub.getContractAddress("paranetKnowledgeCollectionsRegistry") + hub.getContractAddress("ParanetKnowledgeCollectionsRegistry") ); paranetKnowledgeMinersRegistry = ParanetKnowledgeMinersRegistry( hub.getContractAddress("ParanetKnowledgeMinersRegistry") @@ -183,11 +183,10 @@ contract KnowledgeCollection is INamed, IVersioned, ContractStatus, IInitializab ParanetKnowledgeCollectionsRegistry pkar = paranetKnowledgeCollectionsRegistry; - if (pkar.isParanetKnowledgeCollection(keccak256(abi.encodePacked(address(kcs), id)))) { + bytes32 paranetId = pkar.getParanetId(keccak256(abi.encodePacked(address(kcs), id))); + if (pkar.isParanetKnowledgeCollection(paranetId)) { ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; - bytes32 paranetId = pkar.getParanetId(keccak256(abi.encodePacked(address(kcs), id))); - // Add Knowledge Asset Token Amount Metadata to the ParanetsRegistry paranetsRegistry.addCumulativeKnowledgeValue(paranetId, tokenAmount); @@ -224,11 +223,10 @@ contract KnowledgeCollection is INamed, IVersioned, ContractStatus, IInitializab ParanetKnowledgeCollectionsRegistry pkar = paranetKnowledgeCollectionsRegistry; - if (pkar.isParanetKnowledgeCollection(keccak256(abi.encodePacked(address(kcs), id)))) { + bytes32 paranetId = pkar.getParanetId(keccak256(abi.encodePacked(address(kcs), id))); + if (pkar.isParanetKnowledgeCollection(paranetId)) { ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; - bytes32 paranetId = pkar.getParanetId(keccak256(abi.encodePacked(address(kcs), id))); - // Add Knowledge Asset Token Amount Metadata to the ParanetsRegistry paranetsRegistry.addCumulativeKnowledgeValue(paranetId, tokenAmount); @@ -261,11 +259,10 @@ contract KnowledgeCollection is INamed, IVersioned, ContractStatus, IInitializab ParanetKnowledgeCollectionsRegistry pkar = paranetKnowledgeCollectionsRegistry; - if (pkar.isParanetKnowledgeCollection(keccak256(abi.encodePacked(address(kcs), id)))) { + bytes32 paranetId = pkar.getParanetId(keccak256(abi.encodePacked(address(kcs), id))); + if (pkar.isParanetKnowledgeCollection(paranetId)) { ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; - bytes32 paranetId = pkar.getParanetId(keccak256(abi.encodePacked(address(kcs), id))); - // Add Knowledge Asset Token Amount Metadata to the ParanetsRegistry paranetsRegistry.addCumulativeKnowledgeValue(paranetId, tokenAmount); diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index 4a011a80..be3843d4 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -135,7 +135,7 @@ library ParanetLib { uint256 totalSubmittedKnowledgeCollectionsCount; } - struct KnolwedgeCollection { + struct knowledgeCollection { address knowledgeCollectionStorageContract; uint256 knowledgeCollectionTokenId; address minerAddress; diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index b575bfdd..e460927b 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -49,28 +49,28 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn function deployNeuroIncentivesPool( bool isNativeReward, - address paranetKAStorageContract, - uint256 paranetKATokenId, + address paranetKCStorageContract, + uint256 paranetKCTokenId, uint256 tracToNeuroEmissionMultiplier, uint16 paranetOperatorRewardPercentage, uint16 paranetIncentivizationProposalVotersRewardPercentage - ) external onlyKnowledgeCollectionOwner(paranetKAStorageContract, paranetKATokenId) returns (address) { + ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) returns (address) { Hub h = hub; ParanetsRegistry pr = paranetsRegistry; string memory incentivesPoolType = isNativeReward ? "Neuroweb" : "NeurowebERC20"; if ( pr.hasIncentivesPoolByType( - keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)), + keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)), incentivesPoolType ) ) { revert ParanetLib.ParanetIncentivesPoolAlreadyExists( - paranetKAStorageContract, - paranetKATokenId, + paranetKCStorageContract, + paranetKCTokenId, incentivesPoolType, pr.getIncentivesPoolAddress( - keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)), + keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)), incentivesPoolType ) ); @@ -81,21 +81,21 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn isNativeReward ? address(0) : h.getContractAddress(incentivesPoolType), h.getContractAddress("ParanetsRegistry"), h.getContractAddress("ParanetKnowledgeMinersRegistry"), - keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)), + keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)), tracToNeuroEmissionMultiplier, paranetOperatorRewardPercentage, paranetIncentivizationProposalVotersRewardPercentage ); pr.setIncentivesPoolAddress( - keccak256(abi.encodePacked(paranetKAStorageContract, paranetKATokenId)), + keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)), incentivesPoolType, address(incentivesPool) ); emit ParanetIncetivesPoolDeployed( - paranetKAStorageContract, - paranetKATokenId, + paranetKCStorageContract, + paranetKCTokenId, ParanetLib.IncentivesPool({poolType: incentivesPoolType, addr: address(incentivesPool)}) ); diff --git a/contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol b/contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol index 2afab151..4f749d4c 100644 --- a/contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol +++ b/contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol @@ -12,7 +12,7 @@ contract ParanetKnowledgeCollectionsRegistry is INamed, IVersioned, HubDependent string private constant _VERSION = "1.0.1"; // Knowledge Collection ID => Knowledge Collection On Paranet - mapping(bytes32 => ParanetLib.KnolwedgeCollection) internal knolwedgeCollections; + mapping(bytes32 => ParanetLib.knowledgeCollection) internal knowledgeCollections; // solhint-disable-next-line no-empty-blocks constructor(address hubAddress) HubDependent(hubAddress) {} @@ -31,42 +31,41 @@ contract ParanetKnowledgeCollectionsRegistry is INamed, IVersioned, HubDependent uint256 knowledgeCollectionTokenId, address miner ) external onlyContracts returns (bytes32) { - knolwedgeCollections[ - keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)) - ] = ParanetLib.KnolwedgeCollection({ + bytes32 kcId = keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)); + knowledgeCollections[kcId] = ParanetLib.knowledgeCollection({ knowledgeCollectionStorageContract: knowledgeCollectionStorageContract, knowledgeCollectionTokenId: knowledgeCollectionTokenId, minerAddress: miner, paranetId: paranetId }); - return keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)); + return kcId; } function removeKnowledgeCollection(bytes32 knowledgeCollectionId) external onlyContracts { - delete knolwedgeCollections[knowledgeCollectionId]; + delete knowledgeCollections[knowledgeCollectionId]; } - function isParanetKnowledgeCollection(bytes32 knolwedgeCollectionId) external view returns (bool) { + function isParanetKnowledgeCollection(bytes32 knowledgeCollectionId) external view returns (bool) { return keccak256( abi.encodePacked( - knolwedgeCollections[knolwedgeCollectionId].knowledgeCollectionStorageContract, - knolwedgeCollections[knolwedgeCollectionId].knowledgeCollectionTokenId + knowledgeCollections[knowledgeCollectionId].knowledgeCollectionStorageContract, + knowledgeCollections[knowledgeCollectionId].knowledgeCollectionTokenId ) - ) == knolwedgeCollectionId; + ) == knowledgeCollectionId; } function getKnowledgeCollectionObject( - bytes32 knolwedgeCollectionId - ) external view returns (ParanetLib.KnolwedgeCollection memory) { - return knolwedgeCollections[knolwedgeCollectionId]; + bytes32 knowledgeCollectionId + ) external view returns (ParanetLib.knowledgeCollection memory) { + return knowledgeCollections[knowledgeCollectionId]; } function getKnowledgeCollectionLocator(bytes32 knowledgeCollectionId) external view returns (address, uint256) { return ( - knolwedgeCollections[knowledgeCollectionId].knowledgeCollectionStorageContract, - knolwedgeCollections[knowledgeCollectionId].knowledgeCollectionTokenId + knowledgeCollections[knowledgeCollectionId].knowledgeCollectionStorageContract, + knowledgeCollections[knowledgeCollectionId].knowledgeCollectionTokenId ); } @@ -81,8 +80,8 @@ contract ParanetKnowledgeCollectionsRegistry is INamed, IVersioned, HubDependent bytes32 id = knowledgeCollectionIds[i]; locators[i] = ParanetLib.UniversalCollectionLocator({ - knowledgeCollectionStorageContract: knolwedgeCollections[id].knowledgeCollectionStorageContract, - knowledgeCollectionTokenId: knolwedgeCollections[id].knowledgeCollectionTokenId + knowledgeCollectionStorageContract: knowledgeCollections[id].knowledgeCollectionStorageContract, + knowledgeCollectionTokenId: knowledgeCollections[id].knowledgeCollectionTokenId }); } @@ -90,18 +89,18 @@ contract ParanetKnowledgeCollectionsRegistry is INamed, IVersioned, HubDependent } function getMinerAddress(bytes32 knowledgeCollectionId) external view returns (address) { - return knolwedgeCollections[knowledgeCollectionId].minerAddress; + return knowledgeCollections[knowledgeCollectionId].minerAddress; } function setMinerAddress(bytes32 knowledgeCollectionId, address minerAddress) external onlyContracts { - knolwedgeCollections[knowledgeCollectionId].minerAddress = minerAddress; + knowledgeCollections[knowledgeCollectionId].minerAddress = minerAddress; } function getParanetId(bytes32 knowledgeCollectionId) external view returns (bytes32) { - return knolwedgeCollections[knowledgeCollectionId].paranetId; + return knowledgeCollections[knowledgeCollectionId].paranetId; } function setParanetId(bytes32 knowledgeCollectionId, bytes32 paranetId) external onlyContracts { - knolwedgeCollections[knowledgeCollectionId].paranetId = paranetId; + knowledgeCollections[knowledgeCollectionId].paranetId = paranetId; } } diff --git a/contracts/storage/paranets/ParanetServicesRegistry.sol b/contracts/storage/paranets/ParanetServicesRegistry.sol index 1776d82b..2088ddf6 100644 --- a/contracts/storage/paranets/ParanetServicesRegistry.sol +++ b/contracts/storage/paranets/ParanetServicesRegistry.sol @@ -32,9 +32,10 @@ contract ParanetServicesRegistry is INamed, IVersioned, HubDependent { string calldata paranetServiceDescription, address[] calldata paranetServiceAddresses ) external onlyContracts returns (bytes32) { - ParanetLib.ParanetService storage paranetService = paranetServices[ - keccak256(abi.encodePacked(paranetServiceKCStorageContract, paranetServiceKCTokenId)) - ]; + bytes32 paranetServiceId = keccak256( + abi.encodePacked(paranetServiceKCStorageContract, paranetServiceKCTokenId) + ); + ParanetLib.ParanetService storage paranetService = paranetServices[paranetServiceId]; paranetService.paranetServiceKCStorageContract = paranetServiceKCStorageContract; paranetService.paranetServiceKCTokenId = paranetServiceKCTokenId; @@ -50,7 +51,7 @@ contract ParanetServicesRegistry is INamed, IVersioned, HubDependent { } } - return keccak256(abi.encodePacked(paranetServiceKCStorageContract, paranetServiceKCTokenId)); + return paranetServiceId; } function deleteParanetService(bytes32 paranetServiceId) external onlyContracts { diff --git a/contracts/storage/paranets/ParanetsRegistry.sol b/contracts/storage/paranets/ParanetsRegistry.sol index 8917f7c8..8bcd2a5b 100644 --- a/contracts/storage/paranets/ParanetsRegistry.sol +++ b/contracts/storage/paranets/ParanetsRegistry.sol @@ -55,7 +55,7 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { paranetIds.push(paranetId); paranetIdsMapping[paranetId] = paranetIds.length - 1; - return keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)); + return paranetId; } function deleteParanet(bytes32 paranetId) external onlyContracts { From f6351fedabca5bd901a46c6e5c12b436a600a435 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 17 Jan 2025 16:18:27 +0100 Subject: [PATCH 020/153] Renamve ParanetLib.knowledgeCollection to ParanetLib.KnowledgeCollection --- contracts/libraries/ParanetLib.sol | 2 +- .../paranets/ParanetKnowledgeCollectionsRegistry.sol | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index be3843d4..dc4f8de5 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -135,7 +135,7 @@ library ParanetLib { uint256 totalSubmittedKnowledgeCollectionsCount; } - struct knowledgeCollection { + struct KnowledgeCollection { address knowledgeCollectionStorageContract; uint256 knowledgeCollectionTokenId; address minerAddress; diff --git a/contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol b/contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol index 4f749d4c..be289394 100644 --- a/contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol +++ b/contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol @@ -12,7 +12,7 @@ contract ParanetKnowledgeCollectionsRegistry is INamed, IVersioned, HubDependent string private constant _VERSION = "1.0.1"; // Knowledge Collection ID => Knowledge Collection On Paranet - mapping(bytes32 => ParanetLib.knowledgeCollection) internal knowledgeCollections; + mapping(bytes32 => ParanetLib.KnowledgeCollection) internal knowledgeCollections; // solhint-disable-next-line no-empty-blocks constructor(address hubAddress) HubDependent(hubAddress) {} @@ -32,7 +32,7 @@ contract ParanetKnowledgeCollectionsRegistry is INamed, IVersioned, HubDependent address miner ) external onlyContracts returns (bytes32) { bytes32 kcId = keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)); - knowledgeCollections[kcId] = ParanetLib.knowledgeCollection({ + knowledgeCollections[kcId] = ParanetLib.KnowledgeCollection({ knowledgeCollectionStorageContract: knowledgeCollectionStorageContract, knowledgeCollectionTokenId: knowledgeCollectionTokenId, minerAddress: miner, @@ -58,7 +58,7 @@ contract ParanetKnowledgeCollectionsRegistry is INamed, IVersioned, HubDependent function getKnowledgeCollectionObject( bytes32 knowledgeCollectionId - ) external view returns (ParanetLib.knowledgeCollection memory) { + ) external view returns (ParanetLib.KnowledgeCollection memory) { return knowledgeCollections[knowledgeCollectionId]; } From 502215656866c36c96ccd7e075202bbf374e828b Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 17 Jan 2025 16:46:48 +0100 Subject: [PATCH 021/153] wip --- contracts/libraries/ParanetLib.sol | 4 +- contracts/paranets/Paranet.sol | 187 +++++++++--------- .../ParanetKnowledgeMinersRegistry.sol | 14 +- 3 files changed, 103 insertions(+), 102 deletions(-) diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index dc4f8de5..1946a1b8 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -144,8 +144,8 @@ library ParanetLib { struct UpdatingKnowledgeCollectionState { address knowledgeCollectionStorageContract; - uint256 knowledgeCollectionTokenId; - bytes32 assertionId; + uint256 knowledgeCollectionId; + bytes32 merkleRoot; // Do we need this ? uint96 updateTokenAmount; } diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index bc3bd186..c0eccec0 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -908,6 +908,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { !pr.isKnowledgeMinerRegistered(paranetId, msg.sender) ) { revert ParanetLib.ParanetCuratedMinerDoesntExist(paranetId, msg.sender); + // Should this be done in both cases why would OPEN have separeted logic ??? } else if (minersAccessPolicy == ParanetLib.MinersAccessPolicy.OPEN) { // Check if Knowledge Miner has profile // If not: Create a profile @@ -934,7 +935,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ) ); } - // Is this correct way to do this + // Is this correct way to do this ??? uint96 remainingTokenAmount = KnowledgeCollectionStorage(knowledgeCollectionStorageContract).getTokenAmount( knowledgeCollectionId ); @@ -955,19 +956,19 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); } - // function processUpdatedKnowledgeCollectionStatesMetadata( - // address paranetKCStorageContract, - // uint256 paranetKCTokenId, - // uint256 start, - // uint256 end - // ) external { - // bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); + function processUpdatedKnowledgeCollectionStatesMetadata( + address paranetKCStorageContract, + uint256 paranetKCTokenId, + uint256 start, + uint256 end + ) external { + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); - // _processUpdatedKnowledgeCollectionStatesMetadata( - // paranetId, - // paranetKnowledgeMinersRegistry.getUpdatingKnowledgeCollectionStates(msg.sender, paranetId, start, end) - // ); - // } + _processUpdatedKnowledgeCollectionStatesMetadata( + paranetId, + paranetKnowledgeMinersRegistry.getUpdatingKnowledgeCollectionStates(msg.sender, paranetId, start, end) + ); + } function _updateSubmittedKnowledgeCollectionMetadata( address paranetKCStorageContract, @@ -1004,89 +1005,89 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pkmr.addTotalTracSpent(msg.sender, tokenAmount); } - // function _processUpdatedKnowledgeCollectionStatesMetadata( - // bytes32 paranetId, - // ParanetLib.UpdatingKnowledgeCollectionState[] memory updatingKnowledgeCollectionStates - // ) internal { - // ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; - // ParanetsRegistry pr = paranetsRegistry; - // ContentCollection ca = contentCollection; - - // for (uint i; i < updatingKnowledgeCollectionStates.length; ) { - // _checkKnowledgeCollectionOwner( - // updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract, - // updatingKnowledgeCollectionStates[i].tokenId - // ); - - // bool continueOuterLoop = false; - - // bytes32[] memory assertionIds = ContentCollectionStorage( - // updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract - // ).getAssertionIds(updatingKnowledgeCollectionStates[i].tokenId); - - // for (uint j = assertionIds.length; j > 0; ) { - // if (assertionIds[j - 1] == updatingKnowledgeCollectionStates[i].assertionId) { - // // Add Knowledge Collection Token Amount Metadata to the ParanetsRegistry - // pr.addCumulativeKnowledgeValue(paranetId, updatingKnowledgeCollectionStates[i].updateTokenAmount); - - // // Add Knowledge Collection Token Amount Metadata to the KnowledgeMinersRegistry - // pkmr.addCumulativeTracSpent( - // msg.sender, - // paranetId, - // updatingKnowledgeCollectionStates[i].updateTokenAmount - // ); - // pkmr.addUnrewardedTracSpent( - // msg.sender, - // paranetId, - // updatingKnowledgeCollectionStates[i].updateTokenAmount - // ); - // pkmr.addTotalTracSpent(msg.sender, updatingKnowledgeCollectionStates[i].updateTokenAmount); - - // pkmr.removeUpdatingKnowledgeCollectionState( - // msg.sender, - // paranetId, - // keccak256( - // abi.encodePacked( - // updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract, - // updatingKnowledgeCollectionStates[i].tokenId, - // updatingKnowledgeCollectionStates[i].assertionId - // ) - // ) - // ); - - // continueOuterLoop = true; - // break; - // } - - // unchecked { - // j--; - // } - // } + function _processUpdatedKnowledgeCollectionStatesMetadata( + bytes32 paranetId, + ParanetLib.UpdatingKnowledgeCollectionState[] memory updatingKnowledgeCollectionStates + ) internal { + ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; + ParanetsRegistry pr = paranetsRegistry; + ContentCollection ca = contentCollection; - // unchecked { - // i++; - // } + for (uint i; i < updatingKnowledgeCollectionStates.length; ) { + _checkKnowledgeCollectionOwner( + updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract, + updatingKnowledgeCollectionStates[i].tokenId + ); - // if (continueOuterLoop) { - // continue; - // } + bool continueOuterLoop = false; + + bytes32[] memory assertionIds = ContentCollectionStorage( + updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract + ).getAssertionIds(updatingKnowledgeCollectionStates[i].tokenId); + + for (uint j = assertionIds.length; j > 0; ) { + if (assertionIds[j - 1] == updatingKnowledgeCollectionStates[i].assertionId) { + // Add Knowledge Collection Token Amount Metadata to the ParanetsRegistry + pr.addCumulativeKnowledgeValue(paranetId, updatingKnowledgeCollectionStates[i].updateTokenAmount); + + // Add Knowledge Collection Token Amount Metadata to the KnowledgeMinersRegistry + pkmr.addCumulativeTracSpent( + msg.sender, + paranetId, + updatingKnowledgeCollectionStates[i].updateTokenAmount + ); + pkmr.addUnrewardedTracSpent( + msg.sender, + paranetId, + updatingKnowledgeCollectionStates[i].updateTokenAmount + ); + pkmr.addTotalTracSpent(msg.sender, updatingKnowledgeCollectionStates[i].updateTokenAmount); + + pkmr.removeUpdatingKnowledgeCollectionState( + msg.sender, + paranetId, + keccak256( + abi.encodePacked( + updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract, + updatingKnowledgeCollectionStates[i].tokenId, + updatingKnowledgeCollectionStates[i].assertionId + ) + ) + ); - // try ca.cancelCollectionStateUpdateFromContract(updatingKnowledgeCollectionStates[i].tokenId) { - // pkmr.removeUpdatingKnowledgeCollectionState( - // msg.sender, - // paranetId, - // keccak256( - // abi.encodePacked( - // updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract, - // updatingKnowledgeCollectionStates[i].tokenId, - // updatingKnowledgeCollectionStates[i].assertionId - // ) - // ) - // ); - // // solhint-disable-next-line no-empty-blocks - // } catch {} - // } - // } + continueOuterLoop = true; + break; + } + + unchecked { + j--; + } + } + + unchecked { + i++; + } + + if (continueOuterLoop) { + continue; + } + + try ca.cancelCollectionStateUpdateFromContract(updatingKnowledgeCollectionStates[i].tokenId) { + pkmr.removeUpdatingKnowledgeCollectionState( + msg.sender, + paranetId, + keccak256( + abi.encodePacked( + updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract, + updatingKnowledgeCollectionStates[i].tokenId, + updatingKnowledgeCollectionStates[i].assertionId + ) + ) + ); + // solhint-disable-next-line no-empty-blocks + } catch {} + } + } function _checkParanetOperator(bytes32 paranetId) internal view virtual { (address paranetKCStorageContract, uint256 paranetKCTokenId) = paranetsRegistry diff --git a/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol b/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol index 06e7af57..bea36379 100644 --- a/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol +++ b/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol @@ -171,25 +171,25 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { address miner, bytes32 paranetId, address knowledgeCollectionStorageContract, - uint256 knowledgeCollectionTokenId, - bytes32 assertionId, // Should this be renamed + uint256 knowledgeCollectionId, + bytes32 merkleRoot, uint96 updateTokenAmount ) external onlyContracts { knowledgeMiners[miner].updatingKnowledgeCollectionsStateIndexes[paranetId][ - keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId, assertionId)) + keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionId, merkleRoot)) ] = knowledgeMiners[miner].updatingKnowledgeCollectionsStates[paranetId].length; knowledgeMiners[miner].updatingKnowledgeCollectionsStates[paranetId].push( ParanetLib.UpdatingKnowledgeCollectionState({ knowledgeCollectionStorageContract: knowledgeCollectionStorageContract, - knowledgeCollectionTokenId: knowledgeCollectionTokenId, - assertionId: assertionId, + knowledgeCollectionId: knowledgeCollectionId, + merkleRoot: merkleRoot, updateTokenAmount: updateTokenAmount }) ); } - // What to do with updating this has to be reworked + // If we do this on update // function removeUpdatingKnowledgeCollectionState( // address miner, // bytes32 paranetId, @@ -217,7 +217,7 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { // knowledgeMiners[miner] // .updatingKnowledgeCollectionStates[paranetId][ // knowledgeMiners[miner].updatingKnowledgeCollectionStates[paranetId].length - 1 - // ].assertionId + // ].merkleRoot // ) // ) // ] = knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId]; From 7ed374f171a769ca572a297152c7bcb02e263b57 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 17 Jan 2025 17:11:09 +0100 Subject: [PATCH 022/153] Add comments --- contracts/paranets/Paranet.sol | 2 ++ contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol | 1 + 2 files changed, 3 insertions(+) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index c0eccec0..f301a9a9 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -887,6 +887,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // return knowledgeCollectionTokenId; // } + // If asset has been updated there should be logic to update paranet kc states metadata with info about previouse state if posible function submitKnowledgeCollection( address paranetKCStorageContract, uint256 paranetKnowledgeCollectionId, @@ -1005,6 +1006,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pkmr.addTotalTracSpent(msg.sender, tokenAmount); } + // When is this used ??? function _processUpdatedKnowledgeCollectionStatesMetadata( bytes32 paranetId, ParanetLib.UpdatingKnowledgeCollectionState[] memory updatingKnowledgeCollectionStates diff --git a/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol b/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol index bea36379..380a34a0 100644 --- a/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol +++ b/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol @@ -167,6 +167,7 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { return slice; } + // This should be called on update from KC function addUpdatingKnowledgeCollectionState( address miner, bytes32 paranetId, From e896651658153f0862a6ee078b928b7d301303b2 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Mon, 20 Jan 2025 13:51:29 +0100 Subject: [PATCH 023/153] Update state infor in paranet on submit and update --- contracts/KnowledgeCollection.sol | 16 +- contracts/libraries/ParanetLib.sol | 2 +- contracts/paranets/Paranet.sol | 232 ++++++++++-------- .../ParanetKnowledgeMinersRegistry.sol | 44 ++-- 4 files changed, 160 insertions(+), 134 deletions(-) diff --git a/contracts/KnowledgeCollection.sol b/contracts/KnowledgeCollection.sol index 4b9ebcfb..b88a75bc 100644 --- a/contracts/KnowledgeCollection.sol +++ b/contracts/KnowledgeCollection.sol @@ -183,9 +183,10 @@ contract KnowledgeCollection is INamed, IVersioned, ContractStatus, IInitializab ParanetKnowledgeCollectionsRegistry pkar = paranetKnowledgeCollectionsRegistry; - bytes32 paranetId = pkar.getParanetId(keccak256(abi.encodePacked(address(kcs), id))); - if (pkar.isParanetKnowledgeCollection(paranetId)) { + bytes32 knowledgeCollectionId = pkar.getParanetId(keccak256(abi.encodePacked(address(kcs), id))); + if (pkar.isParanetKnowledgeCollection(knowledgeCollectionId)) { ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; + bytes32 paranetId = paranetKnowledgeCollectionsRegistry.getParanetId(knowledgeCollectionId); // Add Knowledge Asset Token Amount Metadata to the ParanetsRegistry paranetsRegistry.addCumulativeKnowledgeValue(paranetId, tokenAmount); @@ -194,6 +195,7 @@ contract KnowledgeCollection is INamed, IVersioned, ContractStatus, IInitializab pkmr.addCumulativeTracSpent(msg.sender, paranetId, tokenAmount); pkmr.addUnrewardedTracSpent(msg.sender, paranetId, tokenAmount); pkmr.addTotalTracSpent(msg.sender, tokenAmount); + pkmr.addUpdatingKnowledgeCollectionState(msg.sender, paranetId, address(kcs), id, merkleRoot, tokenAmount); } } @@ -223,9 +225,10 @@ contract KnowledgeCollection is INamed, IVersioned, ContractStatus, IInitializab ParanetKnowledgeCollectionsRegistry pkar = paranetKnowledgeCollectionsRegistry; - bytes32 paranetId = pkar.getParanetId(keccak256(abi.encodePacked(address(kcs), id))); - if (pkar.isParanetKnowledgeCollection(paranetId)) { + bytes32 knowledgeCollectionId = pkar.getParanetId(keccak256(abi.encodePacked(address(kcs), id))); + if (pkar.isParanetKnowledgeCollection(knowledgeCollectionId)) { ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; + bytes32 paranetId = paranetKnowledgeCollectionsRegistry.getParanetId(knowledgeCollectionId); // Add Knowledge Asset Token Amount Metadata to the ParanetsRegistry paranetsRegistry.addCumulativeKnowledgeValue(paranetId, tokenAmount); @@ -259,9 +262,10 @@ contract KnowledgeCollection is INamed, IVersioned, ContractStatus, IInitializab ParanetKnowledgeCollectionsRegistry pkar = paranetKnowledgeCollectionsRegistry; - bytes32 paranetId = pkar.getParanetId(keccak256(abi.encodePacked(address(kcs), id))); - if (pkar.isParanetKnowledgeCollection(paranetId)) { + bytes32 knowledgeCollectionId = pkar.getParanetId(keccak256(abi.encodePacked(address(kcs), id))); + if (pkar.isParanetKnowledgeCollection(knowledgeCollectionId)) { ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; + bytes32 paranetId = paranetKnowledgeCollectionsRegistry.getParanetId(knowledgeCollectionId); // Add Knowledge Asset Token Amount Metadata to the ParanetsRegistry paranetsRegistry.addCumulativeKnowledgeValue(paranetId, tokenAmount); diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index 1946a1b8..f4bef2a1 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -145,7 +145,7 @@ library ParanetLib { struct UpdatingKnowledgeCollectionState { address knowledgeCollectionStorageContract; uint256 knowledgeCollectionId; - bytes32 merkleRoot; // Do we need this ? + bytes32 merkleRoot; uint96 updateTokenAmount; } diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index f301a9a9..20fea616 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -15,6 +15,7 @@ import {INamed} from "../interfaces/INamed.sol"; import {IVersioned} from "../interfaces/IVersioned.sol"; import {ParanetLib} from "../libraries/ParanetLib.sol"; import {ProfileLib} from "../libraries/ProfileLib.sol"; +import {KnowledgeCollectionLib} from "../libraries/KnowledgeCollectionLib.sol"; import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { @@ -888,12 +889,13 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // } // If asset has been updated there should be logic to update paranet kc states metadata with info about previouse state if posible + function submitKnowledgeCollection( address paranetKCStorageContract, uint256 paranetKnowledgeCollectionId, address knowledgeCollectionStorageContract, - uint256 knowledgeCollectionId - ) external onlyKnowledgeCollectionOwner(knowledgeCollectionStorageContract, knowledgeCollectionId) { + uint256 knowledgeCollectionTokenId + ) external onlyKnowledgeCollectionOwner(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) { ParanetsRegistry pr = paranetsRegistry; bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionId)); @@ -925,58 +927,61 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { if ( paranetKnowledgeCollectionsRegistry.isParanetKnowledgeCollection( - keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionId)) + keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)) ) ) { revert ParanetLib.KnowledgeCollectionIsAPartOfOtherParanet( knowledgeCollectionStorageContract, - knowledgeCollectionId, + knowledgeCollectionTokenId, paranetKnowledgeCollectionsRegistry.getParanetId( - keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionId)) + keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)) ) ); } // Is this correct way to do this ??? - uint96 remainingTokenAmount = KnowledgeCollectionStorage(knowledgeCollectionStorageContract).getTokenAmount( - knowledgeCollectionId - ); + KnowledgeCollectionStorage kcs = KnowledgeCollectionStorage(knowledgeCollectionStorageContract); + uint96 remainingTokenAmount = kcs.getTokenAmount(knowledgeCollectionTokenId); + KnowledgeCollectionLib.MerkleRoot[] calldata merkleRoots = kcs.getMerkleRoots(knowledgeCollectionTokenId); _updateSubmittedKnowledgeCollectionMetadata( + // Update KnowledgeMiner metadata paranetKCStorageContract, paranetKnowledgeCollectionId, knowledgeCollectionStorageContract, - knowledgeCollectionId, - remainingTokenAmount + knowledgeCollectionTokenId, + remainingTokenAmount, + merkleRoots ); emit KnowledgeCollectionSubmittedToParanet( paranetKCStorageContract, paranetKnowledgeCollectionId, knowledgeCollectionStorageContract, - knowledgeCollectionId + knowledgeCollectionTokenId ); } - function processUpdatedKnowledgeCollectionStatesMetadata( - address paranetKCStorageContract, - uint256 paranetKCTokenId, - uint256 start, - uint256 end - ) external { - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); + // function processUpdatedKnowledgeCollectionStatesMetadata( + // address paranetKCStorageContract, + // uint256 paranetKCTokenId, + // uint256 start, + // uint256 end + // ) external { + // bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); - _processUpdatedKnowledgeCollectionStatesMetadata( - paranetId, - paranetKnowledgeMinersRegistry.getUpdatingKnowledgeCollectionStates(msg.sender, paranetId, start, end) - ); - } + // _processUpdatedKnowledgeCollectionStatesMetadata( + // paranetId, + // paranetKnowledgeMinersRegistry.getUpdatingKnowledgeCollectionStates(msg.sender, paranetId, start, end) + // ); + // } function _updateSubmittedKnowledgeCollectionMetadata( address paranetKCStorageContract, uint256 paranetKCTokenId, address knowledgeCollectionStorageContract, uint256 knowledgeCollectionTokenId, - uint96 tokenAmount + uint96 tokenAmount, + KnowledgeCollectionLib.MerkleRoot[] calldata merkleRoots ) internal { ParanetsRegistry pr = paranetsRegistry; ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; @@ -999,6 +1004,24 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pr.addCumulativeKnowledgeValue(paranetId, tokenAmount); // Add Knowledge Collection Metadata to the KnowledgeMinersRegistry + for (uint256 i = 0; i < merkleRoots.length - 1; i++) { + pkmr.addUpdatingKnowledgeCollectionState( + msg.sender, + paranetId, + knowledgeCollectionStorageContract, + knowledgeCollectionTokenId, + merkleRoots[i].merkleRoot, + 0 + ); + } + pkmr.addUpdatingKnowledgeCollectionState( + msg.sender, + paranetId, + knowledgeCollectionStorageContract, + knowledgeCollectionTokenId, + merkleRoots[merkleRoots.length - 1].merkleRoot, + tokenAmount + ); pkmr.addSubmittedKnowledgeCollection(msg.sender, paranetId, knowledgeCollectionId); pkmr.addCumulativeTracSpent(msg.sender, paranetId, tokenAmount); pkmr.addUnrewardedTracSpent(msg.sender, paranetId, tokenAmount); @@ -1006,90 +1029,89 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pkmr.addTotalTracSpent(msg.sender, tokenAmount); } - // When is this used ??? - function _processUpdatedKnowledgeCollectionStatesMetadata( - bytes32 paranetId, - ParanetLib.UpdatingKnowledgeCollectionState[] memory updatingKnowledgeCollectionStates - ) internal { - ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; - ParanetsRegistry pr = paranetsRegistry; - ContentCollection ca = contentCollection; - - for (uint i; i < updatingKnowledgeCollectionStates.length; ) { - _checkKnowledgeCollectionOwner( - updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract, - updatingKnowledgeCollectionStates[i].tokenId - ); - - bool continueOuterLoop = false; - - bytes32[] memory assertionIds = ContentCollectionStorage( - updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract - ).getAssertionIds(updatingKnowledgeCollectionStates[i].tokenId); - - for (uint j = assertionIds.length; j > 0; ) { - if (assertionIds[j - 1] == updatingKnowledgeCollectionStates[i].assertionId) { - // Add Knowledge Collection Token Amount Metadata to the ParanetsRegistry - pr.addCumulativeKnowledgeValue(paranetId, updatingKnowledgeCollectionStates[i].updateTokenAmount); - - // Add Knowledge Collection Token Amount Metadata to the KnowledgeMinersRegistry - pkmr.addCumulativeTracSpent( - msg.sender, - paranetId, - updatingKnowledgeCollectionStates[i].updateTokenAmount - ); - pkmr.addUnrewardedTracSpent( - msg.sender, - paranetId, - updatingKnowledgeCollectionStates[i].updateTokenAmount - ); - pkmr.addTotalTracSpent(msg.sender, updatingKnowledgeCollectionStates[i].updateTokenAmount); - - pkmr.removeUpdatingKnowledgeCollectionState( - msg.sender, - paranetId, - keccak256( - abi.encodePacked( - updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract, - updatingKnowledgeCollectionStates[i].tokenId, - updatingKnowledgeCollectionStates[i].assertionId - ) - ) - ); - - continueOuterLoop = true; - break; - } - - unchecked { - j--; - } - } + // function _processUpdatedKnowledgeCollectionStatesMetadata( + // bytes32 paranetId, + // ParanetLib.UpdatingKnowledgeCollectionState[] memory updatingKnowledgeCollectionStates + // ) internal { + // ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; + // ParanetsRegistry pr = paranetsRegistry; + // ContentCollection ca = contentCollection; + + // for (uint i; i < updatingKnowledgeCollectionStates.length; ) { + // _checkKnowledgeCollectionOwner( + // updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract, + // updatingKnowledgeCollectionStates[i].tokenId + // ); + + // bool continueOuterLoop = false; + + // bytes32[] memory assertionIds = ContentCollectionStorage( + // updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract + // ).getAssertionIds(updatingKnowledgeCollectionStates[i].tokenId); + + // for (uint j = assertionIds.length; j > 0; ) { + // if (assertionIds[j - 1] == updatingKnowledgeCollectionStates[i].assertionId) { + // // Add Knowledge Collection Token Amount Metadata to the ParanetsRegistry + // pr.addCumulativeKnowledgeValue(paranetId, updatingKnowledgeCollectionStates[i].updateTokenAmount); + + // // Add Knowledge Collection Token Amount Metadata to the KnowledgeMinersRegistry + // pkmr.addCumulativeTracSpent( + // msg.sender, + // paranetId, + // updatingKnowledgeCollectionStates[i].updateTokenAmount + // ); + // pkmr.addUnrewardedTracSpent( + // msg.sender, + // paranetId, + // updatingKnowledgeCollectionStates[i].updateTokenAmount + // ); + // pkmr.addTotalTracSpent(msg.sender, updatingKnowledgeCollectionStates[i].updateTokenAmount); + + // pkmr.removeUpdatingKnowledgeCollectionState( + // msg.sender, + // paranetId, + // keccak256( + // abi.encodePacked( + // updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract, + // updatingKnowledgeCollectionStates[i].tokenId, + // updatingKnowledgeCollectionStates[i].assertionId + // ) + // ) + // ); + + // continueOuterLoop = true; + // break; + // } + + // unchecked { + // j--; + // } + // } - unchecked { - i++; - } + // unchecked { + // i++; + // } - if (continueOuterLoop) { - continue; - } + // if (continueOuterLoop) { + // continue; + // } - try ca.cancelCollectionStateUpdateFromContract(updatingKnowledgeCollectionStates[i].tokenId) { - pkmr.removeUpdatingKnowledgeCollectionState( - msg.sender, - paranetId, - keccak256( - abi.encodePacked( - updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract, - updatingKnowledgeCollectionStates[i].tokenId, - updatingKnowledgeCollectionStates[i].assertionId - ) - ) - ); - // solhint-disable-next-line no-empty-blocks - } catch {} - } - } + // try ca.cancelCollectionStateUpdateFromContract(updatingKnowledgeCollectionStates[i].tokenId) { + // pkmr.removeUpdatingKnowledgeCollectionState( + // msg.sender, + // paranetId, + // keccak256( + // abi.encodePacked( + // updatingKnowledgeCollectionStates[i].knowledgeCollectionStorageContract, + // updatingKnowledgeCollectionStates[i].tokenId, + // updatingKnowledgeCollectionStates[i].assertionId + // ) + // ) + // ); + // // solhint-disable-next-line no-empty-blocks + // } catch {} + // } + // } function _checkParanetOperator(bytes32 paranetId) internal view virtual { (address paranetKCStorageContract, uint256 paranetKCTokenId) = paranetsRegistry diff --git a/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol b/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol index 380a34a0..afaf7398 100644 --- a/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol +++ b/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol @@ -263,29 +263,29 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { return slice; } - // function setUpdatingKnowledgeCollectionUpdateTokenAmount( - // address miner, - // bytes32 paranetId, - // bytes32 knowledgeCollectionStateId, - // uint96 updateTokenAmount - // ) external onlyContracts { - // knowledgeMiners[miner] - // .updatingKnowledgeCollectionsStates[paranetId][ - // knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId] - // ].updateTokenAmount = updateTokenAmount; - // } + function setUpdatingKnowledgeCollectionUpdateTokenAmount( + address miner, + bytes32 paranetId, + bytes32 knowledgeCollectionStateId, + uint96 updateTokenAmount + ) external onlyContracts { + knowledgeMiners[miner] + .updatingKnowledgeCollectionsStates[paranetId][ + knowledgeMiners[miner].updatingKnowledgeCollectionsStateIndexes[paranetId][knowledgeCollectionStateId] + ].updateTokenAmount = updateTokenAmount; + } - // function addUpdatingKnowledgeCollectionUpdateTokenAmount( - // address miner, - // bytes32 paranetId, - // bytes32 knowledgeCollectionStateId, - // uint96 addedUpdateTokenAmount - // ) external onlyContracts { - // knowledgeMiners[miner] - // .updatingKnowledgeCollectionsStates[paranetId][ - // knowledgeMiners[miner].updatingKnowledgeCollectionStateIndexes[paranetId][knowledgeCollectionStateId] - // ].updateTokenAmount += addedUpdateTokenAmount; - // } + function addUpdatingKnowledgeCollectionUpdateTokenAmount( + address miner, + bytes32 paranetId, + bytes32 knowledgeCollectionStateId, + uint96 addedUpdateTokenAmount + ) external onlyContracts { + knowledgeMiners[miner] + .updatingKnowledgeCollectionsStates[paranetId][ + knowledgeMiners[miner].updatingKnowledgeCollectionsStateIndexes[paranetId][knowledgeCollectionStateId] + ].updateTokenAmount += addedUpdateTokenAmount; + } function subUpdatingKnowledgeCollectionUpdateTokenAmount( address miner, From c44f28de934d6f0eb08c6c95c37678c04a6f8605 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Mon, 20 Jan 2025 14:31:33 +0100 Subject: [PATCH 024/153] Change merkleRoots to memory --- contracts/paranets/Paranet.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 20fea616..8fe20b40 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -941,10 +941,10 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // Is this correct way to do this ??? KnowledgeCollectionStorage kcs = KnowledgeCollectionStorage(knowledgeCollectionStorageContract); uint96 remainingTokenAmount = kcs.getTokenAmount(knowledgeCollectionTokenId); - KnowledgeCollectionLib.MerkleRoot[] calldata merkleRoots = kcs.getMerkleRoots(knowledgeCollectionTokenId); + KnowledgeCollectionLib.MerkleRoot[] memory merkleRoots = kcs.getMerkleRoots(knowledgeCollectionTokenId); + // Update KnowledgeMiner metadata _updateSubmittedKnowledgeCollectionMetadata( - // Update KnowledgeMiner metadata paranetKCStorageContract, paranetKnowledgeCollectionId, knowledgeCollectionStorageContract, @@ -981,7 +981,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { address knowledgeCollectionStorageContract, uint256 knowledgeCollectionTokenId, uint96 tokenAmount, - KnowledgeCollectionLib.MerkleRoot[] calldata merkleRoots + KnowledgeCollectionLib.MerkleRoot[] memory merkleRoots ) internal { ParanetsRegistry pr = paranetsRegistry; ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; From 631ac4db2abf85cce335bc83e4853b92c19f9785 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Mon, 20 Jan 2025 15:07:06 +0100 Subject: [PATCH 025/153] Update ABI --- abi/KnowledgeCollection.json | 39 +++ abi/Paranet.json | 258 ++++++++++++------ abi/ParanetIncentivesPoolFactory.json | 17 +- ... ParanetKnowledgeCollectionsRegistry.json} | 65 +++-- abi/ParanetKnowledgeMinersRegistry.json | 107 +++----- abi/ParanetNeuroIncentivesPool.json | 18 ++ abi/ParanetServicesRegistry.json | 10 +- abi/ParanetsRegistry.json | 138 ++++++++-- 8 files changed, 450 insertions(+), 202 deletions(-) rename abi/{ParanetKnowledgeAssetsRegistry.json => ParanetKnowledgeCollectionsRegistry.json} (75%) diff --git a/abi/KnowledgeCollection.json b/abi/KnowledgeCollection.json index 3eaeebfa..79ff0586 100644 --- a/abi/KnowledgeCollection.json +++ b/abi/KnowledgeCollection.json @@ -451,6 +451,45 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "paranetKnowledgeCollectionsRegistry", + "outputs": [ + { + "internalType": "contract ParanetKnowledgeCollectionsRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paranetKnowledgeMinersRegistry", + "outputs": [ + { + "internalType": "contract ParanetKnowledgeMinersRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paranetsRegistry", + "outputs": [ + { + "internalType": "contract ParanetsRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "paymasterManager", diff --git a/abi/Paranet.json b/abi/Paranet.json index 04ce8992..2f029c96 100644 --- a/abi/Paranet.json +++ b/abi/Paranet.json @@ -42,6 +42,27 @@ "name": "InvalidParanetNodesAccessPolicy", "type": "error" }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKnowledgeCollectionStorageAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeCollectionTokenId", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "KnowledgeCollectionIsAPartOfOtherParanet", + "type": "error" + }, { "inputs": [ { @@ -184,12 +205,12 @@ "inputs": [ { "internalType": "address", - "name": "knowledgeAssetStorageAddress", + "name": "knowledgeCollectionStorageAddress", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionTokenId", "type": "uint256" } ], @@ -200,12 +221,12 @@ "inputs": [ { "internalType": "address", - "name": "knowledgeAssetStorageAddress", + "name": "knowledgeCollectionStorageAddress", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionTokenId", "type": "uint256" } ], @@ -216,12 +237,12 @@ "inputs": [ { "internalType": "address", - "name": "knowledgeAssetStorageAddress", + "name": "knowledgeCollectionStorageAddress", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionTokenId", "type": "uint256" } ], @@ -248,12 +269,12 @@ "inputs": [ { "internalType": "address", - "name": "knowledgeAssetStorageAddress", + "name": "knowledgeCollectionStorageAddress", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionTokenId", "type": "uint256" } ], @@ -293,29 +314,29 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { "indexed": true, "internalType": "address", - "name": "knowledgeAssetStorageContract", + "name": "knowledgeCollectionStorageContract", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "knowledgeAssetTokenId", + "name": "knowledgeCollectionId", "type": "uint256" } ], - "name": "KnowledgeAssetSubmittedToParanet", + "name": "KnowledgeCollectionSubmittedToParanet", "type": "event" }, { @@ -324,13 +345,13 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -349,13 +370,13 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -374,13 +395,13 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -399,13 +420,13 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -424,13 +445,13 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -449,13 +470,13 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -474,13 +495,13 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -499,13 +520,13 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -524,13 +545,13 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -549,13 +570,13 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -574,13 +595,13 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -611,13 +632,13 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -642,13 +663,13 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -677,8 +698,8 @@ }, { "indexed": false, - "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", - "name": "knowledgeAssetsAccessPolicy", + "internalType": "enum ParanetLib.KnowledgeCollectionsAccessPolicy", + "name": "knowledgeCollectionsAccessPolicy", "type": "uint8" } ], @@ -691,25 +712,25 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { "indexed": true, "internalType": "address", - "name": "paranetServiceKAStorageContract", + "name": "paranetServiceKCStorageContract", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "paranetServiceKATokenId", + "name": "paranetServiceKCTokenId", "type": "uint256" } ], @@ -722,13 +743,13 @@ { "indexed": true, "internalType": "address", - "name": "paranetServiceKAStorageContract", + "name": "paranetServiceKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetServiceKATokenId", + "name": "paranetServiceKCTokenId", "type": "uint256" }, { @@ -759,13 +780,13 @@ { "indexed": true, "internalType": "address", - "name": "paranetServiceKAStorageContract", + "name": "paranetServiceKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetServiceKATokenId", + "name": "paranetServiceKCTokenId", "type": "uint256" }, { @@ -794,12 +815,12 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -817,12 +838,12 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -840,28 +861,28 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { "components": [ { "internalType": "address", - "name": "knowledgeAssetStorageContract", + "name": "knowledgeCollectionStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionTokenId", "type": "uint256" } ], - "internalType": "struct ParanetLib.UniversalAssetLocator[]", + "internalType": "struct ParanetLib.UniversalCollectionLocator[]", "name": "services", "type": "tuple[]" } @@ -875,12 +896,12 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -898,12 +919,12 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -917,6 +938,47 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "getKnowledgeCollectionLocatorsWithPagination", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "knowledgeCollectionStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "knowledgeCollectionTokenId", + "type": "uint256" + } + ], + "internalType": "struct ParanetLib.UniversalCollectionLocator[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "hub", @@ -965,10 +1027,10 @@ }, { "inputs": [], - "name": "paranetKnowledgeAssetsRegistry", + "name": "paranetKnowledgeCollectionsRegistry", "outputs": [ { - "internalType": "contract ParanetKnowledgeAssetsRegistry", + "internalType": "contract ParanetKnowledgeCollectionsRegistry", "name": "", "type": "address" } @@ -1032,12 +1094,12 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -1076,12 +1138,12 @@ "inputs": [ { "internalType": "address", - "name": "paranetServiceKAStorageContract", + "name": "paranetServiceKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetServiceKATokenId", + "name": "paranetServiceKCTokenId", "type": "uint256" }, { @@ -1115,12 +1177,12 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -1138,12 +1200,12 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -1161,12 +1223,12 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -1184,12 +1246,12 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -1207,12 +1269,12 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" } ], @@ -1225,12 +1287,12 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" } ], @@ -1269,12 +1331,40 @@ "inputs": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeCollectionId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "knowledgeCollectionStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "knowledgeCollectionTokenId", + "type": "uint256" + } + ], + "name": "submitKnowledgeCollection", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -1297,12 +1387,12 @@ "inputs": [ { "internalType": "address", - "name": "paranetServiceKAStorageContract", + "name": "paranetServiceKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetServiceKATokenId", + "name": "paranetServiceKCTokenId", "type": "uint256" }, { diff --git a/abi/ParanetIncentivesPoolFactory.json b/abi/ParanetIncentivesPoolFactory.json index 774b2299..f3b72120 100644 --- a/abi/ParanetIncentivesPoolFactory.json +++ b/abi/ParanetIncentivesPoolFactory.json @@ -14,12 +14,12 @@ "inputs": [ { "internalType": "address", - "name": "knowledgeAssetStorageAddress", + "name": "knowledgeCollectionStorageAddress", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionTokenId", "type": "uint256" }, { @@ -58,13 +58,13 @@ { "indexed": true, "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "indexed": true, "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -91,14 +91,19 @@ }, { "inputs": [ + { + "internalType": "bool", + "name": "isNativeReward", + "type": "bool" + }, { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { diff --git a/abi/ParanetKnowledgeAssetsRegistry.json b/abi/ParanetKnowledgeCollectionsRegistry.json similarity index 75% rename from abi/ParanetKnowledgeAssetsRegistry.json rename to abi/ParanetKnowledgeCollectionsRegistry.json index 92c68f87..7a654245 100644 --- a/abi/ParanetKnowledgeAssetsRegistry.json +++ b/abi/ParanetKnowledgeCollectionsRegistry.json @@ -35,12 +35,12 @@ }, { "internalType": "address", - "name": "knowledgeAssetStorageContract", + "name": "knowledgeCollectionStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionTokenId", "type": "uint256" }, { @@ -49,7 +49,7 @@ "type": "address" } ], - "name": "addKnowledgeAsset", + "name": "addKnowledgeCollection", "outputs": [ { "internalType": "bytes32", @@ -64,7 +64,7 @@ "inputs": [ { "internalType": "bytes32", - "name": "knowledgeAssetId", + "name": "knowledgeCollectionId", "type": "bytes32" } ], @@ -84,26 +84,57 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "knowledgeCollectionIds", + "type": "bytes32[]" + } + ], + "name": "getKnowledgeCollectionLocators", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "knowledgeCollectionStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "knowledgeCollectionTokenId", + "type": "uint256" + } + ], + "internalType": "struct ParanetLib.UniversalCollectionLocator[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { "internalType": "bytes32", - "name": "knowledgeAssetId", + "name": "knowledgeCollectionId", "type": "bytes32" } ], - "name": "getKnowledgeAssetObject", + "name": "getKnowledgeCollectionObject", "outputs": [ { "components": [ { "internalType": "address", - "name": "knowledgeAssetStorageContract", + "name": "knowledgeCollectionStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionTokenId", "type": "uint256" }, { @@ -117,7 +148,7 @@ "type": "bytes32" } ], - "internalType": "struct ParanetLib.KnowledgeAsset", + "internalType": "struct ParanetLib.KnowledgeCollection", "name": "", "type": "tuple" } @@ -129,7 +160,7 @@ "inputs": [ { "internalType": "bytes32", - "name": "knowledgeAssetId", + "name": "knowledgeCollectionId", "type": "bytes32" } ], @@ -148,7 +179,7 @@ "inputs": [ { "internalType": "bytes32", - "name": "knowledgeAssetId", + "name": "knowledgeCollectionId", "type": "bytes32" } ], @@ -180,11 +211,11 @@ "inputs": [ { "internalType": "bytes32", - "name": "knowledgeAssetId", + "name": "knowledgeCollectionId", "type": "bytes32" } ], - "name": "isParanetKnowledgeAsset", + "name": "isParanetKnowledgeCollection", "outputs": [ { "internalType": "bool", @@ -212,11 +243,11 @@ "inputs": [ { "internalType": "bytes32", - "name": "knowledgeAssetId", + "name": "knowledgeCollectionId", "type": "bytes32" } ], - "name": "removeKnowledgeAsset", + "name": "removeKnowledgeCollection", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -225,7 +256,7 @@ "inputs": [ { "internalType": "bytes32", - "name": "knowledgeAssetId", + "name": "knowledgeCollectionId", "type": "bytes32" }, { @@ -243,7 +274,7 @@ "inputs": [ { "internalType": "bytes32", - "name": "knowledgeAssetId", + "name": "knowledgeCollectionId", "type": "bytes32" }, { diff --git a/abi/ParanetKnowledgeMinersRegistry.json b/abi/ParanetKnowledgeMinersRegistry.json index f78c7e52..f77f96fd 100644 --- a/abi/ParanetKnowledgeMinersRegistry.json +++ b/abi/ParanetKnowledgeMinersRegistry.json @@ -86,11 +86,11 @@ }, { "internalType": "bytes32", - "name": "knowledgeAssetId", + "name": "knowledgeCollectionId", "type": "bytes32" } ], - "name": "addSubmittedKnowledgeAsset", + "name": "addSubmittedKnowledgeCollection", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -150,17 +150,17 @@ }, { "internalType": "address", - "name": "knowledgeAssetStorageContract", + "name": "knowledgeCollectionStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionId", "type": "uint256" }, { "internalType": "bytes32", - "name": "assertionId", + "name": "merkleRoot", "type": "bytes32" }, { @@ -169,7 +169,7 @@ "type": "uint96" } ], - "name": "addUpdatingKnowledgeAssetState", + "name": "addUpdatingKnowledgeCollectionState", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -188,7 +188,7 @@ }, { "internalType": "bytes32", - "name": "knowledgeAssetStateId", + "name": "knowledgeCollectionStateId", "type": "bytes32" }, { @@ -197,7 +197,7 @@ "type": "uint96" } ], - "name": "addUpdatingKnowledgeAssetUpdateTokenAmount", + "name": "addUpdatingKnowledgeCollectionUpdateTokenAmount", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -210,7 +210,7 @@ "type": "address" } ], - "name": "decrementTotalSubmittedKnowledgeAssetsCount", + "name": "decrementTotalSubmittedKnowledgeCollectionsCount", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -300,7 +300,7 @@ }, { "internalType": "uint256", - "name": "totalSubmittedKnowledgeAssetsCount", + "name": "totalSubmittedKnowledgeCollectionsCount", "type": "uint256" } ], @@ -325,7 +325,7 @@ "type": "bytes32" } ], - "name": "getSubmittedKnowledgeAssets", + "name": "getSubmittedKnowledgeCollections", "outputs": [ { "internalType": "bytes32[]", @@ -359,7 +359,7 @@ "type": "uint256" } ], - "name": "getSubmittedKnowledgeAssets", + "name": "getSubmittedKnowledgeCollections", "outputs": [ { "internalType": "bytes32[]", @@ -378,7 +378,7 @@ "type": "address" } ], - "name": "getTotalSubmittedKnowledgeAssetsCount", + "name": "getTotalSubmittedKnowledgeCollectionsCount", "outputs": [ { "internalType": "uint256", @@ -443,35 +443,25 @@ "internalType": "bytes32", "name": "paranetId", "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "start", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "end", - "type": "uint256" } ], - "name": "getUpdatingKnowledgeAssetStates", + "name": "getUpdatingKnowledgeCollectionStates", "outputs": [ { "components": [ { "internalType": "address", - "name": "knowledgeAssetStorageContract", + "name": "knowledgeCollectionStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionId", "type": "uint256" }, { "internalType": "bytes32", - "name": "assertionId", + "name": "merkleRoot", "type": "bytes32" }, { @@ -480,7 +470,7 @@ "type": "uint96" } ], - "internalType": "struct ParanetLib.UpdatingKnowledgeAssetState[]", + "internalType": "struct ParanetLib.UpdatingKnowledgeCollectionState[]", "name": "", "type": "tuple[]" } @@ -499,25 +489,35 @@ "internalType": "bytes32", "name": "paranetId", "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "end", + "type": "uint256" } ], - "name": "getUpdatingKnowledgeAssetStates", + "name": "getUpdatingKnowledgeCollectionStates", "outputs": [ { "components": [ { "internalType": "address", - "name": "knowledgeAssetStorageContract", + "name": "knowledgeCollectionStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionId", "type": "uint256" }, { "internalType": "bytes32", - "name": "assertionId", + "name": "merkleRoot", "type": "bytes32" }, { @@ -526,7 +526,7 @@ "type": "uint96" } ], - "internalType": "struct ParanetLib.UpdatingKnowledgeAssetState[]", + "internalType": "struct ParanetLib.UpdatingKnowledgeCollectionState[]", "name": "", "type": "tuple[]" } @@ -555,7 +555,7 @@ "type": "address" } ], - "name": "incrementTotalSubmittedKnowledgeAssetsCount", + "name": "incrementTotalSubmittedKnowledgeCollectionsCount", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -639,34 +639,11 @@ }, { "internalType": "bytes32", - "name": "knowledgeAssetId", - "type": "bytes32" - } - ], - "name": "removeSubmittedKnowledgeAsset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "miner", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "knowledgeAssetStateId", + "name": "knowledgeCollectionId", "type": "bytes32" } ], - "name": "removeUpdatingKnowledgeAssetState", + "name": "removeSubmittedKnowledgeCollection", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -726,11 +703,11 @@ }, { "internalType": "uint256", - "name": "totalSubmittedKnowledgeAssetsCount", + "name": "totalSubmittedKnowledgeCollectionsCount", "type": "uint256" } ], - "name": "setTotalSubmittedKnowledgeAssetsCount", + "name": "setTotalSubmittedKnowledgeCollectionsCount", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -790,7 +767,7 @@ }, { "internalType": "bytes32", - "name": "knowledgeAssetStateId", + "name": "knowledgeCollectionStateId", "type": "bytes32" }, { @@ -799,7 +776,7 @@ "type": "uint96" } ], - "name": "setUpdatingKnowledgeAssetUpdateTokenAmount", + "name": "setUpdatingKnowledgeCollectionUpdateTokenAmount", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -905,7 +882,7 @@ }, { "internalType": "bytes32", - "name": "knowledgeAssetStateId", + "name": "knowledgeCollectionStateId", "type": "bytes32" }, { @@ -914,7 +891,7 @@ "type": "uint96" } ], - "name": "subUpdatingKnowledgeAssetUpdateTokenAmount", + "name": "subUpdatingKnowledgeCollectionUpdateTokenAmount", "outputs": [], "stateMutability": "nonpayable", "type": "function" diff --git a/abi/ParanetNeuroIncentivesPool.json b/abi/ParanetNeuroIncentivesPool.json index 1677d836..41e29420 100644 --- a/abi/ParanetNeuroIncentivesPool.json +++ b/abi/ParanetNeuroIncentivesPool.json @@ -6,6 +6,11 @@ "name": "hubAddress", "type": "address" }, + { + "internalType": "address", + "name": "rewardTokenAddress", + "type": "address" + }, { "internalType": "address", "name": "paranetsRegistryAddress", @@ -924,6 +929,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "totalMinersClaimedNeuro", diff --git a/abi/ParanetServicesRegistry.json b/abi/ParanetServicesRegistry.json index 7bdde7e6..59e26327 100644 --- a/abi/ParanetServicesRegistry.json +++ b/abi/ParanetServicesRegistry.json @@ -104,7 +104,7 @@ "type": "bytes32" } ], - "name": "getParanetServiceKnowledgeAssetLocator", + "name": "getParanetServiceKnowledgeCollectionLocator", "outputs": [ { "internalType": "address", @@ -134,12 +134,12 @@ "components": [ { "internalType": "address", - "name": "paranetServiceKAStorageContract", + "name": "paranetServiceKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetServiceKATokenId", + "name": "paranetServiceKCTokenId", "type": "uint256" }, { @@ -239,12 +239,12 @@ "inputs": [ { "internalType": "address", - "name": "paranetServiceKAStorageContract", + "name": "paranetServiceKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetServiceKATokenId", + "name": "paranetServiceKCTokenId", "type": "uint256" }, { diff --git a/abi/ParanetsRegistry.json b/abi/ParanetsRegistry.json index 438a9fbc..5c8acee9 100644 --- a/abi/ParanetsRegistry.json +++ b/abi/ParanetsRegistry.json @@ -130,11 +130,11 @@ }, { "internalType": "bytes32", - "name": "knowledgeAssetId", + "name": "knowledgeCollectionId", "type": "bytes32" } ], - "name": "addKnowledgeAsset", + "name": "addKnowledgeCollecton", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -265,6 +265,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "getAllParanetIds", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -385,7 +398,7 @@ "type": "bytes32" } ], - "name": "getKnowledgeAssets", + "name": "getKnowledgeCollections", "outputs": [ { "internalType": "bytes32[]", @@ -404,10 +417,10 @@ "type": "bytes32" } ], - "name": "getKnowledgeAssetsAccessPolicy", + "name": "getKnowledgeCollectionsAccessPolicy", "outputs": [ { - "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", + "internalType": "enum ParanetLib.KnowledgeCollectionsAccessPolicy", "name": "", "type": "uint8" } @@ -423,7 +436,7 @@ "type": "bytes32" } ], - "name": "getKnowledgeAssetsCount", + "name": "getKnowledgeCollectionsCount", "outputs": [ { "internalType": "uint256", @@ -443,7 +456,7 @@ }, { "internalType": "bytes32", - "name": "knowledgeAssetId", + "name": "knowledgeCollectionId", "type": "bytes32" }, { @@ -452,7 +465,7 @@ "type": "uint256" } ], - "name": "getKnowledgeAssetsStartingFromKnowledgeAssetId", + "name": "getKnowledgeCollectionsStartingFromKnowlCollectionId", "outputs": [ { "internalType": "bytes32[]", @@ -481,7 +494,7 @@ "type": "uint256" } ], - "name": "getKnowledgeAssetsWithPagination", + "name": "getKnowledgeCollectionsWithPagination", "outputs": [ { "internalType": "bytes32[]", @@ -921,6 +934,49 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getParanetIdAtIndex", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "getParanetIds", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -929,7 +985,26 @@ "type": "bytes32" } ], - "name": "getParanetKnowledgeAssetLocator", + "name": "getParanetIdsMapping", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "getParanetKnowledgeCollectionLocator", "outputs": [ { "internalType": "address", @@ -959,12 +1034,12 @@ "components": [ { "internalType": "address", - "name": "paranetKAStorageContract", + "name": "paranetKCStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetKATokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { @@ -988,8 +1063,8 @@ "type": "uint8" }, { - "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", - "name": "knowledgeAssetsAccessPolicy", + "internalType": "enum ParanetLib.KnowledgeCollectionsAccessPolicy", + "name": "knowledgeCollectionsAccessPolicy", "type": "uint8" }, { @@ -1006,6 +1081,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "getParanetsCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1138,11 +1226,11 @@ }, { "internalType": "bytes32", - "name": "knowledgeAssetId", + "name": "knowledgeCollectionId", "type": "bytes32" } ], - "name": "isKnowledgeAssetRegistered", + "name": "isKnowledgeCollectionRegistered", "outputs": [ { "internalType": "bool", @@ -1237,12 +1325,12 @@ "inputs": [ { "internalType": "address", - "name": "knowledgeAssetStorageContract", + "name": "knowledgeCollectionStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "tokenId", + "name": "knowledgeCollectionTokenId", "type": "uint256" }, { @@ -1266,8 +1354,8 @@ "type": "uint8" }, { - "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", - "name": "knowledgeAssetsAccessPolicy", + "internalType": "enum ParanetLib.KnowledgeCollectionsAccessPolicy", + "name": "knowledgeColletionsAccessPolicy", "type": "uint8" } ], @@ -1345,11 +1433,11 @@ }, { "internalType": "bytes32", - "name": "knowledgeAssetId", + "name": "knowledgeCollectionId", "type": "bytes32" } ], - "name": "removeKnowledgeAsset", + "name": "removeKnowledgeCollection", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1503,12 +1591,12 @@ "type": "bytes32" }, { - "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", - "name": "knowledgeAssetsAccessPolicy", + "internalType": "enum ParanetLib.KnowledgeCollectionsAccessPolicy", + "name": "knowledgeCollectionsAccessPolicy", "type": "uint8" } ], - "name": "setKnowledgeAssetsAccessPolicy", + "name": "setKnowledgeCollectionsAccessPolicy", "outputs": [], "stateMutability": "nonpayable", "type": "function" From f97063a95c94d7443aa324101037baf14fe43ed7 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Mon, 20 Jan 2025 15:27:59 +0100 Subject: [PATCH 026/153] Update deployment script & ABIs exports --- deploy/012_deploy_paranets_registry.ts | 3 --- deploy/013_deploy_paranet_services_registry.ts | 3 --- ...> 014_deploy_paranet_knowledge_collections_registry.ts} | 7 ++----- deploy/015_deploy_paranet_knowledge_miners_registry.ts | 3 --- deploy/024_deploy_paranet.ts | 5 +---- deploy/025_deploy_paranet_incentives_pool_factory.ts | 3 --- index.ts | 4 ++-- 7 files changed, 5 insertions(+), 23 deletions(-) rename deploy/{014_deploy_paranet_knowledge_assets_registry.ts => 014_deploy_paranet_knowledge_collections_registry.ts} (63%) diff --git a/deploy/012_deploy_paranets_registry.ts b/deploy/012_deploy_paranets_registry.ts index 21b2721d..fad5d8cd 100644 --- a/deploy/012_deploy_paranets_registry.ts +++ b/deploy/012_deploy_paranets_registry.ts @@ -2,9 +2,6 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { DeployFunction } from 'hardhat-deploy/types'; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - // TODO: Remove when paranets V2 are finished - return; - await hre.helpers.deploy({ newContractName: 'ParanetsRegistry', }); diff --git a/deploy/013_deploy_paranet_services_registry.ts b/deploy/013_deploy_paranet_services_registry.ts index 516a0d9d..f2ae3e20 100644 --- a/deploy/013_deploy_paranet_services_registry.ts +++ b/deploy/013_deploy_paranet_services_registry.ts @@ -2,9 +2,6 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { DeployFunction } from 'hardhat-deploy/types'; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - // TODO: Remove when paranets V2 are finished - return; - await hre.helpers.deploy({ newContractName: 'ParanetServicesRegistry', }); diff --git a/deploy/014_deploy_paranet_knowledge_assets_registry.ts b/deploy/014_deploy_paranet_knowledge_collections_registry.ts similarity index 63% rename from deploy/014_deploy_paranet_knowledge_assets_registry.ts rename to deploy/014_deploy_paranet_knowledge_collections_registry.ts index 131d080a..b3cc14d8 100644 --- a/deploy/014_deploy_paranet_knowledge_assets_registry.ts +++ b/deploy/014_deploy_paranet_knowledge_collections_registry.ts @@ -2,14 +2,11 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { DeployFunction } from 'hardhat-deploy/types'; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - // TODO: Remove when paranets V2 are finished - return; - await hre.helpers.deploy({ - newContractName: 'ParanetKnowledgeAssetsRegistry', + newContractName: 'ParanetKnowledgeCollectionsRegistry', }); }; export default func; -func.tags = ['ParanetKnowledgeAssetsRegistry']; +func.tags = ['ParanetKnowledgeCollectionsRegistry']; func.dependencies = ['Hub']; diff --git a/deploy/015_deploy_paranet_knowledge_miners_registry.ts b/deploy/015_deploy_paranet_knowledge_miners_registry.ts index 7341c9e9..3c72d735 100644 --- a/deploy/015_deploy_paranet_knowledge_miners_registry.ts +++ b/deploy/015_deploy_paranet_knowledge_miners_registry.ts @@ -2,9 +2,6 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { DeployFunction } from 'hardhat-deploy/types'; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - // TODO: Remove when paranets V2 are finished - return; - await hre.helpers.deploy({ newContractName: 'ParanetKnowledgeMinersRegistry', }); diff --git a/deploy/024_deploy_paranet.ts b/deploy/024_deploy_paranet.ts index b82a5272..a78c3542 100644 --- a/deploy/024_deploy_paranet.ts +++ b/deploy/024_deploy_paranet.ts @@ -2,9 +2,6 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { DeployFunction } from 'hardhat-deploy/types'; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - // TODO: Remove when paranets V2 are finished - return; - await hre.helpers.deploy({ newContractName: 'Paranet', }); @@ -14,7 +11,7 @@ export default func; func.tags = ['Paranet']; func.dependencies = [ 'Hub', - 'ParanetKnowledgeAssetsRegistry', + 'ParanetKnowledgeCollectionsRegistry', 'ParanetKnowledgeMinersRegistry', 'ParanetsRegistry', 'ParanetServicesRegistry', diff --git a/deploy/025_deploy_paranet_incentives_pool_factory.ts b/deploy/025_deploy_paranet_incentives_pool_factory.ts index 907175f8..68d18455 100644 --- a/deploy/025_deploy_paranet_incentives_pool_factory.ts +++ b/deploy/025_deploy_paranet_incentives_pool_factory.ts @@ -2,9 +2,6 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { DeployFunction } from 'hardhat-deploy/types'; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - // TODO: Remove when paranets V2 are finished - return; - if ( !hre.network.name.startsWith('neuroweb') && !hre.network.name.startsWith('hardhat') diff --git a/index.ts b/index.ts index 84179306..882ff8c5 100644 --- a/index.ts +++ b/index.ts @@ -21,7 +21,7 @@ import Migrator from './abi/Migrator.json'; import ParametersStorage from './abi/ParametersStorage.json'; import Paranet from './abi/Paranet.json'; import ParanetIncentivesPoolFactory from './abi/ParanetIncentivesPoolFactory.json'; -import ParanetKnowledgeAssetsRegistry from './abi/ParanetKnowledgeAssetsRegistry.json'; +import ParanetKnowledgeCollectionsRegistry from './abi/ParanetKnowledgeCollectionsRegistry.json'; import ParanetKnowledgeMinersRegistry from './abi/ParanetKnowledgeMinersRegistry.json'; import ParanetNeuroIncentivesPool from './abi/ParanetNeuroIncentivesPool.json'; import ParanetServicesRegistry from './abi/ParanetServicesRegistry.json'; @@ -49,7 +49,7 @@ export { Identity as IdentityABI, Paranet as ParanetABI, ParanetIncentivesPoolFactory as ParanetIncentivesPoolFactoryABI, - ParanetKnowledgeAssetsRegistry as ParanetKnowledgeAssetsRegistryABI, + ParanetKnowledgeCollectionsRegistry as ParanetKnowledgeCollectionsRegistryABI, ParanetKnowledgeMinersRegistry as ParanetKnowledgeMinersRegistryABI, ParanetServicesRegistry as ParanetServicesRegistryABI, ParanetsRegistry as ParanetsRegistryABI, From 57e3c2bd61ab3cfccd749585a5834b5ca3d6c104 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Mon, 20 Jan 2025 15:28:22 +0100 Subject: [PATCH 027/153] Remove unused import --- contracts/paranets/Paranet.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 8fe20b40..eddffab7 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -16,7 +16,6 @@ import {IVersioned} from "../interfaces/IVersioned.sol"; import {ParanetLib} from "../libraries/ParanetLib.sol"; import {ProfileLib} from "../libraries/ProfileLib.sol"; import {KnowledgeCollectionLib} from "../libraries/KnowledgeCollectionLib.sol"; -import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { event ParanetRegistered( From 3e90db072a675e5461f123925dc28920d2723118 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 21 Jan 2025 13:06:31 +0100 Subject: [PATCH 028/153] Add debugevent --- contracts/paranets/Paranet.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index eddffab7..fecd3916 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -114,6 +114,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 indexed paranetKCTokenId, address minerAddress ); + event DebugOwner(uint256 minted, uint256 burnedCount, uint256 activeCount, uint256 ownedCountInRange); string private constant _NAME = "Paranet"; string private constant _VERSION = "1.0.0"; From a9ad1aca8da21c060c33e1f87e433610a60f20c5 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 21 Jan 2025 13:09:59 +0100 Subject: [PATCH 029/153] Add debugevent --- contracts/paranets/Paranet.sol | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index fecd3916..702f4a2c 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -1113,13 +1113,13 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // } // } - function _checkParanetOperator(bytes32 paranetId) internal view virtual { + function _checkParanetOperator(bytes32 paranetId) internal virtual { (address paranetKCStorageContract, uint256 paranetKCTokenId) = paranetsRegistry .getParanetKnowledgeCollectionLocator(paranetId); _checkKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId); } - function _checkParanetServiceOperator(bytes32 paranetServiceId) internal view virtual { + function _checkParanetServiceOperator(bytes32 paranetServiceId) internal virtual { (address paranetServiceKCStorageContract, uint256 paranetServiceKCTokenId) = paranetServicesRegistry .getParanetServiceKnowledgeCollectionLocator(paranetServiceId); _checkKnowledgeCollectionOwner(paranetServiceKCStorageContract, paranetServiceKCTokenId); @@ -1128,7 +1128,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { function _checkKnowledgeCollectionOwner( address knowledgeCollectionStorageContractAddress, uint256 knowledgeCollectionId - ) internal view virtual { + ) internal virtual { require(hub.isAssetStorage(knowledgeCollectionStorageContractAddress), "Given address isn't KC Storage"); KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage( @@ -1150,6 +1150,8 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { minted + burnedCount ); + emit DebugOwner(minted, burnedCount, activeCount, ownedCountInRange); + require(ownedCountInRange == activeCount, "Caller isn't the owner of the KC"); } } From 7cf3d642e40eb173ed8b57156a0c9de9e71b23a3 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 21 Jan 2025 13:19:47 +0100 Subject: [PATCH 030/153] Add local logs --- contracts/paranets/Paranet.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 702f4a2c..301ca629 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -16,6 +16,7 @@ import {IVersioned} from "../interfaces/IVersioned.sol"; import {ParanetLib} from "../libraries/ParanetLib.sol"; import {ProfileLib} from "../libraries/ProfileLib.sol"; import {KnowledgeCollectionLib} from "../libraries/KnowledgeCollectionLib.sol"; +import "hardhat/console.sol"; contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { event ParanetRegistered( @@ -1150,7 +1151,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { minted + burnedCount ); - emit DebugOwner(minted, burnedCount, activeCount, ownedCountInRange); + console.log(minted, burnedCount, activeCount, ownedCountInRange); require(ownedCountInRange == activeCount, "Caller isn't the owner of the KC"); } From 50779d785fdbcf4309a9e2cfaa0d1aa44afa38c8 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 21 Jan 2025 14:23:25 +0100 Subject: [PATCH 031/153] Remove debug code and fix how _checkKnowledgeCollectionOwner is calculated --- contracts/paranets/Paranet.sol | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 301ca629..1519f023 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -16,7 +16,6 @@ import {IVersioned} from "../interfaces/IVersioned.sol"; import {ParanetLib} from "../libraries/ParanetLib.sol"; import {ProfileLib} from "../libraries/ProfileLib.sol"; import {KnowledgeCollectionLib} from "../libraries/KnowledgeCollectionLib.sol"; -import "hardhat/console.sol"; contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { event ParanetRegistered( @@ -115,7 +114,6 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 indexed paranetKCTokenId, address minerAddress ); - event DebugOwner(uint256 minted, uint256 burnedCount, uint256 activeCount, uint256 ownedCountInRange); string private constant _NAME = "Paranet"; string private constant _VERSION = "1.0.0"; @@ -1135,7 +1133,6 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage( knowledgeCollectionStorageContractAddress ); - uint256 minted = knowledgeCollectionStorage.getMinted(knowledgeCollectionId); uint256 burnedCount = knowledgeCollectionStorage.getBurnedAmount(knowledgeCollectionId); uint256 activeCount = minted - burnedCount; @@ -1148,11 +1145,9 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 ownedCountInRange = knowledgeCollectionStorage.balanceOf( msg.sender, startTokenId, - minted + burnedCount + startTokenId + minted + burnedCount ); - console.log(minted, burnedCount, activeCount, ownedCountInRange); - require(ownedCountInRange == activeCount, "Caller isn't the owner of the KC"); } } From 70ea1f679ab59d7a12c5d0268242aeae5f6e94e5 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 21 Jan 2025 18:26:20 +0100 Subject: [PATCH 032/153] Update _checkKnowledgeCollectionOwner in ParanetIncentivesPoolFactory --- contracts/paranets/ParanetIncentivesPoolFactory.sol | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index e460927b..0db21459 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -105,13 +105,12 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn function _checkKnowledgeCollectionOwner( address knowledgeCollectionStorageContractAddress, uint256 knowledgeCollectionId - ) internal view virtual { + ) internal virtual { require(hub.isAssetStorage(knowledgeCollectionStorageContractAddress), "Given address isn't KC Storage"); KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage( knowledgeCollectionStorageContractAddress ); - uint256 minted = knowledgeCollectionStorage.getMinted(knowledgeCollectionId); uint256 burnedCount = knowledgeCollectionStorage.getBurnedAmount(knowledgeCollectionId); uint256 activeCount = minted - burnedCount; @@ -124,7 +123,7 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn uint256 ownedCountInRange = knowledgeCollectionStorage.balanceOf( msg.sender, startTokenId, - minted + burnedCount + startTokenId + minted + burnedCount ); require(ownedCountInRange == activeCount, "Caller isn't the owner of the KC"); From bdb071a4c93ebf0d2e1cc36be54ca2f49b3210cf Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 21 Jan 2025 18:35:12 +0100 Subject: [PATCH 033/153] Change reverte msg --- contracts/paranets/Paranet.sol | 3 +-- contracts/paranets/ParanetIncentivesPoolFactory.sol | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 1519f023..98941d79 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -823,7 +823,6 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 limit ) external view returns (ParanetLib.UniversalCollectionLocator[] memory) { ParanetsRegistry pr = paranetsRegistry; - bytes32[] memory knowledgeCollections = pr.getKnowledgeCollectionsWithPagination(paranetId, offset, limit); ParanetKnowledgeCollectionsRegistry pkcr = paranetKnowledgeCollectionsRegistry; @@ -1136,7 +1135,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 minted = knowledgeCollectionStorage.getMinted(knowledgeCollectionId); uint256 burnedCount = knowledgeCollectionStorage.getBurnedAmount(knowledgeCollectionId); uint256 activeCount = minted - burnedCount; - require(activeCount != 0, "No KCs in Collection"); + require(activeCount != 0, "No KAs in Collection"); uint256 startTokenId = (knowledgeCollectionId - 1) * knowledgeCollectionStorage.knowledgeCollectionMaxSize() + diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index 0db21459..7621f612 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -114,7 +114,7 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn uint256 minted = knowledgeCollectionStorage.getMinted(knowledgeCollectionId); uint256 burnedCount = knowledgeCollectionStorage.getBurnedAmount(knowledgeCollectionId); uint256 activeCount = minted - burnedCount; - require(activeCount != 0, "No KCs in Collection"); + require(activeCount != 0, "No KAs in Collection"); uint256 startTokenId = (knowledgeCollectionId - 1) * knowledgeCollectionStorage.knowledgeCollectionMaxSize() + From e847d002d81cec0642317b8c5e77d3bacc1661eb Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 22 Jan 2025 12:36:38 +0100 Subject: [PATCH 034/153] Version bump --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1b336b86..06ab018c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "dkg-evm-module", - "version": "8.0.0", + "version": "8.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "dkg-evm-module", - "version": "8.0.0", + "version": "8.0.1", "license": "Apache-2.0", "dependencies": { "@openzeppelin/contracts": "^5.1.0", diff --git a/package.json b/package.json index 1c880046..6edd4b51 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dkg-evm-module", - "version": "8.0.0", + "version": "8.0.1", "description": "Smart contracts for OriginTrail V8", "main": "index.ts", "files": [ From b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 22 Jan 2025 13:21:51 +0100 Subject: [PATCH 035/153] Fix isParanetOperator in ParanetNeuroIncentivesPool --- contracts/paranets/ParanetNeuroIncentivesPool.sol | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/contracts/paranets/ParanetNeuroIncentivesPool.sol b/contracts/paranets/ParanetNeuroIncentivesPool.sol index 51303c2e..fc88b94b 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPool.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPool.sol @@ -264,7 +264,11 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { uint256 startTokenId = (paranetKCTokenId - 1) * knowledgeCollectionStorage.knowledgeCollectionMaxSize() + 1; // _startTokenId() - uint256 ownedCountInRange = knowledgeCollectionStorage.balanceOf(addr, startTokenId, minted + burnedCount); + uint256 ownedCountInRange = knowledgeCollectionStorage.balanceOf( + addr, + startTokenId, + startTokenId + minted + burnedCount + ); return ownedCountInRange == activeCount; } From 6fbacb268cf9afca7617179a7064e0ee1e14123f Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 22 Jan 2025 14:26:14 +0100 Subject: [PATCH 036/153] Update deployments --- deployments/base_sepolia_test_contracts.json | 55 ++++++++++++-- deployments/gnosis_chiado_test_contracts.json | 55 ++++++++++++-- deployments/neuroweb_testnet_contracts.json | 72 +++++++++++++++++-- 3 files changed, 166 insertions(+), 16 deletions(-) diff --git a/deployments/base_sepolia_test_contracts.json b/deployments/base_sepolia_test_contracts.json index 2ac7be33..42dc4eba 100644 --- a/deployments/base_sepolia_test_contracts.json +++ b/deployments/base_sepolia_test_contracts.json @@ -173,12 +173,12 @@ "deployed": true }, "KnowledgeCollection": { - "evmAddress": "0x46121121F78f8351DA4526813FbfBffD044dec6c", + "evmAddress": "0xA85c3117fA62176830ADA98A6d429c0D0947cEFb", "version": "1.0.0", - "gitBranch": "v8-contracts", - "gitCommitHash": "ddb3f9e1ef7c2f9f7ca8554b19fae7d521a5507f", - "deploymentBlock": 19684808, - "deploymentTimestamp": 1735137910837, + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 20892002, + "deploymentTimestamp": 1737552295950, "deployed": true }, "Migrator": { @@ -189,6 +189,51 @@ "deploymentBlock": 19684813, "deploymentTimestamp": 1735137919078, "deployed": true + }, + "ParanetsRegistry": { + "evmAddress": "0x5960930cC6A47A4606fa05Fe26ca9A6Eb2250097", + "version": "1.0.1", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 20891862, + "deploymentTimestamp": 1737552017110, + "deployed": true + }, + "ParanetServicesRegistry": { + "evmAddress": "0x6e1E82955f00CF8Bf062e8B35608B0fFE3FC4Df6", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 20891866, + "deploymentTimestamp": 1737552023350, + "deployed": true + }, + "ParanetKnowledgeCollectionsRegistry": { + "evmAddress": "0xB7f43dc2f4863a3a771F7E7e2BF08adc1de68fC7", + "version": "1.0.1", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 20891869, + "deploymentTimestamp": 1737552029843, + "deployed": true + }, + "ParanetKnowledgeMinersRegistry": { + "evmAddress": "0x91EF627b8581D41658611b1b376FF31b9a3884ea", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 20891872, + "deploymentTimestamp": 1737552036245, + "deployed": true + }, + "Paranet": { + "evmAddress": "0x8DBfBe94a5E24d8Bd4ea3e933C77C054128F29b5", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 20891875, + "deploymentTimestamp": 1737552043122, + "deployed": true } } } diff --git a/deployments/gnosis_chiado_test_contracts.json b/deployments/gnosis_chiado_test_contracts.json index fd7b30b4..9db54c25 100644 --- a/deployments/gnosis_chiado_test_contracts.json +++ b/deployments/gnosis_chiado_test_contracts.json @@ -173,12 +173,12 @@ "deployed": true }, "KnowledgeCollection": { - "evmAddress": "0xdd2B900b121CD258Fbfd05C1C0482C0E25582f2C", + "evmAddress": "0x27F52c0d7289A982D76F74De1adeFBFCB1EB8ed8", "version": "1.0.0", - "gitBranch": "v8-contracts", - "gitCommitHash": "ddb3f9e1ef7c2f9f7ca8554b19fae7d521a5507f", - "deploymentBlock": 13494299, - "deploymentTimestamp": 1735137979260, + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 13947424, + "deploymentTimestamp": 1737552337932, "deployed": true }, "Migrator": { @@ -189,6 +189,51 @@ "deploymentBlock": 13494301, "deploymentTimestamp": 1735137986444, "deployed": true + }, + "ParanetsRegistry": { + "evmAddress": "0xd926A082A87D3A2536a48CAff6a9B8583434B1D7", + "version": "1.0.1", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 13947383, + "deploymentTimestamp": 1737552116734, + "deployed": true + }, + "ParanetServicesRegistry": { + "evmAddress": "0x0495C0251A3fCbe3561abD033A2Cb54f752d46eD", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 13947384, + "deploymentTimestamp": 1737552121766, + "deployed": true + }, + "ParanetKnowledgeCollectionsRegistry": { + "evmAddress": "0x6499c0006a5408Ca7A5D1380E4f7d0e3e2C23650", + "version": "1.0.1", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 13947385, + "deploymentTimestamp": 1737552126777, + "deployed": true + }, + "ParanetKnowledgeMinersRegistry": { + "evmAddress": "0x1769C41E2B8ddbb1F429fA0aF453Bb34cce52D60", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 13947386, + "deploymentTimestamp": 1737552131790, + "deployed": true + }, + "Paranet": { + "evmAddress": "0x8e49110922bC01241f434B4dAc0Fbc335FeBE63C", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 13947388, + "deploymentTimestamp": 1737552145114, + "deployed": true } } } diff --git a/deployments/neuroweb_testnet_contracts.json b/deployments/neuroweb_testnet_contracts.json index 74566147..d6d23f9c 100644 --- a/deployments/neuroweb_testnet_contracts.json +++ b/deployments/neuroweb_testnet_contracts.json @@ -192,13 +192,13 @@ "deployed": true }, "KnowledgeCollection": { - "evmAddress": "0x731227B9B8eB9B1ad209585cec3e0568278a0C89", - "substrateAddress": "5EMjsczjESbn133kUVssGUuA55dCkRtKK1LTYeoULYqASafv", + "evmAddress": "0xD842553c0a6C1C1427db6B56Ab3299F575a726F2", + "substrateAddress": "5EMjsd15WQzb9JzKqn2kvi2PXHnfL8JFjn9Gi1bH29FGE2WU", "version": "1.0.0", - "gitBranch": "v8-contracts", - "gitCommitHash": "ddb3f9e1ef7c2f9f7ca8554b19fae7d521a5507f", - "deploymentBlock": 5706407, - "deploymentTimestamp": 1735137995151, + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 6086206, + "deploymentTimestamp": 1737551947852, "deployed": true }, "Migrator": { @@ -210,6 +210,66 @@ "deploymentBlock": 5706409, "deploymentTimestamp": 1735138003714, "deployed": true + }, + "ParanetsRegistry": { + "evmAddress": "0x03fD0638d57e1DFf059cfB0A59D465d96bc3d381", + "substrateAddress": "5EMjsczLyUsdcHaiGPvbVQtY5RrHNDDNdGz56TkyLhkGqyjB", + "version": "1.0.1", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 6086202, + "deploymentTimestamp": 1737551926889, + "deployed": true + }, + "ParanetServicesRegistry": { + "evmAddress": "0xE56Ac2244FCFb20D3B7d7eFfd9EB9B3490fd1C8d", + "substrateAddress": "5EMjsd189L9Y8LfKAMeFQZ2jzZQWqWA2rpZeDqysvNSni8B8", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 6086203, + "deploymentTimestamp": 1737551931960, + "deployed": true + }, + "ParanetKnowledgeCollectionsRegistry": { + "evmAddress": "0xA6f3E79c083aFc6Bf69bFbA4cb488A98d70481b7", + "substrateAddress": "5EMjsczudPoVZCQMERLv7QbbGJR7fZCFQvdx2vYX4faDRiSZ", + "version": "1.0.1", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 6086204, + "deploymentTimestamp": 1737551937030, + "deployed": true + }, + "ParanetKnowledgeMinersRegistry": { + "evmAddress": "0xdc65788847B633C8Ea6A90e65E67a7A431f10244", + "substrateAddress": "5EMjsd16LVjR5mXywuAMRgFA9vVPBnk7r2VstqK5txaT4aHw", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 6086205, + "deploymentTimestamp": 1737551942154, + "deployed": true + }, + "Paranet": { + "evmAddress": "0x2d2bAddadD98AD4BFCDd3F3A6d20D6b5c21297DA", + "substrateAddress": "5EMjsczVE5xz2ejNb3s3Xc8mRwrLhBi86L5LiBtHMzgjkga7", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 6086207, + "deploymentTimestamp": 1737551953213, + "deployed": true + }, + "ParanetIncentivesPoolFactory": { + "evmAddress": "0x0A7301DE4a368E22C7Bb3F6786a00daCFAC51Fb3", + "substrateAddress": "5EMjsczNGZrZL176FuPFJS3H8TXFkHGWexw6aC2ui9gpy7DH", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", + "deploymentBlock": 6086208, + "deploymentTimestamp": 1737551962358, + "deployed": true } } } From 1cf13968f378b58f7d08b35bf4558f70784be8e4 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 24 Jan 2025 12:33:37 +0100 Subject: [PATCH 037/153] wip --- contracts/libraries/ParanetLib.sol | 11 +- contracts/paranets/Paranet.sol | 142 +++++++++++++----- .../storage/paranets/ParanetsRegistry.sol | 15 +- 3 files changed, 123 insertions(+), 45 deletions(-) diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index f4bef2a1..3d780603 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -58,6 +58,7 @@ library ParanetLib { struct Paranet { address paranetKCStorageContract; uint256 paranetKCTokenId; + uint256 paranetKATokenId; string name; string description; NodesAccessPolicy nodesAccessPolicy; @@ -86,6 +87,7 @@ library ParanetLib { struct ParanetMetadata { address paranetKCStorageContract; uint256 paranetKCTokenId; + uint256 paranetKATokenId; string name; string description; NodesAccessPolicy nodesAccessPolicy; @@ -173,7 +175,8 @@ library ParanetLib { error ParanetHasAlreadyBeenRegistered( address knowledgeCollectionStorageAddress, - uint256 knowledgeCollectionTokenId + uint256 knowledgeCollectionTokenId, + uint256 knowledgeAssetTokenId ); error InvalidParanetNodesAccessPolicy( ParanetLib.NodesAccessPolicy[] expectedAccessPolicies, @@ -205,7 +208,11 @@ library ParanetLib { string poolType, address poolAddress ); - error ParanetDoesntExist(address knowledgeCollectionStorageAddress, uint256 knowledgeCollectionTokenId); + error ParanetDoesntExist( + address knowledgeCollectionStorageAddress, + uint256 knowledgeCollectionTokenId, + uint256 knowledgeAssetTokenId + ); error ParanetServiceHasAlreadyBeenRegistered( address knowledgeCollectionStorageAddress, uint256 knowledgeCollectionTokenId diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 98941d79..74104a1d 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -21,6 +21,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { event ParanetRegistered( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, + uint256 indexed parnetKATokenId, string paranetName, string paranetDescription, ParanetLib.NodesAccessPolicy nodesAccessPolicy, @@ -160,22 +161,28 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { function registerParanet( address paranetKCStorageContract, uint256 paranetKCTokenId, + uint256 paranetKATokenId, string calldata paranetName, string calldata paranetDescription, ParanetLib.NodesAccessPolicy nodesAccessPolicy, ParanetLib.MinersAccessPolicy minersAccessPolicy - ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) returns (bytes32) { + ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) returns (bytes32) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); if (pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetHasAlreadyBeenRegistered(paranetKCStorageContract, paranetKCTokenId); + revert ParanetLib.ParanetHasAlreadyBeenRegistered( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId + ); } emit ParanetRegistered( paranetKCStorageContract, paranetKCTokenId, + paranetKATokenId, paranetName, paranetDescription, nodesAccessPolicy, @@ -187,6 +194,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pr.registerParanet( paranetKCStorageContract, paranetKCTokenId, + paranetKATokenId, paranetName, paranetDescription, nodesAccessPolicy, @@ -198,35 +206,43 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { function updateParanetMetadata( address paranetKCStorageContract, uint256 paranetKCTokenId, + uint256 paranetKATokenId, string calldata paranetName, string calldata paranetDescription - ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { + ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } pr.setName(paranetId, paranetName); pr.setDescription(paranetId, paranetDescription); - emit ParanetMetadataUpdated(paranetKCStorageContract, paranetKCTokenId, paranetName, paranetDescription); + emit ParanetMetadataUpdated( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetName, + paranetDescription + ); } function addParanetCuratedNodes( address paranetKCStorageContract, uint256 paranetKCTokenId, + uint256 paranetKATokenId, uint72[] calldata identityIds - ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { + ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, onlyKnowledgeAssetOwner) { ParanetsRegistry pr = paranetsRegistry; ProfileStorage ps = profileStorage; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } if (pr.getNodesAccessPolicy(paranetId) != ParanetLib.NodesAccessPolicy.CURATED) { @@ -261,14 +277,15 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { function removeParanetCuratedNodes( address paranetKCStorageContract, uint256 paranetKCTokenId, + uint256 paranetKATokenId, uint72[] calldata identityIds - ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { + ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } if (pr.getNodesAccessPolicy(paranetId) != ParanetLib.NodesAccessPolicy.CURATED) { @@ -288,7 +305,12 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pr.removeCuratedNode(paranetId, identityIds[i]); - emit ParanetCuratedNodeRemoved(paranetKCStorageContract, paranetKCTokenId, identityIds[i]); + emit ParanetCuratedNodeRemoved( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + identityIds[i] + ); unchecked { i++; @@ -296,13 +318,17 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { } } - function requestParanetCuratedNodeAccess(address paranetKCStorageContract, uint256 paranetKCTokenId) external { + function requestParanetCuratedNodeAccess( + address paranetKCStorageContract, + uint256 paranetKCTokenId, + uint256 paranetKATokenId + ) external { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } if (pr.getNodesAccessPolicy(paranetId) != ParanetLib.NodesAccessPolicy.CURATED) { @@ -339,20 +365,26 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pr.addNodeJoinRequest(paranetId, identityId, ParanetLib.RequestStatus.PENDING); - emit ParanetCuratedNodeJoinRequestCreated(paranetKCStorageContract, paranetKCTokenId, identityId); + emit ParanetCuratedNodeJoinRequestCreated( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + identityId + ); } function approveCuratedNode( address paranetKCStorageContract, uint256 paranetKCTokenId, + uint256 paranetKATokenId, uint72 identityId - ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { + ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } if (pr.getNodesAccessPolicy(paranetId) != ParanetLib.NodesAccessPolicy.CURATED) { @@ -390,21 +422,27 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); pr.addCuratedNode(paranetId, identityId, profileStorage.getNodeId(identityId)); - emit ParanetCuratedNodeJoinRequestAccepted(paranetKCStorageContract, paranetKCTokenId, identityId); - emit ParanetCuratedNodeAdded(paranetKCStorageContract, paranetKCTokenId, identityId); + emit ParanetCuratedNodeJoinRequestAccepted( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + identityId + ); + emit ParanetCuratedNodeAdded(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, identityId); } function rejectCuratedNode( address paranetKCStorageContract, uint256 paranetKCTokenId, + uint256 paranetKATokenId, uint72 identityId - ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { + ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } if (pr.getNodesAccessPolicy(paranetId) != ParanetLib.NodesAccessPolicy.CURATED) { @@ -441,21 +479,27 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ParanetLib.RequestStatus.REJECTED ); - emit ParanetCuratedNodeJoinRequestRejected(paranetKCStorageContract, paranetKCTokenId, identityId); + emit ParanetCuratedNodeJoinRequestRejected( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + identityId + ); } function addParanetServices( address paranetKCStorageContract, uint256 paranetKCTokenId, + uint256 paranetKATokenId, ParanetLib.UniversalCollectionLocator[] calldata services - ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { + ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; ParanetServicesRegistry psr = paranetServicesRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } for (uint256 i; i < services.length; ) { @@ -515,6 +559,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { emit ParanetServiceAdded( paranetKCStorageContract, paranetKCTokenId, + paranetKATokenId, services[i].knowledgeCollectionStorageContract, services[i].knowledgeCollectionTokenId ); @@ -528,12 +573,13 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { function registerParanetService( address paranetServiceKCStorageContract, uint256 paranetServiceKCTokenId, + uint256 paranetKATokenId, string calldata paranetServiceName, string calldata paranetServiceDescription, address[] calldata paranetServiceAddresses ) external - onlyKnowledgeCollectionOwner(paranetServiceKCStorageContract, paranetServiceKCTokenId) + onlyKnowledgeAssetOwner(paranetServiceKCStorageContract, paranetServiceKCTokenId, paranetKATokenId) returns (bytes32) { ParanetServicesRegistry psr = paranetServicesRegistry; @@ -600,15 +646,16 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { function addParanetCuratedMiners( address paranetKCStorageContract, uint256 paranetKCTokenId, + uint256 paranetKATokenId, address[] calldata minerAddresses - ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { + ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } if (pr.getMinersAccessPolicy(paranetId) != ParanetLib.MinersAccessPolicy.CURATED) { @@ -632,7 +679,12 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pr.addKnowledgeMiner(paranetId, minerAddresses[i]); - emit ParanetCuratedMinerAdded(paranetKCStorageContract, paranetKCTokenId, minerAddresses[i]); + emit ParanetCuratedMinerAdded( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + minerAddresses[i] + ); unchecked { i++; @@ -643,14 +695,15 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { function removeParanetCuratedMiners( address paranetKCStorageContract, uint256 paranetKCTokenId, + uint256 paranetKATokenId, address[] calldata minerAddresses - ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { + ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } if (pr.getMinersAccessPolicy(paranetId) != ParanetLib.MinersAccessPolicy.CURATED) { @@ -670,7 +723,12 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pr.removeKnowledgeMiner(paranetId, minerAddresses[i]); - emit ParanetCuratedMinerRemoved(paranetKCStorageContract, paranetKCTokenId, minerAddresses[i]); + emit ParanetCuratedMinerRemoved( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + minerAddresses[i] + ); unchecked { i++; @@ -678,7 +736,11 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { } } - function requestParanetCuratedMinerAccess(address paranetKCStorageContract, uint256 paranetKCTokenId) external { + function requestParanetCuratedMinerAccess( + address paranetKCStorageContract, + uint256 paranetKCTokenId, + uint256 paranetKATokenId + ) external { ParanetsRegistry pr = paranetsRegistry; bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); diff --git a/contracts/storage/paranets/ParanetsRegistry.sol b/contracts/storage/paranets/ParanetsRegistry.sol index 8bcd2a5b..5b0a823d 100644 --- a/contracts/storage/paranets/ParanetsRegistry.sol +++ b/contracts/storage/paranets/ParanetsRegistry.sol @@ -34,18 +34,22 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { function registerParanet( address knowledgeCollectionStorageContract, uint256 knowledgeCollectionTokenId, + uint256 knowledgeAssetTokenId, string calldata paranetName, string calldata paranetDescription, ParanetLib.NodesAccessPolicy nodesAccessPolicy, ParanetLib.MinersAccessPolicy minersAccessPolicy, ParanetLib.KnowledgeCollectionsAccessPolicy knowledgeColletionsAccessPolicy ) external onlyContracts returns (bytes32) { - bytes32 paranetId = keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)); + bytes32 paranetId = keccak256( + abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId, knowledgeAssetTokenId) + ); ParanetLib.Paranet storage paranet = paranets[paranetId]; paranet.paranetKCStorageContract = knowledgeCollectionStorageContract; paranet.paranetKCTokenId = knowledgeCollectionTokenId; + paranet.paranetKATokenId = knowledgeAssetTokenId; paranet.name = paranetName; paranet.description = paranetDescription; paranet.nodesAccessPolicy = nodesAccessPolicy; @@ -86,6 +90,7 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { ParanetLib.ParanetMetadata({ paranetKCStorageContract: paranet.paranetKCStorageContract, paranetKCTokenId: paranet.paranetKCTokenId, + paranetKATokenId: paranet.paranetKATokenId, name: paranet.name, description: paranet.description, nodesAccessPolicy: paranet.nodesAccessPolicy, @@ -95,8 +100,12 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { }); } - function getParanetKnowledgeCollectionLocator(bytes32 paranetId) external view returns (address, uint256) { - return (paranets[paranetId].paranetKCStorageContract, paranets[paranetId].paranetKCTokenId); + function getParanetKnowledgeAssetLocator(bytes32 paranetId) external view returns (address, uint256, uint256) { + return ( + paranets[paranetId].paranetKCStorageContract, + paranets[paranetId].paranetKCTokenId, + paranets[paranetId].paranetKATokenId + ); } function getName(bytes32 paranetId) external view returns (string memory) { From c74bddf5625578db33eb8c6c32e66c989b346aba Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 24 Jan 2025 14:28:22 +0100 Subject: [PATCH 038/153] wip --- contracts/libraries/ParanetLib.sol | 1 + contracts/paranets/Paranet.sol | 130 ++++++++++++++---- .../paranets/ParanetIncentivesPoolFactory.sol | 43 +++--- .../paranets/ParanetNeuroIncentivesPool.sol | 23 +--- 4 files changed, 134 insertions(+), 63 deletions(-) diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index 3d780603..aaa85fd9 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -205,6 +205,7 @@ library ParanetLib { error ParanetIncentivesPoolAlreadyExists( address knowledgeCollectionStorageAddress, uint256 knowledgeCollectionTokenId, + uint256 knowledgeAssetTokenId, string poolType, address poolAddress ); diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 74104a1d..a1720dc0 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -31,43 +31,51 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { event ParanetCuratedNodeAdded( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, + uint256 indexed paranetKATokenId, uint72 identityId ); event ParanetCuratedNodeRemoved( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, + uint256 indexed paranetKATokenId, uint72 identityId ); event ParanetCuratedNodeJoinRequestCreated( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, + uint256 indexed paranetKATokenId, uint72 identityId ); event ParanetCuratedNodeJoinRequestAccepted( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, + uint256 indexed paranetKATokenId, uint72 identityId ); event ParanetCuratedNodeJoinRequestRejected( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, + uint256 indexed paranetKATokenId, uint72 identityId ); event ParanetIncetivesPoolDeployed( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, + uint256 indexed paranetKATokenId, ParanetLib.IncentivesPool incentivesPool ); event ParanetMetadataUpdated( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, + uint256 indexed paranetKATokenId, string newParanetName, string newParanetDescription ); event ParanetServiceAdded( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, - address indexed paranetServiceKCStorageContract, + uint256 indexed paranetKATokenId, + address paranetServiceKCStorageContract, uint256 paranetServiceKCTokenId ); event ParanetServiceRegistered( @@ -87,32 +95,38 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { event KnowledgeCollectionSubmittedToParanet( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, - address indexed knowledgeCollectionStorageContract, + uint256 indexed paranetKATokenId, + address knowledgeCollectionStorageContract, uint256 knowledgeCollectionId ); event ParanetCuratedMinerAdded( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, + uint256 indexed paranetKATokenId, address minerAddress ); event ParanetCuratedMinerRemoved( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, + uint256 indexed paranetKATokenId, address minerAddress ); event ParanetCuratedMinerAccessRequestCreated( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, + uint256 indexed paranetKATokenId, address minerAddress ); event ParanetCuratedMinerAccessRequestAccepted( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, + uint256 indexed paranetKATokenId, address minerAddress ); event ParanetCuratedMinerAccessRequestRejected( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, + uint256 indexed paranetKATokenId, address minerAddress ); @@ -137,6 +151,19 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { _; } + modifier onlyKnowledgeAssetOwner( + address knowledgeCollectionStorageContract, + uint256 knowledgeCollectionTokenId, + uint256 knowledgeAssetTokenId + ) { + _checkKnowledgeAssetOwner( + knowledgeCollectionStorageContract, + knowledgeCollectionTokenId, + knowledgeAssetTokenId + ); + _; + } + function initialize() public onlyHub { profileStorage = ProfileStorage(hub.getContractAddress("ProfileStorage")); identityStorage = IdentityStorage(hub.getContractAddress("IdentityStorage")); @@ -235,7 +262,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 paranetKCTokenId, uint256 paranetKATokenId, uint72[] calldata identityIds - ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, onlyKnowledgeAssetOwner) { + ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; ProfileStorage ps = profileStorage; @@ -266,7 +293,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pr.addCuratedNode(paranetId, identityIds[i], ps.getNodeId(identityIds[i])); - emit ParanetCuratedNodeAdded(paranetKCStorageContract, paranetKCTokenId, identityIds[i]); + emit ParanetCuratedNodeAdded(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, identityIds[i]); unchecked { i++; @@ -378,7 +405,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 paranetKCTokenId, uint256 paranetKATokenId, uint72 identityId - ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { + ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); @@ -743,10 +770,10 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ) external { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } if (pr.getMinersAccessPolicy(paranetId) != ParanetLib.MinersAccessPolicy.CURATED) { @@ -776,20 +803,26 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pr.addKnowledgeMinerAccessRequest(paranetId, msg.sender, ParanetLib.RequestStatus.PENDING); - emit ParanetCuratedMinerAccessRequestCreated(paranetKCStorageContract, paranetKCTokenId, msg.sender); + emit ParanetCuratedMinerAccessRequestCreated( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + msg.sender + ); } function approveCuratedMiner( address paranetKCStorageContract, uint256 paranetKCTokenId, + uint256 paranetKATokenId, address minerAddress - ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { + ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } if (pr.getMinersAccessPolicy(paranetId) != ParanetLib.MinersAccessPolicy.CURATED) { @@ -826,21 +859,27 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); pr.addKnowledgeMiner(paranetId, minerAddress); - emit ParanetCuratedMinerAccessRequestAccepted(paranetKCStorageContract, paranetKCTokenId, minerAddress); - emit ParanetCuratedMinerAdded(paranetKCStorageContract, paranetKCTokenId, minerAddress); + emit ParanetCuratedMinerAccessRequestAccepted( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + minerAddress + ); + emit ParanetCuratedMinerAdded(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, minerAddress); } function rejectCuratedMiner( address paranetKCStorageContract, uint256 paranetKCTokenId, + uint256 paranetKATokenId, address minerAddress - ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) { + ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId); + revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } if (pr.getMinersAccessPolicy(paranetId) != ParanetLib.MinersAccessPolicy.CURATED) { @@ -876,7 +915,12 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ParanetLib.RequestStatus.REJECTED ); - emit ParanetCuratedMinerAccessRequestRejected(paranetKCStorageContract, paranetKCTokenId, minerAddress); + emit ParanetCuratedMinerAccessRequestRejected( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + minerAddress + ); } function getKnowledgeCollectionLocatorsWithPagination( @@ -953,14 +997,28 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { function submitKnowledgeCollection( address paranetKCStorageContract, uint256 paranetKnowledgeCollectionId, + uint256 paranetKnowledgeAssetTokenId, address knowledgeCollectionStorageContract, uint256 knowledgeCollectionTokenId - ) external onlyKnowledgeCollectionOwner(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) { + ) + external + onlyKnowledgeAssetOwner( + knowledgeCollectionStorageContract, + knowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId + ) + { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionId)); + bytes32 paranetId = keccak256( + abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionId, paranetKnowledgeAssetTokenId) + ); if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKnowledgeCollectionId); + revert ParanetLib.ParanetDoesntExist( + paranetKCStorageContract, + paranetKnowledgeCollectionId, + paranetKnowledgeAssetTokenId + ); } ParanetLib.MinersAccessPolicy minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); @@ -1007,6 +1065,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { _updateSubmittedKnowledgeCollectionMetadata( paranetKCStorageContract, paranetKnowledgeCollectionId, + paranetKnowledgeAssetTokenId, knowledgeCollectionStorageContract, knowledgeCollectionTokenId, remainingTokenAmount, @@ -1016,6 +1075,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { emit KnowledgeCollectionSubmittedToParanet( paranetKCStorageContract, paranetKnowledgeCollectionId, + paranetKnowledgeAssetTokenId, knowledgeCollectionStorageContract, knowledgeCollectionTokenId ); @@ -1038,6 +1098,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { function _updateSubmittedKnowledgeCollectionMetadata( address paranetKCStorageContract, uint256 paranetKCTokenId, + uint256 paranetKATokenId, address knowledgeCollectionStorageContract, uint256 knowledgeCollectionTokenId, uint96 tokenAmount, @@ -1046,9 +1107,9 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ParanetsRegistry pr = paranetsRegistry; ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)); + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); bytes32 knowledgeCollectionId = keccak256( - abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) + abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId, paranetKATokenId) ); // Add Knowledge Collection to the KnowledgeCollectionsRegistry @@ -1174,9 +1235,9 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // } function _checkParanetOperator(bytes32 paranetId) internal virtual { - (address paranetKCStorageContract, uint256 paranetKCTokenId) = paranetsRegistry - .getParanetKnowledgeCollectionLocator(paranetId); - _checkKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId); + (address paranetKCStorageContract, uint256 paranetKCTokenId, uint256 paranetKATokenId) = paranetsRegistry + .getParanetKnowledgeAssetLocator(paranetId); + _checkKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } function _checkParanetServiceOperator(bytes32 paranetServiceId) internal virtual { @@ -1211,4 +1272,23 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { require(ownedCountInRange == activeCount, "Caller isn't the owner of the KC"); } + + function _checkKnowledgeAssetOwner( + address knowledgeCollectionStorageContractAddress, + uint256 knowledgeCollectionId, + uint256 knowledgeAssetId + ) internal virtual { + require(hub.isAssetStorage(knowledgeCollectionStorageContractAddress), "Given address isn't KC Storage"); + + KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage( + knowledgeCollectionStorageContractAddress + ); + + uint256 startTokenId = (knowledgeCollectionId - 1) * + knowledgeCollectionStorage.knowledgeCollectionMaxSize() + + knowledgeAssetId; + + uint256 ownedCountInRange = knowledgeCollectionStorage.balanceOf(msg.sender, startTokenId, startTokenId + 1); + require(ownedCountInRange == 1, "Caller isn't the owner of the KA"); + } } diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index 7621f612..fbd8bc67 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -27,11 +27,16 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn // solhint-disable-next-line no-empty-blocks constructor(address hubAddress) ContractStatus(hubAddress) {} - modifier onlyKnowledgeCollectionOwner( + modifier onlyKnowledgeAssetOwner( address knowledgeCollectionStorageContract, - uint256 knowledgeCollectionTokenId + uint256 knowledgeCollectionTokenId, + uint256 knowledgeAssetTokenId ) { - _checkKnowledgeCollectionOwner(knowledgeCollectionStorageContract, knowledgeCollectionTokenId); + _checkKnowledgeAssetOwner( + knowledgeCollectionStorageContract, + knowledgeCollectionTokenId, + knowledgeAssetTokenId + ); _; } @@ -51,26 +56,28 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn bool isNativeReward, address paranetKCStorageContract, uint256 paranetKCTokenId, + uint256 paranetKATokenId, uint256 tracToNeuroEmissionMultiplier, uint16 paranetOperatorRewardPercentage, uint16 paranetIncentivizationProposalVotersRewardPercentage - ) external onlyKnowledgeCollectionOwner(paranetKCStorageContract, paranetKCTokenId) returns (address) { + ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) returns (address) { Hub h = hub; ParanetsRegistry pr = paranetsRegistry; string memory incentivesPoolType = isNativeReward ? "Neuroweb" : "NeurowebERC20"; if ( pr.hasIncentivesPoolByType( - keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)), + keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)), incentivesPoolType ) ) { revert ParanetLib.ParanetIncentivesPoolAlreadyExists( paranetKCStorageContract, paranetKCTokenId, + paranetKATokenId, incentivesPoolType, pr.getIncentivesPoolAddress( - keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)), + keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)), incentivesPoolType ) ); @@ -81,14 +88,14 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn isNativeReward ? address(0) : h.getContractAddress(incentivesPoolType), h.getContractAddress("ParanetsRegistry"), h.getContractAddress("ParanetKnowledgeMinersRegistry"), - keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)), + keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)), tracToNeuroEmissionMultiplier, paranetOperatorRewardPercentage, paranetIncentivizationProposalVotersRewardPercentage ); pr.setIncentivesPoolAddress( - keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId)), + keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKCTokenId)), incentivesPoolType, address(incentivesPool) ); @@ -102,30 +109,22 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn return address(incentivesPool); } - function _checkKnowledgeCollectionOwner( + function _checkKnowledgeAssetOwner( address knowledgeCollectionStorageContractAddress, - uint256 knowledgeCollectionId + uint256 knowledgeCollectionId, + uint256 knowledgeAssetId ) internal virtual { require(hub.isAssetStorage(knowledgeCollectionStorageContractAddress), "Given address isn't KC Storage"); KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage( knowledgeCollectionStorageContractAddress ); - uint256 minted = knowledgeCollectionStorage.getMinted(knowledgeCollectionId); - uint256 burnedCount = knowledgeCollectionStorage.getBurnedAmount(knowledgeCollectionId); - uint256 activeCount = minted - burnedCount; - require(activeCount != 0, "No KAs in Collection"); uint256 startTokenId = (knowledgeCollectionId - 1) * knowledgeCollectionStorage.knowledgeCollectionMaxSize() + - 1; // _startTokenId() - - uint256 ownedCountInRange = knowledgeCollectionStorage.balanceOf( - msg.sender, - startTokenId, - startTokenId + minted + burnedCount - ); + knowledgeAssetId; - require(ownedCountInRange == activeCount, "Caller isn't the owner of the KC"); + uint256 ownedCountInRange = knowledgeCollectionStorage.balanceOf(msg.sender, startTokenId, startTokenId + 1); + require(ownedCountInRange == 1, "Caller isn't the owner of the KA"); } } diff --git a/contracts/paranets/ParanetNeuroIncentivesPool.sol b/contracts/paranets/ParanetNeuroIncentivesPool.sol index fc88b94b..fa004342 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPool.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPool.sol @@ -250,27 +250,18 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { } function isParanetOperator(address addr) public view returns (bool) { - (address paranetKCStorageContract, uint256 paranetKCTokenId) = paranetsRegistry - .getParanetKnowledgeCollectionLocator(parentParanetId); + (address paranetKCStorageContract, uint256 paranetKCTokenId, uint256 paranetKATokenId) = paranetsRegistry + .getParanetKnowledgeAssetLocator(parentParanetId); KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage(paranetKCStorageContract); - uint256 minted = knowledgeCollectionStorage.getMinted(paranetKCTokenId); - uint256 burnedCount = knowledgeCollectionStorage.getBurnedAmount(paranetKCTokenId); - uint256 activeCount = minted - burnedCount; - if (activeCount == 0) { - return false; - } - - uint256 startTokenId = (paranetKCTokenId - 1) * knowledgeCollectionStorage.knowledgeCollectionMaxSize() + 1; // _startTokenId() + uint256 startTokenId = (paranetKCTokenId - 1) * + knowledgeCollectionStorage.knowledgeCollectionMaxSize() + + paranetKATokenId; - uint256 ownedCountInRange = knowledgeCollectionStorage.balanceOf( - addr, - startTokenId, - startTokenId + minted + burnedCount - ); + uint256 ownedCountInRange = knowledgeCollectionStorage.balanceOf(addr, startTokenId, startTokenId + 1); - return ownedCountInRange == activeCount; + return ownedCountInRange == 1; } function isProposalVoter(address addr) public view returns (bool) { From 87ee0d77c7b1109878f25ffb8ab4573753f447ab Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 24 Jan 2025 15:16:55 +0100 Subject: [PATCH 039/153] Update services --- contracts/libraries/ParanetLib.sol | 17 ++- contracts/paranets/Paranet.sol | 113 +++++++----------- .../paranets/ParanetServicesRegistry.sol | 13 +- .../storage/paranets/ParanetsRegistry.sol | 12 +- 4 files changed, 78 insertions(+), 77 deletions(-) diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index aaa85fd9..0d6bad7d 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -15,6 +15,12 @@ library ParanetLib { uint256 knowledgeCollectionTokenId; } + struct UniversalAssetLocator { + address knowledgeCollectionStorageContract; + uint256 knowledgeCollectionTokenId; + uint256 knowledgeAssetTokenId; + } + enum NodesAccessPolicy { OPEN, CURATED @@ -104,6 +110,7 @@ library ParanetLib { struct ParanetService { address paranetServiceKCStorageContract; uint256 paranetServiceKCTokenId; + uint256 paranetServiceKATokenId; string name; string description; address[] paranetServiceAddresses; @@ -113,6 +120,7 @@ library ParanetLib { struct ParanetServiceMetadata { address paranetServiceKCStorageContract; uint256 paranetServiceKCTokenId; + uint256 paranetServiceKATokenId; string name; string description; address[] paranetServiceAddresses; @@ -216,9 +224,14 @@ library ParanetLib { ); error ParanetServiceHasAlreadyBeenRegistered( address knowledgeCollectionStorageAddress, - uint256 knowledgeCollectionTokenId + uint256 knowledgeCollectionTokenId, + uint256 knowledgeAssetTokenId + ); + error ParanetServiceDoesntExist( + address knowledgeCollectionStorageAddress, + uint256 knowledgeCollectionTokenId, + uint256 knowledgeAssetTokenId ); - error ParanetServiceDoesntExist(address knowledgeCollectionStorageAddress, uint256 knowledgeCollectionTokenId); error KnowledgeCollectionIsAPartOfOtherParanet( address paranetKnowledgeCollectionStorageAddress, uint256 paranetKnowledgeCollectionTokenId, diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index a1720dc0..b9ec1be9 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -76,11 +76,13 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 indexed paranetKCTokenId, uint256 indexed paranetKATokenId, address paranetServiceKCStorageContract, - uint256 paranetServiceKCTokenId + uint256 paranetServiceKCTokenId, + uint256 paranetServiceKATokenId ); event ParanetServiceRegistered( address indexed paranetServiceKCStorageContract, uint256 indexed paranetServiceKCTokenId, + uint256 indexed paranetServiceKATokenId, string paranetServiceName, string paranetServiceDescription, address[] paranetServiceAddresses @@ -88,6 +90,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { event ParanetServiceMetadataUpdated( address indexed paranetServiceKCStorageContract, uint256 indexed paranetServiceKCTokenId, + uint256 indexed paranetServiceKATokenId, string newParanetServiceName, string newParanetServiceDescription, address[] newParanetServiceAddresses @@ -143,14 +146,6 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // solhint-disable-next-line no-empty-blocks constructor(address hubAddress) ContractStatus(hubAddress) {} - modifier onlyKnowledgeCollectionOwner( - address knowledgeCollectionStorageContract, - uint256 knowledgeCollectionTokenId - ) { - _checkKnowledgeCollectionOwner(knowledgeCollectionStorageContract, knowledgeCollectionTokenId); - _; - } - modifier onlyKnowledgeAssetOwner( address knowledgeCollectionStorageContract, uint256 knowledgeCollectionTokenId, @@ -518,7 +513,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { address paranetKCStorageContract, uint256 paranetKCTokenId, uint256 paranetKATokenId, - ParanetLib.UniversalCollectionLocator[] calldata services + ParanetLib.UniversalAssetLocator[] calldata services ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; ParanetServicesRegistry psr = paranetServicesRegistry; @@ -535,20 +530,23 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { keccak256( abi.encodePacked( services[i].knowledgeCollectionStorageContract, - services[i].knowledgeCollectionTokenId + services[i].knowledgeCollectionTokenId, + services[i].knowledgeAssetTokenId ) ) ) ) { revert ParanetLib.ParanetServiceDoesntExist( services[i].knowledgeCollectionStorageContract, - services[i].knowledgeCollectionTokenId + services[i].knowledgeCollectionTokenId, + services[i].knowledgeAssetTokenId ); } - _checkKnowledgeCollectionOwner( + _checkKnowledgeAssetOwner( services[i].knowledgeCollectionStorageContract, - services[i].knowledgeCollectionTokenId + services[i].knowledgeCollectionTokenId, + services[i].knowledgeAssetTokenId ); if ( @@ -557,7 +555,8 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { keccak256( abi.encodePacked( services[i].knowledgeCollectionStorageContract, - services[i].knowledgeCollectionTokenId + services[i].knowledgeCollectionTokenId, + services[i].knowledgeAssetTokenId ) ) ) @@ -567,7 +566,8 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { keccak256( abi.encodePacked( services[i].knowledgeCollectionStorageContract, - services[i].knowledgeCollectionTokenId + services[i].knowledgeCollectionTokenId, + services[i].knowledgeAssetTokenId ) ) ); @@ -578,7 +578,8 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { keccak256( abi.encodePacked( services[i].knowledgeCollectionStorageContract, - services[i].knowledgeCollectionTokenId + services[i].knowledgeCollectionTokenId, + services[i].knowledgeAssetTokenId ) ) ); @@ -588,7 +589,8 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { paranetKCTokenId, paranetKATokenId, services[i].knowledgeCollectionStorageContract, - services[i].knowledgeCollectionTokenId + services[i].knowledgeCollectionTokenId, + services[i].knowledgeAssetTokenId ); unchecked { @@ -600,31 +602,33 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { function registerParanetService( address paranetServiceKCStorageContract, uint256 paranetServiceKCTokenId, - uint256 paranetKATokenId, + uint256 paranetServiceKATokenId, string calldata paranetServiceName, string calldata paranetServiceDescription, address[] calldata paranetServiceAddresses ) external - onlyKnowledgeAssetOwner(paranetServiceKCStorageContract, paranetServiceKCTokenId, paranetKATokenId) + onlyKnowledgeAssetOwner(paranetServiceKCStorageContract, paranetServiceKCTokenId, paranetServiceKATokenId) returns (bytes32) { ParanetServicesRegistry psr = paranetServicesRegistry; bytes32 paranetServiceId = keccak256( - abi.encodePacked(paranetServiceKCStorageContract, paranetServiceKCTokenId) + abi.encodePacked(paranetServiceKCStorageContract, paranetServiceKCTokenId, paranetServiceKATokenId) ); if (psr.paranetServiceExists(paranetServiceId)) { revert ParanetLib.ParanetServiceHasAlreadyBeenRegistered( paranetServiceKCStorageContract, - paranetServiceKCTokenId + paranetServiceKCTokenId, + paranetServiceKATokenId ); } emit ParanetServiceRegistered( paranetServiceKCStorageContract, paranetServiceKCTokenId, + paranetServiceKATokenId, paranetServiceName, paranetServiceDescription, paranetServiceAddresses @@ -634,6 +638,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { psr.registerParanetService( paranetServiceKCStorageContract, paranetServiceKCTokenId, + paranetServiceKATokenId, paranetServiceName, paranetServiceDescription, paranetServiceAddresses @@ -643,18 +648,26 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { function updateParanetServiceMetadata( address paranetServiceKCStorageContract, uint256 paranetServiceKCTokenId, + uint256 paranetServiceKATokenId, string calldata paranetServiceName, string calldata paranetServiceDescription, address[] calldata paranetServiceAddresses - ) external onlyKnowledgeCollectionOwner(paranetServiceKCStorageContract, paranetServiceKCTokenId) { + ) + external + onlyKnowledgeAssetOwner(paranetServiceKCStorageContract, paranetServiceKCTokenId, paranetServiceKATokenId) + { ParanetServicesRegistry psr = paranetServicesRegistry; bytes32 paranetServiceId = keccak256( - abi.encodePacked(paranetServiceKCStorageContract, paranetServiceKCTokenId) + abi.encodePacked(paranetServiceKCStorageContract, paranetServiceKCTokenId, paranetServiceKATokenId) ); if (!psr.paranetServiceExists(paranetServiceId)) { - revert ParanetLib.ParanetServiceDoesntExist(paranetServiceKCStorageContract, paranetServiceKCTokenId); + revert ParanetLib.ParanetServiceDoesntExist( + paranetServiceKCStorageContract, + paranetServiceKCTokenId, + paranetServiceKATokenId + ); } psr.setName(paranetServiceId, paranetServiceName); @@ -664,6 +677,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { emit ParanetServiceMetadataUpdated( paranetServiceKCStorageContract, paranetServiceKCTokenId, + paranetServiceKATokenId, paranetServiceName, paranetServiceDescription, paranetServiceAddresses @@ -996,7 +1010,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { function submitKnowledgeCollection( address paranetKCStorageContract, - uint256 paranetKnowledgeCollectionId, + uint256 paranetKnowledgeCollectionTokenId, uint256 paranetKnowledgeAssetTokenId, address knowledgeCollectionStorageContract, uint256 knowledgeCollectionTokenId @@ -1010,13 +1024,13 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { { ParanetsRegistry pr = paranetsRegistry; bytes32 paranetId = keccak256( - abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionId, paranetKnowledgeAssetTokenId) + abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId) ); if (!pr.paranetExists(paranetId)) { revert ParanetLib.ParanetDoesntExist( paranetKCStorageContract, - paranetKnowledgeCollectionId, + paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId ); } @@ -1064,7 +1078,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // Update KnowledgeMiner metadata _updateSubmittedKnowledgeCollectionMetadata( paranetKCStorageContract, - paranetKnowledgeCollectionId, + paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId, knowledgeCollectionStorageContract, knowledgeCollectionTokenId, @@ -1074,7 +1088,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { emit KnowledgeCollectionSubmittedToParanet( paranetKCStorageContract, - paranetKnowledgeCollectionId, + paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId, knowledgeCollectionStorageContract, knowledgeCollectionTokenId @@ -1234,45 +1248,6 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // } // } - function _checkParanetOperator(bytes32 paranetId) internal virtual { - (address paranetKCStorageContract, uint256 paranetKCTokenId, uint256 paranetKATokenId) = paranetsRegistry - .getParanetKnowledgeAssetLocator(paranetId); - _checkKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - } - - function _checkParanetServiceOperator(bytes32 paranetServiceId) internal virtual { - (address paranetServiceKCStorageContract, uint256 paranetServiceKCTokenId) = paranetServicesRegistry - .getParanetServiceKnowledgeCollectionLocator(paranetServiceId); - _checkKnowledgeCollectionOwner(paranetServiceKCStorageContract, paranetServiceKCTokenId); - } - - function _checkKnowledgeCollectionOwner( - address knowledgeCollectionStorageContractAddress, - uint256 knowledgeCollectionId - ) internal virtual { - require(hub.isAssetStorage(knowledgeCollectionStorageContractAddress), "Given address isn't KC Storage"); - - KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage( - knowledgeCollectionStorageContractAddress - ); - uint256 minted = knowledgeCollectionStorage.getMinted(knowledgeCollectionId); - uint256 burnedCount = knowledgeCollectionStorage.getBurnedAmount(knowledgeCollectionId); - uint256 activeCount = minted - burnedCount; - require(activeCount != 0, "No KAs in Collection"); - - uint256 startTokenId = (knowledgeCollectionId - 1) * - knowledgeCollectionStorage.knowledgeCollectionMaxSize() + - 1; // _startTokenId() - - uint256 ownedCountInRange = knowledgeCollectionStorage.balanceOf( - msg.sender, - startTokenId, - startTokenId + minted + burnedCount - ); - - require(ownedCountInRange == activeCount, "Caller isn't the owner of the KC"); - } - function _checkKnowledgeAssetOwner( address knowledgeCollectionStorageContractAddress, uint256 knowledgeCollectionId, diff --git a/contracts/storage/paranets/ParanetServicesRegistry.sol b/contracts/storage/paranets/ParanetServicesRegistry.sol index 2088ddf6..a8c39d05 100644 --- a/contracts/storage/paranets/ParanetServicesRegistry.sol +++ b/contracts/storage/paranets/ParanetServicesRegistry.sol @@ -28,17 +28,19 @@ contract ParanetServicesRegistry is INamed, IVersioned, HubDependent { function registerParanetService( address paranetServiceKCStorageContract, uint256 paranetServiceKCTokenId, + uint256 paranetServiceKATokenId, string calldata paranetServiceName, string calldata paranetServiceDescription, address[] calldata paranetServiceAddresses ) external onlyContracts returns (bytes32) { bytes32 paranetServiceId = keccak256( - abi.encodePacked(paranetServiceKCStorageContract, paranetServiceKCTokenId) + abi.encodePacked(paranetServiceKCStorageContract, paranetServiceKCTokenId, paranetServiceKATokenId) ); ParanetLib.ParanetService storage paranetService = paranetServices[paranetServiceId]; paranetService.paranetServiceKCStorageContract = paranetServiceKCStorageContract; paranetService.paranetServiceKCTokenId = paranetServiceKCTokenId; + paranetService.paranetServiceKATokenId = paranetServiceKATokenId; paranetService.name = paranetServiceName; paranetService.description = paranetServiceDescription; paranetService.paranetServiceAddresses = paranetServiceAddresses; @@ -63,7 +65,8 @@ contract ParanetServicesRegistry is INamed, IVersioned, HubDependent { keccak256( abi.encodePacked( paranetServices[paranetServiceId].paranetServiceKCStorageContract, - paranetServices[paranetServiceId].paranetServiceKCTokenId + paranetServices[paranetServiceId].paranetServiceKCTokenId, + paranetServices[paranetServiceId].paranetServiceKATokenId ) ) == paranetServiceId; } @@ -75,6 +78,7 @@ contract ParanetServicesRegistry is INamed, IVersioned, HubDependent { ParanetLib.ParanetServiceMetadata({ paranetServiceKCStorageContract: paranetServices[paranetServiceId].paranetServiceKCStorageContract, paranetServiceKCTokenId: paranetServices[paranetServiceId].paranetServiceKCTokenId, + paranetServiceKATokenId: paranetServices[paranetServiceId].paranetServiceKATokenId, name: paranetServices[paranetServiceId].name, description: paranetServices[paranetServiceId].description, paranetServiceAddresses: paranetServices[paranetServiceId].paranetServiceAddresses @@ -83,10 +87,11 @@ contract ParanetServicesRegistry is INamed, IVersioned, HubDependent { function getParanetServiceKnowledgeCollectionLocator( bytes32 paranetServiceId - ) external view returns (address, uint256) { + ) external view returns (address, uint256, uint256) { return ( paranetServices[paranetServiceId].paranetServiceKCStorageContract, - paranetServices[paranetServiceId].paranetServiceKCTokenId + paranetServices[paranetServiceId].paranetServiceKCTokenId, + paranetServices[paranetServiceId].paranetServiceKATokenId ); } diff --git a/contracts/storage/paranets/ParanetsRegistry.sol b/contracts/storage/paranets/ParanetsRegistry.sol index 5b0a823d..763db4f9 100644 --- a/contracts/storage/paranets/ParanetsRegistry.sol +++ b/contracts/storage/paranets/ParanetsRegistry.sol @@ -80,7 +80,11 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { function paranetExists(bytes32 paranetId) external view returns (bool) { return keccak256( - abi.encodePacked(paranets[paranetId].paranetKCStorageContract, paranets[paranetId].paranetKCTokenId) + abi.encodePacked( + paranets[paranetId].paranetKCStorageContract, + paranets[paranetId].paranetKCTokenId, + paranets[paranetId].paranetKATokenId + ) ) == paranetId; } @@ -564,7 +568,11 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { function getParanetIdsMapping(bytes32 paranetId) external view returns (uint256) { require( keccak256( - abi.encodePacked(paranets[paranetId].paranetKCStorageContract, paranets[paranetId].paranetKCTokenId) + abi.encodePacked( + paranets[paranetId].paranetKCStorageContract, + paranets[paranetId].paranetKCTokenId, + paranets[paranetId].paranetKATokenId + ) ) == paranetId, "Paranet not found" ); From 1715370fab62657807c97ff7e96c507454a30d31 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Thu, 30 Jan 2025 10:12:36 +0100 Subject: [PATCH 040/153] wip --- abi/Paranet.json | 217 +++++++++++++++++++++++++- abi/ParanetIncentivesPoolFactory.json | 10 ++ abi/ParanetServicesRegistry.json | 15 ++ abi/ParanetsRegistry.json | 17 +- 4 files changed, 256 insertions(+), 3 deletions(-) diff --git a/abi/Paranet.json b/abi/Paranet.json index 2f029c96..08bc7d72 100644 --- a/abi/Paranet.json +++ b/abi/Paranet.json @@ -212,6 +212,11 @@ "internalType": "uint256", "name": "knowledgeCollectionTokenId", "type": "uint256" + }, + { + "internalType": "uint256", + "name": "knowledgeAssetTokenId", + "type": "uint256" } ], "name": "ParanetDoesntExist", @@ -228,6 +233,11 @@ "internalType": "uint256", "name": "knowledgeCollectionTokenId", "type": "uint256" + }, + { + "internalType": "uint256", + "name": "knowledgeAssetTokenId", + "type": "uint256" } ], "name": "ParanetHasAlreadyBeenRegistered", @@ -244,6 +254,11 @@ "internalType": "uint256", "name": "knowledgeCollectionTokenId", "type": "uint256" + }, + { + "internalType": "uint256", + "name": "knowledgeAssetTokenId", + "type": "uint256" } ], "name": "ParanetServiceDoesntExist", @@ -276,6 +291,11 @@ "internalType": "uint256", "name": "knowledgeCollectionTokenId", "type": "uint256" + }, + { + "internalType": "uint256", + "name": "knowledgeAssetTokenId", + "type": "uint256" } ], "name": "ParanetServiceHasAlreadyBeenRegistered", @@ -325,6 +345,12 @@ }, { "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "indexed": false, "internalType": "address", "name": "knowledgeCollectionStorageContract", "type": "address" @@ -354,6 +380,12 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "indexed": false, "internalType": "address", @@ -379,6 +411,12 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "indexed": false, "internalType": "address", @@ -404,6 +442,12 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "indexed": false, "internalType": "address", @@ -429,6 +473,12 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "indexed": false, "internalType": "address", @@ -454,6 +504,12 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "indexed": false, "internalType": "address", @@ -479,6 +535,12 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "indexed": false, "internalType": "uint72", @@ -504,6 +566,12 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "indexed": false, "internalType": "uint72", @@ -529,6 +597,12 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "indexed": false, "internalType": "uint72", @@ -554,6 +628,12 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "indexed": false, "internalType": "uint72", @@ -579,6 +659,12 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "indexed": false, "internalType": "uint72", @@ -604,6 +690,12 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "components": [ { @@ -641,6 +733,12 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "indexed": false, "internalType": "string", @@ -672,6 +770,12 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "indexed": true, + "internalType": "uint256", + "name": "parnetKATokenId", + "type": "uint256" + }, { "indexed": false, "internalType": "string", @@ -723,6 +827,12 @@ }, { "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "indexed": false, "internalType": "address", "name": "paranetServiceKCStorageContract", "type": "address" @@ -732,6 +842,12 @@ "internalType": "uint256", "name": "paranetServiceKCTokenId", "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "paranetServiceKATokenId", + "type": "uint256" } ], "name": "ParanetServiceAdded", @@ -752,6 +868,12 @@ "name": "paranetServiceKCTokenId", "type": "uint256" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetServiceKATokenId", + "type": "uint256" + }, { "indexed": false, "internalType": "string", @@ -789,6 +911,12 @@ "name": "paranetServiceKCTokenId", "type": "uint256" }, + { + "indexed": true, + "internalType": "uint256", + "name": "paranetServiceKATokenId", + "type": "uint256" + }, { "indexed": false, "internalType": "string", @@ -823,6 +951,11 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "internalType": "address[]", "name": "minerAddresses", @@ -846,6 +979,11 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "internalType": "uint72[]", "name": "identityIds", @@ -869,6 +1007,11 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "components": [ { @@ -880,9 +1023,14 @@ "internalType": "uint256", "name": "knowledgeCollectionTokenId", "type": "uint256" + }, + { + "internalType": "uint256", + "name": "knowledgeAssetTokenId", + "type": "uint256" } ], - "internalType": "struct ParanetLib.UniversalCollectionLocator[]", + "internalType": "struct ParanetLib.UniversalAssetLocator[]", "name": "services", "type": "tuple[]" } @@ -904,6 +1052,11 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "internalType": "address", "name": "minerAddress", @@ -927,6 +1080,11 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "internalType": "uint72", "name": "identityId", @@ -1102,6 +1260,11 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "internalType": "string", "name": "paranetName", @@ -1146,6 +1309,11 @@ "name": "paranetServiceKCTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "paranetServiceKATokenId", + "type": "uint256" + }, { "internalType": "string", "name": "paranetServiceName", @@ -1185,6 +1353,11 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "internalType": "address", "name": "minerAddress", @@ -1208,6 +1381,11 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "internalType": "uint72", "name": "identityId", @@ -1231,6 +1409,11 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "internalType": "address[]", "name": "minerAddresses", @@ -1254,6 +1437,11 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "internalType": "uint72[]", "name": "identityIds", @@ -1276,6 +1464,11 @@ "internalType": "uint256", "name": "paranetKCTokenId", "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" } ], "name": "requestParanetCuratedMinerAccess", @@ -1294,6 +1487,11 @@ "internalType": "uint256", "name": "paranetKCTokenId", "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" } ], "name": "requestParanetCuratedNodeAccess", @@ -1336,7 +1534,12 @@ }, { "internalType": "uint256", - "name": "paranetKnowledgeCollectionId", + "name": "paranetKnowledgeCollectionTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeAssetTokenId", "type": "uint256" }, { @@ -1367,6 +1570,11 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "internalType": "string", "name": "paranetName", @@ -1395,6 +1603,11 @@ "name": "paranetServiceKCTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "paranetServiceKATokenId", + "type": "uint256" + }, { "internalType": "string", "name": "paranetServiceName", diff --git a/abi/ParanetIncentivesPoolFactory.json b/abi/ParanetIncentivesPoolFactory.json index f3b72120..9d86e09c 100644 --- a/abi/ParanetIncentivesPoolFactory.json +++ b/abi/ParanetIncentivesPoolFactory.json @@ -22,6 +22,11 @@ "name": "knowledgeCollectionTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "knowledgeAssetTokenId", + "type": "uint256" + }, { "internalType": "string", "name": "poolType", @@ -106,6 +111,11 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "internalType": "uint256", "name": "tracToNeuroEmissionMultiplier", diff --git a/abi/ParanetServicesRegistry.json b/abi/ParanetServicesRegistry.json index 59e26327..3501f264 100644 --- a/abi/ParanetServicesRegistry.json +++ b/abi/ParanetServicesRegistry.json @@ -111,6 +111,11 @@ "name": "", "type": "address" }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, { "internalType": "uint256", "name": "", @@ -142,6 +147,11 @@ "name": "paranetServiceKCTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "paranetServiceKATokenId", + "type": "uint256" + }, { "internalType": "string", "name": "name", @@ -247,6 +257,11 @@ "name": "paranetServiceKCTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "paranetServiceKATokenId", + "type": "uint256" + }, { "internalType": "string", "name": "paranetServiceName", diff --git a/abi/ParanetsRegistry.json b/abi/ParanetsRegistry.json index 5c8acee9..274a8604 100644 --- a/abi/ParanetsRegistry.json +++ b/abi/ParanetsRegistry.json @@ -1004,13 +1004,18 @@ "type": "bytes32" } ], - "name": "getParanetKnowledgeCollectionLocator", + "name": "getParanetKnowledgeAssetLocator", "outputs": [ { "internalType": "address", "name": "", "type": "address" }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, { "internalType": "uint256", "name": "", @@ -1042,6 +1047,11 @@ "name": "paranetKCTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, { "internalType": "string", "name": "name", @@ -1333,6 +1343,11 @@ "name": "knowledgeCollectionTokenId", "type": "uint256" }, + { + "internalType": "uint256", + "name": "knowledgeAssetTokenId", + "type": "uint256" + }, { "internalType": "string", "name": "paranetName", From 668f725ac33c65c06e887214598b8f900199ff0b Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 30 Jan 2025 14:43:40 +0100 Subject: [PATCH 041/153] Fix paranetId calculation in incentives pool deployment --- contracts/paranets/ParanetIncentivesPoolFactory.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index fbd8bc67..4c1ad8cb 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -95,7 +95,7 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn ); pr.setIncentivesPoolAddress( - keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKCTokenId)), + keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)), incentivesPoolType, address(incentivesPool) ); From 01dfb903d0ddadefcfbd726faaab0e85b16313e7 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 31 Jan 2025 11:04:02 +0100 Subject: [PATCH 042/153] fix removeVoters --- contracts/paranets/ParanetNeuroIncentivesPool.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/paranets/ParanetNeuroIncentivesPool.sol b/contracts/paranets/ParanetNeuroIncentivesPool.sol index fa004342..91984f17 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPool.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPool.sol @@ -234,9 +234,9 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { require(voters.length >= limit, "Limit exceeds the num of voters"); for (uint256 i; i < limit; ) { - cumulativeVotersWeight -= uint16(voters[voters.length - 1 - i].weight); + cumulativeVotersWeight -= uint16(voters[voters.length - 1].weight); - delete votersIndexes[voters[voters.length - 1 - i].addr]; + delete votersIndexes[voters[voters.length - 1].addr]; voters.pop(); unchecked { From 41d94aaf8f2af16b103f34518bb439ec97e4fed3 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 31 Jan 2025 11:56:36 +0100 Subject: [PATCH 043/153] Fix submit --- contracts/paranets/Paranet.sol | 48 +++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index b9ec1be9..7497e1f4 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -159,6 +159,14 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { _; } + modifier onlyKnowledgeCollectionOwner( + address knowledgeCollectionStorageContract, + uint256 knowledgeCollectionTokenId + ) { + _checkKnowledgeCollectionOwner(knowledgeCollectionStorageContract, knowledgeCollectionTokenId); + _; + } + function initialize() public onlyHub { profileStorage = ProfileStorage(hub.getContractAddress("ProfileStorage")); identityStorage = IdentityStorage(hub.getContractAddress("IdentityStorage")); @@ -1014,14 +1022,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 paranetKnowledgeAssetTokenId, address knowledgeCollectionStorageContract, uint256 knowledgeCollectionTokenId - ) - external - onlyKnowledgeAssetOwner( - knowledgeCollectionStorageContract, - knowledgeCollectionTokenId, - paranetKnowledgeAssetTokenId - ) - { + ) external onlyKnowledgeCollectionOwner(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) { ParanetsRegistry pr = paranetsRegistry; bytes32 paranetId = keccak256( abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId) @@ -1070,7 +1071,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ) ); } - // Is this correct way to do this ??? + KnowledgeCollectionStorage kcs = KnowledgeCollectionStorage(knowledgeCollectionStorageContract); uint96 remainingTokenAmount = kcs.getTokenAmount(knowledgeCollectionTokenId); KnowledgeCollectionLib.MerkleRoot[] memory merkleRoots = kcs.getMerkleRoots(knowledgeCollectionTokenId); @@ -1123,7 +1124,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); bytes32 knowledgeCollectionId = keccak256( - abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId, paranetKATokenId) + abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) ); // Add Knowledge Collection to the KnowledgeCollectionsRegistry @@ -1266,4 +1267,31 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 ownedCountInRange = knowledgeCollectionStorage.balanceOf(msg.sender, startTokenId, startTokenId + 1); require(ownedCountInRange == 1, "Caller isn't the owner of the KA"); } + + function _checkKnowledgeCollectionOwner( + address knowledgeCollectionStorageContractAddress, + uint256 knowledgeCollectionId + ) internal virtual { + require(hub.isAssetStorage(knowledgeCollectionStorageContractAddress), "Given address isn't KC Storage"); + + KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage( + knowledgeCollectionStorageContractAddress + ); + uint256 minted = knowledgeCollectionStorage.getMinted(knowledgeCollectionId); + uint256 burnedCount = knowledgeCollectionStorage.getBurnedAmount(knowledgeCollectionId); + uint256 activeCount = minted - burnedCount; + require(activeCount != 0, "No KAs in Collection"); + + uint256 startTokenId = (knowledgeCollectionId - 1) * + knowledgeCollectionStorage.knowledgeCollectionMaxSize() + + 1; // _startTokenId() + + uint256 ownedCountInRange = knowledgeCollectionStorage.balanceOf( + msg.sender, + startTokenId, + startTokenId + minted + burnedCount + ); + + require(ownedCountInRange == activeCount, "Caller isn't the owner of the KC"); + } } From 8dc1364440d4a940600a5901f1c9acb2b317ade6 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 31 Jan 2025 15:32:39 +0100 Subject: [PATCH 044/153] Update deployment --- deployments/base_sepolia_test_contracts.json | 45 ++++++++++++++ deployments/gnosis_chiado_test_contracts.json | 40 ++++++------- deployments/neuroweb_testnet_contracts.json | 60 +++++++++---------- package.json | 2 +- 4 files changed, 96 insertions(+), 51 deletions(-) diff --git a/deployments/base_sepolia_test_contracts.json b/deployments/base_sepolia_test_contracts.json index d1ed8c08..0426f426 100644 --- a/deployments/base_sepolia_test_contracts.json +++ b/deployments/base_sepolia_test_contracts.json @@ -189,6 +189,51 @@ "deploymentBlock": 20972223, "deploymentTimestamp": 1737712739031, "deployed": true + }, + "ParanetsRegistry": { + "evmAddress": "0x734Ad13B02D41d3e8740c6892B863D53951420Fe", + "version": "1.0.1", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", + "deploymentBlock": 21282805, + "deploymentTimestamp": 1738333901133, + "deployed": true + }, + "ParanetServicesRegistry": { + "evmAddress": "0xB17D6e67998CF107dbCe6b26502e002dd76e9999", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", + "deploymentBlock": 21282808, + "deploymentTimestamp": 1738333908284, + "deployed": true + }, + "ParanetKnowledgeCollectionsRegistry": { + "evmAddress": "0xbdbe818FD8664BF8B2d944CDe33587f419F83C45", + "version": "1.0.1", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", + "deploymentBlock": 21282811, + "deploymentTimestamp": 1738333914891, + "deployed": true + }, + "ParanetKnowledgeMinersRegistry": { + "evmAddress": "0x5f444c05a8Fd28F8BA618F452F439ef5894D3060", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", + "deploymentBlock": 21282815, + "deploymentTimestamp": 1738333921676, + "deployed": true + }, + "Paranet": { + "evmAddress": "0x6f841a01D6Cd947d444cBa94103B9F8D610F12c1", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", + "deploymentBlock": 21282818, + "deploymentTimestamp": 1738333928833, + "deployed": true } } } diff --git a/deployments/gnosis_chiado_test_contracts.json b/deployments/gnosis_chiado_test_contracts.json index 9db54c25..8e4226b1 100644 --- a/deployments/gnosis_chiado_test_contracts.json +++ b/deployments/gnosis_chiado_test_contracts.json @@ -191,48 +191,48 @@ "deployed": true }, "ParanetsRegistry": { - "evmAddress": "0xd926A082A87D3A2536a48CAff6a9B8583434B1D7", + "evmAddress": "0x070b9e4e2C0d8aAB8965D05167572C73C97BB06f", "version": "1.0.1", "gitBranch": "v8-paranet-update", - "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", - "deploymentBlock": 13947383, - "deploymentTimestamp": 1737552116734, + "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", + "deploymentBlock": 14094593, + "deploymentTimestamp": 1738333780660, "deployed": true }, "ParanetServicesRegistry": { - "evmAddress": "0x0495C0251A3fCbe3561abD033A2Cb54f752d46eD", + "evmAddress": "0x698D59C74dccD57b53F5A00e314eA770BAcFab79", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", - "deploymentBlock": 13947384, - "deploymentTimestamp": 1737552121766, + "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", + "deploymentBlock": 14094594, + "deploymentTimestamp": 1738333786293, "deployed": true }, "ParanetKnowledgeCollectionsRegistry": { - "evmAddress": "0x6499c0006a5408Ca7A5D1380E4f7d0e3e2C23650", + "evmAddress": "0x8A055234b7479BA0f9358EBA6cFf3aF1ac6ecC53", "version": "1.0.1", "gitBranch": "v8-paranet-update", - "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", - "deploymentBlock": 13947385, - "deploymentTimestamp": 1737552126777, + "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", + "deploymentBlock": 14094595, + "deploymentTimestamp": 1738333795552, "deployed": true }, "ParanetKnowledgeMinersRegistry": { - "evmAddress": "0x1769C41E2B8ddbb1F429fA0aF453Bb34cce52D60", + "evmAddress": "0x4A83f16dd5c7fd0c9874FE4706cD574011d20E6C", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", - "deploymentBlock": 13947386, - "deploymentTimestamp": 1737552131790, + "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", + "deploymentBlock": 14094596, + "deploymentTimestamp": 1738333801377, "deployed": true }, "Paranet": { - "evmAddress": "0x8e49110922bC01241f434B4dAc0Fbc335FeBE63C", + "evmAddress": "0x6494540fDA6E197A8dF4155f895Aa61A971D2B5b", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", - "deploymentBlock": 13947388, - "deploymentTimestamp": 1737552145114, + "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", + "deploymentBlock": 14094597, + "deploymentTimestamp": 1738333806716, "deployed": true } } diff --git a/deployments/neuroweb_testnet_contracts.json b/deployments/neuroweb_testnet_contracts.json index d6d23f9c..0a9b6d3e 100644 --- a/deployments/neuroweb_testnet_contracts.json +++ b/deployments/neuroweb_testnet_contracts.json @@ -212,63 +212,63 @@ "deployed": true }, "ParanetsRegistry": { - "evmAddress": "0x03fD0638d57e1DFf059cfB0A59D465d96bc3d381", - "substrateAddress": "5EMjsczLyUsdcHaiGPvbVQtY5RrHNDDNdGz56TkyLhkGqyjB", + "evmAddress": "0x5C4915989900577cf623B2F9Cc2e2DEEDDFd1735", + "substrateAddress": "5EMjsczefdy9Q6WfbW6XqnaaqwmweMbYF4xnhgMjL9dWNGt5", "version": "1.0.1", "gitBranch": "v8-paranet-update", - "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", - "deploymentBlock": 6086202, - "deploymentTimestamp": 1737551926889, + "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", + "deploymentBlock": 6207080, + "deploymentTimestamp": 1738333636752, "deployed": true }, "ParanetServicesRegistry": { - "evmAddress": "0xE56Ac2244FCFb20D3B7d7eFfd9EB9B3490fd1C8d", - "substrateAddress": "5EMjsd189L9Y8LfKAMeFQZ2jzZQWqWA2rpZeDqysvNSni8B8", + "evmAddress": "0x612627453FCEF0B3792E621bdF96c9C96d5Ba578", + "substrateAddress": "5EMjsczfeAGYxD6sF1easgsBBqkQgRydgPaMJXxrn2qgERpf", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", - "deploymentBlock": 6086203, - "deploymentTimestamp": 1737551931960, + "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", + "deploymentBlock": 6207081, + "deploymentTimestamp": 1738333641897, "deployed": true }, "ParanetKnowledgeCollectionsRegistry": { - "evmAddress": "0xA6f3E79c083aFc6Bf69bFbA4cb488A98d70481b7", - "substrateAddress": "5EMjsczudPoVZCQMERLv7QbbGJR7fZCFQvdx2vYX4faDRiSZ", + "evmAddress": "0x17686361437FD87D90aEbeb632E6DF98B11288F7", + "substrateAddress": "5EMjsczQsAcDRQe13srwDZN8pqoVBNPWc6Tx7ZHpTD15cUXi", "version": "1.0.1", "gitBranch": "v8-paranet-update", - "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", - "deploymentBlock": 6086204, - "deploymentTimestamp": 1737551937030, + "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", + "deploymentBlock": 6207082, + "deploymentTimestamp": 1738333647010, "deployed": true }, "ParanetKnowledgeMinersRegistry": { - "evmAddress": "0xdc65788847B633C8Ea6A90e65E67a7A431f10244", - "substrateAddress": "5EMjsd16LVjR5mXywuAMRgFA9vVPBnk7r2VstqK5txaT4aHw", + "evmAddress": "0x452b9Ae4998d979368AA9AcdB23A35844914d876", + "substrateAddress": "5EMjscza3162R3cjs88XTMVa24UmMFvGnGtWLDMwR6F9gRYw", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", - "deploymentBlock": 6086205, - "deploymentTimestamp": 1737551942154, + "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", + "deploymentBlock": 6207083, + "deploymentTimestamp": 1738333652729, "deployed": true }, "Paranet": { - "evmAddress": "0x2d2bAddadD98AD4BFCDd3F3A6d20D6b5c21297DA", - "substrateAddress": "5EMjsczVE5xz2ejNb3s3Xc8mRwrLhBi86L5LiBtHMzgjkga7", + "evmAddress": "0xDDDc8ac99313B0BFA251DaA714bCB75566277369", + "substrateAddress": "5EMjsd16dXJdxjKtXvpHpDawRqGazeoBzuY1wew7eKvQL9ND", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", - "deploymentBlock": 6086207, - "deploymentTimestamp": 1737551953213, + "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", + "deploymentBlock": 6207084, + "deploymentTimestamp": 1738333658436, "deployed": true }, "ParanetIncentivesPoolFactory": { - "evmAddress": "0x0A7301DE4a368E22C7Bb3F6786a00daCFAC51Fb3", - "substrateAddress": "5EMjsczNGZrZL176FuPFJS3H8TXFkHGWexw6aC2ui9gpy7DH", + "evmAddress": "0x157C9b49968200B90Da630F18FB809858c87aeBa", + "substrateAddress": "5EMjsczQUqjWoV8veQT7sBtdzLSJYCH8pCzVUhmdmo7xkkRd", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", - "deploymentBlock": 6086208, - "deploymentTimestamp": 1737551962358, + "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", + "deploymentBlock": 6207086, + "deploymentTimestamp": 1738333671698, "deployed": true } } diff --git a/package.json b/package.json index 6edd4b51..a74e9527 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dkg-evm-module", - "version": "8.0.1", + "version": "8.0.2", "description": "Smart contracts for OriginTrail V8", "main": "index.ts", "files": [ From 1acb39f30c01dcbffe39b0668872c8281ee6e07a Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Mon, 3 Feb 2025 12:46:48 +0100 Subject: [PATCH 045/153] Add KC epoch created check --- contracts/libraries/ParanetLib.sol | 4 ++++ contracts/paranets/Paranet.sol | 14 +++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index 0d6bad7d..de43c770 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -244,4 +244,8 @@ library ParanetLib { uint96 currentCumulativeWeight, uint96 targetCumulativeWeight ); + error KnowledgeCollectionNotInFirstEpoch( + address knowledgeCollectionStorageContract, + uint256 knowledgeCollectionTokenId + ); } diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 7497e1f4..83c659f3 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -9,6 +9,7 @@ import {ParanetServicesRegistry} from "../storage/paranets/ParanetServicesRegist import {ProfileStorage} from "../storage/ProfileStorage.sol"; import {IdentityStorage} from "../storage/IdentityStorage.sol"; import {KnowledgeCollectionStorage} from "../storage/KnowledgeCollectionStorage.sol"; +import {Chronos} from "../storage/Chronos.sol"; import {ContractStatus} from "../abstract/ContractStatus.sol"; import {IInitializable} from "../interfaces/IInitializable.sol"; import {INamed} from "../interfaces/INamed.sol"; @@ -142,6 +143,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ParanetKnowledgeCollectionsRegistry public paranetKnowledgeCollectionsRegistry; ProfileStorage public profileStorage; IdentityStorage public identityStorage; + Chronos public chronos; // solhint-disable-next-line no-empty-blocks constructor(address hubAddress) ContractStatus(hubAddress) {} @@ -178,6 +180,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { paranetKnowledgeCollectionsRegistry = ParanetKnowledgeCollectionsRegistry( hub.getContractAddress("ParanetKnowledgeCollectionsRegistry") ); + chronos = Chronos(hub.getContractAddress("Chronos")); } function name() external pure virtual override returns (string memory) { @@ -1035,6 +1038,16 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { paranetKnowledgeAssetTokenId ); } + KnowledgeCollectionStorage kcs = KnowledgeCollectionStorage(knowledgeCollectionStorageContract); + uint256 currentEpoch = chronos.getCurrentEpoch(); + uint40 kcStartEpoch = kcs.getStartEpoch(knowledgeCollectionTokenId); + + if (kcStartEpoch != currentEpoch && kcStartEpoch != currentEpoch) { + revert ParanetLib.KnowledgeCollectionNotInFirstEpoch( + knowledgeCollectionStorageContract, + knowledgeCollectionTokenId + ); + } ParanetLib.MinersAccessPolicy minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); @@ -1072,7 +1085,6 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); } - KnowledgeCollectionStorage kcs = KnowledgeCollectionStorage(knowledgeCollectionStorageContract); uint96 remainingTokenAmount = kcs.getTokenAmount(knowledgeCollectionTokenId); KnowledgeCollectionLib.MerkleRoot[] memory merkleRoots = kcs.getMerkleRoots(knowledgeCollectionTokenId); From 90a95beeebc3730261c2842ffe4e868b66412dcf Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Mon, 3 Feb 2025 13:36:16 +0100 Subject: [PATCH 046/153] Remove increaseKnowledgeCollectionTokenAmount --- contracts/KnowledgeCollection.sol | 37 ------------------------------- 1 file changed, 37 deletions(-) diff --git a/contracts/KnowledgeCollection.sol b/contracts/KnowledgeCollection.sol index e74352dd..a6546b51 100644 --- a/contracts/KnowledgeCollection.sol +++ b/contracts/KnowledgeCollection.sol @@ -242,43 +242,6 @@ contract KnowledgeCollection is INamed, IVersioned, ContractStatus, IInitializab } } - function increaseKnowledgeCollectionTokenAmount(uint256 id, uint96 tokenAmount, address paymaster) external { - if (tokenAmount == 0) { - revert TokenLib.ZeroTokenAmount(); - } - - KnowledgeCollectionStorage kcs = knowledgeCollectionStorage; - - (, , , , , uint40 endEpoch, uint96 oldTokenAmount, ) = kcs.getKnowledgeCollectionMetadata(id); - - uint256 currentEpoch = chronos.getCurrentEpoch(); - if (currentEpoch > endEpoch) { - revert KnowledgeCollectionLib.KnowledgeCollectionExpired(id, currentEpoch, endEpoch); - } - - kcs.setTokenAmount(id, oldTokenAmount + tokenAmount); - - epochStorage.addTokensToEpochRange(1, currentEpoch, endEpoch, tokenAmount); - - _addTokens(tokenAmount, paymaster); - - ParanetKnowledgeCollectionsRegistry pkar = paranetKnowledgeCollectionsRegistry; - - bytes32 knowledgeCollectionId = pkar.getParanetId(keccak256(abi.encodePacked(address(kcs), id))); - if (pkar.isParanetKnowledgeCollection(knowledgeCollectionId)) { - ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; - bytes32 paranetId = paranetKnowledgeCollectionsRegistry.getParanetId(knowledgeCollectionId); - - // Add Knowledge Asset Token Amount Metadata to the ParanetsRegistry - paranetsRegistry.addCumulativeKnowledgeValue(paranetId, tokenAmount); - - // Add Knowledge Asset Token Amount Metadata to the KnowledgeMinersRegistry - pkmr.addCumulativeTracSpent(msg.sender, paranetId, tokenAmount); - pkmr.addUnrewardedTracSpent(msg.sender, paranetId, tokenAmount); - pkmr.addTotalTracSpent(msg.sender, tokenAmount); - } - } - function _verifySignatures( uint72[] calldata identityIds, bytes32 messageHash, From bf82b47f9ba50d341483309c7f7d560898792464 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Mon, 3 Feb 2025 13:36:33 +0100 Subject: [PATCH 047/153] Add ABI --- abi/KnowledgeCollection.json | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/abi/KnowledgeCollection.json b/abi/KnowledgeCollection.json index 5e68b3e1..0b17b30a 100644 --- a/abi/KnowledgeCollection.json +++ b/abi/KnowledgeCollection.json @@ -189,11 +189,6 @@ "name": "ZeroAddressHub", "type": "error" }, - { - "inputs": [], - "name": "ZeroTokenAmount", - "type": "error" - }, { "inputs": [], "name": "askStorage", @@ -371,29 +366,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "id", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - }, - { - "internalType": "address", - "name": "paymaster", - "type": "address" - } - ], - "name": "increaseKnowledgeCollectionTokenAmount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "initialize", From c963a04ec01cc12b47d24b6b87164c23db59527f Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 7 Feb 2025 16:10:29 +0100 Subject: [PATCH 048/153] Initial contracts --- .../paranets/ParanetNeuroIncentivesPool.sol | 396 ++++++++---------- .../ParanetNeuroIncentivesPoolStorage.sol | 294 +++++++++++++ 2 files changed, 466 insertions(+), 224 deletions(-) create mode 100644 contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol diff --git a/contracts/paranets/ParanetNeuroIncentivesPool.sol b/contracts/paranets/ParanetNeuroIncentivesPool.sol index 91984f17..29b1b823 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPool.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPool.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.20; import {ParanetKnowledgeMinersRegistry} from "../storage/paranets/ParanetKnowledgeMinersRegistry.sol"; import {ParanetsRegistry} from "../storage/paranets/ParanetsRegistry.sol"; +import {ParanetNeuroIncentivesPoolStorage} from "./ParanetNeuroIncentivesPoolStorage.sol"; import {KnowledgeCollectionStorage} from "../storage/KnowledgeCollectionStorage.sol"; import {Hub} from "../storage/Hub.sol"; import {INamed} from "../interfaces/INamed.sol"; @@ -24,11 +25,10 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { string private constant _VERSION = "1.0.0"; Hub public hub; - IERC20 public token; ParanetsRegistry public paranetsRegistry; ParanetKnowledgeMinersRegistry public paranetKnowledgeMinersRegistry; + ParanetNeuroIncentivesPoolStorage public paranetNeuroIncentivesPoolStorage; - bytes32 public parentParanetId; // Array of Total NEURO Emission Multipliers // Total NEURO Emission Multiplier = Ratio of how much NEURO is released per 1 TRAC spent // @@ -41,55 +41,17 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { uint256 public neuroEmissionMultiplierUpdateDelay = 7 days; - // Percentage of how much tokens from total NEURO emission goes to the Paranet Operator - // Minimum: 0, Maximum: 10,000 (which is 100%) - uint16 public paranetOperatorRewardPercentage; - // Percentage of how much tokens from total NEURO emission goes to the Paranet Incentivization - // Proposal Voters. Minimum: 0, Maximum: 10,000 (which is 100%) - uint16 public paranetIncentivizationProposalVotersRewardPercentage; - uint16 public cumulativeVotersWeight; - - // Address which can set Voters list and update Total NEURO Emission multiplier - address public votersRegistrar; - - uint256 public totalMinersClaimedNeuro; - uint256 public totalOperatorsClaimedNeuro; - uint256 public totalVotersClaimedNeuro; - - ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[] public claimedMinerRewards; - mapping(address => uint256) public claimedMinerRewardsIndexes; - - ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[] public claimedOperatorRewards; - mapping(address => uint256) public claimedOperatorRewardsIndexes; - - ParanetLib.ParanetIncentivizationProposalVoter[] public voters; - mapping(address => uint256) public votersIndexes; - // solhint-disable-next-line no-empty-blocks constructor( address hubAddress, - address rewardTokenAddress, - address paranetsRegistryAddress, address knowledgeMinersRegistryAddress, - bytes32 paranetId, - uint256 tracToNeuroEmissionMultiplier, - uint16 paranetOperatorRewardPercentage_, - uint16 paranetIncentivizationProposalVotersRewardPercentage_ + address neuroEmissionMultipliersAddress, + uint256 tracToNeuroEmissionMultiplier ) { - require( - paranetOperatorRewardPercentage_ + paranetIncentivizationProposalVotersRewardPercentage_ < - ParanetLib.PERCENTAGE_SCALING_FACTOR, - "Invalid rewards ratio" - ); - hub = Hub(hubAddress); - if (rewardTokenAddress != address(0)) { - token = IERC20(rewardTokenAddress); - } - paranetsRegistry = ParanetsRegistry(paranetsRegistryAddress); paranetKnowledgeMinersRegistry = ParanetKnowledgeMinersRegistry(knowledgeMinersRegistryAddress); + paranetNeuroIncentivesPoolStorage = ParanetNeuroIncentivesPoolStorage(paranetNeuroIncentivesPoolStorage); - parentParanetId = paranetId; neuroEmissionMultipliers.push( ParanetLib.NeuroEmissionMultiplier({ multiplier: tracToNeuroEmissionMultiplier, @@ -97,19 +59,8 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { finalized: true }) ); - paranetOperatorRewardPercentage = paranetOperatorRewardPercentage_; - paranetIncentivizationProposalVotersRewardPercentage = paranetIncentivizationProposalVotersRewardPercentage_; address hubOwner = hub.owner(); - uint256 size; - assembly { - size := extcodesize(hubOwner) - } - if (size > 0) { - votersRegistrar = Ownable(hubOwner).owner(); - } else { - votersRegistrar = hubOwner; - } } modifier onlyHubOwner() { @@ -145,113 +96,32 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { return _VERSION; } - receive() external payable { - emit NeuroRewardDeposit(msg.sender, msg.value); - } - - function totalNeuroReceived() external view returns (uint256) { - return address(this).balance + totalMinersClaimedNeuro + totalOperatorsClaimedNeuro + totalVotersClaimedNeuro; - } - - function getNeuroBalance() external view returns (uint256) { - return address(this).balance; - } - function updateNeuroEmissionMultiplierUpdateDelay(uint256 newDelay) external onlyHubOwner { neuroEmissionMultiplierUpdateDelay = newDelay; } - function transferVotersRegistrarRole(address newRegistrar) external onlyVotersRegistrar { - votersRegistrar = newRegistrar; - } - - function minerClaimedNeuro(address minerAddress) external view returns (uint256) { - return claimedMinerRewards[claimedMinerRewardsIndexes[minerAddress]].claimedNeuro; - } - - function getAllRewardedMiners() - external - view - returns (ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[] memory) - { - return claimedMinerRewards; - } - - function operatorClaimedNeuro(address operatorAddress) external view returns (uint256) { - return claimedOperatorRewards[claimedOperatorRewardsIndexes[operatorAddress]].claimedNeuro; - } - - function getAllRewardedOperators() - external - view - returns (ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[] memory) - { - return claimedOperatorRewards; - } - - function voterClaimedNeuro(address voterAddress) external view returns (uint256) { - return voters[votersIndexes[voterAddress]].claimedNeuro; - } - - function addVoters( - ParanetLib.ParanetIncentivizationProposalVoterInput[] calldata voters_ - ) external onlyVotersRegistrar { - for (uint256 i; i < voters_.length; ) { - votersIndexes[voters_[i].addr] = voters.length; - voters.push( - ParanetLib.ParanetIncentivizationProposalVoter({ - addr: voters_[i].addr, - weight: voters_[i].weight, - claimedNeuro: 0 - }) - ); - - cumulativeVotersWeight += uint16(voters_[i].weight); + function voterClaimedNeuro(address addr) external view returns (uint256) { + uint256 voterIndex = paranetNeuroIncentivesPoolStorage.votersIndexes(addr); - unchecked { - i++; - } + // If the index is out of range or the stored voter doesn't match `voterAddress`, + // return 0 as a default. + if ( + voterIndex >= paranetNeuroIncentivesPoolStorage.getVotersCount() || + paranetNeuroIncentivesPoolStorage.getVoterAtIndex(voterIndex).addr != addr + ) { + return 0; } - require(cumulativeVotersWeight <= ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT, "Cumulative weight is too big"); - } - - function getVoter( - address voterAddress - ) external view returns (ParanetLib.ParanetIncentivizationProposalVoter memory) { - return voters[votersIndexes[voterAddress]]; - } - - function getVoters() external view returns (ParanetLib.ParanetIncentivizationProposalVoter[] memory) { - return voters; - } - - function getVotersCount() external view returns (uint256) { - return voters.length; - } - - function removeVoters(uint256 limit) external onlyVotersRegistrar { - require(voters.length >= limit, "Limit exceeds the num of voters"); - - for (uint256 i; i < limit; ) { - cumulativeVotersWeight -= uint16(voters[voters.length - 1].weight); - - delete votersIndexes[voters[voters.length - 1].addr]; - voters.pop(); - - unchecked { - i++; - } - } + return paranetNeuroIncentivesPoolStorage.getVoterAtIndex(voterIndex).claimedNeuro; } function isKnowledgeMiner(address addr) public view returns (bool) { - return paranetsRegistry.isKnowledgeMinerRegistered(parentParanetId, addr); + return paranetsRegistry.isKnowledgeMinerRegistered(paranetNeuroIncentivesPoolStorage.getParanetId(), addr); } function isParanetOperator(address addr) public view returns (bool) { (address paranetKCStorageContract, uint256 paranetKCTokenId, uint256 paranetKATokenId) = paranetsRegistry - .getParanetKnowledgeAssetLocator(parentParanetId); + .getParanetKnowledgeAssetLocator(paranetNeuroIncentivesPoolStorage.getParanetId()); KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage(paranetKCStorageContract); @@ -265,7 +135,11 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { } function isProposalVoter(address addr) public view returns (bool) { - return (voters.length != 0 && voters[votersIndexes[addr]].addr == addr); + return (paranetNeuroIncentivesPoolStorage.getVotersCount() != 0 && + paranetNeuroIncentivesPoolStorage + .getVoterAtIndex(paranetNeuroIncentivesPoolStorage.votersIndexes(addr)) + .addr == + addr); } function getNeuroEmissionMultipliers() external view returns (ParanetLib.NeuroEmissionMultiplier[] memory) { @@ -323,8 +197,12 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { ); } + // TODO: Rework it should interact with storage function getTotalKnowledgeMinerIncentiveEstimation() public view returns (uint256) { - uint96 unrewardedTracSpent = paranetKnowledgeMinersRegistry.getUnrewardedTracSpent(msg.sender, parentParanetId); + uint96 unrewardedTracSpent = paranetKnowledgeMinersRegistry.getUnrewardedTracSpent( + msg.sender, + paranetNeuroIncentivesPoolStorage.getParanetId() + ); if (unrewardedTracSpent < ParanetLib.TOKENS_DIGITS_DIFF) { return 0; @@ -345,20 +223,23 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { (((unrewardedTracSpent * getEffectiveNeuroEmissionMultiplier(block.timestamp)) / ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) * (ParanetLib.PERCENTAGE_SCALING_FACTOR - - paranetOperatorRewardPercentage - - paranetIncentivizationProposalVotersRewardPercentage)) / ParanetLib.PERCENTAGE_SCALING_FACTOR; + paranetNeuroIncentivesPoolStorage.paranetOperatorRewardPercentage() - + paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage())) / + ParanetLib.PERCENTAGE_SCALING_FACTOR; } + // TODO: Rework it should interact with storage function getTotalAllKnowledgeMinersIncentiveEstimation() public view returns (uint256) { return _getIncentiveEstimation( ParanetLib.PERCENTAGE_SCALING_FACTOR - - paranetOperatorRewardPercentage - - paranetIncentivizationProposalVotersRewardPercentage, - totalMinersClaimedNeuro + paranetNeuroIncentivesPoolStorage.paranetOperatorRewardPercentage() - + paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage(), + paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro() ); } + // TODO: Rework it should interact with storage function getClaimableKnowledgeMinerRewardAmount() public view returns (uint256) { uint256 neuroReward = getTotalKnowledgeMinerIncentiveEstimation(); @@ -366,37 +247,41 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { // and total NEURO received by the contract, so that Miners don't get tokens belonging to Operator/Voters // Following the example from the above, if we have 100 NEURO as a total reward, Miners should never get // more than 80 NEURO. minersRewardLimit = 80 NEURO - uint256 minersRewardLimit = ((address(this).balance + - totalMinersClaimedNeuro + - totalOperatorsClaimedNeuro + - totalVotersClaimedNeuro) * + uint256 minersRewardLimit = ((paranetNeuroIncentivesPoolStorage.getBalance() + + paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro() + + paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro() + + paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro()) * (ParanetLib.PERCENTAGE_SCALING_FACTOR - - paranetOperatorRewardPercentage - - paranetIncentivizationProposalVotersRewardPercentage)) / ParanetLib.PERCENTAGE_SCALING_FACTOR; + paranetNeuroIncentivesPoolStorage.paranetOperatorRewardPercentage() - + paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage())) / + ParanetLib.PERCENTAGE_SCALING_FACTOR; return - totalMinersClaimedNeuro + neuroReward <= minersRewardLimit + paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro() + neuroReward <= minersRewardLimit ? neuroReward - : minersRewardLimit - totalMinersClaimedNeuro; + : minersRewardLimit - paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro(); } + // TODO: Rework it should interact with storage function getClaimableAllKnowledgeMinersRewardAmount() public view returns (uint256) { uint256 neuroReward = getTotalAllKnowledgeMinersIncentiveEstimation(); - uint256 minersRewardLimit = ((address(this).balance + - totalMinersClaimedNeuro + - totalOperatorsClaimedNeuro + - totalVotersClaimedNeuro) * + uint256 minersRewardLimit = ((paranetNeuroIncentivesPoolStorage.getBalance() + + paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro() + + paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro() + + paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro()) * (ParanetLib.PERCENTAGE_SCALING_FACTOR - - paranetOperatorRewardPercentage - - paranetIncentivizationProposalVotersRewardPercentage)) / ParanetLib.PERCENTAGE_SCALING_FACTOR; + paranetNeuroIncentivesPoolStorage.paranetOperatorRewardPercentage() - + paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage())) / + ParanetLib.PERCENTAGE_SCALING_FACTOR; return - totalMinersClaimedNeuro + neuroReward <= minersRewardLimit + paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro() + neuroReward <= minersRewardLimit ? neuroReward - : minersRewardLimit - totalMinersClaimedNeuro; + : minersRewardLimit - paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro(); } + // TODO: Rework it should interact with storage function claimKnowledgeMinerReward() external onlyParanetKnowledgeMiner { ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; @@ -404,7 +289,7 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { uint256 claimableNeuroReward = getClaimableKnowledgeMinerRewardAmount(); if (claimableNeuroReward == 0) { - revert ParanetLib.NoRewardAvailable(parentParanetId, msg.sender); + revert ParanetLib.NoRewardAvailable(paranetNeuroIncentivesPoolStorage.getParanetId(), msg.sender); } // Updating the Unrewarded TRAC variable in the Knowledge Miner Profile @@ -422,7 +307,7 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { // = 40 * 10^18 = 40 TRAC pkmr.setUnrewardedTracSpent( msg.sender, - parentParanetId, + paranetNeuroIncentivesPoolStorage.getParanetId(), neuroReward == claimableNeuroReward ? 0 : uint96( @@ -430,84 +315,115 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { getEffectiveNeuroEmissionMultiplier(block.timestamp) ) ); - pkmr.addCumulativeAwardedNeuro(msg.sender, parentParanetId, claimableNeuroReward); + pkmr.addCumulativeAwardedNeuro( + msg.sender, + paranetNeuroIncentivesPoolStorage.getParanetId(), + claimableNeuroReward + ); if ( - claimedMinerRewards.length == 0 || - claimedMinerRewards[claimedMinerRewardsIndexes[msg.sender]].addr != msg.sender + paranetNeuroIncentivesPoolStorage.getClaimedMinerRewardsLength() == 0 || + paranetNeuroIncentivesPoolStorage + .claimedMinerRewards(paranetNeuroIncentivesPoolStorage.claimedMinerRewardsIndexes(msg.sender)) + .addr != + msg.sender ) { - claimedMinerRewardsIndexes[msg.sender] = claimedMinerRewards.length; - claimedMinerRewards.push( + paranetNeuroIncentivesPoolStorage.claimedMinerRewardsIndexes[msg.sender] = paranetNeuroIncentivesPoolStorage + .claimedMinerRewards + .length; + paranetNeuroIncentivesPoolStorage.claimedMinerRewards.push( ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile({ addr: msg.sender, claimedNeuro: claimableNeuroReward }) ); } else { - claimedMinerRewards[claimedMinerRewardsIndexes[msg.sender]].claimedNeuro += claimableNeuroReward; + paranetNeuroIncentivesPoolStorage + .claimedMinerRewards[paranetNeuroIncentivesPoolStorage.claimedMinerRewardsIndexes[msg.sender]] + .claimedNeuro += claimableNeuroReward; } - totalMinersClaimedNeuro += claimableNeuroReward; + paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro += claimableNeuroReward; - payable(msg.sender).transfer(claimableNeuroReward); + paranetNeuroIncentivesPoolStorage.transferReward(msg.sender, claimableNeuroReward); emit ParanetKnowledgeMinerRewardClaimed(msg.sender, claimableNeuroReward); } + // TODO: Rework it should interact with storage function getTotalParanetOperatorIncentiveEstimation() public view returns (uint256) { - return _getIncentiveEstimation(paranetOperatorRewardPercentage, totalOperatorsClaimedNeuro); + return + _getIncentiveEstimation( + paranetNeuroIncentivesPoolStorage.paranetOperatorRewardPercentage, + paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro + ); } + // TODO: Rework it should interact with storage function getClaimableParanetOperatorRewardAmount() public view returns (uint256) { uint256 neuroReward = getTotalParanetOperatorIncentiveEstimation(); uint256 operatorRewardLimit = ((address(this).balance + - totalMinersClaimedNeuro + - totalOperatorsClaimedNeuro + - totalVotersClaimedNeuro) * paranetOperatorRewardPercentage) / ParanetLib.PERCENTAGE_SCALING_FACTOR; + paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro + + paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro + + paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro) * + paranetNeuroIncentivesPoolStorage.paranetOperatorRewardPercentage) / ParanetLib.PERCENTAGE_SCALING_FACTOR; return - totalOperatorsClaimedNeuro + neuroReward <= operatorRewardLimit + paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro + neuroReward <= operatorRewardLimit ? neuroReward - : operatorRewardLimit - totalOperatorsClaimedNeuro; + : operatorRewardLimit - paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro; } + // TODO: Rework it should interact with storage function claimParanetOperatorReward() external onlyParanetOperator { uint256 claimableNeuroReward = getClaimableParanetOperatorRewardAmount(); if (claimableNeuroReward == 0) { - revert ParanetLib.NoRewardAvailable(parentParanetId, msg.sender); + revert ParanetLib.NoRewardAvailable(paranetNeuroIncentivesPoolStorage.getParanetId(), msg.sender); } if ( - claimedOperatorRewards.length == 0 || - claimedOperatorRewards[claimedOperatorRewardsIndexes[msg.sender]].addr != msg.sender + paranetNeuroIncentivesPoolStorage.claimedOperatorRewards.length == 0 || + paranetNeuroIncentivesPoolStorage + .claimedOperatorRewards[paranetNeuroIncentivesPoolStorage.claimedOperatorRewardsIndexes[msg.sender]] + .addr != + msg.sender ) { - claimedOperatorRewardsIndexes[msg.sender] = claimedOperatorRewards.length; - claimedOperatorRewards.push( + paranetNeuroIncentivesPoolStorage.claimedOperatorRewardsIndexes[ + msg.sender + ] = paranetNeuroIncentivesPoolStorage.claimedOperatorRewards.length; + paranetNeuroIncentivesPoolStorage.claimedOperatorRewards.push( ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile({ addr: msg.sender, claimedNeuro: claimableNeuroReward }) ); } else { - claimedOperatorRewards[claimedOperatorRewardsIndexes[msg.sender]].claimedNeuro += claimableNeuroReward; + paranetNeuroIncentivesPoolStorage + .claimedOperatorRewards[paranetNeuroIncentivesPoolStorage.claimedOperatorRewardsIndexes[msg.sender]] + .claimedNeuro += claimableNeuroReward; } - totalOperatorsClaimedNeuro += claimableNeuroReward; + paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro += claimableNeuroReward; - payable(msg.sender).transfer(claimableNeuroReward); + paranetNeuroIncentivesPoolStorage.transferReward(msg.sender, claimableNeuroReward); emit ParanetOperatorRewardClaimed(msg.sender, claimableNeuroReward); } + // TODO: Rework it should interact with storage function getTotalProposalVoterIncentiveEstimation() public view returns (uint256) { uint256 effectiveNeuroEmissionMultiplier = getEffectiveNeuroEmissionMultiplier(block.timestamp); uint96 cumulativeKnowledgeValueSingleVoterPart = (((paranetsRegistry.getCumulativeKnowledgeValue( - parentParanetId - ) * paranetIncentivizationProposalVotersRewardPercentage) / ParanetLib.PERCENTAGE_SCALING_FACTOR) * - voters[votersIndexes[msg.sender]].weight) / ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT; + paranetNeuroIncentivesPoolStorage.getParanet() + ) * paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage) / + ParanetLib.PERCENTAGE_SCALING_FACTOR) * + paranetNeuroIncentivesPoolStorage + .voters[paranetNeuroIncentivesPoolStorage.votersIndexes[msg.sender]] + .weight) / ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT; uint96 rewardedTracSpentSingleVoterPart = uint96( - (voters[votersIndexes[msg.sender]].claimedNeuro * ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) / - effectiveNeuroEmissionMultiplier + (paranetNeuroIncentivesPoolStorage + .voters[paranetNeuroIncentivesPoolStorage.votersIndexes[msg.sender]] + .claimedNeuro * ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) / effectiveNeuroEmissionMultiplier ); if ( @@ -518,53 +434,81 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { return ((cumulativeKnowledgeValueSingleVoterPart * effectiveNeuroEmissionMultiplier) / - ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) - voters[votersIndexes[msg.sender]].claimedNeuro; + ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) - + paranetNeuroIncentivesPoolStorage + .voters[paranetNeuroIncentivesPoolStorage.votersIndexes[msg.sender]] + .claimedNeuro; } + // TODO: Rework it should interact with storage function getTotalAllProposalVotersIncentiveEstimation() public view returns (uint256) { - return _getIncentiveEstimation(paranetIncentivizationProposalVotersRewardPercentage, totalVotersClaimedNeuro); + return + _getIncentiveEstimation( + paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage, + paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro + ); } + // TODO: Rework it should interact with storage function getClaimableProposalVoterRewardAmount() public view returns (uint256) { - if (voters.length == 0 || voters[votersIndexes[msg.sender]].addr != msg.sender) { + if ( + paranetNeuroIncentivesPoolStorage.voters.length == 0 || + paranetNeuroIncentivesPoolStorage + .voters[paranetNeuroIncentivesPoolStorage.votersIndexes[msg.sender]] + .addr != + msg.sender + ) { return 0; } uint256 neuroReward = getTotalProposalVoterIncentiveEstimation(); uint256 voterRewardLimit = ((((address(this).balance + - totalMinersClaimedNeuro + - totalOperatorsClaimedNeuro + - totalVotersClaimedNeuro) * paranetIncentivizationProposalVotersRewardPercentage) / - ParanetLib.PERCENTAGE_SCALING_FACTOR) * voters[votersIndexes[msg.sender]].weight) / - ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT; + paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro + + paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro + + paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro) * + paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage) / + ParanetLib.PERCENTAGE_SCALING_FACTOR) * + paranetNeuroIncentivesPoolStorage + .voters[paranetNeuroIncentivesPoolStorage.votersIndexes[msg.sender]] + .weight) / ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT; return - voters[votersIndexes[msg.sender]].claimedNeuro + neuroReward <= voterRewardLimit + paranetNeuroIncentivesPoolStorage + .voters[paranetNeuroIncentivesPoolStorage.votersIndexes[msg.sender]] + .claimedNeuro + + neuroReward <= + voterRewardLimit ? neuroReward - : voterRewardLimit - voters[votersIndexes[msg.sender]].claimedNeuro; + : voterRewardLimit - + paranetNeuroIncentivesPoolStorage + .voters[paranetNeuroIncentivesPoolStorage.votersIndexes[msg.sender]] + .claimedNeuro; } + // TODO: Rework it should interact with storage function getClaimableAllProposalVotersRewardAmount() public view returns (uint256) { uint256 neuroReward = getTotalAllProposalVotersIncentiveEstimation(); uint256 votersRewardLimit = ((address(this).balance + - totalMinersClaimedNeuro + - totalOperatorsClaimedNeuro + - totalVotersClaimedNeuro) * paranetIncentivizationProposalVotersRewardPercentage) / + paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro + + paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro + + paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro) * + paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage) / ParanetLib.PERCENTAGE_SCALING_FACTOR; return - totalVotersClaimedNeuro + neuroReward <= votersRewardLimit + paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro + neuroReward <= votersRewardLimit ? neuroReward - : votersRewardLimit - totalVotersClaimedNeuro; + : votersRewardLimit - paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro; } + // TODO: Rework it should interact with storage function claimIncentivizationProposalVoterReward() external onlyParanetIncentivizationProposalVoter { - if (cumulativeVotersWeight != ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT) { + if (paranetNeuroIncentivesPoolStorage.cumulativeVotersWeight != ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT) { revert ParanetLib.InvalidCumulativeVotersWeight( - parentParanetId, - cumulativeVotersWeight, + paranetNeuroIncentivesPoolStorage.parentParanetId, + paranetNeuroIncentivesPoolStorage.cumulativeVotersWeight, ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT ); } @@ -572,24 +516,28 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { uint256 claimableNeuroReward = getClaimableProposalVoterRewardAmount(); if (claimableNeuroReward == 0) { - revert ParanetLib.NoRewardAvailable(parentParanetId, msg.sender); + revert ParanetLib.NoRewardAvailable(paranetNeuroIncentivesPoolStorage.parentParanetId, msg.sender); } - voters[votersIndexes[msg.sender]].claimedNeuro += claimableNeuroReward; - totalVotersClaimedNeuro += claimableNeuroReward; + paranetNeuroIncentivesPoolStorage + .voters[paranetNeuroIncentivesPoolStorage.votersIndexes[msg.sender]] + .claimedNeuro += claimableNeuroReward; + paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro += claimableNeuroReward; - payable(msg.sender).transfer(claimableNeuroReward); + paranetNeuroIncentivesPoolStorage.transferReward(msg.sender, claimableNeuroReward); emit ParanetIncentivizationProposalVoterRewardClaimed(msg.sender, claimableNeuroReward); } + // TODO: Rework it should interact with storage function _getIncentiveEstimation( uint16 rewardPercentage, uint256 totalClaimedNeuro ) internal view returns (uint256) { uint256 effectiveNeuroEmissionMultiplier = getEffectiveNeuroEmissionMultiplier(block.timestamp); - uint96 cumulativeKnowledgeValuePart = (paranetsRegistry.getCumulativeKnowledgeValue(parentParanetId) * - rewardPercentage) / ParanetLib.PERCENTAGE_SCALING_FACTOR; + uint96 cumulativeKnowledgeValuePart = (paranetsRegistry.getCumulativeKnowledgeValue( + paranetNeuroIncentivesPoolStorage.parentParanetId + ) * rewardPercentage) / ParanetLib.PERCENTAGE_SCALING_FACTOR; uint96 rewardedTracSpentPart = uint96( (totalClaimedNeuro * ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) / effectiveNeuroEmissionMultiplier ); @@ -608,7 +556,7 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { } function _checkVotersRegistrar() internal view virtual { - require(msg.sender == votersRegistrar, "Fn can only be used by registrar"); + require(msg.sender == paranetNeuroIncentivesPoolStorage.votersRegistrar, "Fn can only be used by registrar"); } function _checkParanetOperator() internal view virtual { diff --git a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol new file mode 100644 index 00000000..f8aec842 --- /dev/null +++ b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.20; + +import {Hub} from "../storage/Hub.sol"; +import {HubDependent} from "../abstract/HubDependent.sol"; +import {ParanetsRegistry} from "../storage/paranets/ParanetsRegistry.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {ParanetNeuroIncentivesPool} from "./ParanetNeuroIncentivesPool.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {INamed} from "../interfaces/INamed.sol"; +import {IVersioned} from "../interfaces/IVersioned.sol"; +import {ParanetLib} from "../libraries/ParanetLib.sol"; + +// TODO: Large Arrays in getAllRewardedMiners() / getAllRewardedOperators() / getVoters() +// If this arrays are too large maybe introduce pagination? +// TODO: There is no selective voter remove function +// TODO: When working with arrays check if it's empty +// TODO: Add getter for length, at index, reverse look up for arrays + +contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent { + event NeuroRewardDeposit(address sender, uint256 amount); + + string private constant _NAME = "ParanetNeuroIncentivesPoolStorage"; + string private constant _VERSION = "1.0.0"; + + IERC20 public token; + ParanetsRegistry public paranetsRegistry; + ParanetNeuroIncentivesPool public paranetNeuroIncentivesPool; + bytes32 public paranetId; + + // Percentage of how much tokens from total NEURO emission goes to the Paranet Operator + // Minimum: 0, Maximum: 10,000 (which is 100%) + uint16 public paranetOperatorRewardPercentage; + // Percentage of how much tokens from total NEURO emission goes to the Paranet Incentivization + // Proposal Voters. Minimum: 0, Maximum: 10,000 (which is 100%) + uint16 public paranetIncentivizationProposalVotersRewardPercentage; + + // Address which can set Voters list and update Total NEURO Emission multiplier + address public votersRegistrar; + + uint256 public totalMinersClaimedNeuro; + uint256 public totalOperatorsClaimedNeuro; + uint256 public totalVotersClaimedNeuro; + + ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[] public claimedMinerRewards; + mapping(address => uint256) public claimedMinerRewardsIndexes; + + ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[] public claimedOperatorRewards; + mapping(address => uint256) public claimedOperatorRewardsIndexes; + + uint16 public cumulativeVotersWeight; + ParanetLib.ParanetIncentivizationProposalVoter[] public voters; + mapping(address => uint256) public votersIndexes; + + constructor( + address hubAddress, + address rewardTokenAddress, + address paranetsRegistryAddress, + bytes32 paranetId_, + uint16 paranetOperatorRewardPercentage_, + uint16 paranetIncentivizationProposalVotersRewardPercentage_ + ) HubDependent(hubAddress) { + require( + paranetOperatorRewardPercentage_ + paranetIncentivizationProposalVotersRewardPercentage_ < + ParanetLib.PERCENTAGE_SCALING_FACTOR, + "Invalid rewards ratio" + ); + + if (rewardTokenAddress != address(0)) { + token = IERC20(rewardTokenAddress); + } + paranetsRegistry = ParanetsRegistry(paranetsRegistryAddress); + + require(paranetsRegistry.paranetExists(paranetId_), "Non existent paranet"); + paranetId = paranetId_; + + paranetOperatorRewardPercentage = paranetOperatorRewardPercentage_; + paranetIncentivizationProposalVotersRewardPercentage = paranetIncentivizationProposalVotersRewardPercentage_; + + address hubOwner = hub.owner(); + uint256 size; + assembly { + size := extcodesize(hubOwner) + } + if (size > 0) { + votersRegistrar = Ownable(hubOwner).owner(); + } else { + votersRegistrar = hubOwner; + } + } + + function name() external pure virtual override returns (string memory) { + return _NAME; + } + + function version() external pure virtual override returns (string memory) { + return _VERSION; + } + + receive() external payable { + emit NeuroRewardDeposit(msg.sender, msg.value); + } + + function totalNeuroReceived() external view returns (uint256) { + return getBalance() + totalMinersClaimedNeuro + totalOperatorsClaimedNeuro + totalVotersClaimedNeuro; + } + + function transferVotersRegistrarRole(address newRegistrar) external onlyVotersRegistrar { + votersRegistrar = newRegistrar; + } + + function getAllRewardedMiners() + external + view + returns (ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[] memory) + { + return claimedMinerRewards; + } + + function minerClaimedNeuro(address minerAddress) external view returns (uint256) { + return claimedMinerRewards[claimedMinerRewardsIndexes[minerAddress]].claimedNeuro; + } + + function operatorClaimedNeuro(address operatorAddress) external view returns (uint256) { + return claimedOperatorRewards[claimedOperatorRewardsIndexes[operatorAddress]].claimedNeuro; + } + + function getAllRewardedOperators() + external + view + returns (ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[] memory) + { + return claimedOperatorRewards; + } + + modifier onlyVotersRegistrar() { + require(msg.sender == votersRegistrar, "Fn can only be used by registrar"); + _; + } + + function addVoters( + ParanetLib.ParanetIncentivizationProposalVoterInput[] calldata voters_ + ) external onlyVotersRegistrar { + for (uint256 i; i < voters_.length; ) { + address voterAddr = voters_[i].addr; + uint16 weight = uint16(voters_[i].weight); + + require(voterAddr != address(0), "Zero address is not a valid voter"); + + uint256 existingIndex = votersIndexes[voterAddr]; + if (existingIndex < voters.length) { + revert("Voter already exists"); + } + + votersIndexes[voterAddr] = voters.length; + voters.push( + ParanetLib.ParanetIncentivizationProposalVoter({addr: voterAddr, weight: weight, claimedNeuro: 0}) + ); + + cumulativeVotersWeight += weight; + + unchecked { + i++; + } + } + + require(cumulativeVotersWeight <= ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT, "Cumulative weight is too big"); + } + + /** + * @notice Remove the last `limit` voters from the array. + */ + function removeVoters(uint256 limit) external onlyVotersRegistrar { + require(voters.length >= limit, "Limit exceeds number of voters"); + + for (uint256 i; i < limit; ) { + ParanetLib.ParanetIncentivizationProposalVoter memory voter = voters[voters.length - 1]; + // Decrease total weight + cumulativeVotersWeight -= uint16(voter.weight); + + // Clean up indexes + delete votersIndexes[voter.addr]; + + // Remove last element + voters.pop(); + + unchecked { + i++; + } + } + } + + // What if voterAddress doesn't exist, would this remove voter at index 0??? + function removeVoter(address voterAddress) external onlyVotersRegistrar { + uint256 index = votersIndexes[voterAddress]; + ParanetLib.ParanetIncentivizationProposalVoter memory voterToRemove = voters[index]; + require(voterToRemove.addr == voterAddress, "Voter not found"); + + uint16 removedWeight = uint16(voterToRemove.weight); + + uint256 lastIndex = voters.length - 1; + if (index != lastIndex) { + ParanetLib.ParanetIncentivizationProposalVoter memory lastVoter = voters[lastIndex]; + voters[index] = lastVoter; + votersIndexes[lastVoter.addr] = index; + } + + voters.pop(); + + delete votersIndexes[voterAddress]; + + cumulativeVotersWeight -= removedWeight; + } + + function getVotersCount() external view returns (uint256) { + return voters.length; + } + + function getVoters() external view returns (ParanetLib.ParanetIncentivizationProposalVoter[] memory) { + return voters; + } + + function getVoter( + address voterAddress + ) external view returns (ParanetLib.ParanetIncentivizationProposalVoter memory) { + if (voters.length == 0) { + return ParanetLib.ParanetIncentivizationProposalVoter({addr: address(0), weight: 0, claimedNeuro: 0}); + } + + uint256 index = votersIndexes[voterAddress]; + if (index > voters.length || voters[index].addr != voterAddress) { + return ParanetLib.ParanetIncentivizationProposalVoter({addr: address(0), weight: 0, claimedNeuro: 0}); + } + + return voters[index]; + } + + function getVoterAtIndex( + uint256 index + ) external view returns (ParanetLib.ParanetIncentivizationProposalVoter memory) { + return voters[index]; + } + + function isProposalVoter(address addr) external view returns (bool) { + if (voters.length == 0) return false; + uint256 idx = votersIndexes[addr]; + return (idx < voters.length && voters[idx].addr == addr); + } + + /** + * @notice Increments the `claimedNeuro` for a specific voter by `amount`. + */ + function addVoterClaimedNeuro(address voter, uint256 amount) external { + // Only the main pool contract or an allowed address can do this. + require(msg.sender == address(paranetNeuroIncentivesPool), "Not authorized to add claim"); + + uint256 idx = votersIndexes[voter]; + if (idx < voters.length && voters[idx].addr == voter) { + voters[idx].claimedNeuro += amount; + } + } + + function getClaimedMinerRewardsLength() external view returns (uint256) { + return claimedMinerRewards.length; + } + + // TODO: paranetId is public, maybe remove getter and access it directly + function getParanetId() public view returns (bytes32) { + return paranetId; + } + + // This should only be done through hub registerd contracts + function setParanetNeuroIncentivesPool(address paranetNeuroIncentivesPoolAddress) external onlyContracts { + paranetNeuroIncentivesPool = ParanetNeuroIncentivesPool(paranetNeuroIncentivesPoolAddress); + } + + function transferReward(address rewardAddress, uint256 amount) public { + require(msg.sender == address(paranetNeuroIncentivesPool), "Not authorized to add claim"); + if (address(token) == address(0)) { + payable(rewardAddress).transfer(amount); + } else { + token.transfer(rewardAddress, amount); + } + } + + function getBalance() public view returns (uint256) { + if (address(token) == address(0)) { + return address(this).balance; + } else { + return token.balanceOf(address(this)); + } + } +} From b62389090f1f5e3a299de9109ecfd56df3aca741 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Mon, 10 Feb 2025 21:32:51 +0100 Subject: [PATCH 049/153] wip --- .../paranets/ParanetNeuroIncentivesPool.sol | 159 +++++------- .../ParanetNeuroIncentivesPoolStorage.sol | 243 +++++++++++++++--- 2 files changed, 276 insertions(+), 126 deletions(-) diff --git a/contracts/paranets/ParanetNeuroIncentivesPool.sol b/contracts/paranets/ParanetNeuroIncentivesPool.sol index 29b1b823..acd889ea 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPool.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPool.sol @@ -10,8 +10,6 @@ import {Hub} from "../storage/Hub.sol"; import {INamed} from "../interfaces/INamed.sol"; import {IVersioned} from "../interfaces/IVersioned.sol"; import {ParanetLib} from "../libraries/ParanetLib.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; contract ParanetNeuroIncentivesPool is INamed, IVersioned { event NeuroRewardDeposit(address indexed sender, uint256 amount); @@ -42,12 +40,7 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { uint256 public neuroEmissionMultiplierUpdateDelay = 7 days; // solhint-disable-next-line no-empty-blocks - constructor( - address hubAddress, - address knowledgeMinersRegistryAddress, - address neuroEmissionMultipliersAddress, - uint256 tracToNeuroEmissionMultiplier - ) { + constructor(address hubAddress, address knowledgeMinersRegistryAddress, uint256 tracToNeuroEmissionMultiplier) { hub = Hub(hubAddress); paranetKnowledgeMinersRegistry = ParanetKnowledgeMinersRegistry(knowledgeMinersRegistryAddress); paranetNeuroIncentivesPoolStorage = ParanetNeuroIncentivesPoolStorage(paranetNeuroIncentivesPoolStorage); @@ -59,8 +52,6 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { finalized: true }) ); - - address hubOwner = hub.owner(); } modifier onlyHubOwner() { @@ -116,12 +107,12 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { } function isKnowledgeMiner(address addr) public view returns (bool) { - return paranetsRegistry.isKnowledgeMinerRegistered(paranetNeuroIncentivesPoolStorage.getParanetId(), addr); + return paranetsRegistry.isKnowledgeMinerRegistered(paranetNeuroIncentivesPoolStorage.paranetId(), addr); } function isParanetOperator(address addr) public view returns (bool) { (address paranetKCStorageContract, uint256 paranetKCTokenId, uint256 paranetKATokenId) = paranetsRegistry - .getParanetKnowledgeAssetLocator(paranetNeuroIncentivesPoolStorage.getParanetId()); + .getParanetKnowledgeAssetLocator(paranetNeuroIncentivesPoolStorage.paranetId()); KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage(paranetKCStorageContract); @@ -155,6 +146,7 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { return neuroEmissionMultipliers[0].multiplier; } + // TODO:Should there be some check of this value? function initiateNeuroEmissionMultiplierUpdate(uint256 newMultiplier) external onlyVotersRegistrar { if (!neuroEmissionMultipliers[neuroEmissionMultipliers.length - 1].finalized) { neuroEmissionMultipliers[neuroEmissionMultipliers.length - 1].multiplier = newMultiplier; @@ -201,7 +193,7 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { function getTotalKnowledgeMinerIncentiveEstimation() public view returns (uint256) { uint96 unrewardedTracSpent = paranetKnowledgeMinersRegistry.getUnrewardedTracSpent( msg.sender, - paranetNeuroIncentivesPoolStorage.getParanetId() + paranetNeuroIncentivesPoolStorage.paranetId() ); if (unrewardedTracSpent < ParanetLib.TOKENS_DIGITS_DIFF) { @@ -239,7 +231,6 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { ); } - // TODO: Rework it should interact with storage function getClaimableKnowledgeMinerRewardAmount() public view returns (uint256) { uint256 neuroReward = getTotalKnowledgeMinerIncentiveEstimation(); @@ -247,8 +238,9 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { // and total NEURO received by the contract, so that Miners don't get tokens belonging to Operator/Voters // Following the example from the above, if we have 100 NEURO as a total reward, Miners should never get // more than 80 NEURO. minersRewardLimit = 80 NEURO + uint256 totalMinersClaimedNeuro = paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro(); uint256 minersRewardLimit = ((paranetNeuroIncentivesPoolStorage.getBalance() + - paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro() + + totalMinersClaimedNeuro + paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro() + paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro()) * (ParanetLib.PERCENTAGE_SCALING_FACTOR - @@ -257,9 +249,9 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { ParanetLib.PERCENTAGE_SCALING_FACTOR; return - paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro() + neuroReward <= minersRewardLimit + totalMinersClaimedNeuro + neuroReward <= minersRewardLimit ? neuroReward - : minersRewardLimit - paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro(); + : minersRewardLimit - totalMinersClaimedNeuro; } // TODO: Rework it should interact with storage @@ -281,15 +273,15 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { : minersRewardLimit - paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro(); } - // TODO: Rework it should interact with storage function claimKnowledgeMinerReward() external onlyParanetKnowledgeMiner { ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; uint256 neuroReward = getTotalKnowledgeMinerIncentiveEstimation(); uint256 claimableNeuroReward = getClaimableKnowledgeMinerRewardAmount(); + // Use require here if (claimableNeuroReward == 0) { - revert ParanetLib.NoRewardAvailable(paranetNeuroIncentivesPoolStorage.getParanetId(), msg.sender); + revert ParanetLib.NoRewardAvailable(paranetNeuroIncentivesPoolStorage.paranetId(), msg.sender); } // Updating the Unrewarded TRAC variable in the Knowledge Miner Profile @@ -307,7 +299,7 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { // = 40 * 10^18 = 40 TRAC pkmr.setUnrewardedTracSpent( msg.sender, - paranetNeuroIncentivesPoolStorage.getParanetId(), + paranetNeuroIncentivesPoolStorage.paranetId(), neuroReward == claimableNeuroReward ? 0 : uint96( @@ -315,34 +307,20 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { getEffectiveNeuroEmissionMultiplier(block.timestamp) ) ); - pkmr.addCumulativeAwardedNeuro( - msg.sender, - paranetNeuroIncentivesPoolStorage.getParanetId(), - claimableNeuroReward - ); + pkmr.addCumulativeAwardedNeuro(msg.sender, paranetNeuroIncentivesPoolStorage.paranetId(), claimableNeuroReward); if ( paranetNeuroIncentivesPoolStorage.getClaimedMinerRewardsLength() == 0 || paranetNeuroIncentivesPoolStorage - .claimedMinerRewards(paranetNeuroIncentivesPoolStorage.claimedMinerRewardsIndexes(msg.sender)) + .getClaimedMinerRewardsAtIndex(paranetNeuroIncentivesPoolStorage.claimedMinerRewardsIndexes(msg.sender)) .addr != msg.sender ) { - paranetNeuroIncentivesPoolStorage.claimedMinerRewardsIndexes[msg.sender] = paranetNeuroIncentivesPoolStorage - .claimedMinerRewards - .length; - paranetNeuroIncentivesPoolStorage.claimedMinerRewards.push( - ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile({ - addr: msg.sender, - claimedNeuro: claimableNeuroReward - }) - ); + paranetNeuroIncentivesPoolStorage.addMinerClaimedRewardProfile(msg.sender, claimableNeuroReward); } else { - paranetNeuroIncentivesPoolStorage - .claimedMinerRewards[paranetNeuroIncentivesPoolStorage.claimedMinerRewardsIndexes[msg.sender]] - .claimedNeuro += claimableNeuroReward; + paranetNeuroIncentivesPoolStorage.addMinerClaimedReward(msg.sender, claimableNeuroReward); } - paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro += claimableNeuroReward; + paranetNeuroIncentivesPoolStorage.addTotalMinersClaimedNeuro(claimableNeuroReward); paranetNeuroIncentivesPoolStorage.transferReward(msg.sender, claimableNeuroReward); @@ -353,8 +331,8 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { function getTotalParanetOperatorIncentiveEstimation() public view returns (uint256) { return _getIncentiveEstimation( - paranetNeuroIncentivesPoolStorage.paranetOperatorRewardPercentage, - paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro + paranetNeuroIncentivesPoolStorage.paranetOperatorRewardPercentage(), + paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro() ); } @@ -363,47 +341,38 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { uint256 neuroReward = getTotalParanetOperatorIncentiveEstimation(); uint256 operatorRewardLimit = ((address(this).balance + - paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro + - paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro + - paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro) * - paranetNeuroIncentivesPoolStorage.paranetOperatorRewardPercentage) / ParanetLib.PERCENTAGE_SCALING_FACTOR; + paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro() + + paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro() + + paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro()) * + paranetNeuroIncentivesPoolStorage.paranetOperatorRewardPercentage()) / ParanetLib.PERCENTAGE_SCALING_FACTOR; return - paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro + neuroReward <= operatorRewardLimit + paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro() + neuroReward <= operatorRewardLimit ? neuroReward - : operatorRewardLimit - paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro; + : operatorRewardLimit - paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro(); } - // TODO: Rework it should interact with storage function claimParanetOperatorReward() external onlyParanetOperator { uint256 claimableNeuroReward = getClaimableParanetOperatorRewardAmount(); if (claimableNeuroReward == 0) { - revert ParanetLib.NoRewardAvailable(paranetNeuroIncentivesPoolStorage.getParanetId(), msg.sender); + revert ParanetLib.NoRewardAvailable(paranetNeuroIncentivesPoolStorage.paranetId(), msg.sender); } if ( - paranetNeuroIncentivesPoolStorage.claimedOperatorRewards.length == 0 || + paranetNeuroIncentivesPoolStorage.getClaimedOperatorRewardsLength() == 0 || paranetNeuroIncentivesPoolStorage - .claimedOperatorRewards[paranetNeuroIncentivesPoolStorage.claimedOperatorRewardsIndexes[msg.sender]] + .getClaimedOperatorRewardsAtIndex( + paranetNeuroIncentivesPoolStorage.claimedOperatorRewardsIndexes(msg.sender) + ) .addr != msg.sender ) { - paranetNeuroIncentivesPoolStorage.claimedOperatorRewardsIndexes[ - msg.sender - ] = paranetNeuroIncentivesPoolStorage.claimedOperatorRewards.length; - paranetNeuroIncentivesPoolStorage.claimedOperatorRewards.push( - ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile({ - addr: msg.sender, - claimedNeuro: claimableNeuroReward - }) - ); + paranetNeuroIncentivesPoolStorage.addOperatorClaimedRewardsProfile(msg.sender, claimableNeuroReward); } else { - paranetNeuroIncentivesPoolStorage - .claimedOperatorRewards[paranetNeuroIncentivesPoolStorage.claimedOperatorRewardsIndexes[msg.sender]] - .claimedNeuro += claimableNeuroReward; + paranetNeuroIncentivesPoolStorage.addClaimedOperatorReward(msg.sender, claimableNeuroReward); } - paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro += claimableNeuroReward; + paranetNeuroIncentivesPoolStorage.addTotalOperatorsClaimedNeuro(claimableNeuroReward); paranetNeuroIncentivesPoolStorage.transferReward(msg.sender, claimableNeuroReward); @@ -414,15 +383,15 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { function getTotalProposalVoterIncentiveEstimation() public view returns (uint256) { uint256 effectiveNeuroEmissionMultiplier = getEffectiveNeuroEmissionMultiplier(block.timestamp); uint96 cumulativeKnowledgeValueSingleVoterPart = (((paranetsRegistry.getCumulativeKnowledgeValue( - paranetNeuroIncentivesPoolStorage.getParanet() - ) * paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage) / + paranetNeuroIncentivesPoolStorage.paranetId() + ) * paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage()) / ParanetLib.PERCENTAGE_SCALING_FACTOR) * paranetNeuroIncentivesPoolStorage - .voters[paranetNeuroIncentivesPoolStorage.votersIndexes[msg.sender]] + .getVoterAtIndex(paranetNeuroIncentivesPoolStorage.votersIndexes(msg.sender)) .weight) / ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT; uint96 rewardedTracSpentSingleVoterPart = uint96( (paranetNeuroIncentivesPoolStorage - .voters[paranetNeuroIncentivesPoolStorage.votersIndexes[msg.sender]] + .getVoterAtIndex(paranetNeuroIncentivesPoolStorage.votersIndexes(msg.sender)) .claimedNeuro * ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) / effectiveNeuroEmissionMultiplier ); @@ -436,7 +405,7 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { ((cumulativeKnowledgeValueSingleVoterPart * effectiveNeuroEmissionMultiplier) / ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) - paranetNeuroIncentivesPoolStorage - .voters[paranetNeuroIncentivesPoolStorage.votersIndexes[msg.sender]] + .getVoterAtIndex(paranetNeuroIncentivesPoolStorage.votersIndexes(msg.sender)) .claimedNeuro; } @@ -444,17 +413,17 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { function getTotalAllProposalVotersIncentiveEstimation() public view returns (uint256) { return _getIncentiveEstimation( - paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage, - paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro + paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage(), + paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro() ); } // TODO: Rework it should interact with storage function getClaimableProposalVoterRewardAmount() public view returns (uint256) { if ( - paranetNeuroIncentivesPoolStorage.voters.length == 0 || + paranetNeuroIncentivesPoolStorage.getVotersCount() == 0 || paranetNeuroIncentivesPoolStorage - .voters[paranetNeuroIncentivesPoolStorage.votersIndexes[msg.sender]] + .getVoterAtIndex(paranetNeuroIncentivesPoolStorage.votersIndexes(msg.sender)) .addr != msg.sender ) { @@ -463,26 +432,26 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { uint256 neuroReward = getTotalProposalVoterIncentiveEstimation(); - uint256 voterRewardLimit = ((((address(this).balance + - paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro + - paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro + - paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro) * - paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage) / + uint256 voterRewardLimit = ((((paranetNeuroIncentivesPoolStorage.getBalance() + + paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro() + + paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro() + + paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro()) * + paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage()) / ParanetLib.PERCENTAGE_SCALING_FACTOR) * paranetNeuroIncentivesPoolStorage - .voters[paranetNeuroIncentivesPoolStorage.votersIndexes[msg.sender]] + .getVoterAtIndex(paranetNeuroIncentivesPoolStorage.votersIndexes(msg.sender)) .weight) / ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT; return paranetNeuroIncentivesPoolStorage - .voters[paranetNeuroIncentivesPoolStorage.votersIndexes[msg.sender]] + .getVoterAtIndex(paranetNeuroIncentivesPoolStorage.votersIndexes(msg.sender)) .claimedNeuro + neuroReward <= voterRewardLimit ? neuroReward : voterRewardLimit - paranetNeuroIncentivesPoolStorage - .voters[paranetNeuroIncentivesPoolStorage.votersIndexes[msg.sender]] + .getVoterAtIndex(paranetNeuroIncentivesPoolStorage.votersIndexes(msg.sender)) .claimedNeuro; } @@ -491,24 +460,24 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { uint256 neuroReward = getTotalAllProposalVotersIncentiveEstimation(); uint256 votersRewardLimit = ((address(this).balance + - paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro + - paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro + - paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro) * - paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage) / + paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro() + + paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro() + + paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro()) * + paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage()) / ParanetLib.PERCENTAGE_SCALING_FACTOR; return - paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro + neuroReward <= votersRewardLimit + paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro() + neuroReward <= votersRewardLimit ? neuroReward - : votersRewardLimit - paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro; + : votersRewardLimit - paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro(); } // TODO: Rework it should interact with storage function claimIncentivizationProposalVoterReward() external onlyParanetIncentivizationProposalVoter { - if (paranetNeuroIncentivesPoolStorage.cumulativeVotersWeight != ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT) { + if (paranetNeuroIncentivesPoolStorage.cumulativeVotersWeight() != ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT) { revert ParanetLib.InvalidCumulativeVotersWeight( - paranetNeuroIncentivesPoolStorage.parentParanetId, - paranetNeuroIncentivesPoolStorage.cumulativeVotersWeight, + paranetNeuroIncentivesPoolStorage.paranetId(), + paranetNeuroIncentivesPoolStorage.cumulativeVotersWeight(), ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT ); } @@ -516,13 +485,13 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { uint256 claimableNeuroReward = getClaimableProposalVoterRewardAmount(); if (claimableNeuroReward == 0) { - revert ParanetLib.NoRewardAvailable(paranetNeuroIncentivesPoolStorage.parentParanetId, msg.sender); + revert ParanetLib.NoRewardAvailable(paranetNeuroIncentivesPoolStorage.paranetId(), msg.sender); } paranetNeuroIncentivesPoolStorage - .voters[paranetNeuroIncentivesPoolStorage.votersIndexes[msg.sender]] + .getVoterAtIndex(paranetNeuroIncentivesPoolStorage.votersIndexes(msg.sender)) .claimedNeuro += claimableNeuroReward; - paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro += claimableNeuroReward; + paranetNeuroIncentivesPoolStorage.addTotalVotersClaimedNeuro(claimableNeuroReward); paranetNeuroIncentivesPoolStorage.transferReward(msg.sender, claimableNeuroReward); @@ -536,7 +505,7 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { ) internal view returns (uint256) { uint256 effectiveNeuroEmissionMultiplier = getEffectiveNeuroEmissionMultiplier(block.timestamp); uint96 cumulativeKnowledgeValuePart = (paranetsRegistry.getCumulativeKnowledgeValue( - paranetNeuroIncentivesPoolStorage.parentParanetId + paranetNeuroIncentivesPoolStorage.paranetId() ) * rewardPercentage) / ParanetLib.PERCENTAGE_SCALING_FACTOR; uint96 rewardedTracSpentPart = uint96( (totalClaimedNeuro * ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) / effectiveNeuroEmissionMultiplier @@ -556,7 +525,7 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { } function _checkVotersRegistrar() internal view virtual { - require(msg.sender == paranetNeuroIncentivesPoolStorage.votersRegistrar, "Fn can only be used by registrar"); + require(msg.sender == paranetNeuroIncentivesPoolStorage.votersRegistrar(), "Fn can only be used by registrar"); } function _checkParanetOperator() internal view virtual { diff --git a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol index f8aec842..1feb75c5 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol @@ -2,31 +2,35 @@ pragma solidity ^0.8.20; -import {Hub} from "../storage/Hub.sol"; import {HubDependent} from "../abstract/HubDependent.sol"; import {ParanetsRegistry} from "../storage/paranets/ParanetsRegistry.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {ParanetNeuroIncentivesPool} from "./ParanetNeuroIncentivesPool.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {INamed} from "../interfaces/INamed.sol"; import {IVersioned} from "../interfaces/IVersioned.sol"; +import {IInitializable} from "../interfaces/IInitializable.sol"; import {ParanetLib} from "../libraries/ParanetLib.sol"; -// TODO: Large Arrays in getAllRewardedMiners() / getAllRewardedOperators() / getVoters() -// If this arrays are too large maybe introduce pagination? -// TODO: There is no selective voter remove function // TODO: When working with arrays check if it's empty // TODO: Add getter for length, at index, reverse look up for arrays -contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent { +contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInitializable { event NeuroRewardDeposit(address sender, uint256 amount); + event VoterWeightUpdated(address indexed voter, uint96 oldWeight, uint96 newWeight); + event TotalMinersClaimedNeuroSet(uint256 oldAmount, uint256 newAmount); + event TotalOperatorsClaimedNeuroSet(uint256 oldAmount, uint256 newAmount); + event TotalVotersClaimedNeuroSet(uint256 oldAmount, uint256 newAmount); + event TotalMinersClaimedNeuroDecremented(uint256 amount, uint256 newTotal); + event TotalOperatorsClaimedNeuroDecremented(uint256 amount, uint256 newTotal); + event TotalVotersClaimedNeuroDecremented(uint256 amount, uint256 newTotal); string private constant _NAME = "ParanetNeuroIncentivesPoolStorage"; string private constant _VERSION = "1.0.0"; + uint256 private constant MAX_VOTERS_PER_BATCH = 100; IERC20 public token; ParanetsRegistry public paranetsRegistry; - ParanetNeuroIncentivesPool public paranetNeuroIncentivesPool; + address public paranetNeuroIncentivesPoolAddress; bytes32 public paranetId; // Percentage of how much tokens from total NEURO emission goes to the Paranet Operator @@ -49,14 +53,14 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent { ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[] public claimedOperatorRewards; mapping(address => uint256) public claimedOperatorRewardsIndexes; - uint16 public cumulativeVotersWeight; + // Is this good type ? + uint256 public cumulativeVotersWeight; ParanetLib.ParanetIncentivizationProposalVoter[] public voters; mapping(address => uint256) public votersIndexes; constructor( address hubAddress, address rewardTokenAddress, - address paranetsRegistryAddress, bytes32 paranetId_, uint16 paranetOperatorRewardPercentage_, uint16 paranetIncentivizationProposalVotersRewardPercentage_ @@ -90,6 +94,11 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent { } } + // TODO: It shouldn't be onlyHub, but onlyParanetOperator probably + function initialize() public onlyHub { + paranetsRegistry = ParanetsRegistry(hub.getContractAddress("ParanetsRegistry")); + } + function name() external pure virtual override returns (string memory) { return _NAME; } @@ -126,6 +135,35 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent { return claimedOperatorRewards[claimedOperatorRewardsIndexes[operatorAddress]].claimedNeuro; } + function addMinerClaimedRewardProfile(address addr, uint256 claimableNeuroReward) external { + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to add claim"); + claimedMinerRewardsIndexes[addr] = claimedMinerRewards.length; + claimedMinerRewards.push( + ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile({ + addr: msg.sender, + claimedNeuro: claimableNeuroReward + }) + ); + } + + function addMinerClaimedReward(address addr, uint256 claimableNeuroReward) external { + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to add claim"); + claimedMinerRewards[claimedMinerRewardsIndexes[addr]].claimedNeuro += claimableNeuroReward; + } + + function addClaimedOperatorReward(address addr, uint256 claimableNeuroReward) external { + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to add claim"); + claimedOperatorRewards[claimedOperatorRewardsIndexes[addr]].claimedNeuro += claimableNeuroReward; + } + + function addOperatorClaimedRewardsProfile(address addr, uint256 claimableNeuroReward) external { + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to add claim"); + claimedMinerRewardsIndexes[addr] = claimedMinerRewards.length; + claimedMinerRewards.push( + ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile({addr: addr, claimedNeuro: claimableNeuroReward}) + ); + } + function getAllRewardedOperators() external view @@ -139,14 +177,16 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent { _; } + // TODO: Limit size of voters_ array function addVoters( ParanetLib.ParanetIncentivizationProposalVoterInput[] calldata voters_ ) external onlyVotersRegistrar { + require(voters_.length <= MAX_VOTERS_PER_BATCH, "Batch too large"); for (uint256 i; i < voters_.length; ) { address voterAddr = voters_[i].addr; uint16 weight = uint16(voters_[i].weight); - require(voterAddr != address(0), "Zero address is not a valid voter"); + require(voterAddr != address(0), "Zero address is not valid voter"); uint256 existingIndex = votersIndexes[voterAddr]; if (existingIndex < voters.length) { @@ -191,14 +231,18 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent { } } - // What if voterAddress doesn't exist, would this remove voter at index 0??? function removeVoter(address voterAddress) external onlyVotersRegistrar { + require(voterAddress != address(0), "Zero address"); uint256 index = votersIndexes[voterAddress]; + require(index < voters.length, "Invalid voter index"); + ParanetLib.ParanetIncentivizationProposalVoter memory voterToRemove = voters[index]; require(voterToRemove.addr == voterAddress, "Voter not found"); - uint16 removedWeight = uint16(voterToRemove.weight); + uint16 removedWeight = voterToRemove.weight; + require(cumulativeVotersWeight >= removedWeight, "Weight underflow"); + // Move last element to deleted position uint256 lastIndex = voters.length - 1; if (index != lastIndex) { ParanetLib.ParanetIncentivizationProposalVoter memory lastVoter = voters[lastIndex]; @@ -207,10 +251,10 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent { } voters.pop(); - delete votersIndexes[voterAddress]; - cumulativeVotersWeight -= removedWeight; + + emit VoterRemoved(voterAddress, removedWeight); } function getVotersCount() external view returns (uint256) { @@ -248,12 +292,8 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent { return (idx < voters.length && voters[idx].addr == addr); } - /** - * @notice Increments the `claimedNeuro` for a specific voter by `amount`. - */ function addVoterClaimedNeuro(address voter, uint256 amount) external { - // Only the main pool contract or an allowed address can do this. - require(msg.sender == address(paranetNeuroIncentivesPool), "Not authorized to add claim"); + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to add claim"); uint256 idx = votersIndexes[voter]; if (idx < voters.length && voters[idx].addr == voter) { @@ -265,18 +305,52 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent { return claimedMinerRewards.length; } - // TODO: paranetId is public, maybe remove getter and access it directly - function getParanetId() public view returns (bytes32) { - return paranetId; + function getClaimedMinerRewardsAtIndex( + uint256 index + ) external view returns (ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile memory) { + return claimedMinerRewards[index]; + } + + function getClaimedOperatorRewardsLength() external view returns (uint256) { + return claimedOperatorRewards.length; } - // This should only be done through hub registerd contracts - function setParanetNeuroIncentivesPool(address paranetNeuroIncentivesPoolAddress) external onlyContracts { - paranetNeuroIncentivesPool = ParanetNeuroIncentivesPool(paranetNeuroIncentivesPoolAddress); + function getClaimedOperatorRewardsAtIndex( + uint256 index + ) external view returns (ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile memory) { + return claimedOperatorRewards[index]; + } + + function addTotalMinersClaimedNeuro(uint256 amount) external { + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to add claim"); + totalMinersClaimedNeuro += amount; + } + + function addTotalOperatorsClaimedNeuro(uint256 amount) external { + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to add claim"); + totalOperatorsClaimedNeuro += amount; + } + + function addTotalVotersClaimedNeuro(uint256 amount) external { + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to add claim"); + totalVotersClaimedNeuro += amount; + } + + function setParanetNeuroIncentivesPool(address _paranetNeuroIncentivesPoolAddress) external onlyContracts { + paranetNeuroIncentivesPoolAddress = _paranetNeuroIncentivesPoolAddress; + } + + function getBalance() public view returns (uint256) { + if (address(token) == address(0)) { + return address(this).balance; + } else { + return token.balanceOf(address(this)); + } } function transferReward(address rewardAddress, uint256 amount) public { - require(msg.sender == address(paranetNeuroIncentivesPool), "Not authorized to add claim"); + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to transfer reward"); + if (address(token) == address(0)) { payable(rewardAddress).transfer(amount); } else { @@ -284,11 +358,118 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent { } } - function getBalance() public view returns (uint256) { - if (address(token) == address(0)) { - return address(this).balance; - } else { - return token.balanceOf(address(this)); + function setTotalMinersClaimedNeuro(uint256 amount) external { + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to set claim"); + totalMinersClaimedNeuro = amount; + } + + function setTotalOperatorsClaimedNeuro(uint256 amount) external { + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to set claim"); + totalOperatorsClaimedNeuro = amount; + } + + function setTotalVotersClaimedNeuro(uint256 amount) external { + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to set claim"); + totalVotersClaimedNeuro = amount; + } + + function decrementTotalMinersClaimedNeuro(uint256 amount) external { + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to decrement claim"); + require(amount <= totalMinersClaimedNeuro, "Amount exceeds total claimed"); + totalMinersClaimedNeuro -= amount; + } + + function decrementTotalOperatorsClaimedNeuro(uint256 amount) external { + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to decrement claim"); + require(amount <= totalOperatorsClaimedNeuro, "Amount exceeds total claimed"); + totalOperatorsClaimedNeuro -= amount; + } + + function decrementTotalVotersClaimedNeuro(uint256 amount) external { + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to decrement claim"); + require(amount <= totalVotersClaimedNeuro, "Amount exceeds total claimed"); + totalVotersClaimedNeuro -= amount; + } + + function getPaginatedClaimedMinerRewards( + uint256 offset, + uint256 limit + ) external view returns (ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[] memory rewards, uint256 total) { + total = claimedMinerRewards.length; + + if (offset >= total || limit == 0) { + return (new ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[](0), total); + } + + uint256 end = offset + limit; + if (end > total) { + end = total; + } + uint256 resultLength = end - offset; + + rewards = new ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[](resultLength); + for (uint256 i = 0; i < resultLength; i++) { + rewards[i] = claimedMinerRewards[offset + i]; + } + } + + function getPaginatedClaimedOperatorRewards( + uint256 offset, + uint256 limit + ) external view returns (ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[] memory rewards, uint256 total) { + total = claimedOperatorRewards.length; + + if (offset >= total || limit == 0) { + return (new ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[](0), total); + } + + uint256 end = offset + limit; + if (end > total) { + end = total; + } + uint256 resultLength = end - offset; + + rewards = new ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[](resultLength); + for (uint256 i = 0; i < resultLength; i++) { + rewards[i] = claimedOperatorRewards[offset + i]; } } + + function getPaginatedVoters( + uint256 offset, + uint256 limit + ) external view returns (ParanetLib.ParanetIncentivizationProposalVoter[] memory votersList, uint256 total) { + total = voters.length; + + if (offset >= total || limit == 0) { + return (new ParanetLib.ParanetIncentivizationProposalVoter[](0), total); + } + + uint256 end = offset + limit; + if (end > total) { + end = total; + } + uint256 resultLength = end - offset; + + votersList = new ParanetLib.ParanetIncentivizationProposalVoter[](resultLength); + for (uint256 i = 0; i < resultLength; i++) { + votersList[i] = voters[offset + i]; + } + } + + function updateVoterWeight(address voter, uint96 newWeight) external onlyVotersRegistrar { + uint256 index = votersIndexes[voter]; + require(index < voters.length && voters[index].addr == voter, "Voter not found"); + + uint96 oldWeight = voters[index].weight; + require( + cumulativeVotersWeight - oldWeight + newWeight <= ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT, + "New weight would exceed maximum" + ); + + cumulativeVotersWeight = cumulativeVotersWeight - oldWeight + newWeight; + voters[index].weight = newWeight; + + emit VoterWeightUpdated(voter, oldWeight, newWeight); + } } From cc58cb2f00065566ac1c33c11de6c22f920cc8a0 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Mon, 10 Feb 2025 22:47:44 +0100 Subject: [PATCH 050/153] wip --- .../paranets/ParanetIncentivesPoolFactory.sol | 162 ++++++++++++++---- .../paranets/ParanetNeuroIncentivesPool.sol | 11 +- .../ParanetNeuroIncentivesPoolStorage.sol | 9 +- 3 files changed, 143 insertions(+), 39 deletions(-) diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index 4c1ad8cb..8dc9d0a5 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -5,6 +5,7 @@ pragma solidity ^0.8.20; import {Hub} from "../storage/Hub.sol"; import {ParanetsRegistry} from "../storage/paranets/ParanetsRegistry.sol"; import {ParanetNeuroIncentivesPool} from "./ParanetNeuroIncentivesPool.sol"; +import {ParanetNeuroIncentivesPoolStorage} from "./ParanetNeuroIncentivesPoolStorage.sol"; import {KnowledgeCollectionStorage} from "../storage/KnowledgeCollectionStorage.sol"; import {ContractStatus} from "../abstract/ContractStatus.sol"; import {IInitializable} from "../interfaces/IInitializable.sol"; @@ -13,9 +14,21 @@ import {IVersioned} from "../interfaces/IVersioned.sol"; import {ParanetLib} from "../libraries/ParanetLib.sol"; contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IInitializable { - event ParanetIncetivesPoolDeployed( + event ParanetIncentivesPoolDeployed( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, + uint256 indexed paranetKATokenId, + address storageAddress, + address poolAddress, + ParanetLib.IncentivesPool incentivesPool + ); + event ParanetIncentivesPoolRedeployed( + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, + uint256 indexed paranetKATokenId, + address storageAddress, + address oldPoolAddress, + address newPoolAddress, ParanetLib.IncentivesPool incentivesPool ); @@ -60,53 +73,138 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn uint256 tracToNeuroEmissionMultiplier, uint16 paranetOperatorRewardPercentage, uint16 paranetIncentivizationProposalVotersRewardPercentage - ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) returns (address) { + ) + external + onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) + returns (address poolAddress, address storageAddress) + { Hub h = hub; ParanetsRegistry pr = paranetsRegistry; + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); string memory incentivesPoolType = isNativeReward ? "Neuroweb" : "NeurowebERC20"; - if ( - pr.hasIncentivesPoolByType( - keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)), - incentivesPoolType - ) - ) { - revert ParanetLib.ParanetIncentivesPoolAlreadyExists( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - incentivesPoolType, - pr.getIncentivesPoolAddress( - keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)), - incentivesPoolType - ) + // Check if pool already exists + if (pr.hasIncentivesPoolByType(paranetId, incentivesPoolType)) { + // Get existing addresses + address existingPoolAddress = pr.getIncentivesPoolAddress(paranetId, incentivesPoolType); + require(existingPoolAddress != address(0), "Invalid existing pool"); + + ParanetNeuroIncentivesPool existingPool = ParanetNeuroIncentivesPool(existingPoolAddress); + storageAddress = address(existingPool.paranetNeuroIncentivesPoolStorage()); + require(storageAddress != address(0), "Invalid existing storage"); + + // Deploy new pool contract + ParanetNeuroIncentivesPool newPool = new ParanetNeuroIncentivesPool( + address(h), + h.getContractAddress("ParanetKnowledgeMinersRegistry"), + storageAddress, + tracToNeuroEmissionMultiplier + ); + + // Update registry with new pool address + pr.setIncentivesPoolAddress(paranetId, incentivesPoolType, address(newPool)); + + // Update storage with new pool address + ParanetNeuroIncentivesPoolStorage(payable(storageAddress)).setParanetNeuroIncentivesPool(address(newPool)); + + poolAddress = address(newPool); + } else { + // Deploy new storage contract + ParanetNeuroIncentivesPoolStorage storage_ = new ParanetNeuroIncentivesPoolStorage( + address(h), + isNativeReward ? address(0) : h.getContractAddress(incentivesPoolType), + paranetId, + paranetOperatorRewardPercentage, + paranetIncentivizationProposalVotersRewardPercentage + ); + + // Deploy new pool contract + ParanetNeuroIncentivesPool pool = new ParanetNeuroIncentivesPool( + address(h), + h.getContractAddress("ParanetKnowledgeMinersRegistry"), + address(storage_), + tracToNeuroEmissionMultiplier ); + + // Initialize storage + storage_.initialize(); + storage_.setParanetNeuroIncentivesPool(address(pool)); + + // Register pool in registry + pr.setIncentivesPoolAddress(paranetId, incentivesPoolType, address(pool)); + + storageAddress = address(storage_); + poolAddress = address(pool); } - ParanetNeuroIncentivesPool incentivesPool = new ParanetNeuroIncentivesPool( + emit ParanetIncentivesPoolDeployed( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + storageAddress, + poolAddress, + ParanetLib.IncentivesPool({poolType: incentivesPoolType, addr: poolAddress}) + ); + + return (poolAddress, storageAddress); + } + + function redeployNeuroIncentivesPool( + bool isNativeReward, + address paranetKCStorageContract, + uint256 paranetKCTokenId, + uint256 paranetKATokenId, + uint256 tracToNeuroEmissionMultiplier + ) + external + onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) + returns (address newPoolAddress, address storageAddress) + { + Hub h = hub; + ParanetsRegistry pr = paranetsRegistry; + bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); + string memory incentivesPoolType = isNativeReward ? "Neuroweb" : "NeurowebERC20"; + + // Verify existing pool and get addresses + require(pr.hasIncentivesPoolByType(paranetId, incentivesPoolType), "Pool doesn't exist"); + address oldPoolAddress = pr.getIncentivesPoolAddress(paranetId, incentivesPoolType); + require(oldPoolAddress != address(0), "Invalid existing pool"); + + // Get storage address from existing pool + ParanetNeuroIncentivesPool existingPool = ParanetNeuroIncentivesPool(oldPoolAddress); + storageAddress = address(existingPool.paranetNeuroIncentivesPoolStorage()); + require(storageAddress != address(0), "Invalid storage address"); + + // Verify storage contract is active + ParanetNeuroIncentivesPoolStorage storage_ = ParanetNeuroIncentivesPoolStorage(payable(storageAddress)); + require(storage_.paranetId() == paranetId, "Storage paranet ID mismatch"); + + // Deploy new pool contract + ParanetNeuroIncentivesPool newPool = new ParanetNeuroIncentivesPool( address(h), - isNativeReward ? address(0) : h.getContractAddress(incentivesPoolType), - h.getContractAddress("ParanetsRegistry"), h.getContractAddress("ParanetKnowledgeMinersRegistry"), - keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)), - tracToNeuroEmissionMultiplier, - paranetOperatorRewardPercentage, - paranetIncentivizationProposalVotersRewardPercentage + storageAddress, + tracToNeuroEmissionMultiplier ); + newPoolAddress = address(newPool); - pr.setIncentivesPoolAddress( - keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)), - incentivesPoolType, - address(incentivesPool) - ); + // Update registry with new pool address + pr.setIncentivesPoolAddress(paranetId, incentivesPoolType, newPoolAddress); + + // Update storage to point to new pool + storage_.setParanetNeuroIncentivesPool(newPoolAddress); - emit ParanetIncetivesPoolDeployed( + emit ParanetIncentivesPoolRedeployed( paranetKCStorageContract, paranetKCTokenId, - ParanetLib.IncentivesPool({poolType: incentivesPoolType, addr: address(incentivesPool)}) + paranetKATokenId, + storageAddress, + oldPoolAddress, + newPoolAddress, + ParanetLib.IncentivesPool({poolType: incentivesPoolType, addr: newPoolAddress}) ); - return address(incentivesPool); + return (newPoolAddress, storageAddress); } function _checkKnowledgeAssetOwner( diff --git a/contracts/paranets/ParanetNeuroIncentivesPool.sol b/contracts/paranets/ParanetNeuroIncentivesPool.sol index acd889ea..115af55f 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPool.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPool.sol @@ -40,10 +40,17 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { uint256 public neuroEmissionMultiplierUpdateDelay = 7 days; // solhint-disable-next-line no-empty-blocks - constructor(address hubAddress, address knowledgeMinersRegistryAddress, uint256 tracToNeuroEmissionMultiplier) { + constructor( + address hubAddress, + address knowledgeMinersRegistryAddress, + address paranetNeuroIncentivesPoolStorageAddress, + uint256 tracToNeuroEmissionMultiplier + ) { hub = Hub(hubAddress); paranetKnowledgeMinersRegistry = ParanetKnowledgeMinersRegistry(knowledgeMinersRegistryAddress); - paranetNeuroIncentivesPoolStorage = ParanetNeuroIncentivesPoolStorage(paranetNeuroIncentivesPoolStorage); + paranetNeuroIncentivesPoolStorage = ParanetNeuroIncentivesPoolStorage( + payable(paranetNeuroIncentivesPoolStorageAddress) + ); neuroEmissionMultipliers.push( ParanetLib.NeuroEmissionMultiplier({ diff --git a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol index 1feb75c5..b1387d8c 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol @@ -35,9 +35,11 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, // Percentage of how much tokens from total NEURO emission goes to the Paranet Operator // Minimum: 0, Maximum: 10,000 (which is 100%) + // TODO: Check if this is correct type uint16 public paranetOperatorRewardPercentage; // Percentage of how much tokens from total NEURO emission goes to the Paranet Incentivization // Proposal Voters. Minimum: 0, Maximum: 10,000 (which is 100%) + // TODO: Check if this is correct type uint16 public paranetIncentivizationProposalVotersRewardPercentage; // Address which can set Voters list and update Total NEURO Emission multiplier @@ -54,7 +56,7 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, mapping(address => uint256) public claimedOperatorRewardsIndexes; // Is this good type ? - uint256 public cumulativeVotersWeight; + uint96 public cumulativeVotersWeight; ParanetLib.ParanetIncentivizationProposalVoter[] public voters; mapping(address => uint256) public votersIndexes; @@ -74,7 +76,6 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, if (rewardTokenAddress != address(0)) { token = IERC20(rewardTokenAddress); } - paranetsRegistry = ParanetsRegistry(paranetsRegistryAddress); require(paranetsRegistry.paranetExists(paranetId_), "Non existent paranet"); paranetId = paranetId_; @@ -239,7 +240,7 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, ParanetLib.ParanetIncentivizationProposalVoter memory voterToRemove = voters[index]; require(voterToRemove.addr == voterAddress, "Voter not found"); - uint16 removedWeight = voterToRemove.weight; + uint96 removedWeight = voterToRemove.weight; require(cumulativeVotersWeight >= removedWeight, "Weight underflow"); // Move last element to deleted position @@ -253,8 +254,6 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, voters.pop(); delete votersIndexes[voterAddress]; cumulativeVotersWeight -= removedWeight; - - emit VoterRemoved(voterAddress, removedWeight); } function getVotersCount() external view returns (uint256) { From e69463f39083e6315dabbe172316c6040889fcca Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Mon, 10 Feb 2025 22:52:43 +0100 Subject: [PATCH 051/153] Copy multiplier from old contract when redeploying --- contracts/paranets/ParanetIncentivesPoolFactory.sol | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index 8dc9d0a5..b879098a 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -153,8 +153,7 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn bool isNativeReward, address paranetKCStorageContract, uint256 paranetKCTokenId, - uint256 paranetKATokenId, - uint256 tracToNeuroEmissionMultiplier + uint256 paranetKATokenId ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) @@ -179,6 +178,10 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn ParanetNeuroIncentivesPoolStorage storage_ = ParanetNeuroIncentivesPoolStorage(payable(storageAddress)); require(storage_.paranetId() == paranetId, "Storage paranet ID mismatch"); + address oldLogicContract = storage_.paranetNeuroIncentivesPoolAddress(); + ParanetNeuroIncentivesPool oldPool = ParanetNeuroIncentivesPool(oldLogicContract); + uint256 tracToNeuroEmissionMultiplier = oldPool.getEffectiveNeuroEmissionMultiplier(block.timestamp); + // Deploy new pool contract ParanetNeuroIncentivesPool newPool = new ParanetNeuroIncentivesPool( address(h), From 04ac3f95a30e8040f1bd0a3c40aa9eb8f92c3e43 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 11 Feb 2025 11:05:58 +0100 Subject: [PATCH 052/153] Add events for storage --- .../ParanetNeuroIncentivesPoolStorage.sol | 117 ++++++++++-------- 1 file changed, 64 insertions(+), 53 deletions(-) diff --git a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol index b1387d8c..5627c167 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol @@ -11,9 +11,6 @@ import {IVersioned} from "../interfaces/IVersioned.sol"; import {IInitializable} from "../interfaces/IInitializable.sol"; import {ParanetLib} from "../libraries/ParanetLib.sol"; -// TODO: When working with arrays check if it's empty -// TODO: Add getter for length, at index, reverse look up for arrays - contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInitializable { event NeuroRewardDeposit(address sender, uint256 amount); event VoterWeightUpdated(address indexed voter, uint96 oldWeight, uint96 newWeight); @@ -23,6 +20,17 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, event TotalMinersClaimedNeuroDecremented(uint256 amount, uint256 newTotal); event TotalOperatorsClaimedNeuroDecremented(uint256 amount, uint256 newTotal); event TotalVotersClaimedNeuroDecremented(uint256 amount, uint256 newTotal); + event VotersRegistrarTransferred(address indexed previousRegistrar, address indexed newRegistrar); + event MinerRewardProfileAdded(address indexed miner, uint256 amount); + event MinerRewardIncreased(address indexed miner, uint256 additionalAmount, uint256 newTotal); + event OperatorRewardProfileAdded(address indexed operator, uint256 amount); + event OperatorRewardIncreased(address indexed operator, uint256 additionalAmount, uint256 newTotal); + event VoterAdded(address indexed voter, uint16 weight); + event VoterRemoved(address indexed voter, uint96 weight); + event VotersRemoved(uint256 count); + event VoterRewardClaimed(address indexed voter, uint256 amount); + event IncentivesPoolAddressSet(address indexed oldAddress, address indexed newAddress); + event RewardTransferred(address indexed recipient, uint256 amount); string private constant _NAME = "ParanetNeuroIncentivesPoolStorage"; string private constant _VERSION = "1.0.0"; @@ -35,11 +43,9 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, // Percentage of how much tokens from total NEURO emission goes to the Paranet Operator // Minimum: 0, Maximum: 10,000 (which is 100%) - // TODO: Check if this is correct type uint16 public paranetOperatorRewardPercentage; // Percentage of how much tokens from total NEURO emission goes to the Paranet Incentivization // Proposal Voters. Minimum: 0, Maximum: 10,000 (which is 100%) - // TODO: Check if this is correct type uint16 public paranetIncentivizationProposalVotersRewardPercentage; // Address which can set Voters list and update Total NEURO Emission multiplier @@ -95,8 +101,7 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, } } - // TODO: It shouldn't be onlyHub, but onlyParanetOperator probably - function initialize() public onlyHub { + function initialize() public onlyContracts { paranetsRegistry = ParanetsRegistry(hub.getContractAddress("ParanetsRegistry")); } @@ -117,7 +122,9 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, } function transferVotersRegistrarRole(address newRegistrar) external onlyVotersRegistrar { + address oldRegistrar = votersRegistrar; votersRegistrar = newRegistrar; + emit VotersRegistrarTransferred(oldRegistrar, newRegistrar); } function getAllRewardedMiners() @@ -137,32 +144,36 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, } function addMinerClaimedRewardProfile(address addr, uint256 claimableNeuroReward) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to add claim"); + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); claimedMinerRewardsIndexes[addr] = claimedMinerRewards.length; claimedMinerRewards.push( - ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile({ - addr: msg.sender, - claimedNeuro: claimableNeuroReward - }) + ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile({addr: addr, claimedNeuro: claimableNeuroReward}) ); + emit MinerRewardProfileAdded(addr, claimableNeuroReward); } function addMinerClaimedReward(address addr, uint256 claimableNeuroReward) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to add claim"); - claimedMinerRewards[claimedMinerRewardsIndexes[addr]].claimedNeuro += claimableNeuroReward; - } - - function addClaimedOperatorReward(address addr, uint256 claimableNeuroReward) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to add claim"); - claimedOperatorRewards[claimedOperatorRewardsIndexes[addr]].claimedNeuro += claimableNeuroReward; + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); + uint256 newTotal = claimedMinerRewards[claimedMinerRewardsIndexes[addr]].claimedNeuro + claimableNeuroReward; + claimedMinerRewards[claimedMinerRewardsIndexes[addr]].claimedNeuro = newTotal; + emit MinerRewardIncreased(addr, claimableNeuroReward, newTotal); } function addOperatorClaimedRewardsProfile(address addr, uint256 claimableNeuroReward) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to add claim"); - claimedMinerRewardsIndexes[addr] = claimedMinerRewards.length; - claimedMinerRewards.push( + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); + claimedOperatorRewardsIndexes[addr] = claimedOperatorRewards.length; + claimedOperatorRewards.push( ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile({addr: addr, claimedNeuro: claimableNeuroReward}) ); + emit OperatorRewardProfileAdded(addr, claimableNeuroReward); + } + + function addClaimedOperatorReward(address addr, uint256 claimableNeuroReward) external { + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); + uint256 newTotal = claimedOperatorRewards[claimedOperatorRewardsIndexes[addr]].claimedNeuro + + claimableNeuroReward; + claimedOperatorRewards[claimedOperatorRewardsIndexes[addr]].claimedNeuro = newTotal; + emit OperatorRewardIncreased(addr, claimableNeuroReward, newTotal); } function getAllRewardedOperators() @@ -173,12 +184,6 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, return claimedOperatorRewards; } - modifier onlyVotersRegistrar() { - require(msg.sender == votersRegistrar, "Fn can only be used by registrar"); - _; - } - - // TODO: Limit size of voters_ array function addVoters( ParanetLib.ParanetIncentivizationProposalVoterInput[] calldata voters_ ) external onlyVotersRegistrar { @@ -187,8 +192,6 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, address voterAddr = voters_[i].addr; uint16 weight = uint16(voters_[i].weight); - require(voterAddr != address(0), "Zero address is not valid voter"); - uint256 existingIndex = votersIndexes[voterAddr]; if (existingIndex < voters.length) { revert("Voter already exists"); @@ -201,6 +204,8 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, cumulativeVotersWeight += weight; + emit VoterAdded(voterAddr, weight); + unchecked { i++; } @@ -209,9 +214,6 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, require(cumulativeVotersWeight <= ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT, "Cumulative weight is too big"); } - /** - * @notice Remove the last `limit` voters from the array. - */ function removeVoters(uint256 limit) external onlyVotersRegistrar { require(voters.length >= limit, "Limit exceeds number of voters"); @@ -226,14 +228,17 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, // Remove last element voters.pop(); + emit VoterRemoved(voter.addr, voter.weight); + unchecked { i++; } } + + emit VotersRemoved(limit); } function removeVoter(address voterAddress) external onlyVotersRegistrar { - require(voterAddress != address(0), "Zero address"); uint256 index = votersIndexes[voterAddress]; require(index < voters.length, "Invalid voter index"); @@ -254,6 +259,8 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, voters.pop(); delete votersIndexes[voterAddress]; cumulativeVotersWeight -= removedWeight; + + emit VoterRemoved(voterAddress, removedWeight); } function getVotersCount() external view returns (uint256) { @@ -272,7 +279,7 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, } uint256 index = votersIndexes[voterAddress]; - if (index > voters.length || voters[index].addr != voterAddress) { + if (index >= voters.length || voters[index].addr != voterAddress) { return ParanetLib.ParanetIncentivizationProposalVoter({addr: address(0), weight: 0, claimedNeuro: 0}); } @@ -288,15 +295,15 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, function isProposalVoter(address addr) external view returns (bool) { if (voters.length == 0) return false; uint256 idx = votersIndexes[addr]; - return (idx < voters.length && voters[idx].addr == addr); + return (idx <= voters.length && voters[idx].addr == addr); } function addVoterClaimedNeuro(address voter, uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to add claim"); - + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); uint256 idx = votersIndexes[voter]; if (idx < voters.length && voters[idx].addr == voter) { voters[idx].claimedNeuro += amount; + emit VoterRewardClaimed(voter, amount); } } @@ -321,22 +328,24 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, } function addTotalMinersClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to add claim"); + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); totalMinersClaimedNeuro += amount; } function addTotalOperatorsClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to add claim"); + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); totalOperatorsClaimedNeuro += amount; } function addTotalVotersClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to add claim"); + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); totalVotersClaimedNeuro += amount; } function setParanetNeuroIncentivesPool(address _paranetNeuroIncentivesPoolAddress) external onlyContracts { + address oldAddress = paranetNeuroIncentivesPoolAddress; paranetNeuroIncentivesPoolAddress = _paranetNeuroIncentivesPoolAddress; + emit IncentivesPoolAddressSet(oldAddress, _paranetNeuroIncentivesPoolAddress); } function getBalance() public view returns (uint256) { @@ -348,45 +357,42 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, } function transferReward(address rewardAddress, uint256 amount) public { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to transfer reward"); - + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); if (address(token) == address(0)) { payable(rewardAddress).transfer(amount); } else { token.transfer(rewardAddress, amount); } + emit RewardTransferred(rewardAddress, amount); } function setTotalMinersClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to set claim"); + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); totalMinersClaimedNeuro = amount; } function setTotalOperatorsClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to set claim"); + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); totalOperatorsClaimedNeuro = amount; } function setTotalVotersClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to set claim"); + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); totalVotersClaimedNeuro = amount; } function decrementTotalMinersClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to decrement claim"); - require(amount <= totalMinersClaimedNeuro, "Amount exceeds total claimed"); + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); totalMinersClaimedNeuro -= amount; } function decrementTotalOperatorsClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to decrement claim"); - require(amount <= totalOperatorsClaimedNeuro, "Amount exceeds total claimed"); + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); totalOperatorsClaimedNeuro -= amount; } function decrementTotalVotersClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Not authorized to decrement claim"); - require(amount <= totalVotersClaimedNeuro, "Amount exceeds total claimed"); + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); totalVotersClaimedNeuro -= amount; } @@ -458,7 +464,7 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, function updateVoterWeight(address voter, uint96 newWeight) external onlyVotersRegistrar { uint256 index = votersIndexes[voter]; - require(index < voters.length && voters[index].addr == voter, "Voter not found"); + require(index <= voters.length && voters[index].addr == voter, "Voter not found"); uint96 oldWeight = voters[index].weight; require( @@ -471,4 +477,9 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, emit VoterWeightUpdated(voter, oldWeight, newWeight); } + + modifier onlyVotersRegistrar() { + require(msg.sender == votersRegistrar, "Fn can only be used by registrar"); + _; + } } From f6e326ff34e63b2eb1a9557aa4dc98cbb4e1a378 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 11 Feb 2025 11:16:01 +0100 Subject: [PATCH 053/153] remove events --- .../paranets/ParanetNeuroIncentivesPool.sol | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/contracts/paranets/ParanetNeuroIncentivesPool.sol b/contracts/paranets/ParanetNeuroIncentivesPool.sol index 115af55f..5ab430b6 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPool.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPool.sol @@ -12,12 +12,8 @@ import {IVersioned} from "../interfaces/IVersioned.sol"; import {ParanetLib} from "../libraries/ParanetLib.sol"; contract ParanetNeuroIncentivesPool is INamed, IVersioned { - event NeuroRewardDeposit(address indexed sender, uint256 amount); event NeuroEmissionMultiplierUpdateInitiated(uint256 oldMultiplier, uint256 newMultiplier, uint256 timestamp); event NeuroEmissionMultiplierUpdateFinalized(uint256 oldMultiplier, uint256 newMultiplier); - event ParanetKnowledgeMinerRewardClaimed(address indexed miner, uint256 amount); - event ParanetOperatorRewardClaimed(address indexed operator, uint256 amount); - event ParanetIncentivizationProposalVoterRewardClaimed(address indexed voter, uint256 amount); string private constant _NAME = "ParanetNeuroIncentivesPool"; string private constant _VERSION = "1.0.0"; @@ -196,7 +192,6 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { ); } - // TODO: Rework it should interact with storage function getTotalKnowledgeMinerIncentiveEstimation() public view returns (uint256) { uint96 unrewardedTracSpent = paranetKnowledgeMinersRegistry.getUnrewardedTracSpent( msg.sender, @@ -227,7 +222,6 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { ParanetLib.PERCENTAGE_SCALING_FACTOR; } - // TODO: Rework it should interact with storage function getTotalAllKnowledgeMinersIncentiveEstimation() public view returns (uint256) { return _getIncentiveEstimation( @@ -261,7 +255,6 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { : minersRewardLimit - totalMinersClaimedNeuro; } - // TODO: Rework it should interact with storage function getClaimableAllKnowledgeMinersRewardAmount() public view returns (uint256) { uint256 neuroReward = getTotalAllKnowledgeMinersIncentiveEstimation(); @@ -330,11 +323,8 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { paranetNeuroIncentivesPoolStorage.addTotalMinersClaimedNeuro(claimableNeuroReward); paranetNeuroIncentivesPoolStorage.transferReward(msg.sender, claimableNeuroReward); - - emit ParanetKnowledgeMinerRewardClaimed(msg.sender, claimableNeuroReward); } - // TODO: Rework it should interact with storage function getTotalParanetOperatorIncentiveEstimation() public view returns (uint256) { return _getIncentiveEstimation( @@ -343,7 +333,6 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { ); } - // TODO: Rework it should interact with storage function getClaimableParanetOperatorRewardAmount() public view returns (uint256) { uint256 neuroReward = getTotalParanetOperatorIncentiveEstimation(); @@ -382,11 +371,8 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { paranetNeuroIncentivesPoolStorage.addTotalOperatorsClaimedNeuro(claimableNeuroReward); paranetNeuroIncentivesPoolStorage.transferReward(msg.sender, claimableNeuroReward); - - emit ParanetOperatorRewardClaimed(msg.sender, claimableNeuroReward); } - // TODO: Rework it should interact with storage function getTotalProposalVoterIncentiveEstimation() public view returns (uint256) { uint256 effectiveNeuroEmissionMultiplier = getEffectiveNeuroEmissionMultiplier(block.timestamp); uint96 cumulativeKnowledgeValueSingleVoterPart = (((paranetsRegistry.getCumulativeKnowledgeValue( @@ -416,7 +402,6 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { .claimedNeuro; } - // TODO: Rework it should interact with storage function getTotalAllProposalVotersIncentiveEstimation() public view returns (uint256) { return _getIncentiveEstimation( @@ -425,7 +410,6 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { ); } - // TODO: Rework it should interact with storage function getClaimableProposalVoterRewardAmount() public view returns (uint256) { if ( paranetNeuroIncentivesPoolStorage.getVotersCount() == 0 || @@ -462,7 +446,6 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { .claimedNeuro; } - // TODO: Rework it should interact with storage function getClaimableAllProposalVotersRewardAmount() public view returns (uint256) { uint256 neuroReward = getTotalAllProposalVotersIncentiveEstimation(); @@ -479,7 +462,6 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { : votersRewardLimit - paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro(); } - // TODO: Rework it should interact with storage function claimIncentivizationProposalVoterReward() external onlyParanetIncentivizationProposalVoter { if (paranetNeuroIncentivesPoolStorage.cumulativeVotersWeight() != ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT) { revert ParanetLib.InvalidCumulativeVotersWeight( @@ -501,11 +483,8 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { paranetNeuroIncentivesPoolStorage.addTotalVotersClaimedNeuro(claimableNeuroReward); paranetNeuroIncentivesPoolStorage.transferReward(msg.sender, claimableNeuroReward); - - emit ParanetIncentivizationProposalVoterRewardClaimed(msg.sender, claimableNeuroReward); } - // TODO: Rework it should interact with storage function _getIncentiveEstimation( uint16 rewardPercentage, uint256 totalClaimedNeuro From c7c21f242408544c2b7159ba4602ebbe946487e0 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 11 Feb 2025 11:34:52 +0100 Subject: [PATCH 054/153] fixes --- contracts/paranets/ParanetNeuroIncentivesPool.sol | 4 ++-- contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/contracts/paranets/ParanetNeuroIncentivesPool.sol b/contracts/paranets/ParanetNeuroIncentivesPool.sol index 5ab430b6..2b6f92d4 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPool.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPool.sol @@ -336,7 +336,7 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { function getClaimableParanetOperatorRewardAmount() public view returns (uint256) { uint256 neuroReward = getTotalParanetOperatorIncentiveEstimation(); - uint256 operatorRewardLimit = ((address(this).balance + + uint256 operatorRewardLimit = ((paranetNeuroIncentivesPoolStorage.getBalance() + paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro() + paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro() + paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro()) * @@ -449,7 +449,7 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { function getClaimableAllProposalVotersRewardAmount() public view returns (uint256) { uint256 neuroReward = getTotalAllProposalVotersIncentiveEstimation(); - uint256 votersRewardLimit = ((address(this).balance + + uint256 votersRewardLimit = ((paranetNeuroIncentivesPoolStorage.getBalance() + paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro() + paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro() + paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro()) * diff --git a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol index 5627c167..8449428a 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol @@ -83,7 +83,8 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, token = IERC20(rewardTokenAddress); } - require(paranetsRegistry.paranetExists(paranetId_), "Non existent paranet"); + ParanetsRegistry pr = ParanetsRegistry(hub.getContractAddress("ParanetsRegistry")); + require(pr.paranetExists(paranetId_), "Non existent paranet"); paranetId = paranetId_; paranetOperatorRewardPercentage = paranetOperatorRewardPercentage_; From 3925bd5f2b058ecd0123d7ed47a07e2e64268208 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 11 Feb 2025 13:26:23 +0100 Subject: [PATCH 055/153] Rename UniversalCollectionLocator to UniversalAssetCollectionLocator --- contracts/libraries/ParanetLib.sol | 2 +- contracts/paranets/Paranet.sol | 2 +- .../paranets/ParanetKnowledgeCollectionsRegistry.sol | 8 +++++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index 0d6bad7d..642a2c25 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -10,7 +10,7 @@ library ParanetLib { uint16 constant PERCENTAGE_SCALING_FACTOR = 10 ** 4; uint16 constant MAX_CUMULATIVE_VOTERS_WEIGHT = 10 ** 4; - struct UniversalCollectionLocator { + struct UniversalAssetCollectionLocator { address knowledgeCollectionStorageContract; uint256 knowledgeCollectionTokenId; } diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 7497e1f4..a4da8e80 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -949,7 +949,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { bytes32 paranetId, uint256 offset, uint256 limit - ) external view returns (ParanetLib.UniversalCollectionLocator[] memory) { + ) external view returns (ParanetLib.UniversalAssetCollectionLocator[] memory) { ParanetsRegistry pr = paranetsRegistry; bytes32[] memory knowledgeCollections = pr.getKnowledgeCollectionsWithPagination(paranetId, offset, limit); diff --git a/contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol b/contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol index be289394..2ac22a68 100644 --- a/contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol +++ b/contracts/storage/paranets/ParanetKnowledgeCollectionsRegistry.sol @@ -71,15 +71,17 @@ contract ParanetKnowledgeCollectionsRegistry is INamed, IVersioned, HubDependent function getKnowledgeCollectionLocators( bytes32[] calldata knowledgeCollectionIds - ) external view returns (ParanetLib.UniversalCollectionLocator[] memory) { + ) external view returns (ParanetLib.UniversalAssetCollectionLocator[] memory) { uint256 length = knowledgeCollectionIds.length; - ParanetLib.UniversalCollectionLocator[] memory locators = new ParanetLib.UniversalCollectionLocator[](length); + ParanetLib.UniversalAssetCollectionLocator[] memory locators = new ParanetLib.UniversalAssetCollectionLocator[]( + length + ); for (uint256 i = 0; i < length; i++) { bytes32 id = knowledgeCollectionIds[i]; - locators[i] = ParanetLib.UniversalCollectionLocator({ + locators[i] = ParanetLib.UniversalAssetCollectionLocator({ knowledgeCollectionStorageContract: knowledgeCollections[id].knowledgeCollectionStorageContract, knowledgeCollectionTokenId: knowledgeCollections[id].knowledgeCollectionTokenId }); From f9fb318373ec1ee33e020d98871ab40b87e22dff Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 11 Feb 2025 13:34:54 +0100 Subject: [PATCH 056/153] Rename ParanetLib.KnowledgeCollectionIsAPartOfOtherParanet to ParanetLib.KnowledgeCollectionIsAPartOfAParanet --- contracts/libraries/ParanetLib.sol | 2 +- contracts/paranets/Paranet.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index 642a2c25..3b898c1a 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -232,7 +232,7 @@ library ParanetLib { uint256 knowledgeCollectionTokenId, uint256 knowledgeAssetTokenId ); - error KnowledgeCollectionIsAPartOfOtherParanet( + error KnowledgeCollectionIsAPartOfAParanet( address paranetKnowledgeCollectionStorageAddress, uint256 paranetKnowledgeCollectionTokenId, bytes32 paranetId diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index a4da8e80..853bfc4d 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -1063,7 +1063,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)) ) ) { - revert ParanetLib.KnowledgeCollectionIsAPartOfOtherParanet( + revert ParanetLib.KnowledgeCollectionIsAPartOfAParanet( knowledgeCollectionStorageContract, knowledgeCollectionTokenId, paranetKnowledgeCollectionsRegistry.getParanetId( From 051e95011700de85d4fbd8b0dc83d08f94ad042b Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Tue, 11 Feb 2025 14:54:13 +0100 Subject: [PATCH 057/153] Add unit tests to Epoch Storage --- test/unit/EpochStorage.test.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/unit/EpochStorage.test.ts b/test/unit/EpochStorage.test.ts index 6a42956a..c86d0ff4 100644 --- a/test/unit/EpochStorage.test.ts +++ b/test/unit/EpochStorage.test.ts @@ -26,6 +26,11 @@ describe('@unit EpochStorage', () => { ({ accounts, EpochStorage } = await loadFixture(deployEpochStorageFixture)); }); + it('Should have correct name and version', async () => { + expect(await EpochStorage.name()).to.equal('EpochStorage'); + expect(await EpochStorage.version()).to.equal('1.0.0'); + }); + it('Add knowledge value for single epoch, verify totals and max', async () => { const epoch = 10; await EpochStorage.addEpochProducedKnowledgeValue(123, epoch, 500); From d01474a1b904d2638b2163161a8baafd27822c24 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Tue, 11 Feb 2025 14:56:20 +0100 Subject: [PATCH 058/153] Add Chronos unit tests --- test/unit/Paymaster.test.ts | 211 ++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 test/unit/Paymaster.test.ts diff --git a/test/unit/Paymaster.test.ts b/test/unit/Paymaster.test.ts new file mode 100644 index 00000000..547fd0bf --- /dev/null +++ b/test/unit/Paymaster.test.ts @@ -0,0 +1,211 @@ +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { expect } from 'chai'; +import { parseEther } from 'ethers'; +import hre from 'hardhat'; + +import { Hub, Paymaster, Token } from '../../typechain'; + +describe('@unit Paymaster', () => { + let accounts: SignerWithAddress[]; + let Hub: Hub; + let Token: Token; + let Paymaster: Paymaster; + let owner: SignerWithAddress; + let user: SignerWithAddress; + let knowledgeCollectionAddress: string; + + async function deployPaymasterFixture() { + await hre.deployments.fixture(['Hub', 'Token']); + + accounts = await hre.ethers.getSigners(); + [owner, user] = accounts; + + Hub = await hre.ethers.getContract('Hub'); + Token = await hre.ethers.getContract('Token'); + + // Deploy Paymaster + const PaymasterFactory = await hre.ethers.getContractFactory('Paymaster'); + Paymaster = await PaymasterFactory.deploy(Hub.getAddress()); + + // Set mock KnowledgeCollection address in Hub + knowledgeCollectionAddress = accounts[3].address; + await Hub.setContractAddress( + 'KnowledgeCollection', + knowledgeCollectionAddress, + ); + + // Reset user's balance to zero first + const initialBalance = await Token.balanceOf(user.address); + if (initialBalance > 0) { + const BURN_ADDRESS = accounts[66].address; + await Token.connect(user).transfer(BURN_ADDRESS, initialBalance); + } + + // Mint some tokens to user for testing + await Token.mint(user.address, parseEther('100')); + + return { accounts, Hub, Token, Paymaster, owner, user }; + } + + beforeEach(async () => { + ({ accounts, Hub, Token, Paymaster, owner, user } = await loadFixture( + deployPaymasterFixture, + )); + }); + + describe('Constructor', () => { + it('Should set correct hub address', async () => { + expect(await Paymaster.hub()).to.equal(await Hub.getAddress()); + }); + + it('Should set correct token contract', async () => { + expect(await Paymaster.tokenContract()).to.equal( + await Token.getAddress(), + ); + }); + + it('Should set correct owner', async () => { + expect(await Paymaster.owner()).to.equal(owner.address); + }); + }); + + /* eslint-disable @typescript-eslint/no-unused-expressions */ + describe('Access Control', () => { + it('Should allow owner to add allowed address', async () => { + await Paymaster.addAllowedAddress(user.address); + expect(await Paymaster.allowedAddresses(user.address)).to.be.true; + }); + + it('Should not allow non-owner to add allowed address', async () => { + await expect( + Paymaster.connect(user).addAllowedAddress(user.address), + ).to.be.revertedWithCustomError(Paymaster, 'OwnableUnauthorizedAccount'); + }); + + it('Should allow owner to remove allowed address', async () => { + await Paymaster.addAllowedAddress(user.address); + await Paymaster.removeAllowedAddress(user.address); + expect(await Paymaster.allowedAddresses(user.address)).to.be.false; + }); + }); + + describe('Fund Paymaster', () => { + const fundAmount = parseEther('100'); + + beforeEach(async () => { + // Approve tokens first + await Token.connect(user).approve(Paymaster.getAddress(), fundAmount); + }); + + it('Should allow funding with tokens', async () => { + await expect(Paymaster.connect(user).fundPaymaster(fundAmount)) + .to.emit(Token, 'Transfer') + .withArgs(user.address, await Paymaster.getAddress(), fundAmount); + }); + + it('Should revert with zero amount', async () => { + await expect( + Paymaster.connect(user).fundPaymaster(0), + ).to.be.revertedWithCustomError(Paymaster, 'ZeroTokenAmount'); + }); + + it('Should revert with insufficient allowance', async () => { + await Token.connect(user).approve(Paymaster.getAddress(), 0); + await expect( + Paymaster.connect(user).fundPaymaster(fundAmount), + ).to.be.revertedWithCustomError(Paymaster, 'TooLowAllowance'); + }); + + it('Should revert with insufficient balance', async () => { + const tooMuch = parseEther('200'); + await Token.connect(user).approve(Paymaster.getAddress(), tooMuch); + await expect( + Paymaster.connect(user).fundPaymaster(tooMuch), + ).to.be.revertedWithCustomError(Paymaster, 'TooLowBalance'); + }); + }); + + describe('Withdraw', () => { + const withdrawAmount = parseEther('50'); + + beforeEach(async () => { + // Fund the paymaster first + await Token.connect(user).approve( + Paymaster.getAddress(), + parseEther('100'), + ); + await Paymaster.connect(user).fundPaymaster(parseEther('100')); + }); + + it('Should allow owner to withdraw tokens', async () => { + await expect(Paymaster.withdraw(owner.address, withdrawAmount)) + .to.emit(Token, 'Transfer') + .withArgs(await Paymaster.getAddress(), owner.address, withdrawAmount); + }); + + it('Should revert when non-owner tries to withdraw', async () => { + await expect( + Paymaster.connect(user).withdraw(user.address, withdrawAmount), + ).to.be.revertedWithCustomError(Paymaster, 'OwnableUnauthorizedAccount'); + }); + + it('Should revert with zero amount', async () => { + await expect( + Paymaster.withdraw(owner.address, 0), + ).to.be.revertedWithCustomError(Paymaster, 'ZeroTokenAmount'); + }); + + it('Should revert with insufficient balance', async () => { + const tooMuch = parseEther('200'); + await expect( + Paymaster.withdraw(owner.address, tooMuch), + ).to.be.revertedWithCustomError(Paymaster, 'TooLowBalance'); + }); + }); + + describe('Cover Cost', () => { + const coverAmount = parseEther('30'); + + beforeEach(async () => { + // Fund the paymaster first + await Token.connect(user).approve( + Paymaster.getAddress(), + parseEther('100'), + ); + await Paymaster.connect(user).fundPaymaster(parseEther('100')); + // Add allowed address + await Paymaster.addAllowedAddress(user.address); + }); + + it('Should allow allowed address to cover cost', async () => { + await expect(Paymaster.connect(user).coverCost(coverAmount)) + .to.emit(Token, 'Transfer') + .withArgs( + await Paymaster.getAddress(), + knowledgeCollectionAddress, + coverAmount, + ); + }); + + it('Should revert when non-allowed address tries to cover cost', async () => { + const nonAllowed = accounts[4]; + await expect( + Paymaster.connect(nonAllowed).coverCost(coverAmount), + ).to.be.revertedWithCustomError(Paymaster, 'NotAllowed'); + }); + + it('Should revert with zero amount', async () => { + await expect( + Paymaster.connect(user).coverCost(0), + ).to.be.revertedWithCustomError(Paymaster, 'ZeroTokenAmount'); + }); + + it('Should revert with insufficient balance', async () => { + const tooMuch = parseEther('200'); + await expect( + Paymaster.connect(user).coverCost(tooMuch), + ).to.be.revertedWithCustomError(Paymaster, 'TooLowBalance'); + }); + }); +}); From d2e09ea8993dc02aaf633515f1338eec5c36cbf1 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Tue, 11 Feb 2025 14:57:51 +0100 Subject: [PATCH 059/153] Add Chronos unit tests --- test/unit/Chronos.test.ts | 164 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 test/unit/Chronos.test.ts diff --git a/test/unit/Chronos.test.ts b/test/unit/Chronos.test.ts new file mode 100644 index 00000000..89d5fcd3 --- /dev/null +++ b/test/unit/Chronos.test.ts @@ -0,0 +1,164 @@ +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { loadFixture, time } from '@nomicfoundation/hardhat-network-helpers'; +import { expect } from 'chai'; +import hre from 'hardhat'; + +import { Chronos } from '../../typechain'; + +describe('@unit Chronos', () => { + let accounts: SignerWithAddress[]; + let Chronos: Chronos; + + async function deployChronosFixture() { + const currentTime = await time.latest(); + const startTime = currentTime + 3600; // Start 1 hour from now + const epochLength = 3600; // 1 hour epochs + + const ChronosFactory = await hre.ethers.getContractFactory('Chronos'); + Chronos = await ChronosFactory.deploy(startTime, epochLength); + + accounts = await hre.ethers.getSigners(); + return { accounts, Chronos, startTime, epochLength }; + } + + beforeEach(async () => { + ({ accounts, Chronos } = await loadFixture(deployChronosFixture)); + }); + + describe('Constructor', () => { + it('Should revert with invalid start time', async () => { + const ChronosFactory = await hre.ethers.getContractFactory('Chronos'); + await expect( + ChronosFactory.deploy(0, 3600), + ).to.be.revertedWithCustomError(ChronosFactory, 'InvalidStartTime'); + }); + + it('Should revert with invalid epoch length', async () => { + const currentTime = await time.latest(); + const ChronosFactory = await hre.ethers.getContractFactory('Chronos'); + await expect( + ChronosFactory.deploy(currentTime + 3600, 0), + ).to.be.revertedWithCustomError(ChronosFactory, 'InvalidEpochLength'); + }); + }); + + describe('Basic getters', () => { + it('Should return correct start time', async () => { + const startTime = await Chronos.START_TIME(); + expect(await Chronos.startTime()).to.equal(startTime); + }); + + it('Should return correct epoch length', async () => { + const epochLength = await Chronos.EPOCH_LENGTH(); + expect(await Chronos.epochLength()).to.equal(epochLength); + }); + }); + + describe('getCurrentEpoch', () => { + it('Should return 1 before start time', async () => { + expect(await Chronos.getCurrentEpoch()).to.equal(1); + }); + + it('Should return correct epoch after start time', async () => { + const startTime = await Chronos.START_TIME(); + await time.increaseTo('0x' + startTime.toString(16)); + await time.increase(7200); // 2 hours after start + expect(await Chronos.getCurrentEpoch()).to.equal(3); // Should be in 3rd epoch + }); + }); + + describe('epochAtTimestamp', () => { + it('Should return 1 for timestamp before start time', async () => { + const startTime = await Chronos.START_TIME(); + expect(await Chronos.epochAtTimestamp(startTime - 1n)).to.equal(1); + }); + + it('Should return correct epoch for timestamp after start time', async () => { + const startTime = await Chronos.START_TIME(); + const timestamp = startTime + 7200n; // 2 hours after start + expect(await Chronos.epochAtTimestamp(timestamp)).to.equal(3); + }); + }); + + describe('timeUntilNextEpoch', () => { + it('Should return time until first epoch before start', async () => { + const startTime = await Chronos.START_TIME(); + const currentTime = await time.latest(); + const expected = startTime + 3600n - BigInt(currentTime); + expect(await Chronos.timeUntilNextEpoch()).to.be.closeTo(expected, 5); + }); + + it('Should return correct time within an epoch', async () => { + const startTime = await Chronos.START_TIME(); + await time.increaseTo('0x' + startTime.toString(16)); + await time.increase(1800); // Half epoch passed + expect(await Chronos.timeUntilNextEpoch()).to.be.closeTo(1800n, 5); + }); + }); + + /* eslint-disable @typescript-eslint/no-unused-expressions */ + describe('hasEpochElapsed', () => { + it('Should return false for future epochs', async () => { + expect(await Chronos.hasEpochElapsed(5)).to.be.false; + }); + + it('Should return true for past epochs', async () => { + const startTime = await Chronos.START_TIME(); + await time.increaseTo('0x' + startTime.toString(16)); + await time.increase(7200); // 2 hours after start + expect(await Chronos.hasEpochElapsed(2)).to.be.true; + }); + }); + + describe('timestampForEpoch', () => { + it('Should return 0 for epoch 0', async () => { + expect(await Chronos.timestampForEpoch(0)).to.equal(0); + }); + + it('Should return correct timestamp for future epoch', async () => { + const startTime = await Chronos.START_TIME(); + const epochLength = await Chronos.EPOCH_LENGTH(); + expect(await Chronos.timestampForEpoch(3)).to.equal( + startTime + epochLength * 2n, + ); + }); + }); + + describe('elapsedTimeInCurrentEpoch', () => { + it('Should return 0 before start time', async () => { + expect(await Chronos.elapsedTimeInCurrentEpoch()).to.equal(0); + }); + + it('Should return correct elapsed time within epoch', async () => { + const startTime = await Chronos.START_TIME(); + await time.increaseTo('0x' + startTime.toString(16)); + await time.increase(1800); // Half epoch passed + expect(await Chronos.elapsedTimeInCurrentEpoch()).to.be.closeTo(1800n, 5); + }); + }); + + describe('totalElapsedTime', () => { + it('Should return 0 before start time', async () => { + expect(await Chronos.totalElapsedTime()).to.equal(0); + }); + + it('Should return correct total elapsed time', async () => { + const startTime = await Chronos.START_TIME(); + await time.increaseTo('0x' + startTime.toString(16)); + await time.increase(7200); // 2 hours after start + expect(await Chronos.totalElapsedTime()).to.be.closeTo(7200n, 5); + }); + }); + + describe('isChronosActive', () => { + it('Should return false before start time', async () => { + expect(await Chronos.isChronosActive()).to.be.false; + }); + + it('Should return true after start time', async () => { + const startTime = await Chronos.START_TIME(); + await time.increaseTo('0x' + startTime.toString(16)); + expect(await Chronos.isChronosActive()).to.be.true; + }); + }); +}); From bba5dae650fb919bdb3fb85730870a5daa2476e2 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 11 Feb 2025 16:18:29 +0100 Subject: [PATCH 060/153] Fix check if voter already exists in addVoters --- contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol index 8449428a..b4bb1638 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol @@ -194,7 +194,7 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, uint16 weight = uint16(voters_[i].weight); uint256 existingIndex = votersIndexes[voterAddr]; - if (existingIndex < voters.length) { + if (existingIndex < voters.length && voters[existingIndex].addr == voterAddr) { revert("Voter already exists"); } From e299779dfe4b95afb37761506f6c2522d65dcece Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 11 Feb 2025 16:20:17 +0100 Subject: [PATCH 061/153] If voter doesn't exist, getter reverts --- contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol index b4bb1638..6e2a2994 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol @@ -275,14 +275,10 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, function getVoter( address voterAddress ) external view returns (ParanetLib.ParanetIncentivizationProposalVoter memory) { - if (voters.length == 0) { - return ParanetLib.ParanetIncentivizationProposalVoter({addr: address(0), weight: 0, claimedNeuro: 0}); - } + require(voters.length > 0, "Address is not a registered voter"); uint256 index = votersIndexes[voterAddress]; - if (index >= voters.length || voters[index].addr != voterAddress) { - return ParanetLib.ParanetIncentivizationProposalVoter({addr: address(0), weight: 0, claimedNeuro: 0}); - } + require(index >= voters.length || voters[index].addr != voterAddress, "Address is not a registered voter"); return voters[index]; } From 54eb61c95e32dcd28c5f1faaa789c725c26a9857 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 11 Feb 2025 16:21:35 +0100 Subject: [PATCH 062/153] revert if index out of bounds --- contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol index 6e2a2994..269c1cae 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol @@ -286,6 +286,7 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, function getVoterAtIndex( uint256 index ) external view returns (ParanetLib.ParanetIncentivizationProposalVoter memory) { + require(index >= voters.length, "Index is out of bounds"); return voters[index]; } @@ -311,6 +312,7 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, function getClaimedMinerRewardsAtIndex( uint256 index ) external view returns (ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile memory) { + require(index >= claimedMinerRewards.length, "Index is out of bounds"); return claimedMinerRewards[index]; } @@ -321,6 +323,7 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, function getClaimedOperatorRewardsAtIndex( uint256 index ) external view returns (ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile memory) { + require(index >= claimedOperatorRewards.length, "Index is out of bounds"); return claimedOperatorRewards[index]; } From 8f65ccdc691720267ecbe1b1d25c0414d9fc041e Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 11 Feb 2025 16:24:12 +0100 Subject: [PATCH 063/153] Fixed require condition for index out of bounds check --- contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol index 269c1cae..b73369ac 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol @@ -286,7 +286,7 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, function getVoterAtIndex( uint256 index ) external view returns (ParanetLib.ParanetIncentivizationProposalVoter memory) { - require(index >= voters.length, "Index is out of bounds"); + require(index < voters.length, "Index is out of bounds"); return voters[index]; } @@ -312,7 +312,7 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, function getClaimedMinerRewardsAtIndex( uint256 index ) external view returns (ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile memory) { - require(index >= claimedMinerRewards.length, "Index is out of bounds"); + require(index < claimedMinerRewards.length, "Index is out of bounds"); return claimedMinerRewards[index]; } @@ -323,7 +323,7 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, function getClaimedOperatorRewardsAtIndex( uint256 index ) external view returns (ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile memory) { - require(index >= claimedOperatorRewards.length, "Index is out of bounds"); + require(index < claimedOperatorRewards.length, "Index is out of bounds"); return claimedOperatorRewards[index]; } From f7ff318a04720e952cc6e6c3824e488685c1a19a Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 11 Feb 2025 16:29:26 +0100 Subject: [PATCH 064/153] Fix voter.lenght checks --- contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol index b73369ac..506be8cb 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol @@ -293,7 +293,7 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, function isProposalVoter(address addr) external view returns (bool) { if (voters.length == 0) return false; uint256 idx = votersIndexes[addr]; - return (idx <= voters.length && voters[idx].addr == addr); + return (idx < voters.length && voters[idx].addr == addr); } function addVoterClaimedNeuro(address voter, uint256 amount) external { @@ -464,7 +464,7 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, function updateVoterWeight(address voter, uint96 newWeight) external onlyVotersRegistrar { uint256 index = votersIndexes[voter]; - require(index <= voters.length && voters[index].addr == voter, "Voter not found"); + require(index < voters.length && voters[index].addr == voter, "Voter not found"); uint96 oldWeight = voters[index].weight; require( From 5acfe828ea8ac4cc4741be10dda8362387b392c4 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 11 Feb 2025 16:47:00 +0100 Subject: [PATCH 065/153] Remove redundant variables --- .../paranets/ParanetIncentivesPoolFactory.sol | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index b879098a..d781f162 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -169,17 +169,21 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn address oldPoolAddress = pr.getIncentivesPoolAddress(paranetId, incentivesPoolType); require(oldPoolAddress != address(0), "Invalid existing pool"); - // Get storage address from existing pool - ParanetNeuroIncentivesPool existingPool = ParanetNeuroIncentivesPool(oldPoolAddress); - storageAddress = address(existingPool.paranetNeuroIncentivesPoolStorage()); + ParanetNeuroIncentivesPool oldPool = ParanetNeuroIncentivesPool(oldPoolAddress); + + storageAddress = address(oldPool.paranetNeuroIncentivesPoolStorage()); require(storageAddress != address(0), "Invalid storage address"); // Verify storage contract is active ParanetNeuroIncentivesPoolStorage storage_ = ParanetNeuroIncentivesPoolStorage(payable(storageAddress)); require(storage_.paranetId() == paranetId, "Storage paranet ID mismatch"); + address tokenrAddress = address(storage_.token()); + if (isNativeReward) { + require(tokenrAddress == address(0), "Native reward pool must have no token"); + } else { + require(tokenrAddress != address(0), "ERC20 reward pool must have a token"); + } - address oldLogicContract = storage_.paranetNeuroIncentivesPoolAddress(); - ParanetNeuroIncentivesPool oldPool = ParanetNeuroIncentivesPool(oldLogicContract); uint256 tracToNeuroEmissionMultiplier = oldPool.getEffectiveNeuroEmissionMultiplier(block.timestamp); // Deploy new pool contract From 7cdd3204ca670975ab89f843181589f618f18c0f Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 11 Feb 2025 16:57:54 +0100 Subject: [PATCH 066/153] Add todo comment --- contracts/paranets/ParanetIncentivesPoolFactory.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index d781f162..dbda5923 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -65,6 +65,7 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn return _VERSION; } + // TODO: Should we allow to deploy both types of pools at once? function deployNeuroIncentivesPool( bool isNativeReward, address paranetKCStorageContract, From 81ad9203385a76f74328955bc5cfb5c1a63422ea Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 12 Feb 2025 14:26:05 +0100 Subject: [PATCH 067/153] Knowledge collection unit tests --- test/unit/KnowledgeCollection.test.ts | 329 ++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) create mode 100644 test/unit/KnowledgeCollection.test.ts diff --git a/test/unit/KnowledgeCollection.test.ts b/test/unit/KnowledgeCollection.test.ts new file mode 100644 index 00000000..9e5f713f --- /dev/null +++ b/test/unit/KnowledgeCollection.test.ts @@ -0,0 +1,329 @@ +import { randomBytes } from 'crypto'; + +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { expect } from 'chai'; +import { ethers, getBytes } from 'ethers'; +import hre from 'hardhat'; + +import { + KnowledgeCollection, + KnowledgeCollectionStorage, + EpochStorage, + AskStorage, + Chronos, + Token, + ParametersStorage, + IdentityStorage, + Hub, + Profile, + ParanetKnowledgeCollectionsRegistry, + ParanetKnowledgeMinersRegistry, + Identity, + Staking, +} from '../../typechain'; + +type KnowledgeCollectionFixture = { + accounts: SignerWithAddress[]; + KnowledgeCollection: KnowledgeCollection; + KnowledgeCollectionStorage: KnowledgeCollectionStorage; + EpochStorage: EpochStorage; + AskStorage: AskStorage; + Chronos: Chronos; + Token: Token; + ParametersStorage: ParametersStorage; + IdentityStorage: IdentityStorage; + Identity: Identity; + Profile: Profile; + ParanetsKnowledgeCollectionsRegistry: ParanetKnowledgeCollectionsRegistry; + ParanetKnowledgeMinersRegistry: ParanetKnowledgeMinersRegistry; + Staking: Staking; +}; + +describe('@unit KnowledgeCollection', () => { + let accounts: SignerWithAddress[]; + let KnowledgeCollection: KnowledgeCollection; + let KnowledgeCollectionStorage: KnowledgeCollectionStorage; + let EpochStorage: EpochStorage; + let AskStorage: AskStorage; + let Chronos: Chronos; + let Token: Token; + let ParametersStorage: ParametersStorage; + let IdentityStorage: IdentityStorage; + let Identity: Identity; + let Profile: Profile; + let ParanetsKnowledgeCollectionsRegistry: ParanetKnowledgeCollectionsRegistry; + let ParanetKnowledgeMinersRegistry: ParanetKnowledgeMinersRegistry; + let Staking: Staking; + + async function deployKnowledgeCollectionFixture(): Promise { + await hre.deployments.fixture([ + 'Token', + 'AskStorage', + 'EpochStorage', + 'KnowledgeCollection', + 'ParanetKnowledgeCollectionsRegistry', + 'ParanetKnowledgeMinersRegistry', + 'Chronos', + 'Profile', + 'Identity', + 'Staking', + ]); + + accounts = await hre.ethers.getSigners(); + const Hub = await hre.ethers.getContract('Hub'); + + KnowledgeCollection = await hre.ethers.getContract( + 'KnowledgeCollection', + ); + KnowledgeCollectionStorage = + await hre.ethers.getContract( + 'KnowledgeCollectionStorage', + ); + EpochStorage = await hre.ethers.getContract('EpochStorageV8'); + AskStorage = await hre.ethers.getContract('AskStorage'); + Chronos = await hre.ethers.getContract('Chronos'); + Token = await hre.ethers.getContract('Token'); + ParametersStorage = + await hre.ethers.getContract('ParametersStorage'); + IdentityStorage = + await hre.ethers.getContract('IdentityStorage'); + Identity = await hre.ethers.getContract('Identity'); + Profile = await hre.ethers.getContract('Profile'); + ParanetsKnowledgeCollectionsRegistry = + await hre.ethers.getContract( + 'ParanetKnowledgeCollectionsRegistry', + ); + ParanetKnowledgeMinersRegistry = + await hre.ethers.getContract( + 'ParanetKnowledgeMinersRegistry', + ); + Staking = await hre.ethers.getContract('Staking'); + + await Hub.setContractAddress('HubOwner', accounts[0].address); + + return { + accounts, + KnowledgeCollection, + KnowledgeCollectionStorage, + EpochStorage, + AskStorage, + Chronos, + Token, + ParametersStorage, + IdentityStorage, + Profile, + ParanetsKnowledgeCollectionsRegistry, + ParanetKnowledgeMinersRegistry, + Identity, + Staking, + }; + } + + const createProfile = async ( + admin: SignerWithAddress, + operational: SignerWithAddress, + ) => { + const nodeId = '0x' + randomBytes(32).toString('hex'); + const tx = await Profile.connect(operational).createProfile( + admin.address, + [], + `Node ${Math.floor(Math.random() * 1000)}`, + nodeId, + 0, + ); + const receipt = await tx.wait(); + const identityId = Number(receipt!.logs[0].topics[1]); + return { nodeId, identityId }; + }; + + async function signMessage( + signer: SignerWithAddress, + messageHash: string | Uint8Array, + ) { + // Pack the message the same way as the contract + const packedMessage = getBytes(messageHash); + + // Sign the message + const signature = await signer.signMessage(packedMessage); + + const { v, r, s } = ethers.Signature.from(signature); + + // Calculate the combined value + const vsValue = BigInt(s) | ((BigInt(v) - BigInt(27)) << BigInt(255)); + + // Convert to proper bytes32 format + const vs = ethers.zeroPadValue(ethers.toBeHex(vsValue), 32); + + return { r, vs }; + } + + const setupTestProfiles = async () => { + const { identityId: identityIdPublisher } = await createProfile( + accounts[0], + accounts[1], + ); + const { identityId: identityIdValidator1 } = await createProfile( + accounts[0], + accounts[2], + ); + const { identityId: identityIdValidator2 } = await createProfile( + accounts[0], + accounts[3], + ); + const { identityId: identityIdValidator3 } = await createProfile( + accounts[0], + accounts[4], + ); + + const merkleRoot = ethers.keccak256(ethers.toUtf8Bytes('test-merkle-root')); + const publisherMessageHash = ethers.solidityPackedKeccak256( + ['uint72', 'bytes32'], + [identityIdPublisher, merkleRoot], + ); + + // Get signatures + const { r: publisherR, vs: publisherVS } = await signMessage( + accounts[1], + publisherMessageHash, + ); + const { r: validatorR1, vs: validatorVS1 } = await signMessage( + accounts[2], + merkleRoot, + ); + const { r: validatorR2, vs: validatorVS2 } = await signMessage( + accounts[3], + merkleRoot, + ); + const { r: validatorR3, vs: validatorVS3 } = await signMessage( + accounts[4], + merkleRoot, + ); + + const validatorIds = [ + identityIdValidator1, + identityIdValidator2, + identityIdValidator3, + ]; + const validatorRs = [validatorR1, validatorR2, validatorR3]; + const validatorVSs = [validatorVS1, validatorVS2, validatorVS3]; + + return { + identityIdPublisher, + merkleRoot, + publisherR, + publisherVS, + validatorIds, + validatorRs, + validatorVSs, + }; + }; + + beforeEach(async () => { + hre.helpers.resetDeploymentsJson(); + ({ + accounts, + KnowledgeCollection, + KnowledgeCollectionStorage, + EpochStorage, + AskStorage, + Chronos, + Token, + ParametersStorage, + IdentityStorage, + Profile, + } = await loadFixture(deployKnowledgeCollectionFixture)); + }); + + it('Should create a knowledge collection successfully', async () => { + const { + identityIdPublisher, + merkleRoot, + publisherR, + publisherVS, + validatorIds, + validatorRs, + validatorVSs, + } = await setupTestProfiles(); + + // Setup test parameters + const tokenAmount = hre.ethers.parseEther('100'); + const byteSize = 1000; + const isImmutable = false; + + // Approve tokens + await Token.mint(accounts[0].address, tokenAmount); + await Token.approve(KnowledgeCollection.getAddress(), tokenAmount); + + // Create knowledge collection + const tx = await KnowledgeCollection.createKnowledgeCollection( + 'test-operation-id', // publishOperationId + merkleRoot, + 10, // knowledgeAssetsAmount + byteSize, + 2, // epochs + tokenAmount, + isImmutable, + ethers.ZeroAddress, // paymaster + identityIdPublisher, + publisherR, + publisherVS, + validatorIds, + validatorRs, + validatorVSs, + ); + + await expect(tx).to.not.be.reverted; + + const receipt = await tx.wait(); + const collectionId = Number(receipt!.logs[2].topics[1]); + + expect(collectionId).to.equal(1); + + // Verify knowledge collection was created + const metadata = + await KnowledgeCollectionStorage.getKnowledgeCollectionMetadata( + collectionId, + ); + + expect(metadata[0][0].length).to.equal(3); // merkle roots + expect(metadata[1].length).to.equal(0); // burned + expect(metadata[2]).to.equal(10); // minted + expect(metadata[3]).to.equal(byteSize); // byteSize + expect(metadata[4]).to.equal(2); // startEpoch + expect(metadata[5]).to.equal(4); // endEpoch + expect(metadata[6]).to.equal(tokenAmount); // tokenAmount + expect(metadata[7]).to.equal(isImmutable); // isImmutable + }); + + it('Should revert if insufficient signatures provided', async () => { + const { identityIdPublisher, merkleRoot, publisherR, publisherVS } = + await setupTestProfiles(); + + const tokenAmount = hre.ethers.parseEther('100'); + await Token.mint(accounts[0].address, tokenAmount); + await Token.approve(KnowledgeCollection.getAddress(), tokenAmount); + + await expect( + KnowledgeCollection.createKnowledgeCollection( + 'test-operation-id', // publishOperationId + merkleRoot, + 10, // knowledgeAssetsAmount + 1000, // byteSize + 10, // epochs + tokenAmount, + false, // isImmutable + ethers.ZeroAddress, // paymaster + identityIdPublisher, + publisherR, + publisherVS, + [], // Empty validator identityIds array + [], // Empty validator R array + [], // Empty validator VS array + ), + ).to.be.revertedWithCustomError( + KnowledgeCollection, + 'MinSignaturesRequirementNotMet', + ); + }); +}); From 7312b48b951db7b72bd508a81ad4dcd5ac3b411d Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 12 Feb 2025 14:54:19 +0100 Subject: [PATCH 068/153] Add support for multiple incentives pools --- contracts/libraries/ParanetLib.sol | 15 +- .../paranets/ParanetIncentivesPoolFactory.sol | 132 ++++++------------ .../ParanetNeuroIncentivesPoolStorage.sol | 15 -- .../storage/paranets/ParanetsRegistry.sol | 71 +++++----- 4 files changed, 88 insertions(+), 145 deletions(-) diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index 0d6bad7d..9987d925 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -61,6 +61,12 @@ library ParanetLib { RequestStatus status; } + struct IncentivesPool { + string name; + address storageAddr; + address rewardTokenAddress; + } + struct Paranet { address paranetKCStorageContract; uint256 paranetKCTokenId; @@ -71,7 +77,9 @@ library ParanetLib { MinersAccessPolicy minersAccessPolicy; KnowledgeCollectionsAccessPolicy knowledgeCollectionsAccessPolicy; uint96 cumulativeKnowledgeValue; - UnorderedNamedContractDynamicSet.Set incentivesPools; + IncentivesPool[] incentivesPools; + mapping(string => uint256) incentivesPoolsByNameIndexes; + mapping(address => uint256) incentivesPoolsByStorageAddressIndexes; Node[] curatedNodes; // Identity ID => Index in the array mapping(uint72 => uint256) curatedNodesIndexes; @@ -102,11 +110,6 @@ library ParanetLib { uint96 cumulativeKnowledgeValue; } - struct IncentivesPool { - string poolType; - address addr; - } - struct ParanetService { address paranetServiceKCStorageContract; uint256 paranetServiceKCTokenId; diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index dbda5923..bb6ae7f2 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -20,7 +20,8 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn uint256 indexed paranetKATokenId, address storageAddress, address poolAddress, - ParanetLib.IncentivesPool incentivesPool + string incentivesPoolName, + address rewardTokenAddress ); event ParanetIncentivesPoolRedeployed( address indexed paranetKCStorageContract, @@ -28,8 +29,7 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn uint256 indexed paranetKATokenId, address storageAddress, address oldPoolAddress, - address newPoolAddress, - ParanetLib.IncentivesPool incentivesPool + address newPoolAddress ); string private constant _NAME = "ParanetIncentivesPoolFactory"; @@ -65,7 +65,6 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn return _VERSION; } - // TODO: Should we allow to deploy both types of pools at once? function deployNeuroIncentivesPool( bool isNativeReward, address paranetKCStorageContract, @@ -73,7 +72,9 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn uint256 paranetKATokenId, uint256 tracToNeuroEmissionMultiplier, uint16 paranetOperatorRewardPercentage, - uint16 paranetIncentivizationProposalVotersRewardPercentage + uint16 paranetIncentivizationProposalVotersRewardPercentage, + string calldata incentivesPoolName, + address rewardTokenAddress ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) @@ -82,61 +83,34 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn Hub h = hub; ParanetsRegistry pr = paranetsRegistry; bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); - string memory incentivesPoolType = isNativeReward ? "Neuroweb" : "NeurowebERC20"; - - // Check if pool already exists - if (pr.hasIncentivesPoolByType(paranetId, incentivesPoolType)) { - // Get existing addresses - address existingPoolAddress = pr.getIncentivesPoolAddress(paranetId, incentivesPoolType); - require(existingPoolAddress != address(0), "Invalid existing pool"); - - ParanetNeuroIncentivesPool existingPool = ParanetNeuroIncentivesPool(existingPoolAddress); - storageAddress = address(existingPool.paranetNeuroIncentivesPoolStorage()); - require(storageAddress != address(0), "Invalid existing storage"); - - // Deploy new pool contract - ParanetNeuroIncentivesPool newPool = new ParanetNeuroIncentivesPool( - address(h), - h.getContractAddress("ParanetKnowledgeMinersRegistry"), - storageAddress, - tracToNeuroEmissionMultiplier - ); - - // Update registry with new pool address - pr.setIncentivesPoolAddress(paranetId, incentivesPoolType, address(newPool)); - - // Update storage with new pool address - ParanetNeuroIncentivesPoolStorage(payable(storageAddress)).setParanetNeuroIncentivesPool(address(newPool)); - - poolAddress = address(newPool); - } else { - // Deploy new storage contract - ParanetNeuroIncentivesPoolStorage storage_ = new ParanetNeuroIncentivesPoolStorage( - address(h), - isNativeReward ? address(0) : h.getContractAddress(incentivesPoolType), - paranetId, - paranetOperatorRewardPercentage, - paranetIncentivizationProposalVotersRewardPercentage - ); - - // Deploy new pool contract - ParanetNeuroIncentivesPool pool = new ParanetNeuroIncentivesPool( - address(h), - h.getContractAddress("ParanetKnowledgeMinersRegistry"), - address(storage_), - tracToNeuroEmissionMultiplier - ); - - // Initialize storage - storage_.initialize(); - storage_.setParanetNeuroIncentivesPool(address(pool)); - - // Register pool in registry - pr.setIncentivesPoolAddress(paranetId, incentivesPoolType, address(pool)); - - storageAddress = address(storage_); - poolAddress = address(pool); - } + + require(pr.paranetExists(paranetId), "Paranet doesn't exist"); + require(pr.hasIncentivesPoolByName(paranetId, incentivesPoolName), "Incentives pool already exists"); + + ParanetNeuroIncentivesPoolStorage storage_ = new ParanetNeuroIncentivesPoolStorage( + address(h), + rewardTokenAddress, + paranetId, + paranetOperatorRewardPercentage, + paranetIncentivizationProposalVotersRewardPercentage + ); + storageAddress = address(storage_); + + ParanetNeuroIncentivesPool pool = new ParanetNeuroIncentivesPool( + address(h), + h.getContractAddress("ParanetKnowledgeMinersRegistry"), + storageAddress, + tracToNeuroEmissionMultiplier + ); + poolAddress = address(pool); + + // Initialize storage contract + storage_.initialize(); + storage_.setParanetNeuroIncentivesPool(poolAddress); + pr.addIncentivesPool( + paranetId, + ParanetLib.IncentivesPool({name: incentivesPoolName, storageAddr: storageAddress}) + ); emit ParanetIncentivesPoolDeployed( paranetKCStorageContract, @@ -144,50 +118,37 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn paranetKATokenId, storageAddress, poolAddress, - ParanetLib.IncentivesPool({poolType: incentivesPoolType, addr: poolAddress}) + incentivesPoolName, + rewardTokenAddress ); return (poolAddress, storageAddress); } function redeployNeuroIncentivesPool( - bool isNativeReward, address paranetKCStorageContract, uint256 paranetKCTokenId, - uint256 paranetKATokenId + uint256 paranetKATokenId, + address storageAddress ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) - returns (address newPoolAddress, address storageAddress) + returns (address newPoolAddress) { Hub h = hub; ParanetsRegistry pr = paranetsRegistry; bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); - string memory incentivesPoolType = isNativeReward ? "Neuroweb" : "NeurowebERC20"; - // Verify existing pool and get addresses - require(pr.hasIncentivesPoolByType(paranetId, incentivesPoolType), "Pool doesn't exist"); - address oldPoolAddress = pr.getIncentivesPoolAddress(paranetId, incentivesPoolType); - require(oldPoolAddress != address(0), "Invalid existing pool"); + require(pr.paranetExists(paranetId), "Paranet doesn't exist"); + require(pr.hasIncentivesPoolByStorageAddress(paranetId, storageAddress), "Incentives pool doesn't exist"); - ParanetNeuroIncentivesPool oldPool = ParanetNeuroIncentivesPool(oldPoolAddress); - - storageAddress = address(oldPool.paranetNeuroIncentivesPoolStorage()); - require(storageAddress != address(0), "Invalid storage address"); - - // Verify storage contract is active ParanetNeuroIncentivesPoolStorage storage_ = ParanetNeuroIncentivesPoolStorage(payable(storageAddress)); require(storage_.paranetId() == paranetId, "Storage paranet ID mismatch"); - address tokenrAddress = address(storage_.token()); - if (isNativeReward) { - require(tokenrAddress == address(0), "Native reward pool must have no token"); - } else { - require(tokenrAddress != address(0), "ERC20 reward pool must have a token"); - } + address oldPoolAddress = storage_.paranetNeuroIncentivesPool(); + ParanetNeuroIncentivesPool oldPool = ParanetNeuroIncentivesPool(oldPoolAddress); uint256 tracToNeuroEmissionMultiplier = oldPool.getEffectiveNeuroEmissionMultiplier(block.timestamp); - // Deploy new pool contract ParanetNeuroIncentivesPool newPool = new ParanetNeuroIncentivesPool( address(h), h.getContractAddress("ParanetKnowledgeMinersRegistry"), @@ -196,10 +157,6 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn ); newPoolAddress = address(newPool); - // Update registry with new pool address - pr.setIncentivesPoolAddress(paranetId, incentivesPoolType, newPoolAddress); - - // Update storage to point to new pool storage_.setParanetNeuroIncentivesPool(newPoolAddress); emit ParanetIncentivesPoolRedeployed( @@ -208,8 +165,7 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn paranetKATokenId, storageAddress, oldPoolAddress, - newPoolAddress, - ParanetLib.IncentivesPool({poolType: incentivesPoolType, addr: newPoolAddress}) + newPoolAddress ); return (newPoolAddress, storageAddress); diff --git a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol index 506be8cb..042fd065 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol @@ -366,21 +366,6 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, emit RewardTransferred(rewardAddress, amount); } - function setTotalMinersClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); - totalMinersClaimedNeuro = amount; - } - - function setTotalOperatorsClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); - totalOperatorsClaimedNeuro = amount; - } - - function setTotalVotersClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); - totalVotersClaimedNeuro = amount; - } - function decrementTotalMinersClaimedNeuro(uint256 amount) external { require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); totalMinersClaimedNeuro -= amount; diff --git a/contracts/storage/paranets/ParanetsRegistry.sol b/contracts/storage/paranets/ParanetsRegistry.sol index 763db4f9..742ae010 100644 --- a/contracts/storage/paranets/ParanetsRegistry.sol +++ b/contracts/storage/paranets/ParanetsRegistry.sol @@ -6,14 +6,13 @@ import {HubDependent} from "../../abstract/HubDependent.sol"; import {INamed} from "../../interfaces/INamed.sol"; import {IVersioned} from "../../interfaces/IVersioned.sol"; import {ParanetLib} from "../../libraries/ParanetLib.sol"; -import {UnorderedNamedContractDynamicSet} from "../../libraries/UnorderedNamedContractDynamicSet.sol"; contract ParanetsRegistry is INamed, IVersioned, HubDependent { - using UnorderedNamedContractDynamicSet for UnorderedNamedContractDynamicSet.Set; - string private constant _NAME = "ParanetsRegistry"; string private constant _VERSION = "1.0.1"; + uint256 private constant _MAX_INCENTIVES_POOLS = 50; + bytes32[] private paranetIds; mapping(bytes32 => uint256) internal paranetIdsMapping; @@ -251,52 +250,52 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { identityId); } - function getIncentivesPoolAddress( - bytes32 paranetId, - string calldata incentivesPoolType - ) external view returns (address) { - return paranets[paranetId].incentivesPools.get(incentivesPoolType).addr; - } - - function setIncentivesPoolAddress( + function addIncentivesPool( bytes32 paranetId, - string calldata incentivesPoolType, - address incentivesPoolAddress + ParanetLib.IncentivesPool calldata incentivesPool ) external onlyContracts { - paranets[paranetId].incentivesPools.append(incentivesPoolType, incentivesPoolAddress); + require(paranets[paranetId].incentivesPools.length < _MAX_INCENTIVES_POOLS, "Max incentives pools reached"); + paranets[paranetId].incentivesPoolsByNameIndexes[incentivesPool.name] = paranets[paranetId] + .incentivesPools + .length; + paranets[paranetId].incentivesPoolsByStorageAddressIndexes[incentivesPool.storageAddr] = paranets[paranetId] + .incentivesPools + .length; + paranets[paranetId].incentivesPools.push(incentivesPool); } - function updateIncentivesPoolAddress( + function getIncentivesPoolByPoolName( bytes32 paranetId, - string calldata incentivesPoolType, - address incentivesPoolAddress - ) external onlyContracts { - paranets[paranetId].incentivesPools.update(incentivesPoolType, incentivesPoolAddress); - } - - function removeIncentivesPool(bytes32 paranetId, string calldata incentivesPoolType) external onlyContracts { - paranets[paranetId].incentivesPools.remove(incentivesPoolType); + string calldata name + ) external view returns (ParanetLib.IncentivesPool memory) { + return paranets[paranetId].incentivesPools[paranets[paranetId].incentivesPoolsByNameIndexes[name]]; } - function removeIncentivesPool(bytes32 paranetId, address incentivesPoolAddress) external onlyContracts { - paranets[paranetId].incentivesPools.remove(incentivesPoolAddress); + function getIncentivesPoolByStorageAddress( + bytes32 paranetId, + address storageAddr + ) external view returns (ParanetLib.IncentivesPool memory) { + return + paranets[paranetId].incentivesPools[ + paranets[paranetId].incentivesPoolsByStorageAddressIndexes[storageAddr] + ]; } - function getAllIncentivesPools( - bytes32 paranetId - ) external view returns (UnorderedNamedContractDynamicSet.Contract[] memory) { - return paranets[paranetId].incentivesPools.getAll(); + function getAllIncentivesPools(bytes32 paranetId) external view returns (ParanetLib.IncentivesPool[] memory) { + return paranets[paranetId].incentivesPools; } - function hasIncentivesPoolByType( - bytes32 paranetId, - string calldata incentivesPoolType - ) external view returns (bool) { - return paranets[paranetId].incentivesPools.exists(incentivesPoolType); + function hasIncentivesPoolByName(bytes32 paranetId, string calldata name) external view returns (bool) { + return + paranets[paranetId].incentivesPools[paranets[paranetId].incentivesPoolsByNameIndexes[name]].storageAddr != + address(0); } - function hasIncentivesPoolByAddress(bytes32 paranetId, address incentivesPoolAddress) external view returns (bool) { - return paranets[paranetId].incentivesPools.exists(incentivesPoolAddress); + function hasIncentivesPoolByStorageAddress(bytes32 paranetId, address storageAddr) external view returns (bool) { + return + paranets[paranetId] + .incentivesPools[paranets[paranetId].incentivesPoolsByStorageAddressIndexes[storageAddr]] + .storageAddr != address(0); } function getCumulativeKnowledgeValue(bytes32 paranetId) external view returns (uint96) { From 90ac32898a04fc29924a0bf00bdb114cf4c206b3 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 12 Feb 2025 16:04:16 +0100 Subject: [PATCH 069/153] Fix _checkSender in ParanetKnowledgeMinersRegistry --- .../IParanetNeuroIncentivesPool.sol | 6 ++++ contracts/libraries/ParanetLib.sol | 2 ++ .../paranets/ParanetNeuroIncentivesPool.sol | 35 +++++++++++-------- .../ParanetKnowledgeMinersRegistry.sol | 8 ++++- 4 files changed, 35 insertions(+), 16 deletions(-) create mode 100644 contracts/interfaces/IParanetNeuroIncentivesPool.sol diff --git a/contracts/interfaces/IParanetNeuroIncentivesPool.sol b/contracts/interfaces/IParanetNeuroIncentivesPool.sol new file mode 100644 index 00000000..27122440 --- /dev/null +++ b/contracts/interfaces/IParanetNeuroIncentivesPool.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +interface IParanetNeuroIncentivesPool { + function paranetNeuroIncentivesPoolStorage() external view returns (address); +} diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index 9987d925..8a6c9e38 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -78,7 +78,9 @@ library ParanetLib { KnowledgeCollectionsAccessPolicy knowledgeCollectionsAccessPolicy; uint96 cumulativeKnowledgeValue; IncentivesPool[] incentivesPools; + // Incentives Pool Name => Index in the array mapping(string => uint256) incentivesPoolsByNameIndexes; + // Incentives Pool Storage Address => Index in the array mapping(address => uint256) incentivesPoolsByStorageAddressIndexes; Node[] curatedNodes; // Identity ID => Index in the array diff --git a/contracts/paranets/ParanetNeuroIncentivesPool.sol b/contracts/paranets/ParanetNeuroIncentivesPool.sol index 2b6f92d4..3373d850 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPool.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPool.sol @@ -10,8 +10,9 @@ import {Hub} from "../storage/Hub.sol"; import {INamed} from "../interfaces/INamed.sol"; import {IVersioned} from "../interfaces/IVersioned.sol"; import {ParanetLib} from "../libraries/ParanetLib.sol"; +import {IParanetNeuroIncentivesPool} from "../interfaces/IParanetNeuroIncentivesPool.sol"; -contract ParanetNeuroIncentivesPool is INamed, IVersioned { +contract ParanetNeuroIncentivesPool is INamed, IVersioned, IParanetNeuroIncentivesPool { event NeuroEmissionMultiplierUpdateInitiated(uint256 oldMultiplier, uint256 newMultiplier, uint256 timestamp); event NeuroEmissionMultiplierUpdateFinalized(uint256 oldMultiplier, uint256 newMultiplier); @@ -506,23 +507,27 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned { ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) - totalClaimedNeuro; } - function _checkHubOwner() internal view virtual { - require(msg.sender == hub.owner(), "Fn can only be used by hub owner"); + function paranetNeuroIncentivesPoolStorage() external view returns (address) { + return address(paranetNeuroIncentivesPoolStorage); } +} - function _checkVotersRegistrar() internal view virtual { - require(msg.sender == paranetNeuroIncentivesPoolStorage.votersRegistrar(), "Fn can only be used by registrar"); - } +function _checkHubOwner() internal view virtual { + require(msg.sender == hub.owner(), "Fn can only be used by hub owner"); +} - function _checkParanetOperator() internal view virtual { - require(isParanetOperator(msg.sender), "Fn can only be used by operator"); - } +function _checkVotersRegistrar() internal view virtual { + require(msg.sender == paranetNeuroIncentivesPoolStorage.votersRegistrar(), "Fn can only be used by registrar"); +} - function _checkParanetIncentivizationProposalVoter() internal view virtual { - require(isProposalVoter(msg.sender), "Fn can only be used by voter"); - } +function _checkParanetOperator() internal view virtual { + require(isParanetOperator(msg.sender), "Fn can only be used by operator"); +} - function _checkParanetKnowledgeMiner() internal view virtual { - require(isKnowledgeMiner(msg.sender), "Fn can only be used by K-Miners"); - } +function _checkParanetIncentivizationProposalVoter() internal view virtual { + require(isProposalVoter(msg.sender), "Fn can only be used by voter"); +} + +function _checkParanetKnowledgeMiner() internal view virtual { + require(isKnowledgeMiner(msg.sender), "Fn can only be used by K-Miners"); } diff --git a/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol b/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol index afaf7398..4144cff8 100644 --- a/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol +++ b/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol @@ -3,9 +3,11 @@ pragma solidity ^0.8.20; import {ParanetsRegistry} from "./ParanetsRegistry.sol"; +import {ParanetNeuroIncentivesPoolStorage} from "../../paranets/ParanetNeuroIncentivesPoolStorage.sol"; import {HubDependent} from "../../abstract/HubDependent.sol"; import {INamed} from "../../interfaces/INamed.sol"; import {IVersioned} from "../../interfaces/IVersioned.sol"; +import {IParanetNeuroIncentivesPool} from "../../interfaces/IParanetNeuroIncentivesPool.sol"; import {ParanetLib} from "../../libraries/ParanetLib.sol"; contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { @@ -381,7 +383,11 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { function _checkSender(bytes32 paranetId) internal view virtual { require( - hub.isContract(msg.sender) || paranetsRegistry.hasIncentivesPoolByAddress(paranetId, msg.sender), + hub.isContract(msg.sender) || + paranetsRegistry.hasIncentivesPoolByStorageAddress( + paranetId, + IParanetNeuroIncentivesPool(msg.sender).paranetNeuroIncentivesPoolStorage() + ), "Hub/IncentivesPool function" ); } From 1cc6979ed48d1242794583defa11bf64fd561922 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 12 Feb 2025 16:07:01 +0100 Subject: [PATCH 070/153] Rename IParanetNeuroIncentivesPool function --- .../IParanetNeuroIncentivesPool.sol | 2 +- .../paranets/ParanetNeuroIncentivesPool.sol | 32 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/contracts/interfaces/IParanetNeuroIncentivesPool.sol b/contracts/interfaces/IParanetNeuroIncentivesPool.sol index 27122440..888acabd 100644 --- a/contracts/interfaces/IParanetNeuroIncentivesPool.sol +++ b/contracts/interfaces/IParanetNeuroIncentivesPool.sol @@ -2,5 +2,5 @@ pragma solidity ^0.8.20; interface IParanetNeuroIncentivesPool { - function paranetNeuroIncentivesPoolStorage() external view returns (address); + function getParanetNeuroIncentivesPoolStorage() external view returns (address); } diff --git a/contracts/paranets/ParanetNeuroIncentivesPool.sol b/contracts/paranets/ParanetNeuroIncentivesPool.sol index 3373d850..c2f1e4f9 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPool.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPool.sol @@ -507,27 +507,27 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned, IParanetNeuroIncentiv ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) - totalClaimedNeuro; } - function paranetNeuroIncentivesPoolStorage() external view returns (address) { + function getParanetNeuroIncentivesPoolStorage() external view returns (address) { return address(paranetNeuroIncentivesPoolStorage); } -} -function _checkHubOwner() internal view virtual { - require(msg.sender == hub.owner(), "Fn can only be used by hub owner"); -} + function _checkHubOwner() internal view virtual { + require(msg.sender == hub.owner(), "Fn can only be used by hub owner"); + } -function _checkVotersRegistrar() internal view virtual { - require(msg.sender == paranetNeuroIncentivesPoolStorage.votersRegistrar(), "Fn can only be used by registrar"); -} + function _checkVotersRegistrar() internal view virtual { + require(msg.sender == paranetNeuroIncentivesPoolStorage.votersRegistrar(), "Fn can only be used by registrar"); + } -function _checkParanetOperator() internal view virtual { - require(isParanetOperator(msg.sender), "Fn can only be used by operator"); -} + function _checkParanetOperator() internal view virtual { + require(isParanetOperator(msg.sender), "Fn can only be used by operator"); + } -function _checkParanetIncentivizationProposalVoter() internal view virtual { - require(isProposalVoter(msg.sender), "Fn can only be used by voter"); -} + function _checkParanetIncentivizationProposalVoter() internal view virtual { + require(isProposalVoter(msg.sender), "Fn can only be used by voter"); + } -function _checkParanetKnowledgeMiner() internal view virtual { - require(isKnowledgeMiner(msg.sender), "Fn can only be used by K-Miners"); + function _checkParanetKnowledgeMiner() internal view virtual { + require(isKnowledgeMiner(msg.sender), "Fn can only be used by K-Miners"); + } } From 37d3c1ea22c7993c3c6253927d7b272dd96c0d78 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 12 Feb 2025 16:21:05 +0100 Subject: [PATCH 071/153] Add amount to claimKnowledgeMinerReward function --- .../paranets/ParanetNeuroIncentivesPool.sol | 47 ++++++------------- 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/contracts/paranets/ParanetNeuroIncentivesPool.sol b/contracts/paranets/ParanetNeuroIncentivesPool.sol index c2f1e4f9..35ecb5c3 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPool.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPool.sol @@ -274,41 +274,24 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned, IParanetNeuroIncentiv : minersRewardLimit - paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro(); } - function claimKnowledgeMinerReward() external onlyParanetKnowledgeMiner { + function claimKnowledgeMinerReward(uint256 amount) external onlyParanetKnowledgeMiner { ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; uint256 neuroReward = getTotalKnowledgeMinerIncentiveEstimation(); uint256 claimableNeuroReward = getClaimableKnowledgeMinerRewardAmount(); - - // Use require here - if (claimableNeuroReward == 0) { + if (claimableNeuroReward == 0 || amount == 0 || amount > claimableNeuroReward) { revert ParanetLib.NoRewardAvailable(paranetNeuroIncentivesPoolStorage.paranetId(), msg.sender); } - // Updating the Unrewarded TRAC variable in the Knowledge Miner Profile - // If limit for reward wasn't exceeded, we set Unrewarded TRAC to 0, otherwise we need to calculate - // how many TRAC tokens were rewarded in this specific call and set variable to the amount that is left - // unrewarded - // - // Example: We have 100 NEURO total reward. 80 NEURO is for Knowledge Miners. Total NEURO Emission Rate is - // 0.5 NEURO per 1 TRAC. Knowledge Miner has 200 Unrewarded TRAC. 10% Operator Reward Percentage, - // 10% Voters Reward Percentage - // - // neuroReward = 100 NEURO = 100 * 10^12 - // claimableNeuroReward = 80 NEURO = 80 * 10^12 - // newUnrewardedTracSpent = (100 * 10^12 - 80 * 10^12) * 10^18) / (5 * 10^11) = (20 * 10^30) / (5 * 10^11) = - // = 40 * 10^18 = 40 TRAC - pkmr.setUnrewardedTracSpent( - msg.sender, - paranetNeuroIncentivesPoolStorage.paranetId(), - neuroReward == claimableNeuroReward - ? 0 - : uint96( - ((neuroReward - claimableNeuroReward) * ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) / - getEffectiveNeuroEmissionMultiplier(block.timestamp) - ) - ); - pkmr.addCumulativeAwardedNeuro(msg.sender, paranetNeuroIncentivesPoolStorage.paranetId(), claimableNeuroReward); + uint96 newUnrewardedTracSpent = amount == neuroReward + ? 0 + : uint96( + ((neuroReward - amount) * ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) / + getEffectiveNeuroEmissionMultiplier(block.timestamp) + ); + + pkmr.setUnrewardedTracSpent(msg.sender, paranetNeuroIncentivesPoolStorage.paranetId(), newUnrewardedTracSpent); + pkmr.addCumulativeAwardedNeuro(msg.sender, paranetNeuroIncentivesPoolStorage.paranetId(), amount); if ( paranetNeuroIncentivesPoolStorage.getClaimedMinerRewardsLength() == 0 || @@ -317,13 +300,13 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned, IParanetNeuroIncentiv .addr != msg.sender ) { - paranetNeuroIncentivesPoolStorage.addMinerClaimedRewardProfile(msg.sender, claimableNeuroReward); + paranetNeuroIncentivesPoolStorage.addMinerClaimedRewardProfile(msg.sender, amount); } else { - paranetNeuroIncentivesPoolStorage.addMinerClaimedReward(msg.sender, claimableNeuroReward); + paranetNeuroIncentivesPoolStorage.addMinerClaimedReward(msg.sender, amount); } - paranetNeuroIncentivesPoolStorage.addTotalMinersClaimedNeuro(claimableNeuroReward); + paranetNeuroIncentivesPoolStorage.addTotalMinersClaimedNeuro(amount); - paranetNeuroIncentivesPoolStorage.transferReward(msg.sender, claimableNeuroReward); + paranetNeuroIncentivesPoolStorage.transferReward(msg.sender, amount); } function getTotalParanetOperatorIncentiveEstimation() public view returns (uint256) { From fcf0d4b0e7ebca5f9124f1968ab868619a085896 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 12 Feb 2025 16:26:10 +0100 Subject: [PATCH 072/153] remove unused argument from deployNeuroIncentivesPool --- contracts/paranets/ParanetIncentivesPoolFactory.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index bb6ae7f2..e3a5dfae 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -66,7 +66,6 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn } function deployNeuroIncentivesPool( - bool isNativeReward, address paranetKCStorageContract, uint256 paranetKCTokenId, uint256 paranetKATokenId, From a2f8c3b764fb44ec758ac851ddc6056257638960 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 12 Feb 2025 16:29:33 +0100 Subject: [PATCH 073/153] Add not 0 address check to transferVotersRegistrarRole --- contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol index 042fd065..5243a793 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol @@ -123,6 +123,7 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, } function transferVotersRegistrarRole(address newRegistrar) external onlyVotersRegistrar { + require(newRegistrar != address(0), "New registrar cannot be zero address"); address oldRegistrar = votersRegistrar; votersRegistrar = newRegistrar; emit VotersRegistrarTransferred(oldRegistrar, newRegistrar); From 67ccaa0a325e820304c52e91ced6c74bcb7a6e81 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 12 Feb 2025 16:42:14 +0100 Subject: [PATCH 074/153] Revert changes --- .../ParanetNeuroIncentivesPoolStorage.sol | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol index 5243a793..c1f6e20f 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol @@ -367,6 +367,21 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, emit RewardTransferred(rewardAddress, amount); } + function setTotalMinersClaimedNeuro(uint256 amount) external { + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); + totalMinersClaimedNeuro = amount; + } + + function setTotalOperatorsClaimedNeuro(uint256 amount) external { + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); + totalOperatorsClaimedNeuro = amount; + } + + function setTotalVotersClaimedNeuro(uint256 amount) external { + require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); + totalVotersClaimedNeuro = amount; + } + function decrementTotalMinersClaimedNeuro(uint256 amount) external { require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); totalMinersClaimedNeuro -= amount; From 988a3995566e312c4ed7f152a45441c15fdcd677 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 12 Feb 2025 16:52:11 +0100 Subject: [PATCH 075/153] Type and function names fixes --- contracts/paranets/ParanetIncentivesPoolFactory.sol | 10 +++++++--- .../paranets/ParanetKnowledgeMinersRegistry.sol | 2 +- contracts/storage/paranets/ParanetsRegistry.sol | 11 ++++++----- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index e3a5dfae..ad528cc1 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -108,7 +108,11 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn storage_.setParanetNeuroIncentivesPool(poolAddress); pr.addIncentivesPool( paranetId, - ParanetLib.IncentivesPool({name: incentivesPoolName, storageAddr: storageAddress}) + ParanetLib.IncentivesPool({ + name: incentivesPoolName, + storageAddr: storageAddress, + rewardTokenAddress: rewardTokenAddress + }) ); emit ParanetIncentivesPoolDeployed( @@ -144,7 +148,7 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn ParanetNeuroIncentivesPoolStorage storage_ = ParanetNeuroIncentivesPoolStorage(payable(storageAddress)); require(storage_.paranetId() == paranetId, "Storage paranet ID mismatch"); - address oldPoolAddress = storage_.paranetNeuroIncentivesPool(); + address oldPoolAddress = storage_.paranetNeuroIncentivesPoolAddress(); ParanetNeuroIncentivesPool oldPool = ParanetNeuroIncentivesPool(oldPoolAddress); uint256 tracToNeuroEmissionMultiplier = oldPool.getEffectiveNeuroEmissionMultiplier(block.timestamp); @@ -167,7 +171,7 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn newPoolAddress ); - return (newPoolAddress, storageAddress); + return newPoolAddress; } function _checkKnowledgeAssetOwner( diff --git a/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol b/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol index 4144cff8..1efc8612 100644 --- a/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol +++ b/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol @@ -386,7 +386,7 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { hub.isContract(msg.sender) || paranetsRegistry.hasIncentivesPoolByStorageAddress( paranetId, - IParanetNeuroIncentivesPool(msg.sender).paranetNeuroIncentivesPoolStorage() + IParanetNeuroIncentivesPool(msg.sender).getParanetNeuroIncentivesPoolStorage() ), "Hub/IncentivesPool function" ); diff --git a/contracts/storage/paranets/ParanetsRegistry.sol b/contracts/storage/paranets/ParanetsRegistry.sol index 742ae010..e38e3305 100644 --- a/contracts/storage/paranets/ParanetsRegistry.sol +++ b/contracts/storage/paranets/ParanetsRegistry.sol @@ -266,9 +266,9 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { function getIncentivesPoolByPoolName( bytes32 paranetId, - string calldata name + string calldata poolName ) external view returns (ParanetLib.IncentivesPool memory) { - return paranets[paranetId].incentivesPools[paranets[paranetId].incentivesPoolsByNameIndexes[name]]; + return paranets[paranetId].incentivesPools[paranets[paranetId].incentivesPoolsByNameIndexes[poolName]]; } function getIncentivesPoolByStorageAddress( @@ -285,10 +285,11 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { return paranets[paranetId].incentivesPools; } - function hasIncentivesPoolByName(bytes32 paranetId, string calldata name) external view returns (bool) { + function hasIncentivesPoolByName(bytes32 paranetId, string calldata poolName) external view returns (bool) { return - paranets[paranetId].incentivesPools[paranets[paranetId].incentivesPoolsByNameIndexes[name]].storageAddr != - address(0); + paranets[paranetId] + .incentivesPools[paranets[paranetId].incentivesPoolsByNameIndexes[poolName]] + .storageAddr != address(0); } function hasIncentivesPoolByStorageAddress(bytes32 paranetId, address storageAddr) external view returns (bool) { From d250078032c8f1ab523b8cb0044bf0e3cc43d39c Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 12 Feb 2025 16:56:45 +0100 Subject: [PATCH 076/153] Fix check for kc epoch --- contracts/paranets/Paranet.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 83c659f3..9b47a91c 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -1042,7 +1042,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 currentEpoch = chronos.getCurrentEpoch(); uint40 kcStartEpoch = kcs.getStartEpoch(knowledgeCollectionTokenId); - if (kcStartEpoch != currentEpoch && kcStartEpoch != currentEpoch) { + if (kcStartEpoch == currentEpoch || kcStartEpoch - 1 == currentEpoch) { revert ParanetLib.KnowledgeCollectionNotInFirstEpoch( knowledgeCollectionStorageContract, knowledgeCollectionTokenId From aa80160aafcc8ab528f883ad42a62a01fa37ffe2 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 12 Feb 2025 17:06:46 +0100 Subject: [PATCH 077/153] Add checkERC20Compliance --- .../ParanetNeuroIncentivesPoolStorage.sol | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol index c1f6e20f..20daded9 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol @@ -80,6 +80,7 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, ); if (rewardTokenAddress != address(0)) { + require(checkERC20Compliance(rewardTokenAddress), "Invalid ERC20 contract"); token = IERC20(rewardTokenAddress); } @@ -479,6 +480,23 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, emit VoterWeightUpdated(voter, oldWeight, newWeight); } + function checkERC20Compliance(address tokenAddress) internal view returns (bool) { + bytes4[4] memory selectors = [ + IERC20.balanceOf.selector, + IERC20.totalSupply.selector, + IERC20.transfer.selector, + IERC20.allowance.selector + ]; + + for (uint i = 0; i < selectors.length; i++) { + (bool success, ) = tokenAddress.staticcall(abi.encodeWithSelector(selectors[i], address(this))); + if (!success) { + return false; // If any function is missing, reject the contract + } + } + return true; // All ERC-20 functions exist + } + modifier onlyVotersRegistrar() { require(msg.sender == votersRegistrar, "Fn can only be used by registrar"); _; From a2fa370a14a91f88605122b8f64acf972304350e Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 12 Feb 2025 17:10:37 +0100 Subject: [PATCH 078/153] rework removeVoters --- .../ParanetNeuroIncentivesPoolStorage.sol | 23 ++++--------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol index 20daded9..2836f5e0 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol @@ -217,31 +217,16 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, require(cumulativeVotersWeight <= ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT, "Cumulative weight is too big"); } - function removeVoters(uint256 limit) external onlyVotersRegistrar { - require(voters.length >= limit, "Limit exceeds number of voters"); - - for (uint256 i; i < limit; ) { - ParanetLib.ParanetIncentivizationProposalVoter memory voter = voters[voters.length - 1]; - // Decrease total weight - cumulativeVotersWeight -= uint16(voter.weight); - - // Clean up indexes - delete votersIndexes[voter.addr]; - - // Remove last element - voters.pop(); - - emit VoterRemoved(voter.addr, voter.weight); - + function removeVoters(address[] calldata votersToRemove) external onlyVotersRegistrar { + for (uint256 i; i < votersToRemove.length; ) { + removeVoter(votersToRemove[i]); unchecked { i++; } } - - emit VotersRemoved(limit); } - function removeVoter(address voterAddress) external onlyVotersRegistrar { + function removeVoter(address voterAddress) public onlyVotersRegistrar { uint256 index = votersIndexes[voterAddress]; require(index < voters.length, "Invalid voter index"); From 524fdbb56d2c179108f5251f29448aca0b1ae027 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 12 Feb 2025 18:27:41 +0100 Subject: [PATCH 079/153] Add KC helpers --- test/helpers/kc-helpers.ts | 112 +++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 test/helpers/kc-helpers.ts diff --git a/test/helpers/kc-helpers.ts b/test/helpers/kc-helpers.ts new file mode 100644 index 00000000..b01eb53b --- /dev/null +++ b/test/helpers/kc-helpers.ts @@ -0,0 +1,112 @@ +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { ethers, getBytes } from 'ethers'; + +import { KnowledgeCollection, Token } from '../../typechain'; + +export type ValidatorInfo = { + identityId: number; + r: string; + vs: string; +}; + +export type KCSignaturesData = { + merkleRoot: string; + publisherR: string; + publisherVS: string; + receiverRs: string[]; + receiverVSs: string[]; +}; + +export async function signMessage( + signer: SignerWithAddress, + messageHash: string | Uint8Array, +) { + const packedMessage = getBytes(messageHash); + const signature = await signer.signMessage(packedMessage); + const { v, r, s } = ethers.Signature.from(signature); + const vsValue = BigInt(s) | ((BigInt(v) - BigInt(27)) << BigInt(255)); + const vs = ethers.zeroPadValue(ethers.toBeHex(vsValue), 32); + return { r, vs }; +} + +export async function getKCSignaturesData( + publisher: SignerWithAddress, + publisherIdentityId: number, + receivers: SignerWithAddress[], +): Promise { + const merkleRoot = ethers.keccak256(ethers.toUtf8Bytes('test-merkle-root')); + const publisherMessageHash = ethers.solidityPackedKeccak256( + ['uint72', 'bytes32'], + [publisherIdentityId, merkleRoot], + ); + + const { r: publisherR, vs: publisherVS } = await signMessage( + publisher, + publisherMessageHash, + ); + const { r: receiverR1, vs: receiverVS1 } = await signMessage( + receivers[0], + merkleRoot, + ); + const { r: receiverR2, vs: receiverVS2 } = await signMessage( + receivers[1], + merkleRoot, + ); + const { r: receiverR3, vs: receiverVS3 } = await signMessage( + receivers[2], + merkleRoot, + ); + const receiverRs = [receiverR1, receiverR2, receiverR3]; + const receiverVSs = [receiverVS1, receiverVS2, receiverVS3]; + + return { + merkleRoot, + publisherR, + publisherVS, + receiverRs, + receiverVSs, + }; +} + +export async function createKnowledgeCollection( + KnowledgeCollection: KnowledgeCollection, + Token: Token, + owner: SignerWithAddress, + publisherIdentityId: number, + receiversIdentityIds: number[], + signaturesData: KCSignaturesData, + publishOperationId: string = 'test-operation-id', + knowledgeAssetsAmount: number = 10, + byteSize: number = 1000, + epochs: number = 2, + tokenAmount: bigint = ethers.parseEther('100'), + isImmutable: boolean = false, + paymaster: string = ethers.ZeroAddress, +) { + // Approve tokens + await Token.mint(owner.address, tokenAmount); + await Token.approve(KnowledgeCollection.getAddress(), tokenAmount); + + // Create knowledge collection + const tx = await KnowledgeCollection.createKnowledgeCollection( + publishOperationId, + signaturesData.merkleRoot, + knowledgeAssetsAmount, + byteSize, + epochs, + tokenAmount, + isImmutable, + paymaster, + publisherIdentityId, + signaturesData.publisherR, + signaturesData.publisherVS, + receiversIdentityIds, + signaturesData.receiverRs, + signaturesData.receiverVSs, + ); + + const receipt = await tx.wait(); + const collectionId = Number(receipt!.logs[2].topics[1]); + + return { tx, receipt, collectionId }; +} From 2bc7b7e89637cda810c7f7cfb52d79c2f98b4bae Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 12 Feb 2025 18:27:53 +0100 Subject: [PATCH 080/153] Add profile helpers --- test/helpers/profile-helpers.ts | 40 +++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 test/helpers/profile-helpers.ts diff --git a/test/helpers/profile-helpers.ts b/test/helpers/profile-helpers.ts new file mode 100644 index 00000000..67c5bf47 --- /dev/null +++ b/test/helpers/profile-helpers.ts @@ -0,0 +1,40 @@ +import { randomBytes } from 'crypto'; + +import { HardhatEthersSigner as SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; + +import { Profile } from '../../typechain'; + +export async function createProfile( + ProfileContract: Profile, + admin: SignerWithAddress, + operational: SignerWithAddress, +) { + const nodeId = '0x' + randomBytes(32).toString('hex'); + const tx = await ProfileContract.connect(operational).createProfile( + admin.address, + [], + `Node ${Math.floor(Math.random() * 1000)}`, + nodeId, + 0, + ); + const receipt = await tx.wait(); + const identityId = Number(receipt!.logs[0].topics[1]); + return { nodeId, identityId }; +} + +export async function createProfiles( + ProfileContract: Profile, + admin: SignerWithAddress, + accounts: SignerWithAddress[], +): Promise<{ nodeId: string; identityId: number }[]> { + const profiles: { nodeId: string; identityId: number }[] = []; + for (let i = 0; i < accounts.length; i++) { + const { nodeId, identityId } = await createProfile( + ProfileContract, + admin, + accounts[i], + ); + profiles.push({ nodeId, identityId }); + } + return profiles; +} From 0bc8082bd33e44eb9422db2b415a35ebb81d3c0f Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 12 Feb 2025 18:28:27 +0100 Subject: [PATCH 081/153] Adapt Knowledge Collection tests --- test/unit/KnowledgeCollection.test.ts | 221 +++++++------------------- 1 file changed, 59 insertions(+), 162 deletions(-) diff --git a/test/unit/KnowledgeCollection.test.ts b/test/unit/KnowledgeCollection.test.ts index 9e5f713f..b2845cea 100644 --- a/test/unit/KnowledgeCollection.test.ts +++ b/test/unit/KnowledgeCollection.test.ts @@ -1,9 +1,7 @@ -import { randomBytes } from 'crypto'; - import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { expect } from 'chai'; -import { ethers, getBytes } from 'ethers'; +import { ethers } from 'ethers'; import hre from 'hardhat'; import { @@ -22,7 +20,11 @@ import { Identity, Staking, } from '../../typechain'; - +import { + createKnowledgeCollection, + getKCSignaturesData, +} from '../helpers/kc-helpers'; +import { createProfile, createProfiles } from '../helpers/profile-helpers'; type KnowledgeCollectionFixture = { accounts: SignerWithAddress[]; KnowledgeCollection: KnowledgeCollection; @@ -120,105 +122,6 @@ describe('@unit KnowledgeCollection', () => { }; } - const createProfile = async ( - admin: SignerWithAddress, - operational: SignerWithAddress, - ) => { - const nodeId = '0x' + randomBytes(32).toString('hex'); - const tx = await Profile.connect(operational).createProfile( - admin.address, - [], - `Node ${Math.floor(Math.random() * 1000)}`, - nodeId, - 0, - ); - const receipt = await tx.wait(); - const identityId = Number(receipt!.logs[0].topics[1]); - return { nodeId, identityId }; - }; - - async function signMessage( - signer: SignerWithAddress, - messageHash: string | Uint8Array, - ) { - // Pack the message the same way as the contract - const packedMessage = getBytes(messageHash); - - // Sign the message - const signature = await signer.signMessage(packedMessage); - - const { v, r, s } = ethers.Signature.from(signature); - - // Calculate the combined value - const vsValue = BigInt(s) | ((BigInt(v) - BigInt(27)) << BigInt(255)); - - // Convert to proper bytes32 format - const vs = ethers.zeroPadValue(ethers.toBeHex(vsValue), 32); - - return { r, vs }; - } - - const setupTestProfiles = async () => { - const { identityId: identityIdPublisher } = await createProfile( - accounts[0], - accounts[1], - ); - const { identityId: identityIdValidator1 } = await createProfile( - accounts[0], - accounts[2], - ); - const { identityId: identityIdValidator2 } = await createProfile( - accounts[0], - accounts[3], - ); - const { identityId: identityIdValidator3 } = await createProfile( - accounts[0], - accounts[4], - ); - - const merkleRoot = ethers.keccak256(ethers.toUtf8Bytes('test-merkle-root')); - const publisherMessageHash = ethers.solidityPackedKeccak256( - ['uint72', 'bytes32'], - [identityIdPublisher, merkleRoot], - ); - - // Get signatures - const { r: publisherR, vs: publisherVS } = await signMessage( - accounts[1], - publisherMessageHash, - ); - const { r: validatorR1, vs: validatorVS1 } = await signMessage( - accounts[2], - merkleRoot, - ); - const { r: validatorR2, vs: validatorVS2 } = await signMessage( - accounts[3], - merkleRoot, - ); - const { r: validatorR3, vs: validatorVS3 } = await signMessage( - accounts[4], - merkleRoot, - ); - - const validatorIds = [ - identityIdValidator1, - identityIdValidator2, - identityIdValidator3, - ]; - const validatorRs = [validatorR1, validatorR2, validatorR3]; - const validatorVSs = [validatorVS1, validatorVS2, validatorVS3]; - - return { - identityIdPublisher, - merkleRoot, - publisherR, - publisherVS, - validatorIds, - validatorRs, - validatorVSs, - }; - }; - beforeEach(async () => { hre.helpers.resetDeploymentsJson(); ({ @@ -236,48 +139,36 @@ describe('@unit KnowledgeCollection', () => { }); it('Should create a knowledge collection successfully', async () => { - const { - identityIdPublisher, - merkleRoot, - publisherR, - publisherVS, - validatorIds, - validatorRs, - validatorVSs, - } = await setupTestProfiles(); + const admin = accounts[0]; + const publisher = accounts[1]; + const receivers = [accounts[2], accounts[3], accounts[4]]; - // Setup test parameters - const tokenAmount = hre.ethers.parseEther('100'); - const byteSize = 1000; - const isImmutable = false; + const { identityId: publisherIdentityId } = await createProfile( + Profile, + admin, + publisher, + ); - // Approve tokens - await Token.mint(accounts[0].address, tokenAmount); - await Token.approve(KnowledgeCollection.getAddress(), tokenAmount); + const receiversIdentityIds = ( + await createProfiles(Profile, admin, receivers) + ).map((p) => p.identityId); - // Create knowledge collection - const tx = await KnowledgeCollection.createKnowledgeCollection( - 'test-operation-id', // publishOperationId - merkleRoot, - 10, // knowledgeAssetsAmount - byteSize, - 2, // epochs - tokenAmount, - isImmutable, - ethers.ZeroAddress, // paymaster - identityIdPublisher, - publisherR, - publisherVS, - validatorIds, - validatorRs, - validatorVSs, + const signaturesData = await getKCSignaturesData( + publisher, + publisherIdentityId, + receivers, ); - await expect(tx).to.not.be.reverted; - - const receipt = await tx.wait(); - const collectionId = Number(receipt!.logs[2].topics[1]); + const { tx, collectionId } = await createKnowledgeCollection( + KnowledgeCollection, + Token, + admin, + publisherIdentityId, + receiversIdentityIds, + signaturesData, + ); + await expect(tx).to.not.be.reverted; expect(collectionId).to.equal(1); // Verify knowledge collection was created @@ -289,37 +180,43 @@ describe('@unit KnowledgeCollection', () => { expect(metadata[0][0].length).to.equal(3); // merkle roots expect(metadata[1].length).to.equal(0); // burned expect(metadata[2]).to.equal(10); // minted - expect(metadata[3]).to.equal(byteSize); // byteSize + expect(metadata[3]).to.equal(1000); // byteSize expect(metadata[4]).to.equal(2); // startEpoch expect(metadata[5]).to.equal(4); // endEpoch - expect(metadata[6]).to.equal(tokenAmount); // tokenAmount - expect(metadata[7]).to.equal(isImmutable); // isImmutable + expect(metadata[6]).to.equal(ethers.parseEther('100')); // tokenAmount + expect(metadata[7]).to.equal(false); // isImmutable }); it('Should revert if insufficient signatures provided', async () => { - const { identityIdPublisher, merkleRoot, publisherR, publisherVS } = - await setupTestProfiles(); + const admin = accounts[0]; + const publisher = accounts[1]; + const receivers = [accounts[2], accounts[3], accounts[4]]; + + const { identityId: publisherIdentityId } = await createProfile( + Profile, + admin, + publisher, + ); + + const signaturesData = await getKCSignaturesData( + publisher, + publisherIdentityId, + receivers, + ); - const tokenAmount = hre.ethers.parseEther('100'); - await Token.mint(accounts[0].address, tokenAmount); - await Token.approve(KnowledgeCollection.getAddress(), tokenAmount); + // Override receivers arrays to be empty + const receiversIdentityIds: number[] = []; + signaturesData.receiverRs = []; + signaturesData.receiverVSs = []; await expect( - KnowledgeCollection.createKnowledgeCollection( - 'test-operation-id', // publishOperationId - merkleRoot, - 10, // knowledgeAssetsAmount - 1000, // byteSize - 10, // epochs - tokenAmount, - false, // isImmutable - ethers.ZeroAddress, // paymaster - identityIdPublisher, - publisherR, - publisherVS, - [], // Empty validator identityIds array - [], // Empty validator R array - [], // Empty validator VS array + createKnowledgeCollection( + KnowledgeCollection, + Token, + admin, + publisherIdentityId, + receiversIdentityIds, + signaturesData, ), ).to.be.revertedWithCustomError( KnowledgeCollection, From a851597e8beceeaee7987a6c6b97a19b5f71e132 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Thu, 13 Feb 2025 09:46:58 +0100 Subject: [PATCH 082/153] Remove unused import --- contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol b/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol index 1efc8612..04ae39d0 100644 --- a/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol +++ b/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.20; import {ParanetsRegistry} from "./ParanetsRegistry.sol"; -import {ParanetNeuroIncentivesPoolStorage} from "../../paranets/ParanetNeuroIncentivesPoolStorage.sol"; import {HubDependent} from "../../abstract/HubDependent.sol"; import {INamed} from "../../interfaces/INamed.sol"; import {IVersioned} from "../../interfaces/IVersioned.sol"; From 88b10682d4a465e77b74f89cf548acf93d4e8d63 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 13 Feb 2025 13:54:17 +0100 Subject: [PATCH 083/153] Improve kc and profile helper functions --- test/helpers/kc-helpers.ts | 25 ++++++---- test/helpers/profile-helpers.ts | 22 +++++---- test/unit/KnowledgeCollection.test.ts | 66 ++++++++++++++++++++------- 3 files changed, 77 insertions(+), 36 deletions(-) diff --git a/test/helpers/kc-helpers.ts b/test/helpers/kc-helpers.ts index b01eb53b..83958f0f 100644 --- a/test/helpers/kc-helpers.ts +++ b/test/helpers/kc-helpers.ts @@ -1,6 +1,7 @@ import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; import { ethers, getBytes } from 'ethers'; +import { NodeAccounts } from './profile-helpers'; import { KnowledgeCollection, Token } from '../../typechain'; export type ValidatorInfo = { @@ -30,9 +31,9 @@ export async function signMessage( } export async function getKCSignaturesData( - publisher: SignerWithAddress, + publishingNode: NodeAccounts, publisherIdentityId: number, - receivers: SignerWithAddress[], + receivingNodes: NodeAccounts[], ): Promise { const merkleRoot = ethers.keccak256(ethers.toUtf8Bytes('test-merkle-root')); const publisherMessageHash = ethers.solidityPackedKeccak256( @@ -41,19 +42,19 @@ export async function getKCSignaturesData( ); const { r: publisherR, vs: publisherVS } = await signMessage( - publisher, + publishingNode.operational, publisherMessageHash, ); const { r: receiverR1, vs: receiverVS1 } = await signMessage( - receivers[0], + receivingNodes[0].operational, merkleRoot, ); const { r: receiverR2, vs: receiverVS2 } = await signMessage( - receivers[1], + receivingNodes[1].operational, merkleRoot, ); const { r: receiverR3, vs: receiverVS3 } = await signMessage( - receivers[2], + receivingNodes[2].operational, merkleRoot, ); const receiverRs = [receiverR1, receiverR2, receiverR3]; @@ -71,7 +72,7 @@ export async function getKCSignaturesData( export async function createKnowledgeCollection( KnowledgeCollection: KnowledgeCollection, Token: Token, - owner: SignerWithAddress, + kcCreator: SignerWithAddress, publisherIdentityId: number, receiversIdentityIds: number[], signaturesData: KCSignaturesData, @@ -84,11 +85,15 @@ export async function createKnowledgeCollection( paymaster: string = ethers.ZeroAddress, ) { // Approve tokens - await Token.mint(owner.address, tokenAmount); - await Token.approve(KnowledgeCollection.getAddress(), tokenAmount); + await Token.connect(kcCreator).increaseAllowance( + KnowledgeCollection.getAddress(), + tokenAmount, + ); // Create knowledge collection - const tx = await KnowledgeCollection.createKnowledgeCollection( + const tx = await KnowledgeCollection.connect( + kcCreator, + ).createKnowledgeCollection( publishOperationId, signaturesData.merkleRoot, knowledgeAssetsAmount, diff --git a/test/helpers/profile-helpers.ts b/test/helpers/profile-helpers.ts index 67c5bf47..d8c75ed2 100644 --- a/test/helpers/profile-helpers.ts +++ b/test/helpers/profile-helpers.ts @@ -4,14 +4,20 @@ import { HardhatEthersSigner as SignerWithAddress } from '@nomicfoundation/hardh import { Profile } from '../../typechain'; +export type NodeAccounts = { + admin: SignerWithAddress; + operational: SignerWithAddress; +}; + export async function createProfile( ProfileContract: Profile, - admin: SignerWithAddress, - operational: SignerWithAddress, + nodeAccounts: NodeAccounts, ) { const nodeId = '0x' + randomBytes(32).toString('hex'); - const tx = await ProfileContract.connect(operational).createProfile( - admin.address, + const tx = await ProfileContract.connect( + nodeAccounts.operational, + ).createProfile( + nodeAccounts.admin.address, [], `Node ${Math.floor(Math.random() * 1000)}`, nodeId, @@ -24,15 +30,13 @@ export async function createProfile( export async function createProfiles( ProfileContract: Profile, - admin: SignerWithAddress, - accounts: SignerWithAddress[], + nodeAccounts: NodeAccounts[], ): Promise<{ nodeId: string; identityId: number }[]> { const profiles: { nodeId: string; identityId: number }[] = []; - for (let i = 0; i < accounts.length; i++) { + for (let i = 0; i < nodeAccounts.length; i++) { const { nodeId, identityId } = await createProfile( ProfileContract, - admin, - accounts[i], + nodeAccounts[i], ); profiles.push({ nodeId, identityId }); } diff --git a/test/unit/KnowledgeCollection.test.ts b/test/unit/KnowledgeCollection.test.ts index b2845cea..5f4acfbb 100644 --- a/test/unit/KnowledgeCollection.test.ts +++ b/test/unit/KnowledgeCollection.test.ts @@ -139,30 +139,46 @@ describe('@unit KnowledgeCollection', () => { }); it('Should create a knowledge collection successfully', async () => { - const admin = accounts[0]; - const publisher = accounts[1]; - const receivers = [accounts[2], accounts[3], accounts[4]]; + const publishingNode = { + admin: accounts[1], + operational: accounts[2], + }; + const receivingNodes = [ + { + admin: accounts[3], + operational: accounts[4], + }, + { + admin: accounts[5], + operational: accounts[6], + }, + { + admin: accounts[7], + operational: accounts[8], + }, + ]; + + const kcCreator = accounts[9]; // knowledge collection creator const { identityId: publisherIdentityId } = await createProfile( Profile, - admin, - publisher, + publishingNode, ); const receiversIdentityIds = ( - await createProfiles(Profile, admin, receivers) + await createProfiles(Profile, receivingNodes) ).map((p) => p.identityId); const signaturesData = await getKCSignaturesData( - publisher, + publishingNode, publisherIdentityId, - receivers, + receivingNodes, ); const { tx, collectionId } = await createKnowledgeCollection( KnowledgeCollection, Token, - admin, + kcCreator, publisherIdentityId, receiversIdentityIds, signaturesData, @@ -188,20 +204,36 @@ describe('@unit KnowledgeCollection', () => { }); it('Should revert if insufficient signatures provided', async () => { - const admin = accounts[0]; - const publisher = accounts[1]; - const receivers = [accounts[2], accounts[3], accounts[4]]; + const publishingNode = { + admin: accounts[1], + operational: accounts[2], + }; + const receivingNodes = [ + { + admin: accounts[3], + operational: accounts[4], + }, + { + admin: accounts[5], + operational: accounts[6], + }, + { + admin: accounts[7], + operational: accounts[8], + }, + ]; + + const kcCreator = accounts[9]; // knowledge collection creator const { identityId: publisherIdentityId } = await createProfile( Profile, - admin, - publisher, + publishingNode, ); const signaturesData = await getKCSignaturesData( - publisher, + publishingNode, publisherIdentityId, - receivers, + receivingNodes, ); // Override receivers arrays to be empty @@ -213,7 +245,7 @@ describe('@unit KnowledgeCollection', () => { createKnowledgeCollection( KnowledgeCollection, Token, - admin, + kcCreator, publisherIdentityId, receiversIdentityIds, signaturesData, From 1605af292214f39c0b5fc8187ae28dc16bfd2efe Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Thu, 13 Feb 2025 14:03:05 +0100 Subject: [PATCH 084/153] Remove commit --- .../paranets/ParanetStagingStorage.sol | 148 ++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 contracts/storage/paranets/ParanetStagingStorage.sol diff --git a/contracts/storage/paranets/ParanetStagingStorage.sol b/contracts/storage/paranets/ParanetStagingStorage.sol new file mode 100644 index 00000000..3015bf7a --- /dev/null +++ b/contracts/storage/paranets/ParanetStagingStorage.sol @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.20; + +import {INamed} from "../../interfaces/INamed.sol"; +import {IVersioned} from "../../interfaces/IVersioned.sol"; +import {HubDependent} from "../../abstract/HubDependent.sol"; +import {ParanetLib} from "../../libraries/ParanetLib.sol"; + +contract ParanetStagingStorage is INamed, IVersioned, HubDependent { + string private constant _NAME = "ParanetStagingStorage"; + string private constant _VERSION = "1.0.0"; + + // Events + event KnowledgeCollectionStaged(bytes32 indexed paranetId, bytes32 indexed collectionId, address indexed submitter); + event KnowledgeCollectionReviewed(bytes32 indexed paranetId, bytes32 indexed collectionId, bool accepted); + event CuratorAdded(address indexed curator); + event CuratorRemoved(address indexed curator); + + // Paranet ID => Collection ID => Staging Status + mapping(bytes32 => mapping(bytes32 => ParanetLib.RequestStatus)) public stagedCollections; + + // Paranet ID => Collection ID => Submitter Address + mapping(bytes32 => mapping(bytes32 => address)) public collectionSubmitters; + + // Curator addresses + mapping(address => bool) public curators; + + // Add these structs and functions + struct StagedCollection { + bytes32 collectionId; + address submitter; + ParanetLib.RequestStatus status; + } + + // Track collections for pagination + mapping(bytes32 => bytes32[]) private pendingCollectionIds; + // Paranet ID => Collection ID => Index + mapping(bytes32 => mapping(bytes32 => uint256)) private pendingCollectionIndexes; + + constructor(address hubAddress) HubDependent(hubAddress) {} + + function name() external pure override returns (string memory) { + return _NAME; + } + + function version() external pure override returns (string memory) { + return _VERSION; + } + + function addCurator(address curator) external onlyContracts { + curators[curator] = true; + emit CuratorAdded(curator); + } + + function removeCurator(address curator) external onlyContracts { + curators[curator] = false; + emit CuratorRemoved(curator); + } + + function isCurator(address account) external view returns (bool) { + return curators[account]; + } + + function stageKnowledgeCollection( + bytes32 paranetId, + bytes32 collectionId, + address submitter + ) external onlyContracts { + stagedCollections[paranetId][collectionId] = ParanetLib.RequestStatus.PENDING; + collectionSubmitters[paranetId][collectionId] = submitter; + emit KnowledgeCollectionStaged(paranetId, collectionId, submitter); + _addToPendingCollections(paranetId, collectionId); + } + + function reviewKnowledgeCollection(bytes32 paranetId, bytes32 collectionId, bool accepted) external onlyContracts { + stagedCollections[paranetId][collectionId] = accepted + ? ParanetLib.RequestStatus.APPROVED + : ParanetLib.RequestStatus.REJECTED; + + emit KnowledgeCollectionReviewed(paranetId, collectionId, accepted); + _removeFromPendingCollections(paranetId, collectionId); + } + + function isKnowledgeCollectionStaged(bytes32 paranetId, bytes32 collectionId) external view returns (bool) { + return stagedCollections[paranetId][collectionId] != ParanetLib.RequestStatus.NONE; + } + + function getKnowledgeCollectionStatus( + bytes32 paranetId, + bytes32 collectionId + ) external view returns (ParanetLib.RequestStatus) { + return stagedCollections[paranetId][collectionId]; + } + + function getKnowledgeCollectionSubmitter(bytes32 paranetId, bytes32 collectionId) external view returns (address) { + return collectionSubmitters[paranetId][collectionId]; + } + + // Add this after stageKnowledgeCollection function + function _addToPendingCollections(bytes32 paranetId, bytes32 collectionId) internal { + pendingCollectionIndexes[paranetId][collectionId] = pendingCollectionIds[paranetId].length; + pendingCollectionIds[paranetId].push(collectionId); + } + + // Add this in reviewKnowledgeCollection function after status update + function _removeFromPendingCollections(bytes32 paranetId, bytes32 collectionId) internal { + uint256 index = pendingCollectionIndexes[paranetId][collectionId]; + uint256 lastIndex = pendingCollectionIds[paranetId].length - 1; + + if (index != lastIndex) { + bytes32 lastCollectionId = pendingCollectionIds[paranetId][lastIndex]; + pendingCollectionIds[paranetId][index] = lastCollectionId; + pendingCollectionIndexes[paranetId][lastCollectionId] = index; + } + + pendingCollectionIds[paranetId].pop(); + delete pendingCollectionIndexes[paranetId][collectionId]; + } + + function getPendingCollections( + bytes32 paranetId, + uint256 offset, + uint256 limit + ) external view returns (StagedCollection[] memory collections, uint256 total) { + total = pendingCollectionIds[paranetId].length; + + if (offset >= total || limit == 0) { + return (new StagedCollection[](0), total); + } + + uint256 end = offset + limit; + if (end > total) { + end = total; + } + uint256 resultLength = end - offset; + + collections = new StagedCollection[](resultLength); + for (uint256 i = 0; i < resultLength; i++) { + bytes32 collectionId = pendingCollectionIds[paranetId][offset + i]; + collections[i] = StagedCollection({ + collectionId: collectionId, + submitter: collectionSubmitters[paranetId][collectionId], + status: stagedCollections[paranetId][collectionId] + }); + } + } +} From dced0fca04ce2810d1b42dc6f16199adc20e717d Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Thu, 13 Feb 2025 15:06:17 +0100 Subject: [PATCH 085/153] Add KnowledgeCollectionStaged --- contracts/libraries/ParanetLib.sol | 3 +- contracts/paranets/Paranet.sol | 167 ++++++++++++++++++ .../paranets/ParanetStagingStorage.sol | 115 +++++++----- 3 files changed, 237 insertions(+), 48 deletions(-) diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index 8a6c9e38..8be4136d 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -32,7 +32,8 @@ library ParanetLib { } enum KnowledgeCollectionsAccessPolicy { - OPEN + OPEN, + STAGING } struct Node { diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 7497e1f4..a2c4306a 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -6,6 +6,7 @@ import {ParanetKnowledgeCollectionsRegistry} from "../storage/paranets/ParanetKn import {ParanetKnowledgeMinersRegistry} from "../storage/paranets/ParanetKnowledgeMinersRegistry.sol"; import {ParanetsRegistry} from "../storage/paranets/ParanetsRegistry.sol"; import {ParanetServicesRegistry} from "../storage/paranets/ParanetServicesRegistry.sol"; +import {ParanetStagingStorage} from "../storage/paranets/ParanetStagingStorage.sol"; import {ProfileStorage} from "../storage/ProfileStorage.sol"; import {IdentityStorage} from "../storage/IdentityStorage.sol"; import {KnowledgeCollectionStorage} from "../storage/KnowledgeCollectionStorage.sol"; @@ -140,6 +141,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ParanetServicesRegistry public paranetServicesRegistry; ParanetKnowledgeMinersRegistry public paranetKnowledgeMinersRegistry; ParanetKnowledgeCollectionsRegistry public paranetKnowledgeCollectionsRegistry; + ParanetStagingStorage public paranetStagingStorage; ProfileStorage public profileStorage; IdentityStorage public identityStorage; @@ -167,6 +169,15 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { _; } + modifier onlyCurator( + address paranetKCStorageContract, + uint256 paranetKnowledgeCollectionTokenId, + uint256 paranetKnowledgeAssetTokenId + ) { + _checkCurator(paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId); + _; + } + function initialize() public onlyHub { profileStorage = ProfileStorage(hub.getContractAddress("ProfileStorage")); identityStorage = IdentityStorage(hub.getContractAddress("IdentityStorage")); @@ -178,6 +189,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { paranetKnowledgeCollectionsRegistry = ParanetKnowledgeCollectionsRegistry( hub.getContractAddress("ParanetKnowledgeCollectionsRegistry") ); + paranetStagingStorage = ParanetStagingStorage(hub.getContractAddress("ParanetStagingStorage")); } function name() external pure virtual override returns (string memory) { @@ -1072,6 +1084,16 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); } + if (pr.getKnowledgeCollectionsAccessPolicy(paranetId) == ParanetLib.KnowledgeCollectionsAccessPolicy.STAGING) { + require( + paranetStagingStorage.isKnowledgeCollectionApproved( + paranetId, + keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)) + ), + "Knowledge collection is not approved" + ); + } + KnowledgeCollectionStorage kcs = KnowledgeCollectionStorage(knowledgeCollectionStorageContract); uint96 remainingTokenAmount = kcs.getTokenAmount(knowledgeCollectionTokenId); KnowledgeCollectionLib.MerkleRoot[] memory merkleRoots = kcs.getMerkleRoots(knowledgeCollectionTokenId); @@ -1096,6 +1118,131 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); } + function stageKnowledgeCollection( + address paranetKCStorageContract, + uint256 paranetKnowledgeCollectionTokenId, + uint256 paranetKnowledgeAssetTokenId, + address knowledgeCollectionStorageContract, + uint256 knowledgeCollectionTokenId + ) external onlyKnowledgeCollectionOwner(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) { + ParanetsRegistry pr = paranetsRegistry; + bytes32 paranetId = keccak256( + abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId) + ); + + if (!pr.paranetExists(paranetId)) { + revert ParanetLib.ParanetDoesntExist( + paranetKCStorageContract, + paranetKnowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId + ); + } + + if (pr.getMinersAccessPolicy(paranetId) == ParanetLib.MinersAccessPolicy.CURATED) { + require(pr.isKnowledgeMinerRegistered(paranetId, msg.sender), "Knowledge miner is not registered"); + } + + ParanetLib.KnowledgeCollectionsAccessPolicy knowledgeCollectionsAccessPolicy = pr + .getKnowledgeCollectionsAccessPolicy(paranetId); + + require( + knowledgeCollectionsAccessPolicy == ParanetLib.KnowledgeCollectionsAccessPolicy.STAGING, + "Paranet does not allow staging of knowledge collections" + ); + + bytes32 knowledgeCollectionId = keccak256( + abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) + ); + ParanetStagingStorage pss = paranetStagingStorage; + require( + !pss.isKnowledgeCollectionStaged(paranetId, knowledgeCollectionId), + "Knowledge collection is already staged" + ); + pss.stageKnowledgeCollection(paranetId, knowledgeCollectionId, msg.sender); + } + + function addCurator( + address paranetKCStorageContract, + uint256 paranetKnowledgeCollectionTokenId, + uint256 paranetKnowledgeAssetTokenId, + address curator + ) + external + onlyKnowledgeAssetOwner( + paranetKCStorageContract, + paranetKnowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId + ) + { + bytes32 paranetId = keccak256( + abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId) + ); + ParanetsRegistry pr = paranetsRegistry; + if (!pr.paranetExists(paranetId)) { + revert ParanetLib.ParanetDoesntExist( + paranetKCStorageContract, + paranetKnowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId + ); + } + + ParanetLib.MinersAccessPolicy minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); + require(minersAccessPolicy == ParanetLib.MinersAccessPolicy.CURATED, "Paranet does not allow adding curators"); + paranetStagingStorage.addCurator(paranetId, curator); + } + + function removeCurator( + address paranetKCStorageContract, + uint256 paranetKnowledgeCollectionTokenId, + uint256 paranetKnowledgeAssetTokenId, + address curator + ) + external + onlyKnowledgeAssetOwner( + paranetKCStorageContract, + paranetKnowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId + ) + { + bytes32 paranetId = keccak256( + abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId) + ); + ParanetsRegistry pr = paranetsRegistry; + if (!pr.paranetExists(paranetId)) { + revert ParanetLib.ParanetDoesntExist( + paranetKCStorageContract, + paranetKnowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId + ); + } + + ParanetLib.MinersAccessPolicy minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); + require(minersAccessPolicy == ParanetLib.MinersAccessPolicy.CURATED, "Paranet does not allow adding curators"); + paranetStagingStorage.removeCurator(paranetId, curator); + } + + function reviewKnowledgeCollection( + address paranetKCStorageContract, + uint256 paranetKnowledgeCollectionTokenId, + uint256 paranetKnowledgeAssetTokenId, + address knowledgeCollectionStorageContract, + uint256 knowledgeCollectionTokenId, + bool accepted + ) external onlyCurator(paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId) { + bytes32 paranetId = keccak256( + abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId) + ); + bytes32 knowledgeCollectionId = keccak256( + abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) + ); + ParanetStagingStorage pss = paranetStagingStorage; + require( + pss.isKnowledgeCollectionStaged(paranetId, knowledgeCollectionId), + "Knowledge collection is not staged" + ); + pss.reviewKnowledgeCollection(paranetId, knowledgeCollectionId, accepted); + } + // function processUpdatedKnowledgeCollectionStatesMetadata( // address paranetKCStorageContract, // uint256 paranetKCTokenId, @@ -1294,4 +1441,24 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { require(ownedCountInRange == activeCount, "Caller isn't the owner of the KC"); } + + function _checkCurator( + address paranetKCStorageContract, + uint256 paranetKnowledgeCollectionTokenId, + uint256 paranetKnowledgeAssetTokenId + ) internal view { + require( + paranetStagingStorage.isCurator( + keccak256( + abi.encodePacked( + paranetKCStorageContract, + paranetKnowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId + ) + ), + msg.sender + ), + "Not authorized curator" + ); + } } diff --git a/contracts/storage/paranets/ParanetStagingStorage.sol b/contracts/storage/paranets/ParanetStagingStorage.sol index 3015bf7a..48e7d8b0 100644 --- a/contracts/storage/paranets/ParanetStagingStorage.sol +++ b/contracts/storage/paranets/ParanetStagingStorage.sol @@ -12,10 +12,14 @@ contract ParanetStagingStorage is INamed, IVersioned, HubDependent { string private constant _VERSION = "1.0.0"; // Events - event KnowledgeCollectionStaged(bytes32 indexed paranetId, bytes32 indexed collectionId, address indexed submitter); - event KnowledgeCollectionReviewed(bytes32 indexed paranetId, bytes32 indexed collectionId, bool accepted); - event CuratorAdded(address indexed curator); - event CuratorRemoved(address indexed curator); + event KnowledgeCollectionStaged( + bytes32 indexed paranetId, + bytes32 indexed knowledgeCollectionId, + address indexed submitter + ); + event KnowledgeCollectionReviewed(bytes32 indexed paranetId, bytes32 indexed knowledgeCollectionId, bool accepted); + event CuratorAdded(bytes32 indexed paranetId, address indexed curator); + event CuratorRemoved(bytes32 indexed paranetId, address indexed curator); // Paranet ID => Collection ID => Staging Status mapping(bytes32 => mapping(bytes32 => ParanetLib.RequestStatus)) public stagedCollections; @@ -23,18 +27,18 @@ contract ParanetStagingStorage is INamed, IVersioned, HubDependent { // Paranet ID => Collection ID => Submitter Address mapping(bytes32 => mapping(bytes32 => address)) public collectionSubmitters; - // Curator addresses - mapping(address => bool) public curators; + // Paranet ID => Curator Address => Is Curator + mapping(bytes32 => mapping(address => bool)) public curators; // Add these structs and functions struct StagedCollection { - bytes32 collectionId; + bytes32 knowledgeCollectionId; address submitter; ParanetLib.RequestStatus status; } // Track collections for pagination - mapping(bytes32 => bytes32[]) private pendingCollectionIds; + mapping(bytes32 => bytes32[]) private pendingknowledgeCollectionIds; // Paranet ID => Collection ID => Index mapping(bytes32 => mapping(bytes32 => uint256)) private pendingCollectionIndexes; @@ -48,74 +52,91 @@ contract ParanetStagingStorage is INamed, IVersioned, HubDependent { return _VERSION; } - function addCurator(address curator) external onlyContracts { - curators[curator] = true; - emit CuratorAdded(curator); + function addCurator(bytes32 paranetId, address curator) external onlyContracts { + curators[paranetId][curator] = true; + emit CuratorAdded(paranetId, curator); } - function removeCurator(address curator) external onlyContracts { - curators[curator] = false; - emit CuratorRemoved(curator); + function removeCurator(bytes32 paranetId, address curator) external onlyContracts { + curators[paranetId][curator] = false; + emit CuratorRemoved(paranetId, curator); } - function isCurator(address account) external view returns (bool) { - return curators[account]; + function isCurator(bytes32 paranetId, address account) external view returns (bool) { + return curators[paranetId][account]; } function stageKnowledgeCollection( bytes32 paranetId, - bytes32 collectionId, + bytes32 knowledgeCollectionId, address submitter ) external onlyContracts { - stagedCollections[paranetId][collectionId] = ParanetLib.RequestStatus.PENDING; - collectionSubmitters[paranetId][collectionId] = submitter; - emit KnowledgeCollectionStaged(paranetId, collectionId, submitter); - _addToPendingCollections(paranetId, collectionId); + stagedCollections[paranetId][knowledgeCollectionId] = ParanetLib.RequestStatus.PENDING; + collectionSubmitters[paranetId][knowledgeCollectionId] = submitter; + emit KnowledgeCollectionStaged(paranetId, knowledgeCollectionId, submitter); + _addToPendingCollections(paranetId, knowledgeCollectionId); } - function reviewKnowledgeCollection(bytes32 paranetId, bytes32 collectionId, bool accepted) external onlyContracts { - stagedCollections[paranetId][collectionId] = accepted + function reviewKnowledgeCollection( + bytes32 paranetId, + bytes32 knowledgeCollectionId, + bool accepted + ) external onlyContracts { + stagedCollections[paranetId][knowledgeCollectionId] = accepted ? ParanetLib.RequestStatus.APPROVED : ParanetLib.RequestStatus.REJECTED; - emit KnowledgeCollectionReviewed(paranetId, collectionId, accepted); - _removeFromPendingCollections(paranetId, collectionId); + emit KnowledgeCollectionReviewed(paranetId, knowledgeCollectionId, accepted); + _removeFromPendingCollections(paranetId, knowledgeCollectionId); } - function isKnowledgeCollectionStaged(bytes32 paranetId, bytes32 collectionId) external view returns (bool) { - return stagedCollections[paranetId][collectionId] != ParanetLib.RequestStatus.NONE; + function isKnowledgeCollectionStaged( + bytes32 paranetId, + bytes32 knowledgeCollectionId + ) external view returns (bool) { + return stagedCollections[paranetId][knowledgeCollectionId] != ParanetLib.RequestStatus.NONE; + } + + function isKnowledgeCollectionApproved( + bytes32 paranetId, + bytes32 knowledgeCollectionId + ) external view returns (bool) { + return stagedCollections[paranetId][knowledgeCollectionId] == ParanetLib.RequestStatus.APPROVED; } function getKnowledgeCollectionStatus( bytes32 paranetId, - bytes32 collectionId + bytes32 knowledgeCollectionId ) external view returns (ParanetLib.RequestStatus) { - return stagedCollections[paranetId][collectionId]; + return stagedCollections[paranetId][knowledgeCollectionId]; } - function getKnowledgeCollectionSubmitter(bytes32 paranetId, bytes32 collectionId) external view returns (address) { - return collectionSubmitters[paranetId][collectionId]; + function getKnowledgeCollectionSubmitter( + bytes32 paranetId, + bytes32 knowledgeCollectionId + ) external view returns (address) { + return collectionSubmitters[paranetId][knowledgeCollectionId]; } // Add this after stageKnowledgeCollection function - function _addToPendingCollections(bytes32 paranetId, bytes32 collectionId) internal { - pendingCollectionIndexes[paranetId][collectionId] = pendingCollectionIds[paranetId].length; - pendingCollectionIds[paranetId].push(collectionId); + function _addToPendingCollections(bytes32 paranetId, bytes32 knowledgeCollectionId) internal { + pendingCollectionIndexes[paranetId][knowledgeCollectionId] = pendingknowledgeCollectionIds[paranetId].length; + pendingknowledgeCollectionIds[paranetId].push(knowledgeCollectionId); } // Add this in reviewKnowledgeCollection function after status update - function _removeFromPendingCollections(bytes32 paranetId, bytes32 collectionId) internal { - uint256 index = pendingCollectionIndexes[paranetId][collectionId]; - uint256 lastIndex = pendingCollectionIds[paranetId].length - 1; + function _removeFromPendingCollections(bytes32 paranetId, bytes32 knowledgeCollectionId) internal { + uint256 index = pendingCollectionIndexes[paranetId][knowledgeCollectionId]; + uint256 lastIndex = pendingknowledgeCollectionIds[paranetId].length - 1; if (index != lastIndex) { - bytes32 lastCollectionId = pendingCollectionIds[paranetId][lastIndex]; - pendingCollectionIds[paranetId][index] = lastCollectionId; - pendingCollectionIndexes[paranetId][lastCollectionId] = index; + bytes32 lastknowledgeCollectionId = pendingknowledgeCollectionIds[paranetId][lastIndex]; + pendingknowledgeCollectionIds[paranetId][index] = lastknowledgeCollectionId; + pendingCollectionIndexes[paranetId][lastknowledgeCollectionId] = index; } - pendingCollectionIds[paranetId].pop(); - delete pendingCollectionIndexes[paranetId][collectionId]; + pendingknowledgeCollectionIds[paranetId].pop(); + delete pendingCollectionIndexes[paranetId][knowledgeCollectionId]; } function getPendingCollections( @@ -123,7 +144,7 @@ contract ParanetStagingStorage is INamed, IVersioned, HubDependent { uint256 offset, uint256 limit ) external view returns (StagedCollection[] memory collections, uint256 total) { - total = pendingCollectionIds[paranetId].length; + total = pendingknowledgeCollectionIds[paranetId].length; if (offset >= total || limit == 0) { return (new StagedCollection[](0), total); @@ -137,11 +158,11 @@ contract ParanetStagingStorage is INamed, IVersioned, HubDependent { collections = new StagedCollection[](resultLength); for (uint256 i = 0; i < resultLength; i++) { - bytes32 collectionId = pendingCollectionIds[paranetId][offset + i]; + bytes32 knowledgeCollectionId = pendingknowledgeCollectionIds[paranetId][offset + i]; collections[i] = StagedCollection({ - collectionId: collectionId, - submitter: collectionSubmitters[paranetId][collectionId], - status: stagedCollections[paranetId][collectionId] + knowledgeCollectionId: knowledgeCollectionId, + submitter: collectionSubmitters[paranetId][knowledgeCollectionId], + status: stagedCollections[paranetId][knowledgeCollectionId] }); } } From 1fef82fb267b1e16262f4e71c159342df49783cb Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 13 Feb 2025 15:09:13 +0100 Subject: [PATCH 086/153] Create paranet integration tests --- test/integration/OldParanet.test.ts | 494 +++++++++++++++++ test/integration/Paranet.test.ts | 819 +++++++++++----------------- 2 files changed, 819 insertions(+), 494 deletions(-) create mode 100644 test/integration/OldParanet.test.ts diff --git a/test/integration/OldParanet.test.ts b/test/integration/OldParanet.test.ts new file mode 100644 index 00000000..4127bb49 --- /dev/null +++ b/test/integration/OldParanet.test.ts @@ -0,0 +1,494 @@ +// import { randomBytes } from 'crypto'; + +// import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +// import { expect } from 'chai'; +// import { BigNumberish, BytesLike } from 'ethers'; +// import hre from 'hardhat'; +// import { SignerWithAddress } from 'hardhat-deploy-ethers/signers'; +// import { Address } from 'hardhat-deploy/types'; + +// import { +// Paranet, +// ParanetsRegistry, +// ParanetKnowledgeMinersRegistry, +// HubController, +// ContentAssetV2, +// ServiceAgreementV1, +// ContentAssetStorageV2, +// Token, +// ParanetIncentivesPoolFactory, +// } from '../../typechain'; +// import { ContentAssetStructs } from '../../../typechain/contracts/v2/assets/ContentAsset.sol/ContentAssetV2'; + +// type ParanetNeuroIncentivesPoolFixture = { +// accounts: SignerWithAddress[]; +// ContentAsset: ContentAssetV2; +// ContentAssetStorage: ContentAssetStorageV2; +// ServiceAgreementV1: ServiceAgreementV1; +// Token: Token; +// ParanetKnowledgeMinersRegistry: ParanetKnowledgeMinersRegistry; +// ParanetsRegistry: ParanetsRegistry; +// Paranet: Paranet; +// ParanetIncentivesPoolFactory: ParanetIncentivesPoolFactory; +// }; + +// describe('@v2 @integration Paranet', function () { +// let accounts: SignerWithAddress[]; +// let operator: SignerWithAddress; +// let miner: SignerWithAddress; +// let HubController: HubController; +// let ContentAsset: ContentAssetV2; +// let ServiceAgreementV1: ServiceAgreementV1; +// let ContentAssetStorage: ContentAssetStorageV2; +// let Token: Token; +// let ParanetKnowledgeMinersRegistry: ParanetKnowledgeMinersRegistry; +// let ParanetsRegistry: ParanetsRegistry; +// let Paranet: Paranet; +// let ParanetIncentivesPoolFactory: ParanetIncentivesPoolFactory; + +// async function deployParanetNeuroIncentivesPoolFixture(): Promise { +// await hre.deployments.fixture([ +// 'Token', +// 'ServiceAgreementV1', +// 'ContentAssetStorageV2', +// 'ContentAssetV2', +// 'Paranet', +// 'ParanetIncentivesPoolFactory', +// ]); + +// ContentAssetStorage = await hre.ethers.getContract('ContentAssetStorage'); +// ContentAsset = await hre.ethers.getContract('ContentAsset'); +// ServiceAgreementV1 = await hre.ethers.getContract('ServiceAgreementV1'); +// Token = await hre.ethers.getContract('Token'); + +// ParanetKnowledgeMinersRegistry = await hre.ethers.getContract( +// 'ParanetKnowledgeMinersRegistry', +// ); +// ParanetsRegistry = await hre.ethers.getContract('ParanetsRegistry'); +// Paranet = await hre.ethers.getContract('Paranet'); +// ParanetIncentivesPoolFactory = await hre.ethers.getContract( +// 'ParanetIncentivesPoolFactory', +// ); + +// accounts = await hre.ethers.getSigners(); + +// HubController = await hre.ethers.getContract('HubController'); +// await HubController.setContractAddress('HubOwner', accounts[0].address); + +// return { +// accounts, +// ContentAssetStorage, +// ContentAsset, +// ServiceAgreementV1, +// Token, +// ParanetKnowledgeMinersRegistry, +// ParanetsRegistry, +// Paranet, +// ParanetIncentivesPoolFactory, +// }; +// } + +// async function createAsset( +// assetInputStruct: ContentAssetStructs.AssetInputArgsStruct, +// ): Promise<{ tokenId: number; keyword: BytesLike; agreementId: BytesLike }> { +// await Token.connect(operator).increaseAllowance(ServiceAgreementV1.address, assetInputStruct.tokenAmount); +// const receipt = await (await ContentAsset.connect(operator).createAsset(assetInputStruct)).wait(); +// const tokenId = Number(receipt.logs[0].topics[3]); + +// const keyword = hre.ethers.utils.solidityPack( +// ['address', 'bytes32'], +// [ContentAssetStorage.address, assetInputStruct.assertionId], +// ); +// const agreementId = hre.ethers.utils.soliditySha256( +// ['address', 'uint256', 'bytes'], +// [ContentAssetStorage.address, tokenId, keyword], +// ); +// return { tokenId, keyword, agreementId }; +// } + +// async function registerParanet( +// paranetKATokenId: BigNumberish, +// paranetName: string, +// paranetDescription: string, +// tracToNeuroEmissionMultiplier: BigNumberish, +// paranetOperatorRewardPercentage: BigNumberish, +// paranetIncentivizationProposalVotersRewardPercentage: BigNumberish, +// ): Promise<{ paranetId: BytesLike; ParanetNeuroIncentivesPoolAddress: Address }> { +// const tx1 = await Paranet.connect(operator).registerParanet( +// ContentAssetStorage.address, +// paranetKATokenId, +// paranetName, +// paranetDescription, +// 0, +// 0, +// ); +// await tx1.wait(); + +// const tx2 = await ParanetIncentivesPoolFactory.connect(operator).deployNeuroIncentivesPool( +// ContentAssetStorage.address, +// paranetKATokenId, +// tracToNeuroEmissionMultiplier, +// paranetOperatorRewardPercentage, +// paranetIncentivizationProposalVotersRewardPercentage, +// ); +// await tx2.wait(); + +// const paranetId = hre.ethers.utils.keccak256( +// hre.ethers.utils.solidityPack(['address', 'uint256'], [ContentAssetStorage.address, paranetKATokenId]), +// ); +// const ParanetNeuroIncentivesPoolAddress = await ParanetsRegistry.getIncentivesPoolAddress(paranetId, 'Neuroweb'); + +// return { +// paranetId, +// ParanetNeuroIncentivesPoolAddress, +// }; +// } + +// beforeEach(async function () { +// hre.helpers.resetDeploymentsJson(); +// ({ +// accounts, +// ContentAssetStorage, +// ContentAsset, +// ServiceAgreementV1, +// Token, +// ParanetKnowledgeMinersRegistry, +// ParanetsRegistry, +// Paranet, +// ParanetIncentivesPoolFactory, +// } = await loadFixture(deployParanetNeuroIncentivesPoolFixture)); + +// operator = accounts[1]; +// miner = accounts[2]; +// }); + +// it('Should accept native tokens, update balance and variable successfully', async function () { +// const paranetKAStruct: ContentAssetStructs.AssetInputArgsStruct = { +// assertionId: '0x' + randomBytes(32).toString('hex'), +// size: 1000, +// triplesNumber: 10, +// chunksNumber: 10, +// epochsNumber: 5, +// tokenAmount: hre.ethers.utils.parseEther('250'), +// scoreFunctionId: 2, +// immutable_: false, +// }; +// const { tokenId: paranetTokenId } = await createAsset(paranetKAStruct); + +// const { ParanetNeuroIncentivesPoolAddress } = await registerParanet( +// paranetTokenId, +// 'Paranet1', +// 'Test Paranet', +// hre.ethers.utils.parseEther('1'), // tracToNeuroRatio -- 1:1 +// 1000, // paranetOperatorRewardPercentage -- 10% +// 500, // paranetIncentivizationProposalVotersRewardPercentage -- 5% +// ); + +// const ParanetNeuroIncentivesPool = await hre.ethers.getContractAt( +// 'ParanetNeuroIncentivesPool', +// ParanetNeuroIncentivesPoolAddress, +// ); + +// const initialBalance = await ParanetNeuroIncentivesPool.getNeuroBalance(); + +// expect(initialBalance).to.be.equal(0); + +// const value = hre.ethers.utils.parseEther('100'); +// const tx = await operator.sendTransaction({ +// to: ParanetNeuroIncentivesPool.address, +// value, +// }); +// await tx.wait(); + +// const finalBalance = await ParanetNeuroIncentivesPool.getNeuroBalance(); +// const totalNeuroReceived = await ParanetNeuroIncentivesPool.totalNeuroReceived(); + +// expect(finalBalance).to.be.equal(totalNeuroReceived).to.be.equal(value); +// }); + +// // it('Should revert while getting operator reward before miner', async function () { +// // const paranetKAStruct: ContentAssetStructs.AssetInputArgsStruct = { +// // assertionId: '0x' + randomBytes(32).toString('hex'), +// // size: 1000, +// // triplesNumber: 10, +// // chunksNumber: 10, +// // epochsNumber: 5, +// // tokenAmount: hre.ethers.utils.parseEther('250'), +// // scoreFunctionId: 2, +// // immutable_: false, +// // }; +// // const { tokenId: paranetTokenId } = await createAsset(paranetKAStruct); + +// // const { ParanetNeuroIncentivesPoolAddress } = await registerParanet( +// // paranetTokenId, +// // 'Paranet1', +// // 'Test Paranet', +// // hre.ethers.utils.parseEther('1'), // tracToNeuroRatio - 1:1 +// // 1000, // operatorRewardPercentage -- 10% +// // 500, // paranetIncentivizationProposalVotersRewardPercentage -- 5% +// // ); + +// // const ParanetNeuroIncentivesPool = await hre.ethers.getContractAt( +// // 'ParanetNeuroIncentivesPool', +// // ParanetNeuroIncentivesPoolAddress, +// // ); + +// // const value = hre.ethers.utils.parseEther('1000'); +// // const tx = await operator.sendTransaction({ +// // to: ParanetNeuroIncentivesPool.address, +// // value, +// // }); +// // await tx.wait(); + +// // await expect( +// // ParanetNeuroIncentivesPool.connect(operator).claimParanetOperatorReward(), +// // ).to.be.revertedWithCustomError(ParanetNeuroIncentivesPool, 'NoRewardAvailable'); +// // }); + +// it('Should correctly calculate miner reward', async function () { +// const paranetKAStruct: ContentAssetStructs.AssetInputArgsStruct = { +// assertionId: '0x' + randomBytes(32).toString('hex'), +// size: 1000, +// triplesNumber: 10, +// chunksNumber: 10, +// epochsNumber: 5, +// tokenAmount: hre.ethers.utils.parseEther('250'), +// scoreFunctionId: 2, +// immutable_: false, +// }; +// const { tokenId: paranetTokenId } = await createAsset(paranetKAStruct); + +// const { ParanetNeuroIncentivesPoolAddress } = await registerParanet( +// paranetTokenId, +// 'Paranet1', +// 'Test Paranet', +// hre.ethers.utils.parseEther('1'), // tracToNeuroRatio -- 1:1 +// 1000, // operatorRewardPercentage -- 10% +// 500, // paranetIncentivizationProposalVotersRewardPercentage -- 5% +// ); + +// const ParanetNeuroIncentivesPool = await hre.ethers.getContractAt( +// 'ParanetNeuroIncentivesPool', +// ParanetNeuroIncentivesPoolAddress, +// ); + +// const value = hre.ethers.utils.parseEther('5000'); +// const tx1 = await operator.sendTransaction({ +// to: ParanetNeuroIncentivesPool.address, +// value, +// }); +// await tx1.wait(); + +// // Simulate some miner activity +// const testKAStruct: ContentAssetStructs.AssetInputArgsStruct = { +// assertionId: '0x' + randomBytes(32).toString('hex'), +// size: 1000, +// triplesNumber: 10, +// chunksNumber: 10, +// epochsNumber: 5, +// tokenAmount: hre.ethers.utils.parseEther('2500'), // Miner spent 2500 TRAC +// scoreFunctionId: 2, +// immutable_: false, +// }; +// await Token.connect(miner).increaseAllowance(ServiceAgreementV1.address, testKAStruct.tokenAmount); +// await Paranet.connect(miner).mintKnowledgeAsset(ContentAssetStorage.address, paranetTokenId, testKAStruct); + +// const initialMinerBalance = await miner.getBalance(); +// const tx2 = await ParanetNeuroIncentivesPool.connect(miner).claimKnowledgeMinerReward(); +// const tx2Receipt = await tx2.wait(); +// const tx2Details = await hre.ethers.provider.getTransaction(tx2Receipt.transactionHash); +// const finalMinerBalance = await miner.getBalance(); + +// const expectedMinerReward = value.div(2).mul(85).div(100); +// expect(finalMinerBalance.sub(initialMinerBalance).add(tx2Receipt.gasUsed.mul(tx2Details.gasPrice))).to.equal( +// expectedMinerReward, +// ); +// }); + +// it('Should correctly calculate and send operator reward after miners reward', async function () { +// const paranetKAStruct: ContentAssetStructs.AssetInputArgsStruct = { +// assertionId: '0x' + randomBytes(32).toString('hex'), +// size: 1000, +// triplesNumber: 10, +// chunksNumber: 10, +// epochsNumber: 5, +// tokenAmount: hre.ethers.utils.parseEther('250'), +// scoreFunctionId: 2, +// immutable_: false, +// }; +// const { tokenId: paranetTokenId } = await createAsset(paranetKAStruct); + +// const { ParanetNeuroIncentivesPoolAddress } = await registerParanet( +// paranetTokenId, +// 'Paranet1', +// 'Test Paranet', +// hre.ethers.utils.parseEther('1'), // tracToNeuroRatio -- 1:1 +// 1000, // operatorRewardPercentage -- 10% +// 500, // paranetIncentivizationProposalVotersRewardPercentage -- 5% +// ); + +// const ParanetNeuroIncentivesPool = await hre.ethers.getContractAt( +// 'ParanetNeuroIncentivesPool', +// ParanetNeuroIncentivesPoolAddress, +// ); + +// const value = hre.ethers.utils.parseEther('6783'); +// const tx1 = await operator.sendTransaction({ +// to: ParanetNeuroIncentivesPool.address, +// value, +// }); +// await tx1.wait(); + +// // Simulate some miner activity +// const testKAStruct: ContentAssetStructs.AssetInputArgsStruct = { +// assertionId: '0x' + randomBytes(32).toString('hex'), +// size: 1000, +// triplesNumber: 10, +// chunksNumber: 10, +// epochsNumber: 5, +// tokenAmount: hre.ethers.utils.parseEther('2000'), // Miner spent 5000 TRAC +// scoreFunctionId: 2, +// immutable_: false, +// }; +// await Token.connect(miner).increaseAllowance(ServiceAgreementV1.address, testKAStruct.tokenAmount); +// await Paranet.connect(miner).mintKnowledgeAsset(ContentAssetStorage.address, paranetTokenId, testKAStruct); + +// const initialMinerBalance = await miner.getBalance(); +// const tx2 = await ParanetNeuroIncentivesPool.connect(miner).claimKnowledgeMinerReward(); +// const tx2Receipt = await tx2.wait(); +// const tx2Details = await hre.ethers.provider.getTransaction(tx2Receipt.transactionHash); +// const finalMinerBalance = await miner.getBalance(); + +// const expectedMinerReward = hre.ethers.utils.parseEther('2000').mul(85).div(100); +// expect(finalMinerBalance.sub(initialMinerBalance).add(tx2Receipt.gasUsed.mul(tx2Details.gasPrice))).to.equal( +// expectedMinerReward, +// ); + +// const initialOperatorBalance = await operator.getBalance(); +// const tx3 = await ParanetNeuroIncentivesPool.connect(operator).claimParanetOperatorReward(); +// const tx3Receipt = await tx3.wait(); +// const tx3Details = await hre.ethers.provider.getTransaction(tx3Receipt.transactionHash); +// const finalOperatorBalance = await operator.getBalance(); + +// const expectedOperatorReward = hre.ethers.utils.parseEther('2000').mul(10).div(100); +// expect(finalOperatorBalance.sub(initialOperatorBalance).add(tx3Receipt.gasUsed.mul(tx3Details.gasPrice))).to.equal( +// expectedOperatorReward, +// ); +// }); + +// it('Should correctly handle additional Neuro deposit and reward claims', async function () { +// const paranetKAStruct: ContentAssetStructs.AssetInputArgsStruct = { +// assertionId: '0x' + randomBytes(32).toString('hex'), +// size: 1000, +// triplesNumber: 10, +// chunksNumber: 10, +// epochsNumber: 5, +// tokenAmount: hre.ethers.utils.parseEther('250'), +// scoreFunctionId: 2, +// immutable_: false, +// }; +// const { tokenId: paranetTokenId } = await createAsset(paranetKAStruct); + +// const { ParanetNeuroIncentivesPoolAddress } = await registerParanet( +// paranetTokenId, +// 'Paranet1', +// 'Test Paranet', +// hre.ethers.utils.parseEther('1'), // tracToNeuroRatio -- 1:1 +// 1000, // operatorRewardPercentage -- 10% +// 500, // paranetIncentivizationProposalVotersRewardPercentage -- 5% +// ); + +// const ParanetNeuroIncentivesPool = await hre.ethers.getContractAt( +// 'ParanetNeuroIncentivesPool', +// ParanetNeuroIncentivesPoolAddress, +// ); + +// const value = hre.ethers.utils.parseEther('6783'); +// const tx1 = await operator.sendTransaction({ +// to: ParanetNeuroIncentivesPool.address, +// value, +// }); +// await tx1.wait(); + +// // Simulate some miner activity +// const testKAStruct: ContentAssetStructs.AssetInputArgsStruct = { +// assertionId: '0x' + randomBytes(32).toString('hex'), +// size: 1000, +// triplesNumber: 10, +// chunksNumber: 10, +// epochsNumber: 5, +// tokenAmount: hre.ethers.utils.parseEther('2000'), // Miner spent 2000 TRAC +// scoreFunctionId: 2, +// immutable_: false, +// }; +// await Token.connect(miner).increaseAllowance(ServiceAgreementV1.address, testKAStruct.tokenAmount); +// await Paranet.connect(miner).mintKnowledgeAsset(ContentAssetStorage.address, paranetTokenId, testKAStruct); + +// const initialMinerBalance = await miner.getBalance(); +// const tx2 = await ParanetNeuroIncentivesPool.connect(miner).claimKnowledgeMinerReward(); +// const tx2Receipt = await tx2.wait(); +// const tx2Details = await hre.ethers.provider.getTransaction(tx2Receipt.transactionHash); +// const finalMinerBalance = await miner.getBalance(); + +// const expectedMinerReward = hre.ethers.utils.parseEther('2000').mul(85).div(100); +// expect(finalMinerBalance.sub(initialMinerBalance).add(tx2Receipt.gasUsed.mul(tx2Details.gasPrice))).to.equal( +// expectedMinerReward, +// ); + +// const initialOperatorBalance = await operator.getBalance(); +// const tx3 = await ParanetNeuroIncentivesPool.connect(operator).claimParanetOperatorReward(); +// const tx3Receipt = await tx3.wait(); +// const tx3Details = await hre.ethers.provider.getTransaction(tx3Receipt.transactionHash); +// const finalOperatorBalance = await operator.getBalance(); + +// const expectedOperatorReward = hre.ethers.utils.parseEther('2000').mul(10).div(100); +// expect(finalOperatorBalance.sub(initialOperatorBalance).add(tx3Receipt.gasUsed.mul(tx3Details.gasPrice))).to.equal( +// expectedOperatorReward, +// ); + +// // Send additional Neuro to the contract +// const additionalValue = hre.ethers.utils.parseEther('3000'); +// const tx4 = await operator.sendTransaction({ +// to: ParanetNeuroIncentivesPool.address, +// value: additionalValue, +// }); +// await tx4.wait(); + +// // Mint another Knowledge asset from miner address +// const additionalKAStruct: ContentAssetStructs.AssetInputArgsStruct = { +// assertionId: '0x' + randomBytes(32).toString('hex'), +// size: 1000, +// triplesNumber: 10, +// chunksNumber: 10, +// epochsNumber: 5, +// tokenAmount: hre.ethers.utils.parseEther('1500'), // Miner spent 1500 TRAC +// scoreFunctionId: 2, +// immutable_: false, +// }; +// await Token.connect(miner).increaseAllowance(ServiceAgreementV1.address, additionalKAStruct.tokenAmount); +// await Paranet.connect(miner).mintKnowledgeAsset(ContentAssetStorage.address, paranetTokenId, additionalKAStruct); + +// // Claim rewards for miner and operator again +// const initialMinerBalance2 = await miner.getBalance(); +// const tx5 = await ParanetNeuroIncentivesPool.connect(miner).claimKnowledgeMinerReward(); +// const tx5Receipt = await tx5.wait(); +// const tx5Details = await hre.ethers.provider.getTransaction(tx5Receipt.transactionHash); +// const finalMinerBalance2 = await miner.getBalance(); + +// const expectedMinerReward2 = hre.ethers.utils.parseEther('1500').mul(85).div(100); +// expect(finalMinerBalance2.sub(initialMinerBalance2).add(tx5Receipt.gasUsed.mul(tx5Details.gasPrice))).to.equal( +// expectedMinerReward2, +// ); + +// const initialOperatorBalance2 = await operator.getBalance(); +// const tx6 = await ParanetNeuroIncentivesPool.connect(operator).claimParanetOperatorReward(); +// const tx6Receipt = await tx6.wait(); +// const tx6Details = await hre.ethers.provider.getTransaction(tx6Receipt.transactionHash); +// const finalOperatorBalance2 = await operator.getBalance(); + +// const expectedOperatorReward2 = hre.ethers.utils.parseEther('1500').mul(10).div(100); +// expect( +// finalOperatorBalance2.sub(initialOperatorBalance2).add(tx6Receipt.gasUsed.mul(tx6Details.gasPrice)), +// ).to.equal(expectedOperatorReward2); +// }); +// }); diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index 4127bb49..fe6a3c24 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -1,494 +1,325 @@ -// import { randomBytes } from 'crypto'; - -// import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; -// import { expect } from 'chai'; -// import { BigNumberish, BytesLike } from 'ethers'; -// import hre from 'hardhat'; -// import { SignerWithAddress } from 'hardhat-deploy-ethers/signers'; -// import { Address } from 'hardhat-deploy/types'; - -// import { -// Paranet, -// ParanetsRegistry, -// ParanetKnowledgeMinersRegistry, -// HubController, -// ContentAssetV2, -// ServiceAgreementV1, -// ContentAssetStorageV2, -// Token, -// ParanetIncentivesPoolFactory, -// } from '../../typechain'; -// import { ContentAssetStructs } from '../../../typechain/contracts/v2/assets/ContentAsset.sol/ContentAssetV2'; - -// type ParanetNeuroIncentivesPoolFixture = { -// accounts: SignerWithAddress[]; -// ContentAsset: ContentAssetV2; -// ContentAssetStorage: ContentAssetStorageV2; -// ServiceAgreementV1: ServiceAgreementV1; -// Token: Token; -// ParanetKnowledgeMinersRegistry: ParanetKnowledgeMinersRegistry; -// ParanetsRegistry: ParanetsRegistry; -// Paranet: Paranet; -// ParanetIncentivesPoolFactory: ParanetIncentivesPoolFactory; -// }; - -// describe('@v2 @integration Paranet', function () { -// let accounts: SignerWithAddress[]; -// let operator: SignerWithAddress; -// let miner: SignerWithAddress; -// let HubController: HubController; -// let ContentAsset: ContentAssetV2; -// let ServiceAgreementV1: ServiceAgreementV1; -// let ContentAssetStorage: ContentAssetStorageV2; -// let Token: Token; -// let ParanetKnowledgeMinersRegistry: ParanetKnowledgeMinersRegistry; -// let ParanetsRegistry: ParanetsRegistry; -// let Paranet: Paranet; -// let ParanetIncentivesPoolFactory: ParanetIncentivesPoolFactory; - -// async function deployParanetNeuroIncentivesPoolFixture(): Promise { -// await hre.deployments.fixture([ -// 'Token', -// 'ServiceAgreementV1', -// 'ContentAssetStorageV2', -// 'ContentAssetV2', -// 'Paranet', -// 'ParanetIncentivesPoolFactory', -// ]); - -// ContentAssetStorage = await hre.ethers.getContract('ContentAssetStorage'); -// ContentAsset = await hre.ethers.getContract('ContentAsset'); -// ServiceAgreementV1 = await hre.ethers.getContract('ServiceAgreementV1'); -// Token = await hre.ethers.getContract('Token'); - -// ParanetKnowledgeMinersRegistry = await hre.ethers.getContract( -// 'ParanetKnowledgeMinersRegistry', -// ); -// ParanetsRegistry = await hre.ethers.getContract('ParanetsRegistry'); -// Paranet = await hre.ethers.getContract('Paranet'); -// ParanetIncentivesPoolFactory = await hre.ethers.getContract( -// 'ParanetIncentivesPoolFactory', -// ); - -// accounts = await hre.ethers.getSigners(); - -// HubController = await hre.ethers.getContract('HubController'); -// await HubController.setContractAddress('HubOwner', accounts[0].address); - -// return { -// accounts, -// ContentAssetStorage, -// ContentAsset, -// ServiceAgreementV1, -// Token, -// ParanetKnowledgeMinersRegistry, -// ParanetsRegistry, -// Paranet, -// ParanetIncentivesPoolFactory, -// }; -// } - -// async function createAsset( -// assetInputStruct: ContentAssetStructs.AssetInputArgsStruct, -// ): Promise<{ tokenId: number; keyword: BytesLike; agreementId: BytesLike }> { -// await Token.connect(operator).increaseAllowance(ServiceAgreementV1.address, assetInputStruct.tokenAmount); -// const receipt = await (await ContentAsset.connect(operator).createAsset(assetInputStruct)).wait(); -// const tokenId = Number(receipt.logs[0].topics[3]); - -// const keyword = hre.ethers.utils.solidityPack( -// ['address', 'bytes32'], -// [ContentAssetStorage.address, assetInputStruct.assertionId], -// ); -// const agreementId = hre.ethers.utils.soliditySha256( -// ['address', 'uint256', 'bytes'], -// [ContentAssetStorage.address, tokenId, keyword], -// ); -// return { tokenId, keyword, agreementId }; -// } - -// async function registerParanet( -// paranetKATokenId: BigNumberish, -// paranetName: string, -// paranetDescription: string, -// tracToNeuroEmissionMultiplier: BigNumberish, -// paranetOperatorRewardPercentage: BigNumberish, -// paranetIncentivizationProposalVotersRewardPercentage: BigNumberish, -// ): Promise<{ paranetId: BytesLike; ParanetNeuroIncentivesPoolAddress: Address }> { -// const tx1 = await Paranet.connect(operator).registerParanet( -// ContentAssetStorage.address, -// paranetKATokenId, -// paranetName, -// paranetDescription, -// 0, -// 0, -// ); -// await tx1.wait(); - -// const tx2 = await ParanetIncentivesPoolFactory.connect(operator).deployNeuroIncentivesPool( -// ContentAssetStorage.address, -// paranetKATokenId, -// tracToNeuroEmissionMultiplier, -// paranetOperatorRewardPercentage, -// paranetIncentivizationProposalVotersRewardPercentage, -// ); -// await tx2.wait(); - -// const paranetId = hre.ethers.utils.keccak256( -// hre.ethers.utils.solidityPack(['address', 'uint256'], [ContentAssetStorage.address, paranetKATokenId]), -// ); -// const ParanetNeuroIncentivesPoolAddress = await ParanetsRegistry.getIncentivesPoolAddress(paranetId, 'Neuroweb'); - -// return { -// paranetId, -// ParanetNeuroIncentivesPoolAddress, -// }; -// } - -// beforeEach(async function () { -// hre.helpers.resetDeploymentsJson(); -// ({ -// accounts, -// ContentAssetStorage, -// ContentAsset, -// ServiceAgreementV1, -// Token, -// ParanetKnowledgeMinersRegistry, -// ParanetsRegistry, -// Paranet, -// ParanetIncentivesPoolFactory, -// } = await loadFixture(deployParanetNeuroIncentivesPoolFixture)); - -// operator = accounts[1]; -// miner = accounts[2]; -// }); - -// it('Should accept native tokens, update balance and variable successfully', async function () { -// const paranetKAStruct: ContentAssetStructs.AssetInputArgsStruct = { -// assertionId: '0x' + randomBytes(32).toString('hex'), -// size: 1000, -// triplesNumber: 10, -// chunksNumber: 10, -// epochsNumber: 5, -// tokenAmount: hre.ethers.utils.parseEther('250'), -// scoreFunctionId: 2, -// immutable_: false, -// }; -// const { tokenId: paranetTokenId } = await createAsset(paranetKAStruct); - -// const { ParanetNeuroIncentivesPoolAddress } = await registerParanet( -// paranetTokenId, -// 'Paranet1', -// 'Test Paranet', -// hre.ethers.utils.parseEther('1'), // tracToNeuroRatio -- 1:1 -// 1000, // paranetOperatorRewardPercentage -- 10% -// 500, // paranetIncentivizationProposalVotersRewardPercentage -- 5% -// ); - -// const ParanetNeuroIncentivesPool = await hre.ethers.getContractAt( -// 'ParanetNeuroIncentivesPool', -// ParanetNeuroIncentivesPoolAddress, -// ); - -// const initialBalance = await ParanetNeuroIncentivesPool.getNeuroBalance(); - -// expect(initialBalance).to.be.equal(0); - -// const value = hre.ethers.utils.parseEther('100'); -// const tx = await operator.sendTransaction({ -// to: ParanetNeuroIncentivesPool.address, -// value, -// }); -// await tx.wait(); - -// const finalBalance = await ParanetNeuroIncentivesPool.getNeuroBalance(); -// const totalNeuroReceived = await ParanetNeuroIncentivesPool.totalNeuroReceived(); - -// expect(finalBalance).to.be.equal(totalNeuroReceived).to.be.equal(value); -// }); - -// // it('Should revert while getting operator reward before miner', async function () { -// // const paranetKAStruct: ContentAssetStructs.AssetInputArgsStruct = { -// // assertionId: '0x' + randomBytes(32).toString('hex'), -// // size: 1000, -// // triplesNumber: 10, -// // chunksNumber: 10, -// // epochsNumber: 5, -// // tokenAmount: hre.ethers.utils.parseEther('250'), -// // scoreFunctionId: 2, -// // immutable_: false, -// // }; -// // const { tokenId: paranetTokenId } = await createAsset(paranetKAStruct); - -// // const { ParanetNeuroIncentivesPoolAddress } = await registerParanet( -// // paranetTokenId, -// // 'Paranet1', -// // 'Test Paranet', -// // hre.ethers.utils.parseEther('1'), // tracToNeuroRatio - 1:1 -// // 1000, // operatorRewardPercentage -- 10% -// // 500, // paranetIncentivizationProposalVotersRewardPercentage -- 5% -// // ); - -// // const ParanetNeuroIncentivesPool = await hre.ethers.getContractAt( -// // 'ParanetNeuroIncentivesPool', -// // ParanetNeuroIncentivesPoolAddress, -// // ); - -// // const value = hre.ethers.utils.parseEther('1000'); -// // const tx = await operator.sendTransaction({ -// // to: ParanetNeuroIncentivesPool.address, -// // value, -// // }); -// // await tx.wait(); - -// // await expect( -// // ParanetNeuroIncentivesPool.connect(operator).claimParanetOperatorReward(), -// // ).to.be.revertedWithCustomError(ParanetNeuroIncentivesPool, 'NoRewardAvailable'); -// // }); - -// it('Should correctly calculate miner reward', async function () { -// const paranetKAStruct: ContentAssetStructs.AssetInputArgsStruct = { -// assertionId: '0x' + randomBytes(32).toString('hex'), -// size: 1000, -// triplesNumber: 10, -// chunksNumber: 10, -// epochsNumber: 5, -// tokenAmount: hre.ethers.utils.parseEther('250'), -// scoreFunctionId: 2, -// immutable_: false, -// }; -// const { tokenId: paranetTokenId } = await createAsset(paranetKAStruct); - -// const { ParanetNeuroIncentivesPoolAddress } = await registerParanet( -// paranetTokenId, -// 'Paranet1', -// 'Test Paranet', -// hre.ethers.utils.parseEther('1'), // tracToNeuroRatio -- 1:1 -// 1000, // operatorRewardPercentage -- 10% -// 500, // paranetIncentivizationProposalVotersRewardPercentage -- 5% -// ); - -// const ParanetNeuroIncentivesPool = await hre.ethers.getContractAt( -// 'ParanetNeuroIncentivesPool', -// ParanetNeuroIncentivesPoolAddress, -// ); - -// const value = hre.ethers.utils.parseEther('5000'); -// const tx1 = await operator.sendTransaction({ -// to: ParanetNeuroIncentivesPool.address, -// value, -// }); -// await tx1.wait(); - -// // Simulate some miner activity -// const testKAStruct: ContentAssetStructs.AssetInputArgsStruct = { -// assertionId: '0x' + randomBytes(32).toString('hex'), -// size: 1000, -// triplesNumber: 10, -// chunksNumber: 10, -// epochsNumber: 5, -// tokenAmount: hre.ethers.utils.parseEther('2500'), // Miner spent 2500 TRAC -// scoreFunctionId: 2, -// immutable_: false, -// }; -// await Token.connect(miner).increaseAllowance(ServiceAgreementV1.address, testKAStruct.tokenAmount); -// await Paranet.connect(miner).mintKnowledgeAsset(ContentAssetStorage.address, paranetTokenId, testKAStruct); - -// const initialMinerBalance = await miner.getBalance(); -// const tx2 = await ParanetNeuroIncentivesPool.connect(miner).claimKnowledgeMinerReward(); -// const tx2Receipt = await tx2.wait(); -// const tx2Details = await hre.ethers.provider.getTransaction(tx2Receipt.transactionHash); -// const finalMinerBalance = await miner.getBalance(); - -// const expectedMinerReward = value.div(2).mul(85).div(100); -// expect(finalMinerBalance.sub(initialMinerBalance).add(tx2Receipt.gasUsed.mul(tx2Details.gasPrice))).to.equal( -// expectedMinerReward, -// ); -// }); - -// it('Should correctly calculate and send operator reward after miners reward', async function () { -// const paranetKAStruct: ContentAssetStructs.AssetInputArgsStruct = { -// assertionId: '0x' + randomBytes(32).toString('hex'), -// size: 1000, -// triplesNumber: 10, -// chunksNumber: 10, -// epochsNumber: 5, -// tokenAmount: hre.ethers.utils.parseEther('250'), -// scoreFunctionId: 2, -// immutable_: false, -// }; -// const { tokenId: paranetTokenId } = await createAsset(paranetKAStruct); - -// const { ParanetNeuroIncentivesPoolAddress } = await registerParanet( -// paranetTokenId, -// 'Paranet1', -// 'Test Paranet', -// hre.ethers.utils.parseEther('1'), // tracToNeuroRatio -- 1:1 -// 1000, // operatorRewardPercentage -- 10% -// 500, // paranetIncentivizationProposalVotersRewardPercentage -- 5% -// ); - -// const ParanetNeuroIncentivesPool = await hre.ethers.getContractAt( -// 'ParanetNeuroIncentivesPool', -// ParanetNeuroIncentivesPoolAddress, -// ); - -// const value = hre.ethers.utils.parseEther('6783'); -// const tx1 = await operator.sendTransaction({ -// to: ParanetNeuroIncentivesPool.address, -// value, -// }); -// await tx1.wait(); - -// // Simulate some miner activity -// const testKAStruct: ContentAssetStructs.AssetInputArgsStruct = { -// assertionId: '0x' + randomBytes(32).toString('hex'), -// size: 1000, -// triplesNumber: 10, -// chunksNumber: 10, -// epochsNumber: 5, -// tokenAmount: hre.ethers.utils.parseEther('2000'), // Miner spent 5000 TRAC -// scoreFunctionId: 2, -// immutable_: false, -// }; -// await Token.connect(miner).increaseAllowance(ServiceAgreementV1.address, testKAStruct.tokenAmount); -// await Paranet.connect(miner).mintKnowledgeAsset(ContentAssetStorage.address, paranetTokenId, testKAStruct); - -// const initialMinerBalance = await miner.getBalance(); -// const tx2 = await ParanetNeuroIncentivesPool.connect(miner).claimKnowledgeMinerReward(); -// const tx2Receipt = await tx2.wait(); -// const tx2Details = await hre.ethers.provider.getTransaction(tx2Receipt.transactionHash); -// const finalMinerBalance = await miner.getBalance(); - -// const expectedMinerReward = hre.ethers.utils.parseEther('2000').mul(85).div(100); -// expect(finalMinerBalance.sub(initialMinerBalance).add(tx2Receipt.gasUsed.mul(tx2Details.gasPrice))).to.equal( -// expectedMinerReward, -// ); - -// const initialOperatorBalance = await operator.getBalance(); -// const tx3 = await ParanetNeuroIncentivesPool.connect(operator).claimParanetOperatorReward(); -// const tx3Receipt = await tx3.wait(); -// const tx3Details = await hre.ethers.provider.getTransaction(tx3Receipt.transactionHash); -// const finalOperatorBalance = await operator.getBalance(); - -// const expectedOperatorReward = hre.ethers.utils.parseEther('2000').mul(10).div(100); -// expect(finalOperatorBalance.sub(initialOperatorBalance).add(tx3Receipt.gasUsed.mul(tx3Details.gasPrice))).to.equal( -// expectedOperatorReward, -// ); -// }); - -// it('Should correctly handle additional Neuro deposit and reward claims', async function () { -// const paranetKAStruct: ContentAssetStructs.AssetInputArgsStruct = { -// assertionId: '0x' + randomBytes(32).toString('hex'), -// size: 1000, -// triplesNumber: 10, -// chunksNumber: 10, -// epochsNumber: 5, -// tokenAmount: hre.ethers.utils.parseEther('250'), -// scoreFunctionId: 2, -// immutable_: false, -// }; -// const { tokenId: paranetTokenId } = await createAsset(paranetKAStruct); - -// const { ParanetNeuroIncentivesPoolAddress } = await registerParanet( -// paranetTokenId, -// 'Paranet1', -// 'Test Paranet', -// hre.ethers.utils.parseEther('1'), // tracToNeuroRatio -- 1:1 -// 1000, // operatorRewardPercentage -- 10% -// 500, // paranetIncentivizationProposalVotersRewardPercentage -- 5% -// ); - -// const ParanetNeuroIncentivesPool = await hre.ethers.getContractAt( -// 'ParanetNeuroIncentivesPool', -// ParanetNeuroIncentivesPoolAddress, -// ); - -// const value = hre.ethers.utils.parseEther('6783'); -// const tx1 = await operator.sendTransaction({ -// to: ParanetNeuroIncentivesPool.address, -// value, -// }); -// await tx1.wait(); - -// // Simulate some miner activity -// const testKAStruct: ContentAssetStructs.AssetInputArgsStruct = { -// assertionId: '0x' + randomBytes(32).toString('hex'), -// size: 1000, -// triplesNumber: 10, -// chunksNumber: 10, -// epochsNumber: 5, -// tokenAmount: hre.ethers.utils.parseEther('2000'), // Miner spent 2000 TRAC -// scoreFunctionId: 2, -// immutable_: false, -// }; -// await Token.connect(miner).increaseAllowance(ServiceAgreementV1.address, testKAStruct.tokenAmount); -// await Paranet.connect(miner).mintKnowledgeAsset(ContentAssetStorage.address, paranetTokenId, testKAStruct); - -// const initialMinerBalance = await miner.getBalance(); -// const tx2 = await ParanetNeuroIncentivesPool.connect(miner).claimKnowledgeMinerReward(); -// const tx2Receipt = await tx2.wait(); -// const tx2Details = await hre.ethers.provider.getTransaction(tx2Receipt.transactionHash); -// const finalMinerBalance = await miner.getBalance(); - -// const expectedMinerReward = hre.ethers.utils.parseEther('2000').mul(85).div(100); -// expect(finalMinerBalance.sub(initialMinerBalance).add(tx2Receipt.gasUsed.mul(tx2Details.gasPrice))).to.equal( -// expectedMinerReward, -// ); - -// const initialOperatorBalance = await operator.getBalance(); -// const tx3 = await ParanetNeuroIncentivesPool.connect(operator).claimParanetOperatorReward(); -// const tx3Receipt = await tx3.wait(); -// const tx3Details = await hre.ethers.provider.getTransaction(tx3Receipt.transactionHash); -// const finalOperatorBalance = await operator.getBalance(); - -// const expectedOperatorReward = hre.ethers.utils.parseEther('2000').mul(10).div(100); -// expect(finalOperatorBalance.sub(initialOperatorBalance).add(tx3Receipt.gasUsed.mul(tx3Details.gasPrice))).to.equal( -// expectedOperatorReward, -// ); - -// // Send additional Neuro to the contract -// const additionalValue = hre.ethers.utils.parseEther('3000'); -// const tx4 = await operator.sendTransaction({ -// to: ParanetNeuroIncentivesPool.address, -// value: additionalValue, -// }); -// await tx4.wait(); - -// // Mint another Knowledge asset from miner address -// const additionalKAStruct: ContentAssetStructs.AssetInputArgsStruct = { -// assertionId: '0x' + randomBytes(32).toString('hex'), -// size: 1000, -// triplesNumber: 10, -// chunksNumber: 10, -// epochsNumber: 5, -// tokenAmount: hre.ethers.utils.parseEther('1500'), // Miner spent 1500 TRAC -// scoreFunctionId: 2, -// immutable_: false, -// }; -// await Token.connect(miner).increaseAllowance(ServiceAgreementV1.address, additionalKAStruct.tokenAmount); -// await Paranet.connect(miner).mintKnowledgeAsset(ContentAssetStorage.address, paranetTokenId, additionalKAStruct); - -// // Claim rewards for miner and operator again -// const initialMinerBalance2 = await miner.getBalance(); -// const tx5 = await ParanetNeuroIncentivesPool.connect(miner).claimKnowledgeMinerReward(); -// const tx5Receipt = await tx5.wait(); -// const tx5Details = await hre.ethers.provider.getTransaction(tx5Receipt.transactionHash); -// const finalMinerBalance2 = await miner.getBalance(); - -// const expectedMinerReward2 = hre.ethers.utils.parseEther('1500').mul(85).div(100); -// expect(finalMinerBalance2.sub(initialMinerBalance2).add(tx5Receipt.gasUsed.mul(tx5Details.gasPrice))).to.equal( -// expectedMinerReward2, -// ); - -// const initialOperatorBalance2 = await operator.getBalance(); -// const tx6 = await ParanetNeuroIncentivesPool.connect(operator).claimParanetOperatorReward(); -// const tx6Receipt = await tx6.wait(); -// const tx6Details = await hre.ethers.provider.getTransaction(tx6Receipt.transactionHash); -// const finalOperatorBalance2 = await operator.getBalance(); - -// const expectedOperatorReward2 = hre.ethers.utils.parseEther('1500').mul(10).div(100); -// expect( -// finalOperatorBalance2.sub(initialOperatorBalance2).add(tx6Receipt.gasUsed.mul(tx6Details.gasPrice)), -// ).to.equal(expectedOperatorReward2); -// }); -// }); +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { expect } from 'chai'; +import { ethers, EventLog } from 'ethers'; +import hre from 'hardhat'; + +import { + Paranet, + ParanetsRegistry, + ParanetServicesRegistry, + ParanetKnowledgeMinersRegistry, + ParanetKnowledgeCollectionsRegistry, + ParanetIncentivesPoolFactory, + KnowledgeCollection, + KnowledgeCollectionStorage, + Profile, + Token, + Hub, + EpochStorage, + ParanetNeuroIncentivesPool, +} from '../../typechain'; +import { + createKnowledgeCollection, + getKCSignaturesData, +} from '../helpers/kc-helpers'; +import { createProfile, createProfiles } from '../helpers/profile-helpers'; + +// Fixture containing all contracts and accounts needed to test Paranet +type ParanetFixture = { + accounts: SignerWithAddress[]; + Paranet: Paranet; + ParanetsRegistry: ParanetsRegistry; + ParanetServicesRegistry: ParanetServicesRegistry; + ParanetKnowledgeMinersRegistry: ParanetKnowledgeMinersRegistry; + ParanetKnowledgeCollectionsRegistry: ParanetKnowledgeCollectionsRegistry; + ParanetIncentivesPoolFactory: ParanetIncentivesPoolFactory; + KnowledgeCollection: KnowledgeCollection; + KnowledgeCollectionStorage: KnowledgeCollectionStorage; + Profile: Profile; + Token: Token; + EpochStorage: EpochStorage; +}; + +describe('@unit Paranet', () => { + let accounts: SignerWithAddress[]; + let Paranet: Paranet; + let ParanetsRegistry: ParanetsRegistry; + let ParanetServicesRegistry: ParanetServicesRegistry; + let ParanetKnowledgeMinersRegistry: ParanetKnowledgeMinersRegistry; + let ParanetKnowledgeCollectionsRegistry: ParanetKnowledgeCollectionsRegistry; + let ParanetIncentivesPoolFactory: ParanetIncentivesPoolFactory; + let KnowledgeCollection: KnowledgeCollection; + let KnowledgeCollectionStorage: KnowledgeCollectionStorage; + let Profile: Profile; + let Token: Token; + let EpochStorage: EpochStorage; + + // Deploy all contracts, set the HubOwner and necessary accounts. Returns the ParanetFixture + async function deployParanetFixture(): Promise { + await hre.deployments.fixture([ + 'Paranet', + 'ParanetsRegistry', + 'ParanetServicesRegistry', + 'ParanetKnowledgeMinersRegistry', + 'ParanetKnowledgeCollectionsRegistry', + 'ParanetIncentivesPoolFactory', + 'KnowledgeCollection', + 'Profile', + 'Token', + 'EpochStorage', + ]); + + accounts = await hre.ethers.getSigners(); + const Hub = await hre.ethers.getContract('Hub'); + await Hub.setContractAddress('HubOwner', accounts[0].address); + + EpochStorage = await hre.ethers.getContract('EpochStorageV8'); + Paranet = await hre.ethers.getContract('Paranet'); + ParanetsRegistry = + await hre.ethers.getContract('ParanetsRegistry'); + ParanetServicesRegistry = + await hre.ethers.getContract( + 'ParanetServicesRegistry', + ); + ParanetKnowledgeMinersRegistry = + await hre.ethers.getContract( + 'ParanetKnowledgeMinersRegistry', + ); + ParanetKnowledgeCollectionsRegistry = + await hre.ethers.getContract( + 'ParanetKnowledgeCollectionsRegistry', + ); + ParanetIncentivesPoolFactory = + await hre.ethers.getContract( + 'ParanetIncentivesPoolFactory', + ); + KnowledgeCollection = await hre.ethers.getContract( + 'KnowledgeCollection', + ); + KnowledgeCollectionStorage = + await hre.ethers.getContract( + 'KnowledgeCollectionStorage', + ); + Profile = await hre.ethers.getContract('Profile'); + Token = await hre.ethers.getContract('Token'); + + return { + accounts, + Paranet, + ParanetsRegistry, + ParanetServicesRegistry, + ParanetKnowledgeMinersRegistry, + ParanetKnowledgeCollectionsRegistry, + ParanetIncentivesPoolFactory, + KnowledgeCollection, + KnowledgeCollectionStorage, + Profile, + Token, + EpochStorage, + }; + } + + async function createAndRegisterParanet() { + // Create profiles for admin, publisher and validators + const publishingNode = { + admin: accounts[1], + operational: accounts[2], + }; + const receivingNodes = [ + { + admin: accounts[3], + operational: accounts[4], + }, + { + admin: accounts[5], + operational: accounts[6], + }, + { + admin: accounts[7], + operational: accounts[8], + }, + ]; + + const kcCreator = accounts[9]; // knowledge collection creator and paranet owner + + const { identityId: publishingNodeIdentityId } = await createProfile( + Profile, + publishingNode, + ); + const receivingNodesIdentityIds = ( + await createProfiles(Profile, receivingNodes) + ).map((p) => p.identityId); + + // Create knowledge collection + const signaturesData = await getKCSignaturesData( + publishingNode, + publishingNodeIdentityId, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + KnowledgeCollection, + Token, + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + ); + + // Register paranet + const paranetKCStorageContract = + await KnowledgeCollectionStorage.getAddress(); + const paranetKATokenId = 1; + const paranetName = 'Test Paranet'; + const paranetDescription = 'Test Paranet Description'; + const nodesAccessPolicy = 0; // OPEN + const minersAccessPolicy = 0; // OPEN + + await Paranet.connect(kcCreator).registerParanet( + paranetKCStorageContract, + collectionId, + paranetKATokenId, + paranetName, + paranetDescription, + nodesAccessPolicy, + minersAccessPolicy, + ); + + return { + publishingNode, + receivingNodes, + publishingNodeIdentityId, + receivingNodesIdentityIds, + paranetOwner: kcCreator, + paranetKCStorageContract, + paranetKCTokenId: collectionId, + paranetKATokenId, + paranetName, + paranetDescription, + nodesAccessPolicy, + minersAccessPolicy, + paranetId: ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256', 'uint256'], + [paranetKCStorageContract, collectionId, paranetKATokenId], + ), + ), + }; + } + + // Before each test, deploy all contracts and necessary accounts. These variables can be used in the tests + beforeEach(async () => { + ({ + accounts, + Paranet, + ParanetsRegistry, + ParanetServicesRegistry, + ParanetKnowledgeMinersRegistry, + ParanetKnowledgeCollectionsRegistry, + ParanetIncentivesPoolFactory, + KnowledgeCollection, + KnowledgeCollectionStorage, + Profile, + Token, + } = await loadFixture(deployParanetFixture)); + }); + + describe('Paranet Registration', () => { + it('Should register a paranet successfully', async () => { + const { + paranetOwner, + paranetId, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetName, + paranetDescription, + nodesAccessPolicy, + minersAccessPolicy, + } = await createAndRegisterParanet(); + + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(await ParanetsRegistry.paranetExists(paranetId)).to.be.true; + + // Check paranet owner + const startTokenId = + (paranetKCTokenId - 1) * + Number( + await KnowledgeCollectionStorage.knowledgeCollectionMaxSize(), + ) + + paranetKATokenId; + + const ownedCountInRange = await KnowledgeCollectionStorage[ + 'balanceOf(address,uint256,uint256)' + ](paranetOwner.address, startTokenId, startTokenId + 1); + + expect(ownedCountInRange).to.equal(1); + + // Check paranet metadata + const paranetMetadata = + await ParanetsRegistry.getParanetMetadata(paranetId); + expect(paranetMetadata.paranetKCStorageContract).to.equal( + paranetKCStorageContract, + ); + expect(paranetMetadata.paranetKCTokenId).to.equal(paranetKCTokenId); + expect(paranetMetadata.paranetKATokenId).to.equal(paranetKATokenId); + expect(paranetMetadata.name).to.equal(paranetName); + expect(paranetMetadata.description).to.equal(paranetDescription); + expect(paranetMetadata.nodesAccessPolicy).to.equal(nodesAccessPolicy); + expect(paranetMetadata.minersAccessPolicy).to.equal(minersAccessPolicy); + }); + }); + + describe('Paranet Incentives Pool', () => { + it('Should deploy incentives pool successfully', async () => { + const { + paranetId, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner, + } = await createAndRegisterParanet(); + + const tracToNeuroEmissionMultiplier = ethers.parseUnits('1', 12); // 1 NEURO per 1 TRAC + const operatorRewardPercentage = 1000; // 10% + const votersRewardPercentage = 2000; // 20% + + const tx = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployNeuroIncentivesPool( + true, // isNativeReward + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + tracToNeuroEmissionMultiplier, + operatorRewardPercentage, + votersRewardPercentage, + ); + + const receipt = await tx.wait(); + const event = receipt!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncetivesPoolDeployed', + ).topicHash, + ) as EventLog; + + expect(event?.args[0]).to.equal(paranetKCStorageContract); + expect(event?.args[1]).to.equal(paranetKCTokenId); + expect(event?.args[2][0]).to.equal('Neuroweb'); + + const poolAddress = await ParanetsRegistry.getIncentivesPoolAddress( + paranetId, + 'Neuroweb', + ); + expect(poolAddress).to.equal(event?.args[2][1]); + + const pool = (await hre.ethers.getContractAt( + 'ParanetNeuroIncentivesPool', + poolAddress, + )) as ParanetNeuroIncentivesPool; + expect(await pool.parentParanetId()).to.equal(paranetId); + }); + }); +}); From c5d3cf59481df1503280ff2311149c6a3521143a Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Thu, 13 Feb 2025 15:39:31 +0100 Subject: [PATCH 087/153] Remove enums for paranet policies --- contracts/libraries/ParanetLib.sol | 37 ++---- contracts/paranets/Paranet.sol | 119 ++++++++++-------- .../storage/paranets/ParanetsRegistry.sol | 36 +++--- 3 files changed, 92 insertions(+), 100 deletions(-) diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index 8be4136d..34aa0d05 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -21,21 +21,6 @@ library ParanetLib { uint256 knowledgeAssetTokenId; } - enum NodesAccessPolicy { - OPEN, - CURATED - } - - enum MinersAccessPolicy { - OPEN, - CURATED - } - - enum KnowledgeCollectionsAccessPolicy { - OPEN, - STAGING - } - struct Node { uint72 identityId; bytes nodeId; @@ -74,9 +59,9 @@ library ParanetLib { uint256 paranetKATokenId; string name; string description; - NodesAccessPolicy nodesAccessPolicy; - MinersAccessPolicy minersAccessPolicy; - KnowledgeCollectionsAccessPolicy knowledgeCollectionsAccessPolicy; + uint8 nodesAccessPolicy; + uint8 minersAccessPolicy; + uint8 knowledgeCollectionsSubmissionPolicy; uint96 cumulativeKnowledgeValue; IncentivesPool[] incentivesPools; // Incentives Pool Name => Index in the array @@ -107,9 +92,9 @@ library ParanetLib { uint256 paranetKATokenId; string name; string description; - NodesAccessPolicy nodesAccessPolicy; - MinersAccessPolicy minersAccessPolicy; - KnowledgeCollectionsAccessPolicy knowledgeCollectionsAccessPolicy; + uint8 nodesAccessPolicy; + uint8 minersAccessPolicy; + uint8 knowledgeCollectionsSubmissionPolicy; uint96 cumulativeKnowledgeValue; } @@ -192,10 +177,7 @@ library ParanetLib { uint256 knowledgeCollectionTokenId, uint256 knowledgeAssetTokenId ); - error InvalidParanetNodesAccessPolicy( - ParanetLib.NodesAccessPolicy[] expectedAccessPolicies, - ParanetLib.NodesAccessPolicy actualAccessPolicy - ); + error InvalidParanetNodesAccessPolicy(uint8[] expectedAccessPolicies, uint8 actualAccessPolicy); error ParanetCuratedNodeHasAlreadyBeenAdded(bytes32 paranetId, uint72 identityId); error ParanetCuratedNodeDoesntExist(bytes32 paranetId, uint72 identityId); error ParanetCuratedNodeJoinRequestInvalidStatus( @@ -204,10 +186,7 @@ library ParanetLib { ParanetLib.RequestStatus status ); error ParanetCuratedNodeJoinRequestDoesntExist(bytes32 paranetId, uint72 identityId); - error InvalidParanetMinersAccessPolicy( - ParanetLib.MinersAccessPolicy[] expectedAccessPolicies, - ParanetLib.MinersAccessPolicy actualAccessPolicy - ); + error InvalidParanetMinersAccessPolicy(uint8[] expectedAccessPolicies, uint8 actualAccessPolicy); error ParanetCuratedMinerHasAlreadyBeenAdded(bytes32 paranetId, address miner); error ParanetCuratedMinerDoesntExist(bytes32 paranetId, address miner); error ParanetCuratedMinerAccessRequestInvalidStatus( diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index a2c4306a..970863e7 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -19,15 +19,25 @@ import {ProfileLib} from "../libraries/ProfileLib.sol"; import {KnowledgeCollectionLib} from "../libraries/KnowledgeCollectionLib.sol"; contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { + // Access Policy Constants + uint8 constant NODES_ACCESS_POLICY_OPEN = 0; + uint8 constant NODES_ACCESS_POLICY_PERMISSIONED = 1; + + uint8 constant MINERS_ACCESS_POLICY_OPEN = 0; + uint8 constant MINERS_ACCESS_POLICY_PERMISSIONED = 1; + + uint8 constant KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_OPEN = 0; + uint8 constant KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING = 1; + event ParanetRegistered( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, uint256 indexed parnetKATokenId, string paranetName, string paranetDescription, - ParanetLib.NodesAccessPolicy nodesAccessPolicy, - ParanetLib.MinersAccessPolicy minersAccessPolicy, - ParanetLib.KnowledgeCollectionsAccessPolicy knowledgeCollectionsAccessPolicy + uint8 nodesAccessPolicy, + uint8 minersAccessPolicy, + uint8 knowledgeCollectionsSubmissionPolicy ); event ParanetCuratedNodeAdded( address indexed paranetKCStorageContract, @@ -206,9 +216,14 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 paranetKATokenId, string calldata paranetName, string calldata paranetDescription, - ParanetLib.NodesAccessPolicy nodesAccessPolicy, - ParanetLib.MinersAccessPolicy minersAccessPolicy + uint8 nodesAccessPolicy, + uint8 minersAccessPolicy, + uint8 knowledgeCollectionsSubmissionPolicy ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) returns (bytes32) { + require( + nodesAccessPolicy < 2 && minersAccessPolicy < 2 && knowledgeCollectionsSubmissionPolicy < 2, + "Invalid policy" + ); ParanetsRegistry pr = paranetsRegistry; bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); @@ -229,7 +244,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { paranetDescription, nodesAccessPolicy, minersAccessPolicy, - ParanetLib.KnowledgeCollectionsAccessPolicy.OPEN + knowledgeCollectionsSubmissionPolicy ); return @@ -241,7 +256,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { paranetDescription, nodesAccessPolicy, minersAccessPolicy, - ParanetLib.KnowledgeCollectionsAccessPolicy.OPEN + knowledgeCollectionsSubmissionPolicy ); } @@ -287,9 +302,10 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } - if (pr.getNodesAccessPolicy(paranetId) != ParanetLib.NodesAccessPolicy.CURATED) { - ParanetLib.NodesAccessPolicy[] memory expectedAccessPolicies = new ParanetLib.NodesAccessPolicy[](1); - expectedAccessPolicies[0] = ParanetLib.NodesAccessPolicy.CURATED; + if (pr.getNodesAccessPolicy(paranetId) != NODES_ACCESS_POLICY_PERMISSIONED) { + // TODO: Why is this 1 element array + uint8[] memory expectedAccessPolicies = new uint8[](1); + expectedAccessPolicies[0] = NODES_ACCESS_POLICY_PERMISSIONED; revert ParanetLib.InvalidParanetNodesAccessPolicy( expectedAccessPolicies, @@ -330,9 +346,9 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } - if (pr.getNodesAccessPolicy(paranetId) != ParanetLib.NodesAccessPolicy.CURATED) { - ParanetLib.NodesAccessPolicy[] memory expectedAccessPolicies = new ParanetLib.NodesAccessPolicy[](1); - expectedAccessPolicies[0] = ParanetLib.NodesAccessPolicy.CURATED; + if (pr.getNodesAccessPolicy(paranetId) != NODES_ACCESS_POLICY_PERMISSIONED) { + uint8[] memory expectedAccessPolicies = new uint8[](1); + expectedAccessPolicies[0] = NODES_ACCESS_POLICY_PERMISSIONED; revert ParanetLib.InvalidParanetNodesAccessPolicy( expectedAccessPolicies, @@ -373,9 +389,9 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } - if (pr.getNodesAccessPolicy(paranetId) != ParanetLib.NodesAccessPolicy.CURATED) { - ParanetLib.NodesAccessPolicy[] memory expectedAccessPolicies = new ParanetLib.NodesAccessPolicy[](1); - expectedAccessPolicies[0] = ParanetLib.NodesAccessPolicy.CURATED; + if (pr.getNodesAccessPolicy(paranetId) != NODES_ACCESS_POLICY_PERMISSIONED) { + uint8[] memory expectedAccessPolicies = new uint8[](1); + expectedAccessPolicies[0] = NODES_ACCESS_POLICY_PERMISSIONED; revert ParanetLib.InvalidParanetNodesAccessPolicy( expectedAccessPolicies, @@ -429,9 +445,9 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } - if (pr.getNodesAccessPolicy(paranetId) != ParanetLib.NodesAccessPolicy.CURATED) { - ParanetLib.NodesAccessPolicy[] memory expectedAccessPolicies = new ParanetLib.NodesAccessPolicy[](1); - expectedAccessPolicies[0] = ParanetLib.NodesAccessPolicy.CURATED; + if (pr.getNodesAccessPolicy(paranetId) != NODES_ACCESS_POLICY_PERMISSIONED) { + uint8[] memory expectedAccessPolicies = new uint8[](1); + expectedAccessPolicies[0] = NODES_ACCESS_POLICY_PERMISSIONED; revert ParanetLib.InvalidParanetNodesAccessPolicy( expectedAccessPolicies, @@ -487,9 +503,9 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } - if (pr.getNodesAccessPolicy(paranetId) != ParanetLib.NodesAccessPolicy.CURATED) { - ParanetLib.NodesAccessPolicy[] memory expectedAccessPolicies = new ParanetLib.NodesAccessPolicy[](1); - expectedAccessPolicies[0] = ParanetLib.NodesAccessPolicy.CURATED; + if (pr.getNodesAccessPolicy(paranetId) != NODES_ACCESS_POLICY_PERMISSIONED) { + uint8[] memory expectedAccessPolicies = new uint8[](1); + expectedAccessPolicies[0] = NODES_ACCESS_POLICY_PERMISSIONED; revert ParanetLib.InvalidParanetNodesAccessPolicy( expectedAccessPolicies, @@ -719,9 +735,9 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } - if (pr.getMinersAccessPolicy(paranetId) != ParanetLib.MinersAccessPolicy.CURATED) { - ParanetLib.MinersAccessPolicy[] memory expectedAccessPolicies = new ParanetLib.MinersAccessPolicy[](1); - expectedAccessPolicies[0] = ParanetLib.MinersAccessPolicy.CURATED; + if (pr.getMinersAccessPolicy(paranetId) != MINERS_ACCESS_POLICY_PERMISSIONED) { + uint8[] memory expectedAccessPolicies = new uint8[](1); + expectedAccessPolicies[0] = MINERS_ACCESS_POLICY_PERMISSIONED; revert ParanetLib.InvalidParanetMinersAccessPolicy( expectedAccessPolicies, @@ -767,9 +783,9 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } - if (pr.getMinersAccessPolicy(paranetId) != ParanetLib.MinersAccessPolicy.CURATED) { - ParanetLib.MinersAccessPolicy[] memory expectedAccessPolicies = new ParanetLib.MinersAccessPolicy[](1); - expectedAccessPolicies[0] = ParanetLib.MinersAccessPolicy.CURATED; + if (pr.getMinersAccessPolicy(paranetId) != MINERS_ACCESS_POLICY_PERMISSIONED) { + uint8[] memory expectedAccessPolicies = new uint8[](1); + expectedAccessPolicies[0] = MINERS_ACCESS_POLICY_PERMISSIONED; revert ParanetLib.InvalidParanetMinersAccessPolicy( expectedAccessPolicies, @@ -810,9 +826,9 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } - if (pr.getMinersAccessPolicy(paranetId) != ParanetLib.MinersAccessPolicy.CURATED) { - ParanetLib.MinersAccessPolicy[] memory expectedAccessPolicies = new ParanetLib.MinersAccessPolicy[](1); - expectedAccessPolicies[0] = ParanetLib.MinersAccessPolicy.CURATED; + if (pr.getMinersAccessPolicy(paranetId) != MINERS_ACCESS_POLICY_PERMISSIONED) { + uint8[] memory expectedAccessPolicies = new uint8[](1); + expectedAccessPolicies[0] = MINERS_ACCESS_POLICY_PERMISSIONED; revert ParanetLib.InvalidParanetMinersAccessPolicy( expectedAccessPolicies, @@ -859,9 +875,9 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } - if (pr.getMinersAccessPolicy(paranetId) != ParanetLib.MinersAccessPolicy.CURATED) { - ParanetLib.MinersAccessPolicy[] memory expectedAccessPolicies = new ParanetLib.MinersAccessPolicy[](1); - expectedAccessPolicies[0] = ParanetLib.MinersAccessPolicy.CURATED; + if (pr.getMinersAccessPolicy(paranetId) != MINERS_ACCESS_POLICY_PERMISSIONED) { + uint8[] memory expectedAccessPolicies = new uint8[](1); + expectedAccessPolicies[0] = MINERS_ACCESS_POLICY_PERMISSIONED; revert ParanetLib.InvalidParanetMinersAccessPolicy( expectedAccessPolicies, @@ -916,9 +932,9 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); } - if (pr.getMinersAccessPolicy(paranetId) != ParanetLib.MinersAccessPolicy.CURATED) { - ParanetLib.MinersAccessPolicy[] memory expectedAccessPolicies = new ParanetLib.MinersAccessPolicy[](1); - expectedAccessPolicies[0] = ParanetLib.MinersAccessPolicy.CURATED; + if (pr.getMinersAccessPolicy(paranetId) != MINERS_ACCESS_POLICY_PERMISSIONED) { + uint8[] memory expectedAccessPolicies = new uint8[](1); + expectedAccessPolicies[0] = MINERS_ACCESS_POLICY_PERMISSIONED; revert ParanetLib.InvalidParanetMinersAccessPolicy( expectedAccessPolicies, @@ -1048,16 +1064,16 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); } - ParanetLib.MinersAccessPolicy minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); + uint8 minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); // Check if paranet is curated and if knowledge miner is whitelisted if ( - minersAccessPolicy == ParanetLib.MinersAccessPolicy.CURATED && + minersAccessPolicy == MINERS_ACCESS_POLICY_PERMISSIONED && !pr.isKnowledgeMinerRegistered(paranetId, msg.sender) ) { revert ParanetLib.ParanetCuratedMinerDoesntExist(paranetId, msg.sender); // Should this be done in both cases why would OPEN have separeted logic ??? - } else if (minersAccessPolicy == ParanetLib.MinersAccessPolicy.OPEN) { + } else if (minersAccessPolicy == MINERS_ACCESS_POLICY_OPEN) { // Check if Knowledge Miner has profile // If not: Create a profile if (!paranetKnowledgeMinersRegistry.knowledgeMinerExists(msg.sender)) { @@ -1084,7 +1100,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); } - if (pr.getKnowledgeCollectionsAccessPolicy(paranetId) == ParanetLib.KnowledgeCollectionsAccessPolicy.STAGING) { + if (pr.getKnowledgeCollectionsSubmissionPolicy(paranetId) == KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING) { require( paranetStagingStorage.isKnowledgeCollectionApproved( paranetId, @@ -1138,15 +1154,14 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); } - if (pr.getMinersAccessPolicy(paranetId) == ParanetLib.MinersAccessPolicy.CURATED) { + if (pr.getMinersAccessPolicy(paranetId) == MINERS_ACCESS_POLICY_PERMISSIONED) { require(pr.isKnowledgeMinerRegistered(paranetId, msg.sender), "Knowledge miner is not registered"); } - ParanetLib.KnowledgeCollectionsAccessPolicy knowledgeCollectionsAccessPolicy = pr - .getKnowledgeCollectionsAccessPolicy(paranetId); + uint8 knowledgeCollectionsSubmissionPolicy = pr.getKnowledgeCollectionsSubmissionPolicy(paranetId); require( - knowledgeCollectionsAccessPolicy == ParanetLib.KnowledgeCollectionsAccessPolicy.STAGING, + knowledgeCollectionsSubmissionPolicy == KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, "Paranet does not allow staging of knowledge collections" ); @@ -1186,8 +1201,11 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); } - ParanetLib.MinersAccessPolicy minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); - require(minersAccessPolicy == ParanetLib.MinersAccessPolicy.CURATED, "Paranet does not allow adding curators"); + uint8 knowledgeCollectionsSubmissionPolicy = pr.getKnowledgeCollectionsSubmissionPolicy(paranetId); + require( + knowledgeCollectionsSubmissionPolicy == KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, + "Paranet does not allow adding curators" + ); paranetStagingStorage.addCurator(paranetId, curator); } @@ -1216,8 +1234,11 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); } - ParanetLib.MinersAccessPolicy minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); - require(minersAccessPolicy == ParanetLib.MinersAccessPolicy.CURATED, "Paranet does not allow adding curators"); + uint8 knowledgeCollectionsSubmissionPolicy = pr.getKnowledgeCollectionsSubmissionPolicy(paranetId); + require( + knowledgeCollectionsSubmissionPolicy == KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, + "Paranet does not allow adding curators" + ); paranetStagingStorage.removeCurator(paranetId, curator); } diff --git a/contracts/storage/paranets/ParanetsRegistry.sol b/contracts/storage/paranets/ParanetsRegistry.sol index e38e3305..415cb7ca 100644 --- a/contracts/storage/paranets/ParanetsRegistry.sol +++ b/contracts/storage/paranets/ParanetsRegistry.sol @@ -36,9 +36,9 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { uint256 knowledgeAssetTokenId, string calldata paranetName, string calldata paranetDescription, - ParanetLib.NodesAccessPolicy nodesAccessPolicy, - ParanetLib.MinersAccessPolicy minersAccessPolicy, - ParanetLib.KnowledgeCollectionsAccessPolicy knowledgeColletionsAccessPolicy + uint8 nodesAccessPolicy, + uint8 minersAccessPolicy, + uint8 knowledgeCollectionsSubmissionPolicy ) external onlyContracts returns (bytes32) { bytes32 paranetId = keccak256( abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId, knowledgeAssetTokenId) @@ -53,7 +53,7 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { paranet.description = paranetDescription; paranet.nodesAccessPolicy = nodesAccessPolicy; paranet.minersAccessPolicy = minersAccessPolicy; - paranet.knowledgeCollectionsAccessPolicy = knowledgeColletionsAccessPolicy; + paranet.knowledgeCollectionsSubmissionPolicy = knowledgeCollectionsSubmissionPolicy; paranetIds.push(paranetId); paranetIdsMapping[paranetId] = paranetIds.length - 1; @@ -98,7 +98,7 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { description: paranet.description, nodesAccessPolicy: paranet.nodesAccessPolicy, minersAccessPolicy: paranet.minersAccessPolicy, - knowledgeCollectionsAccessPolicy: paranet.knowledgeCollectionsAccessPolicy, + knowledgeCollectionsSubmissionPolicy: paranet.knowledgeCollectionsSubmissionPolicy, cumulativeKnowledgeValue: paranet.cumulativeKnowledgeValue }); } @@ -127,39 +127,31 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { paranets[paranetId].description = description; } - function getNodesAccessPolicy(bytes32 paranetId) external view returns (ParanetLib.NodesAccessPolicy) { + function getNodesAccessPolicy(bytes32 paranetId) external view returns (uint8) { return paranets[paranetId].nodesAccessPolicy; } - function setNodesAccessPolicy( - bytes32 paranetId, - ParanetLib.NodesAccessPolicy nodesAccessPolicy - ) external onlyContracts { + function setNodesAccessPolicy(bytes32 paranetId, uint8 nodesAccessPolicy) external onlyContracts { paranets[paranetId].nodesAccessPolicy = nodesAccessPolicy; } - function getMinersAccessPolicy(bytes32 paranetId) external view returns (ParanetLib.MinersAccessPolicy) { + function getMinersAccessPolicy(bytes32 paranetId) external view returns (uint8) { return paranets[paranetId].minersAccessPolicy; } - function setMinersAccessPolicy( - bytes32 paranetId, - ParanetLib.MinersAccessPolicy minersAccessPolicy - ) external onlyContracts { + function setMinersAccessPolicy(bytes32 paranetId, uint8 minersAccessPolicy) external onlyContracts { paranets[paranetId].minersAccessPolicy = minersAccessPolicy; } - function getKnowledgeCollectionsAccessPolicy( - bytes32 paranetId - ) external view returns (ParanetLib.KnowledgeCollectionsAccessPolicy) { - return paranets[paranetId].knowledgeCollectionsAccessPolicy; + function getKnowledgeCollectionsSubmissionPolicy(bytes32 paranetId) external view returns (uint8) { + return paranets[paranetId].knowledgeCollectionsSubmissionPolicy; } - function setKnowledgeCollectionsAccessPolicy( + function setKnowledgeCollectionsSubmissionPolicy( bytes32 paranetId, - ParanetLib.KnowledgeCollectionsAccessPolicy knowledgeCollectionsAccessPolicy + uint8 knowledgeCollectionsSubmissionPolicy ) external onlyContracts { - paranets[paranetId].knowledgeCollectionsAccessPolicy = knowledgeCollectionsAccessPolicy; + paranets[paranetId].knowledgeCollectionsSubmissionPolicy = knowledgeCollectionsSubmissionPolicy; } function addNodeJoinRequest( From 4f737aebf23fa82c7eb4621890ab64aaeb2babb8 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Thu, 13 Feb 2025 17:26:03 +0100 Subject: [PATCH 088/153] Reduce factory size --- .../paranets/ParanetIncentivesPoolFactory.sol | 141 +++++++----------- .../storage/paranets/ParanetsRegistry.sol | 13 +- 2 files changed, 63 insertions(+), 91 deletions(-) diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index ad528cc1..4b882c50 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -11,26 +11,16 @@ import {ContractStatus} from "../abstract/ContractStatus.sol"; import {IInitializable} from "../interfaces/IInitializable.sol"; import {INamed} from "../interfaces/INamed.sol"; import {IVersioned} from "../interfaces/IVersioned.sol"; -import {ParanetLib} from "../libraries/ParanetLib.sol"; contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IInitializable { event ParanetIncentivesPoolDeployed( - address indexed paranetKCStorageContract, - uint256 indexed paranetKCTokenId, - uint256 indexed paranetKATokenId, + bytes32 indexed paranetId, address storageAddress, address poolAddress, - string incentivesPoolName, address rewardTokenAddress ); - event ParanetIncentivesPoolRedeployed( - address indexed paranetKCStorageContract, - uint256 indexed paranetKCTokenId, - uint256 indexed paranetKATokenId, - address storageAddress, - address oldPoolAddress, - address newPoolAddress - ); + + event ParanetIncentivesPoolRedeployed(bytes32 indexed paranetId, address storageAddress, address newPoolAddress); string private constant _NAME = "ParanetIncentivesPoolFactory"; string private constant _VERSION = "1.0.0"; @@ -74,58 +64,27 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn uint16 paranetIncentivizationProposalVotersRewardPercentage, string calldata incentivesPoolName, address rewardTokenAddress - ) - external - onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) - returns (address poolAddress, address storageAddress) - { - Hub h = hub; + ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { + bytes32 paranetId = _computeParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); - - require(pr.paranetExists(paranetId), "Paranet doesn't exist"); - require(pr.hasIncentivesPoolByName(paranetId, incentivesPoolName), "Incentives pool already exists"); + require(pr.paranetExists(paranetId)); + require(pr.hasIncentivesPoolByName(paranetId, incentivesPoolName)); ParanetNeuroIncentivesPoolStorage storage_ = new ParanetNeuroIncentivesPoolStorage( - address(h), + address(hub), rewardTokenAddress, paranetId, paranetOperatorRewardPercentage, paranetIncentivizationProposalVotersRewardPercentage ); - storageAddress = address(storage_); + address storageAddress = address(storage_); - ParanetNeuroIncentivesPool pool = new ParanetNeuroIncentivesPool( - address(h), - h.getContractAddress("ParanetKnowledgeMinersRegistry"), - storageAddress, - tracToNeuroEmissionMultiplier - ); - poolAddress = address(pool); + address poolAddress = _deployNeuroIncentivesPool(storageAddress, tracToNeuroEmissionMultiplier, storage_); - // Initialize storage contract storage_.initialize(); - storage_.setParanetNeuroIncentivesPool(poolAddress); - pr.addIncentivesPool( - paranetId, - ParanetLib.IncentivesPool({ - name: incentivesPoolName, - storageAddr: storageAddress, - rewardTokenAddress: rewardTokenAddress - }) - ); - - emit ParanetIncentivesPoolDeployed( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - storageAddress, - poolAddress, - incentivesPoolName, - rewardTokenAddress - ); + paranetsRegistry.addIncentivesPool(paranetId, incentivesPoolName, storageAddress, rewardTokenAddress); - return (poolAddress, storageAddress); + emit ParanetIncentivesPoolDeployed(paranetId, storageAddress, poolAddress, rewardTokenAddress); } function redeployNeuroIncentivesPool( @@ -133,53 +92,60 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn uint256 paranetKCTokenId, uint256 paranetKATokenId, address storageAddress - ) - external - onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) - returns (address newPoolAddress) - { - Hub h = hub; - ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); + ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { + bytes32 paranetId = _computeParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - require(pr.paranetExists(paranetId), "Paranet doesn't exist"); - require(pr.hasIncentivesPoolByStorageAddress(paranetId, storageAddress), "Incentives pool doesn't exist"); + ParanetsRegistry pr = paranetsRegistry; + require(pr.paranetExists(paranetId)); + require(pr.hasIncentivesPoolByStorageAddress(paranetId, storageAddress)); - ParanetNeuroIncentivesPoolStorage storage_ = ParanetNeuroIncentivesPoolStorage(payable(storageAddress)); - require(storage_.paranetId() == paranetId, "Storage paranet ID mismatch"); + ParanetNeuroIncentivesPoolStorage storage_ = ParanetNeuroIncentivesPoolStorage((storageAddress)); + require(storage_.paranetId() == paranetId); address oldPoolAddress = storage_.paranetNeuroIncentivesPoolAddress(); - ParanetNeuroIncentivesPool oldPool = ParanetNeuroIncentivesPool(oldPoolAddress); - uint256 tracToNeuroEmissionMultiplier = oldPool.getEffectiveNeuroEmissionMultiplier(block.timestamp); - - ParanetNeuroIncentivesPool newPool = new ParanetNeuroIncentivesPool( - address(h), - h.getContractAddress("ParanetKnowledgeMinersRegistry"), - storageAddress, - tracToNeuroEmissionMultiplier - ); - newPoolAddress = address(newPool); + uint256 tracToNeuroEmissionMultiplier = ParanetNeuroIncentivesPool(oldPoolAddress) + .getEffectiveNeuroEmissionMultiplier(block.timestamp); + + address newPoolAddress = _deployNeuroIncentivesPool(storageAddress, tracToNeuroEmissionMultiplier, storage_); - storage_.setParanetNeuroIncentivesPool(newPoolAddress); + emit ParanetIncentivesPoolRedeployed(paranetId, storageAddress, newPoolAddress); + } - emit ParanetIncentivesPoolRedeployed( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - storageAddress, - oldPoolAddress, - newPoolAddress + function _deployNeuroIncentivesPool( + address storageAddress, + uint256 tracToNeuroEmissionMultiplier, + ParanetNeuroIncentivesPoolStorage poolStorage + ) internal returns (address) { + address addr = address( + new ParanetNeuroIncentivesPool( + address(hub), + hub.getContractAddress("ParanetKnowledgeMinersRegistry"), + storageAddress, + tracToNeuroEmissionMultiplier + ) ); + poolStorage.setParanetNeuroIncentivesPool(addr); - return newPoolAddress; + return addr; + } + + function _computeParanetId( + address knowledgeCollectionStorageContract, + uint256 knowledgeCollectionTokenId, + uint256 knowledgeAssetTokenId + ) internal pure returns (bytes32) { + return + keccak256( + abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId, knowledgeAssetTokenId) + ); } function _checkKnowledgeAssetOwner( address knowledgeCollectionStorageContractAddress, uint256 knowledgeCollectionId, uint256 knowledgeAssetId - ) internal virtual { - require(hub.isAssetStorage(knowledgeCollectionStorageContractAddress), "Given address isn't KC Storage"); + ) internal view { + require(hub.isAssetStorage(knowledgeCollectionStorageContractAddress)); KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage( knowledgeCollectionStorageContractAddress @@ -189,7 +155,6 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn knowledgeCollectionStorage.knowledgeCollectionMaxSize() + knowledgeAssetId; - uint256 ownedCountInRange = knowledgeCollectionStorage.balanceOf(msg.sender, startTokenId, startTokenId + 1); - require(ownedCountInRange == 1, "Caller isn't the owner of the KA"); + require(knowledgeCollectionStorage.balanceOf(msg.sender, startTokenId, startTokenId + 1) == 1); } } diff --git a/contracts/storage/paranets/ParanetsRegistry.sol b/contracts/storage/paranets/ParanetsRegistry.sol index e38e3305..734a00ea 100644 --- a/contracts/storage/paranets/ParanetsRegistry.sol +++ b/contracts/storage/paranets/ParanetsRegistry.sol @@ -252,13 +252,20 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { function addIncentivesPool( bytes32 paranetId, - ParanetLib.IncentivesPool calldata incentivesPool + string calldata incentivesPoolName, + address storageAddress, + address rewardTokenAddress ) external onlyContracts { require(paranets[paranetId].incentivesPools.length < _MAX_INCENTIVES_POOLS, "Max incentives pools reached"); - paranets[paranetId].incentivesPoolsByNameIndexes[incentivesPool.name] = paranets[paranetId] + ParanetLib.IncentivesPool memory incentivesPool = ParanetLib.IncentivesPool({ + name: incentivesPoolName, + storageAddr: storageAddress, + rewardTokenAddress: rewardTokenAddress + }); + paranets[paranetId].incentivesPoolsByNameIndexes[incentivesPoolName] = paranets[paranetId] .incentivesPools .length; - paranets[paranetId].incentivesPoolsByStorageAddressIndexes[incentivesPool.storageAddr] = paranets[paranetId] + paranets[paranetId].incentivesPoolsByStorageAddressIndexes[storageAddress] = paranets[paranetId] .incentivesPools .length; paranets[paranetId].incentivesPools.push(incentivesPool); From cf2863aa5b11d85659c4bef588d15701b2da8bc1 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 13 Feb 2025 18:08:31 +0100 Subject: [PATCH 089/153] Update helper functions for easier setup --- test/helpers/constants.ts | 14 ++++++- test/helpers/kc-helpers.ts | 73 ++++++++++++++++++++++---------- test/helpers/paranet-helpers.ts | 74 +++++++++++++++++++++++++++++++++ test/helpers/profile-helpers.ts | 18 +++----- test/helpers/setup-helpers.ts | 22 ++++++++++ test/helpers/types.ts | 14 +++++++ 6 files changed, 180 insertions(+), 35 deletions(-) create mode 100644 test/helpers/paranet-helpers.ts create mode 100644 test/helpers/setup-helpers.ts create mode 100644 test/helpers/types.ts diff --git a/test/helpers/constants.ts b/test/helpers/constants.ts index 4b51c90c..850e1561 100644 --- a/test/helpers/constants.ts +++ b/test/helpers/constants.ts @@ -5,4 +5,16 @@ const ADMIN_KEY = 1; const OPERATIONAL_KEY = 2; const ECDSA = 1; -export { ADMIN_KEY, ECDSA, OPERATIONAL_KEY, ZERO_ADDRESS, ZERO_BYTES32 }; +const ACCESS_POLICIES = { + OPEN: 0, + CURATED: 1, +}; + +export { + ADMIN_KEY, + ECDSA, + OPERATIONAL_KEY, + ZERO_ADDRESS, + ZERO_BYTES32, + ACCESS_POLICIES, +}; diff --git a/test/helpers/kc-helpers.ts b/test/helpers/kc-helpers.ts index 83958f0f..dc6c41de 100644 --- a/test/helpers/kc-helpers.ts +++ b/test/helpers/kc-helpers.ts @@ -1,22 +1,9 @@ import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; import { ethers, getBytes } from 'ethers'; -import { NodeAccounts } from './profile-helpers'; -import { KnowledgeCollection, Token } from '../../typechain'; - -export type ValidatorInfo = { - identityId: number; - r: string; - vs: string; -}; - -export type KCSignaturesData = { - merkleRoot: string; - publisherR: string; - publisherVS: string; - receiverRs: string[]; - receiverVSs: string[]; -}; +import { createProfile, createProfiles } from './profile-helpers'; +import { KCSignaturesData, NodeAccounts } from './types'; +import { KnowledgeCollection, Token, Profile } from '../../typechain'; export async function signMessage( signer: SignerWithAddress, @@ -70,12 +57,14 @@ export async function getKCSignaturesData( } export async function createKnowledgeCollection( - KnowledgeCollection: KnowledgeCollection, - Token: Token, kcCreator: SignerWithAddress, publisherIdentityId: number, receiversIdentityIds: number[], signaturesData: KCSignaturesData, + contracts: { + KnowledgeCollection: KnowledgeCollection; + Token: Token; + }, publishOperationId: string = 'test-operation-id', knowledgeAssetsAmount: number = 10, byteSize: number = 1000, @@ -85,13 +74,13 @@ export async function createKnowledgeCollection( paymaster: string = ethers.ZeroAddress, ) { // Approve tokens - await Token.connect(kcCreator).increaseAllowance( - KnowledgeCollection.getAddress(), + await contracts.Token.connect(kcCreator).increaseAllowance( + contracts.KnowledgeCollection.getAddress(), tokenAmount, ); // Create knowledge collection - const tx = await KnowledgeCollection.connect( + const tx = await contracts.KnowledgeCollection.connect( kcCreator, ).createKnowledgeCollection( publishOperationId, @@ -115,3 +104,45 @@ export async function createKnowledgeCollection( return { tx, receipt, collectionId }; } + +export async function createProfilesAndKC( + kcCreator: SignerWithAddress, + publishingNode: NodeAccounts, + receivingNodes: NodeAccounts[], + contracts: { + Profile: Profile; + KnowledgeCollection: KnowledgeCollection; + Token: Token; + }, +) { + const { identityId: publishingNodeIdentityId } = await createProfile( + contracts.Profile, + publishingNode, + ); + const receivingNodesIdentityIds = ( + await createProfiles(contracts.Profile, receivingNodes) + ).map((p) => p.identityId); + + // Create knowledge collection + const signaturesData = await getKCSignaturesData( + publishingNode, + publishingNodeIdentityId, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + contracts, + ); + + return { + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + kcCreator, + collectionId, + }; +} diff --git a/test/helpers/paranet-helpers.ts b/test/helpers/paranet-helpers.ts new file mode 100644 index 00000000..debb58f2 --- /dev/null +++ b/test/helpers/paranet-helpers.ts @@ -0,0 +1,74 @@ +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { ethers } from 'ethers'; + +import { ACCESS_POLICIES } from './constants'; +import { createProfilesAndKC } from './kc-helpers'; +import { NodeAccounts } from './types'; +import { + Profile, + KnowledgeCollection, + Token, + KnowledgeCollectionStorage, + Paranet, +} from '../../typechain'; + +export async function setupParanet( + kcCreator: SignerWithAddress, + publishingNode: NodeAccounts, + receivingNodes: NodeAccounts[], + contracts: { + Paranet: Paranet; + Profile: Profile; + Token: Token; + KnowledgeCollection: KnowledgeCollection; + KnowledgeCollectionStorage: KnowledgeCollectionStorage; + }, + paranetName: string = 'Test Paranet', + paranetDescription: string = 'Test Paranet Description', + nodesAccessPolicy: number = ACCESS_POLICIES.OPEN, + minersAccessPolicy: number = ACCESS_POLICIES.OPEN, +) { + const { publishingNodeIdentityId, receivingNodesIdentityIds, collectionId } = + await createProfilesAndKC( + kcCreator, + publishingNode, + receivingNodes, + contracts, + ); + + // Register paranet + const paranetKCStorageContract = + await contracts.KnowledgeCollectionStorage.getAddress(); + const paranetKATokenId = 1; + + await contracts.Paranet.connect(kcCreator).registerParanet( + paranetKCStorageContract, + collectionId, + paranetKATokenId, + paranetName, + paranetDescription, + nodesAccessPolicy, + minersAccessPolicy, + ); + + return { + publishingNode, + receivingNodes, + publishingNodeIdentityId, + receivingNodesIdentityIds, + paranetOwner: kcCreator, + paranetKCStorageContract, + paranetKCTokenId: collectionId, + paranetKATokenId, + paranetName, + paranetDescription, + nodesAccessPolicy, + minersAccessPolicy, + paranetId: ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256', 'uint256'], + [paranetKCStorageContract, collectionId, paranetKATokenId], + ), + ), + }; +} diff --git a/test/helpers/profile-helpers.ts b/test/helpers/profile-helpers.ts index d8c75ed2..c262a39f 100644 --- a/test/helpers/profile-helpers.ts +++ b/test/helpers/profile-helpers.ts @@ -1,22 +1,14 @@ import { randomBytes } from 'crypto'; -import { HardhatEthersSigner as SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; - +import { NodeAccounts } from './types'; import { Profile } from '../../typechain'; -export type NodeAccounts = { - admin: SignerWithAddress; - operational: SignerWithAddress; -}; - export async function createProfile( - ProfileContract: Profile, + Profile: Profile, nodeAccounts: NodeAccounts, ) { const nodeId = '0x' + randomBytes(32).toString('hex'); - const tx = await ProfileContract.connect( - nodeAccounts.operational, - ).createProfile( + const tx = await Profile.connect(nodeAccounts.operational).createProfile( nodeAccounts.admin.address, [], `Node ${Math.floor(Math.random() * 1000)}`, @@ -29,13 +21,13 @@ export async function createProfile( } export async function createProfiles( - ProfileContract: Profile, + Profile: Profile, nodeAccounts: NodeAccounts[], ): Promise<{ nodeId: string; identityId: number }[]> { const profiles: { nodeId: string; identityId: number }[] = []; for (let i = 0; i < nodeAccounts.length; i++) { const { nodeId, identityId } = await createProfile( - ProfileContract, + Profile, nodeAccounts[i], ); profiles.push({ nodeId, identityId }); diff --git a/test/helpers/setup-helpers.ts b/test/helpers/setup-helpers.ts new file mode 100644 index 00000000..7cf5c109 --- /dev/null +++ b/test/helpers/setup-helpers.ts @@ -0,0 +1,22 @@ +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; + +export function getDefaultPublishingNode(accounts: SignerWithAddress[]) { + return { + admin: accounts[1], + operational: accounts[2], + }; +} + +export function getDefaultReceivingNodes( + accounts: SignerWithAddress[], + receivingNodesNumber: number = 3, +) { + return Array.from({ length: receivingNodesNumber }, (_, i) => ({ + admin: accounts[3 + i], + operational: accounts[4 + i], + })); +} + +export function getDefaultKCCreator(accounts: SignerWithAddress[]) { + return accounts[9]; +} diff --git a/test/helpers/types.ts b/test/helpers/types.ts new file mode 100644 index 00000000..5ec02048 --- /dev/null +++ b/test/helpers/types.ts @@ -0,0 +1,14 @@ +import { HardhatEthersSigner as SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; + +export type NodeAccounts = { + admin: SignerWithAddress; + operational: SignerWithAddress; +}; + +export type KCSignaturesData = { + merkleRoot: string; + publisherR: string; + publisherVS: string; + receiverRs: string[]; + receiverVSs: string[]; +}; From 2110a562d0077c8291fbc4ce35506eaf011351b3 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 13 Feb 2025 18:09:18 +0100 Subject: [PATCH 090/153] Update KC tests --- test/unit/KnowledgeCollection.test.ts | 90 +++++++-------------------- 1 file changed, 22 insertions(+), 68 deletions(-) diff --git a/test/unit/KnowledgeCollection.test.ts b/test/unit/KnowledgeCollection.test.ts index 5f4acfbb..f80739cd 100644 --- a/test/unit/KnowledgeCollection.test.ts +++ b/test/unit/KnowledgeCollection.test.ts @@ -22,9 +22,16 @@ import { } from '../../typechain'; import { createKnowledgeCollection, + createProfilesAndKC, getKCSignaturesData, } from '../helpers/kc-helpers'; -import { createProfile, createProfiles } from '../helpers/profile-helpers'; +import { createProfile } from '../helpers/profile-helpers'; +import { + getDefaultPublishingNode, + getDefaultReceivingNodes, + getDefaultKCCreator, +} from '../helpers/setup-helpers'; + type KnowledgeCollectionFixture = { accounts: SignerWithAddress[]; KnowledgeCollection: KnowledgeCollection; @@ -139,52 +146,17 @@ describe('@unit KnowledgeCollection', () => { }); it('Should create a knowledge collection successfully', async () => { - const publishingNode = { - admin: accounts[1], - operational: accounts[2], - }; - const receivingNodes = [ - { - admin: accounts[3], - operational: accounts[4], - }, - { - admin: accounts[5], - operational: accounts[6], - }, - { - admin: accounts[7], - operational: accounts[8], - }, - ]; - - const kcCreator = accounts[9]; // knowledge collection creator - - const { identityId: publisherIdentityId } = await createProfile( - Profile, - publishingNode, - ); - - const receiversIdentityIds = ( - await createProfiles(Profile, receivingNodes) - ).map((p) => p.identityId); - - const signaturesData = await getKCSignaturesData( - publishingNode, - publisherIdentityId, - receivingNodes, - ); + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); - const { tx, collectionId } = await createKnowledgeCollection( - KnowledgeCollection, - Token, - kcCreator, - publisherIdentityId, - receiversIdentityIds, - signaturesData, - ); + const { receivingNodesIdentityIds, collectionId } = + await createProfilesAndKC(kcCreator, publishingNode, receivingNodes, { + Profile, + KnowledgeCollection, + Token, + }); - await expect(tx).to.not.be.reverted; expect(collectionId).to.equal(1); // Verify knowledge collection was created @@ -193,7 +165,7 @@ describe('@unit KnowledgeCollection', () => { collectionId, ); - expect(metadata[0][0].length).to.equal(3); // merkle roots + expect(metadata[0][0].length).to.equal(receivingNodesIdentityIds.length); // merkle roots expect(metadata[1].length).to.equal(0); // burned expect(metadata[2]).to.equal(10); // minted expect(metadata[3]).to.equal(1000); // byteSize @@ -204,26 +176,9 @@ describe('@unit KnowledgeCollection', () => { }); it('Should revert if insufficient signatures provided', async () => { - const publishingNode = { - admin: accounts[1], - operational: accounts[2], - }; - const receivingNodes = [ - { - admin: accounts[3], - operational: accounts[4], - }, - { - admin: accounts[5], - operational: accounts[6], - }, - { - admin: accounts[7], - operational: accounts[8], - }, - ]; - - const kcCreator = accounts[9]; // knowledge collection creator + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); const { identityId: publisherIdentityId } = await createProfile( Profile, @@ -243,12 +198,11 @@ describe('@unit KnowledgeCollection', () => { await expect( createKnowledgeCollection( - KnowledgeCollection, - Token, kcCreator, publisherIdentityId, receiversIdentityIds, signaturesData, + { KnowledgeCollection, Token }, ), ).to.be.revertedWithCustomError( KnowledgeCollection, From fd8fc065e96133ecd6d7314254d43f2e84a8b74d Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 13 Feb 2025 18:09:54 +0100 Subject: [PATCH 091/153] Add incentives pool deployment test and update helpers --- test/integration/Paranet.test.ts | 163 +++++++++++-------------------- 1 file changed, 58 insertions(+), 105 deletions(-) diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index fe6a3c24..7c306ccb 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -17,13 +17,14 @@ import { Token, Hub, EpochStorage, - ParanetNeuroIncentivesPool, + ParanetNeuroIncentivesPoolStorage, } from '../../typechain'; +import { setupParanet } from '../helpers/paranet-helpers'; import { - createKnowledgeCollection, - getKCSignaturesData, -} from '../helpers/kc-helpers'; -import { createProfile, createProfiles } from '../helpers/profile-helpers'; + getDefaultPublishingNode, + getDefaultReceivingNodes, + getDefaultKCCreator, +} from '../helpers/setup-helpers'; // Fixture containing all contracts and accounts needed to test Paranet type ParanetFixture = { @@ -120,93 +121,6 @@ describe('@unit Paranet', () => { }; } - async function createAndRegisterParanet() { - // Create profiles for admin, publisher and validators - const publishingNode = { - admin: accounts[1], - operational: accounts[2], - }; - const receivingNodes = [ - { - admin: accounts[3], - operational: accounts[4], - }, - { - admin: accounts[5], - operational: accounts[6], - }, - { - admin: accounts[7], - operational: accounts[8], - }, - ]; - - const kcCreator = accounts[9]; // knowledge collection creator and paranet owner - - const { identityId: publishingNodeIdentityId } = await createProfile( - Profile, - publishingNode, - ); - const receivingNodesIdentityIds = ( - await createProfiles(Profile, receivingNodes) - ).map((p) => p.identityId); - - // Create knowledge collection - const signaturesData = await getKCSignaturesData( - publishingNode, - publishingNodeIdentityId, - receivingNodes, - ); - const { collectionId } = await createKnowledgeCollection( - KnowledgeCollection, - Token, - kcCreator, - publishingNodeIdentityId, - receivingNodesIdentityIds, - signaturesData, - ); - - // Register paranet - const paranetKCStorageContract = - await KnowledgeCollectionStorage.getAddress(); - const paranetKATokenId = 1; - const paranetName = 'Test Paranet'; - const paranetDescription = 'Test Paranet Description'; - const nodesAccessPolicy = 0; // OPEN - const minersAccessPolicy = 0; // OPEN - - await Paranet.connect(kcCreator).registerParanet( - paranetKCStorageContract, - collectionId, - paranetKATokenId, - paranetName, - paranetDescription, - nodesAccessPolicy, - minersAccessPolicy, - ); - - return { - publishingNode, - receivingNodes, - publishingNodeIdentityId, - receivingNodesIdentityIds, - paranetOwner: kcCreator, - paranetKCStorageContract, - paranetKCTokenId: collectionId, - paranetKATokenId, - paranetName, - paranetDescription, - nodesAccessPolicy, - minersAccessPolicy, - paranetId: ethers.keccak256( - ethers.solidityPacked( - ['address', 'uint256', 'uint256'], - [paranetKCStorageContract, collectionId, paranetKATokenId], - ), - ), - }; - } - // Before each test, deploy all contracts and necessary accounts. These variables can be used in the tests beforeEach(async () => { ({ @@ -226,6 +140,10 @@ describe('@unit Paranet', () => { describe('Paranet Registration', () => { it('Should register a paranet successfully', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const { paranetOwner, paranetId, @@ -236,7 +154,13 @@ describe('@unit Paranet', () => { paranetDescription, nodesAccessPolicy, minersAccessPolicy, - } = await createAndRegisterParanet(); + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); // eslint-disable-next-line @typescript-eslint/no-unused-expressions expect(await ParanetsRegistry.paranetExists(paranetId)).to.be.true; @@ -272,13 +196,23 @@ describe('@unit Paranet', () => { describe('Paranet Incentives Pool', () => { it('Should deploy incentives pool successfully', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const { paranetId, paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, paranetOwner, - } = await createAndRegisterParanet(); + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); const tracToNeuroEmissionMultiplier = ethers.parseUnits('1', 12); // 1 NEURO per 1 TRAC const operatorRewardPercentage = 1000; // 10% @@ -287,13 +221,14 @@ describe('@unit Paranet', () => { const tx = await ParanetIncentivesPoolFactory.connect( paranetOwner, ).deployNeuroIncentivesPool( - true, // isNativeReward paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, tracToNeuroEmissionMultiplier, operatorRewardPercentage, votersRewardPercentage, + 'Neuroweb', + await Token.getAddress(), ); const receipt = await tx.wait(); @@ -301,25 +236,43 @@ describe('@unit Paranet', () => { (log) => log.topics[0] === ParanetIncentivesPoolFactory.interface.getEvent( - 'ParanetIncetivesPoolDeployed', + 'ParanetIncentivesPoolDeployed', ).topicHash, ) as EventLog; expect(event?.args[0]).to.equal(paranetKCStorageContract); expect(event?.args[1]).to.equal(paranetKCTokenId); - expect(event?.args[2][0]).to.equal('Neuroweb'); + expect(event?.args[2]).to.equal(paranetKATokenId); + expect(event?.args[5]).to.equal('Neuroweb'); + expect(event?.args[6]).to.equal(await Token.getAddress()); - const poolAddress = await ParanetsRegistry.getIncentivesPoolAddress( + let incentivesPool = await ParanetsRegistry.getIncentivesPoolByPoolName( paranetId, - 'Neuroweb', + event?.args[5], + ); + expect(incentivesPool.storageAddr).to.equal(event?.args[3]); + expect(incentivesPool.rewardTokenAddress).to.equal( + await Token.getAddress(), + ); + + incentivesPool = await ParanetsRegistry.getIncentivesPoolByStorageAddress( + paranetId, + event?.args[3], + ); + expect(incentivesPool.name).to.equal(event?.args[5]); + expect(incentivesPool.rewardTokenAddress).to.equal( + await Token.getAddress(), ); - expect(poolAddress).to.equal(event?.args[2][1]); - const pool = (await hre.ethers.getContractAt( - 'ParanetNeuroIncentivesPool', - poolAddress, - )) as ParanetNeuroIncentivesPool; - expect(await pool.parentParanetId()).to.equal(paranetId); + // validate incentives pool address + const incentivesPoolStorage = (await hre.ethers.getContractAt( + 'ParanetNeuroIncentivesPoolStorage', + event?.args[3], + )) as ParanetNeuroIncentivesPoolStorage; + expect( + await incentivesPoolStorage.paranetNeuroIncentivesPoolAddress(), + ).to.equal(event?.args[4]); + expect(await incentivesPoolStorage.paranetId()).to.equal(paranetId); }); }); }); From 0cdd976b1e95a79097c63a0c9f0becfdba027866 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 14 Feb 2025 08:59:13 +0100 Subject: [PATCH 092/153] Add ParanetIncentivesPoolFactoryHelper --- .../paranets/ParanetIncentivesPoolFactory.sol | 37 +++++++-------- .../ParanetIncentivesPoolFactoryHelper.sol | 46 +++++++++++++++++++ 2 files changed, 62 insertions(+), 21 deletions(-) create mode 100644 contracts/paranets/ParanetIncentivesPoolFactoryHelper.sol diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index 4b882c50..84b1cf2f 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -6,6 +6,7 @@ import {Hub} from "../storage/Hub.sol"; import {ParanetsRegistry} from "../storage/paranets/ParanetsRegistry.sol"; import {ParanetNeuroIncentivesPool} from "./ParanetNeuroIncentivesPool.sol"; import {ParanetNeuroIncentivesPoolStorage} from "./ParanetNeuroIncentivesPoolStorage.sol"; +import {ParanetIncentivesPoolFactoryHelper} from "./ParanetIncentivesPoolFactoryHelper.sol"; import {KnowledgeCollectionStorage} from "../storage/KnowledgeCollectionStorage.sol"; import {ContractStatus} from "../abstract/ContractStatus.sol"; import {IInitializable} from "../interfaces/IInitializable.sol"; @@ -26,6 +27,7 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn string private constant _VERSION = "1.0.0"; ParanetsRegistry public paranetsRegistry; + ParanetIncentivesPoolFactoryHelper public paranetIncentivesPoolFactoryHelper; // solhint-disable-next-line no-empty-blocks constructor(address hubAddress) ContractStatus(hubAddress) {} @@ -45,6 +47,9 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn function initialize() public onlyHub { paranetsRegistry = ParanetsRegistry(hub.getContractAddress("ParanetsRegistry")); + paranetIncentivesPoolFactoryHelper = ParanetIncentivesPoolFactoryHelper( + hub.getContractAddress("ParanetIncentivesPoolFactoryHelper") + ); } function name() external pure virtual override returns (string memory) { @@ -79,7 +84,11 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn ); address storageAddress = address(storage_); - address poolAddress = _deployNeuroIncentivesPool(storageAddress, tracToNeuroEmissionMultiplier, storage_); + address poolAddress = paranetIncentivesPoolFactoryHelper.deployNeuroIncentivesPool( + storageAddress, + tracToNeuroEmissionMultiplier, + address(storage_) + ); storage_.initialize(); paranetsRegistry.addIncentivesPool(paranetId, incentivesPoolName, storageAddress, rewardTokenAddress); @@ -99,34 +108,20 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn require(pr.paranetExists(paranetId)); require(pr.hasIncentivesPoolByStorageAddress(paranetId, storageAddress)); - ParanetNeuroIncentivesPoolStorage storage_ = ParanetNeuroIncentivesPoolStorage((storageAddress)); + ParanetNeuroIncentivesPoolStorage storage_ = ParanetNeuroIncentivesPoolStorage(payable(storageAddress)); require(storage_.paranetId() == paranetId); address oldPoolAddress = storage_.paranetNeuroIncentivesPoolAddress(); uint256 tracToNeuroEmissionMultiplier = ParanetNeuroIncentivesPool(oldPoolAddress) .getEffectiveNeuroEmissionMultiplier(block.timestamp); - address newPoolAddress = _deployNeuroIncentivesPool(storageAddress, tracToNeuroEmissionMultiplier, storage_); - - emit ParanetIncentivesPoolRedeployed(paranetId, storageAddress, newPoolAddress); - } - - function _deployNeuroIncentivesPool( - address storageAddress, - uint256 tracToNeuroEmissionMultiplier, - ParanetNeuroIncentivesPoolStorage poolStorage - ) internal returns (address) { - address addr = address( - new ParanetNeuroIncentivesPool( - address(hub), - hub.getContractAddress("ParanetKnowledgeMinersRegistry"), - storageAddress, - tracToNeuroEmissionMultiplier - ) + address newPoolAddress = paranetIncentivesPoolFactoryHelper.deployNeuroIncentivesPool( + storageAddress, + tracToNeuroEmissionMultiplier, + address(storage_) ); - poolStorage.setParanetNeuroIncentivesPool(addr); - return addr; + emit ParanetIncentivesPoolRedeployed(paranetId, storageAddress, newPoolAddress); } function _computeParanetId( diff --git a/contracts/paranets/ParanetIncentivesPoolFactoryHelper.sol b/contracts/paranets/ParanetIncentivesPoolFactoryHelper.sol new file mode 100644 index 00000000..f9be07ab --- /dev/null +++ b/contracts/paranets/ParanetIncentivesPoolFactoryHelper.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.20; + +import {Hub} from "../storage/Hub.sol"; +import {ParanetNeuroIncentivesPool} from "./ParanetNeuroIncentivesPool.sol"; +import {ParanetNeuroIncentivesPoolStorage} from "./ParanetNeuroIncentivesPoolStorage.sol"; +import {KnowledgeCollectionStorage} from "../storage/KnowledgeCollectionStorage.sol"; +import {ContractStatus} from "../abstract/ContractStatus.sol"; +import {IInitializable} from "../interfaces/IInitializable.sol"; +import {INamed} from "../interfaces/INamed.sol"; +import {IVersioned} from "../interfaces/IVersioned.sol"; + +contract ParanetIncentivesPoolFactoryHelper is INamed, IVersioned, ContractStatus { + string private constant _NAME = "ParanetIncentivesPoolFactoryHelper"; + string private constant _VERSION = "1.0.0"; + + // solhint-disable-next-line no-empty-blocks + constructor(address hubAddress) ContractStatus(hubAddress) {} + + function name() external pure virtual override returns (string memory) { + return _NAME; + } + + function version() external pure virtual override returns (string memory) { + return _VERSION; + } + + function deployNeuroIncentivesPool( + address storageAddress, + uint256 tracToNeuroEmissionMultiplier, + address poolStorageAddress + ) external onlyContracts returns (address) { + address addr = address( + new ParanetNeuroIncentivesPool( + address(hub), + hub.getContractAddress("ParanetKnowledgeMinersRegistry"), + storageAddress, + tracToNeuroEmissionMultiplier + ) + ); + ParanetNeuroIncentivesPoolStorage(payable(poolStorageAddress)).setParanetNeuroIncentivesPool(addr); + + return addr; + } +} From 1f3759f42dea4139b34e0e7206ced327c8127fe4 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 14 Feb 2025 10:00:15 +0100 Subject: [PATCH 093/153] Makde curators discoverable --- .../paranets/ParanetStagingStorage.sol | 44 +++++++++++++++---- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/contracts/storage/paranets/ParanetStagingStorage.sol b/contracts/storage/paranets/ParanetStagingStorage.sol index 48e7d8b0..d9f83500 100644 --- a/contracts/storage/paranets/ParanetStagingStorage.sol +++ b/contracts/storage/paranets/ParanetStagingStorage.sol @@ -21,6 +21,12 @@ contract ParanetStagingStorage is INamed, IVersioned, HubDependent { event CuratorAdded(bytes32 indexed paranetId, address indexed curator); event CuratorRemoved(bytes32 indexed paranetId, address indexed curator); + struct StagedCollection { + bytes32 knowledgeCollectionId; + address submitter; + ParanetLib.RequestStatus status; + } + // Paranet ID => Collection ID => Staging Status mapping(bytes32 => mapping(bytes32 => ParanetLib.RequestStatus)) public stagedCollections; @@ -30,12 +36,10 @@ contract ParanetStagingStorage is INamed, IVersioned, HubDependent { // Paranet ID => Curator Address => Is Curator mapping(bytes32 => mapping(address => bool)) public curators; - // Add these structs and functions - struct StagedCollection { - bytes32 knowledgeCollectionId; - address submitter; - ParanetLib.RequestStatus status; - } + // Paranet ID => Curator => Index + mapping(bytes32 => mapping(address => uint256)) public paranetCuratorIndexes; + // Paranet ID => Curators + mapping(bytes32 => address[]) public paranetCurators; // Track collections for pagination mapping(bytes32 => bytes32[]) private pendingknowledgeCollectionIds; @@ -52,16 +56,38 @@ contract ParanetStagingStorage is INamed, IVersioned, HubDependent { return _VERSION; } - function addCurator(bytes32 paranetId, address curator) external onlyContracts { + function addCurator(bytes32 paranetId, address curator) public { + paranetCuratorIndexes[paranetId][curator] = paranetCurators[paranetId].length; + paranetCurators[paranetId].push(curator); + curators[paranetId][curator] = true; + emit CuratorAdded(paranetId, curator); } - function removeCurator(bytes32 paranetId, address curator) external onlyContracts { - curators[paranetId][curator] = false; + function removeCurator(bytes32 paranetId, address curator) public { + uint256 index = paranetCuratorIndexes[paranetId][curator]; + uint256 lastIndex = paranetCurators[paranetId].length - 1; + + if (index != lastIndex) { + // Swap the last curator with the one to be removed + address lastCurator = paranetCurators[paranetId][lastIndex]; + paranetCurators[paranetId][index] = lastCurator; + paranetCuratorIndexes[paranetId][lastCurator] = index; + } + + // Remove the last element + paranetCurators[paranetId].pop(); + delete paranetCuratorIndexes[paranetId][curator]; + delete curators[paranetId][curator]; + emit CuratorRemoved(paranetId, curator); } + function getAllParanetCurators(bytes32 paranetId) public view returns (address[] memory) { + return paranetCurators[paranetId]; + } + function isCurator(bytes32 paranetId, address account) external view returns (bool) { return curators[paranetId][account]; } From dc533b9f1790ce12b2badbacfdc007cb6227a17b Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 14 Feb 2025 10:22:55 +0100 Subject: [PATCH 094/153] Update deployer script --- contracts/paranets/Paranet.sol | 18 +++++++++--------- ...gStorage.sol => ParanetStagingRegistry.sol} | 6 ++---- deploy/024_deploy_paranet_staging_registry.ts | 12 ++++++++++++ ...deploy_paranet.ts => 025_deploy_paranet.ts} | 1 + ..._deploy_paranet_incentives_pool_factory.ts} | 0 ...ploy_migrator.ts => 028_deploy_migrator.ts} | 0 6 files changed, 24 insertions(+), 13 deletions(-) rename contracts/storage/paranets/{ParanetStagingStorage.sol => ParanetStagingRegistry.sol} (97%) create mode 100644 deploy/024_deploy_paranet_staging_registry.ts rename deploy/{024_deploy_paranet.ts => 025_deploy_paranet.ts} (94%) rename deploy/{025_deploy_paranet_incentives_pool_factory.ts => 027_deploy_paranet_incentives_pool_factory.ts} (100%) rename deploy/{026_deploy_migrator.ts => 028_deploy_migrator.ts} (100%) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 970863e7..2002bbe3 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -6,7 +6,7 @@ import {ParanetKnowledgeCollectionsRegistry} from "../storage/paranets/ParanetKn import {ParanetKnowledgeMinersRegistry} from "../storage/paranets/ParanetKnowledgeMinersRegistry.sol"; import {ParanetsRegistry} from "../storage/paranets/ParanetsRegistry.sol"; import {ParanetServicesRegistry} from "../storage/paranets/ParanetServicesRegistry.sol"; -import {ParanetStagingStorage} from "../storage/paranets/ParanetStagingStorage.sol"; +import {ParanetStagingRegistry} from "../storage/paranets/ParanetStagingRegistry.sol"; import {ProfileStorage} from "../storage/ProfileStorage.sol"; import {IdentityStorage} from "../storage/IdentityStorage.sol"; import {KnowledgeCollectionStorage} from "../storage/KnowledgeCollectionStorage.sol"; @@ -151,7 +151,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ParanetServicesRegistry public paranetServicesRegistry; ParanetKnowledgeMinersRegistry public paranetKnowledgeMinersRegistry; ParanetKnowledgeCollectionsRegistry public paranetKnowledgeCollectionsRegistry; - ParanetStagingStorage public paranetStagingStorage; + ParanetStagingRegistry public paranetStagingRegistry; ProfileStorage public profileStorage; IdentityStorage public identityStorage; @@ -199,7 +199,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { paranetKnowledgeCollectionsRegistry = ParanetKnowledgeCollectionsRegistry( hub.getContractAddress("ParanetKnowledgeCollectionsRegistry") ); - paranetStagingStorage = ParanetStagingStorage(hub.getContractAddress("ParanetStagingStorage")); + paranetStagingRegistry = ParanetStagingRegistry(hub.getContractAddress("ParanetStagingRegistry")); } function name() external pure virtual override returns (string memory) { @@ -1102,7 +1102,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { if (pr.getKnowledgeCollectionsSubmissionPolicy(paranetId) == KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING) { require( - paranetStagingStorage.isKnowledgeCollectionApproved( + paranetStagingRegistry.isKnowledgeCollectionApproved( paranetId, keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)) ), @@ -1168,7 +1168,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { bytes32 knowledgeCollectionId = keccak256( abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) ); - ParanetStagingStorage pss = paranetStagingStorage; + ParanetStagingRegistry pss = paranetStagingRegistry; require( !pss.isKnowledgeCollectionStaged(paranetId, knowledgeCollectionId), "Knowledge collection is already staged" @@ -1206,7 +1206,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { knowledgeCollectionsSubmissionPolicy == KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, "Paranet does not allow adding curators" ); - paranetStagingStorage.addCurator(paranetId, curator); + paranetStagingRegistry.addCurator(paranetId, curator); } function removeCurator( @@ -1239,7 +1239,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { knowledgeCollectionsSubmissionPolicy == KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, "Paranet does not allow adding curators" ); - paranetStagingStorage.removeCurator(paranetId, curator); + paranetStagingRegistry.removeCurator(paranetId, curator); } function reviewKnowledgeCollection( @@ -1256,7 +1256,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { bytes32 knowledgeCollectionId = keccak256( abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) ); - ParanetStagingStorage pss = paranetStagingStorage; + ParanetStagingRegistry pss = paranetStagingRegistry; require( pss.isKnowledgeCollectionStaged(paranetId, knowledgeCollectionId), "Knowledge collection is not staged" @@ -1469,7 +1469,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 paranetKnowledgeAssetTokenId ) internal view { require( - paranetStagingStorage.isCurator( + paranetStagingRegistry.isCurator( keccak256( abi.encodePacked( paranetKCStorageContract, diff --git a/contracts/storage/paranets/ParanetStagingStorage.sol b/contracts/storage/paranets/ParanetStagingRegistry.sol similarity index 97% rename from contracts/storage/paranets/ParanetStagingStorage.sol rename to contracts/storage/paranets/ParanetStagingRegistry.sol index d9f83500..f28de7d9 100644 --- a/contracts/storage/paranets/ParanetStagingStorage.sol +++ b/contracts/storage/paranets/ParanetStagingRegistry.sol @@ -7,8 +7,8 @@ import {IVersioned} from "../../interfaces/IVersioned.sol"; import {HubDependent} from "../../abstract/HubDependent.sol"; import {ParanetLib} from "../../libraries/ParanetLib.sol"; -contract ParanetStagingStorage is INamed, IVersioned, HubDependent { - string private constant _NAME = "ParanetStagingStorage"; +contract ParanetStagingRegistry is INamed, IVersioned, HubDependent { + string private constant _NAME = "ParanetStagingRegistry"; string private constant _VERSION = "1.0.0"; // Events @@ -70,13 +70,11 @@ contract ParanetStagingStorage is INamed, IVersioned, HubDependent { uint256 lastIndex = paranetCurators[paranetId].length - 1; if (index != lastIndex) { - // Swap the last curator with the one to be removed address lastCurator = paranetCurators[paranetId][lastIndex]; paranetCurators[paranetId][index] = lastCurator; paranetCuratorIndexes[paranetId][lastCurator] = index; } - // Remove the last element paranetCurators[paranetId].pop(); delete paranetCuratorIndexes[paranetId][curator]; delete curators[paranetId][curator]; diff --git a/deploy/024_deploy_paranet_staging_registry.ts b/deploy/024_deploy_paranet_staging_registry.ts new file mode 100644 index 00000000..238b5de8 --- /dev/null +++ b/deploy/024_deploy_paranet_staging_registry.ts @@ -0,0 +1,12 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + await hre.helpers.deploy({ + newContractName: 'ParanetStagingRegistry', + }); +}; + +export default func; +func.tags = ['ParanetStagingRegistry']; +func.dependencies = ['Hub']; diff --git a/deploy/024_deploy_paranet.ts b/deploy/025_deploy_paranet.ts similarity index 94% rename from deploy/024_deploy_paranet.ts rename to deploy/025_deploy_paranet.ts index a78c3542..ffeaa802 100644 --- a/deploy/024_deploy_paranet.ts +++ b/deploy/025_deploy_paranet.ts @@ -15,6 +15,7 @@ func.dependencies = [ 'ParanetKnowledgeMinersRegistry', 'ParanetsRegistry', 'ParanetServicesRegistry', + 'ParanetStagingRegistry', 'ProfileStorage', 'IdentityStorage', ]; diff --git a/deploy/025_deploy_paranet_incentives_pool_factory.ts b/deploy/027_deploy_paranet_incentives_pool_factory.ts similarity index 100% rename from deploy/025_deploy_paranet_incentives_pool_factory.ts rename to deploy/027_deploy_paranet_incentives_pool_factory.ts diff --git a/deploy/026_deploy_migrator.ts b/deploy/028_deploy_migrator.ts similarity index 100% rename from deploy/026_deploy_migrator.ts rename to deploy/028_deploy_migrator.ts From 6b46debe580f3cd3cf77753b2475de88d70b453a Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 14 Feb 2025 10:27:52 +0100 Subject: [PATCH 095/153] Add deployer scripts --- ..._paranet_Incentives_pool_factory_helper.ts | 19 +++++++++++++++++++ ...deploy_paranet_incentives_pool_factory.ts} | 6 +++++- ...loy_migrator.ts => 027_deploy_migrator.ts} | 0 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 deploy/025_deploy_paranet_Incentives_pool_factory_helper.ts rename deploy/{025_deploy_paranet_incentives_pool_factory.ts => 026_deploy_paranet_incentives_pool_factory.ts} (83%) rename deploy/{026_deploy_migrator.ts => 027_deploy_migrator.ts} (100%) diff --git a/deploy/025_deploy_paranet_Incentives_pool_factory_helper.ts b/deploy/025_deploy_paranet_Incentives_pool_factory_helper.ts new file mode 100644 index 00000000..fcd2fe90 --- /dev/null +++ b/deploy/025_deploy_paranet_Incentives_pool_factory_helper.ts @@ -0,0 +1,19 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + if ( + !hre.network.name.startsWith('neuroweb') && + !hre.network.name.startsWith('hardhat') + ) { + return; + } + + await hre.helpers.deploy({ + newContractName: 'ParanetIncentivesPoolFactoryHelper', + }); +}; + +export default func; +func.tags = ['ParanetIncentivesPoolFactoryHelper']; +func.dependencies = ['Hub']; diff --git a/deploy/025_deploy_paranet_incentives_pool_factory.ts b/deploy/026_deploy_paranet_incentives_pool_factory.ts similarity index 83% rename from deploy/025_deploy_paranet_incentives_pool_factory.ts rename to deploy/026_deploy_paranet_incentives_pool_factory.ts index 68d18455..5d6a0cba 100644 --- a/deploy/025_deploy_paranet_incentives_pool_factory.ts +++ b/deploy/026_deploy_paranet_incentives_pool_factory.ts @@ -16,4 +16,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { export default func; func.tags = ['ParanetIncentivesPoolFactory']; -func.dependencies = ['Hub', 'ParanetsRegistry']; +func.dependencies = [ + 'Hub', + 'ParanetsRegistry', + ParanetIncentivesPoolFactoryHelper, +]; diff --git a/deploy/026_deploy_migrator.ts b/deploy/027_deploy_migrator.ts similarity index 100% rename from deploy/026_deploy_migrator.ts rename to deploy/027_deploy_migrator.ts From 02c890e2091d7b566c65f1e73d378c1a8b4f5e97 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 14 Feb 2025 10:32:05 +0100 Subject: [PATCH 096/153] Fix missing ' --- deploy/026_deploy_paranet_incentives_pool_factory.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/026_deploy_paranet_incentives_pool_factory.ts b/deploy/026_deploy_paranet_incentives_pool_factory.ts index 5d6a0cba..f24494e4 100644 --- a/deploy/026_deploy_paranet_incentives_pool_factory.ts +++ b/deploy/026_deploy_paranet_incentives_pool_factory.ts @@ -19,5 +19,5 @@ func.tags = ['ParanetIncentivesPoolFactory']; func.dependencies = [ 'Hub', 'ParanetsRegistry', - ParanetIncentivesPoolFactoryHelper, + 'ParanetIncentivesPoolFactoryHelper', ]; From 7cf02329416558d587291ba6c33bdcfdd7559611 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 14 Feb 2025 12:30:40 +0100 Subject: [PATCH 097/153] Update reviewKnowledgeCollection to to add KC to collection --- contracts/paranets/Paranet.sol | 115 ++++++++++++++++++++++++--------- 1 file changed, 84 insertions(+), 31 deletions(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 2002bbe3..eb78bafa 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -1100,29 +1100,16 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); } - if (pr.getKnowledgeCollectionsSubmissionPolicy(paranetId) == KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING) { - require( - paranetStagingRegistry.isKnowledgeCollectionApproved( - paranetId, - keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)) - ), - "Knowledge collection is not approved" - ); - } - - KnowledgeCollectionStorage kcs = KnowledgeCollectionStorage(knowledgeCollectionStorageContract); - uint96 remainingTokenAmount = kcs.getTokenAmount(knowledgeCollectionTokenId); - KnowledgeCollectionLib.MerkleRoot[] memory merkleRoots = kcs.getMerkleRoots(knowledgeCollectionTokenId); + require( + pr.getKnowledgeCollectionsSubmissionPolicy(paranetId) != KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, + "Staging policy denied" + ); // Update KnowledgeMiner metadata _updateSubmittedKnowledgeCollectionMetadata( - paranetKCStorageContract, - paranetKnowledgeCollectionTokenId, - paranetKnowledgeAssetTokenId, + paranetId, knowledgeCollectionStorageContract, - knowledgeCollectionTokenId, - remainingTokenAmount, - merkleRoots + knowledgeCollectionTokenId ); emit KnowledgeCollectionSubmittedToParanet( @@ -1142,6 +1129,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 knowledgeCollectionTokenId ) external onlyKnowledgeCollectionOwner(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) { ParanetsRegistry pr = paranetsRegistry; + bytes32 paranetId = keccak256( abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId) ); @@ -1153,6 +1141,20 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { paranetKnowledgeAssetTokenId ); } + ParanetKnowledgeCollectionsRegistry pkcr = paranetKnowledgeCollectionsRegistry; + if ( + pkcr.isParanetKnowledgeCollection( + keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)) + ) + ) { + revert ParanetLib.KnowledgeCollectionIsAPartOfOtherParanet( + knowledgeCollectionStorageContract, + knowledgeCollectionTokenId, + pkcr.getParanetId( + keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)) + ) + ); + } if (pr.getMinersAccessPolicy(paranetId) == MINERS_ACCESS_POLICY_PERMISSIONED) { require(pr.isKnowledgeMinerRegistered(paranetId, msg.sender), "Knowledge miner is not registered"); @@ -1256,12 +1258,64 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { bytes32 knowledgeCollectionId = keccak256( abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) ); + ParanetsRegistry pr = paranetsRegistry; + if (!pr.paranetExists(paranetId)) { + revert ParanetLib.ParanetDoesntExist( + paranetKCStorageContract, + paranetKnowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId + ); + } + ParanetStagingRegistry pss = paranetStagingRegistry; require( pss.isKnowledgeCollectionStaged(paranetId, knowledgeCollectionId), "Knowledge collection is not staged" ); pss.reviewKnowledgeCollection(paranetId, knowledgeCollectionId, accepted); + + if (accepted) { + ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; + uint8 minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); + // Check if paranet is curated and if knowledge miner is whitelisted + if ( + minersAccessPolicy == MINERS_ACCESS_POLICY_PERMISSIONED && + !pr.isKnowledgeMinerRegistered(paranetId, msg.sender) + ) { + revert ParanetLib.ParanetCuratedMinerDoesntExist(paranetId, msg.sender); + // Should this be done in both cases why would OPEN have separeted logic ??? + } else if (minersAccessPolicy == MINERS_ACCESS_POLICY_OPEN) { + // Check if Knowledge Miner has profile + // If not: Create a profile + if (!pkmr.knowledgeMinerExists(msg.sender)) { + pkmr.registerKnowledgeMiner(msg.sender); + } + + // Check if Knowledge Miner is registered on paranet + if (!pr.isKnowledgeMinerRegistered(paranetId, msg.sender)) { + pr.addKnowledgeMiner(paranetId, msg.sender); + } + } + + KnowledgeCollectionStorage kcs = KnowledgeCollectionStorage(knowledgeCollectionStorageContract); + uint96 remainingTokenAmount = kcs.getTokenAmount(knowledgeCollectionTokenId); + KnowledgeCollectionLib.MerkleRoot[] memory merkleRoots = kcs.getMerkleRoots(knowledgeCollectionTokenId); + + // Update KnowledgeMiner metadata + _updateSubmittedKnowledgeCollectionMetadata( + paranetId, + knowledgeCollectionStorageContract, + knowledgeCollectionTokenId + ); + + emit KnowledgeCollectionSubmittedToParanet( + paranetKCStorageContract, + paranetKnowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId, + knowledgeCollectionStorageContract, + knowledgeCollectionTokenId + ); + } } // function processUpdatedKnowledgeCollectionStatesMetadata( @@ -1279,18 +1333,17 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // } function _updateSubmittedKnowledgeCollectionMetadata( - address paranetKCStorageContract, - uint256 paranetKCTokenId, - uint256 paranetKATokenId, + bytes32 paranetId, address knowledgeCollectionStorageContract, - uint256 knowledgeCollectionTokenId, - uint96 tokenAmount, - KnowledgeCollectionLib.MerkleRoot[] memory merkleRoots + uint256 knowledgeCollectionTokenId ) internal { + KnowledgeCollectionStorage kcs = KnowledgeCollectionStorage(knowledgeCollectionStorageContract); + ParanetsRegistry pr = paranetsRegistry; ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); + uint96 remainingTokenAmount = kcs.getTokenAmount(knowledgeCollectionTokenId); + KnowledgeCollectionLib.MerkleRoot[] memory merkleRoots = kcs.getMerkleRoots(knowledgeCollectionTokenId); bytes32 knowledgeCollectionId = keccak256( abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) ); @@ -1305,7 +1358,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // Add Knowledge Collection Metadata to the ParanetsRegistry pr.addKnowledgeCollecton(paranetId, knowledgeCollectionId); - pr.addCumulativeKnowledgeValue(paranetId, tokenAmount); + pr.addCumulativeKnowledgeValue(paranetId, remainingTokenAmount); // Add Knowledge Collection Metadata to the KnowledgeMinersRegistry for (uint256 i = 0; i < merkleRoots.length - 1; i++) { @@ -1324,13 +1377,13 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { knowledgeCollectionStorageContract, knowledgeCollectionTokenId, merkleRoots[merkleRoots.length - 1].merkleRoot, - tokenAmount + remainingTokenAmount ); pkmr.addSubmittedKnowledgeCollection(msg.sender, paranetId, knowledgeCollectionId); - pkmr.addCumulativeTracSpent(msg.sender, paranetId, tokenAmount); - pkmr.addUnrewardedTracSpent(msg.sender, paranetId, tokenAmount); + pkmr.addCumulativeTracSpent(msg.sender, paranetId, remainingTokenAmount); + pkmr.addUnrewardedTracSpent(msg.sender, paranetId, remainingTokenAmount); pkmr.incrementTotalSubmittedKnowledgeCollectionsCount(msg.sender); - pkmr.addTotalTracSpent(msg.sender, tokenAmount); + pkmr.addTotalTracSpent(msg.sender, remainingTokenAmount); } // function _processUpdatedKnowledgeCollectionStatesMetadata( From 4f59650513c98ad2cb99a74fb1c6ff3a3c744d40 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 14 Feb 2025 12:39:53 +0100 Subject: [PATCH 098/153] remove Neuro references --- .../ParanetIncentivesPoolFactoryHelper.sol | 14 +- .../paranets/ParanetNeuroIncentivesPool.sol | 384 +++++++++--------- .../ParanetNeuroIncentivesPoolStorage.sol | 154 +++---- 3 files changed, 273 insertions(+), 279 deletions(-) diff --git a/contracts/paranets/ParanetIncentivesPoolFactoryHelper.sol b/contracts/paranets/ParanetIncentivesPoolFactoryHelper.sol index f9be07ab..986aa5f3 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactoryHelper.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactoryHelper.sol @@ -3,8 +3,8 @@ pragma solidity ^0.8.20; import {Hub} from "../storage/Hub.sol"; -import {ParanetNeuroIncentivesPool} from "./ParanetNeuroIncentivesPool.sol"; -import {ParanetNeuroIncentivesPoolStorage} from "./ParanetNeuroIncentivesPoolStorage.sol"; +import {ParanetIncentivesPool} from "./ParanetIncentivesPool.sol"; +import {ParanetIncentivesPoolStorage} from "./ParanetIncentivesPoolStorage.sol"; import {KnowledgeCollectionStorage} from "../storage/KnowledgeCollectionStorage.sol"; import {ContractStatus} from "../abstract/ContractStatus.sol"; import {IInitializable} from "../interfaces/IInitializable.sol"; @@ -26,20 +26,20 @@ contract ParanetIncentivesPoolFactoryHelper is INamed, IVersioned, ContractStatu return _VERSION; } - function deployNeuroIncentivesPool( + function deployIncentivesPool( address storageAddress, - uint256 tracToNeuroEmissionMultiplier, + uint256 tracToTokenEmissionMultiplier, address poolStorageAddress ) external onlyContracts returns (address) { address addr = address( - new ParanetNeuroIncentivesPool( + new ParanetIncentivesPool( address(hub), hub.getContractAddress("ParanetKnowledgeMinersRegistry"), storageAddress, - tracToNeuroEmissionMultiplier + tracToTokenEmissionMultiplier ) ); - ParanetNeuroIncentivesPoolStorage(payable(poolStorageAddress)).setParanetNeuroIncentivesPool(addr); + ParanetIncentivesPoolStorage(payable(poolStorageAddress)).setParanetIncentivesPool(addr); return addr; } diff --git a/contracts/paranets/ParanetNeuroIncentivesPool.sol b/contracts/paranets/ParanetNeuroIncentivesPool.sol index 35ecb5c3..f3e2ac90 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPool.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPool.sol @@ -4,54 +4,52 @@ pragma solidity ^0.8.20; import {ParanetKnowledgeMinersRegistry} from "../storage/paranets/ParanetKnowledgeMinersRegistry.sol"; import {ParanetsRegistry} from "../storage/paranets/ParanetsRegistry.sol"; -import {ParanetNeuroIncentivesPoolStorage} from "./ParanetNeuroIncentivesPoolStorage.sol"; +import {ParanetIncentivesPoolStorage} from "./ParanetIncentivesPoolStorage.sol"; import {KnowledgeCollectionStorage} from "../storage/KnowledgeCollectionStorage.sol"; import {Hub} from "../storage/Hub.sol"; import {INamed} from "../interfaces/INamed.sol"; import {IVersioned} from "../interfaces/IVersioned.sol"; import {ParanetLib} from "../libraries/ParanetLib.sol"; -import {IParanetNeuroIncentivesPool} from "../interfaces/IParanetNeuroIncentivesPool.sol"; +import {IParanetIncentivesPool} from "../interfaces/IParanetIncentivesPool.sol"; -contract ParanetNeuroIncentivesPool is INamed, IVersioned, IParanetNeuroIncentivesPool { - event NeuroEmissionMultiplierUpdateInitiated(uint256 oldMultiplier, uint256 newMultiplier, uint256 timestamp); - event NeuroEmissionMultiplierUpdateFinalized(uint256 oldMultiplier, uint256 newMultiplier); +contract ParanetIncentivesPool is INamed, IVersioned, IParanetIncentivesPool { + event TokenEmissionMultiplierUpdateInitiated(uint256 oldMultiplier, uint256 newMultiplier, uint256 timestamp); + event TokenEmissionMultiplierUpdateFinalized(uint256 oldMultiplier, uint256 newMultiplier); - string private constant _NAME = "ParanetNeuroIncentivesPool"; + string private constant _NAME = "ParanetIncentivesPool"; string private constant _VERSION = "1.0.0"; Hub public hub; ParanetsRegistry public paranetsRegistry; ParanetKnowledgeMinersRegistry public paranetKnowledgeMinersRegistry; - ParanetNeuroIncentivesPoolStorage public paranetNeuroIncentivesPoolStorage; + ParanetIncentivesPoolStorage public ParanetIncentivesPoolStorage; - // Array of Total NEURO Emission Multipliers - // Total NEURO Emission Multiplier = Ratio of how much NEURO is released per 1 TRAC spent + // Array of Total TOKEN Emission Multipliers + // Total TOKEN Emission Multiplier = Ratio of how much TOKEN is released per 1 TRAC spent // // Examples: - // 1 * 10^12 = 1 NEURO per 1 TRAC - // 0.5 * 10^12 = 5 * 10^11 = 0.5 NEURO per 1 TRAC - // 1 = 1 NEURO wei per 1 TRAC + // 1 * 10^12 = 1 TOKEN per 1 TRAC + // 0.5 * 10^12 = 5 * 10^11 = 0.5 TOKEN per 1 TRAC + // 1 = 1 TOKEN wei per 1 TRAC // - ParanetLib.NeuroEmissionMultiplier[] public neuroEmissionMultipliers; + ParanetLib.TokenEmissionMultiplier[] public TokenEmissionMultipliers; - uint256 public neuroEmissionMultiplierUpdateDelay = 7 days; + uint256 public TokenEmissionMultiplierUpdateDelay = 7 days; // solhint-disable-next-line no-empty-blocks constructor( address hubAddress, address knowledgeMinersRegistryAddress, - address paranetNeuroIncentivesPoolStorageAddress, - uint256 tracToNeuroEmissionMultiplier + address ParanetIncentivesPoolStorageAddress, + uint256 tracToTokenEmissionMultiplier ) { hub = Hub(hubAddress); paranetKnowledgeMinersRegistry = ParanetKnowledgeMinersRegistry(knowledgeMinersRegistryAddress); - paranetNeuroIncentivesPoolStorage = ParanetNeuroIncentivesPoolStorage( - payable(paranetNeuroIncentivesPoolStorageAddress) - ); + ParanetIncentivesPoolStorage = ParanetIncentivesPoolStorage(payable(ParanetIncentivesPoolStorageAddress)); - neuroEmissionMultipliers.push( - ParanetLib.NeuroEmissionMultiplier({ - multiplier: tracToNeuroEmissionMultiplier, + TokenEmissionMultipliers.push( + ParanetLib.TokenEmissionMultiplier({ + multiplier: tracToTokenEmissionMultiplier, timestamp: block.timestamp, finalized: true }) @@ -91,32 +89,32 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned, IParanetNeuroIncentiv return _VERSION; } - function updateNeuroEmissionMultiplierUpdateDelay(uint256 newDelay) external onlyHubOwner { - neuroEmissionMultiplierUpdateDelay = newDelay; + function updateTokenEmissionMultiplierUpdateDelay(uint256 newDelay) external onlyHubOwner { + TokenEmissionMultiplierUpdateDelay = newDelay; } - function voterClaimedNeuro(address addr) external view returns (uint256) { - uint256 voterIndex = paranetNeuroIncentivesPoolStorage.votersIndexes(addr); + function voterclaimedToken(address addr) external view returns (uint256) { + uint256 voterIndex = ParanetIncentivesPoolStorage.votersIndexes(addr); // If the index is out of range or the stored voter doesn't match `voterAddress`, // return 0 as a default. if ( - voterIndex >= paranetNeuroIncentivesPoolStorage.getVotersCount() || - paranetNeuroIncentivesPoolStorage.getVoterAtIndex(voterIndex).addr != addr + voterIndex >= ParanetIncentivesPoolStorage.getVotersCount() || + ParanetIncentivesPoolStorage.getVoterAtIndex(voterIndex).addr != addr ) { return 0; } - return paranetNeuroIncentivesPoolStorage.getVoterAtIndex(voterIndex).claimedNeuro; + return ParanetIncentivesPoolStorage.getVoterAtIndex(voterIndex).claimedToken; } function isKnowledgeMiner(address addr) public view returns (bool) { - return paranetsRegistry.isKnowledgeMinerRegistered(paranetNeuroIncentivesPoolStorage.paranetId(), addr); + return paranetsRegistry.isKnowledgeMinerRegistered(ParanetIncentivesPoolStorage.paranetId(), addr); } function isParanetOperator(address addr) public view returns (bool) { (address paranetKCStorageContract, uint256 paranetKCTokenId, uint256 paranetKATokenId) = paranetsRegistry - .getParanetKnowledgeAssetLocator(paranetNeuroIncentivesPoolStorage.paranetId()); + .getParanetKnowledgeAssetLocator(ParanetIncentivesPoolStorage.paranetId()); KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage(paranetKCStorageContract); @@ -130,73 +128,71 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned, IParanetNeuroIncentiv } function isProposalVoter(address addr) public view returns (bool) { - return (paranetNeuroIncentivesPoolStorage.getVotersCount() != 0 && - paranetNeuroIncentivesPoolStorage - .getVoterAtIndex(paranetNeuroIncentivesPoolStorage.votersIndexes(addr)) - .addr == + return (ParanetIncentivesPoolStorage.getVotersCount() != 0 && + ParanetIncentivesPoolStorage.getVoterAtIndex(ParanetIncentivesPoolStorage.votersIndexes(addr)).addr == addr); } - function getNeuroEmissionMultipliers() external view returns (ParanetLib.NeuroEmissionMultiplier[] memory) { - return neuroEmissionMultipliers; + function getTokenEmissionMultipliers() external view returns (ParanetLib.TokenEmissionMultiplier[] memory) { + return TokenEmissionMultipliers; } - function getEffectiveNeuroEmissionMultiplier(uint256 timestamp) public view returns (uint256) { - for (uint256 i = neuroEmissionMultipliers.length; i > 0; i--) { - if (neuroEmissionMultipliers[i - 1].finalized && timestamp >= neuroEmissionMultipliers[i - 1].timestamp) { - return neuroEmissionMultipliers[i - 1].multiplier; + function getEffectiveTokenEmissionMultiplier(uint256 timestamp) public view returns (uint256) { + for (uint256 i = TokenEmissionMultipliers.length; i > 0; i--) { + if (TokenEmissionMultipliers[i - 1].finalized && timestamp >= TokenEmissionMultipliers[i - 1].timestamp) { + return TokenEmissionMultipliers[i - 1].multiplier; } } - return neuroEmissionMultipliers[0].multiplier; + return TokenEmissionMultipliers[0].multiplier; } // TODO:Should there be some check of this value? - function initiateNeuroEmissionMultiplierUpdate(uint256 newMultiplier) external onlyVotersRegistrar { - if (!neuroEmissionMultipliers[neuroEmissionMultipliers.length - 1].finalized) { - neuroEmissionMultipliers[neuroEmissionMultipliers.length - 1].multiplier = newMultiplier; - neuroEmissionMultipliers[neuroEmissionMultipliers.length - 1].timestamp = + function initiateTokenEmissionMultiplierUpdate(uint256 newMultiplier) external onlyVotersRegistrar { + if (!TokenEmissionMultipliers[TokenEmissionMultipliers.length - 1].finalized) { + TokenEmissionMultipliers[TokenEmissionMultipliers.length - 1].multiplier = newMultiplier; + TokenEmissionMultipliers[TokenEmissionMultipliers.length - 1].timestamp = block.timestamp + - neuroEmissionMultiplierUpdateDelay; + TokenEmissionMultiplierUpdateDelay; } else { - neuroEmissionMultipliers.push( - ParanetLib.NeuroEmissionMultiplier({ + TokenEmissionMultipliers.push( + ParanetLib.TokenEmissionMultiplier({ multiplier: newMultiplier, - timestamp: block.timestamp + neuroEmissionMultiplierUpdateDelay, + timestamp: block.timestamp + TokenEmissionMultiplierUpdateDelay, finalized: false }) ); } - emit NeuroEmissionMultiplierUpdateInitiated( - neuroEmissionMultipliers[neuroEmissionMultipliers.length - 2].multiplier, + emit TokenEmissionMultiplierUpdateInitiated( + TokenEmissionMultipliers[TokenEmissionMultipliers.length - 2].multiplier, newMultiplier, - block.timestamp + neuroEmissionMultiplierUpdateDelay + block.timestamp + TokenEmissionMultiplierUpdateDelay ); } - function finalizeNeuroEmissionMultiplierUpdate() external onlyVotersRegistrar { - require(neuroEmissionMultipliers.length > 0, "No emission multiplier updates"); + function finalizeTokenEmissionMultiplierUpdate() external onlyVotersRegistrar { + require(TokenEmissionMultipliers.length > 0, "No emission multiplier updates"); require( - !neuroEmissionMultipliers[neuroEmissionMultipliers.length - 1].finalized, + !TokenEmissionMultipliers[TokenEmissionMultipliers.length - 1].finalized, "Last update already finalized" ); require( - block.timestamp >= neuroEmissionMultipliers[neuroEmissionMultipliers.length - 1].timestamp, + block.timestamp >= TokenEmissionMultipliers[TokenEmissionMultipliers.length - 1].timestamp, "Delay period not yet passed" ); - neuroEmissionMultipliers[neuroEmissionMultipliers.length - 1].finalized = true; + TokenEmissionMultipliers[TokenEmissionMultipliers.length - 1].finalized = true; - emit NeuroEmissionMultiplierUpdateFinalized( - neuroEmissionMultipliers[neuroEmissionMultipliers.length - 2].multiplier, - neuroEmissionMultipliers[neuroEmissionMultipliers.length - 1].multiplier + emit TokenEmissionMultiplierUpdateFinalized( + TokenEmissionMultipliers[TokenEmissionMultipliers.length - 2].multiplier, + TokenEmissionMultipliers[TokenEmissionMultipliers.length - 1].multiplier ); } function getTotalKnowledgeMinerIncentiveEstimation() public view returns (uint256) { uint96 unrewardedTracSpent = paranetKnowledgeMinersRegistry.getUnrewardedTracSpent( msg.sender, - paranetNeuroIncentivesPoolStorage.paranetId() + ParanetIncentivesPoolStorage.paranetId() ); if (unrewardedTracSpent < ParanetLib.TOKENS_DIGITS_DIFF) { @@ -204,22 +200,22 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned, IParanetNeuroIncentiv } // Unrewarded TRAC Spent = how much TRAC Knowledge Miner spent for Mining and haven't got a reward for - // Effective Emission Ratio = Current active Multiplier for how much NEURO is released per TRAC spent + // Effective Emission Ratio = Current active Multiplier for how much TOKEN is released per TRAC spent // // Basic Formula: // Reward = UnrewardedTRAC * TotalEmissionRatio * (MinersRewardPercentage / 100) // // Example: - // Let's say we have 10 unrewarded TRAC, 0.5 NEURO per TRAC Total Emission and 80% Miners Reward Percentage, + // Let's say we have 10 unrewarded TRAC, 0.5 TOKEN per TRAC Total Emission and 80% Miners Reward Percentage, // 10% Operator Reward Percentage, 10% Voters Reward Percentage // Reward = (((10 * 10^18) * (5 * 10^11)) / (10^18)) * (10,000 - 1,000 - 1,000) / 10,000) = - // = 10 * 5 * 10^11 * 8,000 / 10,000 = 8/10 * (5 * 10^12) = 80% of 5 NEURO = 4 NEURO + // = 10 * 5 * 10^11 * 8,000 / 10,000 = 8/10 * (5 * 10^12) = 80% of 5 TOKEN = 4 TOKEN return - (((unrewardedTracSpent * getEffectiveNeuroEmissionMultiplier(block.timestamp)) / + (((unrewardedTracSpent * getEffectiveTokenEmissionMultiplier(block.timestamp)) / ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) * (ParanetLib.PERCENTAGE_SCALING_FACTOR - - paranetNeuroIncentivesPoolStorage.paranetOperatorRewardPercentage() - - paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage())) / + ParanetIncentivesPoolStorage.paranetOperatorRewardPercentage() - + ParanetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage())) / ParanetLib.PERCENTAGE_SCALING_FACTOR; } @@ -227,149 +223,149 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned, IParanetNeuroIncentiv return _getIncentiveEstimation( ParanetLib.PERCENTAGE_SCALING_FACTOR - - paranetNeuroIncentivesPoolStorage.paranetOperatorRewardPercentage() - - paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage(), - paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro() + ParanetIncentivesPoolStorage.paranetOperatorRewardPercentage() - + ParanetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage(), + ParanetIncentivesPoolStorage.totalMinersclaimedToken() ); } function getClaimableKnowledgeMinerRewardAmount() public view returns (uint256) { - uint256 neuroReward = getTotalKnowledgeMinerIncentiveEstimation(); + uint256 tokenReward = getTotalKnowledgeMinerIncentiveEstimation(); // Here we should have a limit for Knowledge Miners, which is determined by the % of the Miners Reward - // and total NEURO received by the contract, so that Miners don't get tokens belonging to Operator/Voters - // Following the example from the above, if we have 100 NEURO as a total reward, Miners should never get - // more than 80 NEURO. minersRewardLimit = 80 NEURO - uint256 totalMinersClaimedNeuro = paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro(); - uint256 minersRewardLimit = ((paranetNeuroIncentivesPoolStorage.getBalance() + - totalMinersClaimedNeuro + - paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro() + - paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro()) * + // and total TOKEN received by the contract, so that Miners don't get tokens belonging to Operator/Voters + // Following the example from the above, if we have 100 TOKEN as a total reward, Miners should never get + // more than 80 TOKEN. minersRewardLimit = 80 TOKEN + uint256 totalMinersclaimedToken = ParanetIncentivesPoolStorage.totalMinersclaimedToken(); + uint256 minersRewardLimit = ((ParanetIncentivesPoolStorage.getBalance() + + totalMinersclaimedToken + + ParanetIncentivesPoolStorage.totalOperatorsclaimedToken() + + ParanetIncentivesPoolStorage.totalVotersclaimedToken()) * (ParanetLib.PERCENTAGE_SCALING_FACTOR - - paranetNeuroIncentivesPoolStorage.paranetOperatorRewardPercentage() - - paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage())) / + ParanetIncentivesPoolStorage.paranetOperatorRewardPercentage() - + ParanetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage())) / ParanetLib.PERCENTAGE_SCALING_FACTOR; return - totalMinersClaimedNeuro + neuroReward <= minersRewardLimit - ? neuroReward - : minersRewardLimit - totalMinersClaimedNeuro; + totalMinersclaimedToken + tokenReward <= minersRewardLimit + ? tokenReward + : minersRewardLimit - totalMinersclaimedToken; } function getClaimableAllKnowledgeMinersRewardAmount() public view returns (uint256) { - uint256 neuroReward = getTotalAllKnowledgeMinersIncentiveEstimation(); + uint256 tokenReward = getTotalAllKnowledgeMinersIncentiveEstimation(); - uint256 minersRewardLimit = ((paranetNeuroIncentivesPoolStorage.getBalance() + - paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro() + - paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro() + - paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro()) * + uint256 minersRewardLimit = ((ParanetIncentivesPoolStorage.getBalance() + + ParanetIncentivesPoolStorage.totalMinersclaimedToken() + + ParanetIncentivesPoolStorage.totalOperatorsclaimedToken() + + ParanetIncentivesPoolStorage.totalVotersclaimedToken()) * (ParanetLib.PERCENTAGE_SCALING_FACTOR - - paranetNeuroIncentivesPoolStorage.paranetOperatorRewardPercentage() - - paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage())) / + ParanetIncentivesPoolStorage.paranetOperatorRewardPercentage() - + ParanetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage())) / ParanetLib.PERCENTAGE_SCALING_FACTOR; return - paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro() + neuroReward <= minersRewardLimit - ? neuroReward - : minersRewardLimit - paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro(); + ParanetIncentivesPoolStorage.totalMinersclaimedToken() + tokenReward <= minersRewardLimit + ? tokenReward + : minersRewardLimit - ParanetIncentivesPoolStorage.totalMinersclaimedToken(); } function claimKnowledgeMinerReward(uint256 amount) external onlyParanetKnowledgeMiner { ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; - uint256 neuroReward = getTotalKnowledgeMinerIncentiveEstimation(); - uint256 claimableNeuroReward = getClaimableKnowledgeMinerRewardAmount(); - if (claimableNeuroReward == 0 || amount == 0 || amount > claimableNeuroReward) { - revert ParanetLib.NoRewardAvailable(paranetNeuroIncentivesPoolStorage.paranetId(), msg.sender); + uint256 tokenReward = getTotalKnowledgeMinerIncentiveEstimation(); + uint256 claimableTokenReward = getClaimableKnowledgeMinerRewardAmount(); + if (claimableTokenReward == 0 || amount == 0 || amount > claimableTokenReward) { + revert ParanetLib.NoRewardAvailable(ParanetIncentivesPoolStorage.paranetId(), msg.sender); } - uint96 newUnrewardedTracSpent = amount == neuroReward + uint96 newUnrewardedTracSpent = amount == tokenReward ? 0 : uint96( - ((neuroReward - amount) * ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) / - getEffectiveNeuroEmissionMultiplier(block.timestamp) + ((tokenReward - amount) * ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) / + getEffectiveTokenEmissionMultiplier(block.timestamp) ); - pkmr.setUnrewardedTracSpent(msg.sender, paranetNeuroIncentivesPoolStorage.paranetId(), newUnrewardedTracSpent); - pkmr.addCumulativeAwardedNeuro(msg.sender, paranetNeuroIncentivesPoolStorage.paranetId(), amount); + pkmr.setUnrewardedTracSpent(msg.sender, ParanetIncentivesPoolStorage.paranetId(), newUnrewardedTracSpent); + pkmr.addcumulativeAwardedToken(msg.sender, ParanetIncentivesPoolStorage.paranetId(), amount); if ( - paranetNeuroIncentivesPoolStorage.getClaimedMinerRewardsLength() == 0 || - paranetNeuroIncentivesPoolStorage - .getClaimedMinerRewardsAtIndex(paranetNeuroIncentivesPoolStorage.claimedMinerRewardsIndexes(msg.sender)) + ParanetIncentivesPoolStorage.getClaimedMinerRewardsLength() == 0 || + ParanetIncentivesPoolStorage + .getClaimedMinerRewardsAtIndex(ParanetIncentivesPoolStorage.claimedMinerRewardsIndexes(msg.sender)) .addr != msg.sender ) { - paranetNeuroIncentivesPoolStorage.addMinerClaimedRewardProfile(msg.sender, amount); + ParanetIncentivesPoolStorage.addMinerClaimedRewardProfile(msg.sender, amount); } else { - paranetNeuroIncentivesPoolStorage.addMinerClaimedReward(msg.sender, amount); + ParanetIncentivesPoolStorage.addMinerClaimedReward(msg.sender, amount); } - paranetNeuroIncentivesPoolStorage.addTotalMinersClaimedNeuro(amount); + ParanetIncentivesPoolStorage.addTotalMinersclaimedToken(amount); - paranetNeuroIncentivesPoolStorage.transferReward(msg.sender, amount); + ParanetIncentivesPoolStorage.transferReward(msg.sender, amount); } function getTotalParanetOperatorIncentiveEstimation() public view returns (uint256) { return _getIncentiveEstimation( - paranetNeuroIncentivesPoolStorage.paranetOperatorRewardPercentage(), - paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro() + ParanetIncentivesPoolStorage.paranetOperatorRewardPercentage(), + ParanetIncentivesPoolStorage.totalOperatorsclaimedToken() ); } function getClaimableParanetOperatorRewardAmount() public view returns (uint256) { - uint256 neuroReward = getTotalParanetOperatorIncentiveEstimation(); + uint256 tokenReward = getTotalParanetOperatorIncentiveEstimation(); - uint256 operatorRewardLimit = ((paranetNeuroIncentivesPoolStorage.getBalance() + - paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro() + - paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro() + - paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro()) * - paranetNeuroIncentivesPoolStorage.paranetOperatorRewardPercentage()) / ParanetLib.PERCENTAGE_SCALING_FACTOR; + uint256 operatorRewardLimit = ((ParanetIncentivesPoolStorage.getBalance() + + ParanetIncentivesPoolStorage.totalMinersclaimedToken() + + ParanetIncentivesPoolStorage.totalOperatorsclaimedToken() + + ParanetIncentivesPoolStorage.totalVotersclaimedToken()) * + ParanetIncentivesPoolStorage.paranetOperatorRewardPercentage()) / ParanetLib.PERCENTAGE_SCALING_FACTOR; return - paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro() + neuroReward <= operatorRewardLimit - ? neuroReward - : operatorRewardLimit - paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro(); + ParanetIncentivesPoolStorage.totalOperatorsclaimedToken() + tokenReward <= operatorRewardLimit + ? tokenReward + : operatorRewardLimit - ParanetIncentivesPoolStorage.totalOperatorsclaimedToken(); } function claimParanetOperatorReward() external onlyParanetOperator { - uint256 claimableNeuroReward = getClaimableParanetOperatorRewardAmount(); + uint256 claimableTokenReward = getClaimableParanetOperatorRewardAmount(); - if (claimableNeuroReward == 0) { - revert ParanetLib.NoRewardAvailable(paranetNeuroIncentivesPoolStorage.paranetId(), msg.sender); + if (claimableTokenReward == 0) { + revert ParanetLib.NoRewardAvailable(ParanetIncentivesPoolStorage.paranetId(), msg.sender); } if ( - paranetNeuroIncentivesPoolStorage.getClaimedOperatorRewardsLength() == 0 || - paranetNeuroIncentivesPoolStorage + ParanetIncentivesPoolStorage.getClaimedOperatorRewardsLength() == 0 || + ParanetIncentivesPoolStorage .getClaimedOperatorRewardsAtIndex( - paranetNeuroIncentivesPoolStorage.claimedOperatorRewardsIndexes(msg.sender) + ParanetIncentivesPoolStorage.claimedOperatorRewardsIndexes(msg.sender) ) .addr != msg.sender ) { - paranetNeuroIncentivesPoolStorage.addOperatorClaimedRewardsProfile(msg.sender, claimableNeuroReward); + ParanetIncentivesPoolStorage.addOperatorClaimedRewardsProfile(msg.sender, claimableTokenReward); } else { - paranetNeuroIncentivesPoolStorage.addClaimedOperatorReward(msg.sender, claimableNeuroReward); + ParanetIncentivesPoolStorage.addClaimedOperatorReward(msg.sender, claimableTokenReward); } - paranetNeuroIncentivesPoolStorage.addTotalOperatorsClaimedNeuro(claimableNeuroReward); + ParanetIncentivesPoolStorage.addTotalOperatorsclaimedToken(claimableTokenReward); - paranetNeuroIncentivesPoolStorage.transferReward(msg.sender, claimableNeuroReward); + ParanetIncentivesPoolStorage.transferReward(msg.sender, claimableTokenReward); } function getTotalProposalVoterIncentiveEstimation() public view returns (uint256) { - uint256 effectiveNeuroEmissionMultiplier = getEffectiveNeuroEmissionMultiplier(block.timestamp); + uint256 effectiveTokenEmissionMultiplier = getEffectiveTokenEmissionMultiplier(block.timestamp); uint96 cumulativeKnowledgeValueSingleVoterPart = (((paranetsRegistry.getCumulativeKnowledgeValue( - paranetNeuroIncentivesPoolStorage.paranetId() - ) * paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage()) / + ParanetIncentivesPoolStorage.paranetId() + ) * ParanetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage()) / ParanetLib.PERCENTAGE_SCALING_FACTOR) * - paranetNeuroIncentivesPoolStorage - .getVoterAtIndex(paranetNeuroIncentivesPoolStorage.votersIndexes(msg.sender)) + ParanetIncentivesPoolStorage + .getVoterAtIndex(ParanetIncentivesPoolStorage.votersIndexes(msg.sender)) .weight) / ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT; uint96 rewardedTracSpentSingleVoterPart = uint96( - (paranetNeuroIncentivesPoolStorage - .getVoterAtIndex(paranetNeuroIncentivesPoolStorage.votersIndexes(msg.sender)) - .claimedNeuro * ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) / effectiveNeuroEmissionMultiplier + (ParanetIncentivesPoolStorage + .getVoterAtIndex(ParanetIncentivesPoolStorage.votersIndexes(msg.sender)) + .claimedToken * ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) / effectiveTokenEmissionMultiplier ); if ( @@ -379,106 +375,104 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned, IParanetNeuroIncentiv } return - ((cumulativeKnowledgeValueSingleVoterPart * effectiveNeuroEmissionMultiplier) / + ((cumulativeKnowledgeValueSingleVoterPart * effectiveTokenEmissionMultiplier) / ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) - - paranetNeuroIncentivesPoolStorage - .getVoterAtIndex(paranetNeuroIncentivesPoolStorage.votersIndexes(msg.sender)) - .claimedNeuro; + ParanetIncentivesPoolStorage + .getVoterAtIndex(ParanetIncentivesPoolStorage.votersIndexes(msg.sender)) + .claimedToken; } function getTotalAllProposalVotersIncentiveEstimation() public view returns (uint256) { return _getIncentiveEstimation( - paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage(), - paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro() + ParanetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage(), + ParanetIncentivesPoolStorage.totalVotersclaimedToken() ); } function getClaimableProposalVoterRewardAmount() public view returns (uint256) { if ( - paranetNeuroIncentivesPoolStorage.getVotersCount() == 0 || - paranetNeuroIncentivesPoolStorage - .getVoterAtIndex(paranetNeuroIncentivesPoolStorage.votersIndexes(msg.sender)) - .addr != + ParanetIncentivesPoolStorage.getVotersCount() == 0 || + ParanetIncentivesPoolStorage.getVoterAtIndex(ParanetIncentivesPoolStorage.votersIndexes(msg.sender)).addr != msg.sender ) { return 0; } - uint256 neuroReward = getTotalProposalVoterIncentiveEstimation(); + uint256 tokenReward = getTotalProposalVoterIncentiveEstimation(); - uint256 voterRewardLimit = ((((paranetNeuroIncentivesPoolStorage.getBalance() + - paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro() + - paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro() + - paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro()) * - paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage()) / + uint256 voterRewardLimit = ((((ParanetIncentivesPoolStorage.getBalance() + + ParanetIncentivesPoolStorage.totalMinersclaimedToken() + + ParanetIncentivesPoolStorage.totalOperatorsclaimedToken() + + ParanetIncentivesPoolStorage.totalVotersclaimedToken()) * + ParanetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage()) / ParanetLib.PERCENTAGE_SCALING_FACTOR) * - paranetNeuroIncentivesPoolStorage - .getVoterAtIndex(paranetNeuroIncentivesPoolStorage.votersIndexes(msg.sender)) + ParanetIncentivesPoolStorage + .getVoterAtIndex(ParanetIncentivesPoolStorage.votersIndexes(msg.sender)) .weight) / ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT; return - paranetNeuroIncentivesPoolStorage - .getVoterAtIndex(paranetNeuroIncentivesPoolStorage.votersIndexes(msg.sender)) - .claimedNeuro + - neuroReward <= + ParanetIncentivesPoolStorage + .getVoterAtIndex(ParanetIncentivesPoolStorage.votersIndexes(msg.sender)) + .claimedToken + + tokenReward <= voterRewardLimit - ? neuroReward + ? tokenReward : voterRewardLimit - - paranetNeuroIncentivesPoolStorage - .getVoterAtIndex(paranetNeuroIncentivesPoolStorage.votersIndexes(msg.sender)) - .claimedNeuro; + ParanetIncentivesPoolStorage + .getVoterAtIndex(ParanetIncentivesPoolStorage.votersIndexes(msg.sender)) + .claimedToken; } function getClaimableAllProposalVotersRewardAmount() public view returns (uint256) { - uint256 neuroReward = getTotalAllProposalVotersIncentiveEstimation(); + uint256 tokenReward = getTotalAllProposalVotersIncentiveEstimation(); - uint256 votersRewardLimit = ((paranetNeuroIncentivesPoolStorage.getBalance() + - paranetNeuroIncentivesPoolStorage.totalMinersClaimedNeuro() + - paranetNeuroIncentivesPoolStorage.totalOperatorsClaimedNeuro() + - paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro()) * - paranetNeuroIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage()) / + uint256 votersRewardLimit = ((ParanetIncentivesPoolStorage.getBalance() + + ParanetIncentivesPoolStorage.totalMinersclaimedToken() + + ParanetIncentivesPoolStorage.totalOperatorsclaimedToken() + + ParanetIncentivesPoolStorage.totalVotersclaimedToken()) * + ParanetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage()) / ParanetLib.PERCENTAGE_SCALING_FACTOR; return - paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro() + neuroReward <= votersRewardLimit - ? neuroReward - : votersRewardLimit - paranetNeuroIncentivesPoolStorage.totalVotersClaimedNeuro(); + ParanetIncentivesPoolStorage.totalVotersclaimedToken() + tokenReward <= votersRewardLimit + ? tokenReward + : votersRewardLimit - ParanetIncentivesPoolStorage.totalVotersclaimedToken(); } function claimIncentivizationProposalVoterReward() external onlyParanetIncentivizationProposalVoter { - if (paranetNeuroIncentivesPoolStorage.cumulativeVotersWeight() != ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT) { + if (ParanetIncentivesPoolStorage.cumulativeVotersWeight() != ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT) { revert ParanetLib.InvalidCumulativeVotersWeight( - paranetNeuroIncentivesPoolStorage.paranetId(), - paranetNeuroIncentivesPoolStorage.cumulativeVotersWeight(), + ParanetIncentivesPoolStorage.paranetId(), + ParanetIncentivesPoolStorage.cumulativeVotersWeight(), ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT ); } - uint256 claimableNeuroReward = getClaimableProposalVoterRewardAmount(); + uint256 claimableTokenReward = getClaimableProposalVoterRewardAmount(); - if (claimableNeuroReward == 0) { - revert ParanetLib.NoRewardAvailable(paranetNeuroIncentivesPoolStorage.paranetId(), msg.sender); + if (claimableTokenReward == 0) { + revert ParanetLib.NoRewardAvailable(ParanetIncentivesPoolStorage.paranetId(), msg.sender); } - paranetNeuroIncentivesPoolStorage - .getVoterAtIndex(paranetNeuroIncentivesPoolStorage.votersIndexes(msg.sender)) - .claimedNeuro += claimableNeuroReward; - paranetNeuroIncentivesPoolStorage.addTotalVotersClaimedNeuro(claimableNeuroReward); + ParanetIncentivesPoolStorage + .getVoterAtIndex(ParanetIncentivesPoolStorage.votersIndexes(msg.sender)) + .claimedToken += claimableTokenReward; + ParanetIncentivesPoolStorage.addTotalVotersclaimedToken(claimableTokenReward); - paranetNeuroIncentivesPoolStorage.transferReward(msg.sender, claimableNeuroReward); + ParanetIncentivesPoolStorage.transferReward(msg.sender, claimableTokenReward); } function _getIncentiveEstimation( uint16 rewardPercentage, - uint256 totalClaimedNeuro + uint256 totalclaimedToken ) internal view returns (uint256) { - uint256 effectiveNeuroEmissionMultiplier = getEffectiveNeuroEmissionMultiplier(block.timestamp); + uint256 effectiveTokenEmissionMultiplier = getEffectiveTokenEmissionMultiplier(block.timestamp); uint96 cumulativeKnowledgeValuePart = (paranetsRegistry.getCumulativeKnowledgeValue( - paranetNeuroIncentivesPoolStorage.paranetId() + ParanetIncentivesPoolStorage.paranetId() ) * rewardPercentage) / ParanetLib.PERCENTAGE_SCALING_FACTOR; uint96 rewardedTracSpentPart = uint96( - (totalClaimedNeuro * ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) / effectiveNeuroEmissionMultiplier + (totalclaimedToken * ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) / effectiveTokenEmissionMultiplier ); if (cumulativeKnowledgeValuePart - rewardedTracSpentPart < ParanetLib.TOKENS_DIGITS_DIFF) { @@ -486,12 +480,12 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned, IParanetNeuroIncentiv } return - ((cumulativeKnowledgeValuePart * effectiveNeuroEmissionMultiplier) / - ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) - totalClaimedNeuro; + ((cumulativeKnowledgeValuePart * effectiveTokenEmissionMultiplier) / + ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) - totalclaimedToken; } - function getParanetNeuroIncentivesPoolStorage() external view returns (address) { - return address(paranetNeuroIncentivesPoolStorage); + function getParanetIncentivesPoolStorage() external view returns (address) { + return address(ParanetIncentivesPoolStorage); } function _checkHubOwner() internal view virtual { @@ -499,7 +493,7 @@ contract ParanetNeuroIncentivesPool is INamed, IVersioned, IParanetNeuroIncentiv } function _checkVotersRegistrar() internal view virtual { - require(msg.sender == paranetNeuroIncentivesPoolStorage.votersRegistrar(), "Fn can only be used by registrar"); + require(msg.sender == ParanetIncentivesPoolStorage.votersRegistrar(), "Fn can only be used by registrar"); } function _checkParanetOperator() internal view virtual { diff --git a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol index 2836f5e0..3c37d3bf 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol @@ -11,15 +11,15 @@ import {IVersioned} from "../interfaces/IVersioned.sol"; import {IInitializable} from "../interfaces/IInitializable.sol"; import {ParanetLib} from "../libraries/ParanetLib.sol"; -contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInitializable { - event NeuroRewardDeposit(address sender, uint256 amount); +contract ParanetIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInitializable { + event TokenRewardDeposit(address sender, uint256 amount); event VoterWeightUpdated(address indexed voter, uint96 oldWeight, uint96 newWeight); - event TotalMinersClaimedNeuroSet(uint256 oldAmount, uint256 newAmount); - event TotalOperatorsClaimedNeuroSet(uint256 oldAmount, uint256 newAmount); - event TotalVotersClaimedNeuroSet(uint256 oldAmount, uint256 newAmount); - event TotalMinersClaimedNeuroDecremented(uint256 amount, uint256 newTotal); - event TotalOperatorsClaimedNeuroDecremented(uint256 amount, uint256 newTotal); - event TotalVotersClaimedNeuroDecremented(uint256 amount, uint256 newTotal); + event TotalMinersclaimedTokenSet(uint256 oldAmount, uint256 newAmount); + event TotalOperatorsclaimedTokenSet(uint256 oldAmount, uint256 newAmount); + event TotalVotersclaimedTokenSet(uint256 oldAmount, uint256 newAmount); + event TotalMinersclaimedTokenDecremented(uint256 amount, uint256 newTotal); + event TotalOperatorsclaimedTokenDecremented(uint256 amount, uint256 newTotal); + event TotalVotersclaimedTokenDecremented(uint256 amount, uint256 newTotal); event VotersRegistrarTransferred(address indexed previousRegistrar, address indexed newRegistrar); event MinerRewardProfileAdded(address indexed miner, uint256 amount); event MinerRewardIncreased(address indexed miner, uint256 additionalAmount, uint256 newTotal); @@ -32,28 +32,28 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, event IncentivesPoolAddressSet(address indexed oldAddress, address indexed newAddress); event RewardTransferred(address indexed recipient, uint256 amount); - string private constant _NAME = "ParanetNeuroIncentivesPoolStorage"; + string private constant _NAME = "ParanetIncentivesPoolStorage"; string private constant _VERSION = "1.0.0"; uint256 private constant MAX_VOTERS_PER_BATCH = 100; IERC20 public token; ParanetsRegistry public paranetsRegistry; - address public paranetNeuroIncentivesPoolAddress; + address public ParanetIncentivesPoolAddress; bytes32 public paranetId; - // Percentage of how much tokens from total NEURO emission goes to the Paranet Operator + // Percentage of how much tokens from total TOKEN emission goes to the Paranet Operator // Minimum: 0, Maximum: 10,000 (which is 100%) uint16 public paranetOperatorRewardPercentage; - // Percentage of how much tokens from total NEURO emission goes to the Paranet Incentivization + // Percentage of how much tokens from total TOKEN emission goes to the Paranet Incentivization // Proposal Voters. Minimum: 0, Maximum: 10,000 (which is 100%) uint16 public paranetIncentivizationProposalVotersRewardPercentage; - // Address which can set Voters list and update Total NEURO Emission multiplier + // Address which can set Voters list and update Total TOKEN Emission multiplier address public votersRegistrar; - uint256 public totalMinersClaimedNeuro; - uint256 public totalOperatorsClaimedNeuro; - uint256 public totalVotersClaimedNeuro; + uint256 public totalMinersclaimedToken; + uint256 public totalOperatorsclaimedToken; + uint256 public totalVotersclaimedToken; ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[] public claimedMinerRewards; mapping(address => uint256) public claimedMinerRewardsIndexes; @@ -116,11 +116,11 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, } receive() external payable { - emit NeuroRewardDeposit(msg.sender, msg.value); + emit TokenRewardDeposit(msg.sender, msg.value); } function totalNeuroReceived() external view returns (uint256) { - return getBalance() + totalMinersClaimedNeuro + totalOperatorsClaimedNeuro + totalVotersClaimedNeuro; + return getBalance() + totalMinersclaimedToken + totalOperatorsclaimedToken + totalVotersclaimedToken; } function transferVotersRegistrarRole(address newRegistrar) external onlyVotersRegistrar { @@ -138,45 +138,45 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, return claimedMinerRewards; } - function minerClaimedNeuro(address minerAddress) external view returns (uint256) { - return claimedMinerRewards[claimedMinerRewardsIndexes[minerAddress]].claimedNeuro; + function minerclaimedToken(address minerAddress) external view returns (uint256) { + return claimedMinerRewards[claimedMinerRewardsIndexes[minerAddress]].claimedToken; } - function operatorClaimedNeuro(address operatorAddress) external view returns (uint256) { - return claimedOperatorRewards[claimedOperatorRewardsIndexes[operatorAddress]].claimedNeuro; + function operatorclaimedToken(address operatorAddress) external view returns (uint256) { + return claimedOperatorRewards[claimedOperatorRewardsIndexes[operatorAddress]].claimedToken; } - function addMinerClaimedRewardProfile(address addr, uint256 claimableNeuroReward) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); + function addMinerClaimedRewardProfile(address addr, uint256 claimableTokenReward) external { + require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); claimedMinerRewardsIndexes[addr] = claimedMinerRewards.length; claimedMinerRewards.push( - ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile({addr: addr, claimedNeuro: claimableNeuroReward}) + ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile({addr: addr, claimedToken: claimableTokenReward}) ); - emit MinerRewardProfileAdded(addr, claimableNeuroReward); + emit MinerRewardProfileAdded(addr, claimableTokenReward); } - function addMinerClaimedReward(address addr, uint256 claimableNeuroReward) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); - uint256 newTotal = claimedMinerRewards[claimedMinerRewardsIndexes[addr]].claimedNeuro + claimableNeuroReward; - claimedMinerRewards[claimedMinerRewardsIndexes[addr]].claimedNeuro = newTotal; - emit MinerRewardIncreased(addr, claimableNeuroReward, newTotal); + function addMinerClaimedReward(address addr, uint256 claimableTokenReward) external { + require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + uint256 newTotal = claimedMinerRewards[claimedMinerRewardsIndexes[addr]].claimedToken + claimableTokenReward; + claimedMinerRewards[claimedMinerRewardsIndexes[addr]].claimedToken = newTotal; + emit MinerRewardIncreased(addr, claimableTokenReward, newTotal); } - function addOperatorClaimedRewardsProfile(address addr, uint256 claimableNeuroReward) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); + function addOperatorClaimedRewardsProfile(address addr, uint256 claimableTokenReward) external { + require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); claimedOperatorRewardsIndexes[addr] = claimedOperatorRewards.length; claimedOperatorRewards.push( - ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile({addr: addr, claimedNeuro: claimableNeuroReward}) + ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile({addr: addr, claimedToken: claimableTokenReward}) ); - emit OperatorRewardProfileAdded(addr, claimableNeuroReward); + emit OperatorRewardProfileAdded(addr, claimableTokenReward); } - function addClaimedOperatorReward(address addr, uint256 claimableNeuroReward) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); - uint256 newTotal = claimedOperatorRewards[claimedOperatorRewardsIndexes[addr]].claimedNeuro + - claimableNeuroReward; - claimedOperatorRewards[claimedOperatorRewardsIndexes[addr]].claimedNeuro = newTotal; - emit OperatorRewardIncreased(addr, claimableNeuroReward, newTotal); + function addClaimedOperatorReward(address addr, uint256 claimableTokenReward) external { + require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + uint256 newTotal = claimedOperatorRewards[claimedOperatorRewardsIndexes[addr]].claimedToken + + claimableTokenReward; + claimedOperatorRewards[claimedOperatorRewardsIndexes[addr]].claimedToken = newTotal; + emit OperatorRewardIncreased(addr, claimableTokenReward, newTotal); } function getAllRewardedOperators() @@ -202,7 +202,7 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, votersIndexes[voterAddr] = voters.length; voters.push( - ParanetLib.ParanetIncentivizationProposalVoter({addr: voterAddr, weight: weight, claimedNeuro: 0}) + ParanetLib.ParanetIncentivizationProposalVoter({addr: voterAddr, weight: weight, claimedToken: 0}) ); cumulativeVotersWeight += weight; @@ -283,11 +283,11 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, return (idx < voters.length && voters[idx].addr == addr); } - function addVoterClaimedNeuro(address voter, uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); + function addVoterclaimedToken(address voter, uint256 amount) external { + require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); uint256 idx = votersIndexes[voter]; if (idx < voters.length && voters[idx].addr == voter) { - voters[idx].claimedNeuro += amount; + voters[idx].claimedToken += amount; emit VoterRewardClaimed(voter, amount); } } @@ -314,25 +314,25 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, return claimedOperatorRewards[index]; } - function addTotalMinersClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); - totalMinersClaimedNeuro += amount; + function addTotalMinersclaimedToken(uint256 amount) external { + require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + totalMinersclaimedToken += amount; } - function addTotalOperatorsClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); - totalOperatorsClaimedNeuro += amount; + function addTotalOperatorsclaimedToken(uint256 amount) external { + require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + totalOperatorsclaimedToken += amount; } - function addTotalVotersClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); - totalVotersClaimedNeuro += amount; + function addTotalVotersclaimedToken(uint256 amount) external { + require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + totalVotersclaimedToken += amount; } - function setParanetNeuroIncentivesPool(address _paranetNeuroIncentivesPoolAddress) external onlyContracts { - address oldAddress = paranetNeuroIncentivesPoolAddress; - paranetNeuroIncentivesPoolAddress = _paranetNeuroIncentivesPoolAddress; - emit IncentivesPoolAddressSet(oldAddress, _paranetNeuroIncentivesPoolAddress); + function setParanetIncentivesPool(address _ParanetIncentivesPoolAddress) external onlyContracts { + address oldAddress = ParanetIncentivesPoolAddress; + ParanetIncentivesPoolAddress = _ParanetIncentivesPoolAddress; + emit IncentivesPoolAddressSet(oldAddress, _ParanetIncentivesPoolAddress); } function getBalance() public view returns (uint256) { @@ -344,7 +344,7 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, } function transferReward(address rewardAddress, uint256 amount) public { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); + require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); if (address(token) == address(0)) { payable(rewardAddress).transfer(amount); } else { @@ -353,34 +353,34 @@ contract ParanetNeuroIncentivesPoolStorage is INamed, IVersioned, HubDependent, emit RewardTransferred(rewardAddress, amount); } - function setTotalMinersClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); - totalMinersClaimedNeuro = amount; + function setTotalMinersclaimedToken(uint256 amount) external { + require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + totalMinersclaimedToken = amount; } - function setTotalOperatorsClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); - totalOperatorsClaimedNeuro = amount; + function setTotalOperatorsclaimedToken(uint256 amount) external { + require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + totalOperatorsclaimedToken = amount; } - function setTotalVotersClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); - totalVotersClaimedNeuro = amount; + function setTotalVotersclaimedToken(uint256 amount) external { + require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + totalVotersclaimedToken = amount; } - function decrementTotalMinersClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); - totalMinersClaimedNeuro -= amount; + function decrementTotalMinersclaimedToken(uint256 amount) external { + require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + totalMinersclaimedToken -= amount; } - function decrementTotalOperatorsClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); - totalOperatorsClaimedNeuro -= amount; + function decrementTotalOperatorsclaimedToken(uint256 amount) external { + require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + totalOperatorsclaimedToken -= amount; } - function decrementTotalVotersClaimedNeuro(uint256 amount) external { - require(msg.sender == paranetNeuroIncentivesPoolAddress, "Caller is not incentives pool contract"); - totalVotersClaimedNeuro -= amount; + function decrementTotalVotersclaimedToken(uint256 amount) external { + require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + totalVotersclaimedToken -= amount; } function getPaginatedClaimedMinerRewards( From 5b1ae4fa44e516eb7c8565e599cdc622bcaac20e Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 14 Feb 2025 12:50:00 +0100 Subject: [PATCH 099/153] Fix redeployIncentivesPool require --- .../paranets/ParanetIncentivesPoolFactory.sol | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index 84b1cf2f..24357aa2 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -4,8 +4,8 @@ pragma solidity ^0.8.20; import {Hub} from "../storage/Hub.sol"; import {ParanetsRegistry} from "../storage/paranets/ParanetsRegistry.sol"; -import {ParanetNeuroIncentivesPool} from "./ParanetNeuroIncentivesPool.sol"; -import {ParanetNeuroIncentivesPoolStorage} from "./ParanetNeuroIncentivesPoolStorage.sol"; +import {ParanetIncentivesPool} from "./ParanetIncentivesPool.sol"; +import {ParanetIncentivesPoolStorage} from "./ParanetIncentivesPoolStorage.sol"; import {ParanetIncentivesPoolFactoryHelper} from "./ParanetIncentivesPoolFactoryHelper.sol"; import {KnowledgeCollectionStorage} from "../storage/KnowledgeCollectionStorage.sol"; import {ContractStatus} from "../abstract/ContractStatus.sol"; @@ -60,11 +60,11 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn return _VERSION; } - function deployNeuroIncentivesPool( + function deployIncentivesPool( address paranetKCStorageContract, uint256 paranetKCTokenId, uint256 paranetKATokenId, - uint256 tracToNeuroEmissionMultiplier, + uint256 tracToTokenEmissionMultiplier, uint16 paranetOperatorRewardPercentage, uint16 paranetIncentivizationProposalVotersRewardPercentage, string calldata incentivesPoolName, @@ -75,7 +75,7 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn require(pr.paranetExists(paranetId)); require(pr.hasIncentivesPoolByName(paranetId, incentivesPoolName)); - ParanetNeuroIncentivesPoolStorage storage_ = new ParanetNeuroIncentivesPoolStorage( + ParanetIncentivesPoolStorage storage_ = new ParanetIncentivesPoolStorage( address(hub), rewardTokenAddress, paranetId, @@ -84,9 +84,9 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn ); address storageAddress = address(storage_); - address poolAddress = paranetIncentivesPoolFactoryHelper.deployNeuroIncentivesPool( + address poolAddress = paranetIncentivesPoolFactoryHelper.deployIncentivesPool( storageAddress, - tracToNeuroEmissionMultiplier, + tracToTokenEmissionMultiplier, address(storage_) ); @@ -96,7 +96,7 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn emit ParanetIncentivesPoolDeployed(paranetId, storageAddress, poolAddress, rewardTokenAddress); } - function redeployNeuroIncentivesPool( + function redeployIncentivesPool( address paranetKCStorageContract, uint256 paranetKCTokenId, uint256 paranetKATokenId, @@ -106,18 +106,18 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn ParanetsRegistry pr = paranetsRegistry; require(pr.paranetExists(paranetId)); - require(pr.hasIncentivesPoolByStorageAddress(paranetId, storageAddress)); + require(!pr.hasIncentivesPoolByStorageAddress(paranetId, storageAddress)); - ParanetNeuroIncentivesPoolStorage storage_ = ParanetNeuroIncentivesPoolStorage(payable(storageAddress)); + ParanetIncentivesPoolStorage storage_ = ParanetIncentivesPoolStorage(payable(storageAddress)); require(storage_.paranetId() == paranetId); - address oldPoolAddress = storage_.paranetNeuroIncentivesPoolAddress(); - uint256 tracToNeuroEmissionMultiplier = ParanetNeuroIncentivesPool(oldPoolAddress) - .getEffectiveNeuroEmissionMultiplier(block.timestamp); + address oldPoolAddress = storage_.ParanetIncentivesPoolAddress(); + uint256 tracToTokenEmissionMultiplier = ParanetIncentivesPool(oldPoolAddress) + .getEffectiveTokenEmissionMultiplier(block.timestamp); - address newPoolAddress = paranetIncentivesPoolFactoryHelper.deployNeuroIncentivesPool( + address newPoolAddress = paranetIncentivesPoolFactoryHelper.deployIncentivesPool( storageAddress, - tracToNeuroEmissionMultiplier, + tracToTokenEmissionMultiplier, address(storage_) ); From 655d678ae3cf490d74c455cafc59e0e5daebc367 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 14 Feb 2025 13:20:11 +0100 Subject: [PATCH 100/153] fixes --- .../interfaces/IParanetIncentivesPool.sol | 6 + .../IParanetNeuroIncentivesPool.sol | 6 - contracts/libraries/ParanetLib.sol | 8 +- contracts/paranets/Paranet.sol | 108 +++----- ...ivesPool.sol => ParanetIncentivesPool.sol} | 248 +++++++++--------- ...e.sol => ParanetIncentivesPoolStorage.sol} | 2 +- .../ParanetKnowledgeMinersRegistry.sol | 26 +- 7 files changed, 186 insertions(+), 218 deletions(-) create mode 100644 contracts/interfaces/IParanetIncentivesPool.sol delete mode 100644 contracts/interfaces/IParanetNeuroIncentivesPool.sol rename contracts/paranets/{ParanetNeuroIncentivesPool.sol => ParanetIncentivesPool.sol} (67%) rename contracts/paranets/{ParanetNeuroIncentivesPoolStorage.sol => ParanetIncentivesPoolStorage.sol} (99%) diff --git a/contracts/interfaces/IParanetIncentivesPool.sol b/contracts/interfaces/IParanetIncentivesPool.sol new file mode 100644 index 00000000..50b24209 --- /dev/null +++ b/contracts/interfaces/IParanetIncentivesPool.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +interface IParanetIncentivesPool { + function getParanetIncentivesPoolStorage() external view returns (address); +} diff --git a/contracts/interfaces/IParanetNeuroIncentivesPool.sol b/contracts/interfaces/IParanetNeuroIncentivesPool.sol deleted file mode 100644 index 888acabd..00000000 --- a/contracts/interfaces/IParanetNeuroIncentivesPool.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.20; - -interface IParanetNeuroIncentivesPool { - function getParanetNeuroIncentivesPoolStorage() external view returns (address); -} diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index 2c9f08ee..a56cdd1d 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -127,7 +127,7 @@ library ParanetLib { mapping(bytes32 => mapping(bytes32 => uint256)) updatingKnowledgeCollectionsStateIndexes; mapping(bytes32 => uint96) cumulativeTracSpent; mapping(bytes32 => uint96) unrewardedTracSpent; - mapping(bytes32 => uint256) cumulativeAwardedNeuro; + mapping(bytes32 => uint256) cumulativeAwardedToken; } struct KnowledgeMinerMetadata { @@ -150,7 +150,7 @@ library ParanetLib { uint96 updateTokenAmount; } - struct NeuroEmissionMultiplier { + struct TokenEmissionMultiplier { uint256 multiplier; uint256 timestamp; bool finalized; @@ -158,7 +158,7 @@ library ParanetLib { struct ParanetIncentivesPoolClaimedRewardsProfile { address addr; - uint256 claimedNeuro; + uint256 claimedToken; } struct ParanetIncentivizationProposalVoterInput { @@ -169,7 +169,7 @@ library ParanetLib { struct ParanetIncentivizationProposalVoter { address addr; uint96 weight; - uint256 claimedNeuro; + uint256 claimedToken; } error ParanetHasAlreadyBeenRegistered( diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 54ece972..8d981889 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -1077,41 +1077,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); } - uint8 minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); - - // Check if paranet is curated and if knowledge miner is whitelisted - if ( - minersAccessPolicy == MINERS_ACCESS_POLICY_PERMISSIONED && - !pr.isKnowledgeMinerRegistered(paranetId, msg.sender) - ) { - revert ParanetLib.ParanetCuratedMinerDoesntExist(paranetId, msg.sender); - // Should this be done in both cases why would OPEN have separeted logic ??? - } else if (minersAccessPolicy == MINERS_ACCESS_POLICY_OPEN) { - // Check if Knowledge Miner has profile - // If not: Create a profile - if (!paranetKnowledgeMinersRegistry.knowledgeMinerExists(msg.sender)) { - paranetKnowledgeMinersRegistry.registerKnowledgeMiner(msg.sender); - } - - // Check if Knowledge Miner is registered on paranet - if (!pr.isKnowledgeMinerRegistered(paranetId, msg.sender)) { - pr.addKnowledgeMiner(paranetId, msg.sender); - } - } - - if ( - paranetKnowledgeCollectionsRegistry.isParanetKnowledgeCollection( - keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)) - ) - ) { - revert ParanetLib.KnowledgeCollectionIsAPartOfOtherParanet( - knowledgeCollectionStorageContract, - knowledgeCollectionTokenId, - paranetKnowledgeCollectionsRegistry.getParanetId( - keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)) - ) - ); - } + _updateKnowledgeMinerMetadata(paranetId); require( pr.getKnowledgeCollectionsSubmissionPolicy(paranetId) != KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, @@ -1121,11 +1087,6 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // Update KnowledgeMiner metadata _updateSubmittedKnowledgeCollectionMetadata( paranetId, - knowledgeCollectionStorageContract, - knowledgeCollectionTokenId - ); - - emit KnowledgeCollectionSubmittedToParanet( paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId, @@ -1288,40 +1249,11 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pss.reviewKnowledgeCollection(paranetId, knowledgeCollectionId, accepted); if (accepted) { - ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; - uint8 minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); - // Check if paranet is curated and if knowledge miner is whitelisted - if ( - minersAccessPolicy == MINERS_ACCESS_POLICY_PERMISSIONED && - !pr.isKnowledgeMinerRegistered(paranetId, msg.sender) - ) { - revert ParanetLib.ParanetCuratedMinerDoesntExist(paranetId, msg.sender); - // Should this be done in both cases why would OPEN have separeted logic ??? - } else if (minersAccessPolicy == MINERS_ACCESS_POLICY_OPEN) { - // Check if Knowledge Miner has profile - // If not: Create a profile - if (!pkmr.knowledgeMinerExists(msg.sender)) { - pkmr.registerKnowledgeMiner(msg.sender); - } - - // Check if Knowledge Miner is registered on paranet - if (!pr.isKnowledgeMinerRegistered(paranetId, msg.sender)) { - pr.addKnowledgeMiner(paranetId, msg.sender); - } - } - - KnowledgeCollectionStorage kcs = KnowledgeCollectionStorage(knowledgeCollectionStorageContract); - uint96 remainingTokenAmount = kcs.getTokenAmount(knowledgeCollectionTokenId); - KnowledgeCollectionLib.MerkleRoot[] memory merkleRoots = kcs.getMerkleRoots(knowledgeCollectionTokenId); + _updateKnowledgeMinerMetadata(paranetId); // Update KnowledgeMiner metadata _updateSubmittedKnowledgeCollectionMetadata( paranetId, - knowledgeCollectionStorageContract, - knowledgeCollectionTokenId - ); - - emit KnowledgeCollectionSubmittedToParanet( paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId, @@ -1331,6 +1263,31 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { } } + function _updateKnowledgeMinerMetadata(bytes32 paranetId) internal { + ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; + ParanetsRegistry pr = paranetsRegistry; + uint8 minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); + // Check if paranet is curated and if knowledge miner is whitelisted + if ( + minersAccessPolicy == MINERS_ACCESS_POLICY_PERMISSIONED && + !pr.isKnowledgeMinerRegistered(paranetId, msg.sender) + ) { + revert ParanetLib.ParanetCuratedMinerDoesntExist(paranetId, msg.sender); + // Should this be done in both cases why would OPEN have separeted logic ??? + } else if (minersAccessPolicy == MINERS_ACCESS_POLICY_OPEN) { + // Check if Knowledge Miner has profile + // If not: Create a profile + if (!pkmr.knowledgeMinerExists(msg.sender)) { + pkmr.registerKnowledgeMiner(msg.sender); + } + + // Check if Knowledge Miner is registered on paranet + if (!pr.isKnowledgeMinerRegistered(paranetId, msg.sender)) { + pr.addKnowledgeMiner(paranetId, msg.sender); + } + } + } + // function processUpdatedKnowledgeCollectionStatesMetadata( // address paranetKCStorageContract, // uint256 paranetKCTokenId, @@ -1347,6 +1304,9 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { function _updateSubmittedKnowledgeCollectionMetadata( bytes32 paranetId, + address paranetKCStorageContract, + uint256 paranetKnowledgeCollectionTokenId, + uint256 paranetKnowledgeAssetTokenId, address knowledgeCollectionStorageContract, uint256 knowledgeCollectionTokenId ) internal { @@ -1397,6 +1357,14 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pkmr.addUnrewardedTracSpent(msg.sender, paranetId, remainingTokenAmount); pkmr.incrementTotalSubmittedKnowledgeCollectionsCount(msg.sender); pkmr.addTotalTracSpent(msg.sender, remainingTokenAmount); + + emit KnowledgeCollectionSubmittedToParanet( + paranetKCStorageContract, + paranetKnowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId, + knowledgeCollectionStorageContract, + knowledgeCollectionTokenId + ); } // function _processUpdatedKnowledgeCollectionStatesMetadata( diff --git a/contracts/paranets/ParanetNeuroIncentivesPool.sol b/contracts/paranets/ParanetIncentivesPool.sol similarity index 67% rename from contracts/paranets/ParanetNeuroIncentivesPool.sol rename to contracts/paranets/ParanetIncentivesPool.sol index f3e2ac90..db156e86 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPool.sol +++ b/contracts/paranets/ParanetIncentivesPool.sol @@ -22,7 +22,7 @@ contract ParanetIncentivesPool is INamed, IVersioned, IParanetIncentivesPool { Hub public hub; ParanetsRegistry public paranetsRegistry; ParanetKnowledgeMinersRegistry public paranetKnowledgeMinersRegistry; - ParanetIncentivesPoolStorage public ParanetIncentivesPoolStorage; + ParanetIncentivesPoolStorage public paranetIncentivesPoolStorage; // Array of Total TOKEN Emission Multipliers // Total TOKEN Emission Multiplier = Ratio of how much TOKEN is released per 1 TRAC spent @@ -32,22 +32,22 @@ contract ParanetIncentivesPool is INamed, IVersioned, IParanetIncentivesPool { // 0.5 * 10^12 = 5 * 10^11 = 0.5 TOKEN per 1 TRAC // 1 = 1 TOKEN wei per 1 TRAC // - ParanetLib.TokenEmissionMultiplier[] public TokenEmissionMultipliers; + ParanetLib.TokenEmissionMultiplier[] public tokenEmissionMultipliers; - uint256 public TokenEmissionMultiplierUpdateDelay = 7 days; + uint256 public tokenEmissionMultiplierUpdateDelay = 7 days; // solhint-disable-next-line no-empty-blocks constructor( address hubAddress, address knowledgeMinersRegistryAddress, - address ParanetIncentivesPoolStorageAddress, + address paranetIncentivesPoolStorageAddress, uint256 tracToTokenEmissionMultiplier ) { hub = Hub(hubAddress); paranetKnowledgeMinersRegistry = ParanetKnowledgeMinersRegistry(knowledgeMinersRegistryAddress); - ParanetIncentivesPoolStorage = ParanetIncentivesPoolStorage(payable(ParanetIncentivesPoolStorageAddress)); + paranetIncentivesPoolStorage = ParanetIncentivesPoolStorage(payable(paranetIncentivesPoolStorageAddress)); - TokenEmissionMultipliers.push( + tokenEmissionMultipliers.push( ParanetLib.TokenEmissionMultiplier({ multiplier: tracToTokenEmissionMultiplier, timestamp: block.timestamp, @@ -89,32 +89,32 @@ contract ParanetIncentivesPool is INamed, IVersioned, IParanetIncentivesPool { return _VERSION; } - function updateTokenEmissionMultiplierUpdateDelay(uint256 newDelay) external onlyHubOwner { - TokenEmissionMultiplierUpdateDelay = newDelay; + function updatetokenEmissionMultiplierUpdateDelay(uint256 newDelay) external onlyHubOwner { + tokenEmissionMultiplierUpdateDelay = newDelay; } function voterclaimedToken(address addr) external view returns (uint256) { - uint256 voterIndex = ParanetIncentivesPoolStorage.votersIndexes(addr); + uint256 voterIndex = paranetIncentivesPoolStorage.votersIndexes(addr); // If the index is out of range or the stored voter doesn't match `voterAddress`, // return 0 as a default. if ( - voterIndex >= ParanetIncentivesPoolStorage.getVotersCount() || - ParanetIncentivesPoolStorage.getVoterAtIndex(voterIndex).addr != addr + voterIndex >= paranetIncentivesPoolStorage.getVotersCount() || + paranetIncentivesPoolStorage.getVoterAtIndex(voterIndex).addr != addr ) { return 0; } - return ParanetIncentivesPoolStorage.getVoterAtIndex(voterIndex).claimedToken; + return paranetIncentivesPoolStorage.getVoterAtIndex(voterIndex).claimedToken; } function isKnowledgeMiner(address addr) public view returns (bool) { - return paranetsRegistry.isKnowledgeMinerRegistered(ParanetIncentivesPoolStorage.paranetId(), addr); + return paranetsRegistry.isKnowledgeMinerRegistered(paranetIncentivesPoolStorage.paranetId(), addr); } function isParanetOperator(address addr) public view returns (bool) { (address paranetKCStorageContract, uint256 paranetKCTokenId, uint256 paranetKATokenId) = paranetsRegistry - .getParanetKnowledgeAssetLocator(ParanetIncentivesPoolStorage.paranetId()); + .getParanetKnowledgeAssetLocator(paranetIncentivesPoolStorage.paranetId()); KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage(paranetKCStorageContract); @@ -128,71 +128,71 @@ contract ParanetIncentivesPool is INamed, IVersioned, IParanetIncentivesPool { } function isProposalVoter(address addr) public view returns (bool) { - return (ParanetIncentivesPoolStorage.getVotersCount() != 0 && - ParanetIncentivesPoolStorage.getVoterAtIndex(ParanetIncentivesPoolStorage.votersIndexes(addr)).addr == + return (paranetIncentivesPoolStorage.getVotersCount() != 0 && + paranetIncentivesPoolStorage.getVoterAtIndex(paranetIncentivesPoolStorage.votersIndexes(addr)).addr == addr); } - function getTokenEmissionMultipliers() external view returns (ParanetLib.TokenEmissionMultiplier[] memory) { - return TokenEmissionMultipliers; + function gettokenEmissionMultipliers() external view returns (ParanetLib.TokenEmissionMultiplier[] memory) { + return tokenEmissionMultipliers; } function getEffectiveTokenEmissionMultiplier(uint256 timestamp) public view returns (uint256) { - for (uint256 i = TokenEmissionMultipliers.length; i > 0; i--) { - if (TokenEmissionMultipliers[i - 1].finalized && timestamp >= TokenEmissionMultipliers[i - 1].timestamp) { - return TokenEmissionMultipliers[i - 1].multiplier; + for (uint256 i = tokenEmissionMultipliers.length; i > 0; i--) { + if (tokenEmissionMultipliers[i - 1].finalized && timestamp >= tokenEmissionMultipliers[i - 1].timestamp) { + return tokenEmissionMultipliers[i - 1].multiplier; } } - return TokenEmissionMultipliers[0].multiplier; + return tokenEmissionMultipliers[0].multiplier; } // TODO:Should there be some check of this value? function initiateTokenEmissionMultiplierUpdate(uint256 newMultiplier) external onlyVotersRegistrar { - if (!TokenEmissionMultipliers[TokenEmissionMultipliers.length - 1].finalized) { - TokenEmissionMultipliers[TokenEmissionMultipliers.length - 1].multiplier = newMultiplier; - TokenEmissionMultipliers[TokenEmissionMultipliers.length - 1].timestamp = + if (!tokenEmissionMultipliers[tokenEmissionMultipliers.length - 1].finalized) { + tokenEmissionMultipliers[tokenEmissionMultipliers.length - 1].multiplier = newMultiplier; + tokenEmissionMultipliers[tokenEmissionMultipliers.length - 1].timestamp = block.timestamp + - TokenEmissionMultiplierUpdateDelay; + tokenEmissionMultiplierUpdateDelay; } else { - TokenEmissionMultipliers.push( + tokenEmissionMultipliers.push( ParanetLib.TokenEmissionMultiplier({ multiplier: newMultiplier, - timestamp: block.timestamp + TokenEmissionMultiplierUpdateDelay, + timestamp: block.timestamp + tokenEmissionMultiplierUpdateDelay, finalized: false }) ); } emit TokenEmissionMultiplierUpdateInitiated( - TokenEmissionMultipliers[TokenEmissionMultipliers.length - 2].multiplier, + tokenEmissionMultipliers[tokenEmissionMultipliers.length - 2].multiplier, newMultiplier, - block.timestamp + TokenEmissionMultiplierUpdateDelay + block.timestamp + tokenEmissionMultiplierUpdateDelay ); } function finalizeTokenEmissionMultiplierUpdate() external onlyVotersRegistrar { - require(TokenEmissionMultipliers.length > 0, "No emission multiplier updates"); + require(tokenEmissionMultipliers.length > 0, "No emission multiplier updates"); require( - !TokenEmissionMultipliers[TokenEmissionMultipliers.length - 1].finalized, + !tokenEmissionMultipliers[tokenEmissionMultipliers.length - 1].finalized, "Last update already finalized" ); require( - block.timestamp >= TokenEmissionMultipliers[TokenEmissionMultipliers.length - 1].timestamp, + block.timestamp >= tokenEmissionMultipliers[tokenEmissionMultipliers.length - 1].timestamp, "Delay period not yet passed" ); - TokenEmissionMultipliers[TokenEmissionMultipliers.length - 1].finalized = true; + tokenEmissionMultipliers[tokenEmissionMultipliers.length - 1].finalized = true; emit TokenEmissionMultiplierUpdateFinalized( - TokenEmissionMultipliers[TokenEmissionMultipliers.length - 2].multiplier, - TokenEmissionMultipliers[TokenEmissionMultipliers.length - 1].multiplier + tokenEmissionMultipliers[tokenEmissionMultipliers.length - 2].multiplier, + tokenEmissionMultipliers[tokenEmissionMultipliers.length - 1].multiplier ); } function getTotalKnowledgeMinerIncentiveEstimation() public view returns (uint256) { uint96 unrewardedTracSpent = paranetKnowledgeMinersRegistry.getUnrewardedTracSpent( msg.sender, - ParanetIncentivesPoolStorage.paranetId() + paranetIncentivesPoolStorage.paranetId() ); if (unrewardedTracSpent < ParanetLib.TOKENS_DIGITS_DIFF) { @@ -214,8 +214,8 @@ contract ParanetIncentivesPool is INamed, IVersioned, IParanetIncentivesPool { (((unrewardedTracSpent * getEffectiveTokenEmissionMultiplier(block.timestamp)) / ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) * (ParanetLib.PERCENTAGE_SCALING_FACTOR - - ParanetIncentivesPoolStorage.paranetOperatorRewardPercentage() - - ParanetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage())) / + paranetIncentivesPoolStorage.paranetOperatorRewardPercentage() - + paranetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage())) / ParanetLib.PERCENTAGE_SCALING_FACTOR; } @@ -223,9 +223,9 @@ contract ParanetIncentivesPool is INamed, IVersioned, IParanetIncentivesPool { return _getIncentiveEstimation( ParanetLib.PERCENTAGE_SCALING_FACTOR - - ParanetIncentivesPoolStorage.paranetOperatorRewardPercentage() - - ParanetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage(), - ParanetIncentivesPoolStorage.totalMinersclaimedToken() + paranetIncentivesPoolStorage.paranetOperatorRewardPercentage() - + paranetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage(), + paranetIncentivesPoolStorage.totalMinersclaimedToken() ); } @@ -236,14 +236,14 @@ contract ParanetIncentivesPool is INamed, IVersioned, IParanetIncentivesPool { // and total TOKEN received by the contract, so that Miners don't get tokens belonging to Operator/Voters // Following the example from the above, if we have 100 TOKEN as a total reward, Miners should never get // more than 80 TOKEN. minersRewardLimit = 80 TOKEN - uint256 totalMinersclaimedToken = ParanetIncentivesPoolStorage.totalMinersclaimedToken(); - uint256 minersRewardLimit = ((ParanetIncentivesPoolStorage.getBalance() + + uint256 totalMinersclaimedToken = paranetIncentivesPoolStorage.totalMinersclaimedToken(); + uint256 minersRewardLimit = ((paranetIncentivesPoolStorage.getBalance() + totalMinersclaimedToken + - ParanetIncentivesPoolStorage.totalOperatorsclaimedToken() + - ParanetIncentivesPoolStorage.totalVotersclaimedToken()) * + paranetIncentivesPoolStorage.totalOperatorsclaimedToken() + + paranetIncentivesPoolStorage.totalVotersclaimedToken()) * (ParanetLib.PERCENTAGE_SCALING_FACTOR - - ParanetIncentivesPoolStorage.paranetOperatorRewardPercentage() - - ParanetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage())) / + paranetIncentivesPoolStorage.paranetOperatorRewardPercentage() - + paranetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage())) / ParanetLib.PERCENTAGE_SCALING_FACTOR; return @@ -255,19 +255,19 @@ contract ParanetIncentivesPool is INamed, IVersioned, IParanetIncentivesPool { function getClaimableAllKnowledgeMinersRewardAmount() public view returns (uint256) { uint256 tokenReward = getTotalAllKnowledgeMinersIncentiveEstimation(); - uint256 minersRewardLimit = ((ParanetIncentivesPoolStorage.getBalance() + - ParanetIncentivesPoolStorage.totalMinersclaimedToken() + - ParanetIncentivesPoolStorage.totalOperatorsclaimedToken() + - ParanetIncentivesPoolStorage.totalVotersclaimedToken()) * + uint256 minersRewardLimit = ((paranetIncentivesPoolStorage.getBalance() + + paranetIncentivesPoolStorage.totalMinersclaimedToken() + + paranetIncentivesPoolStorage.totalOperatorsclaimedToken() + + paranetIncentivesPoolStorage.totalVotersclaimedToken()) * (ParanetLib.PERCENTAGE_SCALING_FACTOR - - ParanetIncentivesPoolStorage.paranetOperatorRewardPercentage() - - ParanetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage())) / + paranetIncentivesPoolStorage.paranetOperatorRewardPercentage() - + paranetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage())) / ParanetLib.PERCENTAGE_SCALING_FACTOR; return - ParanetIncentivesPoolStorage.totalMinersclaimedToken() + tokenReward <= minersRewardLimit + paranetIncentivesPoolStorage.totalMinersclaimedToken() + tokenReward <= minersRewardLimit ? tokenReward - : minersRewardLimit - ParanetIncentivesPoolStorage.totalMinersclaimedToken(); + : minersRewardLimit - paranetIncentivesPoolStorage.totalMinersclaimedToken(); } function claimKnowledgeMinerReward(uint256 amount) external onlyParanetKnowledgeMiner { @@ -276,7 +276,7 @@ contract ParanetIncentivesPool is INamed, IVersioned, IParanetIncentivesPool { uint256 tokenReward = getTotalKnowledgeMinerIncentiveEstimation(); uint256 claimableTokenReward = getClaimableKnowledgeMinerRewardAmount(); if (claimableTokenReward == 0 || amount == 0 || amount > claimableTokenReward) { - revert ParanetLib.NoRewardAvailable(ParanetIncentivesPoolStorage.paranetId(), msg.sender); + revert ParanetLib.NoRewardAvailable(paranetIncentivesPoolStorage.paranetId(), msg.sender); } uint96 newUnrewardedTracSpent = amount == tokenReward @@ -286,85 +286,85 @@ contract ParanetIncentivesPool is INamed, IVersioned, IParanetIncentivesPool { getEffectiveTokenEmissionMultiplier(block.timestamp) ); - pkmr.setUnrewardedTracSpent(msg.sender, ParanetIncentivesPoolStorage.paranetId(), newUnrewardedTracSpent); - pkmr.addcumulativeAwardedToken(msg.sender, ParanetIncentivesPoolStorage.paranetId(), amount); + pkmr.setUnrewardedTracSpent(msg.sender, paranetIncentivesPoolStorage.paranetId(), newUnrewardedTracSpent); + pkmr.addcumulativeAwardedToken(msg.sender, paranetIncentivesPoolStorage.paranetId(), amount); if ( - ParanetIncentivesPoolStorage.getClaimedMinerRewardsLength() == 0 || - ParanetIncentivesPoolStorage - .getClaimedMinerRewardsAtIndex(ParanetIncentivesPoolStorage.claimedMinerRewardsIndexes(msg.sender)) + paranetIncentivesPoolStorage.getClaimedMinerRewardsLength() == 0 || + paranetIncentivesPoolStorage + .getClaimedMinerRewardsAtIndex(paranetIncentivesPoolStorage.claimedMinerRewardsIndexes(msg.sender)) .addr != msg.sender ) { - ParanetIncentivesPoolStorage.addMinerClaimedRewardProfile(msg.sender, amount); + paranetIncentivesPoolStorage.addMinerClaimedRewardProfile(msg.sender, amount); } else { - ParanetIncentivesPoolStorage.addMinerClaimedReward(msg.sender, amount); + paranetIncentivesPoolStorage.addMinerClaimedReward(msg.sender, amount); } - ParanetIncentivesPoolStorage.addTotalMinersclaimedToken(amount); + paranetIncentivesPoolStorage.addTotalMinersclaimedToken(amount); - ParanetIncentivesPoolStorage.transferReward(msg.sender, amount); + paranetIncentivesPoolStorage.transferReward(msg.sender, amount); } function getTotalParanetOperatorIncentiveEstimation() public view returns (uint256) { return _getIncentiveEstimation( - ParanetIncentivesPoolStorage.paranetOperatorRewardPercentage(), - ParanetIncentivesPoolStorage.totalOperatorsclaimedToken() + paranetIncentivesPoolStorage.paranetOperatorRewardPercentage(), + paranetIncentivesPoolStorage.totalOperatorsclaimedToken() ); } function getClaimableParanetOperatorRewardAmount() public view returns (uint256) { uint256 tokenReward = getTotalParanetOperatorIncentiveEstimation(); - uint256 operatorRewardLimit = ((ParanetIncentivesPoolStorage.getBalance() + - ParanetIncentivesPoolStorage.totalMinersclaimedToken() + - ParanetIncentivesPoolStorage.totalOperatorsclaimedToken() + - ParanetIncentivesPoolStorage.totalVotersclaimedToken()) * - ParanetIncentivesPoolStorage.paranetOperatorRewardPercentage()) / ParanetLib.PERCENTAGE_SCALING_FACTOR; + uint256 operatorRewardLimit = ((paranetIncentivesPoolStorage.getBalance() + + paranetIncentivesPoolStorage.totalMinersclaimedToken() + + paranetIncentivesPoolStorage.totalOperatorsclaimedToken() + + paranetIncentivesPoolStorage.totalVotersclaimedToken()) * + paranetIncentivesPoolStorage.paranetOperatorRewardPercentage()) / ParanetLib.PERCENTAGE_SCALING_FACTOR; return - ParanetIncentivesPoolStorage.totalOperatorsclaimedToken() + tokenReward <= operatorRewardLimit + paranetIncentivesPoolStorage.totalOperatorsclaimedToken() + tokenReward <= operatorRewardLimit ? tokenReward - : operatorRewardLimit - ParanetIncentivesPoolStorage.totalOperatorsclaimedToken(); + : operatorRewardLimit - paranetIncentivesPoolStorage.totalOperatorsclaimedToken(); } function claimParanetOperatorReward() external onlyParanetOperator { uint256 claimableTokenReward = getClaimableParanetOperatorRewardAmount(); if (claimableTokenReward == 0) { - revert ParanetLib.NoRewardAvailable(ParanetIncentivesPoolStorage.paranetId(), msg.sender); + revert ParanetLib.NoRewardAvailable(paranetIncentivesPoolStorage.paranetId(), msg.sender); } if ( - ParanetIncentivesPoolStorage.getClaimedOperatorRewardsLength() == 0 || - ParanetIncentivesPoolStorage + paranetIncentivesPoolStorage.getClaimedOperatorRewardsLength() == 0 || + paranetIncentivesPoolStorage .getClaimedOperatorRewardsAtIndex( - ParanetIncentivesPoolStorage.claimedOperatorRewardsIndexes(msg.sender) + paranetIncentivesPoolStorage.claimedOperatorRewardsIndexes(msg.sender) ) .addr != msg.sender ) { - ParanetIncentivesPoolStorage.addOperatorClaimedRewardsProfile(msg.sender, claimableTokenReward); + paranetIncentivesPoolStorage.addOperatorClaimedRewardsProfile(msg.sender, claimableTokenReward); } else { - ParanetIncentivesPoolStorage.addClaimedOperatorReward(msg.sender, claimableTokenReward); + paranetIncentivesPoolStorage.addClaimedOperatorReward(msg.sender, claimableTokenReward); } - ParanetIncentivesPoolStorage.addTotalOperatorsclaimedToken(claimableTokenReward); + paranetIncentivesPoolStorage.addTotalOperatorsclaimedToken(claimableTokenReward); - ParanetIncentivesPoolStorage.transferReward(msg.sender, claimableTokenReward); + paranetIncentivesPoolStorage.transferReward(msg.sender, claimableTokenReward); } function getTotalProposalVoterIncentiveEstimation() public view returns (uint256) { uint256 effectiveTokenEmissionMultiplier = getEffectiveTokenEmissionMultiplier(block.timestamp); uint96 cumulativeKnowledgeValueSingleVoterPart = (((paranetsRegistry.getCumulativeKnowledgeValue( - ParanetIncentivesPoolStorage.paranetId() - ) * ParanetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage()) / + paranetIncentivesPoolStorage.paranetId() + ) * paranetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage()) / ParanetLib.PERCENTAGE_SCALING_FACTOR) * - ParanetIncentivesPoolStorage - .getVoterAtIndex(ParanetIncentivesPoolStorage.votersIndexes(msg.sender)) + paranetIncentivesPoolStorage + .getVoterAtIndex(paranetIncentivesPoolStorage.votersIndexes(msg.sender)) .weight) / ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT; uint96 rewardedTracSpentSingleVoterPart = uint96( - (ParanetIncentivesPoolStorage - .getVoterAtIndex(ParanetIncentivesPoolStorage.votersIndexes(msg.sender)) + (paranetIncentivesPoolStorage + .getVoterAtIndex(paranetIncentivesPoolStorage.votersIndexes(msg.sender)) .claimedToken * ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) / effectiveTokenEmissionMultiplier ); @@ -377,23 +377,23 @@ contract ParanetIncentivesPool is INamed, IVersioned, IParanetIncentivesPool { return ((cumulativeKnowledgeValueSingleVoterPart * effectiveTokenEmissionMultiplier) / ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) - - ParanetIncentivesPoolStorage - .getVoterAtIndex(ParanetIncentivesPoolStorage.votersIndexes(msg.sender)) + paranetIncentivesPoolStorage + .getVoterAtIndex(paranetIncentivesPoolStorage.votersIndexes(msg.sender)) .claimedToken; } function getTotalAllProposalVotersIncentiveEstimation() public view returns (uint256) { return _getIncentiveEstimation( - ParanetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage(), - ParanetIncentivesPoolStorage.totalVotersclaimedToken() + paranetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage(), + paranetIncentivesPoolStorage.totalVotersclaimedToken() ); } function getClaimableProposalVoterRewardAmount() public view returns (uint256) { if ( - ParanetIncentivesPoolStorage.getVotersCount() == 0 || - ParanetIncentivesPoolStorage.getVoterAtIndex(ParanetIncentivesPoolStorage.votersIndexes(msg.sender)).addr != + paranetIncentivesPoolStorage.getVotersCount() == 0 || + paranetIncentivesPoolStorage.getVoterAtIndex(paranetIncentivesPoolStorage.votersIndexes(msg.sender)).addr != msg.sender ) { return 0; @@ -401,50 +401,50 @@ contract ParanetIncentivesPool is INamed, IVersioned, IParanetIncentivesPool { uint256 tokenReward = getTotalProposalVoterIncentiveEstimation(); - uint256 voterRewardLimit = ((((ParanetIncentivesPoolStorage.getBalance() + - ParanetIncentivesPoolStorage.totalMinersclaimedToken() + - ParanetIncentivesPoolStorage.totalOperatorsclaimedToken() + - ParanetIncentivesPoolStorage.totalVotersclaimedToken()) * - ParanetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage()) / + uint256 voterRewardLimit = ((((paranetIncentivesPoolStorage.getBalance() + + paranetIncentivesPoolStorage.totalMinersclaimedToken() + + paranetIncentivesPoolStorage.totalOperatorsclaimedToken() + + paranetIncentivesPoolStorage.totalVotersclaimedToken()) * + paranetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage()) / ParanetLib.PERCENTAGE_SCALING_FACTOR) * - ParanetIncentivesPoolStorage - .getVoterAtIndex(ParanetIncentivesPoolStorage.votersIndexes(msg.sender)) + paranetIncentivesPoolStorage + .getVoterAtIndex(paranetIncentivesPoolStorage.votersIndexes(msg.sender)) .weight) / ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT; return - ParanetIncentivesPoolStorage - .getVoterAtIndex(ParanetIncentivesPoolStorage.votersIndexes(msg.sender)) + paranetIncentivesPoolStorage + .getVoterAtIndex(paranetIncentivesPoolStorage.votersIndexes(msg.sender)) .claimedToken + tokenReward <= voterRewardLimit ? tokenReward : voterRewardLimit - - ParanetIncentivesPoolStorage - .getVoterAtIndex(ParanetIncentivesPoolStorage.votersIndexes(msg.sender)) + paranetIncentivesPoolStorage + .getVoterAtIndex(paranetIncentivesPoolStorage.votersIndexes(msg.sender)) .claimedToken; } function getClaimableAllProposalVotersRewardAmount() public view returns (uint256) { uint256 tokenReward = getTotalAllProposalVotersIncentiveEstimation(); - uint256 votersRewardLimit = ((ParanetIncentivesPoolStorage.getBalance() + - ParanetIncentivesPoolStorage.totalMinersclaimedToken() + - ParanetIncentivesPoolStorage.totalOperatorsclaimedToken() + - ParanetIncentivesPoolStorage.totalVotersclaimedToken()) * - ParanetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage()) / + uint256 votersRewardLimit = ((paranetIncentivesPoolStorage.getBalance() + + paranetIncentivesPoolStorage.totalMinersclaimedToken() + + paranetIncentivesPoolStorage.totalOperatorsclaimedToken() + + paranetIncentivesPoolStorage.totalVotersclaimedToken()) * + paranetIncentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage()) / ParanetLib.PERCENTAGE_SCALING_FACTOR; return - ParanetIncentivesPoolStorage.totalVotersclaimedToken() + tokenReward <= votersRewardLimit + paranetIncentivesPoolStorage.totalVotersclaimedToken() + tokenReward <= votersRewardLimit ? tokenReward - : votersRewardLimit - ParanetIncentivesPoolStorage.totalVotersclaimedToken(); + : votersRewardLimit - paranetIncentivesPoolStorage.totalVotersclaimedToken(); } function claimIncentivizationProposalVoterReward() external onlyParanetIncentivizationProposalVoter { - if (ParanetIncentivesPoolStorage.cumulativeVotersWeight() != ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT) { + if (paranetIncentivesPoolStorage.cumulativeVotersWeight() != ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT) { revert ParanetLib.InvalidCumulativeVotersWeight( - ParanetIncentivesPoolStorage.paranetId(), - ParanetIncentivesPoolStorage.cumulativeVotersWeight(), + paranetIncentivesPoolStorage.paranetId(), + paranetIncentivesPoolStorage.cumulativeVotersWeight(), ParanetLib.MAX_CUMULATIVE_VOTERS_WEIGHT ); } @@ -452,15 +452,15 @@ contract ParanetIncentivesPool is INamed, IVersioned, IParanetIncentivesPool { uint256 claimableTokenReward = getClaimableProposalVoterRewardAmount(); if (claimableTokenReward == 0) { - revert ParanetLib.NoRewardAvailable(ParanetIncentivesPoolStorage.paranetId(), msg.sender); + revert ParanetLib.NoRewardAvailable(paranetIncentivesPoolStorage.paranetId(), msg.sender); } - ParanetIncentivesPoolStorage - .getVoterAtIndex(ParanetIncentivesPoolStorage.votersIndexes(msg.sender)) + paranetIncentivesPoolStorage + .getVoterAtIndex(paranetIncentivesPoolStorage.votersIndexes(msg.sender)) .claimedToken += claimableTokenReward; - ParanetIncentivesPoolStorage.addTotalVotersclaimedToken(claimableTokenReward); + paranetIncentivesPoolStorage.addTotalVotersclaimedToken(claimableTokenReward); - ParanetIncentivesPoolStorage.transferReward(msg.sender, claimableTokenReward); + paranetIncentivesPoolStorage.transferReward(msg.sender, claimableTokenReward); } function _getIncentiveEstimation( @@ -469,7 +469,7 @@ contract ParanetIncentivesPool is INamed, IVersioned, IParanetIncentivesPool { ) internal view returns (uint256) { uint256 effectiveTokenEmissionMultiplier = getEffectiveTokenEmissionMultiplier(block.timestamp); uint96 cumulativeKnowledgeValuePart = (paranetsRegistry.getCumulativeKnowledgeValue( - ParanetIncentivesPoolStorage.paranetId() + paranetIncentivesPoolStorage.paranetId() ) * rewardPercentage) / ParanetLib.PERCENTAGE_SCALING_FACTOR; uint96 rewardedTracSpentPart = uint96( (totalclaimedToken * ParanetLib.EMISSION_MULTIPLIER_SCALING_FACTOR) / effectiveTokenEmissionMultiplier @@ -485,7 +485,7 @@ contract ParanetIncentivesPool is INamed, IVersioned, IParanetIncentivesPool { } function getParanetIncentivesPoolStorage() external view returns (address) { - return address(ParanetIncentivesPoolStorage); + return address(paranetIncentivesPoolStorage); } function _checkHubOwner() internal view virtual { @@ -493,7 +493,7 @@ contract ParanetIncentivesPool is INamed, IVersioned, IParanetIncentivesPool { } function _checkVotersRegistrar() internal view virtual { - require(msg.sender == ParanetIncentivesPoolStorage.votersRegistrar(), "Fn can only be used by registrar"); + require(msg.sender == paranetIncentivesPoolStorage.votersRegistrar(), "Fn can only be used by registrar"); } function _checkParanetOperator() internal view virtual { diff --git a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol b/contracts/paranets/ParanetIncentivesPoolStorage.sol similarity index 99% rename from contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol rename to contracts/paranets/ParanetIncentivesPoolStorage.sol index 3c37d3bf..28e70790 100644 --- a/contracts/paranets/ParanetNeuroIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetIncentivesPoolStorage.sol @@ -119,7 +119,7 @@ contract ParanetIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInit emit TokenRewardDeposit(msg.sender, msg.value); } - function totalNeuroReceived() external view returns (uint256) { + function totalReceived() external view returns (uint256) { return getBalance() + totalMinersclaimedToken + totalOperatorsclaimedToken + totalVotersclaimedToken; } diff --git a/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol b/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol index 04ae39d0..ad417bf9 100644 --- a/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol +++ b/contracts/storage/paranets/ParanetKnowledgeMinersRegistry.sol @@ -6,7 +6,7 @@ import {ParanetsRegistry} from "./ParanetsRegistry.sol"; import {HubDependent} from "../../abstract/HubDependent.sol"; import {INamed} from "../../interfaces/INamed.sol"; import {IVersioned} from "../../interfaces/IVersioned.sol"; -import {IParanetNeuroIncentivesPool} from "../../interfaces/IParanetNeuroIncentivesPool.sol"; +import {IParanetIncentivesPool} from "../../interfaces/IParanetIncentivesPool.sol"; import {ParanetLib} from "../../libraries/ParanetLib.sol"; contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { @@ -352,32 +352,32 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { knowledgeMiners[miner].unrewardedTracSpent[paranetId] -= subtractedUnrewardedTracSpent; } - function getCumulativeAwardedNeuro(address miner, bytes32 paranetId) external view returns (uint256) { - return knowledgeMiners[miner].cumulativeAwardedNeuro[paranetId]; + function getcumulativeAwardedToken(address miner, bytes32 paranetId) external view returns (uint256) { + return knowledgeMiners[miner].cumulativeAwardedToken[paranetId]; } - function setCumulativeAwardedNeuro( + function setcumulativeAwardedToken( address miner, bytes32 paranetId, - uint256 cumulativeAwardedNeuro + uint256 cumulativeAwardedToken ) external onlyContractsOrIncentivesPool(paranetId) { - knowledgeMiners[miner].cumulativeAwardedNeuro[paranetId] = cumulativeAwardedNeuro; + knowledgeMiners[miner].cumulativeAwardedToken[paranetId] = cumulativeAwardedToken; } - function addCumulativeAwardedNeuro( + function addcumulativeAwardedToken( address miner, bytes32 paranetId, - uint256 addedCumulativeAwardedNeuro + uint256 addedcumulativeAwardedToken ) external onlyContractsOrIncentivesPool(paranetId) { - knowledgeMiners[miner].cumulativeAwardedNeuro[paranetId] += addedCumulativeAwardedNeuro; + knowledgeMiners[miner].cumulativeAwardedToken[paranetId] += addedcumulativeAwardedToken; } - function subCumulativeAwardedNeuro( + function subcumulativeAwardedToken( address miner, bytes32 paranetId, - uint256 subtractedCumulativeAwardedNeuro + uint256 subtractedcumulativeAwardedToken ) external onlyContractsOrIncentivesPool(paranetId) { - knowledgeMiners[miner].cumulativeAwardedNeuro[paranetId] -= subtractedCumulativeAwardedNeuro; + knowledgeMiners[miner].cumulativeAwardedToken[paranetId] -= subtractedcumulativeAwardedToken; } function _checkSender(bytes32 paranetId) internal view virtual { @@ -385,7 +385,7 @@ contract ParanetKnowledgeMinersRegistry is INamed, IVersioned, HubDependent { hub.isContract(msg.sender) || paranetsRegistry.hasIncentivesPoolByStorageAddress( paranetId, - IParanetNeuroIncentivesPool(msg.sender).getParanetNeuroIncentivesPoolStorage() + IParanetIncentivesPool(msg.sender).getParanetIncentivesPoolStorage() ), "Hub/IncentivesPool function" ); From ca91f2c8a95ed7f909c6e6227bcf5710e9329b18 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 14 Feb 2025 13:31:33 +0100 Subject: [PATCH 101/153] Fix variable naming --- .../paranets/ParanetIncentivesPoolStorage.sol | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/contracts/paranets/ParanetIncentivesPoolStorage.sol b/contracts/paranets/ParanetIncentivesPoolStorage.sol index 28e70790..b89933dd 100644 --- a/contracts/paranets/ParanetIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetIncentivesPoolStorage.sol @@ -38,7 +38,7 @@ contract ParanetIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInit IERC20 public token; ParanetsRegistry public paranetsRegistry; - address public ParanetIncentivesPoolAddress; + address public paranetIncentivesPoolAddress; bytes32 public paranetId; // Percentage of how much tokens from total TOKEN emission goes to the Paranet Operator @@ -147,7 +147,7 @@ contract ParanetIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInit } function addMinerClaimedRewardProfile(address addr, uint256 claimableTokenReward) external { - require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + require(msg.sender == paranetIncentivesPoolAddress, "Caller is not incentives pool contract"); claimedMinerRewardsIndexes[addr] = claimedMinerRewards.length; claimedMinerRewards.push( ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile({addr: addr, claimedToken: claimableTokenReward}) @@ -156,14 +156,14 @@ contract ParanetIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInit } function addMinerClaimedReward(address addr, uint256 claimableTokenReward) external { - require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + require(msg.sender == paranetIncentivesPoolAddress, "Caller is not incentives pool contract"); uint256 newTotal = claimedMinerRewards[claimedMinerRewardsIndexes[addr]].claimedToken + claimableTokenReward; claimedMinerRewards[claimedMinerRewardsIndexes[addr]].claimedToken = newTotal; emit MinerRewardIncreased(addr, claimableTokenReward, newTotal); } function addOperatorClaimedRewardsProfile(address addr, uint256 claimableTokenReward) external { - require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + require(msg.sender == paranetIncentivesPoolAddress, "Caller is not incentives pool contract"); claimedOperatorRewardsIndexes[addr] = claimedOperatorRewards.length; claimedOperatorRewards.push( ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile({addr: addr, claimedToken: claimableTokenReward}) @@ -172,7 +172,7 @@ contract ParanetIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInit } function addClaimedOperatorReward(address addr, uint256 claimableTokenReward) external { - require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + require(msg.sender == paranetIncentivesPoolAddress, "Caller is not incentives pool contract"); uint256 newTotal = claimedOperatorRewards[claimedOperatorRewardsIndexes[addr]].claimedToken + claimableTokenReward; claimedOperatorRewards[claimedOperatorRewardsIndexes[addr]].claimedToken = newTotal; @@ -284,7 +284,7 @@ contract ParanetIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInit } function addVoterclaimedToken(address voter, uint256 amount) external { - require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + require(msg.sender == paranetIncentivesPoolAddress, "Caller is not incentives pool contract"); uint256 idx = votersIndexes[voter]; if (idx < voters.length && voters[idx].addr == voter) { voters[idx].claimedToken += amount; @@ -315,24 +315,24 @@ contract ParanetIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInit } function addTotalMinersclaimedToken(uint256 amount) external { - require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + require(msg.sender == paranetIncentivesPoolAddress, "Caller is not incentives pool contract"); totalMinersclaimedToken += amount; } function addTotalOperatorsclaimedToken(uint256 amount) external { - require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + require(msg.sender == paranetIncentivesPoolAddress, "Caller is not incentives pool contract"); totalOperatorsclaimedToken += amount; } function addTotalVotersclaimedToken(uint256 amount) external { - require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + require(msg.sender == paranetIncentivesPoolAddress, "Caller is not incentives pool contract"); totalVotersclaimedToken += amount; } - function setParanetIncentivesPool(address _ParanetIncentivesPoolAddress) external onlyContracts { - address oldAddress = ParanetIncentivesPoolAddress; - ParanetIncentivesPoolAddress = _ParanetIncentivesPoolAddress; - emit IncentivesPoolAddressSet(oldAddress, _ParanetIncentivesPoolAddress); + function setParanetIncentivesPool(address _paranetIncentivesPoolAddress) external onlyContracts { + address oldAddress = paranetIncentivesPoolAddress; + paranetIncentivesPoolAddress = _paranetIncentivesPoolAddress; + emit IncentivesPoolAddressSet(oldAddress, _paranetIncentivesPoolAddress); } function getBalance() public view returns (uint256) { @@ -344,7 +344,7 @@ contract ParanetIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInit } function transferReward(address rewardAddress, uint256 amount) public { - require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + require(msg.sender == paranetIncentivesPoolAddress, "Caller is not incentives pool contract"); if (address(token) == address(0)) { payable(rewardAddress).transfer(amount); } else { @@ -354,32 +354,32 @@ contract ParanetIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInit } function setTotalMinersclaimedToken(uint256 amount) external { - require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + require(msg.sender == paranetIncentivesPoolAddress, "Caller is not incentives pool contract"); totalMinersclaimedToken = amount; } function setTotalOperatorsclaimedToken(uint256 amount) external { - require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + require(msg.sender == paranetIncentivesPoolAddress, "Caller is not incentives pool contract"); totalOperatorsclaimedToken = amount; } function setTotalVotersclaimedToken(uint256 amount) external { - require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + require(msg.sender == paranetIncentivesPoolAddress, "Caller is not incentives pool contract"); totalVotersclaimedToken = amount; } function decrementTotalMinersclaimedToken(uint256 amount) external { - require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + require(msg.sender == paranetIncentivesPoolAddress, "Caller is not incentives pool contract"); totalMinersclaimedToken -= amount; } function decrementTotalOperatorsclaimedToken(uint256 amount) external { - require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + require(msg.sender == paranetIncentivesPoolAddress, "Caller is not incentives pool contract"); totalOperatorsclaimedToken -= amount; } function decrementTotalVotersclaimedToken(uint256 amount) external { - require(msg.sender == ParanetIncentivesPoolAddress, "Caller is not incentives pool contract"); + require(msg.sender == paranetIncentivesPoolAddress, "Caller is not incentives pool contract"); totalVotersclaimedToken -= amount; } From 76a81f6ca7c18458fcdadb64e50901498e9676db Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 14 Feb 2025 13:36:44 +0100 Subject: [PATCH 102/153] fix naming and missing error type --- contracts/libraries/ParanetLib.sol | 6 ++++++ contracts/paranets/ParanetIncentivesPoolFactory.sol | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index 48dc8200..9861694a 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -233,4 +233,10 @@ library ParanetLib { address knowledgeCollectionStorageContract, uint256 knowledgeCollectionTokenId ); + + error KnowledgeCollectionIsAPartOfOtherParanet( + address knowledgeCollectionStorageContract, + uint256 knowledgeCollectionTokenId, + bytes32 paranetId + ); } diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index 24357aa2..52ba7755 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -111,7 +111,7 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn ParanetIncentivesPoolStorage storage_ = ParanetIncentivesPoolStorage(payable(storageAddress)); require(storage_.paranetId() == paranetId); - address oldPoolAddress = storage_.ParanetIncentivesPoolAddress(); + address oldPoolAddress = storage_.paranetIncentivesPoolAddress(); uint256 tracToTokenEmissionMultiplier = ParanetIncentivesPool(oldPoolAddress) .getEffectiveTokenEmissionMultiplier(block.timestamp); From 9a35e23ea400f03cc87f152d1c582d795961462b Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 14 Feb 2025 14:14:05 +0100 Subject: [PATCH 103/153] Fix hasIncentivesPoolByName and hasIncentivesPoolByStorageAddress --- .../paranets/ParanetIncentivesPoolFactory.sol | 2 +- .../storage/paranets/ParanetsRegistry.sol | 34 ++++++++++++++----- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index 52ba7755..164c9ef7 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -73,7 +73,7 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn bytes32 paranetId = _computeParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); ParanetsRegistry pr = paranetsRegistry; require(pr.paranetExists(paranetId)); - require(pr.hasIncentivesPoolByName(paranetId, incentivesPoolName)); + require(!pr.hasIncentivesPoolByName(paranetId, incentivesPoolName)); ParanetIncentivesPoolStorage storage_ = new ParanetIncentivesPoolStorage( address(hub), diff --git a/contracts/storage/paranets/ParanetsRegistry.sol b/contracts/storage/paranets/ParanetsRegistry.sol index e713d1a0..2302a102 100644 --- a/contracts/storage/paranets/ParanetsRegistry.sol +++ b/contracts/storage/paranets/ParanetsRegistry.sol @@ -285,17 +285,35 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { } function hasIncentivesPoolByName(bytes32 paranetId, string calldata poolName) external view returns (bool) { - return - paranets[paranetId] - .incentivesPools[paranets[paranetId].incentivesPoolsByNameIndexes[poolName]] - .storageAddr != address(0); + ParanetLib.Paranet storage paranet = paranets[paranetId]; + + if (paranet.incentivesPools.length == 0) { + return false; + } + + uint256 index = paranet.incentivesPoolsByNameIndexes[poolName]; + + if (index >= paranet.incentivesPools.length) { + return false; + } + + return paranet.incentivesPools[index].storageAddr != address(0); } function hasIncentivesPoolByStorageAddress(bytes32 paranetId, address storageAddr) external view returns (bool) { - return - paranets[paranetId] - .incentivesPools[paranets[paranetId].incentivesPoolsByStorageAddressIndexes[storageAddr]] - .storageAddr != address(0); + ParanetLib.Paranet storage paranet = paranets[paranetId]; + + if (paranet.incentivesPools.length == 0) { + return false; + } + + uint256 index = paranet.incentivesPoolsByStorageAddressIndexes[storageAddr]; + + if (index >= paranet.incentivesPools.length) { + return false; + } + + return paranet.incentivesPools[index].storageAddr != address(0); } function getCumulativeKnowledgeValue(bytes32 paranetId) external view returns (uint96) { From c01b13bc7e615740157ed2625be52aaae594de88 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 14 Feb 2025 14:37:27 +0100 Subject: [PATCH 104/153] Change facotry events --- .../paranets/ParanetIncentivesPoolFactory.sol | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index 164c9ef7..97b5459c 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -15,13 +15,21 @@ import {IVersioned} from "../interfaces/IVersioned.sol"; contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IInitializable { event ParanetIncentivesPoolDeployed( - bytes32 indexed paranetId, + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, + uint256 indexed paranetKATokenId, address storageAddress, address poolAddress, address rewardTokenAddress ); - event ParanetIncentivesPoolRedeployed(bytes32 indexed paranetId, address storageAddress, address newPoolAddress); + event ParanetIncentivesPoolRedeployed( + address indexed paranetKCStorageContract, + uint256 indexed paranetKCTokenId, + uint256 indexed paranetKATokenId, + address storageAddress, + address newPoolAddress + ); string private constant _NAME = "ParanetIncentivesPoolFactory"; string private constant _VERSION = "1.0.0"; @@ -93,7 +101,14 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn storage_.initialize(); paranetsRegistry.addIncentivesPool(paranetId, incentivesPoolName, storageAddress, rewardTokenAddress); - emit ParanetIncentivesPoolDeployed(paranetId, storageAddress, poolAddress, rewardTokenAddress); + emit ParanetIncentivesPoolDeployed( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + storageAddress, + poolAddress, + rewardTokenAddress + ); } function redeployIncentivesPool( @@ -121,7 +136,13 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn address(storage_) ); - emit ParanetIncentivesPoolRedeployed(paranetId, storageAddress, newPoolAddress); + emit ParanetIncentivesPoolRedeployed( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + storageAddress, + newPoolAddress + ); } function _computeParanetId( From 1da4123cb022d2abc4356c7886e874ebdc4d5a2c Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 14 Feb 2025 14:38:00 +0100 Subject: [PATCH 105/153] Remove ERC20 check from IncentiveStorage --- .../paranets/ParanetIncentivesPoolStorage.sol | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/contracts/paranets/ParanetIncentivesPoolStorage.sol b/contracts/paranets/ParanetIncentivesPoolStorage.sol index b89933dd..1173beeb 100644 --- a/contracts/paranets/ParanetIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetIncentivesPoolStorage.sol @@ -80,7 +80,6 @@ contract ParanetIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInit ); if (rewardTokenAddress != address(0)) { - require(checkERC20Compliance(rewardTokenAddress), "Invalid ERC20 contract"); token = IERC20(rewardTokenAddress); } @@ -465,23 +464,6 @@ contract ParanetIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInit emit VoterWeightUpdated(voter, oldWeight, newWeight); } - function checkERC20Compliance(address tokenAddress) internal view returns (bool) { - bytes4[4] memory selectors = [ - IERC20.balanceOf.selector, - IERC20.totalSupply.selector, - IERC20.transfer.selector, - IERC20.allowance.selector - ]; - - for (uint i = 0; i < selectors.length; i++) { - (bool success, ) = tokenAddress.staticcall(abi.encodeWithSelector(selectors[i], address(this))); - if (!success) { - return false; // If any function is missing, reject the contract - } - } - return true; // All ERC-20 functions exist - } - modifier onlyVotersRegistrar() { require(msg.sender == votersRegistrar, "Fn can only be used by registrar"); _; From 05b23898329e5fd47239264b140e619bbf63d1c1 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 14 Feb 2025 14:50:53 +0100 Subject: [PATCH 106/153] Add new paranet tests and update old --- test/helpers/paranet-helpers.ts | 2 + test/integration/Paranet.test.ts | 112 ++++++++++++++++++++++++++++--- 2 files changed, 105 insertions(+), 9 deletions(-) diff --git a/test/helpers/paranet-helpers.ts b/test/helpers/paranet-helpers.ts index debb58f2..d90b8c5d 100644 --- a/test/helpers/paranet-helpers.ts +++ b/test/helpers/paranet-helpers.ts @@ -27,6 +27,7 @@ export async function setupParanet( paranetDescription: string = 'Test Paranet Description', nodesAccessPolicy: number = ACCESS_POLICIES.OPEN, minersAccessPolicy: number = ACCESS_POLICIES.OPEN, + knowledgeCollectionsSubmissionPolicy: number = ACCESS_POLICIES.OPEN, ) { const { publishingNodeIdentityId, receivingNodesIdentityIds, collectionId } = await createProfilesAndKC( @@ -49,6 +50,7 @@ export async function setupParanet( paranetDescription, nodesAccessPolicy, minersAccessPolicy, + knowledgeCollectionsSubmissionPolicy, ); return { diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index 7c306ccb..85f0df78 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -17,8 +17,11 @@ import { Token, Hub, EpochStorage, - ParanetNeuroIncentivesPoolStorage, + ParanetIncentivesPoolStorage, + ParanetIncentivesPoolFactoryHelper, } from '../../typechain'; +import { ACCESS_POLICIES } from '../helpers/constants'; +import { createProfilesAndKC } from '../helpers/kc-helpers'; import { setupParanet } from '../helpers/paranet-helpers'; import { getDefaultPublishingNode, @@ -34,6 +37,7 @@ type ParanetFixture = { ParanetServicesRegistry: ParanetServicesRegistry; ParanetKnowledgeMinersRegistry: ParanetKnowledgeMinersRegistry; ParanetKnowledgeCollectionsRegistry: ParanetKnowledgeCollectionsRegistry; + ParanetIncentivesPoolFactoryHelper: ParanetIncentivesPoolFactoryHelper; ParanetIncentivesPoolFactory: ParanetIncentivesPoolFactory; KnowledgeCollection: KnowledgeCollection; KnowledgeCollectionStorage: KnowledgeCollectionStorage; @@ -49,6 +53,7 @@ describe('@unit Paranet', () => { let ParanetServicesRegistry: ParanetServicesRegistry; let ParanetKnowledgeMinersRegistry: ParanetKnowledgeMinersRegistry; let ParanetKnowledgeCollectionsRegistry: ParanetKnowledgeCollectionsRegistry; + let ParanetIncentivesPoolFactoryHelper: ParanetIncentivesPoolFactoryHelper; let ParanetIncentivesPoolFactory: ParanetIncentivesPoolFactory; let KnowledgeCollection: KnowledgeCollection; let KnowledgeCollectionStorage: KnowledgeCollectionStorage; @@ -64,6 +69,7 @@ describe('@unit Paranet', () => { 'ParanetServicesRegistry', 'ParanetKnowledgeMinersRegistry', 'ParanetKnowledgeCollectionsRegistry', + 'ParanetIncentivesPoolFactoryHelper', 'ParanetIncentivesPoolFactory', 'KnowledgeCollection', 'Profile', @@ -91,6 +97,10 @@ describe('@unit Paranet', () => { await hre.ethers.getContract( 'ParanetKnowledgeCollectionsRegistry', ); + ParanetIncentivesPoolFactoryHelper = + await hre.ethers.getContract( + 'ParanetIncentivesPoolFactoryHelper', + ); ParanetIncentivesPoolFactory = await hre.ethers.getContract( 'ParanetIncentivesPoolFactory', @@ -103,6 +113,11 @@ describe('@unit Paranet', () => { 'KnowledgeCollectionStorage', ); Profile = await hre.ethers.getContract('Profile'); + // await hre.deployments.deploy('Token', { + // from: accounts[0].address, + // args: ['Neuro', 'NEURO'], + // log: true, + // }); Token = await hre.ethers.getContract('Token'); return { @@ -112,6 +127,7 @@ describe('@unit Paranet', () => { ParanetServicesRegistry, ParanetKnowledgeMinersRegistry, ParanetKnowledgeCollectionsRegistry, + ParanetIncentivesPoolFactoryHelper, ParanetIncentivesPoolFactory, KnowledgeCollection, KnowledgeCollectionStorage, @@ -130,6 +146,7 @@ describe('@unit Paranet', () => { ParanetServicesRegistry, ParanetKnowledgeMinersRegistry, ParanetKnowledgeCollectionsRegistry, + ParanetIncentivesPoolFactoryHelper, ParanetIncentivesPoolFactory, KnowledgeCollection, KnowledgeCollectionStorage, @@ -192,6 +209,84 @@ describe('@unit Paranet', () => { expect(paranetMetadata.nodesAccessPolicy).to.equal(nodesAccessPolicy); expect(paranetMetadata.minersAccessPolicy).to.equal(minersAccessPolicy); }); + + it('Should revert when registering the same paranet twice', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const paranetName = 'Test Paranet'; + const paranetDescription = 'Test Paranet Description'; + const nodesAccessPolicy = ACCESS_POLICIES.OPEN; + const minersAccessPolicy = ACCESS_POLICIES.OPEN; + + const { paranetKCStorageContract, paranetKCTokenId, paranetKATokenId } = + await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + paranetName, + paranetDescription, + nodesAccessPolicy, + minersAccessPolicy, + ); + + await expect( + Paranet.connect(kcCreator).registerParanet( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetName, + paranetDescription, + nodesAccessPolicy, + minersAccessPolicy, + ACCESS_POLICIES.OPEN, + ), + ).to.be.revertedWithCustomError( + Paranet, + 'ParanetHasAlreadyBeenRegistered', + ); + }); + + it('Should revert when non-owner tries to register paranet', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const nonOwner = accounts[10]; + + const paranetKCStorageContract = + await KnowledgeCollectionStorage.getAddress(); + + const { collectionId } = await createProfilesAndKC( + kcCreator, + publishingNode, + receivingNodes, + { + Profile, + KnowledgeCollection, + Token, + }, + ); + + await expect( + Paranet.connect(nonOwner).registerParanet( + paranetKCStorageContract, + collectionId, + 1, + 'paranetName', + 'paranetDescription', + ACCESS_POLICIES.OPEN, + ACCESS_POLICIES.OPEN, + ACCESS_POLICIES.OPEN, + ), + ).to.be.revertedWith("Caller isn't the owner of the KA"); + }); }); describe('Paranet Incentives Pool', () => { @@ -220,7 +315,7 @@ describe('@unit Paranet', () => { const tx = await ParanetIncentivesPoolFactory.connect( paranetOwner, - ).deployNeuroIncentivesPool( + ).deployIncentivesPool( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, @@ -243,12 +338,11 @@ describe('@unit Paranet', () => { expect(event?.args[0]).to.equal(paranetKCStorageContract); expect(event?.args[1]).to.equal(paranetKCTokenId); expect(event?.args[2]).to.equal(paranetKATokenId); - expect(event?.args[5]).to.equal('Neuroweb'); - expect(event?.args[6]).to.equal(await Token.getAddress()); + expect(event?.args[5]).to.equal(await Token.getAddress()); let incentivesPool = await ParanetsRegistry.getIncentivesPoolByPoolName( paranetId, - event?.args[5], + 'Neuroweb', ); expect(incentivesPool.storageAddr).to.equal(event?.args[3]); expect(incentivesPool.rewardTokenAddress).to.equal( @@ -259,18 +353,18 @@ describe('@unit Paranet', () => { paranetId, event?.args[3], ); - expect(incentivesPool.name).to.equal(event?.args[5]); + expect(incentivesPool.name).to.equal('Neuroweb'); expect(incentivesPool.rewardTokenAddress).to.equal( await Token.getAddress(), ); // validate incentives pool address const incentivesPoolStorage = (await hre.ethers.getContractAt( - 'ParanetNeuroIncentivesPoolStorage', + 'ParanetIncentivesPoolStorage', event?.args[3], - )) as ParanetNeuroIncentivesPoolStorage; + )) as ParanetIncentivesPoolStorage; expect( - await incentivesPoolStorage.paranetNeuroIncentivesPoolAddress(), + await incentivesPoolStorage.paranetIncentivesPoolAddress(), ).to.equal(event?.args[4]); expect(await incentivesPoolStorage.paranetId()).to.equal(paranetId); }); From 7be210346245cde0d188fde08028f689fefad02f Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 14 Feb 2025 14:54:32 +0100 Subject: [PATCH 107/153] Update abis --- abi/IParanetIncentivesPool.json | 15 + abi/Paranet.json | 209 +++- abi/ParanetIncentivesPool.json | 557 +++++++++ abi/ParanetIncentivesPoolFactory.json | 152 ++- abi/ParanetIncentivesPoolFactoryHelper.json | 123 ++ ...json => ParanetIncentivesPoolStorage.json} | 1015 ++++++++++++----- abi/ParanetKnowledgeCollectionsRegistry.json | 2 +- abi/ParanetKnowledgeMinersRegistry.json | 128 +-- abi/ParanetStagingRegistry.json | 548 +++++++++ abi/ParanetsRegistry.json | 297 ++--- 10 files changed, 2444 insertions(+), 602 deletions(-) create mode 100644 abi/IParanetIncentivesPool.json create mode 100644 abi/ParanetIncentivesPool.json create mode 100644 abi/ParanetIncentivesPoolFactoryHelper.json rename abi/{ParanetNeuroIncentivesPool.json => ParanetIncentivesPoolStorage.json} (58%) create mode 100644 abi/ParanetStagingRegistry.json diff --git a/abi/IParanetIncentivesPool.json b/abi/IParanetIncentivesPool.json new file mode 100644 index 00000000..0ec9841b --- /dev/null +++ b/abi/IParanetIncentivesPool.json @@ -0,0 +1,15 @@ +[ + { + "inputs": [], + "name": "getParanetIncentivesPoolStorage", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abi/Paranet.json b/abi/Paranet.json index 08bc7d72..b5cd5606 100644 --- a/abi/Paranet.json +++ b/abi/Paranet.json @@ -13,12 +13,12 @@ { "inputs": [ { - "internalType": "enum ParanetLib.MinersAccessPolicy[]", + "internalType": "uint8[]", "name": "expectedAccessPolicies", "type": "uint8[]" }, { - "internalType": "enum ParanetLib.MinersAccessPolicy", + "internalType": "uint8", "name": "actualAccessPolicy", "type": "uint8" } @@ -29,12 +29,12 @@ { "inputs": [ { - "internalType": "enum ParanetLib.NodesAccessPolicy[]", + "internalType": "uint8[]", "name": "expectedAccessPolicies", "type": "uint8[]" }, { - "internalType": "enum ParanetLib.NodesAccessPolicy", + "internalType": "uint8", "name": "actualAccessPolicy", "type": "uint8" } @@ -46,12 +46,12 @@ "inputs": [ { "internalType": "address", - "name": "paranetKnowledgeCollectionStorageAddress", + "name": "knowledgeCollectionStorageContract", "type": "address" }, { "internalType": "uint256", - "name": "paranetKnowledgeCollectionTokenId", + "name": "knowledgeCollectionTokenId", "type": "uint256" }, { @@ -63,6 +63,22 @@ "name": "KnowledgeCollectionIsAPartOfOtherParanet", "type": "error" }, + { + "inputs": [ + { + "internalType": "address", + "name": "knowledgeCollectionStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "knowledgeCollectionTokenId", + "type": "uint256" + } + ], + "name": "KnowledgeCollectionNotInFirstEpoch", + "type": "error" + }, { "inputs": [ { @@ -700,12 +716,17 @@ "components": [ { "internalType": "string", - "name": "poolType", + "name": "name", "type": "string" }, { "internalType": "address", - "name": "addr", + "name": "storageAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "rewardTokenAddress", "type": "address" } ], @@ -790,20 +811,20 @@ }, { "indexed": false, - "internalType": "enum ParanetLib.NodesAccessPolicy", + "internalType": "uint8", "name": "nodesAccessPolicy", "type": "uint8" }, { "indexed": false, - "internalType": "enum ParanetLib.MinersAccessPolicy", + "internalType": "uint8", "name": "minersAccessPolicy", "type": "uint8" }, { "indexed": false, - "internalType": "enum ParanetLib.KnowledgeCollectionsAccessPolicy", - "name": "knowledgeCollectionsAccessPolicy", + "internalType": "uint8", + "name": "knowledgeCollectionsSubmissionPolicy", "type": "uint8" } ], @@ -939,6 +960,34 @@ "name": "ParanetServiceRegistered", "type": "event" }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKCStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeCollectionTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeAssetTokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "curator", + "type": "address" + } + ], + "name": "addCurator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -1096,6 +1145,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "chronos", + "outputs": [ + { + "internalType": "contract Chronos", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1129,7 +1191,7 @@ "type": "uint256" } ], - "internalType": "struct ParanetLib.UniversalCollectionLocator[]", + "internalType": "struct ParanetLib.UniversalAssetCollectionLocator[]", "name": "", "type": "tuple[]" } @@ -1222,6 +1284,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "paranetStagingRegistry", + "outputs": [ + { + "internalType": "contract ParanetStagingRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "paranetsRegistry", @@ -1276,14 +1351,19 @@ "type": "string" }, { - "internalType": "enum ParanetLib.NodesAccessPolicy", + "internalType": "uint8", "name": "nodesAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetLib.MinersAccessPolicy", + "internalType": "uint8", "name": "minersAccessPolicy", "type": "uint8" + }, + { + "internalType": "uint8", + "name": "knowledgeCollectionsSubmissionPolicy", + "type": "uint8" } ], "name": "registerParanet", @@ -1397,6 +1477,34 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKCStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeCollectionTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeAssetTokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "curator", + "type": "address" + } + ], + "name": "removeCurator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -1499,6 +1607,44 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKCStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeCollectionTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeAssetTokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "knowledgeCollectionStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "knowledgeCollectionTokenId", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "accepted", + "type": "bool" + } + ], + "name": "reviewKnowledgeCollection", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -1512,6 +1658,39 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKCStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeCollectionTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paranetKnowledgeAssetTokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "knowledgeCollectionStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "knowledgeCollectionTokenId", + "type": "uint256" + } + ], + "name": "stageKnowledgeCollection", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "status", diff --git a/abi/ParanetIncentivesPool.json b/abi/ParanetIncentivesPool.json new file mode 100644 index 00000000..aa111f16 --- /dev/null +++ b/abi/ParanetIncentivesPool.json @@ -0,0 +1,557 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "hubAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "knowledgeMinersRegistryAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "paranetIncentivesPoolStorageAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tracToTokenEmissionMultiplier", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint96", + "name": "currentCumulativeWeight", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "targetCumulativeWeight", + "type": "uint96" + } + ], + "name": "InvalidCumulativeVotersWeight", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "claimer", + "type": "address" + } + ], + "name": "NoRewardAvailable", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMultiplier", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newMultiplier", + "type": "uint256" + } + ], + "name": "TokenEmissionMultiplierUpdateFinalized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMultiplier", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newMultiplier", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "TokenEmissionMultiplierUpdateInitiated", + "type": "event" + }, + { + "inputs": [], + "name": "claimIncentivizationProposalVoterReward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "claimKnowledgeMinerReward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "claimParanetOperatorReward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "finalizeTokenEmissionMultiplierUpdate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getClaimableAllKnowledgeMinersRewardAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getClaimableAllProposalVotersRewardAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getClaimableKnowledgeMinerRewardAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getClaimableParanetOperatorRewardAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getClaimableProposalVoterRewardAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "getEffectiveTokenEmissionMultiplier", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getParanetIncentivesPoolStorage", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalAllKnowledgeMinersIncentiveEstimation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalAllProposalVotersIncentiveEstimation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalKnowledgeMinerIncentiveEstimation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalParanetOperatorIncentiveEstimation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalProposalVoterIncentiveEstimation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gettokenEmissionMultipliers", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "multiplier", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "finalized", + "type": "bool" + } + ], + "internalType": "struct ParanetLib.TokenEmissionMultiplier[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "hub", + "outputs": [ + { + "internalType": "contract Hub", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newMultiplier", + "type": "uint256" + } + ], + "name": "initiateTokenEmissionMultiplierUpdate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "isKnowledgeMiner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "isParanetOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "isProposalVoter", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "paranetIncentivesPoolStorage", + "outputs": [ + { + "internalType": "contract ParanetIncentivesPoolStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paranetKnowledgeMinersRegistry", + "outputs": [ + { + "internalType": "contract ParanetKnowledgeMinersRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paranetsRegistry", + "outputs": [ + { + "internalType": "contract ParanetsRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tokenEmissionMultiplierUpdateDelay", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "tokenEmissionMultipliers", + "outputs": [ + { + "internalType": "uint256", + "name": "multiplier", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "finalized", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newDelay", + "type": "uint256" + } + ], + "name": "updatetokenEmissionMultiplierUpdateDelay", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "voterclaimedToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abi/ParanetIncentivesPoolFactory.json b/abi/ParanetIncentivesPoolFactory.json index 9d86e09c..87a2d9c4 100644 --- a/abi/ParanetIncentivesPoolFactory.json +++ b/abi/ParanetIncentivesPoolFactory.json @@ -13,49 +13,61 @@ { "inputs": [ { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, "internalType": "address", - "name": "knowledgeCollectionStorageAddress", + "name": "paranetKCStorageContract", "type": "address" }, { + "indexed": true, "internalType": "uint256", - "name": "knowledgeCollectionTokenId", + "name": "paranetKCTokenId", "type": "uint256" }, { + "indexed": true, "internalType": "uint256", - "name": "knowledgeAssetTokenId", + "name": "paranetKATokenId", "type": "uint256" }, { - "internalType": "string", - "name": "poolType", - "type": "string" + "indexed": false, + "internalType": "address", + "name": "storageAddress", + "type": "address" }, { + "indexed": false, "internalType": "address", "name": "poolAddress", "type": "address" - } - ], - "name": "ParanetIncentivesPoolAlreadyExists", - "type": "error" - }, - { - "inputs": [ + }, { - "internalType": "string", - "name": "msg", - "type": "string" + "indexed": false, + "internalType": "address", + "name": "rewardTokenAddress", + "type": "address" } ], - "name": "UnauthorizedAccess", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddressHub", - "type": "error" + "name": "ParanetIncentivesPoolDeployed", + "type": "event" }, { "anonymous": false, @@ -73,34 +85,29 @@ "type": "uint256" }, { - "components": [ - { - "internalType": "string", - "name": "poolType", - "type": "string" - }, - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], + "indexed": true, + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "storageAddress", + "type": "address" + }, + { "indexed": false, - "internalType": "struct ParanetLib.IncentivesPool", - "name": "incentivesPool", - "type": "tuple" + "internalType": "address", + "name": "newPoolAddress", + "type": "address" } ], - "name": "ParanetIncetivesPoolDeployed", + "name": "ParanetIncentivesPoolRedeployed", "type": "event" }, { "inputs": [ - { - "internalType": "bool", - "name": "isNativeReward", - "type": "bool" - }, { "internalType": "address", "name": "paranetKCStorageContract", @@ -118,7 +125,7 @@ }, { "internalType": "uint256", - "name": "tracToNeuroEmissionMultiplier", + "name": "tracToTokenEmissionMultiplier", "type": "uint256" }, { @@ -130,16 +137,20 @@ "internalType": "uint16", "name": "paranetIncentivizationProposalVotersRewardPercentage", "type": "uint16" - } - ], - "name": "deployNeuroIncentivesPool", - "outputs": [ + }, + { + "internalType": "string", + "name": "incentivesPoolName", + "type": "string" + }, { "internalType": "address", - "name": "", + "name": "rewardTokenAddress", "type": "address" } ], + "name": "deployIncentivesPool", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, @@ -176,6 +187,19 @@ "stateMutability": "pure", "type": "function" }, + { + "inputs": [], + "name": "paranetIncentivesPoolFactoryHelper", + "outputs": [ + { + "internalType": "contract ParanetIncentivesPoolFactoryHelper", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "paranetsRegistry", @@ -189,6 +213,34 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "paranetKCStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "paranetKCTokenId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "paranetKATokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "storageAddress", + "type": "address" + } + ], + "name": "redeployIncentivesPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { diff --git a/abi/ParanetIncentivesPoolFactoryHelper.json b/abi/ParanetIncentivesPoolFactoryHelper.json new file mode 100644 index 00000000..6c139382 --- /dev/null +++ b/abi/ParanetIncentivesPoolFactoryHelper.json @@ -0,0 +1,123 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "hubAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "storageAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tracToTokenEmissionMultiplier", + "type": "uint256" + }, + { + "internalType": "address", + "name": "poolStorageAddress", + "type": "address" + } + ], + "name": "deployIncentivesPool", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "hub", + "outputs": [ + { + "internalType": "contract Hub", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_status", + "type": "bool" + } + ], + "name": "setStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "status", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/abi/ParanetNeuroIncentivesPool.json b/abi/ParanetIncentivesPoolStorage.json similarity index 58% rename from abi/ParanetNeuroIncentivesPool.json rename to abi/ParanetIncentivesPoolStorage.json index 41e29420..2c66b014 100644 --- a/abi/ParanetNeuroIncentivesPool.json +++ b/abi/ParanetIncentivesPoolStorage.json @@ -12,75 +12,399 @@ "type": "address" }, { + "internalType": "bytes32", + "name": "paranetId_", + "type": "bytes32" + }, + { + "internalType": "uint16", + "name": "paranetOperatorRewardPercentage_", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "paranetIncentivizationProposalVotersRewardPercentage_", + "type": "uint16" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, "internalType": "address", - "name": "paranetsRegistryAddress", + "name": "oldAddress", "type": "address" }, { + "indexed": true, "internalType": "address", - "name": "knowledgeMinersRegistryAddress", + "name": "newAddress", + "type": "address" + } + ], + "name": "IncentivesPoolAddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "miner", "type": "address" }, { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" + "indexed": false, + "internalType": "uint256", + "name": "additionalAmount", + "type": "uint256" }, { + "indexed": false, "internalType": "uint256", - "name": "tracToNeuroEmissionMultiplier", + "name": "newTotal", "type": "uint256" + } + ], + "name": "MinerRewardIncreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "miner", + "type": "address" }, { - "internalType": "uint16", - "name": "paranetOperatorRewardPercentage_", - "type": "uint16" + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "MinerRewardProfileAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "additionalAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotal", + "type": "uint256" + } + ], + "name": "OperatorRewardIncreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "OperatorRewardProfileAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" }, { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RewardTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokenRewardDeposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotal", + "type": "uint256" + } + ], + "name": "TotalMinersclaimedTokenDecremented", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newAmount", + "type": "uint256" + } + ], + "name": "TotalMinersclaimedTokenSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotal", + "type": "uint256" + } + ], + "name": "TotalOperatorsclaimedTokenDecremented", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newAmount", + "type": "uint256" + } + ], + "name": "TotalOperatorsclaimedTokenSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotal", + "type": "uint256" + } + ], + "name": "TotalVotersclaimedTokenDecremented", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newAmount", + "type": "uint256" + } + ], + "name": "TotalVotersclaimedTokenSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, "internalType": "uint16", - "name": "paranetIncentivizationProposalVotersRewardPercentage_", + "name": "weight", "type": "uint16" } ], - "stateMutability": "nonpayable", - "type": "constructor" + "name": "VoterAdded", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "weight", + "type": "uint96" + } + ], + "name": "VoterRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" }, { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "VoterRewardClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "indexed": false, "internalType": "uint96", - "name": "currentCumulativeWeight", + "name": "oldWeight", "type": "uint96" }, { + "indexed": false, "internalType": "uint96", - "name": "targetCumulativeWeight", + "name": "newWeight", "type": "uint96" } ], - "name": "InvalidCumulativeVotersWeight", - "type": "error" + "name": "VoterWeightUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" + "indexed": true, + "internalType": "address", + "name": "previousRegistrar", + "type": "address" }, { + "indexed": true, "internalType": "address", - "name": "claimer", + "name": "newRegistrar", "type": "address" } ], - "name": "NoRewardAvailable", - "type": "error" + "name": "VotersRegistrarTransferred", + "type": "event" }, { "anonymous": false, @@ -88,119 +412,141 @@ { "indexed": false, "internalType": "uint256", - "name": "oldMultiplier", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "newMultiplier", + "name": "count", "type": "uint256" } ], - "name": "NeuroEmissionMultiplierUpdateFinalized", + "name": "VotersRemoved", "type": "event" }, { - "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "oldMultiplier", - "type": "uint256" + "internalType": "address", + "name": "addr", + "type": "address" }, { - "indexed": false, "internalType": "uint256", - "name": "newMultiplier", + "name": "claimableTokenReward", "type": "uint256" + } + ], + "name": "addClaimedOperatorReward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" }, { - "indexed": false, "internalType": "uint256", - "name": "timestamp", + "name": "claimableTokenReward", "type": "uint256" } ], - "name": "NeuroEmissionMultiplierUpdateInitiated", - "type": "event" + "name": "addMinerClaimedReward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "sender", + "name": "addr", "type": "address" }, { - "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "claimableTokenReward", "type": "uint256" } ], - "name": "NeuroRewardDeposit", - "type": "event" + "name": "addMinerClaimedRewardProfile", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "voter", + "name": "addr", "type": "address" }, { - "indexed": false, + "internalType": "uint256", + "name": "claimableTokenReward", + "type": "uint256" + } + ], + "name": "addOperatorClaimedRewardsProfile", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amount", "type": "uint256" } ], - "name": "ParanetIncentivizationProposalVoterRewardClaimed", - "type": "event" + "name": "addTotalMinersclaimedToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "miner", - "type": "address" - }, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "addTotalOperatorsclaimedToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { - "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" } ], - "name": "ParanetKnowledgeMinerRewardClaimed", - "type": "event" + "name": "addTotalVotersclaimedToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "operator", + "name": "voter", "type": "address" }, { - "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" } ], - "name": "ParanetOperatorRewardClaimed", - "type": "event" + "name": "addVoterclaimedToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { "inputs": [ @@ -227,27 +573,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "claimIncentivizationProposalVoterReward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "claimKnowledgeMinerReward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "claimParanetOperatorReward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -265,7 +590,7 @@ }, { "internalType": "uint256", - "name": "claimedNeuro", + "name": "claimedToken", "type": "uint256" } ], @@ -308,7 +633,7 @@ }, { "internalType": "uint256", - "name": "claimedNeuro", + "name": "claimedToken", "type": "uint256" } ], @@ -339,17 +664,49 @@ "name": "cumulativeVotersWeight", "outputs": [ { - "internalType": "uint16", + "internalType": "uint96", "name": "", - "type": "uint16" + "type": "uint96" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "finalizeNeuroEmissionMultiplierUpdate", + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "decrementTotalMinersclaimedToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "decrementTotalOperatorsclaimedToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "decrementTotalVotersclaimedToken", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -367,7 +724,7 @@ }, { "internalType": "uint256", - "name": "claimedNeuro", + "name": "claimedToken", "type": "uint256" } ], @@ -392,7 +749,7 @@ }, { "internalType": "uint256", - "name": "claimedNeuro", + "name": "claimedToken", "type": "uint256" } ], @@ -406,20 +763,7 @@ }, { "inputs": [], - "name": "getClaimableAllKnowledgeMinersRewardAmount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getClaimableAllProposalVotersRewardAmount", + "name": "getBalance", "outputs": [ { "internalType": "uint256", @@ -431,26 +775,31 @@ "type": "function" }, { - "inputs": [], - "name": "getClaimableKnowledgeMinerRewardAmount", - "outputs": [ + "inputs": [ { "internalType": "uint256", - "name": "", + "name": "index", "type": "uint256" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getClaimableParanetOperatorRewardAmount", + "name": "getClaimedMinerRewardsAtIndex", "outputs": [ { - "internalType": "uint256", + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "claimedToken", + "type": "uint256" + } + ], + "internalType": "struct ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile", "name": "", - "type": "uint256" + "type": "tuple" } ], "stateMutability": "view", @@ -458,7 +807,7 @@ }, { "inputs": [], - "name": "getClaimableProposalVoterRewardAmount", + "name": "getClaimedMinerRewardsLength", "outputs": [ { "internalType": "uint256", @@ -473,16 +822,28 @@ "inputs": [ { "internalType": "uint256", - "name": "timestamp", + "name": "index", "type": "uint256" } ], - "name": "getEffectiveNeuroEmissionMultiplier", + "name": "getClaimedOperatorRewardsAtIndex", "outputs": [ { - "internalType": "uint256", + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "claimedToken", + "type": "uint256" + } + ], + "internalType": "struct ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile", "name": "", - "type": "uint256" + "type": "tuple" } ], "stateMutability": "view", @@ -490,7 +851,7 @@ }, { "inputs": [], - "name": "getNeuroBalance", + "name": "getClaimedOperatorRewardsLength", "outputs": [ { "internalType": "uint256", @@ -502,55 +863,81 @@ "type": "function" }, { - "inputs": [], - "name": "getNeuroEmissionMultipliers", + "inputs": [ + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "getPaginatedClaimedMinerRewards", "outputs": [ { "components": [ { - "internalType": "uint256", - "name": "multiplier", - "type": "uint256" + "internalType": "address", + "name": "addr", + "type": "address" }, { "internalType": "uint256", - "name": "timestamp", + "name": "claimedToken", "type": "uint256" - }, - { - "internalType": "bool", - "name": "finalized", - "type": "bool" } ], - "internalType": "struct ParanetLib.NeuroEmissionMultiplier[]", - "name": "", + "internalType": "struct ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[]", + "name": "rewards", "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "total", + "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "getTotalAllKnowledgeMinersIncentiveEstimation", - "outputs": [ + "inputs": [ { "internalType": "uint256", - "name": "", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", "type": "uint256" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTotalAllProposalVotersIncentiveEstimation", + "name": "getPaginatedClaimedOperatorRewards", "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "claimedToken", + "type": "uint256" + } + ], + "internalType": "struct ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[]", + "name": "rewards", + "type": "tuple[]" + }, { "internalType": "uint256", - "name": "", + "name": "total", "type": "uint256" } ], @@ -558,25 +945,45 @@ "type": "function" }, { - "inputs": [], - "name": "getTotalKnowledgeMinerIncentiveEstimation", - "outputs": [ + "inputs": [ { "internalType": "uint256", - "name": "", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", "type": "uint256" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTotalParanetOperatorIncentiveEstimation", + "name": "getPaginatedVoters", "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint96", + "name": "weight", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "claimedToken", + "type": "uint256" + } + ], + "internalType": "struct ParanetLib.ParanetIncentivizationProposalVoter[]", + "name": "votersList", + "type": "tuple[]" + }, { "internalType": "uint256", - "name": "", + "name": "total", "type": "uint256" } ], @@ -584,13 +991,36 @@ "type": "function" }, { - "inputs": [], - "name": "getTotalProposalVoterIncentiveEstimation", + "inputs": [ + { + "internalType": "address", + "name": "voterAddress", + "type": "address" + } + ], + "name": "getVoter", "outputs": [ { - "internalType": "uint256", + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint96", + "name": "weight", + "type": "uint96" + }, + { + "internalType": "uint256", + "name": "claimedToken", + "type": "uint256" + } + ], + "internalType": "struct ParanetLib.ParanetIncentivizationProposalVoter", "name": "", - "type": "uint256" + "type": "tuple" } ], "stateMutability": "view", @@ -599,12 +1029,12 @@ { "inputs": [ { - "internalType": "address", - "name": "voterAddress", - "type": "address" + "internalType": "uint256", + "name": "index", + "type": "uint256" } ], - "name": "getVoter", + "name": "getVoterAtIndex", "outputs": [ { "components": [ @@ -620,7 +1050,7 @@ }, { "internalType": "uint256", - "name": "claimedNeuro", + "name": "claimedToken", "type": "uint256" } ], @@ -650,7 +1080,7 @@ }, { "internalType": "uint256", - "name": "claimedNeuro", + "name": "claimedToken", "type": "uint256" } ], @@ -689,14 +1119,8 @@ "type": "function" }, { - "inputs": [ - { - "internalType": "uint256", - "name": "newMultiplier", - "type": "uint256" - } - ], - "name": "initiateNeuroEmissionMultiplierUpdate", + "inputs": [], + "name": "initialize", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -709,7 +1133,7 @@ "type": "address" } ], - "name": "isKnowledgeMiner", + "name": "isProposalVoter", "outputs": [ { "internalType": "bool", @@ -724,49 +1148,43 @@ "inputs": [ { "internalType": "address", - "name": "addr", + "name": "minerAddress", "type": "address" } ], - "name": "isParanetOperator", + "name": "minerclaimedToken", "outputs": [ { - "internalType": "bool", + "internalType": "uint256", "name": "", - "type": "bool" + "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "isProposalVoter", + "inputs": [], + "name": "name", "outputs": [ { - "internalType": "bool", + "internalType": "string", "name": "", - "type": "bool" + "type": "string" } ], - "stateMutability": "view", + "stateMutability": "pure", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "minerAddress", + "name": "operatorAddress", "type": "address" } ], - "name": "minerClaimedNeuro", + "name": "operatorclaimedToken", "outputs": [ { "internalType": "uint256", @@ -779,73 +1197,51 @@ }, { "inputs": [], - "name": "name", + "name": "paranetId", "outputs": [ { - "internalType": "string", + "internalType": "bytes32", "name": "", - "type": "string" + "type": "bytes32" } ], - "stateMutability": "pure", + "stateMutability": "view", "type": "function" }, { "inputs": [], - "name": "neuroEmissionMultiplierUpdateDelay", + "name": "paranetIncentivesPoolAddress", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "neuroEmissionMultipliers", + "inputs": [], + "name": "paranetIncentivizationProposalVotersRewardPercentage", "outputs": [ { - "internalType": "uint256", - "name": "multiplier", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "finalized", - "type": "bool" + "internalType": "uint16", + "name": "", + "type": "uint16" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [ - { - "internalType": "address", - "name": "operatorAddress", - "type": "address" - } - ], - "name": "operatorClaimedNeuro", + "inputs": [], + "name": "paranetOperatorRewardPercentage", "outputs": [ { - "internalType": "uint256", + "internalType": "uint16", "name": "", - "type": "uint256" + "type": "uint16" } ], "stateMutability": "view", @@ -853,78 +1249,91 @@ }, { "inputs": [], - "name": "paranetIncentivizationProposalVotersRewardPercentage", + "name": "paranetsRegistry", "outputs": [ { - "internalType": "uint16", + "internalType": "contract ParanetsRegistry", "name": "", - "type": "uint16" + "type": "address" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "paranetKnowledgeMinersRegistry", - "outputs": [ + "inputs": [ { - "internalType": "contract ParanetKnowledgeMinersRegistry", - "name": "", + "internalType": "address", + "name": "voterAddress", "type": "address" } ], - "stateMutability": "view", + "name": "removeVoter", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "paranetOperatorRewardPercentage", - "outputs": [ + "inputs": [ { - "internalType": "uint16", - "name": "", - "type": "uint16" + "internalType": "address[]", + "name": "votersToRemove", + "type": "address[]" } ], - "stateMutability": "view", + "name": "removeVoters", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "paranetsRegistry", - "outputs": [ + "inputs": [ { - "internalType": "contract ParanetsRegistry", - "name": "", + "internalType": "address", + "name": "_paranetIncentivesPoolAddress", "type": "address" } ], - "stateMutability": "view", + "name": "setParanetIncentivesPool", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "parentParanetId", - "outputs": [ + "inputs": [ { - "internalType": "bytes32", - "name": "", - "type": "bytes32" + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "stateMutability": "view", + "name": "setTotalMinersclaimedToken", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "uint256", - "name": "limit", + "name": "amount", "type": "uint256" } ], - "name": "removeVoters", + "name": "setTotalOperatorsclaimedToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "setTotalVotersclaimedToken", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -944,7 +1353,7 @@ }, { "inputs": [], - "name": "totalMinersClaimedNeuro", + "name": "totalMinersclaimedToken", "outputs": [ { "internalType": "uint256", @@ -957,7 +1366,7 @@ }, { "inputs": [], - "name": "totalNeuroReceived", + "name": "totalOperatorsclaimedToken", "outputs": [ { "internalType": "uint256", @@ -970,7 +1379,7 @@ }, { "inputs": [], - "name": "totalOperatorsClaimedNeuro", + "name": "totalReceived", "outputs": [ { "internalType": "uint256", @@ -983,7 +1392,7 @@ }, { "inputs": [], - "name": "totalVotersClaimedNeuro", + "name": "totalVotersclaimedToken", "outputs": [ { "internalType": "uint256", @@ -994,6 +1403,24 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "rewardAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferReward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -1010,12 +1437,17 @@ { "inputs": [ { - "internalType": "uint256", - "name": "newDelay", - "type": "uint256" + "internalType": "address", + "name": "voter", + "type": "address" + }, + { + "internalType": "uint96", + "name": "newWeight", + "type": "uint96" } ], - "name": "updateNeuroEmissionMultiplierUpdateDelay", + "name": "updateVoterWeight", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1033,25 +1465,6 @@ "stateMutability": "pure", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "voterAddress", - "type": "address" - } - ], - "name": "voterClaimedNeuro", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -1074,7 +1487,7 @@ }, { "internalType": "uint256", - "name": "claimedNeuro", + "name": "claimedToken", "type": "uint256" } ], diff --git a/abi/ParanetKnowledgeCollectionsRegistry.json b/abi/ParanetKnowledgeCollectionsRegistry.json index 7a654245..dea39e71 100644 --- a/abi/ParanetKnowledgeCollectionsRegistry.json +++ b/abi/ParanetKnowledgeCollectionsRegistry.json @@ -107,7 +107,7 @@ "type": "uint256" } ], - "internalType": "struct ParanetLib.UniversalCollectionLocator[]", + "internalType": "struct ParanetLib.UniversalAssetCollectionLocator[]", "name": "", "type": "tuple[]" } diff --git a/abi/ParanetKnowledgeMinersRegistry.json b/abi/ParanetKnowledgeMinersRegistry.json index f77f96fd..5aa6397f 100644 --- a/abi/ParanetKnowledgeMinersRegistry.json +++ b/abi/ParanetKnowledgeMinersRegistry.json @@ -26,29 +26,6 @@ "name": "ZeroAddressHub", "type": "error" }, - { - "inputs": [ - { - "internalType": "address", - "name": "miner", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "addedCumulativeAwardedNeuro", - "type": "uint256" - } - ], - "name": "addCumulativeAwardedNeuro", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -208,9 +185,19 @@ "internalType": "address", "name": "miner", "type": "address" + }, + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "addedcumulativeAwardedToken", + "type": "uint256" } ], - "name": "decrementTotalSubmittedKnowledgeCollectionsCount", + "name": "addcumulativeAwardedToken", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -223,7 +210,7 @@ "type": "address" } ], - "name": "deleteKnowledgeMiner", + "name": "decrementTotalSubmittedKnowledgeCollectionsCount", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -234,22 +221,11 @@ "internalType": "address", "name": "miner", "type": "address" - }, - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - } - ], - "name": "getCumulativeAwardedNeuro", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" } ], - "stateMutability": "view", + "name": "deleteKnowledgeMiner", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { @@ -534,6 +510,30 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "miner", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "getcumulativeAwardedToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "hub", @@ -648,29 +648,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "miner", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "cumulativeAwardedNeuro", - "type": "uint256" - } - ], - "name": "setCumulativeAwardedNeuro", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -795,11 +772,11 @@ }, { "internalType": "uint256", - "name": "subtractedCumulativeAwardedNeuro", + "name": "cumulativeAwardedToken", "type": "uint256" } ], - "name": "subCumulativeAwardedNeuro", + "name": "setcumulativeAwardedToken", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -896,6 +873,29 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "miner", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "subtractedcumulativeAwardedToken", + "type": "uint256" + } + ], + "name": "subcumulativeAwardedToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "version", diff --git a/abi/ParanetStagingRegistry.json b/abi/ParanetStagingRegistry.json new file mode 100644 index 00000000..3fa71f09 --- /dev/null +++ b/abi/ParanetStagingRegistry.json @@ -0,0 +1,548 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "hubAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "curator", + "type": "address" + } + ], + "name": "CuratorAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "curator", + "type": "address" + } + ], + "name": "CuratorRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "knowledgeCollectionId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bool", + "name": "accepted", + "type": "bool" + } + ], + "name": "KnowledgeCollectionReviewed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "knowledgeCollectionId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "submitter", + "type": "address" + } + ], + "name": "KnowledgeCollectionStaged", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "curator", + "type": "address" + } + ], + "name": "addCurator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "collectionSubmitters", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "curators", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "getAllParanetCurators", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "knowledgeCollectionId", + "type": "bytes32" + } + ], + "name": "getKnowledgeCollectionStatus", + "outputs": [ + { + "internalType": "enum ParanetLib.RequestStatus", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "knowledgeCollectionId", + "type": "bytes32" + } + ], + "name": "getKnowledgeCollectionSubmitter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "getPendingCollections", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "knowledgeCollectionId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "submitter", + "type": "address" + }, + { + "internalType": "enum ParanetLib.RequestStatus", + "name": "status", + "type": "uint8" + } + ], + "internalType": "struct ParanetStagingRegistry.StagedCollection[]", + "name": "collections", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "total", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "hub", + "outputs": [ + { + "internalType": "contract Hub", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "isCurator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "knowledgeCollectionId", + "type": "bytes32" + } + ], + "name": "isKnowledgeCollectionApproved", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "knowledgeCollectionId", + "type": "bytes32" + } + ], + "name": "isKnowledgeCollectionStaged", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "paranetCuratorIndexes", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "paranetCurators", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "curator", + "type": "address" + } + ], + "name": "removeCurator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "knowledgeCollectionId", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "accepted", + "type": "bool" + } + ], + "name": "reviewKnowledgeCollection", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "knowledgeCollectionId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "submitter", + "type": "address" + } + ], + "name": "stageKnowledgeCollection", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "stagedCollections", + "outputs": [ + { + "internalType": "enum ParanetLib.RequestStatus", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/abi/ParanetsRegistry.json b/abi/ParanetsRegistry.json index 274a8604..f7e46720 100644 --- a/abi/ParanetsRegistry.json +++ b/abi/ParanetsRegistry.json @@ -10,55 +10,6 @@ "stateMutability": "nonpayable", "type": "constructor" }, - { - "inputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "AddressAlreadyInSet", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "AddressDoesNotExist", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "name", - "type": "string" - } - ], - "name": "ContractAlreadyExists", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "name", - "type": "string" - } - ], - "name": "ContractDoesNotExist", - "type": "error" - }, - { - "inputs": [], - "name": "EmptyName", - "type": "error" - }, { "inputs": [ { @@ -70,11 +21,6 @@ "name": "UnauthorizedAccess", "type": "error" }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, { "inputs": [], "name": "ZeroAddressHub", @@ -121,6 +67,34 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "incentivesPoolName", + "type": "string" + }, + { + "internalType": "address", + "name": "storageAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "rewardTokenAddress", + "type": "address" + } + ], + "name": "addIncentivesPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -253,11 +227,16 @@ }, { "internalType": "address", - "name": "addr", + "name": "storageAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "rewardTokenAddress", "type": "address" } ], - "internalType": "struct UnorderedNamedContractDynamicSet.Contract[]", + "internalType": "struct ParanetLib.IncentivesPool[]", "name": "", "type": "tuple[]" } @@ -375,16 +354,33 @@ }, { "internalType": "string", - "name": "incentivesPoolType", + "name": "poolName", "type": "string" } ], - "name": "getIncentivesPoolAddress", + "name": "getIncentivesPoolByPoolName", "outputs": [ { - "internalType": "address", + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "storageAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "rewardTokenAddress", + "type": "address" + } + ], + "internalType": "struct ParanetLib.IncentivesPool", "name": "", - "type": "address" + "type": "tuple" } ], "stateMutability": "view", @@ -396,14 +392,36 @@ "internalType": "bytes32", "name": "paranetId", "type": "bytes32" + }, + { + "internalType": "address", + "name": "storageAddr", + "type": "address" } ], - "name": "getKnowledgeCollections", + "name": "getIncentivesPoolByStorageAddress", "outputs": [ { - "internalType": "bytes32[]", + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "storageAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "rewardTokenAddress", + "type": "address" + } + ], + "internalType": "struct ParanetLib.IncentivesPool", "name": "", - "type": "bytes32[]" + "type": "tuple" } ], "stateMutability": "view", @@ -417,12 +435,12 @@ "type": "bytes32" } ], - "name": "getKnowledgeCollectionsAccessPolicy", + "name": "getKnowledgeCollections", "outputs": [ { - "internalType": "enum ParanetLib.KnowledgeCollectionsAccessPolicy", + "internalType": "bytes32[]", "name": "", - "type": "uint8" + "type": "bytes32[]" } ], "stateMutability": "view", @@ -476,6 +494,25 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "getKnowledgeCollectionsSubmissionPolicy", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -767,7 +804,7 @@ "name": "getMinersAccessPolicy", "outputs": [ { - "internalType": "enum ParanetLib.MinersAccessPolicy", + "internalType": "uint8", "name": "", "type": "uint8" } @@ -926,7 +963,7 @@ "name": "getNodesAccessPolicy", "outputs": [ { - "internalType": "enum ParanetLib.NodesAccessPolicy", + "internalType": "uint8", "name": "", "type": "uint8" } @@ -1063,18 +1100,18 @@ "type": "string" }, { - "internalType": "enum ParanetLib.NodesAccessPolicy", + "internalType": "uint8", "name": "nodesAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetLib.MinersAccessPolicy", + "internalType": "uint8", "name": "minersAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetLib.KnowledgeCollectionsAccessPolicy", - "name": "knowledgeCollectionsAccessPolicy", + "internalType": "uint8", + "name": "knowledgeCollectionsSubmissionPolicy", "type": "uint8" }, { @@ -1150,12 +1187,12 @@ "type": "bytes32" }, { - "internalType": "address", - "name": "incentivesPoolAddress", - "type": "address" + "internalType": "string", + "name": "poolName", + "type": "string" } ], - "name": "hasIncentivesPoolByAddress", + "name": "hasIncentivesPoolByName", "outputs": [ { "internalType": "bool", @@ -1174,12 +1211,12 @@ "type": "bytes32" }, { - "internalType": "string", - "name": "incentivesPoolType", - "type": "string" + "internalType": "address", + "name": "storageAddr", + "type": "address" } ], - "name": "hasIncentivesPoolByType", + "name": "hasIncentivesPoolByStorageAddress", "outputs": [ { "internalType": "bool", @@ -1359,18 +1396,18 @@ "type": "string" }, { - "internalType": "enum ParanetLib.NodesAccessPolicy", + "internalType": "uint8", "name": "nodesAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetLib.MinersAccessPolicy", + "internalType": "uint8", "name": "minersAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetLib.KnowledgeCollectionsAccessPolicy", - "name": "knowledgeColletionsAccessPolicy", + "internalType": "uint8", + "name": "knowledgeCollectionsSubmissionPolicy", "type": "uint8" } ], @@ -1403,42 +1440,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "incentivesPoolAddress", - "type": "address" - } - ], - "name": "removeIncentivesPool", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "incentivesPoolType", - "type": "string" - } - ], - "name": "removeIncentivesPool", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -1583,35 +1584,12 @@ "type": "bytes32" }, { - "internalType": "string", - "name": "incentivesPoolType", - "type": "string" - }, - { - "internalType": "address", - "name": "incentivesPoolAddress", - "type": "address" - } - ], - "name": "setIncentivesPoolAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "enum ParanetLib.KnowledgeCollectionsAccessPolicy", - "name": "knowledgeCollectionsAccessPolicy", + "internalType": "uint8", + "name": "knowledgeCollectionsSubmissionPolicy", "type": "uint8" } ], - "name": "setKnowledgeCollectionsAccessPolicy", + "name": "setKnowledgeCollectionsSubmissionPolicy", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1624,7 +1602,7 @@ "type": "bytes32" }, { - "internalType": "enum ParanetLib.MinersAccessPolicy", + "internalType": "uint8", "name": "minersAccessPolicy", "type": "uint8" } @@ -1660,7 +1638,7 @@ "type": "bytes32" }, { - "internalType": "enum ParanetLib.NodesAccessPolicy", + "internalType": "uint8", "name": "nodesAccessPolicy", "type": "uint8" } @@ -1688,29 +1666,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "incentivesPoolType", - "type": "string" - }, - { - "internalType": "address", - "name": "incentivesPoolAddress", - "type": "address" - } - ], - "name": "updateIncentivesPoolAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { From 5115bc4b4c82fa3fe42df976f37fc6372056230c Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 14 Feb 2025 15:31:09 +0100 Subject: [PATCH 108/153] Fix deployer function --- ...paranet_Incentives_pool_factory_helper.ts} | 7 ---- ..._deploy_paranet_incentives_pool_factory.ts | 23 ------------- deploy/027_deploy_migrator.ts | 34 ------------------- ..._deploy_paranet_incentives_pool_factory.ts | 13 +++---- 4 files changed, 5 insertions(+), 72 deletions(-) rename deploy/{025_deploy_paranet_Incentives_pool_factory_helper.ts => 026_deploy_paranet_Incentives_pool_factory_helper.ts} (76%) delete mode 100644 deploy/026_deploy_paranet_incentives_pool_factory.ts delete mode 100644 deploy/027_deploy_migrator.ts diff --git a/deploy/025_deploy_paranet_Incentives_pool_factory_helper.ts b/deploy/026_deploy_paranet_Incentives_pool_factory_helper.ts similarity index 76% rename from deploy/025_deploy_paranet_Incentives_pool_factory_helper.ts rename to deploy/026_deploy_paranet_Incentives_pool_factory_helper.ts index fcd2fe90..6bdba8ba 100644 --- a/deploy/025_deploy_paranet_Incentives_pool_factory_helper.ts +++ b/deploy/026_deploy_paranet_Incentives_pool_factory_helper.ts @@ -2,13 +2,6 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { DeployFunction } from 'hardhat-deploy/types'; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - if ( - !hre.network.name.startsWith('neuroweb') && - !hre.network.name.startsWith('hardhat') - ) { - return; - } - await hre.helpers.deploy({ newContractName: 'ParanetIncentivesPoolFactoryHelper', }); diff --git a/deploy/026_deploy_paranet_incentives_pool_factory.ts b/deploy/026_deploy_paranet_incentives_pool_factory.ts deleted file mode 100644 index f24494e4..00000000 --- a/deploy/026_deploy_paranet_incentives_pool_factory.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { HardhatRuntimeEnvironment } from 'hardhat/types'; -import { DeployFunction } from 'hardhat-deploy/types'; - -const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - if ( - !hre.network.name.startsWith('neuroweb') && - !hre.network.name.startsWith('hardhat') - ) { - return; - } - - await hre.helpers.deploy({ - newContractName: 'ParanetIncentivesPoolFactory', - }); -}; - -export default func; -func.tags = ['ParanetIncentivesPoolFactory']; -func.dependencies = [ - 'Hub', - 'ParanetsRegistry', - 'ParanetIncentivesPoolFactoryHelper', -]; diff --git a/deploy/027_deploy_migrator.ts b/deploy/027_deploy_migrator.ts deleted file mode 100644 index 6a06ea38..00000000 --- a/deploy/027_deploy_migrator.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { HardhatRuntimeEnvironment } from 'hardhat/types'; -import { DeployFunction } from 'hardhat-deploy/types'; - -const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const oldHubAddress = - hre.helpers.contractDeployments.contracts['OldHub']?.evmAddress; - - if (hre.network.config.environment === 'development' || !oldHubAddress) { - return; - } - - const Migrator = await hre.helpers.deploy({ - newContractName: 'Migrator', - additionalArgs: [oldHubAddress], - }); - - hre.helpers.setParametersEncodedData.push({ - contractName: 'Migrator', - encodedData: [ - Migrator.interface.encodeFunctionData('initializeOldContracts', []), - Migrator.interface.encodeFunctionData('initializeNewContracts', []), - ], - }); -}; - -export default func; -func.tags = ['Migrator']; -func.dependencies = [ - 'Hub', - 'IdentityStorage', - 'ProfileStorage', - 'StakingStorage', - 'Ask', -]; diff --git a/deploy/027_deploy_paranet_incentives_pool_factory.ts b/deploy/027_deploy_paranet_incentives_pool_factory.ts index 68d18455..13284857 100644 --- a/deploy/027_deploy_paranet_incentives_pool_factory.ts +++ b/deploy/027_deploy_paranet_incentives_pool_factory.ts @@ -2,13 +2,6 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { DeployFunction } from 'hardhat-deploy/types'; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - if ( - !hre.network.name.startsWith('neuroweb') && - !hre.network.name.startsWith('hardhat') - ) { - return; - } - await hre.helpers.deploy({ newContractName: 'ParanetIncentivesPoolFactory', }); @@ -16,4 +9,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { export default func; func.tags = ['ParanetIncentivesPoolFactory']; -func.dependencies = ['Hub', 'ParanetsRegistry']; +func.dependencies = [ + 'Hub', + 'ParanetsRegistry', + 'ParanetIncentivesPoolFactoryHelper', +]; From 588b34becb8e459fba4ec0bfad6a142aba18d404 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 14 Feb 2025 16:15:35 +0100 Subject: [PATCH 109/153] deployments update --- deployments/base_sepolia_test_contracts.json | 67 +++++++++++----- deployments/gnosis_chiado_test_contracts.json | 67 +++++++++++----- deployments/neuroweb_testnet_contracts.json | 80 ++++++++++++------- 3 files changed, 144 insertions(+), 70 deletions(-) diff --git a/deployments/base_sepolia_test_contracts.json b/deployments/base_sepolia_test_contracts.json index 0426f426..ba957e29 100644 --- a/deployments/base_sepolia_test_contracts.json +++ b/deployments/base_sepolia_test_contracts.json @@ -191,48 +191,75 @@ "deployed": true }, "ParanetsRegistry": { - "evmAddress": "0x734Ad13B02D41d3e8740c6892B863D53951420Fe", + "evmAddress": "0x9206357dE0470578577Da64824948F5C0c75062e", "version": "1.0.1", "gitBranch": "v8-paranet-update", - "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", - "deploymentBlock": 21282805, - "deploymentTimestamp": 1738333901133, + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 21888878, + "deploymentTimestamp": 1739546047603, "deployed": true }, "ParanetServicesRegistry": { - "evmAddress": "0xB17D6e67998CF107dbCe6b26502e002dd76e9999", + "evmAddress": "0xD3825ba7f62C64841670e474d5F80DB440761090", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", - "deploymentBlock": 21282808, - "deploymentTimestamp": 1738333908284, + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 21888881, + "deploymentTimestamp": 1739546053932, "deployed": true }, "ParanetKnowledgeCollectionsRegistry": { - "evmAddress": "0xbdbe818FD8664BF8B2d944CDe33587f419F83C45", + "evmAddress": "0xEfE1da366bD33D1aa8463E9B426ec9732Cc08d0f", "version": "1.0.1", "gitBranch": "v8-paranet-update", - "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", - "deploymentBlock": 21282811, - "deploymentTimestamp": 1738333914891, + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 21888884, + "deploymentTimestamp": 1739546060173, "deployed": true }, "ParanetKnowledgeMinersRegistry": { - "evmAddress": "0x5f444c05a8Fd28F8BA618F452F439ef5894D3060", + "evmAddress": "0x69742927D6C05696e8B9FC44dce8482fE1EAC1a7", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", - "deploymentBlock": 21282815, - "deploymentTimestamp": 1738333921676, + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 21888887, + "deploymentTimestamp": 1739546066413, + "deployed": true + }, + "ParanetStagingRegistry": { + "evmAddress": "0x68a499Aa96e3Ab9198E3AFd9878a9A1986ce6FD4", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 21888890, + "deploymentTimestamp": 1739546072785, "deployed": true }, "Paranet": { - "evmAddress": "0x6f841a01D6Cd947d444cBa94103B9F8D610F12c1", + "evmAddress": "0x52E85E8B2Aa0fbc937124657808b58F44d842687", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 21888894, + "deploymentTimestamp": 1739546079456, + "deployed": true + }, + "ParanetIncentivesPoolFactoryHelper": { + "evmAddress": "0x1Ab3D684d68aeFd45D93AD21D38cec8A021dF92c", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 21888897, + "deploymentTimestamp": 1739546085830, + "deployed": true + }, + "ParanetIncentivesPoolFactory": { + "evmAddress": "0xB6C80577a633d33f4f5B1eaC400f8003c10d8eeA", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", - "deploymentBlock": 21282818, - "deploymentTimestamp": 1738333928833, + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 21888900, + "deploymentTimestamp": 1739546092097, "deployed": true } } diff --git a/deployments/gnosis_chiado_test_contracts.json b/deployments/gnosis_chiado_test_contracts.json index 8e4226b1..9c869d69 100644 --- a/deployments/gnosis_chiado_test_contracts.json +++ b/deployments/gnosis_chiado_test_contracts.json @@ -191,48 +191,75 @@ "deployed": true }, "ParanetsRegistry": { - "evmAddress": "0x070b9e4e2C0d8aAB8965D05167572C73C97BB06f", + "evmAddress": "0xE5d5E772A3c244dB74460Fa4aB8164abc3488b77", "version": "1.0.1", "gitBranch": "v8-paranet-update", - "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", - "deploymentBlock": 14094593, - "deploymentTimestamp": 1738333780660, + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 14320926, + "deploymentTimestamp": 1739545228318, "deployed": true }, "ParanetServicesRegistry": { - "evmAddress": "0x698D59C74dccD57b53F5A00e314eA770BAcFab79", + "evmAddress": "0xA5dDA9D3E11Cd893c68C6bD18F106F4dA657b217", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", - "deploymentBlock": 14094594, - "deploymentTimestamp": 1738333786293, + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 14320928, + "deploymentTimestamp": 1739545237257, "deployed": true }, "ParanetKnowledgeCollectionsRegistry": { - "evmAddress": "0x8A055234b7479BA0f9358EBA6cFf3aF1ac6ecC53", + "evmAddress": "0x6e6B1DF2e3C7fA05bFe7B857EC290E09Bb2253E2", "version": "1.0.1", "gitBranch": "v8-paranet-update", - "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", - "deploymentBlock": 14094595, - "deploymentTimestamp": 1738333795552, + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 14320930, + "deploymentTimestamp": 1739545246575, "deployed": true }, "ParanetKnowledgeMinersRegistry": { - "evmAddress": "0x4A83f16dd5c7fd0c9874FE4706cD574011d20E6C", + "evmAddress": "0x9b9fE20D5C0340D211E5A1773b2d0579b76355Ce", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", - "deploymentBlock": 14094596, - "deploymentTimestamp": 1738333801377, + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 14320931, + "deploymentTimestamp": 1739545252290, + "deployed": true + }, + "ParanetStagingRegistry": { + "evmAddress": "0x7E13De6397Dc696f5f787CD1b37b7C7Fa9f7C9F9", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 14320932, + "deploymentTimestamp": 1739545257350, "deployed": true }, "Paranet": { - "evmAddress": "0x6494540fDA6E197A8dF4155f895Aa61A971D2B5b", + "evmAddress": "0x2b4151c089a46271179ddb75bA170f352D66D047", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 14320933, + "deploymentTimestamp": 1739545262737, + "deployed": true + }, + "ParanetIncentivesPoolFactoryHelper": { + "evmAddress": "0x66c1D07945878A5A0D4051a31bC05EDB787f75b0", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 14320935, + "deploymentTimestamp": 1739545272239, + "deployed": true + }, + "ParanetIncentivesPoolFactory": { + "evmAddress": "0x159bBE54A8F3C8c7f78A1dECA0B8B3e203aa0DE5", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", - "deploymentBlock": 14094597, - "deploymentTimestamp": 1738333806716, + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 14320937, + "deploymentTimestamp": 1739545281595, "deployed": true } } diff --git a/deployments/neuroweb_testnet_contracts.json b/deployments/neuroweb_testnet_contracts.json index 0a9b6d3e..6911208f 100644 --- a/deployments/neuroweb_testnet_contracts.json +++ b/deployments/neuroweb_testnet_contracts.json @@ -212,63 +212,83 @@ "deployed": true }, "ParanetsRegistry": { - "evmAddress": "0x5C4915989900577cf623B2F9Cc2e2DEEDDFd1735", - "substrateAddress": "5EMjsczefdy9Q6WfbW6XqnaaqwmweMbYF4xnhgMjL9dWNGt5", + "evmAddress": "0xDAb0dF77a85951e217886995E6bCcB3c6590B01E", + "substrateAddress": "5EMjsd15zgA8DAUHD4xzQDhpUGoGojVnBoC8F8Y9C1M2bAuN", "version": "1.0.1", "gitBranch": "v8-paranet-update", - "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", - "deploymentBlock": 6207080, - "deploymentTimestamp": 1738333636752, + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 6389113, + "deploymentTimestamp": 1739545129429, "deployed": true }, "ParanetServicesRegistry": { - "evmAddress": "0x612627453FCEF0B3792E621bdF96c9C96d5Ba578", - "substrateAddress": "5EMjsczfeAGYxD6sF1easgsBBqkQgRydgPaMJXxrn2qgERpf", + "evmAddress": "0x62bFe0481DC3c0712179241F44178CB92C478CFe", + "substrateAddress": "5EMjsczfxm5abhSYkYUnwnkG62qtbSZdEbhvaRBxmq3g9urX", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", - "deploymentBlock": 6207081, - "deploymentTimestamp": 1738333641897, + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 6389114, + "deploymentTimestamp": 1739545138454, "deployed": true }, "ParanetKnowledgeCollectionsRegistry": { - "evmAddress": "0x17686361437FD87D90aEbeb632E6DF98B11288F7", - "substrateAddress": "5EMjsczQsAcDRQe13srwDZN8pqoVBNPWc6Tx7ZHpTD15cUXi", + "evmAddress": "0x9589181876C5b376dDe6476Fa8B63C5870D788Ce", + "substrateAddress": "5EMjsczr8ydmcL7Z8kHLtUqoHLcVrhy1WngRmVPCzuKAVBuH", "version": "1.0.1", "gitBranch": "v8-paranet-update", - "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", - "deploymentBlock": 6207082, - "deploymentTimestamp": 1738333647010, + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 6389115, + "deploymentTimestamp": 1739545143471, "deployed": true }, "ParanetKnowledgeMinersRegistry": { - "evmAddress": "0x452b9Ae4998d979368AA9AcdB23A35844914d876", - "substrateAddress": "5EMjscza3162R3cjs88XTMVa24UmMFvGnGtWLDMwR6F9gRYw", + "evmAddress": "0x95C1955F10ABD4a7020547D1D78307c8eB61c8fa", + "substrateAddress": "5EMjsczrBYNaDau1HgCooqyi3RRsuVD2XRsMjDRk3CKVZgBB", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", - "deploymentBlock": 6207083, - "deploymentTimestamp": 1738333652729, + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 6389116, + "deploymentTimestamp": 1739545148571, + "deployed": true + }, + "ParanetStagingRegistry": { + "evmAddress": "0x38ca1Ad904ba046831ad5E3449ddbd3Ba3D0413b", + "substrateAddress": "5EMjsczXZ7i4ArZm5eVqEy6iBusAi3Q6fkTMQUgzE1ZEPR8p", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 6389117, + "deploymentTimestamp": 1739545153778, "deployed": true }, "Paranet": { - "evmAddress": "0xDDDc8ac99313B0BFA251DaA714bCB75566277369", - "substrateAddress": "5EMjsd16dXJdxjKtXvpHpDawRqGazeoBzuY1wew7eKvQL9ND", + "evmAddress": "0x450d60D6bBB80Aa262257EF1e8fa72F628CfE53f", + "substrateAddress": "5EMjscza1dVvhhoJwjxFNHTQKzYQdYWF1pHAY7dGrtPH8DRk", + "version": "1.0.0", + "gitBranch": "v8-paranet-update", + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 6389118, + "deploymentTimestamp": 1739545159123, + "deployed": true + }, + "ParanetIncentivesPoolFactoryHelper": { + "evmAddress": "0x5A6553d60540B31184550B05ed83A1B8071Ae31C", + "substrateAddress": "5EMjsczeHgDwtsG594Mk3NPpH8zE35n5pAThyeQgLerwFz2s", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", - "deploymentBlock": 6207084, - "deploymentTimestamp": 1738333658436, + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 6389119, + "deploymentTimestamp": 1739545168191, "deployed": true }, "ParanetIncentivesPoolFactory": { - "evmAddress": "0x157C9b49968200B90Da630F18FB809858c87aeBa", - "substrateAddress": "5EMjsczQUqjWoV8veQT7sBtdzLSJYCH8pCzVUhmdmo7xkkRd", + "evmAddress": "0x4fc427922A9593a137A4E834E019c9F079554719", + "substrateAddress": "5EMjsczcA9JXKbkqeSyX1x91zJf7omcNZr8J3PbXkF8yu3GR", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "4da11a2df6531292cc9ae01c307f6f69e5845f5b", - "deploymentBlock": 6207086, - "deploymentTimestamp": 1738333671698, + "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", + "deploymentBlock": 6389120, + "deploymentTimestamp": 1739545173451, "deployed": true } } From 3b84160f991b8d70ecb453779e76582e1897068a Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 14 Feb 2025 17:01:05 +0100 Subject: [PATCH 110/153] Fix KC epoch check --- contracts/paranets/Paranet.sol | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 980bfc7c..2c8b81aa 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -1070,7 +1070,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 currentEpoch = chronos.getCurrentEpoch(); uint40 kcStartEpoch = kcs.getStartEpoch(knowledgeCollectionTokenId); - if (kcStartEpoch == currentEpoch || kcStartEpoch - 1 == currentEpoch) { + if (!(kcStartEpoch == currentEpoch || kcStartEpoch - 1 == currentEpoch)) { revert ParanetLib.KnowledgeCollectionNotInFirstEpoch( knowledgeCollectionStorageContract, knowledgeCollectionTokenId @@ -1141,6 +1141,17 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { "Paranet does not allow staging of knowledge collections" ); + KnowledgeCollectionStorage kcs = KnowledgeCollectionStorage(knowledgeCollectionStorageContract); + uint256 currentEpoch = chronos.getCurrentEpoch(); + uint40 kcStartEpoch = kcs.getStartEpoch(knowledgeCollectionTokenId); + + if (!(kcStartEpoch == currentEpoch || kcStartEpoch - 1 == currentEpoch)) { + revert ParanetLib.KnowledgeCollectionNotInFirstEpoch( + knowledgeCollectionStorageContract, + knowledgeCollectionTokenId + ); + } + bytes32 knowledgeCollectionId = keccak256( abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) ); From 1fe8493ff9b710ebcf8ff777d2aa14c93f79b784 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 14 Feb 2025 17:04:43 +0100 Subject: [PATCH 111/153] redeploy paranet --- deployments/base_sepolia_test_contracts.json | 8 ++++---- deployments/gnosis_chiado_test_contracts.json | 8 ++++---- deployments/neuroweb_testnet_contracts.json | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/deployments/base_sepolia_test_contracts.json b/deployments/base_sepolia_test_contracts.json index ba957e29..dfa95014 100644 --- a/deployments/base_sepolia_test_contracts.json +++ b/deployments/base_sepolia_test_contracts.json @@ -236,12 +236,12 @@ "deployed": true }, "Paranet": { - "evmAddress": "0x52E85E8B2Aa0fbc937124657808b58F44d842687", + "evmAddress": "0x081Bebed0c8b36031B32a78B115528BD84f11Cb5", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 21888894, - "deploymentTimestamp": 1739546079456, + "gitCommitHash": "3b84160f991b8d70ecb453779e76582e1897068a", + "deploymentBlock": 21890338, + "deploymentTimestamp": 1739548969315, "deployed": true }, "ParanetIncentivesPoolFactoryHelper": { diff --git a/deployments/gnosis_chiado_test_contracts.json b/deployments/gnosis_chiado_test_contracts.json index 9c869d69..2f6f767e 100644 --- a/deployments/gnosis_chiado_test_contracts.json +++ b/deployments/gnosis_chiado_test_contracts.json @@ -236,12 +236,12 @@ "deployed": true }, "Paranet": { - "evmAddress": "0x2b4151c089a46271179ddb75bA170f352D66D047", + "evmAddress": "0x1b57cfdcA17834e9236B745c7d2Fe051216C19ea", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 14320933, - "deploymentTimestamp": 1739545262737, + "gitCommitHash": "3b84160f991b8d70ecb453779e76582e1897068a", + "deploymentBlock": 14321650, + "deploymentTimestamp": 1739549006694, "deployed": true }, "ParanetIncentivesPoolFactoryHelper": { diff --git a/deployments/neuroweb_testnet_contracts.json b/deployments/neuroweb_testnet_contracts.json index 6911208f..a55cd291 100644 --- a/deployments/neuroweb_testnet_contracts.json +++ b/deployments/neuroweb_testnet_contracts.json @@ -262,13 +262,13 @@ "deployed": true }, "Paranet": { - "evmAddress": "0x450d60D6bBB80Aa262257EF1e8fa72F628CfE53f", - "substrateAddress": "5EMjscza1dVvhhoJwjxFNHTQKzYQdYWF1pHAY7dGrtPH8DRk", + "evmAddress": "0xD684d04A372f28c77F44D926BA7ec3A0d76bEfbD", + "substrateAddress": "5EMjsd15ABvrud7GTWN6RXQUGuQpne6UdJVC6DkwckEvAo3y", "version": "1.0.0", "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 6389118, - "deploymentTimestamp": 1739545159123, + "gitCommitHash": "3b84160f991b8d70ecb453779e76582e1897068a", + "deploymentBlock": 6389723, + "deploymentTimestamp": 1739549037657, "deployed": true }, "ParanetIncentivesPoolFactoryHelper": { From b50e0c96a58d3360d21ce0f04b88b50f483e590d Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 18 Feb 2025 15:20:43 +0100 Subject: [PATCH 112/153] Add tests and fixes --- contracts/paranets/Paranet.sol | 94 +- .../paranets/ParanetStagingRegistry.sol | 6 +- test/integration/Paranet.test.ts | 1043 ++++++++++++++++- 3 files changed, 1103 insertions(+), 40 deletions(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 2c8b81aa..78a63421 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -1059,13 +1059,14 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId) ); - if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist( - paranetKCStorageContract, - paranetKnowledgeCollectionTokenId, - paranetKnowledgeAssetTokenId - ); - } + _validateParanetAndKnowledgeCollection( + paranetId, + paranetKCStorageContract, + paranetKnowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId, + knowledgeCollectionStorageContract, + knowledgeCollectionTokenId + ); KnowledgeCollectionStorage kcs = KnowledgeCollectionStorage(knowledgeCollectionStorageContract); uint256 currentEpoch = chronos.getCurrentEpoch(); uint40 kcStartEpoch = kcs.getStartEpoch(knowledgeCollectionTokenId); @@ -1108,27 +1109,14 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId) ); - if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist( - paranetKCStorageContract, - paranetKnowledgeCollectionTokenId, - paranetKnowledgeAssetTokenId - ); - } - ParanetKnowledgeCollectionsRegistry pkcr = paranetKnowledgeCollectionsRegistry; - if ( - pkcr.isParanetKnowledgeCollection( - keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)) - ) - ) { - revert ParanetLib.KnowledgeCollectionIsAPartOfOtherParanet( - knowledgeCollectionStorageContract, - knowledgeCollectionTokenId, - pkcr.getParanetId( - keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)) - ) - ); - } + _validateParanetAndKnowledgeCollection( + paranetId, + paranetKCStorageContract, + paranetKnowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId, + knowledgeCollectionStorageContract, + knowledgeCollectionTokenId + ); if (pr.getMinersAccessPolicy(paranetId) == MINERS_ACCESS_POLICY_PERMISSIONED) { require(pr.isKnowledgeMinerRegistered(paranetId, msg.sender), "Knowledge miner is not registered"); @@ -1163,6 +1151,39 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { pss.stageKnowledgeCollection(paranetId, knowledgeCollectionId, msg.sender); } + function _validateParanetAndKnowledgeCollection( + bytes32 paranetId, + address paranetKCStorageContract, + uint256 paranetKnowledgeCollectionTokenId, + uint256 paranetKnowledgeAssetTokenId, + address knowledgeCollectionStorageContract, + uint256 knowledgeCollectionTokenId + ) internal view { + ParanetsRegistry pr = paranetsRegistry; + if (!pr.paranetExists(paranetId)) { + revert ParanetLib.ParanetDoesntExist( + paranetKCStorageContract, + paranetKnowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId + ); + } + + ParanetKnowledgeCollectionsRegistry pkcr = paranetKnowledgeCollectionsRegistry; + if ( + pkcr.isParanetKnowledgeCollection( + keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)) + ) + ) { + revert ParanetLib.KnowledgeCollectionIsAPartOfOtherParanet( + knowledgeCollectionStorageContract, + knowledgeCollectionTokenId, + pkcr.getParanetId( + keccak256(abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId)) + ) + ); + } + } + function addCurator( address paranetKCStorageContract, uint256 paranetKnowledgeCollectionTokenId, @@ -1243,14 +1264,15 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { bytes32 knowledgeCollectionId = keccak256( abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) ); - ParanetsRegistry pr = paranetsRegistry; - if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist( - paranetKCStorageContract, - paranetKnowledgeCollectionTokenId, - paranetKnowledgeAssetTokenId - ); - } + + _validateParanetAndKnowledgeCollection( + paranetId, + paranetKCStorageContract, + paranetKnowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId, + knowledgeCollectionStorageContract, + knowledgeCollectionTokenId + ); ParanetStagingRegistry pss = paranetStagingRegistry; require( diff --git a/contracts/storage/paranets/ParanetStagingRegistry.sol b/contracts/storage/paranets/ParanetStagingRegistry.sol index f28de7d9..174a666b 100644 --- a/contracts/storage/paranets/ParanetStagingRegistry.sol +++ b/contracts/storage/paranets/ParanetStagingRegistry.sol @@ -56,7 +56,7 @@ contract ParanetStagingRegistry is INamed, IVersioned, HubDependent { return _VERSION; } - function addCurator(bytes32 paranetId, address curator) public { + function addCurator(bytes32 paranetId, address curator) public onlyContracts { paranetCuratorIndexes[paranetId][curator] = paranetCurators[paranetId].length; paranetCurators[paranetId].push(curator); @@ -65,7 +65,7 @@ contract ParanetStagingRegistry is INamed, IVersioned, HubDependent { emit CuratorAdded(paranetId, curator); } - function removeCurator(bytes32 paranetId, address curator) public { + function removeCurator(bytes32 paranetId, address curator) public onlyContracts { uint256 index = paranetCuratorIndexes[paranetId][curator]; uint256 lastIndex = paranetCurators[paranetId].length - 1; @@ -118,7 +118,7 @@ contract ParanetStagingRegistry is INamed, IVersioned, HubDependent { bytes32 paranetId, bytes32 knowledgeCollectionId ) external view returns (bool) { - return stagedCollections[paranetId][knowledgeCollectionId] != ParanetLib.RequestStatus.NONE; + return stagedCollections[paranetId][knowledgeCollectionId] == ParanetLib.RequestStatus.PENDING; } function isKnowledgeCollectionApproved( diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index 85f0df78..0aec5bd3 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -19,9 +19,14 @@ import { EpochStorage, ParanetIncentivesPoolStorage, ParanetIncentivesPoolFactoryHelper, + ParanetStagingRegistry, } from '../../typechain'; import { ACCESS_POLICIES } from '../helpers/constants'; -import { createProfilesAndKC } from '../helpers/kc-helpers'; +import { + createProfilesAndKC, + getKCSignaturesData, + createKnowledgeCollection, +} from '../helpers/kc-helpers'; import { setupParanet } from '../helpers/paranet-helpers'; import { getDefaultPublishingNode, @@ -44,6 +49,7 @@ type ParanetFixture = { Profile: Profile; Token: Token; EpochStorage: EpochStorage; + ParanetStagingRegistry: ParanetStagingRegistry; }; describe('@unit Paranet', () => { @@ -60,6 +66,7 @@ describe('@unit Paranet', () => { let Profile: Profile; let Token: Token; let EpochStorage: EpochStorage; + let ParanetStagingRegistry: ParanetStagingRegistry; // Deploy all contracts, set the HubOwner and necessary accounts. Returns the ParanetFixture async function deployParanetFixture(): Promise { @@ -75,6 +82,7 @@ describe('@unit Paranet', () => { 'Profile', 'Token', 'EpochStorage', + 'ParanetStagingRegistry', ]); accounts = await hre.ethers.getSigners(); @@ -119,6 +127,10 @@ describe('@unit Paranet', () => { // log: true, // }); Token = await hre.ethers.getContract('Token'); + ParanetStagingRegistry = + await hre.ethers.getContract( + 'ParanetStagingRegistry', + ); return { accounts, @@ -134,6 +146,7 @@ describe('@unit Paranet', () => { Profile, Token, EpochStorage, + ParanetStagingRegistry, }; } @@ -152,6 +165,7 @@ describe('@unit Paranet', () => { KnowledgeCollectionStorage, Profile, Token, + ParanetStagingRegistry, } = await loadFixture(deployParanetFixture)); }); @@ -369,4 +383,1031 @@ describe('@unit Paranet', () => { expect(await incentivesPoolStorage.paranetId()).to.equal(paranetId); }); }); + + describe('Submit Knowledge Collection to Paranet', () => { + it('Should submit knowledge collection to paranet successfully', async () => { + // 1. Setup paranet first + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + // paranetOwner, + paranetId, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + // 3. Submit knowledge collection to paranet + await Paranet.connect(kcCreator).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ); + + // 4. Verify submission + // Check if KC is registered in paranet + const isRegistered = + await ParanetsRegistry.isKnowledgeCollectionRegistered( + paranetId, + ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256'], + [await KnowledgeCollectionStorage.getAddress(), collectionId], + ), + ), + ); + + expect(isRegistered).to.be.equal(true); + + // Check if KC is in miner's submitted collections + const submittedCollections = + await ParanetKnowledgeMinersRegistry.getSubmittedKnowledgeCollections( + kcCreator.address, + paranetId, + ); + expect(submittedCollections).to.include( + ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256'], + [await KnowledgeCollectionStorage.getAddress(), collectionId], + ), + ), + ); + + // Check miner's stats were updated + const minerMetadata = + await ParanetKnowledgeMinersRegistry.getKnowledgeMinerMetadata( + kcCreator.address, + ); + expect(minerMetadata.totalSubmittedKnowledgeCollectionsCount).to.equal(1); + + // Check if TRAC amounts were tracked correctly + const remainingTokenAmount = + await KnowledgeCollectionStorage.getTokenAmount(collectionId); + + // Check cumulative TRAC spent + const cumulativeTracSpent = + await ParanetKnowledgeMinersRegistry.getCumulativeTracSpent( + kcCreator.address, + paranetId, + ); + expect(cumulativeTracSpent).to.equal(remainingTokenAmount); + + // Check unrewarded TRAC spent + const unrewardedTracSpent = + await ParanetKnowledgeMinersRegistry.getUnrewardedTracSpent( + kcCreator.address, + paranetId, + ); + expect(unrewardedTracSpent).to.equal(remainingTokenAmount); + + // Check total TRAC spent + const totalTracSpent = + await ParanetKnowledgeMinersRegistry.getTotalTracSpent( + kcCreator.address, + ); + expect(totalTracSpent).to.equal(remainingTokenAmount); + + // Check paranet's cumulative knowledge value + const paranetMetadata = + await ParanetsRegistry.getParanetMetadata(paranetId); + expect(paranetMetadata.cumulativeKnowledgeValue).to.equal( + remainingTokenAmount, + ); + + const signaturesData2 = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId: collectionId2 } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData2, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // Verify event emission + await expect( + Paranet.connect(kcCreator).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId2, + ), + ) + .to.emit(Paranet, 'KnowledgeCollectionSubmittedToParanet') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId2, + ); + }); + + it('Should revert when non-owner tries to submit knowledge collection', async () => { + // 1. Setup paranet + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const nonOwner = accounts[10]; + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Create a knowledge collection + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // 3. Try to submit KC with non-owner account + await expect( + Paranet.connect(nonOwner).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ), + ).to.be.revertedWith("Caller isn't the owner of the KC"); + }); + + it('Should revert when registering the same knowledge collection twice', async () => { + // 1. Setup paranet + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Create a knowledge collection + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + await Paranet.connect(kcCreator).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ); + + // 4. Try to submit the same knowledge collection again + await expect( + Paranet.connect(kcCreator).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ), + ).to.be.revertedWithCustomError( + Paranet, + 'KnowledgeCollectionIsAPartOfOtherParanet', + ); + }); + + it('Should not allow submitting KC to second paranet after first', async () => { + // 1. Setup first paranet + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const firstParanet = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'First Paranet', + 'First Paranet Description', + ); + + // 2. Setup second paranet + + const signaturesData2 = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + + const { collectionId: secondParanetCollectionId } = + await createKnowledgeCollection( + kcCreator, + firstParanet.publishingNodeIdentityId, + firstParanet.receivingNodesIdentityIds, + signaturesData2, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + await Paranet.connect(kcCreator).registerParanet( + await KnowledgeCollectionStorage.getAddress(), + secondParanetCollectionId, + 1, + 'Second Paranet', + 'Second Paranet Description', + 0, + 0, + 0, + ); + + // 3. Create a knowledge collection + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + firstParanet.publishingNodeIdentityId, + firstParanet.receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // 4. Submit KC to first paranet + await Paranet.connect(kcCreator).submitKnowledgeCollection( + firstParanet.paranetKCStorageContract, + firstParanet.paranetKCTokenId, + firstParanet.paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ); + + // 5. Try to submit the same KC to second paranet + await expect( + Paranet.connect(kcCreator).submitKnowledgeCollection( + await KnowledgeCollectionStorage.getAddress(), + secondParanetCollectionId, + 1, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ), + ).to.be.revertedWithCustomError( + Paranet, + 'KnowledgeCollectionIsAPartOfOtherParanet', + ); + + // 6. Verify KC is only registered in first paranet + const knowledgeCollectionId = ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256'], + [await KnowledgeCollectionStorage.getAddress(), collectionId], + ), + ); + + const isRegisteredInFirstParanet = + await ParanetsRegistry.isKnowledgeCollectionRegistered( + firstParanet.paranetId, + knowledgeCollectionId, + ); + expect(isRegisteredInFirstParanet).to.be.equal(true); + + const secondParanetId = ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256', 'uint256'], + [ + await KnowledgeCollectionStorage.getAddress(), + secondParanetCollectionId, + 1, + ], + ), + ); + const isRegisteredInSecondParanet = + await ParanetsRegistry.isKnowledgeCollectionRegistered( + secondParanetId, + knowledgeCollectionId, + ); + expect(isRegisteredInSecondParanet).to.be.equal(false); + }); + }); + + describe('Paranet with Staged Knowledge Collections', () => { + const KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING = 1; + + it('Should create paranet with staging policy and add curator successfully', async () => { + // 1. Setup initial accounts + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + // 2. Create paranet with staging policy + const { + paranetOwner, + paranetId, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, + 0, + KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, + ); + + // 3. Add paranet owner as curator + await Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner.address, + ); + + // 4. Verify curator was added correctly + const isCurator = await ParanetStagingRegistry.isCurator( + paranetId, + paranetOwner.address, + ); + expect(isCurator).to.be.equal(true); + + // 5. Verify paranet metadata + const paranetMetadata = + await ParanetsRegistry.getParanetMetadata(paranetId); + expect(paranetMetadata.knowledgeCollectionsSubmissionPolicy).to.equal( + KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, + ); + + // 6. Get all curators and verify + const curators = + await ParanetStagingRegistry.getAllParanetCurators(paranetId); + expect(curators).to.have.lengthOf(1); + expect(curators[0]).to.equal(paranetOwner.address); + }); + + it('Should revert when non-owner tries to add curator', async () => { + // 1. Setup initial accounts + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const nonOwner = accounts[10]; + + // 2. Create paranet with staging policy + const { paranetKCStorageContract, paranetKCTokenId, paranetKATokenId } = + await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, + 0, + KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, + ); + + // 3. Try to add curator with non-owner account + await expect( + Paranet.connect(nonOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + nonOwner.address, + ), + ).to.be.revertedWith("Caller isn't the owner of the KA"); + }); + + it('Should submit KC to staging and have curator approve it', async () => { + // 1. Setup paranet with staging policy + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetOwner, + paranetId, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, + 0, + KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, + ); + + // 2. Add paranet owner as curator + await Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner.address, + ); + + // 4. Submit KC to paranet (goes to staging) + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + // 3. Submit knowledge collection to paranet + await Paranet.connect(kcCreator).stageKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ); + + // 5. Verify KC is in staging + const knowledgeCollectionId = ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256'], + [await KnowledgeCollectionStorage.getAddress(), collectionId], + ), + ); + + const stagedStatus = + await ParanetStagingRegistry.getKnowledgeCollectionStatus( + paranetId, + knowledgeCollectionId, + ); + expect(stagedStatus).to.equal(1); // PENDING + + const isStaged = await ParanetStagingRegistry.isKnowledgeCollectionStaged( + paranetId, + knowledgeCollectionId, + ); + expect(isStaged).to.be.equal(true); + + // 6. Have curator approve the KC + await Paranet.connect(paranetOwner).reviewKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetKCStorageContract, + collectionId, + true, // approve + ); + + // 7. Verify KC is now registered in paranet + const isRegistered = + await ParanetsRegistry.isKnowledgeCollectionRegistered( + paranetId, + knowledgeCollectionId, + ); + expect(isRegistered).to.be.equal(true); + + const stagedStatusAfterApproval = + await ParanetStagingRegistry.getKnowledgeCollectionStatus( + paranetId, + knowledgeCollectionId, + ); + expect(stagedStatusAfterApproval).to.equal(2); // APPROVED + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [pendingCollections, total] = + await ParanetStagingRegistry.getPendingCollections(paranetId, 0, 10); + expect(total).to.be.equal(0); + }); + + it('Should submit KC to staging and have curator reject it', async () => { + // 1. Setup paranet with staging policy + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetOwner, + paranetId, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, + 0, + KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, + ); + + // 2. Add paranet owner as curator + await Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner.address, + ); + + // 3. Create and submit KC to paranet staging + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + await Paranet.connect(kcCreator).stageKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ); + + // 4. Get knowledge collection ID + const knowledgeCollectionId = ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256'], + [await KnowledgeCollectionStorage.getAddress(), collectionId], + ), + ); + + // 5. Have curator reject the KC + await Paranet.connect(paranetOwner).reviewKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + false, // reject + ); + + // 6. Verify KC was rejected and not registered in paranet + const isRegistered = + await ParanetsRegistry.isKnowledgeCollectionRegistered( + paranetId, + knowledgeCollectionId, + ); + expect(isRegistered).to.be.equal(false); + + const stagedStatusAfterRejection = + await ParanetStagingRegistry.getKnowledgeCollectionStatus( + paranetId, + knowledgeCollectionId, + ); + expect(stagedStatusAfterRejection).to.equal(3); // REJECTED + + // 7. Verify KC is still staged but marked as rejected + const isStaged = await ParanetStagingRegistry.isKnowledgeCollectionStaged( + paranetId, + knowledgeCollectionId, + ); + expect(isStaged).to.be.equal(false); + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [pendingCollectionsAfterRejection, totalAfterRejection] = + await ParanetStagingRegistry.getPendingCollections(paranetId, 0, 10); + expect(totalAfterRejection).to.be.equal(0); + }); + + it('Should allow resubmission of previously rejected Knowledge Collection', async () => { + // 1. Setup paranet with staging policy + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetOwner, + paranetId, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, + 0, + KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, + ); + + // 2. Add paranet owner as curator + await Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner.address, + ); + + // 3. Create and submit KC to paranet staging + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // 4. First submission - Stage the Knowledge Collection + await Paranet.connect(kcCreator).stageKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ); + + const knowledgeCollectionId = ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256'], + [await KnowledgeCollectionStorage.getAddress(), collectionId], + ), + ); + + // 5. Verify it's in pending state + let [pendingCollections, total] = + await ParanetStagingRegistry.getPendingCollections(paranetId, 0, 10); + expect(total).to.equal(1); + expect(pendingCollections[0].knowledgeCollectionId).to.equal( + knowledgeCollectionId, + ); + expect(pendingCollections[0].status).to.equal(1); // PENDING + + // 6. Have curator reject the KC + await Paranet.connect(paranetOwner).reviewKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + false, // reject + ); + + // 7. Verify rejection status (???) + let status = await ParanetStagingRegistry.getKnowledgeCollectionStatus( + paranetId, + knowledgeCollectionId, + ); + expect(status).to.equal(3); // REJECTED + + [pendingCollections, total] = + await ParanetStagingRegistry.getPendingCollections(paranetId, 0, 10); + expect(total).to.equal(0); + expect(pendingCollections).to.have.lengthOf(0); + + // 8. Resubmit the Knowledge Collection + await Paranet.connect(kcCreator).stageKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ); + + // 9. Verify it's back in pending state + [pendingCollections, total] = + await ParanetStagingRegistry.getPendingCollections(paranetId, 0, 10); + expect(total).to.equal(1); + expect(pendingCollections[0].knowledgeCollectionId).to.equal( + knowledgeCollectionId, + ); + expect(pendingCollections[0].status).to.equal(1); // PENDING + + // 10. Have curator approve the KC this time + await Paranet.connect(paranetOwner).reviewKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + true, // approve + ); + + // 11. Verify final approval status + status = await ParanetStagingRegistry.getKnowledgeCollectionStatus( + paranetId, + knowledgeCollectionId, + ); + expect(status).to.equal(2); // APPROVED + + // 12. Verify KC is now registered in paranet + const isRegistered = + await ParanetsRegistry.isKnowledgeCollectionRegistered( + paranetId, + knowledgeCollectionId, + ); + expect(isRegistered).to.be.equal(true); + + // 13. Verify no more pending collections + [pendingCollections, total] = + await ParanetStagingRegistry.getPendingCollections(paranetId, 0, 10); + expect(total).to.equal(0); + expect(pendingCollections).to.have.lengthOf(0); + }); + }); + + describe('Paranet Curator Management', () => { + it('Should add and remove a single curator', async () => { + // Setup paranet + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const curator = accounts[10]; + + const { + paranetOwner, + paranetId, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, + 0, + 1, // STAGING policy + ); + + // Add curator + await Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator.address, + ); + + // Verify curator was added + expect( + await ParanetStagingRegistry.isCurator(paranetId, curator.address), + ).to.be.equal(true); + let curators = + await ParanetStagingRegistry.getAllParanetCurators(paranetId); + expect(curators).to.have.lengthOf(1); + expect(curators[0]).to.equal(curator.address); + + // Remove curator + await Paranet.connect(paranetOwner).removeCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator.address, + ); + + // Verify curator was removed + expect( + await ParanetStagingRegistry.isCurator(paranetId, curator.address), + ).to.be.equal(false); + curators = await ParanetStagingRegistry.getAllParanetCurators(paranetId); + expect(curators).to.have.lengthOf(0); + }); + + it('Should handle multiple curators and removal of middle curator', async () => { + // Setup paranet + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const curator1 = accounts[10]; + const curator2 = accounts[11]; + const curator3 = accounts[12]; + + const { + paranetOwner, + paranetId, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, + 0, + 1, // STAGING policy + ); + + // Add three curators + await Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator1.address, + ); + await Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator2.address, + ); + await Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator3.address, + ); + + // Verify all curators were added + let curators = + await ParanetStagingRegistry.getAllParanetCurators(paranetId); + expect(curators).to.have.lengthOf(3); + expect(curators).to.include(curator1.address); + expect(curators).to.include(curator2.address); + expect(curators).to.include(curator3.address); + + // Remove middle curator + await Paranet.connect(paranetOwner).removeCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator2.address, + ); + + // Verify correct curator was removed and others remain + expect( + await ParanetStagingRegistry.isCurator(paranetId, curator1.address), + ).to.be.equal(true); + expect( + await ParanetStagingRegistry.isCurator(paranetId, curator2.address), + ).to.be.equal(false); + expect( + await ParanetStagingRegistry.isCurator(paranetId, curator3.address), + ).to.be.equal(true); + + curators = await ParanetStagingRegistry.getAllParanetCurators(paranetId); + expect(curators).to.have.lengthOf(2); + expect(curators).to.include(curator1.address); + expect(curators).to.include(curator3.address); + expect(curators).to.not.include(curator2.address); + }); + }); }); From 91f8e740f2bfd43e11d351fdfb06fc968acf6701 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 18 Feb 2025 15:31:56 +0100 Subject: [PATCH 113/153] Should not allow approving a rejected knowledge collection test --- test/integration/Paranet.test.ts | 110 +++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index 0aec5bd3..78016243 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -1256,6 +1256,116 @@ describe('@unit Paranet', () => { expect(total).to.equal(0); expect(pendingCollections).to.have.lengthOf(0); }); + + it('Should not allow approving a rejected knowledge collection', async () => { + // 1. Setup paranet with staging policy + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetOwner, + paranetId, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, + 0, + 1, // STAGING policy + ); + + // 2. Add paranet owner as curator + await Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner.address, + ); + + // 3. Create and submit KC to paranet staging + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // 4. Stage the Knowledge Collection + await Paranet.connect(kcCreator).stageKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ); + + const knowledgeCollectionId = ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256'], + [await KnowledgeCollectionStorage.getAddress(), collectionId], + ), + ); + + // 5. Reject the KC + await Paranet.connect(paranetOwner).reviewKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + false, // reject + ); + + // 6. Verify rejection status + let status = await ParanetStagingRegistry.getKnowledgeCollectionStatus( + paranetId, + knowledgeCollectionId, + ); + expect(status).to.equal(3); // REJECTED + + // 7. Try to approve the rejected KC (should fail) + await expect( + Paranet.connect(paranetOwner).reviewKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + true, // try to approve + ), + ).to.be.revertedWith('Knowledge collection is not staged'); + + // 8. Verify status remains rejected + status = await ParanetStagingRegistry.getKnowledgeCollectionStatus( + paranetId, + knowledgeCollectionId, + ); + expect(status).to.equal(3); // Still REJECTED + }); }); describe('Paranet Curator Management', () => { From d8f201f424126db248ae201568526794f9e0799e Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 18 Feb 2025 16:57:43 +0100 Subject: [PATCH 114/153] Add fixes and tests --- contracts/paranets/Paranet.sol | 75 ++-- test/integration/Paranet.test.ts | 602 ++++++++++++++++++++++++++++++- 2 files changed, 651 insertions(+), 26 deletions(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 78a63421..74e01e0f 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -229,7 +229,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); + bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); if (pr.paranetExists(paranetId)) { revert ParanetLib.ParanetHasAlreadyBeenRegistered( @@ -272,7 +272,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); + bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); if (!pr.paranetExists(paranetId)) { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); @@ -299,7 +299,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ParanetsRegistry pr = paranetsRegistry; ProfileStorage ps = profileStorage; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); + bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); if (!pr.paranetExists(paranetId)) { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); @@ -343,7 +343,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); + bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); if (!pr.paranetExists(paranetId)) { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); @@ -386,7 +386,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ) external { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); + bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); if (!pr.paranetExists(paranetId)) { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); @@ -442,7 +442,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); + bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); if (!pr.paranetExists(paranetId)) { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); @@ -500,7 +500,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); + bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); if (!pr.paranetExists(paranetId)) { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); @@ -557,7 +557,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ParanetsRegistry pr = paranetsRegistry; ParanetServicesRegistry psr = paranetServicesRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); + bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); if (!pr.paranetExists(paranetId)) { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); @@ -732,7 +732,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ParanetsRegistry pr = paranetsRegistry; ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); + bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); if (!pr.paranetExists(paranetId)) { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); @@ -780,7 +780,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); + bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); if (!pr.paranetExists(paranetId)) { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); @@ -823,7 +823,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ) external { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); + bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); if (!pr.paranetExists(paranetId)) { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); @@ -872,7 +872,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); + bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); if (!pr.paranetExists(paranetId)) { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); @@ -929,7 +929,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); + bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); if (!pr.paranetExists(paranetId)) { revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); @@ -1055,8 +1055,10 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 knowledgeCollectionTokenId ) external onlyKnowledgeCollectionOwner(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256( - abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId) + bytes32 paranetId = _getParanetId( + paranetKCStorageContract, + paranetKnowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId ); _validateParanetAndKnowledgeCollection( @@ -1105,8 +1107,10 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ) external onlyKnowledgeCollectionOwner(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) { ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = keccak256( - abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId) + bytes32 paranetId = _getParanetId( + paranetKCStorageContract, + paranetKnowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId ); _validateParanetAndKnowledgeCollection( @@ -1197,9 +1201,12 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { paranetKnowledgeAssetTokenId ) { - bytes32 paranetId = keccak256( - abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId) + bytes32 paranetId = _getParanetId( + paranetKCStorageContract, + paranetKnowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId ); + ParanetsRegistry pr = paranetsRegistry; if (!pr.paranetExists(paranetId)) { revert ParanetLib.ParanetDoesntExist( @@ -1214,7 +1221,10 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { knowledgeCollectionsSubmissionPolicy == KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, "Paranet does not allow adding curators" ); - paranetStagingRegistry.addCurator(paranetId, curator); + ParanetStagingRegistry pss = paranetStagingRegistry; + require(!pss.isCurator(paranetId, curator), "Existing curator"); + + pss.addCurator(paranetId, curator); } function removeCurator( @@ -1230,8 +1240,10 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { paranetKnowledgeAssetTokenId ) { - bytes32 paranetId = keccak256( - abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId) + bytes32 paranetId = _getParanetId( + paranetKCStorageContract, + paranetKnowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId ); ParanetsRegistry pr = paranetsRegistry; if (!pr.paranetExists(paranetId)) { @@ -1247,7 +1259,10 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { knowledgeCollectionsSubmissionPolicy == KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, "Paranet does not allow adding curators" ); - paranetStagingRegistry.removeCurator(paranetId, curator); + + ParanetStagingRegistry pss = paranetStagingRegistry; + require(pss.isCurator(paranetId, curator), "Address is not a curator"); + pss.removeCurator(paranetId, curator); } function reviewKnowledgeCollection( @@ -1258,8 +1273,10 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint256 knowledgeCollectionTokenId, bool accepted ) external onlyCurator(paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId) { - bytes32 paranetId = keccak256( - abi.encodePacked(paranetKCStorageContract, paranetKnowledgeCollectionTokenId, paranetKnowledgeAssetTokenId) + bytes32 paranetId = _getParanetId( + paranetKCStorageContract, + paranetKnowledgeCollectionTokenId, + paranetKnowledgeAssetTokenId ); bytes32 knowledgeCollectionId = keccak256( abi.encodePacked(knowledgeCollectionStorageContract, knowledgeCollectionTokenId) @@ -1400,6 +1417,14 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); } + function _getParanetId( + address paranetKCStorageContract, + uint256 paranetKCTokenId, + uint256 paranetKATokenId + ) internal pure returns (bytes32) { + return keccak256(abi.encodePacked(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId)); + } + // function _processUpdatedKnowledgeCollectionStatesMetadata( // bytes32 paranetId, // ParanetLib.UpdatingKnowledgeCollectionState[] memory updatingKnowledgeCollectionStates diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index 78016243..f1aa87a3 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -301,6 +301,82 @@ describe('@unit Paranet', () => { ), ).to.be.revertedWith("Caller isn't the owner of the KA"); }); + + it('Should revert when registering paranet with invalid access policy values', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const paranetKCStorageContract = + await KnowledgeCollectionStorage.getAddress(); + + // Create profiles and KC first + const { collectionId } = await createProfilesAndKC( + kcCreator, + publishingNode, + receivingNodes, + { + Profile, + KnowledgeCollection, + Token, + }, + ); + + // Try with invalid nodes access policy (2) + await expect( + Paranet.connect(kcCreator).registerParanet( + paranetKCStorageContract, + collectionId, + 1, // kaTokenId + 'Test Paranet', + 'Test Description', + 2, // invalid nodes access policy + 0, // valid miners access policy + 0, // valid submission policy + ), + ).to.be.revertedWith('Invalid policy'); + + // Try with invalid miners access policy (3) + await expect( + Paranet.connect(kcCreator).registerParanet( + paranetKCStorageContract, + collectionId, + 1, // kaTokenId + 'Test Paranet', + 'Test Description', + 0, // valid nodes access policy + 3, // invalid miners access policy + 0, // valid submission policy + ), + ).to.be.revertedWith('Invalid access policy'); + + // Try with invalid submission policy (2) + await expect( + Paranet.connect(kcCreator).registerParanet( + paranetKCStorageContract, + collectionId, + 1, // kaTokenId + 'Test Paranet', + 'Test Description', + 0, // valid nodes access policy + 0, // valid miners access policy + 2, // invalid submission policy + ), + ).to.be.revertedWith('Invalid access policy'); + + // Try with all invalid policies + await expect( + Paranet.connect(kcCreator).registerParanet( + paranetKCStorageContract, + collectionId, + 1, // kaTokenId + 'Test Paranet', + 'Test Description', + 2, // invalid nodes access policy + 3, // invalid miners access policy + 2, // invalid submission policy + ), + ).to.be.revertedWith('Invalid access policy'); + }); }); describe('Paranet Incentives Pool', () => { @@ -1345,7 +1421,7 @@ describe('@unit Paranet', () => { paranetId, knowledgeCollectionId, ); - expect(status).to.equal(3); // REJECTED + expect(status).to.equal(3); // Still REJECTED // 7. Try to approve the rejected KC (should fail) await expect( @@ -1366,6 +1442,173 @@ describe('@unit Paranet', () => { ); expect(status).to.equal(3); // Still REJECTED }); + + it('Should revert when non-curator tries to review collection', async () => { + // 1. Setup paranet with staging policy + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const curator = accounts[10]; + const nonCurator = accounts[11]; + + const { + paranetOwner, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, + 0, + 1, // STAGING policy + ); + + // 2. Add curator + await Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator.address, + ); + + // 3. Create and submit KC to paranet staging + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + await Paranet.connect(kcCreator).stageKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ); + + // 4. Try to review with non-curator account + await expect( + Paranet.connect(nonCurator).reviewKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + true, // approve + ), + ).to.be.revertedWith('Not authorized curator'); + }); + + it('Should revert when reviewing already reviewed collection', async () => { + // 1. Setup paranet with staging policy + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const curator = accounts[10]; + + const { + paranetOwner, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, + 0, + 1, // STAGING policy + ); + + // 2. Add curator + await Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator.address, + ); + + // 3. Create and submit KC to paranet staging + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + await Paranet.connect(kcCreator).stageKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ); + + // 4. First review (approve) + await Paranet.connect(curator).reviewKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + false, // rejected + ); + + // 5. Try to review again + await expect( + Paranet.connect(curator).reviewKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + true, // approve + ), + ).to.be.revertedWith('Knowledge collection is not staged'); + }); }); describe('Paranet Curator Management', () => { @@ -1519,5 +1762,362 @@ describe('@unit Paranet', () => { expect(curators).to.include(curator3.address); expect(curators).to.not.include(curator2.address); }); + + it('Should revert when adding curator to non-staging paranet', async () => { + // Setup paranet with OPEN submission policy (0) + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const curator = accounts[10]; + + const { + paranetOwner, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, // nodesAccessPolicy + 0, // minersAccessPolicy + 0, // OPEN submission policy + ); + + // Attempt to add curator - should fail + await expect( + Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator.address, + ), + ).to.be.revertedWith('Paranet does not allow adding curators'); + }); + + it('Should revert when adding same curator twice', async () => { + // Setup paranet with staging policy + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const curator = accounts[10]; + + const { + paranetOwner, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, // nodesAccessPolicy + 0, // minersAccessPolicy + 1, // STAGING policy + ); + + // Add curator first time + await Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator.address, + ); + + // Try to add same curator again - should fail + await expect( + Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator.address, + ), + ).to.be.revertedWith('Existing curator'); + }); + + it('Should revert when removing non-existent curator', async () => { + // Setup paranet with staging policy + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const nonExistentCurator = accounts[10]; + + const { + paranetOwner, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, // nodesAccessPolicy + 0, // minersAccessPolicy + 1, // STAGING policy + ); + + // Try to remove curator that was never added - should fail + await expect( + Paranet.connect(paranetOwner).removeCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + nonExistentCurator.address, + ), + ).to.be.revertedWith('Address is not a curator'); + }); + }); + + describe('Paranet Service Registration', () => { + it('Should register a paranet service successfully', async () => { + // 1. Setup initial paranet + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetOwner, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetId, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Create a new knowledge collection for the service + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId: serviceCollectionId } = + await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // 3. Setup service parameters + const serviceName = 'Test Service'; + const serviceDescription = 'Test Service Description'; + const serviceAddresses = [accounts[10].address, accounts[11].address]; + + // 4. Register the service + const tx = await Paranet.connect(paranetOwner).registerParanetService( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, // serviceKATokenId + serviceName, + serviceDescription, + serviceAddresses, + ); + + // 5. Verify service registration + const serviceId = ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256', 'uint256'], + [ + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, + ], + ), + ); + + // Check if service exists + const serviceExists = + await ParanetServicesRegistry.paranetServiceExists(serviceId); + expect(serviceExists).to.be.equal(true); + + // Verify service metadata + const serviceMetadata = + await ParanetServicesRegistry.getParanetServiceMetadata(serviceId); + expect(serviceMetadata.name).to.equal(serviceName); + expect(serviceMetadata.description).to.equal(serviceDescription); + expect(serviceMetadata.paranetServiceAddresses).to.deep.equal( + serviceAddresses, + ); + expect(serviceMetadata.paranetServiceKCStorageContract).to.equal( + await KnowledgeCollectionStorage.getAddress(), + ); + expect(serviceMetadata.paranetServiceKCTokenId).to.equal( + serviceCollectionId, + ); + expect(serviceMetadata.paranetServiceKATokenId).to.equal(1); + + // Verify service addresses + const registeredAddresses = + await ParanetServicesRegistry.getParanetServiceAddresses(serviceId); + expect(registeredAddresses).to.deep.equal(serviceAddresses); + + // Verify individual service addresses are registered + for (const addr of serviceAddresses) { + const isRegistered = + await ParanetServicesRegistry.isParanetServiceAddressRegistered( + serviceId, + addr, + ); + expect(isRegistered).to.be.equal(true); + } + + // 6. Verify event emission + await expect(tx) + .to.emit(Paranet, 'ParanetServiceRegistered') + .withArgs( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, + serviceName, + serviceDescription, + serviceAddresses, + ); + + // 7. Add paranet service to paranet + const addServiceTx = await Paranet.connect( + paranetOwner, + ).addParanetServices( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + [ + { + knowledgeCollectionStorageContract: + await KnowledgeCollectionStorage.getAddress(), + knowledgeCollectionTokenId: serviceCollectionId, + knowledgeAssetTokenId: 1, + }, + ], + ); + + // Verify service is implemented in paranet + const isImplemented = await ParanetsRegistry.isServiceImplemented( + paranetId, + serviceId, + ); + expect(isImplemented).to.be.equal(true); + + // Verify paranet services list + const paranetServices = await ParanetsRegistry.getServices(paranetId); + expect(paranetServices).to.include(serviceId); + expect(paranetServices).to.have.lengthOf(1); + + // Verify ParanetServiceAdded event + await expect(addServiceTx) + .to.emit(Paranet, 'ParanetServiceAdded') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, + ); + }); + + it('Should revert when trying to register the same paranet service twice', async () => { + // 1. Setup initial paranet + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetOwner, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Create a new knowledge collection for the service + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId: serviceCollectionId } = + await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // 3. Setup service parameters + const serviceName = 'Test Service'; + const serviceDescription = 'Test Service Description'; + const serviceAddresses = [accounts[10].address, accounts[11].address]; + + // 4. Register the service first time + await Paranet.connect(paranetOwner).registerParanetService( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, // serviceKATokenId + serviceName, + serviceDescription, + serviceAddresses, + ); + + // 5. Attempt to register the same service again + await expect( + Paranet.connect(paranetOwner).registerParanetService( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, // serviceKATokenId + serviceName, + serviceDescription, + serviceAddresses, + ), + ).to.be.revertedWithCustomError( + Paranet, + 'ParanetServiceHasAlreadyBeenRegistered', + ); + }); }); }); From b45f5d25e87fdd6a914d7d53d154ec1da627c116 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Tue, 18 Feb 2025 16:58:08 +0100 Subject: [PATCH 115/153] Add fixes and tests --- test/integration/Paranet.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index f1aa87a3..360c06b8 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -347,7 +347,7 @@ describe('@unit Paranet', () => { 3, // invalid miners access policy 0, // valid submission policy ), - ).to.be.revertedWith('Invalid access policy'); + ).to.be.revertedWith('Invalid policy'); // Try with invalid submission policy (2) await expect( @@ -361,7 +361,7 @@ describe('@unit Paranet', () => { 0, // valid miners access policy 2, // invalid submission policy ), - ).to.be.revertedWith('Invalid access policy'); + ).to.be.revertedWith('Invalid policy'); // Try with all invalid policies await expect( @@ -375,7 +375,7 @@ describe('@unit Paranet', () => { 3, // invalid miners access policy 2, // invalid submission policy ), - ).to.be.revertedWith('Invalid access policy'); + ).to.be.revertedWith('Invalid policy'); }); }); From 9d480b5c2f1a8da197d0e2a4034b94b854390717 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 19 Feb 2025 11:22:06 +0100 Subject: [PATCH 116/153] Add IERC20Extended interface --- contracts/interfaces/IERC20Extended.sol | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 contracts/interfaces/IERC20Extended.sol diff --git a/contracts/interfaces/IERC20Extended.sol b/contracts/interfaces/IERC20Extended.sol new file mode 100644 index 00000000..7eeb5ee3 --- /dev/null +++ b/contracts/interfaces/IERC20Extended.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.20; + +interface IERC20Extended { + function decimals() external view returns (uint8); +} From f621960d96a804cd37d34a00f17cf219a6eaa6cf Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 19 Feb 2025 11:32:20 +0100 Subject: [PATCH 117/153] Add new contract abi --- abi/IERC20Extended.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 abi/IERC20Extended.json diff --git a/abi/IERC20Extended.json b/abi/IERC20Extended.json new file mode 100644 index 00000000..5e361ebf --- /dev/null +++ b/abi/IERC20Extended.json @@ -0,0 +1,15 @@ +[ + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + } +] From 16b908555fcf5a7420e49d284bb09ae82db5a312 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 19 Feb 2025 12:33:00 +0100 Subject: [PATCH 118/153] Tests and fixes --- contracts/paranets/Paranet.sol | 7 +- test/integration/Paranet.test.ts | 1062 +++++++++++++++++++++++++++++- 2 files changed, 1063 insertions(+), 6 deletions(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 74e01e0f..426cf1e9 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -1318,11 +1318,8 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ParanetsRegistry pr = paranetsRegistry; uint8 minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); // Check if paranet is curated and if knowledge miner is whitelisted - if ( - minersAccessPolicy == MINERS_ACCESS_POLICY_PERMISSIONED && - !pr.isKnowledgeMinerRegistered(paranetId, msg.sender) - ) { - revert ParanetLib.ParanetCuratedMinerDoesntExist(paranetId, msg.sender); + if (minersAccessPolicy == MINERS_ACCESS_POLICY_PERMISSIONED) { + require(pr.isKnowledgeMinerRegistered(paranetId, msg.sender), "Miner is not registered"); // Should this be done in both cases why would OPEN have separeted logic ??? } else if (minersAccessPolicy == MINERS_ACCESS_POLICY_OPEN) { // Check if Knowledge Miner has profile diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index 360c06b8..d5549d9c 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -1,3 +1,5 @@ +import { randomBytes } from 'crypto'; + import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { expect } from 'chai'; @@ -20,6 +22,7 @@ import { ParanetIncentivesPoolStorage, ParanetIncentivesPoolFactoryHelper, ParanetStagingRegistry, + IdentityStorage, } from '../../typechain'; import { ACCESS_POLICIES } from '../helpers/constants'; import { @@ -50,6 +53,7 @@ type ParanetFixture = { Token: Token; EpochStorage: EpochStorage; ParanetStagingRegistry: ParanetStagingRegistry; + IdentityStorage: IdentityStorage; }; describe('@unit Paranet', () => { @@ -67,7 +71,7 @@ describe('@unit Paranet', () => { let Token: Token; let EpochStorage: EpochStorage; let ParanetStagingRegistry: ParanetStagingRegistry; - + let IdentityStorage: IdentityStorage; // Deploy all contracts, set the HubOwner and necessary accounts. Returns the ParanetFixture async function deployParanetFixture(): Promise { await hre.deployments.fixture([ @@ -83,6 +87,7 @@ describe('@unit Paranet', () => { 'Token', 'EpochStorage', 'ParanetStagingRegistry', + 'IdentityStorage', ]); accounts = await hre.ethers.getSigners(); @@ -131,6 +136,8 @@ describe('@unit Paranet', () => { await hre.ethers.getContract( 'ParanetStagingRegistry', ); + IdentityStorage = + await hre.ethers.getContract('IdentityStorage'); return { accounts, @@ -147,6 +154,7 @@ describe('@unit Paranet', () => { Token, EpochStorage, ParanetStagingRegistry, + IdentityStorage, }; } @@ -2120,4 +2128,1056 @@ describe('@unit Paranet', () => { ); }); }); + + describe('Paranet Permissioned Miners', () => { + it('Should allow owner to add and remove curated miners', async () => { + // Setup paranet with permissioned miners policy + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const miner1 = accounts[10]; + const miner2 = accounts[11]; + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetId, // Add this to destructuring + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + ACCESS_POLICIES.OPEN, // nodes policy + 1, // miners policy + ACCESS_POLICIES.OPEN, // submission policy + ); + + // Verify initial state + expect( + await ParanetsRegistry.getKnowledgeMinersCount(paranetId), + ).to.equal(0); + expect( + await ParanetsRegistry.isKnowledgeMinerRegistered( + paranetId, + miner1.address, + ), + ).to.be.equal(false); + expect( + await ParanetsRegistry.isKnowledgeMinerRegistered( + paranetId, + miner2.address, + ), + ).to.be.equal(false); + + // Add miners + await expect( + Paranet.connect(kcCreator).addParanetCuratedMiners( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + [miner1.address, miner2.address], + ), + ) + .to.emit(Paranet, 'ParanetCuratedMinerAdded') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + miner1.address, + ) + .to.emit(Paranet, 'ParanetCuratedMinerAdded') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + miner2.address, + ); + + // Verify miners were added + expect( + await ParanetsRegistry.getKnowledgeMinersCount(paranetId), + ).to.equal(2); + expect( + await ParanetsRegistry.isKnowledgeMinerRegistered( + paranetId, + miner1.address, + ), + ).to.be.equal(true); + expect( + await ParanetsRegistry.isKnowledgeMinerRegistered( + paranetId, + miner2.address, + ), + ).to.be.equal(true); + + const registeredMiners = + await ParanetsRegistry.getKnowledgeMiners(paranetId); + expect(registeredMiners[0]).to.be.equal(miner1.address); + expect(registeredMiners[1]).to.be.equal(miner2.address); + + // Remove miners + await expect( + Paranet.connect(kcCreator).removeParanetCuratedMiners( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + [miner1.address], + ), + ) + .to.emit(Paranet, 'ParanetCuratedMinerRemoved') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + miner1.address, + ); + + // Verify miner1 was removed but miner2 remains + expect( + await ParanetsRegistry.getKnowledgeMinersCount(paranetId), + ).to.equal(1); + expect( + await ParanetsRegistry.isKnowledgeMinerRegistered( + paranetId, + miner1.address, + ), + ).to.be.equal(false); + expect( + await ParanetsRegistry.isKnowledgeMinerRegistered( + paranetId, + miner2.address, + ), + ).to.be.equal(true); + + const remainingMiners = + await ParanetsRegistry.getKnowledgeMiners(paranetId); + expect(remainingMiners).to.have.lengthOf(1); + expect(remainingMiners[0]).to.equal(miner2.address); + }); + + it('Should handle miner access requests correctly', async () => { + // Setup paranet with permissioned miners policy + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const miner = accounts[10]; + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetId, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + ACCESS_POLICIES.OPEN, // nodes policy + 1, // miners policy + ACCESS_POLICIES.OPEN, // submission policy + ); + + // Request access + await expect( + Paranet.connect(miner).requestParanetCuratedMinerAccess( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ), + ) + .to.emit(Paranet, 'ParanetCuratedMinerAccessRequestCreated') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + miner.address, + ); + + // Verify request state + const latestRequest = + await ParanetsRegistry.getLatestKnowledgeMinerAccessRequest( + paranetId, + miner.address, + ); + expect(latestRequest.miner).to.equal(miner.address); + expect(latestRequest.status).to.equal(1); // PENDING status + expect(latestRequest.createdAt).to.be.gt(0); + expect(latestRequest.updatedAt).to.equal(latestRequest.createdAt); + + // Approve request + await expect( + Paranet.connect(kcCreator).approveCuratedMiner( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + miner.address, + ), + ) + .to.emit(Paranet, 'ParanetCuratedMinerAccessRequestAccepted') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + miner.address, + ) + .to.emit(Paranet, 'ParanetCuratedMinerAdded') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + miner.address, + ); + + // Verify request state after approval + const updatedRequest = + await ParanetsRegistry.getLatestKnowledgeMinerAccessRequest( + paranetId, + miner.address, + ); + expect(updatedRequest.miner).to.equal(miner.address); + expect(updatedRequest.status).to.equal(2); // ACCEPTED status + expect(updatedRequest.createdAt).to.equal(latestRequest.createdAt); + expect(updatedRequest.updatedAt).to.be.gt(latestRequest.updatedAt); + + // Verify miner is now registered + expect( + await ParanetsRegistry.isKnowledgeMinerRegistered( + paranetId, + miner.address, + ), + ).to.be.equal(true); + }); + + it('Should handle miner access request rejection', async () => { + // Setup paranet with permissioned miners policy + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const miner = accounts[10]; + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetId, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + ACCESS_POLICIES.OPEN, // nodes policy + 1, // miners policy + ACCESS_POLICIES.OPEN, // submission policy + ); + + // Request access + await Paranet.connect(miner).requestParanetCuratedMinerAccess( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ); + + // Verify initial request state + const latestRequest = + await ParanetsRegistry.getLatestKnowledgeMinerAccessRequest( + paranetId, + miner.address, + ); + expect(latestRequest.miner).to.equal(miner.address); + expect(latestRequest.status).to.equal(1); // PENDING status + expect(latestRequest.createdAt).to.be.gt(0); + expect(latestRequest.updatedAt).to.equal(latestRequest.createdAt); + + // Reject request + await expect( + Paranet.connect(kcCreator).rejectCuratedMiner( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + miner.address, + ), + ) + .to.emit(Paranet, 'ParanetCuratedMinerAccessRequestRejected') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + miner.address, + ); + + // Verify request state after rejection + const updatedRequest = + await ParanetsRegistry.getLatestKnowledgeMinerAccessRequest( + paranetId, + miner.address, + ); + expect(updatedRequest.miner).to.equal(miner.address); + expect(updatedRequest.status).to.equal(3); // REJECTED status + expect(updatedRequest.createdAt).to.equal(latestRequest.createdAt); + expect(updatedRequest.updatedAt).to.be.gt(latestRequest.updatedAt); + + // Verify miner is not registered + expect( + await ParanetsRegistry.isKnowledgeMinerRegistered( + paranetId, + miner.address, + ), + ).to.be.equal(false); + }); + + it('Should revert when non-owner tries to add/remove miners', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const miner = accounts[10]; + const nonOwner = accounts[11]; + + const { paranetKCStorageContract, paranetKCTokenId, paranetKATokenId } = + await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + ACCESS_POLICIES.OPEN, + 1, + ACCESS_POLICIES.OPEN, + ); + + // Try to add miner as non-owner + await expect( + Paranet.connect(nonOwner).addParanetCuratedMiners( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + [miner.address], + ), + ).to.be.revertedWith("Caller isn't the owner of the KA"); + + // Try to remove miner as non-owner + await expect( + Paranet.connect(nonOwner).removeParanetCuratedMiners( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + [miner.address], + ), + ).to.be.revertedWith("Caller isn't the owner of the KA"); + }); + + it('Should revert when requesting access multiple times', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const miner = accounts[10]; + + const { paranetKCStorageContract, paranetKCTokenId, paranetKATokenId } = + await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + ACCESS_POLICIES.OPEN, + 1, + ACCESS_POLICIES.OPEN, + ); + + // First request + await Paranet.connect(miner).requestParanetCuratedMinerAccess( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ); + + // Try to request again while first request is pending + await expect( + Paranet.connect(miner).requestParanetCuratedMinerAccess( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ), + ).to.be.revertedWithCustomError( + Paranet, + 'ParanetCuratedMinerAccessRequestInvalidStatus', + ); + }); + + it('Should allow registered miner to submit KC but reject unregistered miner', async () => { + // Setup paranet with permissioned miners policy + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const miner1 = accounts[10]; + const miner2 = accounts[11]; + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetId, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + ACCESS_POLICIES.OPEN, // nodes policy + 1, // miners policy - PERMISSIONED + ACCESS_POLICIES.OPEN, // submission policy + ); + + // Add miner1 as a curated miner + await Paranet.connect(kcCreator).addParanetCuratedMiners( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + [miner1.address], + ); + + // Create KC for miner1 + const signaturesData1 = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId: miner1CollectionId } = + await createKnowledgeCollection( + miner1, // Using miner1 as KC creator + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData1, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // Create KC for miner2 + const signaturesData2 = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId: miner2CollectionId } = + await createKnowledgeCollection( + miner2, // Using miner2 as KC creator + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData2, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // Miner1 (registered) submits KC - should succeed + await expect( + Paranet.connect(miner1).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + miner1CollectionId, + ), + ) + .to.emit(Paranet, 'KnowledgeCollectionSubmittedToParanet') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + miner1CollectionId, + ); + + // Verify miner1's KC was added + const miner1CollectionBytes = ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256'], + [await KnowledgeCollectionStorage.getAddress(), miner1CollectionId], + ), + ); + + expect( + await ParanetsRegistry.isKnowledgeCollectionRegistered( + paranetId, + miner1CollectionBytes, + ), + ).to.be.equal(true); + + // Miner2 (unregistered) attempts to submit KC - should fail + await expect( + Paranet.connect(miner2).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + miner2CollectionId, + ), + ).to.be.revertedWith('Miner is not registered'); + + // Verify miner2's KC was not added + + const miner2CollectionBytes = ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256'], + [await KnowledgeCollectionStorage.getAddress(), miner2CollectionId], + ), + ); + expect( + await ParanetsRegistry.isKnowledgeCollectionRegistered( + paranetId, + miner2CollectionBytes, + ), + ).to.be.equal(false); + + // Verify total KC count is 1 (only miner1's KC) + expect( + await ParanetsRegistry.getKnowledgeCollectionsCount(paranetId), + ).to.equal(1); + }); + }); + + describe('Paranet Permissioned Nodes', () => { + it('Should allow owner to add and remove curated nodes', async () => { + // Setup paranet with permissioned nodes policy + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const node1 = accounts[10]; + const node2 = accounts[11]; + + // Create profiles for test nodes + await Profile.connect(node1).createProfile( + accounts[0].address, + [], // operational wallets + 'Node1', + '0x' + randomBytes(32).toString('hex'), + 0, + ); + await Profile.connect(node2).createProfile( + accounts[0].address, + [], // operational wallets + 'Node2', + '0x' + randomBytes(32).toString('hex'), + 0, + ); + const node1IdentityId = await IdentityStorage.getIdentityId( + node1.address, + ); + const node2IdentityId = await IdentityStorage.getIdentityId( + node2.address, + ); + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetId, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 1, // NODES_ACCESS_POLICY_PERMISSIONED + ACCESS_POLICIES.OPEN, + ACCESS_POLICIES.OPEN, + ); + + // Verify initial state + expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( + 0, + ); + expect( + await ParanetsRegistry.isCuratedNode(paranetId, node1IdentityId), + ).to.be.equal(false); + expect( + await ParanetsRegistry.isCuratedNode(paranetId, node2IdentityId), + ).to.be.equal(false); + + // Add nodes + await expect( + Paranet.connect(kcCreator).addParanetCuratedNodes( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + [node1IdentityId, node2IdentityId], + ), + ) + .to.emit(Paranet, 'ParanetCuratedNodeAdded') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + node1IdentityId, + ) + .to.emit(Paranet, 'ParanetCuratedNodeAdded') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + node2IdentityId, + ); + + // Verify nodes were added + expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( + 2, + ); + expect( + await ParanetsRegistry.isCuratedNode(paranetId, node1IdentityId), + ).to.be.equal(true); + expect( + await ParanetsRegistry.isCuratedNode(paranetId, node2IdentityId), + ).to.be.equal(true); + + const curatedNodes = await ParanetsRegistry.getCuratedNodes(paranetId); + expect(curatedNodes[0].identityId).to.equal(node1IdentityId); + expect(curatedNodes[1].identityId).to.equal(node2IdentityId); + + // Remove node1 + await expect( + Paranet.connect(kcCreator).removeParanetCuratedNodes( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + [node1IdentityId], + ), + ) + .to.emit(Paranet, 'ParanetCuratedNodeRemoved') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + node1IdentityId, + ); + + // Verify node1 was removed but node2 remains + expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( + 1, + ); + expect( + await ParanetsRegistry.isCuratedNode(paranetId, node1IdentityId), + ).to.be.equal(false); + expect( + await ParanetsRegistry.isCuratedNode(paranetId, node2IdentityId), + ).to.be.equal(true); + + const remainingNodes = await ParanetsRegistry.getCuratedNodes(paranetId); + expect(remainingNodes).to.have.lengthOf(1); + expect(remainingNodes[0].identityId).to.equal(node2IdentityId); + }); + + it('Should handle node join requests correctly', async () => { + // Setup paranet with permissioned nodes policy + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const applicantNode = accounts[10]; + + // Create profile for applicant node + await Profile.connect(applicantNode).createProfile( + accounts[0].address, + [], // operational wallets + 'Applicant', + '0x' + randomBytes(32).toString('hex'), + 0, + ); + const applicantIdentityId = await IdentityStorage.getIdentityId( + applicantNode.address, + ); + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetId, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 1, // NODES_ACCESS_POLICY_PERMISSIONED + ACCESS_POLICIES.OPEN, + ACCESS_POLICIES.OPEN, + ); + + // Request to join + await expect( + Paranet.connect(applicantNode).requestParanetCuratedNodeAccess( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ), + ) + .to.emit(Paranet, 'ParanetCuratedNodeJoinRequestCreated') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + applicantIdentityId, + ); + + // Verify initial request state + const latestRequest = await ParanetsRegistry.getLatestNodeJoinRequest( + paranetId, + applicantIdentityId, + ); + expect(latestRequest.identityId).to.equal(applicantIdentityId); + expect(latestRequest.status).to.equal(1); // PENDING status + expect(latestRequest.createdAt).to.be.gt(0); + expect(latestRequest.updatedAt).to.equal(latestRequest.createdAt); + + // Approve request + await expect( + Paranet.connect(kcCreator).approveCuratedNode( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + applicantIdentityId, + ), + ) + .to.emit(Paranet, 'ParanetCuratedNodeJoinRequestAccepted') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + applicantIdentityId, + ) + .to.emit(Paranet, 'ParanetCuratedNodeAdded') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + applicantIdentityId, + ); + + // Verify request state after approval + const updatedRequest = await ParanetsRegistry.getLatestNodeJoinRequest( + paranetId, + applicantIdentityId, + ); + expect(updatedRequest.identityId).to.equal(applicantIdentityId); + expect(updatedRequest.status).to.equal(2); // ACCEPTED status + expect(updatedRequest.createdAt).to.equal(latestRequest.createdAt); + expect(updatedRequest.updatedAt).to.be.gt(latestRequest.updatedAt); + + // Verify node is now registered + expect( + await ParanetsRegistry.isCuratedNode(paranetId, applicantIdentityId), + ).to.be.equal(true); + }); + + it('Should handle node join request rejection correctly', async () => { + // Setup paranet with permissioned nodes policy + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const applicantNode = accounts[10]; + + // Create profile for applicant node + await Profile.connect(applicantNode).createProfile( + accounts[0].address, + [], // operational wallets + 'Applicant', + '0x' + randomBytes(32).toString('hex'), + 0, + ); + const applicantIdentityId = await IdentityStorage.getIdentityId( + applicantNode.address, + ); + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetId, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 1, // NODES_ACCESS_POLICY_PERMISSIONED + ACCESS_POLICIES.OPEN, + ACCESS_POLICIES.OPEN, + ); + + // Request to join + await expect( + Paranet.connect(applicantNode).requestParanetCuratedNodeAccess( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ), + ) + .to.emit(Paranet, 'ParanetCuratedNodeJoinRequestCreated') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + applicantIdentityId, + ); + + // Verify initial request state + const latestRequest = await ParanetsRegistry.getLatestNodeJoinRequest( + paranetId, + applicantIdentityId, + ); + expect(latestRequest.identityId).to.equal(applicantIdentityId); + expect(latestRequest.status).to.equal(1); // PENDING status + + // Reject request + await expect( + Paranet.connect(kcCreator).rejectCuratedNode( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + applicantIdentityId, + ), + ) + .to.emit(Paranet, 'ParanetCuratedNodeJoinRequestRejected') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + applicantIdentityId, + ); + + // Verify request state after rejection + const updatedRequest = await ParanetsRegistry.getLatestNodeJoinRequest( + paranetId, + applicantIdentityId, + ); + expect(updatedRequest.identityId).to.equal(applicantIdentityId); + expect(updatedRequest.status).to.equal(3); // REJECTED status + expect(updatedRequest.createdAt).to.equal(latestRequest.createdAt); + expect(updatedRequest.updatedAt).to.be.gt(latestRequest.updatedAt); + + // Verify node is not registered + expect( + await ParanetsRegistry.isCuratedNode(paranetId, applicantIdentityId), + ).to.be.equal(false); + }); + + it('Should handle edge cases when adding and removing multiple nodes', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const node1 = accounts[10]; + const node2 = accounts[11]; + const node3 = accounts[12]; + + // Create profiles for test nodes + await Profile.connect(node1).createProfile( + accounts[0].address, + [], // operational wallets + 'Node1', + '0x' + randomBytes(32).toString('hex'), + 0, + ); + await Profile.connect(node2).createProfile( + accounts[0].address, + [], // operational wallets + 'Node2', + '0x' + randomBytes(32).toString('hex'), + 0, + ); + await Profile.connect(node3).createProfile( + accounts[0].address, + [], // operational wallets + 'Node3', + '0x' + randomBytes(32).toString('hex'), + 0, + ); + const node1IdentityId = await IdentityStorage.getIdentityId( + node1.address, + ); + const node2IdentityId = await IdentityStorage.getIdentityId( + node2.address, + ); + const node3IdentityId = await IdentityStorage.getIdentityId( + node3.address, + ); + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetId, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 1, // NODES_ACCESS_POLICY_PERMISSIONED + ACCESS_POLICIES.OPEN, + ACCESS_POLICIES.OPEN, + ); + + // Add nodes in sequence + await Paranet.connect(kcCreator).addParanetCuratedNodes( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + [node1IdentityId], + ); + + await Paranet.connect(kcCreator).addParanetCuratedNodes( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + [node2IdentityId, node3IdentityId], + ); + + // Verify all nodes were added + expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( + 3, + ); + const allNodes = await ParanetsRegistry.getCuratedNodes(paranetId); + expect(allNodes.map((node) => node.identityId)).to.have.members([ + node1IdentityId, + node2IdentityId, + node3IdentityId, + ]); + + // Remove nodes from edges (first and last) + await Paranet.connect(kcCreator).removeParanetCuratedNodes( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + [node1IdentityId, node3IdentityId], + ); + + // Verify middle node remains + expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( + 1, + ); + expect( + await ParanetsRegistry.isCuratedNode(paranetId, node1IdentityId), + ).to.be.equal(false); + expect( + await ParanetsRegistry.isCuratedNode(paranetId, node2IdentityId), + ).to.be.equal(true); + expect( + await ParanetsRegistry.isCuratedNode(paranetId, node3IdentityId), + ).to.be.equal(false); + + // Try to remove non-existent node - should revert + await expect( + Paranet.connect(kcCreator).removeParanetCuratedNodes( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + [node1IdentityId], // Already removed + ), + ).to.be.revertedWithCustomError(Paranet, 'ParanetCuratedNodeDoesntExist'); + + // Verify state remains unchanged + expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( + 1, + ); + expect( + await ParanetsRegistry.isCuratedNode(paranetId, node2IdentityId), + ).to.be.equal(true); + + // Try to add duplicate node + await expect( + Paranet.connect(kcCreator).addParanetCuratedNodes( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + [node2IdentityId], + ), + ).to.be.revertedWithCustomError( + Paranet, + 'ParanetCuratedNodeHasAlreadyBeenAdded', + ); + + expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( + 1, + ); + const finalNodes = await ParanetsRegistry.getCuratedNodes(paranetId); + expect(finalNodes).to.have.lengthOf(1); + expect(finalNodes[0].identityId).to.equal(node2IdentityId); + }); + }); }); From 5eeef4d1b49e2682cec476f3a40ceec8f066d613 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 19 Feb 2025 13:23:33 +0100 Subject: [PATCH 119/153] Add incentive test --- test/integration/Paranet.test.ts | 154 +++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index d5549d9c..4f5c3efa 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -468,6 +468,160 @@ describe('@unit Paranet', () => { }); }); + describe('Paranet Incentives Pool Rewards', () => { + it('Should deploy pool, add KCs, fund pool and claim rewards correctly', async () => { + // 1. Setup paranet first + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Deploy incentives pool + const tracToNeuroEmissionMultiplier = ethers.parseUnits('1', 12); // 1 NEURO per 1 TRAC + const operatorRewardPercentage = 1000; // 10% + const votersRewardPercentage = 2000; // 20% + + const tx = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + tracToNeuroEmissionMultiplier, + operatorRewardPercentage, + votersRewardPercentage, + 'TestPool', + await Token.getAddress(), + ); + + const receipt = await tx.wait(); + const event = receipt!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolDeployed', + ).topicHash, + ) as EventLog; + + const poolStorageAddress = event?.args[3]; + const poolAddress = event?.args[4]; + + // 3. Create and submit knowledge collections to paranet + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection, + Token, + }, + ); + + await Paranet.connect(kcCreator).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ); + + // 4. Fund the incentives pool with tokens + const fundAmount = ethers.parseUnits('1000', 18); // 1000 tokens + await Token.connect(accounts[0]).mint(poolStorageAddress, fundAmount); + + // 5. Get pool contracts + const incentivesPool = await hre.ethers.getContractAt( + 'ParanetIncentivesPool', + poolAddress, + ); + const incentivesPoolStorage = await hre.ethers.getContractAt( + 'ParanetIncentivesPoolStorage', + poolStorageAddress, + ); + + // 6. Check initial balances + expect(await incentivesPoolStorage.getBalance()).to.equal(fundAmount); + expect(await incentivesPoolStorage.totalMinersclaimedToken()).to.equal(0); + expect(await incentivesPoolStorage.totalOperatorsclaimedToken()).to.equal( + 0, + ); + expect(await incentivesPoolStorage.totalVotersclaimedToken()).to.equal(0); + + // 7. Claim miner rewards + const minerRewardEstimate = + await incentivesPool.getTotalKnowledgeMinerIncentiveEstimation(); + expect(minerRewardEstimate).to.be.gt(0); + + const claimableMinerReward = + await incentivesPool.getClaimableKnowledgeMinerRewardAmount(); + await incentivesPool + .connect(kcCreator) + .claimKnowledgeMinerReward(claimableMinerReward); + + // 8. Verify miner rewards claimed correctly + expect(await incentivesPoolStorage.totalMinersclaimedToken()).to.equal( + claimableMinerReward, + ); + const minerProfile = + await incentivesPoolStorage.getClaimedMinerRewardsAtIndex( + await incentivesPoolStorage.claimedMinerRewardsIndexes( + kcCreator.address, + ), + ); + expect(minerProfile.addr).to.equal(kcCreator.address); + expect(minerProfile.claimedToken).to.equal(claimableMinerReward); + + // 9. Claim operator rewards + const operatorRewardEstimate = + await incentivesPool.getTotalParanetOperatorIncentiveEstimation(); + expect(operatorRewardEstimate).to.be.gt(0); + + const claimableOperatorReward = + await incentivesPool.getClaimableParanetOperatorRewardAmount(); + await incentivesPool.connect(paranetOwner).claimParanetOperatorReward(); + + // 10. Verify operator rewards claimed correctly + expect(await incentivesPoolStorage.totalOperatorsclaimedToken()).to.equal( + claimableOperatorReward, + ); + const operatorProfile = + await incentivesPoolStorage.getClaimedOperatorRewardsAtIndex( + await incentivesPoolStorage.claimedOperatorRewardsIndexes( + paranetOwner.address, + ), + ); + expect(operatorProfile.addr).to.equal(paranetOwner.address); + expect(operatorProfile.claimedToken).to.equal(claimableOperatorReward); + + // 11. Verify final pool balance + const expectedRemainingBalance = + fundAmount - claimableMinerReward - claimableOperatorReward; + expect(await incentivesPoolStorage.getBalance()).to.equal( + expectedRemainingBalance, + ); + }); + }); + describe('Submit Knowledge Collection to Paranet', () => { it('Should submit knowledge collection to paranet successfully', async () => { // 1. Setup paranet first From b8dcfebace1d99e1d8aa436422f033d9d1b9ee15 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 19 Feb 2025 13:35:18 +0100 Subject: [PATCH 120/153] IERC20Extended inherits from IERC20 --- contracts/interfaces/IERC20Extended.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/interfaces/IERC20Extended.sol b/contracts/interfaces/IERC20Extended.sol index 7eeb5ee3..4d7f5af7 100644 --- a/contracts/interfaces/IERC20Extended.sol +++ b/contracts/interfaces/IERC20Extended.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.20; -interface IERC20Extended { +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +interface IERC20Extended is IERC20 { function decimals() external view returns (uint8); } From 7d43bc9131fcb90e45ea3182be31ec1ff6da78d9 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 19 Feb 2025 13:35:52 +0100 Subject: [PATCH 121/153] Update abi --- abi/IERC20Extended.json | 183 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) diff --git a/abi/IERC20Extended.json b/abi/IERC20Extended.json index 5e361ebf..253d8006 100644 --- a/abi/IERC20Extended.json +++ b/abi/IERC20Extended.json @@ -1,4 +1,121 @@ [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "decimals", @@ -11,5 +128,71 @@ ], "stateMutability": "view", "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" } ] From f7fcaad8cc0b794819abd52e309f33a43bd3d57d Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 19 Feb 2025 14:22:32 +0100 Subject: [PATCH 122/153] Rename --- contracts/libraries/ParanetLib.sol | 4 ++-- contracts/paranets/Paranet.sol | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index 9861694a..7b36c8e2 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -68,9 +68,9 @@ library ParanetLib { mapping(string => uint256) incentivesPoolsByNameIndexes; // Incentives Pool Storage Address => Index in the array mapping(address => uint256) incentivesPoolsByStorageAddressIndexes; - Node[] curatedNodes; + Node[] permissionedNodes; // Identity ID => Index in the array - mapping(uint72 => uint256) curatedNodesIndexes; + mapping(uint72 => uint256) permissionedNodesIndexes; // Identity ID => Requests Array mapping(uint72 => ParanetNodeJoinRequest[]) paranetNodeJoinRequests; bytes32[] services; diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 426cf1e9..629acafd 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -1005,9 +1005,9 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // ParanetLib.MinersAccessPolicy minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); - // // Check if paranet is curated and if knowledge miner is whitelisted + // // Check if paranet is permisioned and if knowledge miner is whitelisted // if ( - // minersAccessPolicy == ParanetLib.MinersAccessPolicy.CURATED && + // minersAccessPolicy == ParanetLib.MinersAccessPolicy.permisioned && // !pr.isKnowledgeMinerRegistered(paranetId, msg.sender) // ) { // revert ParanetLib.ParanetCuratedMinerDoesntExist(paranetId, msg.sender); @@ -1317,7 +1317,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; ParanetsRegistry pr = paranetsRegistry; uint8 minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); - // Check if paranet is curated and if knowledge miner is whitelisted + // Check if paranet is permisioned and if knowledge miner is whitelisted if (minersAccessPolicy == MINERS_ACCESS_POLICY_PERMISSIONED) { require(pr.isKnowledgeMinerRegistered(paranetId, msg.sender), "Miner is not registered"); // Should this be done in both cases why would OPEN have separeted logic ??? From e11392dfaf308144456237c6ab4439c5ac39ea77 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 19 Feb 2025 15:22:03 +0100 Subject: [PATCH 123/153] renaming --- contracts/libraries/ParanetLib.sol | 16 ++++++++-------- contracts/storage/paranets/ParanetsRegistry.sol | 10 +++++----- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/contracts/libraries/ParanetLib.sol b/contracts/libraries/ParanetLib.sol index 7b36c8e2..94031323 100644 --- a/contracts/libraries/ParanetLib.sol +++ b/contracts/libraries/ParanetLib.sol @@ -178,23 +178,23 @@ library ParanetLib { uint256 knowledgeAssetTokenId ); error InvalidParanetNodesAccessPolicy(uint8[] expectedAccessPolicies, uint8 actualAccessPolicy); - error ParanetCuratedNodeHasAlreadyBeenAdded(bytes32 paranetId, uint72 identityId); - error ParanetCuratedNodeDoesntExist(bytes32 paranetId, uint72 identityId); - error ParanetCuratedNodeJoinRequestInvalidStatus( + error ParanetPermissionedNodeHasAlreadyBeenAdded(bytes32 paranetId, uint72 identityId); + error ParanetPermissionedNodeDoesntExist(bytes32 paranetId, uint72 identityId); + error ParanetPermissionedNodeJoinRequestInvalidStatus( bytes32 paranetId, uint72 identityId, ParanetLib.RequestStatus status ); - error ParanetCuratedNodeJoinRequestDoesntExist(bytes32 paranetId, uint72 identityId); + error ParanetPermissionedNodeJoinRequestDoesntExist(bytes32 paranetId, uint72 identityId); error InvalidParanetMinersAccessPolicy(uint8[] expectedAccessPolicies, uint8 actualAccessPolicy); - error ParanetCuratedMinerHasAlreadyBeenAdded(bytes32 paranetId, address miner); - error ParanetCuratedMinerDoesntExist(bytes32 paranetId, address miner); - error ParanetCuratedMinerAccessRequestInvalidStatus( + error ParanetPermissionedMinerHasAlreadyBeenAdded(bytes32 paranetId, address miner); + error ParanetPermissionedMinerDoesntExist(bytes32 paranetId, address miner); + error ParanetPermissionedMinerAccessRequestInvalidStatus( bytes32 paranetId, address miner, ParanetLib.RequestStatus status ); - error ParanetCuratedMinerAccessRequestDoesntExist(bytes32 paranetId, address miner); + error ParanetPermissionedMinerAccessRequestDoesntExist(bytes32 paranetId, address miner); error ParanetIncentivesPoolAlreadyExists( address knowledgeCollectionStorageAddress, uint256 knowledgeCollectionTokenId, diff --git a/contracts/storage/paranets/ParanetsRegistry.sol b/contracts/storage/paranets/ParanetsRegistry.sol index 2302a102..7270e23d 100644 --- a/contracts/storage/paranets/ParanetsRegistry.sol +++ b/contracts/storage/paranets/ParanetsRegistry.sol @@ -212,12 +212,12 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { return paranets[paranetId].paranetNodeJoinRequests[identityId].length; } - function addCuratedNode(bytes32 paranetId, uint72 identityId, bytes calldata nodeId) external onlyContracts { + function addPermissionedNode(bytes32 paranetId, uint72 identityId, bytes calldata nodeId) external onlyContracts { paranets[paranetId].curatedNodesIndexes[identityId] = paranets[paranetId].curatedNodes.length; paranets[paranetId].curatedNodes.push(ParanetLib.Node({identityId: identityId, nodeId: nodeId})); } - function removeCuratedNode(bytes32 paranetId, uint72 identityId) external onlyContracts { + function removePermissionedNode(bytes32 paranetId, uint72 identityId) external onlyContracts { paranets[paranetId].curatedNodes[paranets[paranetId].curatedNodesIndexes[identityId]] = paranets[paranetId] .curatedNodes[paranets[paranetId].curatedNodes.length - 1]; paranets[paranetId].curatedNodesIndexes[ @@ -228,15 +228,15 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { paranets[paranetId].curatedNodes.pop(); } - function getCuratedNodes(bytes32 paranetId) external view returns (ParanetLib.Node[] memory) { + function getPermissionedNodes(bytes32 paranetId) external view returns (ParanetLib.Node[] memory) { return paranets[paranetId].curatedNodes; } - function getCuratedNodesCount(bytes32 paranetId) external view returns (uint256) { + function getPermissionedNodesCount(bytes32 paranetId) external view returns (uint256) { return paranets[paranetId].curatedNodes.length; } - function isCuratedNode(bytes32 paranetId, uint72 identityId) external view returns (bool) { + function isPermissionedNode(bytes32 paranetId, uint72 identityId) external view returns (bool) { return (paranets[paranetId].curatedNodes.length != 0 && paranets[paranetId].curatedNodes[paranets[paranetId].curatedNodesIndexes[identityId]].identityId == identityId); From 93710a970104f52ae4d09f36c8630330afe6b3b2 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 19 Feb 2025 15:25:41 +0100 Subject: [PATCH 124/153] Comment out permissioned function --- contracts/paranets/Paranet.sol | 864 ++++++++++++++++----------------- 1 file changed, 432 insertions(+), 432 deletions(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 629acafd..7a5a63f4 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -40,31 +40,31 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint8 minersAccessPolicy, uint8 knowledgeCollectionsSubmissionPolicy ); - event ParanetCuratedNodeAdded( + event ParanetPermissionedNodeAdded( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, uint256 indexed paranetKATokenId, uint72 identityId ); - event ParanetCuratedNodeRemoved( + event ParanetPermissionedNodeRemoved( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, uint256 indexed paranetKATokenId, uint72 identityId ); - event ParanetCuratedNodeJoinRequestCreated( + event ParanetPermissionedNodeJoinRequestCreated( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, uint256 indexed paranetKATokenId, uint72 identityId ); - event ParanetCuratedNodeJoinRequestAccepted( + event ParanetPermissionedNodeJoinRequestAccepted( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, uint256 indexed paranetKATokenId, uint72 identityId ); - event ParanetCuratedNodeJoinRequestRejected( + event ParanetPermissionedNodeJoinRequestRejected( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, uint256 indexed paranetKATokenId, @@ -114,31 +114,31 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { address knowledgeCollectionStorageContract, uint256 knowledgeCollectionId ); - event ParanetCuratedMinerAdded( + event ParanetPermissionedMinerAdded( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, uint256 indexed paranetKATokenId, address minerAddress ); - event ParanetCuratedMinerRemoved( + event ParanetPermissionedMinerRemoved( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, uint256 indexed paranetKATokenId, address minerAddress ); - event ParanetCuratedMinerAccessRequestCreated( + event ParanetPermissionedMinerAccessRequestCreated( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, uint256 indexed paranetKATokenId, address minerAddress ); - event ParanetCuratedMinerAccessRequestAccepted( + event ParanetPermissionedMinerAccessRequestAccepted( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, uint256 indexed paranetKATokenId, address minerAddress ); - event ParanetCuratedMinerAccessRequestRejected( + event ParanetPermissionedMinerAccessRequestRejected( address indexed paranetKCStorageContract, uint256 indexed paranetKCTokenId, uint256 indexed paranetKATokenId, @@ -224,7 +224,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { uint8 knowledgeCollectionsSubmissionPolicy ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) returns (bytes32) { require( - nodesAccessPolicy < 2 && minersAccessPolicy < 2 && knowledgeCollectionsSubmissionPolicy < 2, + nodesAccessPolicy < 1 && minersAccessPolicy < 1 && knowledgeCollectionsSubmissionPolicy < 2, "Invalid policy" ); ParanetsRegistry pr = paranetsRegistry; @@ -290,263 +290,263 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); } - function addParanetCuratedNodes( - address paranetKCStorageContract, - uint256 paranetKCTokenId, - uint256 paranetKATokenId, - uint72[] calldata identityIds - ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { - ParanetsRegistry pr = paranetsRegistry; - ProfileStorage ps = profileStorage; + // function addParanetPermissionedNodes( + // address paranetKCStorageContract, + // uint256 paranetKCTokenId, + // uint256 paranetKATokenId, + // uint72[] calldata identityIds + // ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { + // ParanetsRegistry pr = paranetsRegistry; + // ProfileStorage ps = profileStorage; - bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - } + // if (!pr.paranetExists(paranetId)) { + // revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // } - if (pr.getNodesAccessPolicy(paranetId) != NODES_ACCESS_POLICY_PERMISSIONED) { - // TODO: Why is this 1 element array - uint8[] memory expectedAccessPolicies = new uint8[](1); - expectedAccessPolicies[0] = NODES_ACCESS_POLICY_PERMISSIONED; + // if (pr.getNodesAccessPolicy(paranetId) != NODES_ACCESS_POLICY_PERMISSIONED) { + // // TODO: Why is this 1 element array + // uint8[] memory expectedAccessPolicies = new uint8[](1); + // expectedAccessPolicies[0] = NODES_ACCESS_POLICY_PERMISSIONED; - revert ParanetLib.InvalidParanetNodesAccessPolicy( - expectedAccessPolicies, - pr.getNodesAccessPolicy(paranetId) - ); - } + // revert ParanetLib.InvalidParanetNodesAccessPolicy( + // expectedAccessPolicies, + // pr.getNodesAccessPolicy(paranetId) + // ); + // } - for (uint256 i; i < identityIds.length; ) { - if (!ps.profileExists(identityIds[i])) { - revert ProfileLib.ProfileDoesntExist(identityIds[i]); - } + // for (uint256 i; i < identityIds.length; ) { + // if (!ps.profileExists(identityIds[i])) { + // revert ProfileLib.ProfileDoesntExist(identityIds[i]); + // } - if (pr.isCuratedNode(paranetId, identityIds[i])) { - revert ParanetLib.ParanetCuratedNodeHasAlreadyBeenAdded(paranetId, identityIds[i]); - } + // if (pr.isPermissionedNode(paranetId, identityIds[i])) { + // revert ParanetLib.ParanetPermissionedNodeHasAlreadyBeenAdded(paranetId, identityIds[i]); + // } - pr.addCuratedNode(paranetId, identityIds[i], ps.getNodeId(identityIds[i])); + // pr.addPermissionedNode(paranetId, identityIds[i], ps.getNodeId(identityIds[i])); - emit ParanetCuratedNodeAdded(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, identityIds[i]); + // emit ParanetPermissionedNodeAdded(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, identityIds[i]); - unchecked { - i++; - } - } - } + // unchecked { + // i++; + // } + // } + // } - function removeParanetCuratedNodes( - address paranetKCStorageContract, - uint256 paranetKCTokenId, - uint256 paranetKATokenId, - uint72[] calldata identityIds - ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { - ParanetsRegistry pr = paranetsRegistry; + // function removeParanetPermissionedNodes( + // address paranetKCStorageContract, + // uint256 paranetKCTokenId, + // uint256 paranetKATokenId, + // uint72[] calldata identityIds + // ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { + // ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - } + // if (!pr.paranetExists(paranetId)) { + // revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // } - if (pr.getNodesAccessPolicy(paranetId) != NODES_ACCESS_POLICY_PERMISSIONED) { - uint8[] memory expectedAccessPolicies = new uint8[](1); - expectedAccessPolicies[0] = NODES_ACCESS_POLICY_PERMISSIONED; + // if (pr.getNodesAccessPolicy(paranetId) != NODES_ACCESS_POLICY_PERMISSIONED) { + // uint8[] memory expectedAccessPolicies = new uint8[](1); + // expectedAccessPolicies[0] = NODES_ACCESS_POLICY_PERMISSIONED; - revert ParanetLib.InvalidParanetNodesAccessPolicy( - expectedAccessPolicies, - pr.getNodesAccessPolicy(paranetId) - ); - } + // revert ParanetLib.InvalidParanetNodesAccessPolicy( + // expectedAccessPolicies, + // pr.getNodesAccessPolicy(paranetId) + // ); + // } - for (uint256 i; i < identityIds.length; ) { - if (!pr.isCuratedNode(paranetId, identityIds[i])) { - revert ParanetLib.ParanetCuratedNodeDoesntExist(paranetId, identityIds[i]); - } + // for (uint256 i; i < identityIds.length; ) { + // if (!pr.isPermissionedNode(paranetId, identityIds[i])) { + // revert ParanetLib.ParanetPermissionedNodeDoesntExist(paranetId, identityIds[i]); + // } - pr.removeCuratedNode(paranetId, identityIds[i]); + // pr.removePermissionedNode(paranetId, identityIds[i]); - emit ParanetCuratedNodeRemoved( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - identityIds[i] - ); + // emit ParanetPermissionedNodeRemoved( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // identityIds[i] + // ); - unchecked { - i++; - } - } - } + // unchecked { + // i++; + // } + // } + // } - function requestParanetCuratedNodeAccess( - address paranetKCStorageContract, - uint256 paranetKCTokenId, - uint256 paranetKATokenId - ) external { - ParanetsRegistry pr = paranetsRegistry; + // function requestParanetPermissionedNodeAccess( + // address paranetKCStorageContract, + // uint256 paranetKCTokenId, + // uint256 paranetKATokenId + // ) external { + // ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - } + // if (!pr.paranetExists(paranetId)) { + // revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // } - if (pr.getNodesAccessPolicy(paranetId) != NODES_ACCESS_POLICY_PERMISSIONED) { - uint8[] memory expectedAccessPolicies = new uint8[](1); - expectedAccessPolicies[0] = NODES_ACCESS_POLICY_PERMISSIONED; + // if (pr.getNodesAccessPolicy(paranetId) != NODES_ACCESS_POLICY_PERMISSIONED) { + // uint8[] memory expectedAccessPolicies = new uint8[](1); + // expectedAccessPolicies[0] = NODES_ACCESS_POLICY_PERMISSIONED; - revert ParanetLib.InvalidParanetNodesAccessPolicy( - expectedAccessPolicies, - pr.getNodesAccessPolicy(paranetId) - ); - } + // revert ParanetLib.InvalidParanetNodesAccessPolicy( + // expectedAccessPolicies, + // pr.getNodesAccessPolicy(paranetId) + // ); + // } - uint72 identityId = identityStorage.getIdentityId(msg.sender); + // uint72 identityId = identityStorage.getIdentityId(msg.sender); - if (!profileStorage.profileExists(identityId)) { - revert ProfileLib.ProfileDoesntExist(identityId); - } + // if (!profileStorage.profileExists(identityId)) { + // revert ProfileLib.ProfileDoesntExist(identityId); + // } - ParanetLib.ParanetNodeJoinRequest[] memory paranetNodeJoinRequests = pr.getNodeJoinRequests( - paranetId, - identityId - ); + // ParanetLib.ParanetNodeJoinRequest[] memory paranetNodeJoinRequests = pr.getNodeJoinRequests( + // paranetId, + // identityId + // ); - if ( - paranetNodeJoinRequests.length > 0 && - paranetNodeJoinRequests[paranetNodeJoinRequests.length - 1].status == ParanetLib.RequestStatus.PENDING - ) { - revert ParanetLib.ParanetCuratedNodeJoinRequestInvalidStatus( - paranetId, - identityId, - paranetNodeJoinRequests[paranetNodeJoinRequests.length - 1].status - ); - } + // if ( + // paranetNodeJoinRequests.length > 0 && + // paranetNodeJoinRequests[paranetNodeJoinRequests.length - 1].status == ParanetLib.RequestStatus.PENDING + // ) { + // revert ParanetLib.ParanetPermissionedNodeJoinRequestInvalidStatus( + // paranetId, + // identityId, + // paranetNodeJoinRequests[paranetNodeJoinRequests.length - 1].status + // ); + // } - pr.addNodeJoinRequest(paranetId, identityId, ParanetLib.RequestStatus.PENDING); + // pr.addNodeJoinRequest(paranetId, identityId, ParanetLib.RequestStatus.PENDING); - emit ParanetCuratedNodeJoinRequestCreated( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - identityId - ); - } + // emit ParanetPermissionedNodeJoinRequestCreated( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // identityId + // ); + // } - function approveCuratedNode( - address paranetKCStorageContract, - uint256 paranetKCTokenId, - uint256 paranetKATokenId, - uint72 identityId - ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { - ParanetsRegistry pr = paranetsRegistry; + // function approvePermissionedNode( + // address paranetKCStorageContract, + // uint256 paranetKCTokenId, + // uint256 paranetKATokenId, + // uint72 identityId + // ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { + // ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - } + // if (!pr.paranetExists(paranetId)) { + // revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // } - if (pr.getNodesAccessPolicy(paranetId) != NODES_ACCESS_POLICY_PERMISSIONED) { - uint8[] memory expectedAccessPolicies = new uint8[](1); - expectedAccessPolicies[0] = NODES_ACCESS_POLICY_PERMISSIONED; + // if (pr.getNodesAccessPolicy(paranetId) != NODES_ACCESS_POLICY_PERMISSIONED) { + // uint8[] memory expectedAccessPolicies = new uint8[](1); + // expectedAccessPolicies[0] = NODES_ACCESS_POLICY_PERMISSIONED; - revert ParanetLib.InvalidParanetNodesAccessPolicy( - expectedAccessPolicies, - pr.getNodesAccessPolicy(paranetId) - ); - } + // revert ParanetLib.InvalidParanetNodesAccessPolicy( + // expectedAccessPolicies, + // pr.getNodesAccessPolicy(paranetId) + // ); + // } - ParanetLib.ParanetNodeJoinRequest[] memory paranetNodeJoinRequests = pr.getNodeJoinRequests( - paranetId, - identityId - ); + // ParanetLib.ParanetNodeJoinRequest[] memory paranetNodeJoinRequests = pr.getNodeJoinRequests( + // paranetId, + // identityId + // ); - if (paranetNodeJoinRequests.length == 0) { - revert ParanetLib.ParanetCuratedNodeJoinRequestDoesntExist(paranetId, identityId); - } else if ( - paranetNodeJoinRequests[paranetNodeJoinRequests.length - 1].status != ParanetLib.RequestStatus.PENDING - ) { - revert ParanetLib.ParanetCuratedNodeJoinRequestInvalidStatus( - paranetId, - identityId, - paranetNodeJoinRequests[paranetNodeJoinRequests.length - 1].status - ); - } + // if (paranetNodeJoinRequests.length == 0) { + // revert ParanetLib.ParanetPermissionedNodeJoinRequestDoesntExist(paranetId, identityId); + // } else if ( + // paranetNodeJoinRequests[paranetNodeJoinRequests.length - 1].status != ParanetLib.RequestStatus.PENDING + // ) { + // revert ParanetLib.ParanetPermissionedNodeJoinRequestInvalidStatus( + // paranetId, + // identityId, + // paranetNodeJoinRequests[paranetNodeJoinRequests.length - 1].status + // ); + // } - pr.updateNodeJoinRequestStatus( - paranetId, - identityId, - paranetNodeJoinRequests.length - 1, - ParanetLib.RequestStatus.APPROVED - ); - pr.addCuratedNode(paranetId, identityId, profileStorage.getNodeId(identityId)); + // pr.updateNodeJoinRequestStatus( + // paranetId, + // identityId, + // paranetNodeJoinRequests.length - 1, + // ParanetLib.RequestStatus.APPROVED + // ); + // pr.addPermissionedNode(paranetId, identityId, profileStorage.getNodeId(identityId)); - emit ParanetCuratedNodeJoinRequestAccepted( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - identityId - ); - emit ParanetCuratedNodeAdded(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, identityId); - } + // emit ParanetPermissionedNodeJoinRequestAccepted( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // identityId + // ); + // emit ParanetPermissionedNodeAdded(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, identityId); + // } - function rejectCuratedNode( - address paranetKCStorageContract, - uint256 paranetKCTokenId, - uint256 paranetKATokenId, - uint72 identityId - ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { - ParanetsRegistry pr = paranetsRegistry; + // function rejectPermissionedNode( + // address paranetKCStorageContract, + // uint256 paranetKCTokenId, + // uint256 paranetKATokenId, + // uint72 identityId + // ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { + // ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - } + // if (!pr.paranetExists(paranetId)) { + // revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // } - if (pr.getNodesAccessPolicy(paranetId) != NODES_ACCESS_POLICY_PERMISSIONED) { - uint8[] memory expectedAccessPolicies = new uint8[](1); - expectedAccessPolicies[0] = NODES_ACCESS_POLICY_PERMISSIONED; + // if (pr.getNodesAccessPolicy(paranetId) != NODES_ACCESS_POLICY_PERMISSIONED) { + // uint8[] memory expectedAccessPolicies = new uint8[](1); + // expectedAccessPolicies[0] = NODES_ACCESS_POLICY_PERMISSIONED; - revert ParanetLib.InvalidParanetNodesAccessPolicy( - expectedAccessPolicies, - pr.getNodesAccessPolicy(paranetId) - ); - } + // revert ParanetLib.InvalidParanetNodesAccessPolicy( + // expectedAccessPolicies, + // pr.getNodesAccessPolicy(paranetId) + // ); + // } - ParanetLib.ParanetNodeJoinRequest[] memory paranetNodeJoinRequests = pr.getNodeJoinRequests( - paranetId, - identityId - ); + // ParanetLib.ParanetNodeJoinRequest[] memory paranetNodeJoinRequests = pr.getNodeJoinRequests( + // paranetId, + // identityId + // ); - if (paranetNodeJoinRequests.length == 0) { - revert ParanetLib.ParanetCuratedNodeJoinRequestDoesntExist(paranetId, identityId); - } else if ( - paranetNodeJoinRequests[paranetNodeJoinRequests.length - 1].status != ParanetLib.RequestStatus.PENDING - ) { - revert ParanetLib.ParanetCuratedNodeJoinRequestInvalidStatus( - paranetId, - identityId, - paranetNodeJoinRequests[paranetNodeJoinRequests.length - 1].status - ); - } + // if (paranetNodeJoinRequests.length == 0) { + // revert ParanetLib.ParanetPermissionedNodeJoinRequestDoesntExist(paranetId, identityId); + // } else if ( + // paranetNodeJoinRequests[paranetNodeJoinRequests.length - 1].status != ParanetLib.RequestStatus.PENDING + // ) { + // revert ParanetLib.ParanetPermissionedNodeJoinRequestInvalidStatus( + // paranetId, + // identityId, + // paranetNodeJoinRequests[paranetNodeJoinRequests.length - 1].status + // ); + // } - pr.updateNodeJoinRequestStatus( - paranetId, - identityId, - paranetNodeJoinRequests.length - 1, - ParanetLib.RequestStatus.REJECTED - ); + // pr.updateNodeJoinRequestStatus( + // paranetId, + // identityId, + // paranetNodeJoinRequests.length - 1, + // ParanetLib.RequestStatus.REJECTED + // ); - emit ParanetCuratedNodeJoinRequestRejected( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - identityId - ); - } + // emit ParanetPermissionedNodeJoinRequestRejected( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // identityId + // ); + // } function addParanetServices( address paranetKCStorageContract, @@ -723,258 +723,258 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ); } - function addParanetCuratedMiners( - address paranetKCStorageContract, - uint256 paranetKCTokenId, - uint256 paranetKATokenId, - address[] calldata minerAddresses - ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { - ParanetsRegistry pr = paranetsRegistry; - ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; + // function addParanetPermissionedMiners( + // address paranetKCStorageContract, + // uint256 paranetKCTokenId, + // uint256 paranetKATokenId, + // address[] calldata minerAddresses + // ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { + // ParanetsRegistry pr = paranetsRegistry; + // ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; - bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - } + // if (!pr.paranetExists(paranetId)) { + // revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // } - if (pr.getMinersAccessPolicy(paranetId) != MINERS_ACCESS_POLICY_PERMISSIONED) { - uint8[] memory expectedAccessPolicies = new uint8[](1); - expectedAccessPolicies[0] = MINERS_ACCESS_POLICY_PERMISSIONED; + // if (pr.getMinersAccessPolicy(paranetId) != MINERS_ACCESS_POLICY_PERMISSIONED) { + // uint8[] memory expectedAccessPolicies = new uint8[](1); + // expectedAccessPolicies[0] = MINERS_ACCESS_POLICY_PERMISSIONED; - revert ParanetLib.InvalidParanetMinersAccessPolicy( - expectedAccessPolicies, - pr.getMinersAccessPolicy(paranetId) - ); - } + // revert ParanetLib.InvalidParanetMinersAccessPolicy( + // expectedAccessPolicies, + // pr.getMinersAccessPolicy(paranetId) + // ); + // } - for (uint256 i; i < minerAddresses.length; ) { - if (!pkmr.knowledgeMinerExists(minerAddresses[i])) { - pkmr.registerKnowledgeMiner(minerAddresses[i]); - } + // for (uint256 i; i < minerAddresses.length; ) { + // if (!pkmr.knowledgeMinerExists(minerAddresses[i])) { + // pkmr.registerKnowledgeMiner(minerAddresses[i]); + // } - if (pr.isKnowledgeMinerRegistered(paranetId, minerAddresses[i])) { - revert ParanetLib.ParanetCuratedMinerHasAlreadyBeenAdded(paranetId, minerAddresses[i]); - } + // if (pr.isKnowledgeMinerRegistered(paranetId, minerAddresses[i])) { + // revert ParanetLib.ParanetPermissionedMinerHasAlreadyBeenAdded(paranetId, minerAddresses[i]); + // } - pr.addKnowledgeMiner(paranetId, minerAddresses[i]); + // pr.addKnowledgeMiner(paranetId, minerAddresses[i]); - emit ParanetCuratedMinerAdded( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - minerAddresses[i] - ); + // emit ParanetPermissionedMinerAdded( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // minerAddresses[i] + // ); - unchecked { - i++; - } - } - } + // unchecked { + // i++; + // } + // } + // } - function removeParanetCuratedMiners( - address paranetKCStorageContract, - uint256 paranetKCTokenId, - uint256 paranetKATokenId, - address[] calldata minerAddresses - ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { - ParanetsRegistry pr = paranetsRegistry; + // function removeParanetPermissionedMiners( + // address paranetKCStorageContract, + // uint256 paranetKCTokenId, + // uint256 paranetKATokenId, + // address[] calldata minerAddresses + // ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { + // ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - } + // if (!pr.paranetExists(paranetId)) { + // revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // } - if (pr.getMinersAccessPolicy(paranetId) != MINERS_ACCESS_POLICY_PERMISSIONED) { - uint8[] memory expectedAccessPolicies = new uint8[](1); - expectedAccessPolicies[0] = MINERS_ACCESS_POLICY_PERMISSIONED; + // if (pr.getMinersAccessPolicy(paranetId) != MINERS_ACCESS_POLICY_PERMISSIONED) { + // uint8[] memory expectedAccessPolicies = new uint8[](1); + // expectedAccessPolicies[0] = MINERS_ACCESS_POLICY_PERMISSIONED; - revert ParanetLib.InvalidParanetMinersAccessPolicy( - expectedAccessPolicies, - pr.getMinersAccessPolicy(paranetId) - ); - } + // revert ParanetLib.InvalidParanetMinersAccessPolicy( + // expectedAccessPolicies, + // pr.getMinersAccessPolicy(paranetId) + // ); + // } - for (uint256 i; i < minerAddresses.length; ) { - if (!pr.isKnowledgeMinerRegistered(paranetId, minerAddresses[i])) { - revert ParanetLib.ParanetCuratedMinerDoesntExist(paranetId, minerAddresses[i]); - } + // for (uint256 i; i < minerAddresses.length; ) { + // if (!pr.isKnowledgeMinerRegistered(paranetId, minerAddresses[i])) { + // revert ParanetLib.ParanetPermissionedMinerDoesntExist(paranetId, minerAddresses[i]); + // } - pr.removeKnowledgeMiner(paranetId, minerAddresses[i]); + // pr.removeKnowledgeMiner(paranetId, minerAddresses[i]); - emit ParanetCuratedMinerRemoved( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - minerAddresses[i] - ); + // emit ParanetPermissionedMinerRemoved( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // minerAddresses[i] + // ); - unchecked { - i++; - } - } - } + // unchecked { + // i++; + // } + // } + // } - function requestParanetCuratedMinerAccess( - address paranetKCStorageContract, - uint256 paranetKCTokenId, - uint256 paranetKATokenId - ) external { - ParanetsRegistry pr = paranetsRegistry; + // function requestParanetPermissionedMinerAccess( + // address paranetKCStorageContract, + // uint256 paranetKCTokenId, + // uint256 paranetKATokenId + // ) external { + // ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - } + // if (!pr.paranetExists(paranetId)) { + // revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // } - if (pr.getMinersAccessPolicy(paranetId) != MINERS_ACCESS_POLICY_PERMISSIONED) { - uint8[] memory expectedAccessPolicies = new uint8[](1); - expectedAccessPolicies[0] = MINERS_ACCESS_POLICY_PERMISSIONED; + // if (pr.getMinersAccessPolicy(paranetId) != MINERS_ACCESS_POLICY_PERMISSIONED) { + // uint8[] memory expectedAccessPolicies = new uint8[](1); + // expectedAccessPolicies[0] = MINERS_ACCESS_POLICY_PERMISSIONED; - revert ParanetLib.InvalidParanetMinersAccessPolicy( - expectedAccessPolicies, - pr.getMinersAccessPolicy(paranetId) - ); - } + // revert ParanetLib.InvalidParanetMinersAccessPolicy( + // expectedAccessPolicies, + // pr.getMinersAccessPolicy(paranetId) + // ); + // } - ParanetLib.ParanetKnowledgeMinerAccessRequest[] memory paranetKnowledgeMinersAccessRequests = pr - .getKnowledgeMinerAccessRequests(paranetId, msg.sender); + // ParanetLib.ParanetKnowledgeMinerAccessRequest[] memory paranetKnowledgeMinersAccessRequests = pr + // .getKnowledgeMinerAccessRequests(paranetId, msg.sender); - if ( - paranetKnowledgeMinersAccessRequests.length > 0 && - paranetKnowledgeMinersAccessRequests[paranetKnowledgeMinersAccessRequests.length - 1].status == - ParanetLib.RequestStatus.PENDING - ) { - revert ParanetLib.ParanetCuratedMinerAccessRequestInvalidStatus( - paranetId, - msg.sender, - paranetKnowledgeMinersAccessRequests[paranetKnowledgeMinersAccessRequests.length - 1].status - ); - } + // if ( + // paranetKnowledgeMinersAccessRequests.length > 0 && + // paranetKnowledgeMinersAccessRequests[paranetKnowledgeMinersAccessRequests.length - 1].status == + // ParanetLib.RequestStatus.PENDING + // ) { + // revert ParanetLib.ParanetPermissionedMinerAccessRequestInvalidStatus( + // paranetId, + // msg.sender, + // paranetKnowledgeMinersAccessRequests[paranetKnowledgeMinersAccessRequests.length - 1].status + // ); + // } - pr.addKnowledgeMinerAccessRequest(paranetId, msg.sender, ParanetLib.RequestStatus.PENDING); + // pr.addKnowledgeMinerAccessRequest(paranetId, msg.sender, ParanetLib.RequestStatus.PENDING); - emit ParanetCuratedMinerAccessRequestCreated( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - msg.sender - ); - } + // emit ParanetPermissionedMinerAccessRequestCreated( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // msg.sender + // ); + // } - function approveCuratedMiner( - address paranetKCStorageContract, - uint256 paranetKCTokenId, - uint256 paranetKATokenId, - address minerAddress - ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { - ParanetsRegistry pr = paranetsRegistry; + // function approvePermissionedMiner( + // address paranetKCStorageContract, + // uint256 paranetKCTokenId, + // uint256 paranetKATokenId, + // address minerAddress + // ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { + // ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - } + // if (!pr.paranetExists(paranetId)) { + // revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // } - if (pr.getMinersAccessPolicy(paranetId) != MINERS_ACCESS_POLICY_PERMISSIONED) { - uint8[] memory expectedAccessPolicies = new uint8[](1); - expectedAccessPolicies[0] = MINERS_ACCESS_POLICY_PERMISSIONED; + // if (pr.getMinersAccessPolicy(paranetId) != MINERS_ACCESS_POLICY_PERMISSIONED) { + // uint8[] memory expectedAccessPolicies = new uint8[](1); + // expectedAccessPolicies[0] = MINERS_ACCESS_POLICY_PERMISSIONED; - revert ParanetLib.InvalidParanetMinersAccessPolicy( - expectedAccessPolicies, - pr.getMinersAccessPolicy(paranetId) - ); - } + // revert ParanetLib.InvalidParanetMinersAccessPolicy( + // expectedAccessPolicies, + // pr.getMinersAccessPolicy(paranetId) + // ); + // } - ParanetLib.ParanetKnowledgeMinerAccessRequest[] memory paranetKnowledgeMinersAccessRequests = pr - .getKnowledgeMinerAccessRequests(paranetId, minerAddress); + // ParanetLib.ParanetKnowledgeMinerAccessRequest[] memory paranetKnowledgeMinersAccessRequests = pr + // .getKnowledgeMinerAccessRequests(paranetId, minerAddress); - if (paranetKnowledgeMinersAccessRequests.length == 0) { - revert ParanetLib.ParanetCuratedMinerAccessRequestDoesntExist(paranetId, minerAddress); - } else if ( - paranetKnowledgeMinersAccessRequests[paranetKnowledgeMinersAccessRequests.length - 1].status != - ParanetLib.RequestStatus.PENDING - ) { - revert ParanetLib.ParanetCuratedMinerAccessRequestInvalidStatus( - paranetId, - minerAddress, - paranetKnowledgeMinersAccessRequests[paranetKnowledgeMinersAccessRequests.length - 1].status - ); - } + // if (paranetKnowledgeMinersAccessRequests.length == 0) { + // revert ParanetLib.ParanetPermissionedMinerAccessRequestDoesntExist(paranetId, minerAddress); + // } else if ( + // paranetKnowledgeMinersAccessRequests[paranetKnowledgeMinersAccessRequests.length - 1].status != + // ParanetLib.RequestStatus.PENDING + // ) { + // revert ParanetLib.ParanetPermissionedMinerAccessRequestInvalidStatus( + // paranetId, + // minerAddress, + // paranetKnowledgeMinersAccessRequests[paranetKnowledgeMinersAccessRequests.length - 1].status + // ); + // } - pr.updateKnowledgeMinerAccessRequestStatus( - paranetId, - minerAddress, - paranetKnowledgeMinersAccessRequests.length - 1, - ParanetLib.RequestStatus.APPROVED - ); - pr.addKnowledgeMiner(paranetId, minerAddress); + // pr.updateKnowledgeMinerAccessRequestStatus( + // paranetId, + // minerAddress, + // paranetKnowledgeMinersAccessRequests.length - 1, + // ParanetLib.RequestStatus.APPROVED + // ); + // pr.addKnowledgeMiner(paranetId, minerAddress); - emit ParanetCuratedMinerAccessRequestAccepted( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - minerAddress - ); - emit ParanetCuratedMinerAdded(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, minerAddress); - } + // emit ParanetPermissionedMinerAccessRequestAccepted( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // minerAddress + // ); + // emit ParanetPermissionedMinerAdded(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, minerAddress); + // } - function rejectCuratedMiner( - address paranetKCStorageContract, - uint256 paranetKCTokenId, - uint256 paranetKATokenId, - address minerAddress - ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { - ParanetsRegistry pr = paranetsRegistry; + // function rejectPermissionedMiner( + // address paranetKCStorageContract, + // uint256 paranetKCTokenId, + // uint256 paranetKATokenId, + // address minerAddress + // ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { + // ParanetsRegistry pr = paranetsRegistry; - bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // bytes32 paranetId = _getParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - if (!pr.paranetExists(paranetId)) { - revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); - } + // if (!pr.paranetExists(paranetId)) { + // revert ParanetLib.ParanetDoesntExist(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); + // } - if (pr.getMinersAccessPolicy(paranetId) != MINERS_ACCESS_POLICY_PERMISSIONED) { - uint8[] memory expectedAccessPolicies = new uint8[](1); - expectedAccessPolicies[0] = MINERS_ACCESS_POLICY_PERMISSIONED; + // if (pr.getMinersAccessPolicy(paranetId) != MINERS_ACCESS_POLICY_PERMISSIONED) { + // uint8[] memory expectedAccessPolicies = new uint8[](1); + // expectedAccessPolicies[0] = MINERS_ACCESS_POLICY_PERMISSIONED; - revert ParanetLib.InvalidParanetMinersAccessPolicy( - expectedAccessPolicies, - pr.getMinersAccessPolicy(paranetId) - ); - } + // revert ParanetLib.InvalidParanetMinersAccessPolicy( + // expectedAccessPolicies, + // pr.getMinersAccessPolicy(paranetId) + // ); + // } - ParanetLib.ParanetKnowledgeMinerAccessRequest[] memory paranetKnowledgeMinerAccessRequests = pr - .getKnowledgeMinerAccessRequests(paranetId, minerAddress); + // ParanetLib.ParanetKnowledgeMinerAccessRequest[] memory paranetKnowledgeMinerAccessRequests = pr + // .getKnowledgeMinerAccessRequests(paranetId, minerAddress); - if (paranetKnowledgeMinerAccessRequests.length == 0) { - revert ParanetLib.ParanetCuratedMinerAccessRequestDoesntExist(paranetId, minerAddress); - } else if ( - paranetKnowledgeMinerAccessRequests[paranetKnowledgeMinerAccessRequests.length - 1].status != - ParanetLib.RequestStatus.PENDING - ) { - revert ParanetLib.ParanetCuratedMinerAccessRequestInvalidStatus( - paranetId, - minerAddress, - paranetKnowledgeMinerAccessRequests[paranetKnowledgeMinerAccessRequests.length - 1].status - ); - } + // if (paranetKnowledgeMinerAccessRequests.length == 0) { + // revert ParanetLib.ParanetPermissionedMinerAccessRequestDoesntExist(paranetId, minerAddress); + // } else if ( + // paranetKnowledgeMinerAccessRequests[paranetKnowledgeMinerAccessRequests.length - 1].status != + // ParanetLib.RequestStatus.PENDING + // ) { + // revert ParanetLib.ParanetPermissionedMinerAccessRequestInvalidStatus( + // paranetId, + // minerAddress, + // paranetKnowledgeMinerAccessRequests[paranetKnowledgeMinerAccessRequests.length - 1].status + // ); + // } - pr.updateKnowledgeMinerAccessRequestStatus( - paranetId, - minerAddress, - paranetKnowledgeMinerAccessRequests.length - 1, - ParanetLib.RequestStatus.REJECTED - ); + // pr.updateKnowledgeMinerAccessRequestStatus( + // paranetId, + // minerAddress, + // paranetKnowledgeMinerAccessRequests.length - 1, + // ParanetLib.RequestStatus.REJECTED + // ); - emit ParanetCuratedMinerAccessRequestRejected( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - minerAddress - ); - } + // emit ParanetPermissionedMinerAccessRequestRejected( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // minerAddress + // ); + // } function getKnowledgeCollectionLocatorsWithPagination( bytes32 paranetId, @@ -1005,12 +1005,12 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // ParanetLib.MinersAccessPolicy minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); - // // Check if paranet is permisioned and if knowledge miner is whitelisted + // // Check if paranet is curated and if knowledge miner is whitelisted // if ( - // minersAccessPolicy == ParanetLib.MinersAccessPolicy.permisioned && + // minersAccessPolicy == ParanetLib.MinersAccessPolicy.CURATED && // !pr.isKnowledgeMinerRegistered(paranetId, msg.sender) // ) { - // revert ParanetLib.ParanetCuratedMinerDoesntExist(paranetId, msg.sender); + // revert ParanetLib.ParanetPermissionedMinerDoesntExist(paranetId, msg.sender); // } else if (minersAccessPolicy == ParanetLib.MinersAccessPolicy.OPEN) { // // Check if Knowledge Miner has profile // // If not: Create a profile @@ -1317,7 +1317,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; ParanetsRegistry pr = paranetsRegistry; uint8 minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); - // Check if paranet is permisioned and if knowledge miner is whitelisted + // Check if paranet is curated and if knowledge miner is whitelisted if (minersAccessPolicy == MINERS_ACCESS_POLICY_PERMISSIONED) { require(pr.isKnowledgeMinerRegistered(paranetId, msg.sender), "Miner is not registered"); // Should this be done in both cases why would OPEN have separeted logic ??? From 56ef8d88700da71e65576344008726b0e79f522a Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 20 Feb 2025 13:23:29 +0100 Subject: [PATCH 125/153] Fix incentive pool reward claiming --- abi/ParanetIncentivesPool.json | 5 +++++ contracts/paranets/ParanetIncentivesPool.sol | 2 ++ contracts/paranets/ParanetIncentivesPoolFactoryHelper.sol | 1 + 3 files changed, 8 insertions(+) diff --git a/abi/ParanetIncentivesPool.json b/abi/ParanetIncentivesPool.json index aa111f16..64fd11d0 100644 --- a/abi/ParanetIncentivesPool.json +++ b/abi/ParanetIncentivesPool.json @@ -16,6 +16,11 @@ "name": "paranetIncentivesPoolStorageAddress", "type": "address" }, + { + "internalType": "address", + "name": "paranetsRegistryAddress", + "type": "address" + }, { "internalType": "uint256", "name": "tracToTokenEmissionMultiplier", diff --git a/contracts/paranets/ParanetIncentivesPool.sol b/contracts/paranets/ParanetIncentivesPool.sol index db156e86..123fb15d 100644 --- a/contracts/paranets/ParanetIncentivesPool.sol +++ b/contracts/paranets/ParanetIncentivesPool.sol @@ -41,11 +41,13 @@ contract ParanetIncentivesPool is INamed, IVersioned, IParanetIncentivesPool { address hubAddress, address knowledgeMinersRegistryAddress, address paranetIncentivesPoolStorageAddress, + address paranetsRegistryAddress, uint256 tracToTokenEmissionMultiplier ) { hub = Hub(hubAddress); paranetKnowledgeMinersRegistry = ParanetKnowledgeMinersRegistry(knowledgeMinersRegistryAddress); paranetIncentivesPoolStorage = ParanetIncentivesPoolStorage(payable(paranetIncentivesPoolStorageAddress)); + paranetsRegistry = ParanetsRegistry(paranetsRegistryAddress); tokenEmissionMultipliers.push( ParanetLib.TokenEmissionMultiplier({ diff --git a/contracts/paranets/ParanetIncentivesPoolFactoryHelper.sol b/contracts/paranets/ParanetIncentivesPoolFactoryHelper.sol index 986aa5f3..8934a071 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactoryHelper.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactoryHelper.sol @@ -36,6 +36,7 @@ contract ParanetIncentivesPoolFactoryHelper is INamed, IVersioned, ContractStatu address(hub), hub.getContractAddress("ParanetKnowledgeMinersRegistry"), storageAddress, + hub.getContractAddress("ParanetsRegistry"), tracToTokenEmissionMultiplier ) ); From a41d0ffce8d366f5516d4f885d5b039c23a7edbd Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 20 Feb 2025 13:45:46 +0100 Subject: [PATCH 126/153] Fail to claim rewards when pool has no funds --- test/integration/Paranet.test.ts | 183 +++++++++++++++++++++++++++++-- 1 file changed, 173 insertions(+), 10 deletions(-) diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index 4f5c3efa..7d20d993 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -482,6 +482,7 @@ describe('@unit Paranet', () => { paranetOwner, publishingNodeIdentityId, receivingNodesIdentityIds, + paranetId, } = await setupParanet(kcCreator, publishingNode, receivingNodes, { Paranet, Profile, @@ -491,7 +492,7 @@ describe('@unit Paranet', () => { }); // 2. Deploy incentives pool - const tracToNeuroEmissionMultiplier = ethers.parseUnits('1', 12); // 1 NEURO per 1 TRAC + const tracToNeuroEmissionMultiplier = ethers.parseUnits('5', 12); // 5 NEURO per 1 TRAC const operatorRewardPercentage = 1000; // 10% const votersRewardPercentage = 2000; // 20% @@ -536,7 +537,6 @@ describe('@unit Paranet', () => { Token, }, ); - await Paranet.connect(kcCreator).submitKnowledgeCollection( paranetKCStorageContract, paranetKCTokenId, @@ -546,7 +546,7 @@ describe('@unit Paranet', () => { ); // 4. Fund the incentives pool with tokens - const fundAmount = ethers.parseUnits('1000', 18); // 1000 tokens + const fundAmount = ethers.parseUnits('1000', 12); // 1000 tokens await Token.connect(accounts[0]).mint(poolStorageAddress, fundAmount); // 5. Get pool contracts @@ -567,21 +567,91 @@ describe('@unit Paranet', () => { ); expect(await incentivesPoolStorage.totalVotersclaimedToken()).to.equal(0); + // 6.1. Check claim subfunctions - Not necessary for the claim flow + // Check all percentage getters + const operatorPercentage = + await incentivesPoolStorage.paranetOperatorRewardPercentage(); + const votersPercentage = + await incentivesPoolStorage.paranetIncentivizationProposalVotersRewardPercentage(); + + expect(operatorPercentage).to.equal(operatorRewardPercentage); // 10% + expect(votersPercentage).to.equal(votersRewardPercentage); // 20% + + // Calculate miners percentage (should be 70%) + const minersPercentage = + BigInt(10 ** 4) - operatorPercentage - votersPercentage; + expect(minersPercentage).to.equal(7000); // 70% + + expect(await incentivesPoolStorage.paranetId()).to.equal(paranetId); + + // Check effective token emission multiplier + const effectiveMultiplier = + await incentivesPool.getEffectiveTokenEmissionMultiplier( + await hre.ethers.provider + .getBlock('latest') + .then((b) => b!.timestamp), + ); + expect(effectiveMultiplier).to.equal(ethers.parseUnits('5', 12)); + + // Check unrewarded TRAC spent + const unrewardedTracSpent = + await ParanetKnowledgeMinersRegistry.getUnrewardedTracSpent( + kcCreator.address, + await incentivesPoolStorage.paranetId(), + ); + expect(unrewardedTracSpent).to.be.gt(10 ** 6); + + // Calculate expected reward manually + const expectedReward = + (((BigInt(unrewardedTracSpent) * effectiveMultiplier) / + BigInt(10 ** 18)) * + BigInt(minersPercentage)) / + BigInt(10 ** 4); + + // Compare with contract calculation + const actualReward = await incentivesPool + .connect(kcCreator) + .getTotalKnowledgeMinerIncentiveEstimation(); + expect(actualReward).to.equal(expectedReward); + expect(actualReward).to.be.gt(0); + + const claimableMinerRewardAmount = await incentivesPool + .connect(kcCreator) + .getClaimableKnowledgeMinerRewardAmount(); + + const newUnrewardedTracSpent = + claimableMinerRewardAmount == actualReward + ? 0 + : (BigInt(actualReward - claimableMinerRewardAmount) * + BigInt(10 ** 18)) / + BigInt(await incentivesPoolStorage.getClaimedMinerRewardsLength()); + + expect(newUnrewardedTracSpent).to.equal(0); + + expect( + await incentivesPoolStorage.getClaimedMinerRewardsLength(), + ).to.equal(0); + // 7. Claim miner rewards - const minerRewardEstimate = - await incentivesPool.getTotalKnowledgeMinerIncentiveEstimation(); + const minerRewardEstimate = await incentivesPool + .connect(kcCreator) + .getTotalKnowledgeMinerIncentiveEstimation(); expect(minerRewardEstimate).to.be.gt(0); - const claimableMinerReward = - await incentivesPool.getClaimableKnowledgeMinerRewardAmount(); + const claimableMinerReward = await incentivesPool + .connect(kcCreator) + .getClaimableKnowledgeMinerRewardAmount(); + await incentivesPool .connect(kcCreator) .claimKnowledgeMinerReward(claimableMinerReward); // 8. Verify miner rewards claimed correctly - expect(await incentivesPoolStorage.totalMinersclaimedToken()).to.equal( - claimableMinerReward, - ); + expect( + await incentivesPoolStorage + .connect(kcCreator) + .totalMinersclaimedToken(), + ).to.equal(claimableMinerReward); const minerProfile = await incentivesPoolStorage.getClaimedMinerRewardsAtIndex( await incentivesPoolStorage.claimedMinerRewardsIndexes( @@ -620,6 +690,99 @@ describe('@unit Paranet', () => { expectedRemainingBalance, ); }); + + it('Should fail to claim rewards when pool has no funds', async () => { + // 1. Setup paranet first + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetOwner, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + publishingNodeIdentityId, + receivingNodesIdentityIds, + paranetId, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // Deploy pool without funding it + const tx = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ethers.parseUnits('1', 12), // 1 NEURO per 1 TRAC + 1000, // 10% operatorRewardPercentage + 2000, // 20% votersRewardPercentage + 'TestPool', + await Token.getAddress(), + ); + + const receipt = await tx.wait(); + const event = receipt!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolDeployed', + ).topicHash, + ) as EventLog; + + const incentivesPool = await hre.ethers.getContractAt( + 'ParanetIncentivesPool', + event?.args[4], + ); + + // Create and submit knowledge collections to paranet + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection, + Token, + }, + ); + + await Paranet.connect(kcCreator).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ); + + expect( + await ParanetsRegistry.isKnowledgeMinerRegistered( + paranetId, + kcCreator.address, + ), + ).to.be.equal(true); + + // Try to claim miner rewards + await expect( + incentivesPool.connect(kcCreator).claimKnowledgeMinerReward(0), + ).to.be.revertedWithCustomError(incentivesPool, 'NoRewardAvailable'); + + // Try to claim operator rewards + await expect( + incentivesPool.connect(paranetOwner).claimParanetOperatorReward(), + ).to.be.revertedWithCustomError(incentivesPool, 'NoRewardAvailable'); + }); }); describe('Submit Knowledge Collection to Paranet', () => { From 4875223820769603df9dc2088a399bd7d70d5a8f Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 20 Feb 2025 15:38:14 +0100 Subject: [PATCH 127/153] Add validation to deployIncentivesPool --- contracts/paranets/ParanetIncentivesPoolFactory.sol | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index 97b5459c..3fe3f01e 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -80,8 +80,10 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn ) external onlyKnowledgeAssetOwner(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId) { bytes32 paranetId = _computeParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); ParanetsRegistry pr = paranetsRegistry; - require(pr.paranetExists(paranetId)); - require(!pr.hasIncentivesPoolByName(paranetId, incentivesPoolName)); + require(pr.paranetExists(paranetId), "Paranet does not exist"); + require(tracToTokenEmissionMultiplier > 0, "Emission multiplier must be greater than 0"); + require(bytes(incentivesPoolName).length > 0, "Pool name cannot be empty"); + require(!pr.hasIncentivesPoolByName(paranetId, incentivesPoolName), "Pool name already exists"); ParanetIncentivesPoolStorage storage_ = new ParanetIncentivesPoolStorage( address(hub), From d670d5b7d362d8c5cba835d6c2ecda725da94264 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 20 Feb 2025 15:38:39 +0100 Subject: [PATCH 128/153] Fix hasIncentivesPoolByName --- contracts/storage/paranets/ParanetsRegistry.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/storage/paranets/ParanetsRegistry.sol b/contracts/storage/paranets/ParanetsRegistry.sol index 2302a102..50169a29 100644 --- a/contracts/storage/paranets/ParanetsRegistry.sol +++ b/contracts/storage/paranets/ParanetsRegistry.sol @@ -297,7 +297,8 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { return false; } - return paranet.incentivesPools[index].storageAddr != address(0); + return + keccak256(abi.encodePacked(paranet.incentivesPools[index].name)) == keccak256(abi.encodePacked(poolName)); } function hasIncentivesPoolByStorageAddress(bytes32 paranetId, address storageAddr) external view returns (bool) { From 333a0521316e61ae46046fee720b825f01af014c Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 20 Feb 2025 15:44:38 +0100 Subject: [PATCH 129/153] Add more incentives pool tests --- test/integration/Paranet.test.ts | 390 +++++++++++++++++++++++++++++++ 1 file changed, 390 insertions(+) diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index 7d20d993..e4b265e1 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -466,6 +466,176 @@ describe('@unit Paranet', () => { ).to.equal(event?.args[4]); expect(await incentivesPoolStorage.paranetId()).to.equal(paranetId); }); + + it('Should handle multiple incentives pools for same paranet', async () => { + // 1. Setup paranet first + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetId, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Deploy first incentives pool + const tx1 = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ethers.parseUnits('1', 12), // 1 NEURO per 1 TRAC + 1000, // 10% operator + 2000, // 20% voters + 'Pool1', + await Token.getAddress(), + ); + + const receipt1 = await tx1.wait(); + const event1 = receipt1!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolDeployed', + ).topicHash, + ) as EventLog; + + // 3. Deploy second incentives pool with different parameters + const tx2 = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ethers.parseUnits('2', 12), // 2 NEURO per 1 TRAC + 1500, // 15% operator + 2500, // 25% voters + 'Pool2', + await Token.getAddress(), + ); + + const receipt2 = await tx2.wait(); + const event2 = receipt2!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolDeployed', + ).topicHash, + ) as EventLog; + + // 4. Verify both pools exist and have correct parameters + const pool1 = await ParanetsRegistry.getIncentivesPoolByPoolName( + paranetId, + 'Pool1', + ); + const pool2 = await ParanetsRegistry.getIncentivesPoolByPoolName( + paranetId, + 'Pool2', + ); + + expect(pool1.storageAddr).to.equal(event1?.args[3]); + expect(pool2.storageAddr).to.equal(event2?.args[3]); + expect(pool1.storageAddr).to.not.equal(pool2.storageAddr); + + // 5. Verify pool parameters through storage contracts + const pool1Storage = await hre.ethers.getContractAt( + 'ParanetIncentivesPoolStorage', + event1?.args[3], + ); + const pool2Storage = await hre.ethers.getContractAt( + 'ParanetIncentivesPoolStorage', + event2?.args[3], + ); + + expect(await pool1Storage.paranetId()).to.equal(paranetId); + expect(await pool2Storage.paranetId()).to.equal(paranetId); + }); + + it('Should fail to deploy incentives pool with invalid parameters', async () => { + // 1. Setup paranet + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Try to deploy with operator + voters percentage > 100% + await expect( + ParanetIncentivesPoolFactory.connect(paranetOwner).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ethers.parseUnits('1', 12), + 5000, // 50% operator + 6000, // 60% voters (total 110%) + 'InvalidPool', + await Token.getAddress(), + ), + ).to.be.revertedWith('Invalid rewards ratio'); + + // 3. Try to deploy with zero emission multiplier + await expect( + ParanetIncentivesPoolFactory.connect(paranetOwner).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + 0, // zero multiplier + 1000, + 2000, + 'InvalidPool', + await Token.getAddress(), + ), + ).to.be.revertedWith('Emission multiplier must be greater than 0'); + + // 4. Try to deploy with empty pool name + await expect( + ParanetIncentivesPoolFactory.connect(paranetOwner).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ethers.parseUnits('1', 12), + 1000, + 2000, + '', // empty name + await Token.getAddress(), + ), + ).to.be.revertedWith('Pool name cannot be empty'); + + // 5. Try to deploy with invalid paranet + await expect( + ParanetIncentivesPoolFactory.connect(paranetOwner).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId + 1, // invalid paranet token id + ethers.parseUnits('1', 12), + 1000, + 2000, + 'InvalidPool', // empty name + await Token.getAddress(), + ), + ).to.be.revertedWith('Paranet does not exist'); + }); }); describe('Paranet Incentives Pool Rewards', () => { @@ -773,16 +943,236 @@ describe('@unit Paranet', () => { ), ).to.be.equal(true); + // Verify rewards are calculated for the miner + const minerRewardEstimate = await incentivesPool + .connect(kcCreator) + .getTotalKnowledgeMinerIncentiveEstimation(); + expect(minerRewardEstimate).to.be.gt(0); + + const claimableMinerReward = await incentivesPool + .connect(kcCreator) + .getClaimableKnowledgeMinerRewardAmount(); + expect(claimableMinerReward).to.equal(0); + // Try to claim miner rewards await expect( incentivesPool.connect(kcCreator).claimKnowledgeMinerReward(0), ).to.be.revertedWithCustomError(incentivesPool, 'NoRewardAvailable'); + // Verify rewards are calculated for the operator + const operatorRewardEstimate = await incentivesPool + .connect(paranetOwner) + .getTotalParanetOperatorIncentiveEstimation(); + expect(operatorRewardEstimate).to.be.gt(0); + + const claimableOperatorReward = + await incentivesPool.getClaimableParanetOperatorRewardAmount(); + expect(claimableOperatorReward).to.equal(0); + // Try to claim operator rewards await expect( incentivesPool.connect(paranetOwner).claimParanetOperatorReward(), ).to.be.revertedWithCustomError(incentivesPool, 'NoRewardAvailable'); }); + + it('Should handle incentives pool with zero rewards available', async () => { + // 1. Setup paranet and create KC + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Deploy incentives pool (but don't fund it) + const tx = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ethers.parseUnits('1', 12), + 1000, + 2000, + 'EmptyPool', + await Token.getAddress(), + ); + + const receipt = await tx.wait(); + const event = receipt!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolDeployed', + ).topicHash, + ) as EventLog; + + // 3. Create and submit KC to generate some rewards + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection, + Token, + }, + ); + + await Paranet.connect(kcCreator).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ); + + // 4. Try to claim rewards from empty pool + const incentivesPool = await hre.ethers.getContractAt( + 'ParanetIncentivesPool', + event?.args[4], + ); + + // Verify rewards are calculated but not claimable + const minerRewardEstimate = await incentivesPool + .connect(kcCreator) + .getTotalKnowledgeMinerIncentiveEstimation(); + expect(minerRewardEstimate).to.be.gt(0); + + const claimableMinerReward = await incentivesPool + .connect(kcCreator) + .getClaimableKnowledgeMinerRewardAmount(); + expect(claimableMinerReward).to.equal(0); + + // Try to claim - should fail + await expect( + incentivesPool.connect(kcCreator).claimKnowledgeMinerReward(0), + ).to.be.revertedWithCustomError(incentivesPool, 'NoRewardAvailable'); + }); + + it('Should handle incentives pool with partial funding', async () => { + // 1. Setup paranet and create KC + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Deploy incentives pool + const tx = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ethers.parseUnits('1', 12), + 1000, + 2000, + 'PartialPool', + await Token.getAddress(), + ); + + const receipt = await tx.wait(); + const event = receipt!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolDeployed', + ).topicHash, + ) as EventLog; + + // 3. Create and submit KC to generate rewards + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection, + Token, + }, + ); + + await Paranet.connect(kcCreator).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ); + + const incentivesPool = await hre.ethers.getContractAt( + 'ParanetIncentivesPool', + event?.args[4], + ); + + // 4. Fund pool with partial miner reward amount + const minerRewardEstimate = await incentivesPool + .connect(kcCreator) + .getTotalKnowledgeMinerIncentiveEstimation(); + const partialFunding = minerRewardEstimate / BigInt(2); // Fund 50% of estimated rewards + + await Token.connect(accounts[0]).mint(event?.args[3], partialFunding); + + // 5. Verify partial rewards are claimable + const claimableMinerReward = await incentivesPool + .connect(kcCreator) + .getClaimableKnowledgeMinerRewardAmount(); + expect(claimableMinerReward).to.be.lessThanOrEqual(partialFunding); + + // 6. Claim partial rewards + await incentivesPool + .connect(kcCreator) + .claimKnowledgeMinerReward(claimableMinerReward); + + // 7. Verify remaining rewards are still tracked but not claimable + const remainingEstimate = await incentivesPool + .connect(kcCreator) + .getTotalKnowledgeMinerIncentiveEstimation(); + expect(remainingEstimate).to.be.lessThanOrEqual( + minerRewardEstimate - partialFunding, + ); + + const remainingClaimable = await incentivesPool + .connect(kcCreator) + .getClaimableKnowledgeMinerRewardAmount(); + expect(remainingClaimable).to.equal(0); + }); }); describe('Submit Knowledge Collection to Paranet', () => { From c5dd07bdf3de02e4daf5f24c76d91bb38fa0937f Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 21 Feb 2025 10:12:26 +0100 Subject: [PATCH 130/153] Fix getVoter require --- contracts/paranets/ParanetIncentivesPoolStorage.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/paranets/ParanetIncentivesPoolStorage.sol b/contracts/paranets/ParanetIncentivesPoolStorage.sol index 1173beeb..52a78327 100644 --- a/contracts/paranets/ParanetIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetIncentivesPoolStorage.sol @@ -264,7 +264,7 @@ contract ParanetIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInit require(voters.length > 0, "Address is not a registered voter"); uint256 index = votersIndexes[voterAddress]; - require(index >= voters.length || voters[index].addr != voterAddress, "Address is not a registered voter"); + require(index < voters.length && voters[index].addr == voterAddress, "Address is not a registered voter"); return voters[index]; } From 211e973af39dda16f99fc7ed19274b7c761fc4d2 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 21 Feb 2025 11:29:33 +0100 Subject: [PATCH 131/153] Add 'Should handle voter management correctly' test --- test/integration/Paranet.test.ts | 98 ++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index e4b265e1..e4d01565 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -636,6 +636,104 @@ describe('@unit Paranet', () => { ), ).to.be.revertedWith('Paranet does not exist'); }); + + it('Should handle voter management correctly', async () => { + // 1. Setup paranet and pool + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // Deploy pool + const tx = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ethers.parseUnits('1', 12), + 1000, + 2000, + 'TestPool', + await Token.getAddress(), + ); + + const receipt = await tx.wait(); + const event = receipt!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolDeployed', + ).topicHash, + ) as EventLog; + + const incentivesPoolStorage = await hre.ethers.getContractAt( + 'ParanetIncentivesPoolStorage', + event?.args[3], + ); + + // Get registrar + const registrar = await incentivesPoolStorage.votersRegistrar(); + const registrarSigner = await hre.ethers.getSigner(registrar); + + // Add voters + const voters = [ + { addr: accounts[5].address, weight: 5000 }, // 50% + { addr: accounts[6].address, weight: 3000 }, // 30% + { addr: accounts[7].address, weight: 2000 }, // 20% + ]; + + await incentivesPoolStorage.connect(registrarSigner).addVoters(voters); + + // Verify voters were added correctly + expect(await incentivesPoolStorage.getVotersCount()).to.equal(3); + expect(await incentivesPoolStorage.cumulativeVotersWeight()).to.equal( + 10000, + ); + + // Update voter weight + await incentivesPoolStorage + .connect(registrarSigner) + .updateVoterWeight(accounts[5].address, 4000); + + const updatedVoter = await incentivesPoolStorage.getVoter( + accounts[5].address, + ); + expect(updatedVoter.weight).to.equal(4000); + expect(await incentivesPoolStorage.cumulativeVotersWeight()).to.equal( + 9000, + ); + + // Remove voter + await incentivesPoolStorage + .connect(registrarSigner) + .removeVoter(accounts[6].address); + + expect(await incentivesPoolStorage.getVotersCount()).to.equal(2); + expect(await incentivesPoolStorage.cumulativeVotersWeight()).to.equal( + 6000, + ); + + // Try to add voter that would exceed max weight + const overweightVoter = [{ addr: accounts[8].address, weight: 5000 }]; + await expect( + incentivesPoolStorage + .connect(registrarSigner) + .addVoters(overweightVoter), + ).to.be.revertedWith('Cumulative weight is too big'); + }); }); describe('Paranet Incentives Pool Rewards', () => { From 1bc36ef926691b0bdeffbed0bec2ee26f917fe3e Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 21 Feb 2025 12:17:52 +0100 Subject: [PATCH 132/153] Fix redeployIncentivesPool function --- contracts/paranets/ParanetIncentivesPoolFactory.sol | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index 3fe3f01e..768955be 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -12,6 +12,7 @@ import {ContractStatus} from "../abstract/ContractStatus.sol"; import {IInitializable} from "../interfaces/IInitializable.sol"; import {INamed} from "../interfaces/INamed.sol"; import {IVersioned} from "../interfaces/IVersioned.sol"; +import "hardhat/console.sol"; contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IInitializable { event ParanetIncentivesPoolDeployed( @@ -122,11 +123,14 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn bytes32 paranetId = _computeParanetId(paranetKCStorageContract, paranetKCTokenId, paranetKATokenId); ParanetsRegistry pr = paranetsRegistry; - require(pr.paranetExists(paranetId)); - require(!pr.hasIncentivesPoolByStorageAddress(paranetId, storageAddress)); + require(pr.paranetExists(paranetId), "Paranet does not exist"); + require( + pr.hasIncentivesPoolByStorageAddress(paranetId, storageAddress), + "Cannot redeploy an incentives pool that does not exist" + ); ParanetIncentivesPoolStorage storage_ = ParanetIncentivesPoolStorage(payable(storageAddress)); - require(storage_.paranetId() == paranetId); + require(storage_.paranetId() == paranetId, "Storage contract does not point to the paranet you provided"); address oldPoolAddress = storage_.paranetIncentivesPoolAddress(); uint256 tracToTokenEmissionMultiplier = ParanetIncentivesPool(oldPoolAddress) @@ -137,7 +141,6 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn tracToTokenEmissionMultiplier, address(storage_) ); - emit ParanetIncentivesPoolRedeployed( paranetKCStorageContract, paranetKCTokenId, From 357e4c458bd5041bb70f1a6225ebe06444fcdf50 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 21 Feb 2025 12:18:55 +0100 Subject: [PATCH 133/153] Remove unnecessary imports --- contracts/paranets/ParanetIncentivesPoolFactory.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index 768955be..5bd5f445 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -12,7 +12,6 @@ import {ContractStatus} from "../abstract/ContractStatus.sol"; import {IInitializable} from "../interfaces/IInitializable.sol"; import {INamed} from "../interfaces/INamed.sol"; import {IVersioned} from "../interfaces/IVersioned.sol"; -import "hardhat/console.sol"; contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IInitializable { event ParanetIncentivesPoolDeployed( From d78456d4061618930badd2b20d5210bd93e090f0 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 21 Feb 2025 12:25:14 +0100 Subject: [PATCH 134/153] Add 'Should handle incentives pool redeployment' test --- test/integration/Paranet.test.ts | 111 ++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index e4d01565..e6bc5802 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -1,7 +1,7 @@ import { randomBytes } from 'crypto'; import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; -import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { loadFixture, time } from '@nomicfoundation/hardhat-network-helpers'; import { expect } from 'chai'; import { ethers, EventLog } from 'ethers'; import hre from 'hardhat'; @@ -734,6 +734,115 @@ describe('@unit Paranet', () => { .addVoters(overweightVoter), ).to.be.revertedWith('Cumulative weight is too big'); }); + + it('Should handle incentives pool redeployment', async () => { + // 1. Setup paranet and initial pool + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner, + paranetId, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + const originalEmissionMultiplier = ethers.parseUnits('1', 12); + + // Deploy initial pool + const tx = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + originalEmissionMultiplier, + 1000, + 2000, + 'TestPool', + await Token.getAddress(), + ); + + const receipt = await tx.wait(); + const event = receipt!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolDeployed', + ).topicHash, + ) as EventLog; + + const originalStorageAddress = event?.args[3]; + const originalPoolAddress = event?.args[4]; + + // Fund the pool + const fundingAmount = ethers.parseUnits('1000', 12); + await Token.connect(accounts[0]).mint( + originalStorageAddress, + fundingAmount, + ); + + // Redeploy pool + const redeployTx = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).redeployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + originalStorageAddress, + ); + + const redeployReceipt = await redeployTx.wait(); + const redeployEvent = redeployReceipt!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolRedeployed', + ).topicHash, + ) as EventLog; + + // Verify new pool address is different + const newPoolAddress = redeployEvent?.args[4]; + expect(newPoolAddress).to.not.equal(originalPoolAddress); + + // Verify storage address remains the same + expect(redeployEvent?.args[3]).to.equal(originalStorageAddress); + + // Verify storage contract points to the same paranet + const incentivesPoolStorage = await hre.ethers.getContractAt( + 'ParanetIncentivesPoolStorage', + originalStorageAddress, + ); + expect(await incentivesPoolStorage.paranetId()).to.equal(paranetId); + + // Verify storage contract points to the new pool and not the old one + expect( + await incentivesPoolStorage.paranetIncentivesPoolAddress(), + ).to.equal(newPoolAddress); + expect( + await incentivesPoolStorage.paranetIncentivesPoolAddress(), + ).to.not.equal(originalPoolAddress); + + // Verify funds are preserved + expect(await incentivesPoolStorage.getBalance()).to.equal(fundingAmount); + + // Verify new pool has the same emission multiplier + const newPool = await hre.ethers.getContractAt( + 'ParanetIncentivesPool', + newPoolAddress, + ); + expect( + await newPool.getEffectiveTokenEmissionMultiplier(await time.latest()), + ).to.equal(originalEmissionMultiplier); + }); }); describe('Paranet Incentives Pool Rewards', () => { From c64083934ea1d2ddfeeda084f58b30b8ff949057 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 21 Feb 2025 12:33:21 +0100 Subject: [PATCH 135/153] Add missing revert messages to require statements --- contracts/paranets/ParanetIncentivesPoolFactory.sol | 10 ++++++++-- contracts/tokens/ERC1155Delta.sol | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/contracts/paranets/ParanetIncentivesPoolFactory.sol b/contracts/paranets/ParanetIncentivesPoolFactory.sol index 5bd5f445..7dce7876 100644 --- a/contracts/paranets/ParanetIncentivesPoolFactory.sol +++ b/contracts/paranets/ParanetIncentivesPoolFactory.sol @@ -165,7 +165,10 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn uint256 knowledgeCollectionId, uint256 knowledgeAssetId ) internal view { - require(hub.isAssetStorage(knowledgeCollectionStorageContractAddress)); + require( + hub.isAssetStorage(knowledgeCollectionStorageContractAddress), + "Knowledge collection storage contract with the provided address is not registered" + ); KnowledgeCollectionStorage knowledgeCollectionStorage = KnowledgeCollectionStorage( knowledgeCollectionStorageContractAddress @@ -175,6 +178,9 @@ contract ParanetIncentivesPoolFactory is INamed, IVersioned, ContractStatus, IIn knowledgeCollectionStorage.knowledgeCollectionMaxSize() + knowledgeAssetId; - require(knowledgeCollectionStorage.balanceOf(msg.sender, startTokenId, startTokenId + 1) == 1); + require( + knowledgeCollectionStorage.balanceOf(msg.sender, startTokenId, startTokenId + 1) == 1, + "Caller is not the owner of the knowledge asset" + ); } } diff --git a/contracts/tokens/ERC1155Delta.sol b/contracts/tokens/ERC1155Delta.sol index efaa2184..ab46c156 100644 --- a/contracts/tokens/ERC1155Delta.sol +++ b/contracts/tokens/ERC1155Delta.sol @@ -325,7 +325,7 @@ contract ERC1155Delta is Context, ERC165, IERC1155, IERC1155MetadataURI, IERC115 uint256 startTokenId = _nextTokenId(); unchecked { - require(type(uint256).max - amount >= startTokenId); + require(type(uint256).max - amount >= startTokenId, "Minting more tokens than the maximum allowed"); for (uint256 i = 0; i < amount; i++) { ids[i] = startTokenId + i; amounts[i] = 1; From 6e84c7b010e60464ebc31dd1087ad5d54b806a47 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 21 Feb 2025 13:36:27 +0100 Subject: [PATCH 136/153] Add 'Should handle token emission multiplier updates correctly' test --- test/integration/Paranet.test.ts | 98 ++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index e6bc5802..97d42834 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -843,6 +843,104 @@ describe('@unit Paranet', () => { await newPool.getEffectiveTokenEmissionMultiplier(await time.latest()), ).to.equal(originalEmissionMultiplier); }); + + it('Should handle token emission multiplier updates correctly', async () => { + // 1. Setup paranet and pool + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + const initialEmissionMultiplier = ethers.parseUnits('1', 12); + + // Deploy pool + const tx = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + initialEmissionMultiplier, + 1000, // 10% operator + 2000, // 20% voters + 'TestPool', + await Token.getAddress(), + ); + + const receipt = await tx.wait(); + const event = receipt!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolDeployed', + ).topicHash, + ) as EventLog; + + const incentivesPool = await hre.ethers.getContractAt( + 'ParanetIncentivesPool', + event?.args[4], + ); + const incentivesPoolStorage = await hre.ethers.getContractAt( + 'ParanetIncentivesPoolStorage', + event?.args[3], + ); + + // Get registrar (hub owner) + const registrar = await incentivesPoolStorage.votersRegistrar(); + const registrarSigner = await hre.ethers.getSigner(registrar); + + // Initiate multiplier update + const newMultiplier = ethers.parseUnits('2', 12); // 2 NEURO per 1 TRAC + await expect( + incentivesPool + .connect(registrarSigner) + .initiateTokenEmissionMultiplierUpdate(newMultiplier), + ) + .to.emit(incentivesPool, 'TokenEmissionMultiplierUpdateInitiated') + .withArgs( + initialEmissionMultiplier, + newMultiplier, + (await time.latest()) + 7 * 24 * 3600 + 1, // Add 1 to account for the block being mined + ); + + // Try to finalize too early - should fail + await expect( + incentivesPool + .connect(registrarSigner) + .finalizeTokenEmissionMultiplierUpdate(), + ).to.be.revertedWith('Delay period not yet passed'); + + // Move time forward 7 days + await time.increase(7 * 24 * 3600); + + // Finalize update + await expect( + incentivesPool + .connect(registrarSigner) + .finalizeTokenEmissionMultiplierUpdate(), + ) + .to.emit(incentivesPool, 'TokenEmissionMultiplierUpdateFinalized') + .withArgs(initialEmissionMultiplier, newMultiplier); + + // Verify new multiplier is active + expect( + await incentivesPool.getEffectiveTokenEmissionMultiplier( + await time.latest(), + ), + ).to.equal(newMultiplier); + }); }); describe('Paranet Incentives Pool Rewards', () => { From e812e18abbd213573437572f91c0a49bb2159bbc Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 21 Feb 2025 15:05:05 +0100 Subject: [PATCH 137/153] Fix naming --- contracts/paranets/Paranet.sol | 6 ++-- .../storage/paranets/ParanetsRegistry.sol | 29 ++++++++++--------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index 7a5a63f4..a5321d52 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -1005,9 +1005,9 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // ParanetLib.MinersAccessPolicy minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); - // // Check if paranet is curated and if knowledge miner is whitelisted + // // Check if paranet is permissioned and if knowledge miner is whitelisted // if ( - // minersAccessPolicy == ParanetLib.MinersAccessPolicy.CURATED && + // minersAccessPolicy == ParanetLib.MinersAccessPolicy.permissioned && // !pr.isKnowledgeMinerRegistered(paranetId, msg.sender) // ) { // revert ParanetLib.ParanetPermissionedMinerDoesntExist(paranetId, msg.sender); @@ -1317,7 +1317,7 @@ contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { ParanetKnowledgeMinersRegistry pkmr = paranetKnowledgeMinersRegistry; ParanetsRegistry pr = paranetsRegistry; uint8 minersAccessPolicy = pr.getMinersAccessPolicy(paranetId); - // Check if paranet is curated and if knowledge miner is whitelisted + // Check if paranet is permissioned and if knowledge miner is whitelisted if (minersAccessPolicy == MINERS_ACCESS_POLICY_PERMISSIONED) { require(pr.isKnowledgeMinerRegistered(paranetId, msg.sender), "Miner is not registered"); // Should this be done in both cases why would OPEN have separeted logic ??? diff --git a/contracts/storage/paranets/ParanetsRegistry.sol b/contracts/storage/paranets/ParanetsRegistry.sol index 7270e23d..f69cc0ff 100644 --- a/contracts/storage/paranets/ParanetsRegistry.sol +++ b/contracts/storage/paranets/ParanetsRegistry.sol @@ -213,32 +213,35 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { } function addPermissionedNode(bytes32 paranetId, uint72 identityId, bytes calldata nodeId) external onlyContracts { - paranets[paranetId].curatedNodesIndexes[identityId] = paranets[paranetId].curatedNodes.length; - paranets[paranetId].curatedNodes.push(ParanetLib.Node({identityId: identityId, nodeId: nodeId})); + paranets[paranetId].permissionedNodesIndexes[identityId] = paranets[paranetId].permissionedNodes.length; + paranets[paranetId].permissionedNodes.push(ParanetLib.Node({identityId: identityId, nodeId: nodeId})); } function removePermissionedNode(bytes32 paranetId, uint72 identityId) external onlyContracts { - paranets[paranetId].curatedNodes[paranets[paranetId].curatedNodesIndexes[identityId]] = paranets[paranetId] - .curatedNodes[paranets[paranetId].curatedNodes.length - 1]; - paranets[paranetId].curatedNodesIndexes[ - paranets[paranetId].curatedNodes[paranets[paranetId].curatedNodes.length - 1].identityId - ] = paranets[paranetId].curatedNodesIndexes[identityId]; + paranets[paranetId].permissionedNodes[paranets[paranetId].permissionedNodesIndexes[identityId]] = paranets[ + paranetId + ].permissionedNodes[paranets[paranetId].permissionedNodes.length - 1]; + paranets[paranetId].permissionedNodesIndexes[ + paranets[paranetId].permissionedNodes[paranets[paranetId].permissionedNodes.length - 1].identityId + ] = paranets[paranetId].permissionedNodesIndexes[identityId]; - delete paranets[paranetId].curatedNodesIndexes[identityId]; - paranets[paranetId].curatedNodes.pop(); + delete paranets[paranetId].permissionedNodesIndexes[identityId]; + paranets[paranetId].permissionedNodes.pop(); } function getPermissionedNodes(bytes32 paranetId) external view returns (ParanetLib.Node[] memory) { - return paranets[paranetId].curatedNodes; + return paranets[paranetId].permissionedNodes; } function getPermissionedNodesCount(bytes32 paranetId) external view returns (uint256) { - return paranets[paranetId].curatedNodes.length; + return paranets[paranetId].permissionedNodes.length; } function isPermissionedNode(bytes32 paranetId, uint72 identityId) external view returns (bool) { - return (paranets[paranetId].curatedNodes.length != 0 && - paranets[paranetId].curatedNodes[paranets[paranetId].curatedNodesIndexes[identityId]].identityId == + return (paranets[paranetId].permissionedNodes.length != 0 && + paranets[paranetId] + .permissionedNodes[paranets[paranetId].permissionedNodesIndexes[identityId]] + .identityId == identityId); } From d0050a42fb4653e16aa2fd06fc8f722beb56dc00 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 21 Feb 2025 15:14:46 +0100 Subject: [PATCH 138/153] Fix hasIncentivesPoolByStorageAddress function --- contracts/storage/paranets/ParanetsRegistry.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/storage/paranets/ParanetsRegistry.sol b/contracts/storage/paranets/ParanetsRegistry.sol index 82139d59..beb1b6dd 100644 --- a/contracts/storage/paranets/ParanetsRegistry.sol +++ b/contracts/storage/paranets/ParanetsRegistry.sol @@ -317,7 +317,9 @@ contract ParanetsRegistry is INamed, IVersioned, HubDependent { return false; } - return paranet.incentivesPools[index].storageAddr != address(0); + address incentivesPoolStorageAddress = paranet.incentivesPools[index].storageAddr; + + return incentivesPoolStorageAddress != address(0) && incentivesPoolStorageAddress == storageAddr; } function getCumulativeKnowledgeValue(bytes32 paranetId) external view returns (uint96) { From 1405a3e9748ff1ae705b9b7d6283443caaf73505 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 21 Feb 2025 15:14:54 +0100 Subject: [PATCH 139/153] Add more checks to existing tests --- test/integration/Paranet.test.ts | 140 +++++++++++++++++++++++++++++-- 1 file changed, 135 insertions(+), 5 deletions(-) diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index 97d42834..3e228cd9 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -23,6 +23,7 @@ import { ParanetIncentivesPoolFactoryHelper, ParanetStagingRegistry, IdentityStorage, + HubLib, } from '../../typechain'; import { ACCESS_POLICIES } from '../helpers/constants'; import { @@ -54,6 +55,7 @@ type ParanetFixture = { EpochStorage: EpochStorage; ParanetStagingRegistry: ParanetStagingRegistry; IdentityStorage: IdentityStorage; + HubLib: HubLib; }; describe('@unit Paranet', () => { @@ -72,6 +74,8 @@ describe('@unit Paranet', () => { let EpochStorage: EpochStorage; let ParanetStagingRegistry: ParanetStagingRegistry; let IdentityStorage: IdentityStorage; + let HubLib: HubLib; + // Deploy all contracts, set the HubOwner and necessary accounts. Returns the ParanetFixture async function deployParanetFixture(): Promise { await hre.deployments.fixture([ @@ -139,6 +143,15 @@ describe('@unit Paranet', () => { IdentityStorage = await hre.ethers.getContract('IdentityStorage'); + const hubLibDeployment = await hre.deployments.deploy('HubLib', { + from: accounts[0].address, + log: true, + }); + HubLib = await hre.ethers.getContract( + 'HubLib', + hubLibDeployment.address, + ); + return { accounts, Paranet, @@ -155,6 +168,7 @@ describe('@unit Paranet', () => { EpochStorage, ParanetStagingRegistry, IdentityStorage, + HubLib, }; } @@ -174,6 +188,7 @@ describe('@unit Paranet', () => { Profile, Token, ParanetStagingRegistry, + HubLib, } = await loadFixture(deployParanetFixture)); }); @@ -559,6 +574,8 @@ describe('@unit Paranet', () => { expect(await pool1Storage.paranetId()).to.equal(paranetId); expect(await pool2Storage.paranetId()).to.equal(paranetId); + + // TODO: Fund the pools and check rewards }); it('Should fail to deploy incentives pool with invalid parameters', async () => { @@ -684,6 +701,11 @@ describe('@unit Paranet', () => { event?.args[3], ); + const incentivesPool = await hre.ethers.getContractAt( + 'ParanetIncentivesPool', + event?.args[4], + ); + // Get registrar const registrar = await incentivesPoolStorage.votersRegistrar(); const registrarSigner = await hre.ethers.getSigner(registrar); @@ -733,6 +755,34 @@ describe('@unit Paranet', () => { .connect(registrarSigner) .addVoters(overweightVoter), ).to.be.revertedWith('Cumulative weight is too big'); + + // Additional voter management checks + // Try to update non-existent voter + await expect( + incentivesPoolStorage + .connect(registrarSigner) + .updateVoterWeight(accounts[9].address, 1000), + ).to.be.revertedWith('Voter not found'); + + // Try to remove non-existent voter + await expect( + incentivesPoolStorage + .connect(registrarSigner) + .removeVoter(accounts[9].address), + ).to.be.revertedWith('Voter not found'); + + // Check voter rewards calculation + const voterReward = + await incentivesPool.getTotalProposalVoterIncentiveEstimation(); + expect(voterReward).to.be.eq(0); // storage contract was not funded + + // Verify voter weight affects reward calculation + const voter = await incentivesPoolStorage.getVoter(accounts[5].address); + const voterShare = (voterReward * BigInt(voter.weight)) / BigInt(10000); + const claimableVoterReward = await incentivesPool + .connect(accounts[5]) + .getClaimableProposalVoterRewardAmount(); + expect(claimableVoterReward).to.equal(voterShare); }); it('Should handle incentives pool redeployment', async () => { @@ -790,6 +840,15 @@ describe('@unit Paranet', () => { fundingAmount, ); + const initialPool = await hre.ethers.getContractAt( + 'ParanetIncentivesPool', + originalPoolAddress, + ); + + const minerRewardBeforeRedeploy = await initialPool + .connect(kcCreator) + .getTotalKnowledgeMinerIncentiveEstimation(); + // Redeploy pool const redeployTx = await ParanetIncentivesPoolFactory.connect( paranetOwner, @@ -842,6 +901,33 @@ describe('@unit Paranet', () => { expect( await newPool.getEffectiveTokenEmissionMultiplier(await time.latest()), ).to.equal(originalEmissionMultiplier); + + const minerRewardAfterRedeploy = await newPool + .connect(kcCreator) + .getTotalKnowledgeMinerIncentiveEstimation(); + + expect(minerRewardAfterRedeploy).to.equal(minerRewardBeforeRedeploy); + + // Try to redeploy non-existent pool + await expect( + ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).redeployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + '0x0000000000000000000000000000000000000000', + ), + ).to.be.revertedWith( + 'Cannot redeploy an incentives pool that does not exist', + ); + + // Verify storage contract permissions + await expect( + incentivesPoolStorage + .connect(paranetOwner) + .setParanetIncentivesPool(ethers.ZeroAddress), + ).to.be.revertedWithCustomError(HubLib, 'UnauthorizedAccess'); }); it('Should handle token emission multiplier updates correctly', async () => { @@ -902,16 +988,16 @@ describe('@unit Paranet', () => { const registrarSigner = await hre.ethers.getSigner(registrar); // Initiate multiplier update - const newMultiplier = ethers.parseUnits('2', 12); // 2 NEURO per 1 TRAC + const secondMultiplier = ethers.parseUnits('2', 12); // 2 NEURO per 1 TRAC await expect( incentivesPool .connect(registrarSigner) - .initiateTokenEmissionMultiplierUpdate(newMultiplier), + .initiateTokenEmissionMultiplierUpdate(secondMultiplier), ) .to.emit(incentivesPool, 'TokenEmissionMultiplierUpdateInitiated') .withArgs( initialEmissionMultiplier, - newMultiplier, + secondMultiplier, (await time.latest()) + 7 * 24 * 3600 + 1, // Add 1 to account for the block being mined ); @@ -932,14 +1018,58 @@ describe('@unit Paranet', () => { .finalizeTokenEmissionMultiplierUpdate(), ) .to.emit(incentivesPool, 'TokenEmissionMultiplierUpdateFinalized') - .withArgs(initialEmissionMultiplier, newMultiplier); + .withArgs(initialEmissionMultiplier, secondMultiplier); + + // Verify new multiplier is active + expect( + await incentivesPool.getEffectiveTokenEmissionMultiplier( + await time.latest(), + ), + ).to.equal(secondMultiplier); + + // Additional checks for emission multiplier updates + // Check multiple updates in sequence + const thirdMultiplier = ethers.parseUnits('3', 12); + await incentivesPool + .connect(registrarSigner) + .initiateTokenEmissionMultiplierUpdate(thirdMultiplier); + + // Verify pending update state + const multipliers = await incentivesPool.gettokenEmissionMultipliers(); + expect(multipliers[multipliers.length - 1].multiplier).to.equal( + thirdMultiplier, + ); + expect(multipliers[multipliers.length - 1].finalized).to.equal(false); + + // Try to initiate another update while one is pending - should update the pending one + const fourthMultiplier = ethers.parseUnits('4', 12); + await incentivesPool + .connect(registrarSigner) + .initiateTokenEmissionMultiplierUpdate(fourthMultiplier); + const updatedMultipliers = + await incentivesPool.gettokenEmissionMultipliers(); + expect( + updatedMultipliers[updatedMultipliers.length - 1].multiplier, + ).to.equal(fourthMultiplier); + + // Move time forward 7 days + await time.increase(7 * 24 * 3600); + + // Finalize update + await expect( + incentivesPool + .connect(registrarSigner) + .finalizeTokenEmissionMultiplierUpdate(), + ) + .to.emit(incentivesPool, 'TokenEmissionMultiplierUpdateFinalized') + .withArgs(secondMultiplier, fourthMultiplier); // Didn't finalize the third multiplier // Verify new multiplier is active expect( await incentivesPool.getEffectiveTokenEmissionMultiplier( await time.latest(), ), - ).to.equal(newMultiplier); + ).to.equal(fourthMultiplier); }); }); From ff28438246b4f33d6e74b8f37e678195d5f19c37 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 21 Feb 2025 16:20:23 +0100 Subject: [PATCH 140/153] Add tests for multiple incentive contracts --- abi/Paranet.json | 557 +++---------------------------- abi/ParanetsRegistry.json | 206 ++++++------ test/integration/Paranet.test.ts | 436 ++++++++++++++++++++++++ 3 files changed, 592 insertions(+), 607 deletions(-) diff --git a/abi/Paranet.json b/abi/Paranet.json index b5cd5606..3cc4597f 100644 --- a/abi/Paranet.json +++ b/abi/Paranet.json @@ -10,38 +10,6 @@ "stateMutability": "nonpayable", "type": "constructor" }, - { - "inputs": [ - { - "internalType": "uint8[]", - "name": "expectedAccessPolicies", - "type": "uint8[]" - }, - { - "internalType": "uint8", - "name": "actualAccessPolicy", - "type": "uint8" - } - ], - "name": "InvalidParanetMinersAccessPolicy", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8[]", - "name": "expectedAccessPolicies", - "type": "uint8[]" - }, - { - "internalType": "uint8", - "name": "actualAccessPolicy", - "type": "uint8" - } - ], - "name": "InvalidParanetNodesAccessPolicy", - "type": "error" - }, { "inputs": [ { @@ -79,144 +47,6 @@ "name": "KnowledgeCollectionNotInFirstEpoch", "type": "error" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "miner", - "type": "address" - } - ], - "name": "ParanetCuratedMinerAccessRequestDoesntExist", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "miner", - "type": "address" - }, - { - "internalType": "enum ParanetLib.RequestStatus", - "name": "status", - "type": "uint8" - } - ], - "name": "ParanetCuratedMinerAccessRequestInvalidStatus", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "miner", - "type": "address" - } - ], - "name": "ParanetCuratedMinerDoesntExist", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "miner", - "type": "address" - } - ], - "name": "ParanetCuratedMinerHasAlreadyBeenAdded", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - } - ], - "name": "ParanetCuratedNodeDoesntExist", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - } - ], - "name": "ParanetCuratedNodeHasAlreadyBeenAdded", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - } - ], - "name": "ParanetCuratedNodeJoinRequestDoesntExist", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - }, - { - "internalType": "enum ParanetLib.RequestStatus", - "name": "status", - "type": "uint8" - } - ], - "name": "ParanetCuratedNodeJoinRequestInvalidStatus", - "type": "error" - }, { "inputs": [ { @@ -317,17 +147,6 @@ "name": "ParanetServiceHasAlreadyBeenRegistered", "type": "error" }, - { - "inputs": [ - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - } - ], - "name": "ProfileDoesntExist", - "type": "error" - }, { "inputs": [ { @@ -403,13 +222,30 @@ "type": "uint256" }, { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "storageAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "rewardTokenAddress", + "type": "address" + } + ], "indexed": false, - "internalType": "address", - "name": "minerAddress", - "type": "address" + "internalType": "struct ParanetLib.IncentivesPool", + "name": "incentivesPool", + "type": "tuple" } ], - "name": "ParanetCuratedMinerAccessRequestAccepted", + "name": "ParanetIncetivesPoolDeployed", "type": "event" }, { @@ -435,12 +271,18 @@ }, { "indexed": false, - "internalType": "address", - "name": "minerAddress", - "type": "address" + "internalType": "string", + "name": "newParanetName", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "newParanetDescription", + "type": "string" } ], - "name": "ParanetCuratedMinerAccessRequestCreated", + "name": "ParanetMetadataUpdated", "type": "event" }, { @@ -471,7 +313,7 @@ "type": "address" } ], - "name": "ParanetCuratedMinerAccessRequestRejected", + "name": "ParanetPermissionedMinerAccessRequestAccepted", "type": "event" }, { @@ -502,7 +344,7 @@ "type": "address" } ], - "name": "ParanetCuratedMinerAdded", + "name": "ParanetPermissionedMinerAccessRequestCreated", "type": "event" }, { @@ -533,7 +375,7 @@ "type": "address" } ], - "name": "ParanetCuratedMinerRemoved", + "name": "ParanetPermissionedMinerAccessRequestRejected", "type": "event" }, { @@ -559,12 +401,12 @@ }, { "indexed": false, - "internalType": "uint72", - "name": "identityId", - "type": "uint72" + "internalType": "address", + "name": "minerAddress", + "type": "address" } ], - "name": "ParanetCuratedNodeAdded", + "name": "ParanetPermissionedMinerAdded", "type": "event" }, { @@ -590,12 +432,12 @@ }, { "indexed": false, - "internalType": "uint72", - "name": "identityId", - "type": "uint72" + "internalType": "address", + "name": "minerAddress", + "type": "address" } ], - "name": "ParanetCuratedNodeJoinRequestAccepted", + "name": "ParanetPermissionedMinerRemoved", "type": "event" }, { @@ -626,7 +468,7 @@ "type": "uint72" } ], - "name": "ParanetCuratedNodeJoinRequestCreated", + "name": "ParanetPermissionedNodeAdded", "type": "event" }, { @@ -657,7 +499,7 @@ "type": "uint72" } ], - "name": "ParanetCuratedNodeJoinRequestRejected", + "name": "ParanetPermissionedNodeJoinRequestAccepted", "type": "event" }, { @@ -688,7 +530,7 @@ "type": "uint72" } ], - "name": "ParanetCuratedNodeRemoved", + "name": "ParanetPermissionedNodeJoinRequestCreated", "type": "event" }, { @@ -713,30 +555,13 @@ "type": "uint256" }, { - "components": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "address", - "name": "storageAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "rewardTokenAddress", - "type": "address" - } - ], "indexed": false, - "internalType": "struct ParanetLib.IncentivesPool", - "name": "incentivesPool", - "type": "tuple" + "internalType": "uint72", + "name": "identityId", + "type": "uint72" } ], - "name": "ParanetIncetivesPoolDeployed", + "name": "ParanetPermissionedNodeJoinRequestRejected", "type": "event" }, { @@ -762,18 +587,12 @@ }, { "indexed": false, - "internalType": "string", - "name": "newParanetName", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "newParanetDescription", - "type": "string" + "internalType": "uint72", + "name": "identityId", + "type": "uint72" } ], - "name": "ParanetMetadataUpdated", + "name": "ParanetPermissionedNodeRemoved", "type": "event" }, { @@ -988,62 +807,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "paranetKCStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "paranetKCTokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "paranetKATokenId", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "minerAddresses", - "type": "address[]" - } - ], - "name": "addParanetCuratedMiners", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "paranetKCStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "paranetKCTokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "paranetKATokenId", - "type": "uint256" - }, - { - "internalType": "uint72[]", - "name": "identityIds", - "type": "uint72[]" - } - ], - "name": "addParanetCuratedNodes", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -1089,62 +852,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "paranetKCStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "paranetKCTokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "paranetKATokenId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "minerAddress", - "type": "address" - } - ], - "name": "approveCuratedMiner", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "paranetKCStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "paranetKCTokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "paranetKATokenId", - "type": "uint256" - }, - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - } - ], - "name": "approveCuratedNode", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "chronos", @@ -1421,62 +1128,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "paranetKCStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "paranetKCTokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "paranetKATokenId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "minerAddress", - "type": "address" - } - ], - "name": "rejectCuratedMiner", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "paranetKCStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "paranetKCTokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "paranetKATokenId", - "type": "uint256" - }, - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - } - ], - "name": "rejectCuratedNode", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -1505,108 +1156,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "paranetKCStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "paranetKCTokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "paranetKATokenId", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "minerAddresses", - "type": "address[]" - } - ], - "name": "removeParanetCuratedMiners", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "paranetKCStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "paranetKCTokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "paranetKATokenId", - "type": "uint256" - }, - { - "internalType": "uint72[]", - "name": "identityIds", - "type": "uint72[]" - } - ], - "name": "removeParanetCuratedNodes", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "paranetKCStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "paranetKCTokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "paranetKATokenId", - "type": "uint256" - } - ], - "name": "requestParanetCuratedMinerAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "paranetKCStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "paranetKCTokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "paranetKATokenId", - "type": "uint256" - } - ], - "name": "requestParanetCuratedNodeAccess", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { diff --git a/abi/ParanetsRegistry.json b/abi/ParanetsRegistry.json index f7e46720..b3abdb9e 100644 --- a/abi/ParanetsRegistry.json +++ b/abi/ParanetsRegistry.json @@ -44,29 +44,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - }, - { - "internalType": "bytes", - "name": "nodeId", - "type": "bytes" - } - ], - "name": "addCuratedNode", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -177,6 +154,29 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "bytes", + "name": "nodeId", + "type": "bytes" + } + ], + "name": "addPermissionedNode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -276,56 +276,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - } - ], - "name": "getCuratedNodes", - "outputs": [ - { - "components": [ - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - }, - { - "internalType": "bytes", - "name": "nodeId", - "type": "bytes" - } - ], - "internalType": "struct ParanetLib.Node[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - } - ], - "name": "getCuratedNodesCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -1141,6 +1091,56 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "getPermissionedNodes", + "outputs": [ + { + "components": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "bytes", + "name": "nodeId", + "type": "bytes" + } + ], + "internalType": "struct ParanetLib.Node[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + } + ], + "name": "getPermissionedNodesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1248,12 +1248,12 @@ "type": "bytes32" }, { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" + "internalType": "bytes32", + "name": "knowledgeCollectionId", + "type": "bytes32" } ], - "name": "isCuratedNode", + "name": "isKnowledgeCollectionRegistered", "outputs": [ { "internalType": "bool", @@ -1272,12 +1272,12 @@ "type": "bytes32" }, { - "internalType": "bytes32", - "name": "knowledgeCollectionId", - "type": "bytes32" + "internalType": "address", + "name": "knowledgeMinerAddress", + "type": "address" } ], - "name": "isKnowledgeCollectionRegistered", + "name": "isKnowledgeMinerRegistered", "outputs": [ { "internalType": "bool", @@ -1296,12 +1296,12 @@ "type": "bytes32" }, { - "internalType": "address", - "name": "knowledgeMinerAddress", - "type": "address" + "internalType": "uint72", + "name": "identityId", + "type": "uint72" } ], - "name": "isKnowledgeMinerRegistered", + "name": "isPermissionedNode", "outputs": [ { "internalType": "bool", @@ -1422,24 +1422,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - }, - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - } - ], - "name": "removeCuratedNode", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -1522,6 +1504,24 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "paranetId", + "type": "bytes32" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "removePermissionedNode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index 3e228cd9..bd29fe89 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -4322,4 +4322,440 @@ describe('@unit Paranet', () => { expect(finalNodes[0].identityId).to.equal(node2IdentityId); }); }); + + describe('Paranet Incentives Pool Rewards', () => { + it('Should handle claiming rewards from multiple incentives pools', async () => { + // 1. Setup paranet with initial configuration + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + // paranetId, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Deploy two incentive pools with different parameters + const tx1 = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ethers.parseUnits('1', 12), // 1 NEURO per 1 TRAC + 1000, // 10% operator + 2000, // 20% voters + 'Pool1', + await Token.getAddress(), + ); + const receipt1 = await tx1.wait(); + const event1 = receipt1!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolDeployed', + ).topicHash, + ) as EventLog; + + const tx2 = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ethers.parseUnits('2', 12), // 2 NEURO per 1 TRAC + 1500, // 15% operator + 2500, // 25% voters + 'Pool2', + await Token.getAddress(), + ); + const receipt2 = await tx2.wait(); + const event2 = receipt2!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolDeployed', + ).topicHash, + ) as EventLog; + + // 3. Fund both pools + const pool1Amount = ethers.parseUnits('100', 18); // 100 NEURO + const pool2Amount = ethers.parseUnits('200', 18); // 200 NEURO + await Token.connect(paranetOwner).approve(event1?.args[3], pool1Amount); + await Token.connect(paranetOwner).approve(event2?.args[3], pool2Amount); + + const pool1Storage = await hre.ethers.getContractAt( + 'ParanetIncentivesPoolStorage', + event1?.args[3], + ); + const pool1 = await hre.ethers.getContractAt( + 'ParanetIncentivesPool', + event1?.args[4], + ); + + const pool2Storage = await hre.ethers.getContractAt( + 'ParanetIncentivesPoolStorage', + event2?.args[3], + ); + const pool2 = await hre.ethers.getContractAt( + 'ParanetIncentivesPool', + event2?.args[4], + ); + + await Token.connect(accounts[0]).mint(pool1Storage, pool1Amount); + await Token.connect(accounts[0]).mint(pool2Storage, pool2Amount); + + expect(await pool1Storage.getBalance()).to.equal(pool1Amount); + expect(await pool1Storage.totalMinersclaimedToken()).to.equal(0); + expect(await pool1Storage.totalOperatorsclaimedToken()).to.equal(0); + expect(await pool1Storage.totalVotersclaimedToken()).to.equal(0); + + expect(await pool2Storage.getBalance()).to.equal(pool2Amount); + expect(await pool2Storage.totalMinersclaimedToken()).to.equal(0); + expect(await pool2Storage.totalOperatorsclaimedToken()).to.equal(0); + expect(await pool2Storage.totalVotersclaimedToken()).to.equal(0); + + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + + const miner = accounts[100]; + const { collectionId } = await createKnowledgeCollection( + miner, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection, + Token, + }, + ); + + await Paranet.connect(miner).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ); + + // 5. Claim rewards from first pool + const initialMinerBalance = await Token.balanceOf( + await miner.getAddress(), + ); + const minerRewardEstimate1 = await pool1 + .connect(miner) + .getTotalKnowledgeMinerIncentiveEstimation(); + expect(minerRewardEstimate1).to.be.gt(0); + + await pool1 + .connect(miner) + .claimKnowledgeMinerReward(minerRewardEstimate1); + // 6. Verify first pool is empty and second pool still has funds + expect(await Token.balanceOf(await miner.getAddress())).to.be.equal( + initialMinerBalance + minerRewardEstimate1, + ); + expect(await Token.balanceOf(event1?.args[3])).to.equal( + pool1Amount - minerRewardEstimate1, + ); + expect(await Token.balanceOf(event2?.args[3])).to.equal(pool2Amount); + + // 7. Claim rewards from second pool + const minerRewardEstimate0 = await pool2 + .connect(miner) + .getTotalKnowledgeMinerIncentiveEstimation(); + expect(minerRewardEstimate0).to.be.equal(0); + + await expect( + pool2.connect(miner).claimKnowledgeMinerReward(minerRewardEstimate0), + ).to.be.revertedWithCustomError(pool2, 'NoRewardAvailable'); + + expect(await Token.balanceOf(await miner.getAddress())).to.equal( + initialMinerBalance + minerRewardEstimate1, + ); + expect(await Token.balanceOf(pool2Storage)).to.equal(pool2Amount); + + const { collectionId: collectionId2 } = await createKnowledgeCollection( + miner, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection, + Token, + }, + ); + + await Paranet.connect(miner).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId2, + ); + const initialMinerBalance2 = await Token.balanceOf( + await miner.getAddress(), + ); + const minerRewardEstimate2 = await pool1 + .connect(miner) + .getTotalKnowledgeMinerIncentiveEstimation(); + expect(minerRewardEstimate2).to.be.gt(0); + + await pool2 + .connect(miner) + .claimKnowledgeMinerReward(minerRewardEstimate2); + + // 8. Verify balances is updated + expect(await Token.balanceOf(pool1Storage)).to.equal( + pool1Amount - minerRewardEstimate1, + ); + expect(await Token.balanceOf(pool2Storage)).to.equal( + pool2Amount - minerRewardEstimate2, + ); + expect(await Token.balanceOf(await miner.getAddress())).to.equal( + initialMinerBalance2 + minerRewardEstimate2, + ); + }); + + it.only('Should handle claiming rewards from multiple incentives pools with native token', async () => { + // 1. Setup paranet with initial configuration + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Deploy two incentive pools with different parameters using address(0) for native token + const tx1 = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ethers.parseUnits('1', 12), // 1 ETH per 1 TRAC + 1000, // 10% operator + 2000, // 20% voters + 'Pool1', + ethers.ZeroAddress, // Use address(0) for native token + ); + const receipt1 = await tx1.wait(); + const event1 = receipt1!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolDeployed', + ).topicHash, + ) as EventLog; + + const tx2 = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ethers.parseUnits('2', 12), // 2 ETH per 1 TRAC + 1500, // 15% operator + 2500, // 25% voters + 'Pool2', + ethers.ZeroAddress, // Use address(0) for native token + ); + const receipt2 = await tx2.wait(); + const event2 = receipt2!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolDeployed', + ).topicHash, + ) as EventLog; + + // 3. Fund both pools with ETH + const pool1Amount = ethers.parseEther('100'); // 100 ETH + const pool2Amount = ethers.parseEther('200'); // 200 ETH + + const pool1Storage = await hre.ethers.getContractAt( + 'ParanetIncentivesPoolStorage', + event1?.args[3], + ); + const pool1 = await hre.ethers.getContractAt( + 'ParanetIncentivesPool', + event1?.args[4], + ); + + const pool2Storage = await hre.ethers.getContractAt( + 'ParanetIncentivesPoolStorage', + event2?.args[3], + ); + const pool2 = await hre.ethers.getContractAt( + 'ParanetIncentivesPool', + event2?.args[4], + ); + + // Send ETH to pools + await paranetOwner.sendTransaction({ + to: pool1Storage.target, + value: pool1Amount, + }); + await paranetOwner.sendTransaction({ + to: pool2Storage.target, + value: pool2Amount, + }); + + // Verify initial balances + expect( + await hre.ethers.provider.getBalance(pool1Storage.target), + ).to.equal(pool1Amount); + expect(await pool1Storage.totalMinersclaimedToken()).to.equal(0); + expect(await pool1Storage.totalOperatorsclaimedToken()).to.equal(0); + expect(await pool1Storage.totalVotersclaimedToken()).to.equal(0); + + expect( + await hre.ethers.provider.getBalance(pool2Storage.target), + ).to.equal(pool2Amount); + expect(await pool2Storage.totalMinersclaimedToken()).to.equal(0); + expect(await pool2Storage.totalOperatorsclaimedToken()).to.equal(0); + expect(await pool2Storage.totalVotersclaimedToken()).to.equal(0); + + // 4. Create and submit knowledge collection + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + + const miner = accounts[100]; + const { collectionId } = await createKnowledgeCollection( + miner, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection, + Token, + }, + ); + + await Paranet.connect(miner).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ); + + // 5. Claim rewards from first pool + const initialMinerBalance = await hre.ethers.provider.getBalance( + miner.address, + ); + const minerRewardEstimate1 = await pool1 + .connect(miner) + .getTotalKnowledgeMinerIncentiveEstimation(); + expect(minerRewardEstimate1).to.be.gt(0); + + const claimTx1 = await pool1 + .connect(miner) + .claimKnowledgeMinerReward(minerRewardEstimate1); + const receipt3 = await claimTx1.wait(); + const gasCost1 = receipt3!.gasUsed * receipt3!.gasPrice; + + // 6. Verify first pool balance and miner received ETH + const newMinerBalance = await hre.ethers.provider.getBalance( + miner.address, + ); + expect(newMinerBalance).to.be.equal( + initialMinerBalance + minerRewardEstimate1 - gasCost1, + ); + expect( + await hre.ethers.provider.getBalance(pool1Storage.target), + ).to.equal(pool1Amount - minerRewardEstimate1); + expect( + await hre.ethers.provider.getBalance(pool2Storage.target), + ).to.equal(pool2Amount); + + // 7. Try claiming from second pool (should fail as no rewards available yet) + const minerRewardEstimate0 = await pool2 + .connect(miner) + .getTotalKnowledgeMinerIncentiveEstimation(); + expect(minerRewardEstimate0).to.be.equal(0); + + await expect( + pool2.connect(miner).claimKnowledgeMinerReward(minerRewardEstimate0), + ).to.be.revertedWithCustomError(pool2, 'NoRewardAvailable'); + + await expect( + pool1.connect(miner).claimKnowledgeMinerReward(minerRewardEstimate0), + ).to.be.revertedWithCustomError(pool1, 'NoRewardAvailable'); + + // 8. Submit second knowledge collection + const { collectionId: collectionId2 } = await createKnowledgeCollection( + miner, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection, + Token, + }, + ); + + await Paranet.connect(miner).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId2, + ); + + // 9. Claim rewards from second pool + const initialMinerBalance2 = await hre.ethers.provider.getBalance( + miner.address, + ); + const minerRewardEstimate2 = await pool2 + .connect(miner) + .getTotalKnowledgeMinerIncentiveEstimation(); + expect(minerRewardEstimate2).to.be.gt(0); + + const claimTx2 = await pool2 + .connect(miner) + .claimKnowledgeMinerReward(minerRewardEstimate2); + const receipt4 = await claimTx2.wait(); + const gasCost2 = receipt4!.gasUsed * receipt4!.gasPrice; + + // 10. Verify final balances + expect( + await hre.ethers.provider.getBalance(pool1Storage.target), + ).to.equal(pool1Amount - minerRewardEstimate1); + expect( + await hre.ethers.provider.getBalance(pool2Storage.target), + ).to.equal(pool2Amount - minerRewardEstimate2); + expect(await hre.ethers.provider.getBalance(miner.address)).to.equal( + initialMinerBalance2 + minerRewardEstimate2 - gasCost2, + ); + }); + }); }); From 8d80da87bb433669bc4a03aacb0bb5054b3b375c Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Fri, 21 Feb 2025 16:21:18 +0100 Subject: [PATCH 141/153] remove only --- test/integration/Paranet.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index bd29fe89..d8268fb5 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -4530,7 +4530,7 @@ describe('@unit Paranet', () => { ); }); - it.only('Should handle claiming rewards from multiple incentives pools with native token', async () => { + it('Should handle claiming rewards from multiple incentives pools with native token', async () => { // 1. Setup paranet with initial configuration const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); From c192f73930c07a83793d1366d9e27735693ad004 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Mon, 24 Feb 2025 11:42:49 +0100 Subject: [PATCH 142/153] Improve pool and pool storage test coverage --- test/integration/Paranet.test.ts | 148 +++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index d8268fb5..66675b7f 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -403,6 +403,78 @@ describe('@unit Paranet', () => { }); describe('Paranet Incentives Pool', () => { + it('Should return correct name and version of factory, incentives pool and storage', async () => { + // Incentives pool factory + const name = await ParanetIncentivesPoolFactory.name(); + const version = await ParanetIncentivesPoolFactory.version(); + expect(name).to.equal('ParanetIncentivesPoolFactory'); + expect(version).to.equal('1.0.0'); + + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + const tracToNeuroEmissionMultiplier = ethers.parseUnits('1', 12); // 1 NEURO per 1 TRAC + const operatorRewardPercentage = 1000; // 10% + const votersRewardPercentage = 2000; // 20% + + const tx = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + tracToNeuroEmissionMultiplier, + operatorRewardPercentage, + votersRewardPercentage, + 'Neuroweb', + await Token.getAddress(), + ); + + // get incentives pool name and version + const receipt = await tx.wait(); + const event = receipt!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolDeployed', + ).topicHash, + ) as EventLog; + const incentivesPool = await hre.ethers.getContractAt( + 'ParanetIncentivesPool', + event?.args[4], + ); + const incentivesPoolName = await incentivesPool.name(); + const incentivesPoolVersion = await incentivesPool.version(); + expect(incentivesPoolName).to.equal('ParanetIncentivesPool'); + expect(incentivesPoolVersion).to.equal('1.0.0'); + + const incentivesPoolStorage = await hre.ethers.getContractAt( + 'ParanetIncentivesPoolStorage', + event?.args[3], + ); + const incentivesPoolStorageName = await incentivesPoolStorage.name(); + const incentivesPoolStorageVersion = + await incentivesPoolStorage.version(); + expect(incentivesPoolStorageName).to.equal( + 'ParanetIncentivesPoolStorage', + ); + expect(incentivesPoolStorageVersion).to.equal('1.0.0'); + }); + it('Should deploy incentives pool successfully', async () => { const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); @@ -706,6 +778,11 @@ describe('@unit Paranet', () => { event?.args[4], ); + // Test non-existent voter + expect( + await incentivesPool.voterclaimedToken(accounts[5].address), + ).to.equal(0); + // Get registrar const registrar = await incentivesPoolStorage.votersRegistrar(); const registrarSigner = await hre.ethers.getSigner(registrar); @@ -725,6 +802,14 @@ describe('@unit Paranet', () => { 10000, ); + // Now voter exists but hasn't claimed anything yet + expect( + await incentivesPool.voterclaimedToken(accounts[5].address), + ).to.equal(0); + expect( + await incentivesPool.isProposalVoter(accounts[5].address), + ).to.be.eq(true); + // Update voter weight await incentivesPoolStorage .connect(registrarSigner) @@ -783,6 +868,27 @@ describe('@unit Paranet', () => { .connect(accounts[5]) .getClaimableProposalVoterRewardAmount(); expect(claimableVoterReward).to.equal(voterShare); + + // Transfer registrar role to new address + await expect( + incentivesPoolStorage + .connect(registrarSigner) + .transferVotersRegistrarRole(accounts[6].address), + ) + .to.emit(incentivesPoolStorage, 'VotersRegistrarTransferred') + .withArgs(registrarSigner.address, accounts[6].address); + + // Verify new registrar + expect(await incentivesPoolStorage.votersRegistrar()).to.equal( + accounts[6].address, + ); + + // Test zero address revert + await expect( + incentivesPoolStorage + .connect(accounts[6]) + .transferVotersRegistrarRole(ethers.ZeroAddress), + ).to.be.revertedWith('New registrar cannot be zero address'); }); it('Should handle incentives pool redeployment', async () => { @@ -1070,6 +1176,31 @@ describe('@unit Paranet', () => { await time.latest(), ), ).to.equal(fourthMultiplier); + + // Should allow hub owner to update token emission multiplier delay + const hubContract = await hre.ethers.getContractAt( + 'Hub', + await incentivesPool.hub(), + ); + const hubOwner = await hubContract.owner(); + const hubOwnerSigner = await hre.ethers.getSigner(hubOwner); + + // Update delay as hub owner + const newDelay = 14 * 24 * 60 * 60; // 14 days + await incentivesPool + .connect(hubOwnerSigner) + .updatetokenEmissionMultiplierUpdateDelay(newDelay); + expect( + await incentivesPool.tokenEmissionMultiplierUpdateDelay(), + ).to.equal(newDelay); + + // Try to update delay as non-hub owner + const nonOwner = accounts[9]; + await expect( + incentivesPool + .connect(nonOwner) + .updatetokenEmissionMultiplierUpdateDelay(newDelay), + ).to.be.revertedWith('Fn can only be used by hub owner'); }); }); @@ -1252,6 +1383,15 @@ describe('@unit Paranet', () => { .claimKnowledgeMinerReward(claimableMinerReward); // 8. Verify miner rewards claimed correctly + // Test getting all rewarded miners/operators + const allMiners = await incentivesPoolStorage.getAllRewardedMiners(); + expect(allMiners.length).to.equal(1); + + // Test claimed token queries + expect( + await incentivesPoolStorage.minerclaimedToken(kcCreator.address), + ).to.equal(claimableMinerReward); + expect( await incentivesPoolStorage .connect(kcCreator) @@ -1276,6 +1416,14 @@ describe('@unit Paranet', () => { await incentivesPool.connect(paranetOwner).claimParanetOperatorReward(); // 10. Verify operator rewards claimed correctly + const allOperators = + await incentivesPoolStorage.getAllRewardedOperators(); + expect(allOperators.length).to.equal(1); + + expect( + await incentivesPoolStorage.operatorclaimedToken(paranetOwner.address), + ).to.equal(claimableOperatorReward); + expect(await incentivesPoolStorage.totalOperatorsclaimedToken()).to.equal( claimableOperatorReward, ); From ef0dcde4a9ba752f7aab98073f16b7ee33e17bac Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Mon, 24 Feb 2025 12:33:31 +0100 Subject: [PATCH 143/153] Add more coverage tests --- test/integration/Paranet.test.ts | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index 66675b7f..c5a88f11 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -193,6 +193,13 @@ describe('@unit Paranet', () => { }); describe('Paranet Registration', () => { + it('Should return the correct name and version of the paranet', async () => { + const name = await Paranet.name(); + const version = await Paranet.version(); + expect(name).to.equal('Paranet'); + expect(version).to.equal('1.0.0'); + }); + it('Should register a paranet successfully', async () => { const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); @@ -405,10 +412,17 @@ describe('@unit Paranet', () => { describe('Paranet Incentives Pool', () => { it('Should return correct name and version of factory, incentives pool and storage', async () => { // Incentives pool factory - const name = await ParanetIncentivesPoolFactory.name(); - const version = await ParanetIncentivesPoolFactory.version(); - expect(name).to.equal('ParanetIncentivesPoolFactory'); - expect(version).to.equal('1.0.0'); + const poolFactoryName = await ParanetIncentivesPoolFactory.name(); + const poolFactoryVersion = await ParanetIncentivesPoolFactory.version(); + expect(poolFactoryName).to.equal('ParanetIncentivesPoolFactory'); + expect(poolFactoryVersion).to.equal('1.0.0'); + + // Incentives pool factory helper + const poolFactoryHelperName = await ParanetIncentivesPoolFactory.name(); + const poolFactoryHelperVersion = + await ParanetIncentivesPoolFactory.version(); + expect(poolFactoryHelperName).to.equal('ParanetIncentivesPoolFactory'); + expect(poolFactoryHelperVersion).to.equal('1.0.0'); const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); From e27a8909b0150f7618c830e6bb90a5fe58b5bbd7 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Mon, 24 Feb 2025 12:34:14 +0100 Subject: [PATCH 144/153] Comment out permissioned tests --- test/integration/Paranet.test.ts | 2104 +++++++++++++++--------------- 1 file changed, 1052 insertions(+), 1052 deletions(-) diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index c5a88f11..5c8323d7 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -1,4 +1,4 @@ -import { randomBytes } from 'crypto'; +// import { randomBytes } from 'crypto'; import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; import { loadFixture, time } from '@nomicfoundation/hardhat-network-helpers'; @@ -3433,1057 +3433,1057 @@ describe('@unit Paranet', () => { }); }); - describe('Paranet Permissioned Miners', () => { - it('Should allow owner to add and remove curated miners', async () => { - // Setup paranet with permissioned miners policy - const kcCreator = getDefaultKCCreator(accounts); - const publishingNode = getDefaultPublishingNode(accounts); - const receivingNodes = getDefaultReceivingNodes(accounts); - const miner1 = accounts[10]; - const miner2 = accounts[11]; - - const { - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - paranetId, // Add this to destructuring - } = await setupParanet( - kcCreator, - publishingNode, - receivingNodes, - { - Paranet, - Profile, - Token, - KnowledgeCollection, - KnowledgeCollectionStorage, - }, - 'Test Paranet', - 'Test Paranet Description', - ACCESS_POLICIES.OPEN, // nodes policy - 1, // miners policy - ACCESS_POLICIES.OPEN, // submission policy - ); - - // Verify initial state - expect( - await ParanetsRegistry.getKnowledgeMinersCount(paranetId), - ).to.equal(0); - expect( - await ParanetsRegistry.isKnowledgeMinerRegistered( - paranetId, - miner1.address, - ), - ).to.be.equal(false); - expect( - await ParanetsRegistry.isKnowledgeMinerRegistered( - paranetId, - miner2.address, - ), - ).to.be.equal(false); - - // Add miners - await expect( - Paranet.connect(kcCreator).addParanetCuratedMiners( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - [miner1.address, miner2.address], - ), - ) - .to.emit(Paranet, 'ParanetCuratedMinerAdded') - .withArgs( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - miner1.address, - ) - .to.emit(Paranet, 'ParanetCuratedMinerAdded') - .withArgs( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - miner2.address, - ); - - // Verify miners were added - expect( - await ParanetsRegistry.getKnowledgeMinersCount(paranetId), - ).to.equal(2); - expect( - await ParanetsRegistry.isKnowledgeMinerRegistered( - paranetId, - miner1.address, - ), - ).to.be.equal(true); - expect( - await ParanetsRegistry.isKnowledgeMinerRegistered( - paranetId, - miner2.address, - ), - ).to.be.equal(true); - - const registeredMiners = - await ParanetsRegistry.getKnowledgeMiners(paranetId); - expect(registeredMiners[0]).to.be.equal(miner1.address); - expect(registeredMiners[1]).to.be.equal(miner2.address); - - // Remove miners - await expect( - Paranet.connect(kcCreator).removeParanetCuratedMiners( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - [miner1.address], - ), - ) - .to.emit(Paranet, 'ParanetCuratedMinerRemoved') - .withArgs( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - miner1.address, - ); - - // Verify miner1 was removed but miner2 remains - expect( - await ParanetsRegistry.getKnowledgeMinersCount(paranetId), - ).to.equal(1); - expect( - await ParanetsRegistry.isKnowledgeMinerRegistered( - paranetId, - miner1.address, - ), - ).to.be.equal(false); - expect( - await ParanetsRegistry.isKnowledgeMinerRegistered( - paranetId, - miner2.address, - ), - ).to.be.equal(true); - - const remainingMiners = - await ParanetsRegistry.getKnowledgeMiners(paranetId); - expect(remainingMiners).to.have.lengthOf(1); - expect(remainingMiners[0]).to.equal(miner2.address); - }); - - it('Should handle miner access requests correctly', async () => { - // Setup paranet with permissioned miners policy - const kcCreator = getDefaultKCCreator(accounts); - const publishingNode = getDefaultPublishingNode(accounts); - const receivingNodes = getDefaultReceivingNodes(accounts); - const miner = accounts[10]; - - const { - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - paranetId, - } = await setupParanet( - kcCreator, - publishingNode, - receivingNodes, - { - Paranet, - Profile, - Token, - KnowledgeCollection, - KnowledgeCollectionStorage, - }, - 'Test Paranet', - 'Test Paranet Description', - ACCESS_POLICIES.OPEN, // nodes policy - 1, // miners policy - ACCESS_POLICIES.OPEN, // submission policy - ); - - // Request access - await expect( - Paranet.connect(miner).requestParanetCuratedMinerAccess( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - ), - ) - .to.emit(Paranet, 'ParanetCuratedMinerAccessRequestCreated') - .withArgs( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - miner.address, - ); - - // Verify request state - const latestRequest = - await ParanetsRegistry.getLatestKnowledgeMinerAccessRequest( - paranetId, - miner.address, - ); - expect(latestRequest.miner).to.equal(miner.address); - expect(latestRequest.status).to.equal(1); // PENDING status - expect(latestRequest.createdAt).to.be.gt(0); - expect(latestRequest.updatedAt).to.equal(latestRequest.createdAt); - - // Approve request - await expect( - Paranet.connect(kcCreator).approveCuratedMiner( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - miner.address, - ), - ) - .to.emit(Paranet, 'ParanetCuratedMinerAccessRequestAccepted') - .withArgs( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - miner.address, - ) - .to.emit(Paranet, 'ParanetCuratedMinerAdded') - .withArgs( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - miner.address, - ); - - // Verify request state after approval - const updatedRequest = - await ParanetsRegistry.getLatestKnowledgeMinerAccessRequest( - paranetId, - miner.address, - ); - expect(updatedRequest.miner).to.equal(miner.address); - expect(updatedRequest.status).to.equal(2); // ACCEPTED status - expect(updatedRequest.createdAt).to.equal(latestRequest.createdAt); - expect(updatedRequest.updatedAt).to.be.gt(latestRequest.updatedAt); - - // Verify miner is now registered - expect( - await ParanetsRegistry.isKnowledgeMinerRegistered( - paranetId, - miner.address, - ), - ).to.be.equal(true); - }); - - it('Should handle miner access request rejection', async () => { - // Setup paranet with permissioned miners policy - const kcCreator = getDefaultKCCreator(accounts); - const publishingNode = getDefaultPublishingNode(accounts); - const receivingNodes = getDefaultReceivingNodes(accounts); - const miner = accounts[10]; - - const { - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - paranetId, - } = await setupParanet( - kcCreator, - publishingNode, - receivingNodes, - { - Paranet, - Profile, - Token, - KnowledgeCollection, - KnowledgeCollectionStorage, - }, - 'Test Paranet', - 'Test Paranet Description', - ACCESS_POLICIES.OPEN, // nodes policy - 1, // miners policy - ACCESS_POLICIES.OPEN, // submission policy - ); - - // Request access - await Paranet.connect(miner).requestParanetCuratedMinerAccess( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - ); - - // Verify initial request state - const latestRequest = - await ParanetsRegistry.getLatestKnowledgeMinerAccessRequest( - paranetId, - miner.address, - ); - expect(latestRequest.miner).to.equal(miner.address); - expect(latestRequest.status).to.equal(1); // PENDING status - expect(latestRequest.createdAt).to.be.gt(0); - expect(latestRequest.updatedAt).to.equal(latestRequest.createdAt); - - // Reject request - await expect( - Paranet.connect(kcCreator).rejectCuratedMiner( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - miner.address, - ), - ) - .to.emit(Paranet, 'ParanetCuratedMinerAccessRequestRejected') - .withArgs( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - miner.address, - ); - - // Verify request state after rejection - const updatedRequest = - await ParanetsRegistry.getLatestKnowledgeMinerAccessRequest( - paranetId, - miner.address, - ); - expect(updatedRequest.miner).to.equal(miner.address); - expect(updatedRequest.status).to.equal(3); // REJECTED status - expect(updatedRequest.createdAt).to.equal(latestRequest.createdAt); - expect(updatedRequest.updatedAt).to.be.gt(latestRequest.updatedAt); - - // Verify miner is not registered - expect( - await ParanetsRegistry.isKnowledgeMinerRegistered( - paranetId, - miner.address, - ), - ).to.be.equal(false); - }); - - it('Should revert when non-owner tries to add/remove miners', async () => { - const kcCreator = getDefaultKCCreator(accounts); - const publishingNode = getDefaultPublishingNode(accounts); - const receivingNodes = getDefaultReceivingNodes(accounts); - const miner = accounts[10]; - const nonOwner = accounts[11]; - - const { paranetKCStorageContract, paranetKCTokenId, paranetKATokenId } = - await setupParanet( - kcCreator, - publishingNode, - receivingNodes, - { - Paranet, - Profile, - Token, - KnowledgeCollection, - KnowledgeCollectionStorage, - }, - 'Test Paranet', - 'Test Paranet Description', - ACCESS_POLICIES.OPEN, - 1, - ACCESS_POLICIES.OPEN, - ); - - // Try to add miner as non-owner - await expect( - Paranet.connect(nonOwner).addParanetCuratedMiners( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - [miner.address], - ), - ).to.be.revertedWith("Caller isn't the owner of the KA"); - - // Try to remove miner as non-owner - await expect( - Paranet.connect(nonOwner).removeParanetCuratedMiners( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - [miner.address], - ), - ).to.be.revertedWith("Caller isn't the owner of the KA"); - }); - - it('Should revert when requesting access multiple times', async () => { - const kcCreator = getDefaultKCCreator(accounts); - const publishingNode = getDefaultPublishingNode(accounts); - const receivingNodes = getDefaultReceivingNodes(accounts); - const miner = accounts[10]; - - const { paranetKCStorageContract, paranetKCTokenId, paranetKATokenId } = - await setupParanet( - kcCreator, - publishingNode, - receivingNodes, - { - Paranet, - Profile, - Token, - KnowledgeCollection, - KnowledgeCollectionStorage, - }, - 'Test Paranet', - 'Test Paranet Description', - ACCESS_POLICIES.OPEN, - 1, - ACCESS_POLICIES.OPEN, - ); - - // First request - await Paranet.connect(miner).requestParanetCuratedMinerAccess( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - ); - - // Try to request again while first request is pending - await expect( - Paranet.connect(miner).requestParanetCuratedMinerAccess( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - ), - ).to.be.revertedWithCustomError( - Paranet, - 'ParanetCuratedMinerAccessRequestInvalidStatus', - ); - }); - - it('Should allow registered miner to submit KC but reject unregistered miner', async () => { - // Setup paranet with permissioned miners policy - const kcCreator = getDefaultKCCreator(accounts); - const publishingNode = getDefaultPublishingNode(accounts); - const receivingNodes = getDefaultReceivingNodes(accounts); - const miner1 = accounts[10]; - const miner2 = accounts[11]; - - const { - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - paranetId, - publishingNodeIdentityId, - receivingNodesIdentityIds, - } = await setupParanet( - kcCreator, - publishingNode, - receivingNodes, - { - Paranet, - Profile, - Token, - KnowledgeCollection, - KnowledgeCollectionStorage, - }, - 'Test Paranet', - 'Test Paranet Description', - ACCESS_POLICIES.OPEN, // nodes policy - 1, // miners policy - PERMISSIONED - ACCESS_POLICIES.OPEN, // submission policy - ); - - // Add miner1 as a curated miner - await Paranet.connect(kcCreator).addParanetCuratedMiners( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - [miner1.address], - ); - - // Create KC for miner1 - const signaturesData1 = await getKCSignaturesData( - publishingNode, - 1, - receivingNodes, - ); - const { collectionId: miner1CollectionId } = - await createKnowledgeCollection( - miner1, // Using miner1 as KC creator - publishingNodeIdentityId, - receivingNodesIdentityIds, - signaturesData1, - { - KnowledgeCollection: KnowledgeCollection, - Token: Token, - }, - ); - - // Create KC for miner2 - const signaturesData2 = await getKCSignaturesData( - publishingNode, - 1, - receivingNodes, - ); - const { collectionId: miner2CollectionId } = - await createKnowledgeCollection( - miner2, // Using miner2 as KC creator - publishingNodeIdentityId, - receivingNodesIdentityIds, - signaturesData2, - { - KnowledgeCollection: KnowledgeCollection, - Token: Token, - }, - ); - - // Miner1 (registered) submits KC - should succeed - await expect( - Paranet.connect(miner1).submitKnowledgeCollection( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - miner1CollectionId, - ), - ) - .to.emit(Paranet, 'KnowledgeCollectionSubmittedToParanet') - .withArgs( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - miner1CollectionId, - ); - - // Verify miner1's KC was added - const miner1CollectionBytes = ethers.keccak256( - ethers.solidityPacked( - ['address', 'uint256'], - [await KnowledgeCollectionStorage.getAddress(), miner1CollectionId], - ), - ); - - expect( - await ParanetsRegistry.isKnowledgeCollectionRegistered( - paranetId, - miner1CollectionBytes, - ), - ).to.be.equal(true); - - // Miner2 (unregistered) attempts to submit KC - should fail - await expect( - Paranet.connect(miner2).submitKnowledgeCollection( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - miner2CollectionId, - ), - ).to.be.revertedWith('Miner is not registered'); - - // Verify miner2's KC was not added - - const miner2CollectionBytes = ethers.keccak256( - ethers.solidityPacked( - ['address', 'uint256'], - [await KnowledgeCollectionStorage.getAddress(), miner2CollectionId], - ), - ); - expect( - await ParanetsRegistry.isKnowledgeCollectionRegistered( - paranetId, - miner2CollectionBytes, - ), - ).to.be.equal(false); - - // Verify total KC count is 1 (only miner1's KC) - expect( - await ParanetsRegistry.getKnowledgeCollectionsCount(paranetId), - ).to.equal(1); - }); - }); - - describe('Paranet Permissioned Nodes', () => { - it('Should allow owner to add and remove curated nodes', async () => { - // Setup paranet with permissioned nodes policy - const kcCreator = getDefaultKCCreator(accounts); - const publishingNode = getDefaultPublishingNode(accounts); - const receivingNodes = getDefaultReceivingNodes(accounts); - const node1 = accounts[10]; - const node2 = accounts[11]; - - // Create profiles for test nodes - await Profile.connect(node1).createProfile( - accounts[0].address, - [], // operational wallets - 'Node1', - '0x' + randomBytes(32).toString('hex'), - 0, - ); - await Profile.connect(node2).createProfile( - accounts[0].address, - [], // operational wallets - 'Node2', - '0x' + randomBytes(32).toString('hex'), - 0, - ); - const node1IdentityId = await IdentityStorage.getIdentityId( - node1.address, - ); - const node2IdentityId = await IdentityStorage.getIdentityId( - node2.address, - ); - - const { - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - paranetId, - } = await setupParanet( - kcCreator, - publishingNode, - receivingNodes, - { - Paranet, - Profile, - Token, - KnowledgeCollection, - KnowledgeCollectionStorage, - }, - 'Test Paranet', - 'Test Paranet Description', - 1, // NODES_ACCESS_POLICY_PERMISSIONED - ACCESS_POLICIES.OPEN, - ACCESS_POLICIES.OPEN, - ); - - // Verify initial state - expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( - 0, - ); - expect( - await ParanetsRegistry.isCuratedNode(paranetId, node1IdentityId), - ).to.be.equal(false); - expect( - await ParanetsRegistry.isCuratedNode(paranetId, node2IdentityId), - ).to.be.equal(false); - - // Add nodes - await expect( - Paranet.connect(kcCreator).addParanetCuratedNodes( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - [node1IdentityId, node2IdentityId], - ), - ) - .to.emit(Paranet, 'ParanetCuratedNodeAdded') - .withArgs( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - node1IdentityId, - ) - .to.emit(Paranet, 'ParanetCuratedNodeAdded') - .withArgs( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - node2IdentityId, - ); - - // Verify nodes were added - expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( - 2, - ); - expect( - await ParanetsRegistry.isCuratedNode(paranetId, node1IdentityId), - ).to.be.equal(true); - expect( - await ParanetsRegistry.isCuratedNode(paranetId, node2IdentityId), - ).to.be.equal(true); - - const curatedNodes = await ParanetsRegistry.getCuratedNodes(paranetId); - expect(curatedNodes[0].identityId).to.equal(node1IdentityId); - expect(curatedNodes[1].identityId).to.equal(node2IdentityId); - - // Remove node1 - await expect( - Paranet.connect(kcCreator).removeParanetCuratedNodes( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - [node1IdentityId], - ), - ) - .to.emit(Paranet, 'ParanetCuratedNodeRemoved') - .withArgs( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - node1IdentityId, - ); - - // Verify node1 was removed but node2 remains - expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( - 1, - ); - expect( - await ParanetsRegistry.isCuratedNode(paranetId, node1IdentityId), - ).to.be.equal(false); - expect( - await ParanetsRegistry.isCuratedNode(paranetId, node2IdentityId), - ).to.be.equal(true); - - const remainingNodes = await ParanetsRegistry.getCuratedNodes(paranetId); - expect(remainingNodes).to.have.lengthOf(1); - expect(remainingNodes[0].identityId).to.equal(node2IdentityId); - }); - - it('Should handle node join requests correctly', async () => { - // Setup paranet with permissioned nodes policy - const kcCreator = getDefaultKCCreator(accounts); - const publishingNode = getDefaultPublishingNode(accounts); - const receivingNodes = getDefaultReceivingNodes(accounts); - const applicantNode = accounts[10]; - - // Create profile for applicant node - await Profile.connect(applicantNode).createProfile( - accounts[0].address, - [], // operational wallets - 'Applicant', - '0x' + randomBytes(32).toString('hex'), - 0, - ); - const applicantIdentityId = await IdentityStorage.getIdentityId( - applicantNode.address, - ); - - const { - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - paranetId, - } = await setupParanet( - kcCreator, - publishingNode, - receivingNodes, - { - Paranet, - Profile, - Token, - KnowledgeCollection, - KnowledgeCollectionStorage, - }, - 'Test Paranet', - 'Test Paranet Description', - 1, // NODES_ACCESS_POLICY_PERMISSIONED - ACCESS_POLICIES.OPEN, - ACCESS_POLICIES.OPEN, - ); - - // Request to join - await expect( - Paranet.connect(applicantNode).requestParanetCuratedNodeAccess( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - ), - ) - .to.emit(Paranet, 'ParanetCuratedNodeJoinRequestCreated') - .withArgs( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - applicantIdentityId, - ); - - // Verify initial request state - const latestRequest = await ParanetsRegistry.getLatestNodeJoinRequest( - paranetId, - applicantIdentityId, - ); - expect(latestRequest.identityId).to.equal(applicantIdentityId); - expect(latestRequest.status).to.equal(1); // PENDING status - expect(latestRequest.createdAt).to.be.gt(0); - expect(latestRequest.updatedAt).to.equal(latestRequest.createdAt); - - // Approve request - await expect( - Paranet.connect(kcCreator).approveCuratedNode( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - applicantIdentityId, - ), - ) - .to.emit(Paranet, 'ParanetCuratedNodeJoinRequestAccepted') - .withArgs( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - applicantIdentityId, - ) - .to.emit(Paranet, 'ParanetCuratedNodeAdded') - .withArgs( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - applicantIdentityId, - ); - - // Verify request state after approval - const updatedRequest = await ParanetsRegistry.getLatestNodeJoinRequest( - paranetId, - applicantIdentityId, - ); - expect(updatedRequest.identityId).to.equal(applicantIdentityId); - expect(updatedRequest.status).to.equal(2); // ACCEPTED status - expect(updatedRequest.createdAt).to.equal(latestRequest.createdAt); - expect(updatedRequest.updatedAt).to.be.gt(latestRequest.updatedAt); - - // Verify node is now registered - expect( - await ParanetsRegistry.isCuratedNode(paranetId, applicantIdentityId), - ).to.be.equal(true); - }); - - it('Should handle node join request rejection correctly', async () => { - // Setup paranet with permissioned nodes policy - const kcCreator = getDefaultKCCreator(accounts); - const publishingNode = getDefaultPublishingNode(accounts); - const receivingNodes = getDefaultReceivingNodes(accounts); - const applicantNode = accounts[10]; - - // Create profile for applicant node - await Profile.connect(applicantNode).createProfile( - accounts[0].address, - [], // operational wallets - 'Applicant', - '0x' + randomBytes(32).toString('hex'), - 0, - ); - const applicantIdentityId = await IdentityStorage.getIdentityId( - applicantNode.address, - ); - - const { - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - paranetId, - } = await setupParanet( - kcCreator, - publishingNode, - receivingNodes, - { - Paranet, - Profile, - Token, - KnowledgeCollection, - KnowledgeCollectionStorage, - }, - 'Test Paranet', - 'Test Paranet Description', - 1, // NODES_ACCESS_POLICY_PERMISSIONED - ACCESS_POLICIES.OPEN, - ACCESS_POLICIES.OPEN, - ); - - // Request to join - await expect( - Paranet.connect(applicantNode).requestParanetCuratedNodeAccess( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - ), - ) - .to.emit(Paranet, 'ParanetCuratedNodeJoinRequestCreated') - .withArgs( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - applicantIdentityId, - ); - - // Verify initial request state - const latestRequest = await ParanetsRegistry.getLatestNodeJoinRequest( - paranetId, - applicantIdentityId, - ); - expect(latestRequest.identityId).to.equal(applicantIdentityId); - expect(latestRequest.status).to.equal(1); // PENDING status - - // Reject request - await expect( - Paranet.connect(kcCreator).rejectCuratedNode( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - applicantIdentityId, - ), - ) - .to.emit(Paranet, 'ParanetCuratedNodeJoinRequestRejected') - .withArgs( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - applicantIdentityId, - ); - - // Verify request state after rejection - const updatedRequest = await ParanetsRegistry.getLatestNodeJoinRequest( - paranetId, - applicantIdentityId, - ); - expect(updatedRequest.identityId).to.equal(applicantIdentityId); - expect(updatedRequest.status).to.equal(3); // REJECTED status - expect(updatedRequest.createdAt).to.equal(latestRequest.createdAt); - expect(updatedRequest.updatedAt).to.be.gt(latestRequest.updatedAt); - - // Verify node is not registered - expect( - await ParanetsRegistry.isCuratedNode(paranetId, applicantIdentityId), - ).to.be.equal(false); - }); - - it('Should handle edge cases when adding and removing multiple nodes', async () => { - const kcCreator = getDefaultKCCreator(accounts); - const publishingNode = getDefaultPublishingNode(accounts); - const receivingNodes = getDefaultReceivingNodes(accounts); - const node1 = accounts[10]; - const node2 = accounts[11]; - const node3 = accounts[12]; - - // Create profiles for test nodes - await Profile.connect(node1).createProfile( - accounts[0].address, - [], // operational wallets - 'Node1', - '0x' + randomBytes(32).toString('hex'), - 0, - ); - await Profile.connect(node2).createProfile( - accounts[0].address, - [], // operational wallets - 'Node2', - '0x' + randomBytes(32).toString('hex'), - 0, - ); - await Profile.connect(node3).createProfile( - accounts[0].address, - [], // operational wallets - 'Node3', - '0x' + randomBytes(32).toString('hex'), - 0, - ); - const node1IdentityId = await IdentityStorage.getIdentityId( - node1.address, - ); - const node2IdentityId = await IdentityStorage.getIdentityId( - node2.address, - ); - const node3IdentityId = await IdentityStorage.getIdentityId( - node3.address, - ); - - const { - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - paranetId, - } = await setupParanet( - kcCreator, - publishingNode, - receivingNodes, - { - Paranet, - Profile, - Token, - KnowledgeCollection, - KnowledgeCollectionStorage, - }, - 'Test Paranet', - 'Test Paranet Description', - 1, // NODES_ACCESS_POLICY_PERMISSIONED - ACCESS_POLICIES.OPEN, - ACCESS_POLICIES.OPEN, - ); - - // Add nodes in sequence - await Paranet.connect(kcCreator).addParanetCuratedNodes( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - [node1IdentityId], - ); - - await Paranet.connect(kcCreator).addParanetCuratedNodes( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - [node2IdentityId, node3IdentityId], - ); - - // Verify all nodes were added - expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( - 3, - ); - const allNodes = await ParanetsRegistry.getCuratedNodes(paranetId); - expect(allNodes.map((node) => node.identityId)).to.have.members([ - node1IdentityId, - node2IdentityId, - node3IdentityId, - ]); - - // Remove nodes from edges (first and last) - await Paranet.connect(kcCreator).removeParanetCuratedNodes( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - [node1IdentityId, node3IdentityId], - ); - - // Verify middle node remains - expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( - 1, - ); - expect( - await ParanetsRegistry.isCuratedNode(paranetId, node1IdentityId), - ).to.be.equal(false); - expect( - await ParanetsRegistry.isCuratedNode(paranetId, node2IdentityId), - ).to.be.equal(true); - expect( - await ParanetsRegistry.isCuratedNode(paranetId, node3IdentityId), - ).to.be.equal(false); - - // Try to remove non-existent node - should revert - await expect( - Paranet.connect(kcCreator).removeParanetCuratedNodes( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - [node1IdentityId], // Already removed - ), - ).to.be.revertedWithCustomError(Paranet, 'ParanetCuratedNodeDoesntExist'); - - // Verify state remains unchanged - expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( - 1, - ); - expect( - await ParanetsRegistry.isCuratedNode(paranetId, node2IdentityId), - ).to.be.equal(true); - - // Try to add duplicate node - await expect( - Paranet.connect(kcCreator).addParanetCuratedNodes( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - [node2IdentityId], - ), - ).to.be.revertedWithCustomError( - Paranet, - 'ParanetCuratedNodeHasAlreadyBeenAdded', - ); - - expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( - 1, - ); - const finalNodes = await ParanetsRegistry.getCuratedNodes(paranetId); - expect(finalNodes).to.have.lengthOf(1); - expect(finalNodes[0].identityId).to.equal(node2IdentityId); - }); - }); + // describe('Paranet Permissioned Miners', () => { + // it('Should allow owner to add and remove curated miners', async () => { + // // Setup paranet with permissioned miners policy + // const kcCreator = getDefaultKCCreator(accounts); + // const publishingNode = getDefaultPublishingNode(accounts); + // const receivingNodes = getDefaultReceivingNodes(accounts); + // const miner1 = accounts[10]; + // const miner2 = accounts[11]; + + // const { + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // paranetId, // Add this to destructuring + // } = await setupParanet( + // kcCreator, + // publishingNode, + // receivingNodes, + // { + // Paranet, + // Profile, + // Token, + // KnowledgeCollection, + // KnowledgeCollectionStorage, + // }, + // 'Test Paranet', + // 'Test Paranet Description', + // ACCESS_POLICIES.OPEN, // nodes policy + // 1, // miners policy + // ACCESS_POLICIES.OPEN, // submission policy + // ); + + // // Verify initial state + // expect( + // await ParanetsRegistry.getKnowledgeMinersCount(paranetId), + // ).to.equal(0); + // expect( + // await ParanetsRegistry.isKnowledgeMinerRegistered( + // paranetId, + // miner1.address, + // ), + // ).to.be.equal(false); + // expect( + // await ParanetsRegistry.isKnowledgeMinerRegistered( + // paranetId, + // miner2.address, + // ), + // ).to.be.equal(false); + + // // Add miners + // await expect( + // Paranet.connect(kcCreator).addParanetCuratedMiners( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // [miner1.address, miner2.address], + // ), + // ) + // .to.emit(Paranet, 'ParanetCuratedMinerAdded') + // .withArgs( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // miner1.address, + // ) + // .to.emit(Paranet, 'ParanetCuratedMinerAdded') + // .withArgs( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // miner2.address, + // ); + + // // Verify miners were added + // expect( + // await ParanetsRegistry.getKnowledgeMinersCount(paranetId), + // ).to.equal(2); + // expect( + // await ParanetsRegistry.isKnowledgeMinerRegistered( + // paranetId, + // miner1.address, + // ), + // ).to.be.equal(true); + // expect( + // await ParanetsRegistry.isKnowledgeMinerRegistered( + // paranetId, + // miner2.address, + // ), + // ).to.be.equal(true); + + // const registeredMiners = + // await ParanetsRegistry.getKnowledgeMiners(paranetId); + // expect(registeredMiners[0]).to.be.equal(miner1.address); + // expect(registeredMiners[1]).to.be.equal(miner2.address); + + // // Remove miners + // await expect( + // Paranet.connect(kcCreator).removeParanetCuratedMiners( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // [miner1.address], + // ), + // ) + // .to.emit(Paranet, 'ParanetCuratedMinerRemoved') + // .withArgs( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // miner1.address, + // ); + + // // Verify miner1 was removed but miner2 remains + // expect( + // await ParanetsRegistry.getKnowledgeMinersCount(paranetId), + // ).to.equal(1); + // expect( + // await ParanetsRegistry.isKnowledgeMinerRegistered( + // paranetId, + // miner1.address, + // ), + // ).to.be.equal(false); + // expect( + // await ParanetsRegistry.isKnowledgeMinerRegistered( + // paranetId, + // miner2.address, + // ), + // ).to.be.equal(true); + + // const remainingMiners = + // await ParanetsRegistry.getKnowledgeMiners(paranetId); + // expect(remainingMiners).to.have.lengthOf(1); + // expect(remainingMiners[0]).to.equal(miner2.address); + // }); + + // it('Should handle miner access requests correctly', async () => { + // // Setup paranet with permissioned miners policy + // const kcCreator = getDefaultKCCreator(accounts); + // const publishingNode = getDefaultPublishingNode(accounts); + // const receivingNodes = getDefaultReceivingNodes(accounts); + // const miner = accounts[10]; + + // const { + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // paranetId, + // } = await setupParanet( + // kcCreator, + // publishingNode, + // receivingNodes, + // { + // Paranet, + // Profile, + // Token, + // KnowledgeCollection, + // KnowledgeCollectionStorage, + // }, + // 'Test Paranet', + // 'Test Paranet Description', + // ACCESS_POLICIES.OPEN, // nodes policy + // 1, // miners policy + // ACCESS_POLICIES.OPEN, // submission policy + // ); + + // // Request access + // await expect( + // Paranet.connect(miner).requestParanetCuratedMinerAccess( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // ), + // ) + // .to.emit(Paranet, 'ParanetCuratedMinerAccessRequestCreated') + // .withArgs( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // miner.address, + // ); + + // // Verify request state + // const latestRequest = + // await ParanetsRegistry.getLatestKnowledgeMinerAccessRequest( + // paranetId, + // miner.address, + // ); + // expect(latestRequest.miner).to.equal(miner.address); + // expect(latestRequest.status).to.equal(1); // PENDING status + // expect(latestRequest.createdAt).to.be.gt(0); + // expect(latestRequest.updatedAt).to.equal(latestRequest.createdAt); + + // // Approve request + // await expect( + // Paranet.connect(kcCreator).approveCuratedMiner( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // miner.address, + // ), + // ) + // .to.emit(Paranet, 'ParanetCuratedMinerAccessRequestAccepted') + // .withArgs( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // miner.address, + // ) + // .to.emit(Paranet, 'ParanetCuratedMinerAdded') + // .withArgs( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // miner.address, + // ); + + // // Verify request state after approval + // const updatedRequest = + // await ParanetsRegistry.getLatestKnowledgeMinerAccessRequest( + // paranetId, + // miner.address, + // ); + // expect(updatedRequest.miner).to.equal(miner.address); + // expect(updatedRequest.status).to.equal(2); // ACCEPTED status + // expect(updatedRequest.createdAt).to.equal(latestRequest.createdAt); + // expect(updatedRequest.updatedAt).to.be.gt(latestRequest.updatedAt); + + // // Verify miner is now registered + // expect( + // await ParanetsRegistry.isKnowledgeMinerRegistered( + // paranetId, + // miner.address, + // ), + // ).to.be.equal(true); + // }); + + // it('Should handle miner access request rejection', async () => { + // // Setup paranet with permissioned miners policy + // const kcCreator = getDefaultKCCreator(accounts); + // const publishingNode = getDefaultPublishingNode(accounts); + // const receivingNodes = getDefaultReceivingNodes(accounts); + // const miner = accounts[10]; + + // const { + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // paranetId, + // } = await setupParanet( + // kcCreator, + // publishingNode, + // receivingNodes, + // { + // Paranet, + // Profile, + // Token, + // KnowledgeCollection, + // KnowledgeCollectionStorage, + // }, + // 'Test Paranet', + // 'Test Paranet Description', + // ACCESS_POLICIES.OPEN, // nodes policy + // 1, // miners policy + // ACCESS_POLICIES.OPEN, // submission policy + // ); + + // // Request access + // await Paranet.connect(miner).requestParanetCuratedMinerAccess( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // ); + + // // Verify initial request state + // const latestRequest = + // await ParanetsRegistry.getLatestKnowledgeMinerAccessRequest( + // paranetId, + // miner.address, + // ); + // expect(latestRequest.miner).to.equal(miner.address); + // expect(latestRequest.status).to.equal(1); // PENDING status + // expect(latestRequest.createdAt).to.be.gt(0); + // expect(latestRequest.updatedAt).to.equal(latestRequest.createdAt); + + // // Reject request + // await expect( + // Paranet.connect(kcCreator).rejectCuratedMiner( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // miner.address, + // ), + // ) + // .to.emit(Paranet, 'ParanetCuratedMinerAccessRequestRejected') + // .withArgs( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // miner.address, + // ); + + // // Verify request state after rejection + // const updatedRequest = + // await ParanetsRegistry.getLatestKnowledgeMinerAccessRequest( + // paranetId, + // miner.address, + // ); + // expect(updatedRequest.miner).to.equal(miner.address); + // expect(updatedRequest.status).to.equal(3); // REJECTED status + // expect(updatedRequest.createdAt).to.equal(latestRequest.createdAt); + // expect(updatedRequest.updatedAt).to.be.gt(latestRequest.updatedAt); + + // // Verify miner is not registered + // expect( + // await ParanetsRegistry.isKnowledgeMinerRegistered( + // paranetId, + // miner.address, + // ), + // ).to.be.equal(false); + // }); + + // it('Should revert when non-owner tries to add/remove miners', async () => { + // const kcCreator = getDefaultKCCreator(accounts); + // const publishingNode = getDefaultPublishingNode(accounts); + // const receivingNodes = getDefaultReceivingNodes(accounts); + // const miner = accounts[10]; + // const nonOwner = accounts[11]; + + // const { paranetKCStorageContract, paranetKCTokenId, paranetKATokenId } = + // await setupParanet( + // kcCreator, + // publishingNode, + // receivingNodes, + // { + // Paranet, + // Profile, + // Token, + // KnowledgeCollection, + // KnowledgeCollectionStorage, + // }, + // 'Test Paranet', + // 'Test Paranet Description', + // ACCESS_POLICIES.OPEN, + // 1, + // ACCESS_POLICIES.OPEN, + // ); + + // // Try to add miner as non-owner + // await expect( + // Paranet.connect(nonOwner).addParanetCuratedMiners( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // [miner.address], + // ), + // ).to.be.revertedWith("Caller isn't the owner of the KA"); + + // // Try to remove miner as non-owner + // await expect( + // Paranet.connect(nonOwner).removeParanetCuratedMiners( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // [miner.address], + // ), + // ).to.be.revertedWith("Caller isn't the owner of the KA"); + // }); + + // it('Should revert when requesting access multiple times', async () => { + // const kcCreator = getDefaultKCCreator(accounts); + // const publishingNode = getDefaultPublishingNode(accounts); + // const receivingNodes = getDefaultReceivingNodes(accounts); + // const miner = accounts[10]; + + // const { paranetKCStorageContract, paranetKCTokenId, paranetKATokenId } = + // await setupParanet( + // kcCreator, + // publishingNode, + // receivingNodes, + // { + // Paranet, + // Profile, + // Token, + // KnowledgeCollection, + // KnowledgeCollectionStorage, + // }, + // 'Test Paranet', + // 'Test Paranet Description', + // ACCESS_POLICIES.OPEN, + // 1, + // ACCESS_POLICIES.OPEN, + // ); + + // // First request + // await Paranet.connect(miner).requestParanetCuratedMinerAccess( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // ); + + // // Try to request again while first request is pending + // await expect( + // Paranet.connect(miner).requestParanetCuratedMinerAccess( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // ), + // ).to.be.revertedWithCustomError( + // Paranet, + // 'ParanetCuratedMinerAccessRequestInvalidStatus', + // ); + // }); + + // it('Should allow registered miner to submit KC but reject unregistered miner', async () => { + // // Setup paranet with permissioned miners policy + // const kcCreator = getDefaultKCCreator(accounts); + // const publishingNode = getDefaultPublishingNode(accounts); + // const receivingNodes = getDefaultReceivingNodes(accounts); + // const miner1 = accounts[10]; + // const miner2 = accounts[11]; + + // const { + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // paranetId, + // publishingNodeIdentityId, + // receivingNodesIdentityIds, + // } = await setupParanet( + // kcCreator, + // publishingNode, + // receivingNodes, + // { + // Paranet, + // Profile, + // Token, + // KnowledgeCollection, + // KnowledgeCollectionStorage, + // }, + // 'Test Paranet', + // 'Test Paranet Description', + // ACCESS_POLICIES.OPEN, // nodes policy + // 1, // miners policy - PERMISSIONED + // ACCESS_POLICIES.OPEN, // submission policy + // ); + + // // Add miner1 as a curated miner + // await Paranet.connect(kcCreator).addParanetCuratedMiners( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // [miner1.address], + // ); + + // // Create KC for miner1 + // const signaturesData1 = await getKCSignaturesData( + // publishingNode, + // 1, + // receivingNodes, + // ); + // const { collectionId: miner1CollectionId } = + // await createKnowledgeCollection( + // miner1, // Using miner1 as KC creator + // publishingNodeIdentityId, + // receivingNodesIdentityIds, + // signaturesData1, + // { + // KnowledgeCollection: KnowledgeCollection, + // Token: Token, + // }, + // ); + + // // Create KC for miner2 + // const signaturesData2 = await getKCSignaturesData( + // publishingNode, + // 1, + // receivingNodes, + // ); + // const { collectionId: miner2CollectionId } = + // await createKnowledgeCollection( + // miner2, // Using miner2 as KC creator + // publishingNodeIdentityId, + // receivingNodesIdentityIds, + // signaturesData2, + // { + // KnowledgeCollection: KnowledgeCollection, + // Token: Token, + // }, + // ); + + // // Miner1 (registered) submits KC - should succeed + // await expect( + // Paranet.connect(miner1).submitKnowledgeCollection( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // await KnowledgeCollectionStorage.getAddress(), + // miner1CollectionId, + // ), + // ) + // .to.emit(Paranet, 'KnowledgeCollectionSubmittedToParanet') + // .withArgs( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // await KnowledgeCollectionStorage.getAddress(), + // miner1CollectionId, + // ); + + // // Verify miner1's KC was added + // const miner1CollectionBytes = ethers.keccak256( + // ethers.solidityPacked( + // ['address', 'uint256'], + // [await KnowledgeCollectionStorage.getAddress(), miner1CollectionId], + // ), + // ); + + // expect( + // await ParanetsRegistry.isKnowledgeCollectionRegistered( + // paranetId, + // miner1CollectionBytes, + // ), + // ).to.be.equal(true); + + // // Miner2 (unregistered) attempts to submit KC - should fail + // await expect( + // Paranet.connect(miner2).submitKnowledgeCollection( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // await KnowledgeCollectionStorage.getAddress(), + // miner2CollectionId, + // ), + // ).to.be.revertedWith('Miner is not registered'); + + // // Verify miner2's KC was not added + + // const miner2CollectionBytes = ethers.keccak256( + // ethers.solidityPacked( + // ['address', 'uint256'], + // [await KnowledgeCollectionStorage.getAddress(), miner2CollectionId], + // ), + // ); + // expect( + // await ParanetsRegistry.isKnowledgeCollectionRegistered( + // paranetId, + // miner2CollectionBytes, + // ), + // ).to.be.equal(false); + + // // Verify total KC count is 1 (only miner1's KC) + // expect( + // await ParanetsRegistry.getKnowledgeCollectionsCount(paranetId), + // ).to.equal(1); + // }); + // }); + + // describe('Paranet Permissioned Nodes', () => { + // it('Should allow owner to add and remove curated nodes', async () => { + // // Setup paranet with permissioned nodes policy + // const kcCreator = getDefaultKCCreator(accounts); + // const publishingNode = getDefaultPublishingNode(accounts); + // const receivingNodes = getDefaultReceivingNodes(accounts); + // const node1 = accounts[10]; + // const node2 = accounts[11]; + + // // Create profiles for test nodes + // await Profile.connect(node1).createProfile( + // accounts[0].address, + // [], // operational wallets + // 'Node1', + // '0x' + randomBytes(32).toString('hex'), + // 0, + // ); + // await Profile.connect(node2).createProfile( + // accounts[0].address, + // [], // operational wallets + // 'Node2', + // '0x' + randomBytes(32).toString('hex'), + // 0, + // ); + // const node1IdentityId = await IdentityStorage.getIdentityId( + // node1.address, + // ); + // const node2IdentityId = await IdentityStorage.getIdentityId( + // node2.address, + // ); + + // const { + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // paranetId, + // } = await setupParanet( + // kcCreator, + // publishingNode, + // receivingNodes, + // { + // Paranet, + // Profile, + // Token, + // KnowledgeCollection, + // KnowledgeCollectionStorage, + // }, + // 'Test Paranet', + // 'Test Paranet Description', + // 1, // NODES_ACCESS_POLICY_PERMISSIONED + // ACCESS_POLICIES.OPEN, + // ACCESS_POLICIES.OPEN, + // ); + + // // Verify initial state + // expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( + // 0, + // ); + // expect( + // await ParanetsRegistry.isCuratedNode(paranetId, node1IdentityId), + // ).to.be.equal(false); + // expect( + // await ParanetsRegistry.isCuratedNode(paranetId, node2IdentityId), + // ).to.be.equal(false); + + // // Add nodes + // await expect( + // Paranet.connect(kcCreator).addParanetCuratedNodes( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // [node1IdentityId, node2IdentityId], + // ), + // ) + // .to.emit(Paranet, 'ParanetCuratedNodeAdded') + // .withArgs( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // node1IdentityId, + // ) + // .to.emit(Paranet, 'ParanetCuratedNodeAdded') + // .withArgs( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // node2IdentityId, + // ); + + // // Verify nodes were added + // expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( + // 2, + // ); + // expect( + // await ParanetsRegistry.isCuratedNode(paranetId, node1IdentityId), + // ).to.be.equal(true); + // expect( + // await ParanetsRegistry.isCuratedNode(paranetId, node2IdentityId), + // ).to.be.equal(true); + + // const curatedNodes = await ParanetsRegistry.getCuratedNodes(paranetId); + // expect(curatedNodes[0].identityId).to.equal(node1IdentityId); + // expect(curatedNodes[1].identityId).to.equal(node2IdentityId); + + // // Remove node1 + // await expect( + // Paranet.connect(kcCreator).removeParanetCuratedNodes( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // [node1IdentityId], + // ), + // ) + // .to.emit(Paranet, 'ParanetCuratedNodeRemoved') + // .withArgs( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // node1IdentityId, + // ); + + // // Verify node1 was removed but node2 remains + // expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( + // 1, + // ); + // expect( + // await ParanetsRegistry.isCuratedNode(paranetId, node1IdentityId), + // ).to.be.equal(false); + // expect( + // await ParanetsRegistry.isCuratedNode(paranetId, node2IdentityId), + // ).to.be.equal(true); + + // const remainingNodes = await ParanetsRegistry.getCuratedNodes(paranetId); + // expect(remainingNodes).to.have.lengthOf(1); + // expect(remainingNodes[0].identityId).to.equal(node2IdentityId); + // }); + + // it('Should handle node join requests correctly', async () => { + // // Setup paranet with permissioned nodes policy + // const kcCreator = getDefaultKCCreator(accounts); + // const publishingNode = getDefaultPublishingNode(accounts); + // const receivingNodes = getDefaultReceivingNodes(accounts); + // const applicantNode = accounts[10]; + + // // Create profile for applicant node + // await Profile.connect(applicantNode).createProfile( + // accounts[0].address, + // [], // operational wallets + // 'Applicant', + // '0x' + randomBytes(32).toString('hex'), + // 0, + // ); + // const applicantIdentityId = await IdentityStorage.getIdentityId( + // applicantNode.address, + // ); + + // const { + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // paranetId, + // } = await setupParanet( + // kcCreator, + // publishingNode, + // receivingNodes, + // { + // Paranet, + // Profile, + // Token, + // KnowledgeCollection, + // KnowledgeCollectionStorage, + // }, + // 'Test Paranet', + // 'Test Paranet Description', + // 1, // NODES_ACCESS_POLICY_PERMISSIONED + // ACCESS_POLICIES.OPEN, + // ACCESS_POLICIES.OPEN, + // ); + + // // Request to join + // await expect( + // Paranet.connect(applicantNode).requestParanetCuratedNodeAccess( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // ), + // ) + // .to.emit(Paranet, 'ParanetCuratedNodeJoinRequestCreated') + // .withArgs( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // applicantIdentityId, + // ); + + // // Verify initial request state + // const latestRequest = await ParanetsRegistry.getLatestNodeJoinRequest( + // paranetId, + // applicantIdentityId, + // ); + // expect(latestRequest.identityId).to.equal(applicantIdentityId); + // expect(latestRequest.status).to.equal(1); // PENDING status + // expect(latestRequest.createdAt).to.be.gt(0); + // expect(latestRequest.updatedAt).to.equal(latestRequest.createdAt); + + // // Approve request + // await expect( + // Paranet.connect(kcCreator).approveCuratedNode( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // applicantIdentityId, + // ), + // ) + // .to.emit(Paranet, 'ParanetCuratedNodeJoinRequestAccepted') + // .withArgs( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // applicantIdentityId, + // ) + // .to.emit(Paranet, 'ParanetCuratedNodeAdded') + // .withArgs( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // applicantIdentityId, + // ); + + // // Verify request state after approval + // const updatedRequest = await ParanetsRegistry.getLatestNodeJoinRequest( + // paranetId, + // applicantIdentityId, + // ); + // expect(updatedRequest.identityId).to.equal(applicantIdentityId); + // expect(updatedRequest.status).to.equal(2); // ACCEPTED status + // expect(updatedRequest.createdAt).to.equal(latestRequest.createdAt); + // expect(updatedRequest.updatedAt).to.be.gt(latestRequest.updatedAt); + + // // Verify node is now registered + // expect( + // await ParanetsRegistry.isCuratedNode(paranetId, applicantIdentityId), + // ).to.be.equal(true); + // }); + + // it('Should handle node join request rejection correctly', async () => { + // // Setup paranet with permissioned nodes policy + // const kcCreator = getDefaultKCCreator(accounts); + // const publishingNode = getDefaultPublishingNode(accounts); + // const receivingNodes = getDefaultReceivingNodes(accounts); + // const applicantNode = accounts[10]; + + // // Create profile for applicant node + // await Profile.connect(applicantNode).createProfile( + // accounts[0].address, + // [], // operational wallets + // 'Applicant', + // '0x' + randomBytes(32).toString('hex'), + // 0, + // ); + // const applicantIdentityId = await IdentityStorage.getIdentityId( + // applicantNode.address, + // ); + + // const { + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // paranetId, + // } = await setupParanet( + // kcCreator, + // publishingNode, + // receivingNodes, + // { + // Paranet, + // Profile, + // Token, + // KnowledgeCollection, + // KnowledgeCollectionStorage, + // }, + // 'Test Paranet', + // 'Test Paranet Description', + // 1, // NODES_ACCESS_POLICY_PERMISSIONED + // ACCESS_POLICIES.OPEN, + // ACCESS_POLICIES.OPEN, + // ); + + // // Request to join + // await expect( + // Paranet.connect(applicantNode).requestParanetCuratedNodeAccess( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // ), + // ) + // .to.emit(Paranet, 'ParanetCuratedNodeJoinRequestCreated') + // .withArgs( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // applicantIdentityId, + // ); + + // // Verify initial request state + // const latestRequest = await ParanetsRegistry.getLatestNodeJoinRequest( + // paranetId, + // applicantIdentityId, + // ); + // expect(latestRequest.identityId).to.equal(applicantIdentityId); + // expect(latestRequest.status).to.equal(1); // PENDING status + + // // Reject request + // await expect( + // Paranet.connect(kcCreator).rejectCuratedNode( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // applicantIdentityId, + // ), + // ) + // .to.emit(Paranet, 'ParanetCuratedNodeJoinRequestRejected') + // .withArgs( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // applicantIdentityId, + // ); + + // // Verify request state after rejection + // const updatedRequest = await ParanetsRegistry.getLatestNodeJoinRequest( + // paranetId, + // applicantIdentityId, + // ); + // expect(updatedRequest.identityId).to.equal(applicantIdentityId); + // expect(updatedRequest.status).to.equal(3); // REJECTED status + // expect(updatedRequest.createdAt).to.equal(latestRequest.createdAt); + // expect(updatedRequest.updatedAt).to.be.gt(latestRequest.updatedAt); + + // // Verify node is not registered + // expect( + // await ParanetsRegistry.isCuratedNode(paranetId, applicantIdentityId), + // ).to.be.equal(false); + // }); + + // it('Should handle edge cases when adding and removing multiple nodes', async () => { + // const kcCreator = getDefaultKCCreator(accounts); + // const publishingNode = getDefaultPublishingNode(accounts); + // const receivingNodes = getDefaultReceivingNodes(accounts); + // const node1 = accounts[10]; + // const node2 = accounts[11]; + // const node3 = accounts[12]; + + // // Create profiles for test nodes + // await Profile.connect(node1).createProfile( + // accounts[0].address, + // [], // operational wallets + // 'Node1', + // '0x' + randomBytes(32).toString('hex'), + // 0, + // ); + // await Profile.connect(node2).createProfile( + // accounts[0].address, + // [], // operational wallets + // 'Node2', + // '0x' + randomBytes(32).toString('hex'), + // 0, + // ); + // await Profile.connect(node3).createProfile( + // accounts[0].address, + // [], // operational wallets + // 'Node3', + // '0x' + randomBytes(32).toString('hex'), + // 0, + // ); + // const node1IdentityId = await IdentityStorage.getIdentityId( + // node1.address, + // ); + // const node2IdentityId = await IdentityStorage.getIdentityId( + // node2.address, + // ); + // const node3IdentityId = await IdentityStorage.getIdentityId( + // node3.address, + // ); + + // const { + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // paranetId, + // } = await setupParanet( + // kcCreator, + // publishingNode, + // receivingNodes, + // { + // Paranet, + // Profile, + // Token, + // KnowledgeCollection, + // KnowledgeCollectionStorage, + // }, + // 'Test Paranet', + // 'Test Paranet Description', + // 1, // NODES_ACCESS_POLICY_PERMISSIONED + // ACCESS_POLICIES.OPEN, + // ACCESS_POLICIES.OPEN, + // ); + + // // Add nodes in sequence + // await Paranet.connect(kcCreator).addParanetCuratedNodes( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // [node1IdentityId], + // ); + + // await Paranet.connect(kcCreator).addParanetCuratedNodes( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // [node2IdentityId, node3IdentityId], + // ); + + // // Verify all nodes were added + // expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( + // 3, + // ); + // const allNodes = await ParanetsRegistry.getCuratedNodes(paranetId); + // expect(allNodes.map((node) => node.identityId)).to.have.members([ + // node1IdentityId, + // node2IdentityId, + // node3IdentityId, + // ]); + + // // Remove nodes from edges (first and last) + // await Paranet.connect(kcCreator).removeParanetCuratedNodes( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // [node1IdentityId, node3IdentityId], + // ); + + // // Verify middle node remains + // expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( + // 1, + // ); + // expect( + // await ParanetsRegistry.isCuratedNode(paranetId, node1IdentityId), + // ).to.be.equal(false); + // expect( + // await ParanetsRegistry.isCuratedNode(paranetId, node2IdentityId), + // ).to.be.equal(true); + // expect( + // await ParanetsRegistry.isCuratedNode(paranetId, node3IdentityId), + // ).to.be.equal(false); + + // // Try to remove non-existent node - should revert + // await expect( + // Paranet.connect(kcCreator).removeParanetCuratedNodes( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // [node1IdentityId], // Already removed + // ), + // ).to.be.revertedWithCustomError(Paranet, 'ParanetCuratedNodeDoesntExist'); + + // // Verify state remains unchanged + // expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( + // 1, + // ); + // expect( + // await ParanetsRegistry.isCuratedNode(paranetId, node2IdentityId), + // ).to.be.equal(true); + + // // Try to add duplicate node + // await expect( + // Paranet.connect(kcCreator).addParanetCuratedNodes( + // paranetKCStorageContract, + // paranetKCTokenId, + // paranetKATokenId, + // [node2IdentityId], + // ), + // ).to.be.revertedWithCustomError( + // Paranet, + // 'ParanetCuratedNodeHasAlreadyBeenAdded', + // ); + + // expect(await ParanetsRegistry.getCuratedNodesCount(paranetId)).to.equal( + // 1, + // ); + // const finalNodes = await ParanetsRegistry.getCuratedNodes(paranetId); + // expect(finalNodes).to.have.lengthOf(1); + // expect(finalNodes[0].identityId).to.equal(node2IdentityId); + // }); + // }); describe('Paranet Incentives Pool Rewards', () => { it('Should handle claiming rewards from multiple incentives pools', async () => { From ead10df2df078082de8a4bc2f2475a4cd1a23620 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Mon, 24 Feb 2025 12:57:33 +0100 Subject: [PATCH 145/153] Move tests to the same section --- test/integration/Paranet.test.ts | 2479 +++++++++++++++--------------- 1 file changed, 1240 insertions(+), 1239 deletions(-) diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index 5c8323d7..26c0506f 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -418,10 +418,13 @@ describe('@unit Paranet', () => { expect(poolFactoryVersion).to.equal('1.0.0'); // Incentives pool factory helper - const poolFactoryHelperName = await ParanetIncentivesPoolFactory.name(); + const poolFactoryHelperName = + await ParanetIncentivesPoolFactoryHelper.name(); const poolFactoryHelperVersion = - await ParanetIncentivesPoolFactory.version(); - expect(poolFactoryHelperName).to.equal('ParanetIncentivesPoolFactory'); + await ParanetIncentivesPoolFactoryHelper.version(); + expect(poolFactoryHelperName).to.equal( + 'ParanetIncentivesPoolFactoryHelper', + ); expect(poolFactoryHelperVersion).to.equal('1.0.0'); const kcCreator = getDefaultKCCreator(accounts); @@ -1770,21 +1773,19 @@ describe('@unit Paranet', () => { .getClaimableKnowledgeMinerRewardAmount(); expect(remainingClaimable).to.equal(0); }); - }); - describe('Submit Knowledge Collection to Paranet', () => { - it('Should submit knowledge collection to paranet successfully', async () => { - // 1. Setup paranet first + it('Should handle claiming rewards from multiple incentives pools', async () => { + // 1. Setup paranet with initial configuration const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); const receivingNodes = getDefaultReceivingNodes(accounts); const { - // paranetOwner, - paranetId, + // paranetId, paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, + paranetOwner, publishingNodeIdentityId, receivingNodesIdentityIds, } = await setupParanet(kcCreator, publishingNode, receivingNodes, { @@ -1795,23 +1796,105 @@ describe('@unit Paranet', () => { KnowledgeCollectionStorage, }); + // 2. Deploy two incentive pools with different parameters + const tx1 = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ethers.parseUnits('1', 12), // 1 NEURO per 1 TRAC + 1000, // 10% operator + 2000, // 20% voters + 'Pool1', + await Token.getAddress(), + ); + const receipt1 = await tx1.wait(); + const event1 = receipt1!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolDeployed', + ).topicHash, + ) as EventLog; + + const tx2 = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ethers.parseUnits('2', 12), // 2 NEURO per 1 TRAC + 1500, // 15% operator + 2500, // 25% voters + 'Pool2', + await Token.getAddress(), + ); + const receipt2 = await tx2.wait(); + const event2 = receipt2!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolDeployed', + ).topicHash, + ) as EventLog; + + // 3. Fund both pools + const pool1Amount = ethers.parseUnits('100', 18); // 100 NEURO + const pool2Amount = ethers.parseUnits('200', 18); // 200 NEURO + await Token.connect(paranetOwner).approve(event1?.args[3], pool1Amount); + await Token.connect(paranetOwner).approve(event2?.args[3], pool2Amount); + + const pool1Storage = await hre.ethers.getContractAt( + 'ParanetIncentivesPoolStorage', + event1?.args[3], + ); + const pool1 = await hre.ethers.getContractAt( + 'ParanetIncentivesPool', + event1?.args[4], + ); + + const pool2Storage = await hre.ethers.getContractAt( + 'ParanetIncentivesPoolStorage', + event2?.args[3], + ); + const pool2 = await hre.ethers.getContractAt( + 'ParanetIncentivesPool', + event2?.args[4], + ); + + await Token.connect(accounts[0]).mint(pool1Storage, pool1Amount); + await Token.connect(accounts[0]).mint(pool2Storage, pool2Amount); + + expect(await pool1Storage.getBalance()).to.equal(pool1Amount); + expect(await pool1Storage.totalMinersclaimedToken()).to.equal(0); + expect(await pool1Storage.totalOperatorsclaimedToken()).to.equal(0); + expect(await pool1Storage.totalVotersclaimedToken()).to.equal(0); + + expect(await pool2Storage.getBalance()).to.equal(pool2Amount); + expect(await pool2Storage.totalMinersclaimedToken()).to.equal(0); + expect(await pool2Storage.totalOperatorsclaimedToken()).to.equal(0); + expect(await pool2Storage.totalVotersclaimedToken()).to.equal(0); + const signaturesData = await getKCSignaturesData( publishingNode, 1, receivingNodes, ); + + const miner = accounts[100]; const { collectionId } = await createKnowledgeCollection( - kcCreator, + miner, publishingNodeIdentityId, receivingNodesIdentityIds, signaturesData, { - KnowledgeCollection: KnowledgeCollection, - Token: Token, + KnowledgeCollection, + Token, }, ); - // 3. Submit knowledge collection to paranet - await Paranet.connect(kcCreator).submitKnowledgeCollection( + + await Paranet.connect(miner).submitKnowledgeCollection( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, @@ -1819,165 +1902,86 @@ describe('@unit Paranet', () => { collectionId, ); - // 4. Verify submission - // Check if KC is registered in paranet - const isRegistered = - await ParanetsRegistry.isKnowledgeCollectionRegistered( - paranetId, - ethers.keccak256( - ethers.solidityPacked( - ['address', 'uint256'], - [await KnowledgeCollectionStorage.getAddress(), collectionId], - ), - ), - ); - - expect(isRegistered).to.be.equal(true); - - // Check if KC is in miner's submitted collections - const submittedCollections = - await ParanetKnowledgeMinersRegistry.getSubmittedKnowledgeCollections( - kcCreator.address, - paranetId, - ); - expect(submittedCollections).to.include( - ethers.keccak256( - ethers.solidityPacked( - ['address', 'uint256'], - [await KnowledgeCollectionStorage.getAddress(), collectionId], - ), - ), + // 5. Claim rewards from first pool + const initialMinerBalance = await Token.balanceOf( + await miner.getAddress(), ); + const minerRewardEstimate1 = await pool1 + .connect(miner) + .getTotalKnowledgeMinerIncentiveEstimation(); + expect(minerRewardEstimate1).to.be.gt(0); - // Check miner's stats were updated - const minerMetadata = - await ParanetKnowledgeMinersRegistry.getKnowledgeMinerMetadata( - kcCreator.address, - ); - expect(minerMetadata.totalSubmittedKnowledgeCollectionsCount).to.equal(1); - - // Check if TRAC amounts were tracked correctly - const remainingTokenAmount = - await KnowledgeCollectionStorage.getTokenAmount(collectionId); - - // Check cumulative TRAC spent - const cumulativeTracSpent = - await ParanetKnowledgeMinersRegistry.getCumulativeTracSpent( - kcCreator.address, - paranetId, - ); - expect(cumulativeTracSpent).to.equal(remainingTokenAmount); + await pool1 + .connect(miner) + .claimKnowledgeMinerReward(minerRewardEstimate1); + // 6. Verify first pool is empty and second pool still has funds + expect(await Token.balanceOf(await miner.getAddress())).to.be.equal( + initialMinerBalance + minerRewardEstimate1, + ); + expect(await Token.balanceOf(event1?.args[3])).to.equal( + pool1Amount - minerRewardEstimate1, + ); + expect(await Token.balanceOf(event2?.args[3])).to.equal(pool2Amount); - // Check unrewarded TRAC spent - const unrewardedTracSpent = - await ParanetKnowledgeMinersRegistry.getUnrewardedTracSpent( - kcCreator.address, - paranetId, - ); - expect(unrewardedTracSpent).to.equal(remainingTokenAmount); + // 7. Claim rewards from second pool + const minerRewardEstimate0 = await pool2 + .connect(miner) + .getTotalKnowledgeMinerIncentiveEstimation(); + expect(minerRewardEstimate0).to.be.equal(0); - // Check total TRAC spent - const totalTracSpent = - await ParanetKnowledgeMinersRegistry.getTotalTracSpent( - kcCreator.address, - ); - expect(totalTracSpent).to.equal(remainingTokenAmount); + await expect( + pool2.connect(miner).claimKnowledgeMinerReward(minerRewardEstimate0), + ).to.be.revertedWithCustomError(pool2, 'NoRewardAvailable'); - // Check paranet's cumulative knowledge value - const paranetMetadata = - await ParanetsRegistry.getParanetMetadata(paranetId); - expect(paranetMetadata.cumulativeKnowledgeValue).to.equal( - remainingTokenAmount, + expect(await Token.balanceOf(await miner.getAddress())).to.equal( + initialMinerBalance + minerRewardEstimate1, ); + expect(await Token.balanceOf(pool2Storage)).to.equal(pool2Amount); - const signaturesData2 = await getKCSignaturesData( - publishingNode, - 1, - receivingNodes, - ); const { collectionId: collectionId2 } = await createKnowledgeCollection( - kcCreator, + miner, publishingNodeIdentityId, receivingNodesIdentityIds, - signaturesData2, + signaturesData, { - KnowledgeCollection: KnowledgeCollection, - Token: Token, + KnowledgeCollection, + Token, }, ); - // Verify event emission - await expect( - Paranet.connect(kcCreator).submitKnowledgeCollection( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - collectionId2, - ), - ) - .to.emit(Paranet, 'KnowledgeCollectionSubmittedToParanet') - .withArgs( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - collectionId2, - ); - }); - - it('Should revert when non-owner tries to submit knowledge collection', async () => { - // 1. Setup paranet - const kcCreator = getDefaultKCCreator(accounts); - const publishingNode = getDefaultPublishingNode(accounts); - const receivingNodes = getDefaultReceivingNodes(accounts); - const nonOwner = accounts[10]; - - const { + await Paranet.connect(miner).submitKnowledgeCollection( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, - publishingNodeIdentityId, - receivingNodesIdentityIds, - } = await setupParanet(kcCreator, publishingNode, receivingNodes, { - Paranet, - Profile, - Token, - KnowledgeCollection, - KnowledgeCollectionStorage, - }); - - // 2. Create a knowledge collection - const signaturesData = await getKCSignaturesData( - publishingNode, - 1, - receivingNodes, + await KnowledgeCollectionStorage.getAddress(), + collectionId2, ); - const { collectionId } = await createKnowledgeCollection( - kcCreator, - publishingNodeIdentityId, - receivingNodesIdentityIds, - signaturesData, - { - KnowledgeCollection: KnowledgeCollection, - Token: Token, - }, + const initialMinerBalance2 = await Token.balanceOf( + await miner.getAddress(), ); + const minerRewardEstimate2 = await pool1 + .connect(miner) + .getTotalKnowledgeMinerIncentiveEstimation(); + expect(minerRewardEstimate2).to.be.gt(0); - // 3. Try to submit KC with non-owner account - await expect( - Paranet.connect(nonOwner).submitKnowledgeCollection( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - collectionId, - ), - ).to.be.revertedWith("Caller isn't the owner of the KC"); + await pool2 + .connect(miner) + .claimKnowledgeMinerReward(minerRewardEstimate2); + + // 8. Verify balances is updated + expect(await Token.balanceOf(pool1Storage)).to.equal( + pool1Amount - minerRewardEstimate1, + ); + expect(await Token.balanceOf(pool2Storage)).to.equal( + pool2Amount - minerRewardEstimate2, + ); + expect(await Token.balanceOf(await miner.getAddress())).to.equal( + initialMinerBalance2 + minerRewardEstimate2, + ); }); - it('Should revert when registering the same knowledge collection twice', async () => { - // 1. Setup paranet + it('Should handle claiming rewards from multiple incentives pools with native token', async () => { + // 1. Setup paranet with initial configuration const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); const receivingNodes = getDefaultReceivingNodes(accounts); @@ -1986,6 +1990,7 @@ describe('@unit Paranet', () => { paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, + paranetOwner, publishingNodeIdentityId, receivingNodesIdentityIds, } = await setupParanet(kcCreator, publishingNode, receivingNodes, { @@ -1996,314 +2001,237 @@ describe('@unit Paranet', () => { KnowledgeCollectionStorage, }); - // 2. Create a knowledge collection - const signaturesData = await getKCSignaturesData( - publishingNode, - 1, - receivingNodes, - ); - const { collectionId } = await createKnowledgeCollection( - kcCreator, - publishingNodeIdentityId, - receivingNodesIdentityIds, - signaturesData, - { - KnowledgeCollection: KnowledgeCollection, - Token: Token, - }, - ); - - await Paranet.connect(kcCreator).submitKnowledgeCollection( + // 2. Deploy two incentive pools with different parameters using address(0) for native token + const tx1 = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployIncentivesPool( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - collectionId, + ethers.parseUnits('1', 12), // 1 ETH per 1 TRAC + 1000, // 10% operator + 2000, // 20% voters + 'Pool1', + ethers.ZeroAddress, // Use address(0) for native token ); + const receipt1 = await tx1.wait(); + const event1 = receipt1!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolDeployed', + ).topicHash, + ) as EventLog; - // 4. Try to submit the same knowledge collection again - await expect( - Paranet.connect(kcCreator).submitKnowledgeCollection( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - collectionId, - ), - ).to.be.revertedWithCustomError( - Paranet, - 'KnowledgeCollectionIsAPartOfOtherParanet', + const tx2 = await ParanetIncentivesPoolFactory.connect( + paranetOwner, + ).deployIncentivesPool( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + ethers.parseUnits('2', 12), // 2 ETH per 1 TRAC + 1500, // 15% operator + 2500, // 25% voters + 'Pool2', + ethers.ZeroAddress, // Use address(0) for native token ); - }); + const receipt2 = await tx2.wait(); + const event2 = receipt2!.logs.find( + (log) => + log.topics[0] === + ParanetIncentivesPoolFactory.interface.getEvent( + 'ParanetIncentivesPoolDeployed', + ).topicHash, + ) as EventLog; - it('Should not allow submitting KC to second paranet after first', async () => { - // 1. Setup first paranet - const kcCreator = getDefaultKCCreator(accounts); - const publishingNode = getDefaultPublishingNode(accounts); - const receivingNodes = getDefaultReceivingNodes(accounts); + // 3. Fund both pools with ETH + const pool1Amount = ethers.parseEther('100'); // 100 ETH + const pool2Amount = ethers.parseEther('200'); // 200 ETH - const firstParanet = await setupParanet( - kcCreator, - publishingNode, - receivingNodes, - { - Paranet, - Profile, - Token, - KnowledgeCollection, - KnowledgeCollectionStorage, - }, - 'First Paranet', - 'First Paranet Description', + const pool1Storage = await hre.ethers.getContractAt( + 'ParanetIncentivesPoolStorage', + event1?.args[3], + ); + const pool1 = await hre.ethers.getContractAt( + 'ParanetIncentivesPool', + event1?.args[4], ); - // 2. Setup second paranet - - const signaturesData2 = await getKCSignaturesData( - publishingNode, - 1, - receivingNodes, + const pool2Storage = await hre.ethers.getContractAt( + 'ParanetIncentivesPoolStorage', + event2?.args[3], + ); + const pool2 = await hre.ethers.getContractAt( + 'ParanetIncentivesPool', + event2?.args[4], ); - const { collectionId: secondParanetCollectionId } = - await createKnowledgeCollection( - kcCreator, - firstParanet.publishingNodeIdentityId, - firstParanet.receivingNodesIdentityIds, - signaturesData2, - { - KnowledgeCollection: KnowledgeCollection, - Token: Token, - }, - ); + // Send ETH to pools + await paranetOwner.sendTransaction({ + to: pool1Storage.target, + value: pool1Amount, + }); + await paranetOwner.sendTransaction({ + to: pool2Storage.target, + value: pool2Amount, + }); - await Paranet.connect(kcCreator).registerParanet( - await KnowledgeCollectionStorage.getAddress(), - secondParanetCollectionId, - 1, - 'Second Paranet', - 'Second Paranet Description', - 0, - 0, - 0, - ); + // Verify initial balances + expect( + await hre.ethers.provider.getBalance(pool1Storage.target), + ).to.equal(pool1Amount); + expect(await pool1Storage.totalMinersclaimedToken()).to.equal(0); + expect(await pool1Storage.totalOperatorsclaimedToken()).to.equal(0); + expect(await pool1Storage.totalVotersclaimedToken()).to.equal(0); - // 3. Create a knowledge collection + expect( + await hre.ethers.provider.getBalance(pool2Storage.target), + ).to.equal(pool2Amount); + expect(await pool2Storage.totalMinersclaimedToken()).to.equal(0); + expect(await pool2Storage.totalOperatorsclaimedToken()).to.equal(0); + expect(await pool2Storage.totalVotersclaimedToken()).to.equal(0); + + // 4. Create and submit knowledge collection const signaturesData = await getKCSignaturesData( publishingNode, 1, receivingNodes, ); + + const miner = accounts[100]; const { collectionId } = await createKnowledgeCollection( - kcCreator, - firstParanet.publishingNodeIdentityId, - firstParanet.receivingNodesIdentityIds, + miner, + publishingNodeIdentityId, + receivingNodesIdentityIds, signaturesData, { - KnowledgeCollection: KnowledgeCollection, - Token: Token, + KnowledgeCollection, + Token, }, ); - // 4. Submit KC to first paranet - await Paranet.connect(kcCreator).submitKnowledgeCollection( - firstParanet.paranetKCStorageContract, - firstParanet.paranetKCTokenId, - firstParanet.paranetKATokenId, + await Paranet.connect(miner).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, await KnowledgeCollectionStorage.getAddress(), collectionId, ); - // 5. Try to submit the same KC to second paranet - await expect( - Paranet.connect(kcCreator).submitKnowledgeCollection( - await KnowledgeCollectionStorage.getAddress(), - secondParanetCollectionId, - 1, - await KnowledgeCollectionStorage.getAddress(), - collectionId, - ), - ).to.be.revertedWithCustomError( - Paranet, - 'KnowledgeCollectionIsAPartOfOtherParanet', + // 5. Claim rewards from first pool + const initialMinerBalance = await hre.ethers.provider.getBalance( + miner.address, ); + const minerRewardEstimate1 = await pool1 + .connect(miner) + .getTotalKnowledgeMinerIncentiveEstimation(); + expect(minerRewardEstimate1).to.be.gt(0); - // 6. Verify KC is only registered in first paranet - const knowledgeCollectionId = ethers.keccak256( - ethers.solidityPacked( - ['address', 'uint256'], - [await KnowledgeCollectionStorage.getAddress(), collectionId], - ), - ); + const claimTx1 = await pool1 + .connect(miner) + .claimKnowledgeMinerReward(minerRewardEstimate1); + const receipt3 = await claimTx1.wait(); + const gasCost1 = receipt3!.gasUsed * receipt3!.gasPrice; - const isRegisteredInFirstParanet = - await ParanetsRegistry.isKnowledgeCollectionRegistered( - firstParanet.paranetId, - knowledgeCollectionId, - ); - expect(isRegisteredInFirstParanet).to.be.equal(true); - - const secondParanetId = ethers.keccak256( - ethers.solidityPacked( - ['address', 'uint256', 'uint256'], - [ - await KnowledgeCollectionStorage.getAddress(), - secondParanetCollectionId, - 1, - ], - ), + // 6. Verify first pool balance and miner received ETH + const newMinerBalance = await hre.ethers.provider.getBalance( + miner.address, ); - const isRegisteredInSecondParanet = - await ParanetsRegistry.isKnowledgeCollectionRegistered( - secondParanetId, - knowledgeCollectionId, - ); - expect(isRegisteredInSecondParanet).to.be.equal(false); - }); - }); + expect(newMinerBalance).to.be.equal( + initialMinerBalance + minerRewardEstimate1 - gasCost1, + ); + expect( + await hre.ethers.provider.getBalance(pool1Storage.target), + ).to.equal(pool1Amount - minerRewardEstimate1); + expect( + await hre.ethers.provider.getBalance(pool2Storage.target), + ).to.equal(pool2Amount); - describe('Paranet with Staged Knowledge Collections', () => { - const KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING = 1; + // 7. Try claiming from second pool (should fail as no rewards available yet) + const minerRewardEstimate0 = await pool2 + .connect(miner) + .getTotalKnowledgeMinerIncentiveEstimation(); + expect(minerRewardEstimate0).to.be.equal(0); - it('Should create paranet with staging policy and add curator successfully', async () => { - // 1. Setup initial accounts - const kcCreator = getDefaultKCCreator(accounts); - const publishingNode = getDefaultPublishingNode(accounts); - const receivingNodes = getDefaultReceivingNodes(accounts); + await expect( + pool2.connect(miner).claimKnowledgeMinerReward(minerRewardEstimate0), + ).to.be.revertedWithCustomError(pool2, 'NoRewardAvailable'); - // 2. Create paranet with staging policy - const { - paranetOwner, - paranetId, - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - } = await setupParanet( - kcCreator, - publishingNode, - receivingNodes, + await expect( + pool1.connect(miner).claimKnowledgeMinerReward(minerRewardEstimate0), + ).to.be.revertedWithCustomError(pool1, 'NoRewardAvailable'); + + // 8. Submit second knowledge collection + const { collectionId: collectionId2 } = await createKnowledgeCollection( + miner, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, { - Paranet, - Profile, - Token, KnowledgeCollection, - KnowledgeCollectionStorage, + Token, }, - 'Test Paranet', - 'Test Paranet Description', - 0, - 0, - KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, ); - // 3. Add paranet owner as curator - await Paranet.connect(paranetOwner).addCurator( + await Paranet.connect(miner).submitKnowledgeCollection( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, - paranetOwner.address, - ); - - // 4. Verify curator was added correctly - const isCurator = await ParanetStagingRegistry.isCurator( - paranetId, - paranetOwner.address, + await KnowledgeCollectionStorage.getAddress(), + collectionId2, ); - expect(isCurator).to.be.equal(true); - // 5. Verify paranet metadata - const paranetMetadata = - await ParanetsRegistry.getParanetMetadata(paranetId); - expect(paranetMetadata.knowledgeCollectionsSubmissionPolicy).to.equal( - KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, + // 9. Claim rewards from second pool + const initialMinerBalance2 = await hre.ethers.provider.getBalance( + miner.address, ); + const minerRewardEstimate2 = await pool2 + .connect(miner) + .getTotalKnowledgeMinerIncentiveEstimation(); + expect(minerRewardEstimate2).to.be.gt(0); - // 6. Get all curators and verify - const curators = - await ParanetStagingRegistry.getAllParanetCurators(paranetId); - expect(curators).to.have.lengthOf(1); - expect(curators[0]).to.equal(paranetOwner.address); - }); - - it('Should revert when non-owner tries to add curator', async () => { - // 1. Setup initial accounts - const kcCreator = getDefaultKCCreator(accounts); - const publishingNode = getDefaultPublishingNode(accounts); - const receivingNodes = getDefaultReceivingNodes(accounts); - const nonOwner = accounts[10]; - - // 2. Create paranet with staging policy - const { paranetKCStorageContract, paranetKCTokenId, paranetKATokenId } = - await setupParanet( - kcCreator, - publishingNode, - receivingNodes, - { - Paranet, - Profile, - Token, - KnowledgeCollection, - KnowledgeCollectionStorage, - }, - 'Test Paranet', - 'Test Paranet Description', - 0, - 0, - KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, - ); + const claimTx2 = await pool2 + .connect(miner) + .claimKnowledgeMinerReward(minerRewardEstimate2); + const receipt4 = await claimTx2.wait(); + const gasCost2 = receipt4!.gasUsed * receipt4!.gasPrice; - // 3. Try to add curator with non-owner account - await expect( - Paranet.connect(nonOwner).addCurator( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - nonOwner.address, - ), - ).to.be.revertedWith("Caller isn't the owner of the KA"); + // 10. Verify final balances + expect( + await hre.ethers.provider.getBalance(pool1Storage.target), + ).to.equal(pool1Amount - minerRewardEstimate1); + expect( + await hre.ethers.provider.getBalance(pool2Storage.target), + ).to.equal(pool2Amount - minerRewardEstimate2); + expect(await hre.ethers.provider.getBalance(miner.address)).to.equal( + initialMinerBalance2 + minerRewardEstimate2 - gasCost2, + ); }); + }); - it('Should submit KC to staging and have curator approve it', async () => { - // 1. Setup paranet with staging policy + describe('Submit Knowledge Collection to Paranet', () => { + it('Should submit knowledge collection to paranet successfully', async () => { + // 1. Setup paranet first const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); const receivingNodes = getDefaultReceivingNodes(accounts); const { - paranetOwner, + // paranetOwner, paranetId, paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, publishingNodeIdentityId, receivingNodesIdentityIds, - } = await setupParanet( - kcCreator, - publishingNode, - receivingNodes, - { - Paranet, - Profile, - Token, - KnowledgeCollection, - KnowledgeCollectionStorage, - }, - 'Test Paranet', - 'Test Paranet Description', - 0, - 0, - KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, - ); - - // 2. Add paranet owner as curator - await Paranet.connect(paranetOwner).addCurator( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - paranetOwner.address, - ); + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); - // 4. Submit KC to paranet (goes to staging) const signaturesData = await getKCSignaturesData( publishingNode, 1, @@ -2320,7 +2248,7 @@ describe('@unit Paranet', () => { }, ); // 3. Submit knowledge collection to paranet - await Paranet.connect(kcCreator).stageKnowledgeCollection( + await Paranet.connect(kcCreator).submitKnowledgeCollection( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, @@ -2328,99 +2256,184 @@ describe('@unit Paranet', () => { collectionId, ); - // 5. Verify KC is in staging - const knowledgeCollectionId = ethers.keccak256( - ethers.solidityPacked( - ['address', 'uint256'], - [await KnowledgeCollectionStorage.getAddress(), collectionId], - ), - ); - - const stagedStatus = - await ParanetStagingRegistry.getKnowledgeCollectionStatus( - paranetId, - knowledgeCollectionId, - ); - expect(stagedStatus).to.equal(1); // PENDING - - const isStaged = await ParanetStagingRegistry.isKnowledgeCollectionStaged( - paranetId, - knowledgeCollectionId, - ); - expect(isStaged).to.be.equal(true); - - // 6. Have curator approve the KC - await Paranet.connect(paranetOwner).reviewKnowledgeCollection( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - paranetKCStorageContract, - collectionId, - true, // approve - ); - - // 7. Verify KC is now registered in paranet + // 4. Verify submission + // Check if KC is registered in paranet const isRegistered = await ParanetsRegistry.isKnowledgeCollectionRegistered( paranetId, - knowledgeCollectionId, + ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256'], + [await KnowledgeCollectionStorage.getAddress(), collectionId], + ), + ), ); + expect(isRegistered).to.be.equal(true); - const stagedStatusAfterApproval = - await ParanetStagingRegistry.getKnowledgeCollectionStatus( + // Check if KC is in miner's submitted collections + const submittedCollections = + await ParanetKnowledgeMinersRegistry.getSubmittedKnowledgeCollections( + kcCreator.address, paranetId, - knowledgeCollectionId, ); - expect(stagedStatusAfterApproval).to.equal(2); // APPROVED - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const [pendingCollections, total] = - await ParanetStagingRegistry.getPendingCollections(paranetId, 0, 10); - expect(total).to.be.equal(0); + expect(submittedCollections).to.include( + ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256'], + [await KnowledgeCollectionStorage.getAddress(), collectionId], + ), + ), + ); + + // Check miner's stats were updated + const minerMetadata = + await ParanetKnowledgeMinersRegistry.getKnowledgeMinerMetadata( + kcCreator.address, + ); + expect(minerMetadata.totalSubmittedKnowledgeCollectionsCount).to.equal(1); + + // Check if TRAC amounts were tracked correctly + const remainingTokenAmount = + await KnowledgeCollectionStorage.getTokenAmount(collectionId); + + // Check cumulative TRAC spent + const cumulativeTracSpent = + await ParanetKnowledgeMinersRegistry.getCumulativeTracSpent( + kcCreator.address, + paranetId, + ); + expect(cumulativeTracSpent).to.equal(remainingTokenAmount); + + // Check unrewarded TRAC spent + const unrewardedTracSpent = + await ParanetKnowledgeMinersRegistry.getUnrewardedTracSpent( + kcCreator.address, + paranetId, + ); + expect(unrewardedTracSpent).to.equal(remainingTokenAmount); + + // Check total TRAC spent + const totalTracSpent = + await ParanetKnowledgeMinersRegistry.getTotalTracSpent( + kcCreator.address, + ); + expect(totalTracSpent).to.equal(remainingTokenAmount); + + // Check paranet's cumulative knowledge value + const paranetMetadata = + await ParanetsRegistry.getParanetMetadata(paranetId); + expect(paranetMetadata.cumulativeKnowledgeValue).to.equal( + remainingTokenAmount, + ); + + const signaturesData2 = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId: collectionId2 } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData2, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // Verify event emission + await expect( + Paranet.connect(kcCreator).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId2, + ), + ) + .to.emit(Paranet, 'KnowledgeCollectionSubmittedToParanet') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId2, + ); }); - it('Should submit KC to staging and have curator reject it', async () => { - // 1. Setup paranet with staging policy + it('Should revert when non-owner tries to submit knowledge collection', async () => { + // 1. Setup paranet const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); const receivingNodes = getDefaultReceivingNodes(accounts); + const nonOwner = accounts[10]; const { - paranetOwner, - paranetId, paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, publishingNodeIdentityId, receivingNodesIdentityIds, - } = await setupParanet( - kcCreator, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Create a knowledge collection + const signaturesData = await getKCSignaturesData( publishingNode, + 1, receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, { - Paranet, - Profile, - Token, - KnowledgeCollection, - KnowledgeCollectionStorage, + KnowledgeCollection: KnowledgeCollection, + Token: Token, }, - 'Test Paranet', - 'Test Paranet Description', - 0, - 0, - KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, ); - // 2. Add paranet owner as curator - await Paranet.connect(paranetOwner).addCurator( + // 3. Try to submit KC with non-owner account + await expect( + Paranet.connect(nonOwner).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ), + ).to.be.revertedWith("Caller isn't the owner of the KC"); + }); + + it('Should revert when registering the same knowledge collection twice', async () => { + // 1. Setup paranet + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, - paranetOwner.address, - ); + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); - // 3. Create and submit KC to paranet staging + // 2. Create a knowledge collection const signaturesData = await getKCSignaturesData( publishingNode, 1, @@ -2437,7 +2450,7 @@ describe('@unit Paranet', () => { }, ); - await Paranet.connect(kcCreator).stageKnowledgeCollection( + await Paranet.connect(kcCreator).submitKnowledgeCollection( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, @@ -2445,67 +2458,28 @@ describe('@unit Paranet', () => { collectionId, ); - // 4. Get knowledge collection ID - const knowledgeCollectionId = ethers.keccak256( - ethers.solidityPacked( - ['address', 'uint256'], - [await KnowledgeCollectionStorage.getAddress(), collectionId], + // 4. Try to submit the same knowledge collection again + await expect( + Paranet.connect(kcCreator).submitKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, ), + ).to.be.revertedWithCustomError( + Paranet, + 'KnowledgeCollectionIsAPartOfOtherParanet', ); - - // 5. Have curator reject the KC - await Paranet.connect(paranetOwner).reviewKnowledgeCollection( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - collectionId, - false, // reject - ); - - // 6. Verify KC was rejected and not registered in paranet - const isRegistered = - await ParanetsRegistry.isKnowledgeCollectionRegistered( - paranetId, - knowledgeCollectionId, - ); - expect(isRegistered).to.be.equal(false); - - const stagedStatusAfterRejection = - await ParanetStagingRegistry.getKnowledgeCollectionStatus( - paranetId, - knowledgeCollectionId, - ); - expect(stagedStatusAfterRejection).to.equal(3); // REJECTED - - // 7. Verify KC is still staged but marked as rejected - const isStaged = await ParanetStagingRegistry.isKnowledgeCollectionStaged( - paranetId, - knowledgeCollectionId, - ); - expect(isStaged).to.be.equal(false); - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const [pendingCollectionsAfterRejection, totalAfterRejection] = - await ParanetStagingRegistry.getPendingCollections(paranetId, 0, 10); - expect(totalAfterRejection).to.be.equal(0); }); - it('Should allow resubmission of previously rejected Knowledge Collection', async () => { - // 1. Setup paranet with staging policy + it('Should not allow submitting KC to second paranet after first', async () => { + // 1. Setup first paranet const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); const receivingNodes = getDefaultReceivingNodes(accounts); - const { - paranetOwner, - paranetId, - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - publishingNodeIdentityId, - receivingNodesIdentityIds, - } = await setupParanet( + const firstParanet = await setupParanet( kcCreator, publishingNode, receivingNodes, @@ -2516,47 +2490,82 @@ describe('@unit Paranet', () => { KnowledgeCollection, KnowledgeCollectionStorage, }, - 'Test Paranet', - 'Test Paranet Description', - 0, - 0, - KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, + 'First Paranet', + 'First Paranet Description', ); - // 2. Add paranet owner as curator - await Paranet.connect(paranetOwner).addCurator( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - paranetOwner.address, - ); + // 2. Setup second paranet - // 3. Create and submit KC to paranet staging - const signaturesData = await getKCSignaturesData( + const signaturesData2 = await getKCSignaturesData( publishingNode, 1, receivingNodes, ); - const { collectionId } = await createKnowledgeCollection( - kcCreator, - publishingNodeIdentityId, - receivingNodesIdentityIds, - signaturesData, - { - KnowledgeCollection: KnowledgeCollection, - Token: Token, - }, - ); - // 4. First submission - Stage the Knowledge Collection - await Paranet.connect(kcCreator).stageKnowledgeCollection( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, + const { collectionId: secondParanetCollectionId } = + await createKnowledgeCollection( + kcCreator, + firstParanet.publishingNodeIdentityId, + firstParanet.receivingNodesIdentityIds, + signaturesData2, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + await Paranet.connect(kcCreator).registerParanet( + await KnowledgeCollectionStorage.getAddress(), + secondParanetCollectionId, + 1, + 'Second Paranet', + 'Second Paranet Description', + 0, + 0, + 0, + ); + + // 3. Create a knowledge collection + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + firstParanet.publishingNodeIdentityId, + firstParanet.receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // 4. Submit KC to first paranet + await Paranet.connect(kcCreator).submitKnowledgeCollection( + firstParanet.paranetKCStorageContract, + firstParanet.paranetKCTokenId, + firstParanet.paranetKATokenId, await KnowledgeCollectionStorage.getAddress(), collectionId, ); + // 5. Try to submit the same KC to second paranet + await expect( + Paranet.connect(kcCreator).submitKnowledgeCollection( + await KnowledgeCollectionStorage.getAddress(), + secondParanetCollectionId, + 1, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ), + ).to.be.revertedWithCustomError( + Paranet, + 'KnowledgeCollectionIsAPartOfOtherParanet', + ); + + // 6. Verify KC is only registered in first paranet const knowledgeCollectionId = ethers.keccak256( ethers.solidityPacked( ['address', 'uint256'], @@ -2564,88 +2573,134 @@ describe('@unit Paranet', () => { ), ); - // 5. Verify it's in pending state - let [pendingCollections, total] = - await ParanetStagingRegistry.getPendingCollections(paranetId, 0, 10); - expect(total).to.equal(1); - expect(pendingCollections[0].knowledgeCollectionId).to.equal( - knowledgeCollectionId, - ); - expect(pendingCollections[0].status).to.equal(1); // PENDING + const isRegisteredInFirstParanet = + await ParanetsRegistry.isKnowledgeCollectionRegistered( + firstParanet.paranetId, + knowledgeCollectionId, + ); + expect(isRegisteredInFirstParanet).to.be.equal(true); - // 6. Have curator reject the KC - await Paranet.connect(paranetOwner).reviewKnowledgeCollection( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - collectionId, - false, // reject + const secondParanetId = ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256', 'uint256'], + [ + await KnowledgeCollectionStorage.getAddress(), + secondParanetCollectionId, + 1, + ], + ), ); + const isRegisteredInSecondParanet = + await ParanetsRegistry.isKnowledgeCollectionRegistered( + secondParanetId, + knowledgeCollectionId, + ); + expect(isRegisteredInSecondParanet).to.be.equal(false); + }); + }); - // 7. Verify rejection status (???) - let status = await ParanetStagingRegistry.getKnowledgeCollectionStatus( - paranetId, - knowledgeCollectionId, - ); - expect(status).to.equal(3); // REJECTED + describe('Paranet with Staged Knowledge Collections', () => { + const KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING = 1; - [pendingCollections, total] = - await ParanetStagingRegistry.getPendingCollections(paranetId, 0, 10); - expect(total).to.equal(0); - expect(pendingCollections).to.have.lengthOf(0); + it('Should create paranet with staging policy and add curator successfully', async () => { + // 1. Setup initial accounts + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); - // 8. Resubmit the Knowledge Collection - await Paranet.connect(kcCreator).stageKnowledgeCollection( + // 2. Create paranet with staging policy + const { + paranetOwner, + paranetId, paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - collectionId, - ); - - // 9. Verify it's back in pending state - [pendingCollections, total] = - await ParanetStagingRegistry.getPendingCollections(paranetId, 0, 10); - expect(total).to.equal(1); - expect(pendingCollections[0].knowledgeCollectionId).to.equal( - knowledgeCollectionId, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, + 0, + KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, ); - expect(pendingCollections[0].status).to.equal(1); // PENDING - // 10. Have curator approve the KC this time - await Paranet.connect(paranetOwner).reviewKnowledgeCollection( + // 3. Add paranet owner as curator + await Paranet.connect(paranetOwner).addCurator( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - collectionId, - true, // approve + paranetOwner.address, ); - // 11. Verify final approval status - status = await ParanetStagingRegistry.getKnowledgeCollectionStatus( + // 4. Verify curator was added correctly + const isCurator = await ParanetStagingRegistry.isCurator( paranetId, - knowledgeCollectionId, + paranetOwner.address, ); - expect(status).to.equal(2); // APPROVED + expect(isCurator).to.be.equal(true); - // 12. Verify KC is now registered in paranet - const isRegistered = - await ParanetsRegistry.isKnowledgeCollectionRegistered( - paranetId, - knowledgeCollectionId, + // 5. Verify paranet metadata + const paranetMetadata = + await ParanetsRegistry.getParanetMetadata(paranetId); + expect(paranetMetadata.knowledgeCollectionsSubmissionPolicy).to.equal( + KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, + ); + + // 6. Get all curators and verify + const curators = + await ParanetStagingRegistry.getAllParanetCurators(paranetId); + expect(curators).to.have.lengthOf(1); + expect(curators[0]).to.equal(paranetOwner.address); + }); + + it('Should revert when non-owner tries to add curator', async () => { + // 1. Setup initial accounts + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const nonOwner = accounts[10]; + + // 2. Create paranet with staging policy + const { paranetKCStorageContract, paranetKCTokenId, paranetKATokenId } = + await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, + 0, + KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, ); - expect(isRegistered).to.be.equal(true); - // 13. Verify no more pending collections - [pendingCollections, total] = - await ParanetStagingRegistry.getPendingCollections(paranetId, 0, 10); - expect(total).to.equal(0); - expect(pendingCollections).to.have.lengthOf(0); + // 3. Try to add curator with non-owner account + await expect( + Paranet.connect(nonOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + nonOwner.address, + ), + ).to.be.revertedWith("Caller isn't the owner of the KA"); }); - it('Should not allow approving a rejected knowledge collection', async () => { + it('Should submit KC to staging and have curator approve it', async () => { // 1. Setup paranet with staging policy const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); @@ -2674,7 +2729,7 @@ describe('@unit Paranet', () => { 'Test Paranet Description', 0, 0, - 1, // STAGING policy + KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, ); // 2. Add paranet owner as curator @@ -2685,7 +2740,7 @@ describe('@unit Paranet', () => { paranetOwner.address, ); - // 3. Create and submit KC to paranet staging + // 4. Submit KC to paranet (goes to staging) const signaturesData = await getKCSignaturesData( publishingNode, 1, @@ -2701,8 +2756,7 @@ describe('@unit Paranet', () => { Token: Token, }, ); - - // 4. Stage the Knowledge Collection + // 3. Submit knowledge collection to paranet await Paranet.connect(kcCreator).stageKnowledgeCollection( paranetKCStorageContract, paranetKCTokenId, @@ -2711,6 +2765,7 @@ describe('@unit Paranet', () => { collectionId, ); + // 5. Verify KC is in staging const knowledgeCollectionId = ethers.keccak256( ethers.solidityPacked( ['address', 'uint256'], @@ -2718,53 +2773,59 @@ describe('@unit Paranet', () => { ), ); - // 5. Reject the KC + const stagedStatus = + await ParanetStagingRegistry.getKnowledgeCollectionStatus( + paranetId, + knowledgeCollectionId, + ); + expect(stagedStatus).to.equal(1); // PENDING + + const isStaged = await ParanetStagingRegistry.isKnowledgeCollectionStaged( + paranetId, + knowledgeCollectionId, + ); + expect(isStaged).to.be.equal(true); + + // 6. Have curator approve the KC await Paranet.connect(paranetOwner).reviewKnowledgeCollection( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), + paranetKCStorageContract, collectionId, - false, // reject + true, // approve ); - // 6. Verify rejection status - let status = await ParanetStagingRegistry.getKnowledgeCollectionStatus( - paranetId, - knowledgeCollectionId, - ); - expect(status).to.equal(3); // Still REJECTED + // 7. Verify KC is now registered in paranet + const isRegistered = + await ParanetsRegistry.isKnowledgeCollectionRegistered( + paranetId, + knowledgeCollectionId, + ); + expect(isRegistered).to.be.equal(true); - // 7. Try to approve the rejected KC (should fail) - await expect( - Paranet.connect(paranetOwner).reviewKnowledgeCollection( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - collectionId, - true, // try to approve - ), - ).to.be.revertedWith('Knowledge collection is not staged'); + const stagedStatusAfterApproval = + await ParanetStagingRegistry.getKnowledgeCollectionStatus( + paranetId, + knowledgeCollectionId, + ); + expect(stagedStatusAfterApproval).to.equal(2); // APPROVED - // 8. Verify status remains rejected - status = await ParanetStagingRegistry.getKnowledgeCollectionStatus( - paranetId, - knowledgeCollectionId, - ); - expect(status).to.equal(3); // Still REJECTED + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [pendingCollections, total] = + await ParanetStagingRegistry.getPendingCollections(paranetId, 0, 10); + expect(total).to.be.equal(0); }); - it('Should revert when non-curator tries to review collection', async () => { + it('Should submit KC to staging and have curator reject it', async () => { // 1. Setup paranet with staging policy const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); const receivingNodes = getDefaultReceivingNodes(accounts); - const curator = accounts[10]; - const nonCurator = accounts[11]; const { paranetOwner, + paranetId, paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, @@ -2785,15 +2846,15 @@ describe('@unit Paranet', () => { 'Test Paranet Description', 0, 0, - 1, // STAGING policy + KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, ); - // 2. Add curator + // 2. Add paranet owner as curator await Paranet.connect(paranetOwner).addCurator( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, - curator.address, + paranetOwner.address, ); // 3. Create and submit KC to paranet staging @@ -2821,28 +2882,61 @@ describe('@unit Paranet', () => { collectionId, ); - // 4. Try to review with non-curator account - await expect( - Paranet.connect(nonCurator).reviewKnowledgeCollection( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - collectionId, - true, // approve + // 4. Get knowledge collection ID + const knowledgeCollectionId = ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256'], + [await KnowledgeCollectionStorage.getAddress(), collectionId], ), - ).to.be.revertedWith('Not authorized curator'); + ); + + // 5. Have curator reject the KC + await Paranet.connect(paranetOwner).reviewKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + false, // reject + ); + + // 6. Verify KC was rejected and not registered in paranet + const isRegistered = + await ParanetsRegistry.isKnowledgeCollectionRegistered( + paranetId, + knowledgeCollectionId, + ); + expect(isRegistered).to.be.equal(false); + + const stagedStatusAfterRejection = + await ParanetStagingRegistry.getKnowledgeCollectionStatus( + paranetId, + knowledgeCollectionId, + ); + expect(stagedStatusAfterRejection).to.equal(3); // REJECTED + + // 7. Verify KC is still staged but marked as rejected + const isStaged = await ParanetStagingRegistry.isKnowledgeCollectionStaged( + paranetId, + knowledgeCollectionId, + ); + expect(isStaged).to.be.equal(false); + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [pendingCollectionsAfterRejection, totalAfterRejection] = + await ParanetStagingRegistry.getPendingCollections(paranetId, 0, 10); + expect(totalAfterRejection).to.be.equal(0); }); - it('Should revert when reviewing already reviewed collection', async () => { + it('Should allow resubmission of previously rejected Knowledge Collection', async () => { // 1. Setup paranet with staging policy const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); const receivingNodes = getDefaultReceivingNodes(accounts); - const curator = accounts[10]; const { paranetOwner, + paranetId, paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, @@ -2863,15 +2957,15 @@ describe('@unit Paranet', () => { 'Test Paranet Description', 0, 0, - 1, // STAGING policy + KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING, ); - // 2. Add curator + // 2. Add paranet owner as curator await Paranet.connect(paranetOwner).addCurator( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, - curator.address, + paranetOwner.address, ); // 3. Create and submit KC to paranet staging @@ -2891,6 +2985,7 @@ describe('@unit Paranet', () => { }, ); + // 4. First submission - Stage the Knowledge Collection await Paranet.connect(kcCreator).stageKnowledgeCollection( paranetKCStorageContract, paranetKCTokenId, @@ -2899,103 +2994,99 @@ describe('@unit Paranet', () => { collectionId, ); - // 4. First review (approve) - await Paranet.connect(curator).reviewKnowledgeCollection( + const knowledgeCollectionId = ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256'], + [await KnowledgeCollectionStorage.getAddress(), collectionId], + ), + ); + + // 5. Verify it's in pending state + let [pendingCollections, total] = + await ParanetStagingRegistry.getPendingCollections(paranetId, 0, 10); + expect(total).to.equal(1); + expect(pendingCollections[0].knowledgeCollectionId).to.equal( + knowledgeCollectionId, + ); + expect(pendingCollections[0].status).to.equal(1); // PENDING + + // 6. Have curator reject the KC + await Paranet.connect(paranetOwner).reviewKnowledgeCollection( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, await KnowledgeCollectionStorage.getAddress(), collectionId, - false, // rejected + false, // reject ); - // 5. Try to review again - await expect( - Paranet.connect(curator).reviewKnowledgeCollection( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - collectionId, - true, // approve - ), - ).to.be.revertedWith('Knowledge collection is not staged'); - }); - }); - - describe('Paranet Curator Management', () => { - it('Should add and remove a single curator', async () => { - // Setup paranet - const kcCreator = getDefaultKCCreator(accounts); - const publishingNode = getDefaultPublishingNode(accounts); - const receivingNodes = getDefaultReceivingNodes(accounts); - const curator = accounts[10]; - - const { - paranetOwner, + // 7. Verify rejection status (???) + let status = await ParanetStagingRegistry.getKnowledgeCollectionStatus( paranetId, - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - } = await setupParanet( - kcCreator, - publishingNode, - receivingNodes, - { - Paranet, - Profile, - Token, - KnowledgeCollection, - KnowledgeCollectionStorage, - }, - 'Test Paranet', - 'Test Paranet Description', - 0, - 0, - 1, // STAGING policy + knowledgeCollectionId, ); + expect(status).to.equal(3); // REJECTED - // Add curator - await Paranet.connect(paranetOwner).addCurator( + [pendingCollections, total] = + await ParanetStagingRegistry.getPendingCollections(paranetId, 0, 10); + expect(total).to.equal(0); + expect(pendingCollections).to.have.lengthOf(0); + + // 8. Resubmit the Knowledge Collection + await Paranet.connect(kcCreator).stageKnowledgeCollection( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, - curator.address, + await KnowledgeCollectionStorage.getAddress(), + collectionId, ); - // Verify curator was added - expect( - await ParanetStagingRegistry.isCurator(paranetId, curator.address), - ).to.be.equal(true); - let curators = - await ParanetStagingRegistry.getAllParanetCurators(paranetId); - expect(curators).to.have.lengthOf(1); - expect(curators[0]).to.equal(curator.address); + // 9. Verify it's back in pending state + [pendingCollections, total] = + await ParanetStagingRegistry.getPendingCollections(paranetId, 0, 10); + expect(total).to.equal(1); + expect(pendingCollections[0].knowledgeCollectionId).to.equal( + knowledgeCollectionId, + ); + expect(pendingCollections[0].status).to.equal(1); // PENDING - // Remove curator - await Paranet.connect(paranetOwner).removeCurator( + // 10. Have curator approve the KC this time + await Paranet.connect(paranetOwner).reviewKnowledgeCollection( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, - curator.address, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + true, // approve ); - // Verify curator was removed - expect( - await ParanetStagingRegistry.isCurator(paranetId, curator.address), - ).to.be.equal(false); - curators = await ParanetStagingRegistry.getAllParanetCurators(paranetId); - expect(curators).to.have.lengthOf(0); + // 11. Verify final approval status + status = await ParanetStagingRegistry.getKnowledgeCollectionStatus( + paranetId, + knowledgeCollectionId, + ); + expect(status).to.equal(2); // APPROVED + + // 12. Verify KC is now registered in paranet + const isRegistered = + await ParanetsRegistry.isKnowledgeCollectionRegistered( + paranetId, + knowledgeCollectionId, + ); + expect(isRegistered).to.be.equal(true); + + // 13. Verify no more pending collections + [pendingCollections, total] = + await ParanetStagingRegistry.getPendingCollections(paranetId, 0, 10); + expect(total).to.equal(0); + expect(pendingCollections).to.have.lengthOf(0); }); - it('Should handle multiple curators and removal of middle curator', async () => { - // Setup paranet + it('Should not allow approving a rejected knowledge collection', async () => { + // 1. Setup paranet with staging policy const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); const receivingNodes = getDefaultReceivingNodes(accounts); - const curator1 = accounts[10]; - const curator2 = accounts[11]; - const curator3 = accounts[12]; const { paranetOwner, @@ -3003,6 +3094,8 @@ describe('@unit Paranet', () => { paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, + publishingNodeIdentityId, + receivingNodesIdentityIds, } = await setupParanet( kcCreator, publishingNode, @@ -3021,72 +3114,99 @@ describe('@unit Paranet', () => { 1, // STAGING policy ); - // Add three curators + // 2. Add paranet owner as curator await Paranet.connect(paranetOwner).addCurator( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, - curator1.address, + paranetOwner.address, ); - await Paranet.connect(paranetOwner).addCurator( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - curator2.address, + + // 3. Create and submit KC to paranet staging + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, ); - await Paranet.connect(paranetOwner).addCurator( + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // 4. Stage the Knowledge Collection + await Paranet.connect(kcCreator).stageKnowledgeCollection( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, - curator3.address, + await KnowledgeCollectionStorage.getAddress(), + collectionId, ); - // Verify all curators were added - let curators = - await ParanetStagingRegistry.getAllParanetCurators(paranetId); - expect(curators).to.have.lengthOf(3); - expect(curators).to.include(curator1.address); - expect(curators).to.include(curator2.address); - expect(curators).to.include(curator3.address); + const knowledgeCollectionId = ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256'], + [await KnowledgeCollectionStorage.getAddress(), collectionId], + ), + ); - // Remove middle curator - await Paranet.connect(paranetOwner).removeCurator( + // 5. Reject the KC + await Paranet.connect(paranetOwner).reviewKnowledgeCollection( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, - curator2.address, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + false, // reject ); - // Verify correct curator was removed and others remain - expect( - await ParanetStagingRegistry.isCurator(paranetId, curator1.address), - ).to.be.equal(true); - expect( - await ParanetStagingRegistry.isCurator(paranetId, curator2.address), - ).to.be.equal(false); - expect( - await ParanetStagingRegistry.isCurator(paranetId, curator3.address), - ).to.be.equal(true); + // 6. Verify rejection status + let status = await ParanetStagingRegistry.getKnowledgeCollectionStatus( + paranetId, + knowledgeCollectionId, + ); + expect(status).to.equal(3); // Still REJECTED - curators = await ParanetStagingRegistry.getAllParanetCurators(paranetId); - expect(curators).to.have.lengthOf(2); - expect(curators).to.include(curator1.address); - expect(curators).to.include(curator3.address); - expect(curators).to.not.include(curator2.address); + // 7. Try to approve the rejected KC (should fail) + await expect( + Paranet.connect(paranetOwner).reviewKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + true, // try to approve + ), + ).to.be.revertedWith('Knowledge collection is not staged'); + + // 8. Verify status remains rejected + status = await ParanetStagingRegistry.getKnowledgeCollectionStatus( + paranetId, + knowledgeCollectionId, + ); + expect(status).to.equal(3); // Still REJECTED }); - it('Should revert when adding curator to non-staging paranet', async () => { - // Setup paranet with OPEN submission policy (0) + it('Should revert when non-curator tries to review collection', async () => { + // 1. Setup paranet with staging policy const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); const receivingNodes = getDefaultReceivingNodes(accounts); const curator = accounts[10]; + const nonCurator = accounts[11]; const { paranetOwner, paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, + publishingNodeIdentityId, + receivingNodesIdentityIds, } = await setupParanet( kcCreator, publishingNode, @@ -3100,24 +3220,59 @@ describe('@unit Paranet', () => { }, 'Test Paranet', 'Test Paranet Description', - 0, // nodesAccessPolicy - 0, // minersAccessPolicy - 0, // OPEN submission policy + 0, + 0, + 1, // STAGING policy ); - // Attempt to add curator - should fail + // 2. Add curator + await Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator.address, + ); + + // 3. Create and submit KC to paranet staging + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + await Paranet.connect(kcCreator).stageKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ); + + // 4. Try to review with non-curator account await expect( - Paranet.connect(paranetOwner).addCurator( + Paranet.connect(nonCurator).reviewKnowledgeCollection( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, - curator.address, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + true, // approve ), - ).to.be.revertedWith('Paranet does not allow adding curators'); + ).to.be.revertedWith('Not authorized curator'); }); - it('Should revert when adding same curator twice', async () => { - // Setup paranet with staging policy + it('Should revert when reviewing already reviewed collection', async () => { + // 1. Setup paranet with staging policy const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); const receivingNodes = getDefaultReceivingNodes(accounts); @@ -3128,6 +3283,8 @@ describe('@unit Paranet', () => { paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, + publishingNodeIdentityId, + receivingNodesIdentityIds, } = await setupParanet( kcCreator, publishingNode, @@ -3141,12 +3298,12 @@ describe('@unit Paranet', () => { }, 'Test Paranet', 'Test Paranet Description', - 0, // nodesAccessPolicy - 0, // minersAccessPolicy + 0, + 0, 1, // STAGING policy ); - // Add curator first time + // 2. Add curator await Paranet.connect(paranetOwner).addCurator( paranetKCStorageContract, paranetKCTokenId, @@ -3154,26 +3311,66 @@ describe('@unit Paranet', () => { curator.address, ); - // Try to add same curator again - should fail + // 3. Create and submit KC to paranet staging + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + await Paranet.connect(kcCreator).stageKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + ); + + // 4. First review (approve) + await Paranet.connect(curator).reviewKnowledgeCollection( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + false, // rejected + ); + + // 5. Try to review again await expect( - Paranet.connect(paranetOwner).addCurator( + Paranet.connect(curator).reviewKnowledgeCollection( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, - curator.address, + await KnowledgeCollectionStorage.getAddress(), + collectionId, + true, // approve ), - ).to.be.revertedWith('Existing curator'); + ).to.be.revertedWith('Knowledge collection is not staged'); }); + }); - it('Should revert when removing non-existent curator', async () => { - // Setup paranet with staging policy + describe('Paranet Curator Management', () => { + it('Should add and remove a single curator', async () => { + // Setup paranet const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); const receivingNodes = getDefaultReceivingNodes(accounts); - const nonExistentCurator = accounts[10]; + const curator = accounts[10]; const { paranetOwner, + paranetId, paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, @@ -3190,37 +3387,277 @@ describe('@unit Paranet', () => { }, 'Test Paranet', 'Test Paranet Description', - 0, // nodesAccessPolicy - 0, // minersAccessPolicy + 0, + 0, 1, // STAGING policy ); - // Try to remove curator that was never added - should fail - await expect( - Paranet.connect(paranetOwner).removeCurator( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - nonExistentCurator.address, - ), - ).to.be.revertedWith('Address is not a curator'); - }); - }); + // Add curator + await Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator.address, + ); - describe('Paranet Service Registration', () => { - it('Should register a paranet service successfully', async () => { - // 1. Setup initial paranet - const kcCreator = getDefaultKCCreator(accounts); - const publishingNode = getDefaultPublishingNode(accounts); - const receivingNodes = getDefaultReceivingNodes(accounts); + // Verify curator was added + expect( + await ParanetStagingRegistry.isCurator(paranetId, curator.address), + ).to.be.equal(true); + let curators = + await ParanetStagingRegistry.getAllParanetCurators(paranetId); + expect(curators).to.have.lengthOf(1); + expect(curators[0]).to.equal(curator.address); - const { - paranetOwner, + // Remove curator + await Paranet.connect(paranetOwner).removeCurator( paranetKCStorageContract, paranetKCTokenId, paranetKATokenId, - paranetId, - publishingNodeIdentityId, + curator.address, + ); + + // Verify curator was removed + expect( + await ParanetStagingRegistry.isCurator(paranetId, curator.address), + ).to.be.equal(false); + curators = await ParanetStagingRegistry.getAllParanetCurators(paranetId); + expect(curators).to.have.lengthOf(0); + }); + + it('Should handle multiple curators and removal of middle curator', async () => { + // Setup paranet + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const curator1 = accounts[10]; + const curator2 = accounts[11]; + const curator3 = accounts[12]; + + const { + paranetOwner, + paranetId, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, + 0, + 1, // STAGING policy + ); + + // Add three curators + await Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator1.address, + ); + await Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator2.address, + ); + await Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator3.address, + ); + + // Verify all curators were added + let curators = + await ParanetStagingRegistry.getAllParanetCurators(paranetId); + expect(curators).to.have.lengthOf(3); + expect(curators).to.include(curator1.address); + expect(curators).to.include(curator2.address); + expect(curators).to.include(curator3.address); + + // Remove middle curator + await Paranet.connect(paranetOwner).removeCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator2.address, + ); + + // Verify correct curator was removed and others remain + expect( + await ParanetStagingRegistry.isCurator(paranetId, curator1.address), + ).to.be.equal(true); + expect( + await ParanetStagingRegistry.isCurator(paranetId, curator2.address), + ).to.be.equal(false); + expect( + await ParanetStagingRegistry.isCurator(paranetId, curator3.address), + ).to.be.equal(true); + + curators = await ParanetStagingRegistry.getAllParanetCurators(paranetId); + expect(curators).to.have.lengthOf(2); + expect(curators).to.include(curator1.address); + expect(curators).to.include(curator3.address); + expect(curators).to.not.include(curator2.address); + }); + + it('Should revert when adding curator to non-staging paranet', async () => { + // Setup paranet with OPEN submission policy (0) + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const curator = accounts[10]; + + const { + paranetOwner, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, // nodesAccessPolicy + 0, // minersAccessPolicy + 0, // OPEN submission policy + ); + + // Attempt to add curator - should fail + await expect( + Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator.address, + ), + ).to.be.revertedWith('Paranet does not allow adding curators'); + }); + + it('Should revert when adding same curator twice', async () => { + // Setup paranet with staging policy + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const curator = accounts[10]; + + const { + paranetOwner, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, // nodesAccessPolicy + 0, // minersAccessPolicy + 1, // STAGING policy + ); + + // Add curator first time + await Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator.address, + ); + + // Try to add same curator again - should fail + await expect( + Paranet.connect(paranetOwner).addCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + curator.address, + ), + ).to.be.revertedWith('Existing curator'); + }); + + it('Should revert when removing non-existent curator', async () => { + // Setup paranet with staging policy + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const nonExistentCurator = accounts[10]; + + const { + paranetOwner, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + 'Test Paranet', + 'Test Paranet Description', + 0, // nodesAccessPolicy + 0, // minersAccessPolicy + 1, // STAGING policy + ); + + // Try to remove curator that was never added - should fail + await expect( + Paranet.connect(paranetOwner).removeCurator( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + nonExistentCurator.address, + ), + ).to.be.revertedWith('Address is not a curator'); + }); + }); + + describe('Paranet Service Registration', () => { + it('Should register a paranet service successfully', async () => { + // 1. Setup initial paranet + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetOwner, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetId, + publishingNodeIdentityId, receivingNodesIdentityIds, } = await setupParanet(kcCreator, publishingNode, receivingNodes, { Paranet, @@ -4484,440 +4921,4 @@ describe('@unit Paranet', () => { // expect(finalNodes[0].identityId).to.equal(node2IdentityId); // }); // }); - - describe('Paranet Incentives Pool Rewards', () => { - it('Should handle claiming rewards from multiple incentives pools', async () => { - // 1. Setup paranet with initial configuration - const kcCreator = getDefaultKCCreator(accounts); - const publishingNode = getDefaultPublishingNode(accounts); - const receivingNodes = getDefaultReceivingNodes(accounts); - - const { - // paranetId, - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - paranetOwner, - publishingNodeIdentityId, - receivingNodesIdentityIds, - } = await setupParanet(kcCreator, publishingNode, receivingNodes, { - Paranet, - Profile, - Token, - KnowledgeCollection, - KnowledgeCollectionStorage, - }); - - // 2. Deploy two incentive pools with different parameters - const tx1 = await ParanetIncentivesPoolFactory.connect( - paranetOwner, - ).deployIncentivesPool( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - ethers.parseUnits('1', 12), // 1 NEURO per 1 TRAC - 1000, // 10% operator - 2000, // 20% voters - 'Pool1', - await Token.getAddress(), - ); - const receipt1 = await tx1.wait(); - const event1 = receipt1!.logs.find( - (log) => - log.topics[0] === - ParanetIncentivesPoolFactory.interface.getEvent( - 'ParanetIncentivesPoolDeployed', - ).topicHash, - ) as EventLog; - - const tx2 = await ParanetIncentivesPoolFactory.connect( - paranetOwner, - ).deployIncentivesPool( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - ethers.parseUnits('2', 12), // 2 NEURO per 1 TRAC - 1500, // 15% operator - 2500, // 25% voters - 'Pool2', - await Token.getAddress(), - ); - const receipt2 = await tx2.wait(); - const event2 = receipt2!.logs.find( - (log) => - log.topics[0] === - ParanetIncentivesPoolFactory.interface.getEvent( - 'ParanetIncentivesPoolDeployed', - ).topicHash, - ) as EventLog; - - // 3. Fund both pools - const pool1Amount = ethers.parseUnits('100', 18); // 100 NEURO - const pool2Amount = ethers.parseUnits('200', 18); // 200 NEURO - await Token.connect(paranetOwner).approve(event1?.args[3], pool1Amount); - await Token.connect(paranetOwner).approve(event2?.args[3], pool2Amount); - - const pool1Storage = await hre.ethers.getContractAt( - 'ParanetIncentivesPoolStorage', - event1?.args[3], - ); - const pool1 = await hre.ethers.getContractAt( - 'ParanetIncentivesPool', - event1?.args[4], - ); - - const pool2Storage = await hre.ethers.getContractAt( - 'ParanetIncentivesPoolStorage', - event2?.args[3], - ); - const pool2 = await hre.ethers.getContractAt( - 'ParanetIncentivesPool', - event2?.args[4], - ); - - await Token.connect(accounts[0]).mint(pool1Storage, pool1Amount); - await Token.connect(accounts[0]).mint(pool2Storage, pool2Amount); - - expect(await pool1Storage.getBalance()).to.equal(pool1Amount); - expect(await pool1Storage.totalMinersclaimedToken()).to.equal(0); - expect(await pool1Storage.totalOperatorsclaimedToken()).to.equal(0); - expect(await pool1Storage.totalVotersclaimedToken()).to.equal(0); - - expect(await pool2Storage.getBalance()).to.equal(pool2Amount); - expect(await pool2Storage.totalMinersclaimedToken()).to.equal(0); - expect(await pool2Storage.totalOperatorsclaimedToken()).to.equal(0); - expect(await pool2Storage.totalVotersclaimedToken()).to.equal(0); - - const signaturesData = await getKCSignaturesData( - publishingNode, - 1, - receivingNodes, - ); - - const miner = accounts[100]; - const { collectionId } = await createKnowledgeCollection( - miner, - publishingNodeIdentityId, - receivingNodesIdentityIds, - signaturesData, - { - KnowledgeCollection, - Token, - }, - ); - - await Paranet.connect(miner).submitKnowledgeCollection( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - collectionId, - ); - - // 5. Claim rewards from first pool - const initialMinerBalance = await Token.balanceOf( - await miner.getAddress(), - ); - const minerRewardEstimate1 = await pool1 - .connect(miner) - .getTotalKnowledgeMinerIncentiveEstimation(); - expect(minerRewardEstimate1).to.be.gt(0); - - await pool1 - .connect(miner) - .claimKnowledgeMinerReward(minerRewardEstimate1); - // 6. Verify first pool is empty and second pool still has funds - expect(await Token.balanceOf(await miner.getAddress())).to.be.equal( - initialMinerBalance + minerRewardEstimate1, - ); - expect(await Token.balanceOf(event1?.args[3])).to.equal( - pool1Amount - minerRewardEstimate1, - ); - expect(await Token.balanceOf(event2?.args[3])).to.equal(pool2Amount); - - // 7. Claim rewards from second pool - const minerRewardEstimate0 = await pool2 - .connect(miner) - .getTotalKnowledgeMinerIncentiveEstimation(); - expect(minerRewardEstimate0).to.be.equal(0); - - await expect( - pool2.connect(miner).claimKnowledgeMinerReward(minerRewardEstimate0), - ).to.be.revertedWithCustomError(pool2, 'NoRewardAvailable'); - - expect(await Token.balanceOf(await miner.getAddress())).to.equal( - initialMinerBalance + minerRewardEstimate1, - ); - expect(await Token.balanceOf(pool2Storage)).to.equal(pool2Amount); - - const { collectionId: collectionId2 } = await createKnowledgeCollection( - miner, - publishingNodeIdentityId, - receivingNodesIdentityIds, - signaturesData, - { - KnowledgeCollection, - Token, - }, - ); - - await Paranet.connect(miner).submitKnowledgeCollection( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - collectionId2, - ); - const initialMinerBalance2 = await Token.balanceOf( - await miner.getAddress(), - ); - const minerRewardEstimate2 = await pool1 - .connect(miner) - .getTotalKnowledgeMinerIncentiveEstimation(); - expect(minerRewardEstimate2).to.be.gt(0); - - await pool2 - .connect(miner) - .claimKnowledgeMinerReward(minerRewardEstimate2); - - // 8. Verify balances is updated - expect(await Token.balanceOf(pool1Storage)).to.equal( - pool1Amount - minerRewardEstimate1, - ); - expect(await Token.balanceOf(pool2Storage)).to.equal( - pool2Amount - minerRewardEstimate2, - ); - expect(await Token.balanceOf(await miner.getAddress())).to.equal( - initialMinerBalance2 + minerRewardEstimate2, - ); - }); - - it('Should handle claiming rewards from multiple incentives pools with native token', async () => { - // 1. Setup paranet with initial configuration - const kcCreator = getDefaultKCCreator(accounts); - const publishingNode = getDefaultPublishingNode(accounts); - const receivingNodes = getDefaultReceivingNodes(accounts); - - const { - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - paranetOwner, - publishingNodeIdentityId, - receivingNodesIdentityIds, - } = await setupParanet(kcCreator, publishingNode, receivingNodes, { - Paranet, - Profile, - Token, - KnowledgeCollection, - KnowledgeCollectionStorage, - }); - - // 2. Deploy two incentive pools with different parameters using address(0) for native token - const tx1 = await ParanetIncentivesPoolFactory.connect( - paranetOwner, - ).deployIncentivesPool( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - ethers.parseUnits('1', 12), // 1 ETH per 1 TRAC - 1000, // 10% operator - 2000, // 20% voters - 'Pool1', - ethers.ZeroAddress, // Use address(0) for native token - ); - const receipt1 = await tx1.wait(); - const event1 = receipt1!.logs.find( - (log) => - log.topics[0] === - ParanetIncentivesPoolFactory.interface.getEvent( - 'ParanetIncentivesPoolDeployed', - ).topicHash, - ) as EventLog; - - const tx2 = await ParanetIncentivesPoolFactory.connect( - paranetOwner, - ).deployIncentivesPool( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - ethers.parseUnits('2', 12), // 2 ETH per 1 TRAC - 1500, // 15% operator - 2500, // 25% voters - 'Pool2', - ethers.ZeroAddress, // Use address(0) for native token - ); - const receipt2 = await tx2.wait(); - const event2 = receipt2!.logs.find( - (log) => - log.topics[0] === - ParanetIncentivesPoolFactory.interface.getEvent( - 'ParanetIncentivesPoolDeployed', - ).topicHash, - ) as EventLog; - - // 3. Fund both pools with ETH - const pool1Amount = ethers.parseEther('100'); // 100 ETH - const pool2Amount = ethers.parseEther('200'); // 200 ETH - - const pool1Storage = await hre.ethers.getContractAt( - 'ParanetIncentivesPoolStorage', - event1?.args[3], - ); - const pool1 = await hre.ethers.getContractAt( - 'ParanetIncentivesPool', - event1?.args[4], - ); - - const pool2Storage = await hre.ethers.getContractAt( - 'ParanetIncentivesPoolStorage', - event2?.args[3], - ); - const pool2 = await hre.ethers.getContractAt( - 'ParanetIncentivesPool', - event2?.args[4], - ); - - // Send ETH to pools - await paranetOwner.sendTransaction({ - to: pool1Storage.target, - value: pool1Amount, - }); - await paranetOwner.sendTransaction({ - to: pool2Storage.target, - value: pool2Amount, - }); - - // Verify initial balances - expect( - await hre.ethers.provider.getBalance(pool1Storage.target), - ).to.equal(pool1Amount); - expect(await pool1Storage.totalMinersclaimedToken()).to.equal(0); - expect(await pool1Storage.totalOperatorsclaimedToken()).to.equal(0); - expect(await pool1Storage.totalVotersclaimedToken()).to.equal(0); - - expect( - await hre.ethers.provider.getBalance(pool2Storage.target), - ).to.equal(pool2Amount); - expect(await pool2Storage.totalMinersclaimedToken()).to.equal(0); - expect(await pool2Storage.totalOperatorsclaimedToken()).to.equal(0); - expect(await pool2Storage.totalVotersclaimedToken()).to.equal(0); - - // 4. Create and submit knowledge collection - const signaturesData = await getKCSignaturesData( - publishingNode, - 1, - receivingNodes, - ); - - const miner = accounts[100]; - const { collectionId } = await createKnowledgeCollection( - miner, - publishingNodeIdentityId, - receivingNodesIdentityIds, - signaturesData, - { - KnowledgeCollection, - Token, - }, - ); - - await Paranet.connect(miner).submitKnowledgeCollection( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - collectionId, - ); - - // 5. Claim rewards from first pool - const initialMinerBalance = await hre.ethers.provider.getBalance( - miner.address, - ); - const minerRewardEstimate1 = await pool1 - .connect(miner) - .getTotalKnowledgeMinerIncentiveEstimation(); - expect(minerRewardEstimate1).to.be.gt(0); - - const claimTx1 = await pool1 - .connect(miner) - .claimKnowledgeMinerReward(minerRewardEstimate1); - const receipt3 = await claimTx1.wait(); - const gasCost1 = receipt3!.gasUsed * receipt3!.gasPrice; - - // 6. Verify first pool balance and miner received ETH - const newMinerBalance = await hre.ethers.provider.getBalance( - miner.address, - ); - expect(newMinerBalance).to.be.equal( - initialMinerBalance + minerRewardEstimate1 - gasCost1, - ); - expect( - await hre.ethers.provider.getBalance(pool1Storage.target), - ).to.equal(pool1Amount - minerRewardEstimate1); - expect( - await hre.ethers.provider.getBalance(pool2Storage.target), - ).to.equal(pool2Amount); - - // 7. Try claiming from second pool (should fail as no rewards available yet) - const minerRewardEstimate0 = await pool2 - .connect(miner) - .getTotalKnowledgeMinerIncentiveEstimation(); - expect(minerRewardEstimate0).to.be.equal(0); - - await expect( - pool2.connect(miner).claimKnowledgeMinerReward(minerRewardEstimate0), - ).to.be.revertedWithCustomError(pool2, 'NoRewardAvailable'); - - await expect( - pool1.connect(miner).claimKnowledgeMinerReward(minerRewardEstimate0), - ).to.be.revertedWithCustomError(pool1, 'NoRewardAvailable'); - - // 8. Submit second knowledge collection - const { collectionId: collectionId2 } = await createKnowledgeCollection( - miner, - publishingNodeIdentityId, - receivingNodesIdentityIds, - signaturesData, - { - KnowledgeCollection, - Token, - }, - ); - - await Paranet.connect(miner).submitKnowledgeCollection( - paranetKCStorageContract, - paranetKCTokenId, - paranetKATokenId, - await KnowledgeCollectionStorage.getAddress(), - collectionId2, - ); - - // 9. Claim rewards from second pool - const initialMinerBalance2 = await hre.ethers.provider.getBalance( - miner.address, - ); - const minerRewardEstimate2 = await pool2 - .connect(miner) - .getTotalKnowledgeMinerIncentiveEstimation(); - expect(minerRewardEstimate2).to.be.gt(0); - - const claimTx2 = await pool2 - .connect(miner) - .claimKnowledgeMinerReward(minerRewardEstimate2); - const receipt4 = await claimTx2.wait(); - const gasCost2 = receipt4!.gasUsed * receipt4!.gasPrice; - - // 10. Verify final balances - expect( - await hre.ethers.provider.getBalance(pool1Storage.target), - ).to.equal(pool1Amount - minerRewardEstimate1); - expect( - await hre.ethers.provider.getBalance(pool2Storage.target), - ).to.equal(pool2Amount - minerRewardEstimate2); - expect(await hre.ethers.provider.getBalance(miner.address)).to.equal( - initialMinerBalance2 + minerRewardEstimate2 - gasCost2, - ); - }); - }); }); From 08b0282b99cdbd39af7dc3e63ce49821902efb11 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Mon, 24 Feb 2025 13:17:11 +0100 Subject: [PATCH 146/153] Update paranet metadata tests --- test/integration/Paranet.test.ts | 329 +++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index 26c0506f..6a8022a7 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -24,6 +24,7 @@ import { ParanetStagingRegistry, IdentityStorage, HubLib, + ParanetLib, } from '../../typechain'; import { ACCESS_POLICIES } from '../helpers/constants'; import { @@ -56,6 +57,7 @@ type ParanetFixture = { ParanetStagingRegistry: ParanetStagingRegistry; IdentityStorage: IdentityStorage; HubLib: HubLib; + ParanetLib: ParanetLib; }; describe('@unit Paranet', () => { @@ -75,6 +77,7 @@ describe('@unit Paranet', () => { let ParanetStagingRegistry: ParanetStagingRegistry; let IdentityStorage: IdentityStorage; let HubLib: HubLib; + let ParanetLib: ParanetLib; // Deploy all contracts, set the HubOwner and necessary accounts. Returns the ParanetFixture async function deployParanetFixture(): Promise { @@ -152,6 +155,15 @@ describe('@unit Paranet', () => { hubLibDeployment.address, ); + const paranetLibDeployment = await hre.deployments.deploy('ParanetLib', { + from: accounts[0].address, + log: true, + }); + ParanetLib = await hre.ethers.getContract( + 'ParanetLib', + paranetLibDeployment.address, + ); + return { accounts, Paranet, @@ -169,6 +181,7 @@ describe('@unit Paranet', () => { ParanetStagingRegistry, IdentityStorage, HubLib, + ParanetLib, }; } @@ -189,6 +202,7 @@ describe('@unit Paranet', () => { Token, ParanetStagingRegistry, HubLib, + ParanetLib, } = await loadFixture(deployParanetFixture)); }); @@ -409,6 +423,321 @@ describe('@unit Paranet', () => { }); }); + describe.only('Paranet Metadata', () => { + it('Should update paranet metadata successfully', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetId, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + const newName = 'New Name'; + const newDescription = 'New Description'; + + await Paranet.connect(paranetOwner).updateParanetMetadata( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + newName, + newDescription, + ); + + const updatedName = await ParanetsRegistry.getName(paranetId); + const updatedDescription = + await ParanetsRegistry.getDescription(paranetId); + expect(updatedName).to.equal(newName); + expect(updatedDescription).to.equal(newDescription); + }); + + it('Should emit ParanetMetadataUpdated event with correct parameters', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + const newName = 'New Name'; + const newDescription = 'New Description'; + + await expect( + Paranet.connect(paranetOwner).updateParanetMetadata( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + newName, + newDescription, + ), + ) + .to.emit(Paranet, 'ParanetMetadataUpdated') + .withArgs( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + newName, + newDescription, + ); + }); + + it('Should handle empty strings for name and description', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetId, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + await Paranet.connect(paranetOwner).updateParanetMetadata( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + '', + '', + ); + + expect(await ParanetsRegistry.getName(paranetId)).to.equal(''); + expect(await ParanetsRegistry.getDescription(paranetId)).to.equal(''); + }); + + it('Should handle very long name and description', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetId, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + const longName = 'a'.repeat(100); + const longDescription = 'b'.repeat(1000); + + await Paranet.connect(paranetOwner).updateParanetMetadata( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + longName, + longDescription, + ); + + expect(await ParanetsRegistry.getName(paranetId)).to.equal(longName); + expect(await ParanetsRegistry.getDescription(paranetId)).to.equal( + longDescription, + ); + }); + + it('Should allow multiple updates to the same paranet', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetId, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // First update + await Paranet.connect(paranetOwner).updateParanetMetadata( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + 'First Name', + 'First Description', + ); + + expect(await ParanetsRegistry.getName(paranetId)).to.equal('First Name'); + expect(await ParanetsRegistry.getDescription(paranetId)).to.equal( + 'First Description', + ); + + // Second update + await Paranet.connect(paranetOwner).updateParanetMetadata( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + 'Second Name', + 'Second Description', + ); + + expect(await ParanetsRegistry.getName(paranetId)).to.equal('Second Name'); + expect(await ParanetsRegistry.getDescription(paranetId)).to.equal( + 'Second Description', + ); + }); + + it('Should handle special characters in name and description', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetId, + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + paranetOwner, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + const specialName = '!@#$%^&*()_+-=[]{}|;:,.<>?`~'; + const specialDescription = '¡™£¢∞§¶•ªº–≠œ∑´®†¥¨ˆøπ"åß∂ƒ©˙∆˚¬…æ'; + + await Paranet.connect(paranetOwner).updateParanetMetadata( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + specialName, + specialDescription, + ); + + expect(await ParanetsRegistry.getName(paranetId)).to.equal(specialName); + expect(await ParanetsRegistry.getDescription(paranetId)).to.equal( + specialDescription, + ); + }); + + it('Should revert when non-owner tries to update paranet metadata', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const nonOwner = accounts[10]; + + const { paranetKCStorageContract, paranetKCTokenId, paranetKATokenId } = + await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + const newName = 'New Name'; + const newDescription = 'New Description'; + + await expect( + Paranet.connect(nonOwner).updateParanetMetadata( + paranetKCStorageContract, + paranetKCTokenId, + paranetKATokenId, + newName, + newDescription, + ), + ).to.be.revertedWith("Caller isn't the owner of the KA"); + }); + + it('updateParanetMetadata should revert when paranet does not exist', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + // Create a KC first + const { collectionId } = await createProfilesAndKC( + kcCreator, + publishingNode, + receivingNodes, + { Profile, KnowledgeCollection, Token }, + ); + + // Try to update metadata for non-existent paranet + await expect( + Paranet.connect(kcCreator).updateParanetMetadata( + await KnowledgeCollectionStorage.getAddress(), + collectionId, + 1, + 'New Name', + 'New Description', + ), + ).to.be.revertedWithCustomError(ParanetLib, 'ParanetDoesntExist'); + }); + + it('Should revert when trying to update with extremely large token IDs', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { paranetKCStorageContract, paranetOwner } = await setupParanet( + kcCreator, + publishingNode, + receivingNodes, + { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }, + ); + + const maxUint256 = ethers.MaxUint256; + + await expect( + Paranet.connect(paranetOwner).updateParanetMetadata( + paranetKCStorageContract, + maxUint256, + maxUint256, + 'New Name', + 'New Description', + ), + ).to.be.reverted; // Should revert with token ID out of range or similar + }); + }); + describe('Paranet Incentives Pool', () => { it('Should return correct name and version of factory, incentives pool and storage', async () => { // Incentives pool factory From 2d3ea6c1f8fce788bcba3547fa95e748e6949ea0 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Mon, 24 Feb 2025 16:24:21 +0100 Subject: [PATCH 147/153] Add Paranet service metadata tests --- test/integration/Paranet.test.ts | 550 ++++++++++++++++++++++++++++++- 1 file changed, 549 insertions(+), 1 deletion(-) diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index 6a8022a7..a2d140f3 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -423,7 +423,7 @@ describe('@unit Paranet', () => { }); }); - describe.only('Paranet Metadata', () => { + describe('Paranet Metadata', () => { it('Should update paranet metadata successfully', async () => { const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); @@ -4199,6 +4199,554 @@ describe('@unit Paranet', () => { }); }); + describe.only('Paranet Service Metadata', () => { + it('Should update paranet service metadata successfully', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetOwner, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Create a new knowledge collection for the service + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId: serviceCollectionId } = + await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // 3. Setup service parameters + const serviceName = 'Test Service'; + const serviceDescription = 'Test Service Description'; + const serviceAddresses = [accounts[10].address, accounts[11].address]; + + // 4. Register the service + await Paranet.connect(paranetOwner).registerParanetService( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, // serviceKATokenId + serviceName, + serviceDescription, + serviceAddresses, + ); + + const serviceId = ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256', 'uint256'], + [ + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, + ], + ), + ); + + const newName = 'New Service Name'; + const newDescription = 'New Service Description'; + const newServiceAddresses = [accounts[1].address, accounts[2].address]; + + await Paranet.connect(paranetOwner).updateParanetServiceMetadata( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, + newName, + newDescription, + newServiceAddresses, + ); + + expect(await ParanetServicesRegistry.getName(serviceId)).to.equal( + newName, + ); + expect(await ParanetServicesRegistry.getDescription(serviceId)).to.equal( + newDescription, + ); + expect( + await ParanetServicesRegistry.getParanetServiceAddresses(serviceId), + ).to.deep.equal(newServiceAddresses); + }); + + it('Should emit ParanetServiceMetadataUpdated event with correct parameters', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetOwner, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Create a new knowledge collection for the service + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId: serviceCollectionId } = + await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // 3. Setup service parameters + const serviceName = 'Test Service'; + const serviceDescription = 'Test Service Description'; + const serviceAddresses = [accounts[10].address, accounts[11].address]; + + // 4. Register the service + await Paranet.connect(paranetOwner).registerParanetService( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, // serviceKATokenId + serviceName, + serviceDescription, + serviceAddresses, + ); + + const newName = 'New Service Name'; + const newDescription = 'New Service Description'; + const newServiceAddresses = [accounts[1].address, accounts[2].address]; + + await expect( + Paranet.connect(paranetOwner).updateParanetServiceMetadata( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, + newName, + newDescription, + newServiceAddresses, + ), + ) + .to.emit(Paranet, 'ParanetServiceMetadataUpdated') + .withArgs( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, + newName, + newDescription, + newServiceAddresses, + ); + }); + + it('Should handle empty strings and empty address array', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetOwner, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Create a new knowledge collection for the service + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId: serviceCollectionId } = + await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // 3. Setup service parameters + const serviceName = 'Test Service'; + const serviceDescription = 'Test Service Description'; + const serviceAddresses = [accounts[10].address, accounts[11].address]; + + // 4. Register the service + await Paranet.connect(paranetOwner).registerParanetService( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, // serviceKATokenId + serviceName, + serviceDescription, + serviceAddresses, + ); + + const serviceId = ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256', 'uint256'], + [ + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, + ], + ), + ); + + await Paranet.connect(paranetOwner).updateParanetServiceMetadata( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, + '', + '', + [], + ); + + expect(await ParanetServicesRegistry.getName(serviceId)).to.equal(''); + expect(await ParanetServicesRegistry.getDescription(serviceId)).to.equal( + '', + ); + expect( + await ParanetServicesRegistry.getParanetServiceAddresses(serviceId), + ).to.deep.equal([]); + }); + + it('Should handle very long name, description and large address array', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetOwner, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Create a new knowledge collection for the service + // 2. Create a new knowledge collection for the service + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId: serviceCollectionId } = + await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // 3. Setup service parameters + const serviceName = 'Test Service'; + const serviceDescription = 'Test Service Description'; + const serviceAddresses = [accounts[10].address, accounts[11].address]; + + // 4. Register the service + await Paranet.connect(paranetOwner).registerParanetService( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, // serviceKATokenId + serviceName, + serviceDescription, + serviceAddresses, + ); + + const serviceId = ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256', 'uint256'], + [ + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, + ], + ), + ); + + const longName = 'a'.repeat(100); + const longDescription = 'b'.repeat(1000); + const manyAddresses = accounts + .slice(0, 20) + .map((account) => account.address); // 20 addresses + + await Paranet.connect(paranetOwner).updateParanetServiceMetadata( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, + longName, + longDescription, + manyAddresses, + ); + + expect(await ParanetServicesRegistry.getName(serviceId)).to.equal( + longName, + ); + expect(await ParanetServicesRegistry.getDescription(serviceId)).to.equal( + longDescription, + ); + expect( + await ParanetServicesRegistry.getParanetServiceAddresses(serviceId), + ).to.deep.equal(manyAddresses); + }); + + it('Should allow multiple updates to the same service', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetOwner, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Create a new knowledge collection for the service + // 2. Create a new knowledge collection for the service + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId: serviceCollectionId } = + await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // 3. Setup service parameters + const serviceName = 'Test Service'; + const serviceDescription = 'Test Service Description'; + const serviceAddresses = [accounts[10].address, accounts[11].address]; + + // 4. Register the service + await Paranet.connect(paranetOwner).registerParanetService( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, // serviceKATokenId + serviceName, + serviceDescription, + serviceAddresses, + ); + + const serviceId = ethers.keccak256( + ethers.solidityPacked( + ['address', 'uint256', 'uint256'], + [ + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, + ], + ), + ); + + // First update + await Paranet.connect(paranetOwner).updateParanetServiceMetadata( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, + 'First Name', + 'First Description', + [accounts[1].address], + ); + + // Second update + await Paranet.connect(paranetOwner).updateParanetServiceMetadata( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, + 'Second Name', + 'Second Description', + [accounts[2].address, accounts[3].address], + ); + + expect(await ParanetServicesRegistry.getName(serviceId)).to.equal( + 'Second Name', + ); + expect(await ParanetServicesRegistry.getDescription(serviceId)).to.equal( + 'Second Description', + ); + expect( + await ParanetServicesRegistry.getParanetServiceAddresses(serviceId), + ).to.deep.equal([accounts[2].address, accounts[3].address]); + }); + + // Error cases + it('Should revert when non-owner tries to update service metadata', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const nonOwner = accounts[10]; + + const { + paranetOwner, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Create a new knowledge collection for the service + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId: serviceCollectionId } = + await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // 3. Setup service parameters + const serviceName = 'Test Service'; + const serviceDescription = 'Test Service Description'; + const serviceAddresses = [accounts[10].address, accounts[11].address]; + + // 4. Register the service + await Paranet.connect(paranetOwner).registerParanetService( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, // serviceKATokenId + serviceName, + serviceDescription, + serviceAddresses, + ); + + await expect( + Paranet.connect(nonOwner).updateParanetServiceMetadata( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, + 'New Name', + 'New Description', + [accounts[1].address], + ), + ).to.be.revertedWith("Caller isn't the owner of the KA"); + }); + + it('Should revert when service does not exist', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { + paranetOwner, + publishingNodeIdentityId, + receivingNodesIdentityIds, + } = await setupParanet(kcCreator, publishingNode, receivingNodes, { + Paranet, + Profile, + Token, + KnowledgeCollection, + KnowledgeCollectionStorage, + }); + + // 2. Create a new knowledge collection for the service + const signaturesData = await getKCSignaturesData( + publishingNode, + 1, + receivingNodes, + ); + const { collectionId: serviceCollectionId } = + await createKnowledgeCollection( + kcCreator, + publishingNodeIdentityId, + receivingNodesIdentityIds, + signaturesData, + { + KnowledgeCollection: KnowledgeCollection, + Token: Token, + }, + ); + + // 3. Setup service parameters + const serviceName = 'Test Service'; + const serviceDescription = 'Test Service Description'; + const serviceAddresses = [accounts[10].address, accounts[11].address]; + + // 4. Register the service + await Paranet.connect(paranetOwner).registerParanetService( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 1, // serviceKATokenId + serviceName, + serviceDescription, + serviceAddresses, + ); + + await expect( + Paranet.connect(kcCreator).updateParanetServiceMetadata( + await KnowledgeCollectionStorage.getAddress(), + serviceCollectionId, + 2, + 'New Name', + 'New Description', + [accounts[1].address], + ), + ).to.be.revertedWithCustomError(ParanetLib, 'ParanetServiceDoesntExist'); + }); + }); + // describe('Paranet Permissioned Miners', () => { // it('Should allow owner to add and remove curated miners', async () => { // // Setup paranet with permissioned miners policy From 90ea01fc599dc84b290611de2880d03641e90c2a Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Tue, 25 Feb 2025 09:14:46 +0100 Subject: [PATCH 148/153] remove only --- test/integration/Paranet.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/Paranet.test.ts b/test/integration/Paranet.test.ts index a2d140f3..f605ed99 100644 --- a/test/integration/Paranet.test.ts +++ b/test/integration/Paranet.test.ts @@ -4199,7 +4199,7 @@ describe('@unit Paranet', () => { }); }); - describe.only('Paranet Service Metadata', () => { + describe('Paranet Service Metadata', () => { it('Should update paranet service metadata successfully', async () => { const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); From 88de7ee3ccf57ec8d6fe0d8c0b1d52665f76233e Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 26 Feb 2025 12:58:34 +0100 Subject: [PATCH 149/153] Add tokenOrigin --- .../paranets/ParanetIncentivesPoolStorage.sol | 11 ++- deployments/base_sepolia_test_contracts.json | 80 ++++++++-------- deployments/gnosis_chiado_test_contracts.json | 80 ++++++++-------- deployments/neuroweb_testnet_contracts.json | 96 +++++++++---------- 4 files changed, 138 insertions(+), 129 deletions(-) diff --git a/contracts/paranets/ParanetIncentivesPoolStorage.sol b/contracts/paranets/ParanetIncentivesPoolStorage.sol index 52a78327..19b856d3 100644 --- a/contracts/paranets/ParanetIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetIncentivesPoolStorage.sol @@ -31,6 +31,7 @@ contract ParanetIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInit event VoterRewardClaimed(address indexed voter, uint256 amount); event IncentivesPoolAddressSet(address indexed oldAddress, address indexed newAddress); event RewardTransferred(address indexed recipient, uint256 amount); + event TokenOriginSet(address indexed oldOrigin, address indexed newOrigin); string private constant _NAME = "ParanetIncentivesPoolStorage"; string private constant _VERSION = "1.0.0"; @@ -61,11 +62,12 @@ contract ParanetIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInit ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[] public claimedOperatorRewards; mapping(address => uint256) public claimedOperatorRewardsIndexes; - // Is this good type ? uint96 public cumulativeVotersWeight; ParanetLib.ParanetIncentivizationProposalVoter[] public voters; mapping(address => uint256) public votersIndexes; + address public tokenOrigin; + constructor( address hubAddress, address rewardTokenAddress, @@ -464,6 +466,13 @@ contract ParanetIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInit emit VoterWeightUpdated(voter, oldWeight, newWeight); } + function setTokenOrigin(address newOrigin) external onlyContracts { + require(newOrigin != address(0), "Token origin cannot be zero address"); + address oldOrigin = tokenOrigin; + tokenOrigin = newOrigin; + emit TokenOriginSet(oldOrigin, newOrigin); + } + modifier onlyVotersRegistrar() { require(msg.sender == votersRegistrar, "Fn can only be used by registrar"); _; diff --git a/deployments/base_sepolia_test_contracts.json b/deployments/base_sepolia_test_contracts.json index dfa95014..b52e33a8 100644 --- a/deployments/base_sepolia_test_contracts.json +++ b/deployments/base_sepolia_test_contracts.json @@ -191,75 +191,75 @@ "deployed": true }, "ParanetsRegistry": { - "evmAddress": "0x9206357dE0470578577Da64824948F5C0c75062e", + "evmAddress": "0xB9668A4321b8a6900289E6aE98D4388570C5935C", "version": "1.0.1", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 21888878, - "deploymentTimestamp": 1739546047603, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 22191895, + "deploymentTimestamp": 1740152083167, "deployed": true }, "ParanetServicesRegistry": { - "evmAddress": "0xD3825ba7f62C64841670e474d5F80DB440761090", + "evmAddress": "0x9aE0D8929546931913e591a8Df44F9E99b38B5c9", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 21888881, - "deploymentTimestamp": 1739546053932, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 22191899, + "deploymentTimestamp": 1740152090458, "deployed": true }, "ParanetKnowledgeCollectionsRegistry": { - "evmAddress": "0xEfE1da366bD33D1aa8463E9B426ec9732Cc08d0f", + "evmAddress": "0x558c8C7998fFF417485DD9105834569d3FC84c02", "version": "1.0.1", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 21888884, - "deploymentTimestamp": 1739546060173, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 22191902, + "deploymentTimestamp": 1740152097326, "deployed": true }, "ParanetKnowledgeMinersRegistry": { - "evmAddress": "0x69742927D6C05696e8B9FC44dce8482fE1EAC1a7", + "evmAddress": "0x8E806Cc918438B8eF1fFC02FACCa8B0Da1D9D23A", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 21888887, - "deploymentTimestamp": 1739546066413, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 22191906, + "deploymentTimestamp": 1740152103788, "deployed": true }, "ParanetStagingRegistry": { - "evmAddress": "0x68a499Aa96e3Ab9198E3AFd9878a9A1986ce6FD4", + "evmAddress": "0xc7A45b5DA7CdC36462Fe6E86A73e741C2fd56FDE", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 21888890, - "deploymentTimestamp": 1739546072785, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 22191909, + "deploymentTimestamp": 1740152110301, "deployed": true }, "Paranet": { - "evmAddress": "0x081Bebed0c8b36031B32a78B115528BD84f11Cb5", + "evmAddress": "0x6C9146151ffe049c3AC93A06382495Ef6DDA8833", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "3b84160f991b8d70ecb453779e76582e1897068a", - "deploymentBlock": 21890338, - "deploymentTimestamp": 1739548969315, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 22191912, + "deploymentTimestamp": 1740152117023, "deployed": true }, "ParanetIncentivesPoolFactoryHelper": { - "evmAddress": "0x1Ab3D684d68aeFd45D93AD21D38cec8A021dF92c", + "evmAddress": "0x707d6853BdCA6278592F52314a47E62376B5973B", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 21888897, - "deploymentTimestamp": 1739546085830, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 22191916, + "deploymentTimestamp": 1740152123528, "deployed": true }, "ParanetIncentivesPoolFactory": { - "evmAddress": "0xB6C80577a633d33f4f5B1eaC400f8003c10d8eeA", + "evmAddress": "0x6C62F6DFE2Fe65009527956d24E25dDC0ea1F32b", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 21888900, - "deploymentTimestamp": 1739546092097, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 22191919, + "deploymentTimestamp": 1740152129897, "deployed": true } } diff --git a/deployments/gnosis_chiado_test_contracts.json b/deployments/gnosis_chiado_test_contracts.json index 2f6f767e..2d3de17f 100644 --- a/deployments/gnosis_chiado_test_contracts.json +++ b/deployments/gnosis_chiado_test_contracts.json @@ -191,75 +191,75 @@ "deployed": true }, "ParanetsRegistry": { - "evmAddress": "0xE5d5E772A3c244dB74460Fa4aB8164abc3488b77", + "evmAddress": "0x086830B0b77e7da1CB203cDd53211eDE4f63cbB7", "version": "1.0.1", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 14320926, - "deploymentTimestamp": 1739545228318, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 14435277, + "deploymentTimestamp": 1740152326034, "deployed": true }, "ParanetServicesRegistry": { - "evmAddress": "0xA5dDA9D3E11Cd893c68C6bD18F106F4dA657b217", + "evmAddress": "0xA9786795A83ca13341418F200A63A55c6a8f869A", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 14320928, - "deploymentTimestamp": 1739545237257, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 14435278, + "deploymentTimestamp": 1740152330970, "deployed": true }, "ParanetKnowledgeCollectionsRegistry": { - "evmAddress": "0x6e6B1DF2e3C7fA05bFe7B857EC290E09Bb2253E2", + "evmAddress": "0x3dE88f6fBe7C6A393d2341f4a668D2d67d9b8a82", "version": "1.0.1", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 14320930, - "deploymentTimestamp": 1739545246575, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 14435279, + "deploymentTimestamp": 1740152336117, "deployed": true }, "ParanetKnowledgeMinersRegistry": { - "evmAddress": "0x9b9fE20D5C0340D211E5A1773b2d0579b76355Ce", + "evmAddress": "0x094cE4666839224Af7caFb4Ec1F313b8cb3E0caB", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 14320931, - "deploymentTimestamp": 1739545252290, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 14435280, + "deploymentTimestamp": 1740152341495, "deployed": true }, "ParanetStagingRegistry": { - "evmAddress": "0x7E13De6397Dc696f5f787CD1b37b7C7Fa9f7C9F9", + "evmAddress": "0x429b460986aFeCB70c5c3a7148ae4df66064F842", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 14320932, - "deploymentTimestamp": 1739545257350, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 14435282, + "deploymentTimestamp": 1740152350739, "deployed": true }, "Paranet": { - "evmAddress": "0x1b57cfdcA17834e9236B745c7d2Fe051216C19ea", + "evmAddress": "0xe63903D1263e41F44754a0d006bC11997F9C0086", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "3b84160f991b8d70ecb453779e76582e1897068a", - "deploymentBlock": 14321650, - "deploymentTimestamp": 1739549006694, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 14435283, + "deploymentTimestamp": 1740152355817, "deployed": true }, "ParanetIncentivesPoolFactoryHelper": { - "evmAddress": "0x66c1D07945878A5A0D4051a31bC05EDB787f75b0", + "evmAddress": "0x4e51168Fc4132Dda57A5cA274ce6D56027aF7Cc3", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 14320935, - "deploymentTimestamp": 1739545272239, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 14435284, + "deploymentTimestamp": 1740152361177, "deployed": true }, "ParanetIncentivesPoolFactory": { - "evmAddress": "0x159bBE54A8F3C8c7f78A1dECA0B8B3e203aa0DE5", + "evmAddress": "0x438ff472D5D8332386640E0a5B172219ffE0159f", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 14320937, - "deploymentTimestamp": 1739545281595, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 14435285, + "deploymentTimestamp": 1740152366258, "deployed": true } } diff --git a/deployments/neuroweb_testnet_contracts.json b/deployments/neuroweb_testnet_contracts.json index a55cd291..4cc9c864 100644 --- a/deployments/neuroweb_testnet_contracts.json +++ b/deployments/neuroweb_testnet_contracts.json @@ -212,83 +212,83 @@ "deployed": true }, "ParanetsRegistry": { - "evmAddress": "0xDAb0dF77a85951e217886995E6bCcB3c6590B01E", - "substrateAddress": "5EMjsd15zgA8DAUHD4xzQDhpUGoGojVnBoC8F8Y9C1M2bAuN", + "evmAddress": "0x657B2306de3525341b64902E2aDfA40dCc89B836", + "substrateAddress": "5EMjsczgWWFZsa6iWELCZs6mnduCti8Wo7BZYKYspHot6pUs", "version": "1.0.1", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 6389113, - "deploymentTimestamp": 1739545129429, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 6478927, + "deploymentTimestamp": 1740152415440, "deployed": true }, "ParanetServicesRegistry": { - "evmAddress": "0x62bFe0481DC3c0712179241F44178CB92C478CFe", - "substrateAddress": "5EMjsczfxm5abhSYkYUnwnkG62qtbSZdEbhvaRBxmq3g9urX", + "evmAddress": "0xbF87DF84B631D6CDB828D2cB5fDFD7F400f24E43", + "substrateAddress": "5EMjsczzZ2ivNSpVZdhco6CC9aYijjQsgU2DxwECbPkx9T43", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 6389114, - "deploymentTimestamp": 1739545138454, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 6478929, + "deploymentTimestamp": 1740152420674, "deployed": true }, "ParanetKnowledgeCollectionsRegistry": { - "evmAddress": "0x9589181876C5b376dDe6476Fa8B63C5870D788Ce", - "substrateAddress": "5EMjsczr8ydmcL7Z8kHLtUqoHLcVrhy1WngRmVPCzuKAVBuH", + "evmAddress": "0x91dc076999887AA167aa8b4b1e04329EC431bF82", + "substrateAddress": "5EMjsczqQFnUyR7uBwrKBpTCtN1LbTYjqjitJx6bSuEbAYHg", "version": "1.0.1", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 6389115, - "deploymentTimestamp": 1739545143471, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 6478930, + "deploymentTimestamp": 1740152425820, "deployed": true }, "ParanetKnowledgeMinersRegistry": { - "evmAddress": "0x95C1955F10ABD4a7020547D1D78307c8eB61c8fa", - "substrateAddress": "5EMjsczrBYNaDau1HgCooqyi3RRsuVD2XRsMjDRk3CKVZgBB", + "evmAddress": "0x6Da31cC3D46414065b184756a61Fe45fbBC55F79", + "substrateAddress": "5EMjsczi9HwuT47F1mPseXgiXfKgizaDRmgNDLpyfSu1tNYW", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 6389116, - "deploymentTimestamp": 1739545148571, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 6478932, + "deploymentTimestamp": 1740152439065, "deployed": true }, "ParanetStagingRegistry": { - "evmAddress": "0x38ca1Ad904ba046831ad5E3449ddbd3Ba3D0413b", - "substrateAddress": "5EMjsczXZ7i4ArZm5eVqEy6iBusAi3Q6fkTMQUgzE1ZEPR8p", + "evmAddress": "0x16c3F5395Dd6b1476b99B94F18781ed9BbF98014", + "substrateAddress": "5EMjsczQjhf9joUyCzDPUg29gvdnRQC43NEPx5AwFYqBRD1h", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 6389117, - "deploymentTimestamp": 1739545153778, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 6478933, + "deploymentTimestamp": 1740152444365, "deployed": true }, "Paranet": { - "evmAddress": "0xD684d04A372f28c77F44D926BA7ec3A0d76bEfbD", - "substrateAddress": "5EMjsd15ABvrud7GTWN6RXQUGuQpne6UdJVC6DkwckEvAo3y", + "evmAddress": "0x14a294001A723eED7DB8e094DE10E0B166bFACA7", + "substrateAddress": "5EMjsczQJwfBEMAwFJtZFgVBGdLytpJnMKimHXqVHqUhF73Y", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "3b84160f991b8d70ecb453779e76582e1897068a", - "deploymentBlock": 6389723, - "deploymentTimestamp": 1739549037657, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 6478934, + "deploymentTimestamp": 1740152449574, "deployed": true }, "ParanetIncentivesPoolFactoryHelper": { - "evmAddress": "0x5A6553d60540B31184550B05ed83A1B8071Ae31C", - "substrateAddress": "5EMjsczeHgDwtsG594Mk3NPpH8zE35n5pAThyeQgLerwFz2s", + "evmAddress": "0x97A17bDE06a458aF633AE04A5a235F25a4FE420d", + "substrateAddress": "5EMjsczrZKxpm5YTBA7RUHRfVZ3REmTMdfKiKRjAL1s7YSdi", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 6389119, - "deploymentTimestamp": 1739545168191, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 6478935, + "deploymentTimestamp": 1740152458924, "deployed": true }, "ParanetIncentivesPoolFactory": { - "evmAddress": "0x4fc427922A9593a137A4E834E019c9F079554719", - "substrateAddress": "5EMjsczcA9JXKbkqeSyX1x91zJf7omcNZr8J3PbXkF8yu3GR", + "evmAddress": "0x4809159221E1ed07Ea0a99B6D335A683A45018Cf", + "substrateAddress": "5EMjsczacJMi1VhsFL9Z1oUCbcqz5XHV3U9zFMqyzDYuZsos", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "5115bc4b4c82fa3fe42df976f37fc6372056230c", - "deploymentBlock": 6389120, - "deploymentTimestamp": 1739545173451, + "gitBranch": "v8/unit-tests", + "gitCommitHash": "8d80da87bb433669bc4a03aacb0bb5054b3b375c", + "deploymentBlock": 6478936, + "deploymentTimestamp": 1740152464238, "deployed": true } } From a627be9fb7e8de9b86c56b4d9c0dc8e47775de78 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 26 Feb 2025 13:01:06 +0100 Subject: [PATCH 150/153] Add ABI --- abi/ParanetIncentivesPoolStorage.json | 45 +++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/abi/ParanetIncentivesPoolStorage.json b/abi/ParanetIncentivesPoolStorage.json index 2c66b014..31e83a8b 100644 --- a/abi/ParanetIncentivesPoolStorage.json +++ b/abi/ParanetIncentivesPoolStorage.json @@ -172,6 +172,25 @@ "name": "RewardTransferred", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldOrigin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOrigin", + "type": "address" + } + ], + "name": "TokenOriginSet", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -1299,6 +1318,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOrigin", + "type": "address" + } + ], + "name": "setTokenOrigin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -1351,6 +1383,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "tokenOrigin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "totalMinersclaimedToken", From 4090f41054f7f96958cb2a0e613f9137910b9646 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 26 Feb 2025 13:05:46 +0100 Subject: [PATCH 151/153] Add access modifier to Paranet.sol contracts --- contracts/paranets/Paranet.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/paranets/Paranet.sol b/contracts/paranets/Paranet.sol index a5321d52..124fa45e 100644 --- a/contracts/paranets/Paranet.sol +++ b/contracts/paranets/Paranet.sol @@ -21,14 +21,14 @@ import {KnowledgeCollectionLib} from "../libraries/KnowledgeCollectionLib.sol"; contract Paranet is INamed, IVersioned, ContractStatus, IInitializable { // Access Policy Constants - uint8 constant NODES_ACCESS_POLICY_OPEN = 0; - uint8 constant NODES_ACCESS_POLICY_PERMISSIONED = 1; + uint8 private constant NODES_ACCESS_POLICY_OPEN = 0; + uint8 private constant NODES_ACCESS_POLICY_PERMISSIONED = 1; - uint8 constant MINERS_ACCESS_POLICY_OPEN = 0; - uint8 constant MINERS_ACCESS_POLICY_PERMISSIONED = 1; + uint8 private constant MINERS_ACCESS_POLICY_OPEN = 0; + uint8 private constant MINERS_ACCESS_POLICY_PERMISSIONED = 1; - uint8 constant KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_OPEN = 0; - uint8 constant KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING = 1; + uint8 private constant KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_OPEN = 0; + uint8 private constant KNOWLEDGE_COLLECTIONS_SUBMISSION_POLICY_STAGING = 1; event ParanetRegistered( address indexed paranetKCStorageContract, From ddf7a6a128e453f183f4b2ea8371782b6b24c204 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 26 Feb 2025 13:31:45 +0100 Subject: [PATCH 152/153] Review fixes --- contracts/paranets/ParanetIncentivesPoolStorage.sol | 2 +- contracts/storage/paranets/ParanetStagingRegistry.sol | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/contracts/paranets/ParanetIncentivesPoolStorage.sol b/contracts/paranets/ParanetIncentivesPoolStorage.sol index 19b856d3..9ed4ea59 100644 --- a/contracts/paranets/ParanetIncentivesPoolStorage.sol +++ b/contracts/paranets/ParanetIncentivesPoolStorage.sol @@ -284,7 +284,7 @@ contract ParanetIncentivesPoolStorage is INamed, IVersioned, HubDependent, IInit return (idx < voters.length && voters[idx].addr == addr); } - function addVoterclaimedToken(address voter, uint256 amount) external { + function addVoterClaimedToken(address voter, uint256 amount) external { require(msg.sender == paranetIncentivesPoolAddress, "Caller is not incentives pool contract"); uint256 idx = votersIndexes[voter]; if (idx < voters.length && voters[idx].addr == voter) { diff --git a/contracts/storage/paranets/ParanetStagingRegistry.sol b/contracts/storage/paranets/ParanetStagingRegistry.sol index 174a666b..2ebcaeed 100644 --- a/contracts/storage/paranets/ParanetStagingRegistry.sol +++ b/contracts/storage/paranets/ParanetStagingRegistry.sol @@ -142,13 +142,11 @@ contract ParanetStagingRegistry is INamed, IVersioned, HubDependent { return collectionSubmitters[paranetId][knowledgeCollectionId]; } - // Add this after stageKnowledgeCollection function function _addToPendingCollections(bytes32 paranetId, bytes32 knowledgeCollectionId) internal { pendingCollectionIndexes[paranetId][knowledgeCollectionId] = pendingknowledgeCollectionIds[paranetId].length; pendingknowledgeCollectionIds[paranetId].push(knowledgeCollectionId); } - // Add this in reviewKnowledgeCollection function after status update function _removeFromPendingCollections(bytes32 paranetId, bytes32 knowledgeCollectionId) internal { uint256 index = pendingCollectionIndexes[paranetId][knowledgeCollectionId]; uint256 lastIndex = pendingknowledgeCollectionIds[paranetId].length - 1; From c6cd370193d87cd6a83784ec9774e449591bd7b3 Mon Sep 17 00:00:00 2001 From: Mihajlo Pavlovic Date: Wed, 26 Feb 2025 13:35:17 +0100 Subject: [PATCH 153/153] Update ABI --- abi/ParanetIncentivesPoolStorage.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/abi/ParanetIncentivesPoolStorage.json b/abi/ParanetIncentivesPoolStorage.json index 31e83a8b..798c2524 100644 --- a/abi/ParanetIncentivesPoolStorage.json +++ b/abi/ParanetIncentivesPoolStorage.json @@ -562,7 +562,7 @@ "type": "uint256" } ], - "name": "addVoterclaimedToken", + "name": "addVoterClaimedToken", "outputs": [], "stateMutability": "nonpayable", "type": "function"