diff --git a/contracts/facets/IexecPocoAccessorsFacet.sol b/contracts/facets/IexecPocoAccessorsFacet.sol index 9678f2b82..4c3426c94 100644 --- a/contracts/facets/IexecPocoAccessorsFacet.sol +++ b/contracts/facets/IexecPocoAccessorsFacet.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; -import {PocoStorageLib} from "../libs/PocoStorageLib.v8.sol"; +import {PocoStorageLib, IRegistry} from "../libs/PocoStorageLib.v8.sol"; import {FacetBase} from "./FacetBase.v8.sol"; import {IexecLibCore_v5} from "../libs/IexecLibCore_v5.sol"; import {IexecLibOrders_v5} from "../libs/IexecLibOrders_v5.sol"; @@ -25,6 +25,7 @@ contract IexecPocoAccessorsFacet is using IexecLibOrders_v5 for IexecLibOrders_v5.WorkerpoolOrder; using IexecLibOrders_v5 for IexecLibOrders_v5.RequestOrder; + // ========= Deal and Task Accessors ========= /** * Get a deal created by PoCo classic facet. * @param id The ID of the deal. @@ -73,4 +74,164 @@ contract IexecPocoAccessorsFacet is _toTypedDataHash(requestOrder.hash()) ); } + + function viewConsumed(bytes32 _id) external view returns (uint256 consumed) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return $.m_consumed[_id]; + } + + function viewPresigned(bytes32 _id) external view returns (address signer) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return $.m_presigned[_id]; + } + + function viewContribution( + bytes32 _taskid, + address _worker + ) external view returns (IexecLibCore_v5.Contribution memory) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return $.m_contributions[_taskid][_worker]; + } + + function viewScore(address _worker) external view returns (uint256) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return $.m_workerScores[_worker]; + } + + function resultFor(bytes32 id) external view returns (bytes memory) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + IexecLibCore_v5.Task storage task = $.m_tasks[id]; + require(task.status == IexecLibCore_v5.TaskStatusEnum.COMPLETED, "task-pending"); + return task.resultsCallback; // Expansion - result separation + } + + // ========= SRLC Token and Account Accessors ========= + + function name() external view returns (string memory) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return $.m_name; + } + + function symbol() external view returns (string memory) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return $.m_symbol; + } + + function decimals() external view returns (uint8) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return $.m_decimals; + } + + function totalSupply() external view returns (uint256) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return $.m_totalSupply; + } + + function balanceOf(address account) external view returns (uint256) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return $.m_balances[account]; + } + + function frozenOf(address account) external view returns (uint256) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return $.m_frozens[account]; + } + + function allowance(address account, address spender) external view returns (uint256) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return $.m_allowances[account][spender]; + } + + function viewAccount(address account) external view returns (IexecLibCore_v5.Account memory) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return IexecLibCore_v5.Account($.m_balances[account], $.m_frozens[account]); + } + + function token() external view returns (address) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return address($.m_baseToken); + } + + // ========= Category Accessors ========= + + function viewCategory( + uint256 _catid + ) external view returns (IexecLibCore_v5.Category memory category) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + if (_catid >= $.m_categories.length) { + revert(); // Intentionally revert without reason instead of panic for retro-compatibility with the old interface + } + return $.m_categories[_catid]; + } + + function countCategory() external view returns (uint256 count) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return $.m_categories.length; + } + + // ========= Registry Accessors ========= + + function appregistry() external view returns (IRegistry) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return $.m_appregistry; + } + + function datasetregistry() external view returns (IRegistry) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return $.m_datasetregistry; + } + + function workerpoolregistry() external view returns (IRegistry) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return $.m_workerpoolregistry; + } + + function teebroker() external view returns (address) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return $.m_teebroker; + } + + function callbackgas() external view returns (uint256) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return $.m_callbackgas; + } + + // ========= Constants Accessors ========= + + function contribution_deadline_ratio() external pure returns (uint256) { + return CONTRIBUTION_DEADLINE_RATIO; + } + + function reveal_deadline_ratio() external pure returns (uint256) { + return REVEAL_DEADLINE_RATIO; + } + + function final_deadline_ratio() external pure returns (uint256) { + return FINAL_DEADLINE_RATIO; + } + + function workerpool_stake_ratio() external pure returns (uint256) { + return WORKERPOOL_STAKE_RATIO; + } + + function kitty_ratio() external pure returns (uint256) { + return KITTY_RATIO; + } + + function kitty_min() external pure returns (uint256) { + return KITTY_MIN; + } + + function kitty_address() external pure returns (address) { + return KITTY_ADDRESS; + } + + function groupmember_purpose() external pure returns (uint256) { + return GROUPMEMBER_PURPOSE; + } + + function eip712domain_separator() external view returns (bytes32) { + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + return $.m_eip712DomainSeparator; + } } diff --git a/contracts/interfaces/IexecPocoAccessors.sol b/contracts/interfaces/IexecPocoAccessors.sol index 4e4ddd276..09593f881 100644 --- a/contracts/interfaces/IexecPocoAccessors.sol +++ b/contracts/interfaces/IexecPocoAccessors.sol @@ -5,8 +5,10 @@ pragma solidity ^0.8.0; import {IexecLibCore_v5} from "../libs/IexecLibCore_v5.sol"; import {IexecLibOrders_v5} from "../libs/IexecLibOrders_v5.sol"; +import {IRegistry} from "../libs/PocoStorageLib.v8.sol"; interface IexecPocoAccessors { + // ========= Deal and Task Accessors ========= function viewDeal(bytes32 id) external view returns (IexecLibCore_v5.Deal memory); function viewTask(bytes32 id) external view returns (IexecLibCore_v5.Task memory); @@ -17,4 +19,50 @@ interface IexecPocoAccessors { IexecLibOrders_v5.WorkerpoolOrder calldata workerpoolOrder, IexecLibOrders_v5.RequestOrder calldata requestOrder ) external view returns (uint256); + + function viewConsumed(bytes32 _id) external view returns (uint256 consumed); + + function viewPresigned(bytes32 _id) external view returns (address signer); + + function viewContribution( + bytes32 _taskid, + address _worker + ) external view returns (IexecLibCore_v5.Contribution memory); + + function viewScore(address _worker) external view returns (uint256); + + function resultFor(bytes32 id) external view returns (bytes memory); + + // ========= SRLC Token and Account Accessors ========= + function name() external view returns (string memory); + function symbol() external view returns (string memory); + function decimals() external view returns (uint8); + function totalSupply() external view returns (uint256); + function balanceOf(address account) external view returns (uint256); + function frozenOf(address account) external view returns (uint256); + function allowance(address account, address spender) external view returns (uint256); + function viewAccount(address account) external view returns (IexecLibCore_v5.Account memory); + function token() external view returns (address); + + // ========= Category Accessors ========= + function viewCategory(uint256 _catid) external view returns (IexecLibCore_v5.Category memory); + function countCategory() external view returns (uint256); + + // ========= Registry Accessors ========= + function appregistry() external view returns (IRegistry); + function datasetregistry() external view returns (IRegistry); + function workerpoolregistry() external view returns (IRegistry); + function teebroker() external view returns (address); + function callbackgas() external view returns (uint256); + + // ========= Constants Accessors ========= + function contribution_deadline_ratio() external view returns (uint256); + function reveal_deadline_ratio() external view returns (uint256); + function final_deadline_ratio() external view returns (uint256); + function workerpool_stake_ratio() external view returns (uint256); + function kitty_ratio() external view returns (uint256); + function kitty_min() external view returns (uint256); + function kitty_address() external view returns (address); + function groupmember_purpose() external view returns (uint256); + function eip712domain_separator() external view returns (bytes32); } diff --git a/deploy/0_deploy.ts b/deploy/0_deploy.ts index 70d2e3047..dcd9467d7 100644 --- a/deploy/0_deploy.ts +++ b/deploy/0_deploy.ts @@ -14,7 +14,6 @@ import { DiamondLoupeFacet__factory, Diamond__factory, IexecAccessorsABILegacyFacet__factory, - IexecAccessorsFacet__factory, IexecAccessors__factory, IexecCategoryManagerFacet__factory, IexecCategoryManager__factory, @@ -93,7 +92,6 @@ export default async function deploy() { const isArbitrumMainnet = (await ethers.provider.getNetwork()).chainId === 42161n; const facets = [ new IexecAccessorsABILegacyFacet__factory(), - new IexecAccessorsFacet__factory(), new IexecCategoryManagerFacet__factory(), new IexecConfigurationExtraFacet__factory(), new IexecConfigurationFacet__factory(iexecLibOrders), diff --git a/hardhat.config.ts b/hardhat.config.ts index ce90b7c75..ad9d02b2c 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -17,6 +17,7 @@ const isNativeChainType = chainConfig.isNativeChain(); const isLocalFork = process.env.LOCAL_FORK == 'true'; const isFujiFork = process.env.FUJI_FORK == 'true'; const isArbitrumSepoliaFork = process.env.ARBITRUM_SEPOLIA_FORK == 'true'; +const isArbitrumFork = process.env.ARBITRUM_FORK == 'true'; const bellecourBlockscoutUrl = 'https://blockscout.bellecour.iex.ec'; /** @@ -119,6 +120,13 @@ const config: HardhatUserConfig = { }, ...arbitrumSepoliaBaseConfig, }), + + ...(isArbitrumFork && { + forking: { + url: process.env.ARBITRUM_RPC_URL || 'https://arbitrum.gateway.tenderly.co', + }, + ...arbitrumBaseConfig, + }), }, 'external-hardhat': { ...defaultHardhatNetworkParams, @@ -139,6 +147,10 @@ const config: HardhatUserConfig = { accounts: 'remote', // Override defaults accounts for impersonation ...arbitrumSepoliaBaseConfig, }), + ...(isArbitrumFork && { + accounts: 'remote', // Override defaults accounts for impersonation + ...arbitrumBaseConfig, + }), }, 'dev-native': { chainId: 65535, diff --git a/scripts/upgrades/accessors/deploy-and-update-accessor-facet.ts b/scripts/upgrades/accessors/deploy-and-update-accessor-facet.ts new file mode 100644 index 000000000..6d62cc1a1 --- /dev/null +++ b/scripts/upgrades/accessors/deploy-and-update-accessor-facet.ts @@ -0,0 +1,116 @@ +// SPDX-FileCopyrightText: 2025 IEXEC BLOCKCHAIN TECH +// SPDX-License-Identifier: Apache-2.0 + +import { ZeroAddress } from 'ethers'; +import { ethers } from 'hardhat'; +import { FacetCutAction } from 'hardhat-deploy/dist/types'; +import type { IDiamond } from '../../../typechain'; +import { + DiamondCutFacet__factory, + DiamondLoupeFacet__factory, + IexecPocoAccessorsFacet__factory, +} from '../../../typechain'; +import { Ownable__factory } from '../../../typechain/factories/rlc-faucet-contract/contracts'; +import { FactoryDeployer } from '../../../utils/FactoryDeployer'; +import config from '../../../utils/config'; +import { linkContractToProxy } from '../../../utils/proxy-tools'; +import { printFunctions } from '../upgrade-helper'; + +(async () => { + console.log('Deploying and updating IexecPocoAccessorsFacet...'); + + const [account] = await ethers.getSigners(); + const chainId = (await ethers.provider.getNetwork()).chainId; + const deploymentOptions = config.getChainConfig(chainId).v5; + + if (!deploymentOptions.IexecLibOrders_v5) { + throw new Error('IexecLibOrders_v5 is required'); + } + if (!deploymentOptions.DiamondProxy) { + throw new Error('DiamondProxy is required'); + } + + const diamondProxyAddress = deploymentOptions.DiamondProxy; + console.log(`Network: ${chainId}`); + console.log(`Diamond proxy address: ${diamondProxyAddress}`); + + const proxyOwnerAddress = await Ownable__factory.connect(diamondProxyAddress, account).owner(); + console.log(`Diamond proxy owner: ${proxyOwnerAddress}`); + + // Use impersonated signer only for fork testing, otherwise use account signer + const proxyOwnerSigner = + process.env.ARBITRUM_FORK === 'true' + ? await ethers.getImpersonatedSigner(proxyOwnerAddress) + : account; + const diamondProxyAsOwner = DiamondCutFacet__factory.connect( + diamondProxyAddress, + proxyOwnerSigner, + ); + + console.log('\n=== Step 1: Deploying new IexecPocoAccessorsFacet ==='); + const factoryDeployer = new FactoryDeployer(account, chainId); + const iexecLibOrders = { + ['contracts/libs/IexecLibOrders_v5.sol:IexecLibOrders_v5']: + deploymentOptions.IexecLibOrders_v5, + }; + + const newFacetFactory = new IexecPocoAccessorsFacet__factory(iexecLibOrders); + const newFacetAddress = await factoryDeployer.deployContract(newFacetFactory); + + console.log('\n=== Step 2: Remove old facets (remove all functions of each facet) ==='); + + const diamondLoupe = DiamondLoupeFacet__factory.connect(diamondProxyAddress, account); + const currentFacets = await diamondLoupe.facets(); + + console.log('\nCurrent facets in diamond:'); + currentFacets.forEach((facet) => { + console.log(` ${facet.facetAddress}: ${facet.functionSelectors.length} functions`); + }); + + const oldAccessorFacets = [ + '0xEa232be31ab0112916505Aeb7A2a94b5571DCc6b', //IexecAccessorsFacet + '0xeb40697b275413241d9b31dE568C98B3EA12FFF0', //IexecPocoAccessorsFacet + ]; + + console.log('Diamond functions before upgrade:'); + await printFunctions(diamondProxyAddress); + + const removalCuts: IDiamond.FacetCutStruct[] = []; + + // Remove ALL functions from the old accessor facets using diamondLoupe.facetFunctionSelectors() + for (const facetAddress of oldAccessorFacets) { + const selectors = await diamondLoupe.facetFunctionSelectors(facetAddress); + if (selectors.length > 0) { + console.log( + `Removing old accessor facet ${facetAddress} with ${selectors.length} functions - will remove ALL`, + ); + removalCuts.push({ + facetAddress: ZeroAddress, + action: FacetCutAction.Remove, + functionSelectors: [...selectors], + }); + } + } + + if (removalCuts.length > 0) { + console.log('Executing diamond cut to remove old functions...'); + console.log(`Removal cuts: ${removalCuts.length}`); + removalCuts.forEach((cut, index) => { + console.log(` Cut ${index + 1}: Remove ${cut.functionSelectors.length} functions`); + }); + + const removeTx = await diamondProxyAsOwner.diamondCut(removalCuts, ZeroAddress, '0x'); + await removeTx.wait(); + console.log(`Transaction hash: ${removeTx.hash}`); + console.log('Diamond functions after removing old facets:'); + await printFunctions(diamondProxyAddress); + } + console.log('\n=== Step 3: Updating diamond proxy with new facet ==='); + await linkContractToProxy(diamondProxyAsOwner, newFacetAddress, newFacetFactory); + console.log('New functions added successfully'); + + console.log('Diamond functions after adding new facet:'); + await printFunctions(diamondProxyAddress); + + console.log('\nUpgrade completed successfully!'); +})();