From bec997849545d712f6b19e2194b89f98c5cd0dec Mon Sep 17 00:00:00 2001 From: gfournieriExec Date: Thu, 24 Jul 2025 20:41:14 +0200 Subject: [PATCH 1/3] feat: replace erc1538 naming to diamond proxy naming --- .github/workflows/deploy-smart-contracts.yml | 2 +- .../{DelegateBase.sol => FacetBase.sol} | 10 +- .../{DelegateBase.v8.sol => FacetBase.v8.sol} | 10 +- .../delegates/ENSIntegrationDelegate.sol | 35 --- .../IexecAccessorsABILegacyDelegate.sol | 159 ------------- .../delegates/IexecAccessorsDelegate.sol | 223 ------------------ .../IexecCategoryManagerDelegate.sol | 53 ----- .../modules/delegates/IexecERC20Delegate.sol | 74 ------ .../delegates/IexecEscrowNativeDelegate.sol | 112 --------- .../delegates/IexecEscrowTokenDelegate.sol | 120 ---------- .../IexecEscrowTokenSwapDelegate.sol | 163 ------------- .../delegates/IexecMaintenanceDelegate.sol | 92 -------- .../IexecMaintenanceExtraDelegate.sol | 38 --- .../modules/delegates/IexecRelayDelegate.sol | 32 --- .../modules/delegates/SignatureVerifier.sol | 177 -------------- .../modules/facets/ENSIntegrationFacet.sol | 17 ++ .../facets/IexecAccessorsABILegacyFacet.sol | 122 ++++++++++ .../modules/facets/IexecAccessorsFacet.sol | 151 ++++++++++++ .../facets/IexecCategoryManagerFacet.sol | 26 ++ .../{delegates => facets}/IexecERC20Core.sol | 6 +- contracts/modules/facets/IexecERC20Facet.sol | 66 ++++++ .../{delegates => facets}/IexecEscrow.v8.sol | 4 +- .../modules/facets/IexecEscrowNativeFacet.sol | 77 ++++++ .../modules/facets/IexecEscrowTokenFacet.sol | 88 +++++++ .../facets/IexecEscrowTokenSwapFacet.sol | 206 ++++++++++++++++ .../facets/IexecMaintenanceExtraFacet.sol | 20 ++ .../modules/facets/IexecMaintenanceFacet.sol | 79 +++++++ .../IexecOrderManagementFacet.sol} | 6 +- .../IexecPoco1Facet.sol} | 12 +- .../IexecPoco2Facet.sol} | 6 +- .../IexecPocoAccessorsFacet.sol} | 12 +- .../IexecPocoBoostAccessorsFacet.sol} | 6 +- .../IexecPocoBoostFacet.sol} | 12 +- .../IexecPocoCommonFacet.sol} | 6 +- contracts/modules/facets/IexecRelayFacet.sol | 29 +++ .../modules/facets/SignatureVerifier.sol | 157 ++++++++++++ .../SignatureVerifier.v8.sol | 6 +- .../tools/testing/IexecEscrowTestContract.sol | 2 +- .../IexecPocoBoostCompositeDelegate.sol | 17 -- .../testing/IexecPocoBoostCompositeFacet.sol | 17 ++ contracts/tools/testing/slither/Slither.sol | 8 +- .../tools/testing/slither/SlitherBoost.sol | 6 +- deploy/0_deploy.ts | 92 ++++---- deploy/1_deploy-ens.ts | 8 +- hardhat.config.ts | 8 +- scripts/set-callback-gas.ts | 12 +- scripts/tools/update-config.ts | 8 +- test/000_fullchain-boost.test.ts | 16 +- .../IexecPocoBoost/IexecPocoBoost.test.ts | 12 +- test/utils/IexecWrapper.ts | 6 +- test/utils/fixture-helpers.ts | 6 +- test/utils/hardhat-fixture-deployer.ts | 14 +- utils/config.ts | 3 +- utils/proxy-tools.ts | 4 +- 54 files changed, 1205 insertions(+), 1448 deletions(-) rename contracts/modules/{DelegateBase.sol => FacetBase.sol} (70%) rename contracts/modules/{DelegateBase.v8.sol => FacetBase.v8.sol} (73%) delete mode 100644 contracts/modules/delegates/ENSIntegrationDelegate.sol delete mode 100644 contracts/modules/delegates/IexecAccessorsABILegacyDelegate.sol delete mode 100644 contracts/modules/delegates/IexecAccessorsDelegate.sol delete mode 100644 contracts/modules/delegates/IexecCategoryManagerDelegate.sol delete mode 100644 contracts/modules/delegates/IexecERC20Delegate.sol delete mode 100644 contracts/modules/delegates/IexecEscrowNativeDelegate.sol delete mode 100644 contracts/modules/delegates/IexecEscrowTokenDelegate.sol delete mode 100644 contracts/modules/delegates/IexecEscrowTokenSwapDelegate.sol delete mode 100644 contracts/modules/delegates/IexecMaintenanceDelegate.sol delete mode 100644 contracts/modules/delegates/IexecMaintenanceExtraDelegate.sol delete mode 100644 contracts/modules/delegates/IexecRelayDelegate.sol delete mode 100644 contracts/modules/delegates/SignatureVerifier.sol create mode 100644 contracts/modules/facets/ENSIntegrationFacet.sol create mode 100644 contracts/modules/facets/IexecAccessorsABILegacyFacet.sol create mode 100644 contracts/modules/facets/IexecAccessorsFacet.sol create mode 100644 contracts/modules/facets/IexecCategoryManagerFacet.sol rename contracts/modules/{delegates => facets}/IexecERC20Core.sol (93%) create mode 100644 contracts/modules/facets/IexecERC20Facet.sol rename contracts/modules/{delegates => facets}/IexecEscrow.v8.sol (97%) create mode 100644 contracts/modules/facets/IexecEscrowNativeFacet.sol create mode 100644 contracts/modules/facets/IexecEscrowTokenFacet.sol create mode 100644 contracts/modules/facets/IexecEscrowTokenSwapFacet.sol create mode 100644 contracts/modules/facets/IexecMaintenanceExtraFacet.sol create mode 100644 contracts/modules/facets/IexecMaintenanceFacet.sol rename contracts/modules/{delegates/IexecOrderManagementDelegate.sol => facets/IexecOrderManagementFacet.sol} (96%) rename contracts/modules/{delegates/IexecPoco1Delegate.sol => facets/IexecPoco1Facet.sol} (98%) rename contracts/modules/{delegates/IexecPoco2Delegate.sol => facets/IexecPoco2Facet.sol} (99%) rename contracts/modules/{delegates/IexecPocoAccessorsDelegate.sol => facets/IexecPocoAccessorsFacet.sol} (89%) rename contracts/modules/{delegates/IexecPocoBoostAccessorsDelegate.sol => facets/IexecPocoBoostAccessorsFacet.sol} (74%) rename contracts/modules/{delegates/IexecPocoBoostDelegate.sol => facets/IexecPocoBoostFacet.sol} (98%) rename contracts/modules/{delegates/IexecPocoCommonDelegate.sol => facets/IexecPocoCommonFacet.sol} (93%) create mode 100644 contracts/modules/facets/IexecRelayFacet.sol create mode 100644 contracts/modules/facets/SignatureVerifier.sol rename contracts/modules/{delegates => facets}/SignatureVerifier.v8.sol (97%) delete mode 100644 contracts/tools/testing/IexecPocoBoostCompositeDelegate.sol create mode 100644 contracts/tools/testing/IexecPocoBoostCompositeFacet.sol diff --git a/.github/workflows/deploy-smart-contracts.yml b/.github/workflows/deploy-smart-contracts.yml index 71f4d22e5..4000cb7b6 100644 --- a/.github/workflows/deploy-smart-contracts.yml +++ b/.github/workflows/deploy-smart-contracts.yml @@ -89,7 +89,7 @@ jobs: echo "Deploying to: ${{ inputs.network }} with ${{ inputs.environment }} environment" npm run deploy -- --network ${{ inputs.network }} - - name: Update config.json with ERC1538Proxy address + - name: Update config.json with DiamondProxy address if: inputs.network != 'hardhat' run: npx hardhat run scripts/tools/update-config.ts --network ${{ inputs.network }} diff --git a/contracts/modules/DelegateBase.sol b/contracts/modules/FacetBase.sol similarity index 70% rename from contracts/modules/DelegateBase.sol rename to contracts/modules/FacetBase.sol index a4783dd66..21a0deca3 100644 --- a/contracts/modules/DelegateBase.sol +++ b/contracts/modules/FacetBase.sol @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2020-2024 IEXEC BLOCKCHAIN TECH +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.6.0; @@ -6,13 +6,12 @@ pragma solidity ^0.6.0; import "../Store.sol"; import "./interfaces/IOwnable.sol"; -// Functions that were declared in ERC1538Store are re-declared here. +// Functions that were declared in ERC2535Store are re-declared here. // TODO clean this (use LibDiamond) // - All calls to `owner()` should use `LibDiamond.contractOwner()`. // TODO rename this contract to `FacetBase`. -abstract contract DelegateBase is Store { - +abstract contract FacetBase is Store { modifier onlyOwner() { require(_msgSender() == owner(), "Ownable: caller is not the owner"); _; @@ -22,8 +21,7 @@ abstract contract DelegateBase is Store { return IOwnable(address(this)).owner(); } - function _msgSender() internal view returns (address ) { + function _msgSender() internal view returns (address) { return msg.sender; } - } diff --git a/contracts/modules/DelegateBase.v8.sol b/contracts/modules/FacetBase.v8.sol similarity index 73% rename from contracts/modules/DelegateBase.v8.sol rename to contracts/modules/FacetBase.v8.sol index 9f1422da8..f1e06a88c 100644 --- a/contracts/modules/DelegateBase.v8.sol +++ b/contracts/modules/FacetBase.v8.sol @@ -6,16 +6,16 @@ pragma solidity ^0.8.0; import {IERC5313} from "@openzeppelin/contracts-v5/interfaces/IERC5313.sol"; import {Store} from "../Store.v8.sol"; -// Functions that were declared in ERC1538Store are re-declared here. +// Functions that were declared in ERC2535Store are re-declared here. // TODO clean this (use LibDiamond) // - All calls to `owner()` should use `LibDiamond.contractOwner()`. // TODO rename this contract to `FacetBase`. /** - * @title Base contract of all Delegate contracts. - * @dev Every module must inherit from this contract. + * @title Base contract of all Facet contracts. + * @dev Every facet must inherit from this contract. */ -abstract contract DelegateBase is Store { +abstract contract FacetBase is Store { modifier onlyOwner() { require(_msgSender() == owner(), "Ownable: caller is not the owner"); _; @@ -26,7 +26,7 @@ abstract contract DelegateBase is Store { return IERC5313(address(this)).owner(); } - function _msgSender() internal view returns (address ) { + function _msgSender() internal view returns (address) { return msg.sender; } } diff --git a/contracts/modules/delegates/ENSIntegrationDelegate.sol b/contracts/modules/delegates/ENSIntegrationDelegate.sol deleted file mode 100644 index 8f6a7ac5c..000000000 --- a/contracts/modules/delegates/ENSIntegrationDelegate.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/****************************************************************************** - * Copyright 2020 IEXEC BLOCKCHAIN TECH * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License is distributed on an "AS IS" BASIS, * - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * - * See the License for the specific language governing permissions and * - * limitations under the License. * - ******************************************************************************/ - -pragma solidity ^0.6.0; -pragma experimental ABIEncoderV2; - -import "@iexec/solidity/contracts/ENStools/ENSReverseRegistration.sol"; -import "../DelegateBase.sol"; -import "../interfaces/ENSIntegration.sol"; - -// TODO don't deploy this as ENSReverseRegistration.ADDR_REVERSE_NODE is not defined on Arbitrum. -// TODO update this to use ENS on Arbitrum (update everywhere this is used). -contract ENSIntegrationDelegate is ENSIntegration, ENSReverseRegistration, DelegateBase -{ - function setName(address _ens, string calldata _name) - external override onlyOwner() - { - _setName(IENS(_ens), _name); - } -} diff --git a/contracts/modules/delegates/IexecAccessorsABILegacyDelegate.sol b/contracts/modules/delegates/IexecAccessorsABILegacyDelegate.sol deleted file mode 100644 index 17aaf11ac..000000000 --- a/contracts/modules/delegates/IexecAccessorsABILegacyDelegate.sol +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/****************************************************************************** - * Copyright 2020 IEXEC BLOCKCHAIN TECH * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License is distributed on an "AS IS" BASIS, * - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * - * See the License for the specific language governing permissions and * - * limitations under the License. * - ******************************************************************************/ - -pragma solidity ^0.6.0; -pragma experimental ABIEncoderV2; - -import "../DelegateBase.sol"; -import "../interfaces/IexecAccessorsABILegacy.sol"; - - -contract IexecAccessorsABILegacyDelegate is IexecAccessorsABILegacy, DelegateBase -{ - function viewDealABILegacy_pt1(bytes32 _id) - external view override returns - ( address - , address - , uint256 - , address - , address - , uint256 - , address - , address - , uint256 - ) - { - IexecLibCore_v5.Deal memory deal = m_deals[_id]; - return ( - deal.app.pointer, - deal.app.owner, - deal.app.price, - deal.dataset.pointer, - deal.dataset.owner, - deal.dataset.price, - deal.workerpool.pointer, - deal.workerpool.owner, - deal.workerpool.price - ); - } - - function viewDealABILegacy_pt2(bytes32 _id) - external view override returns - ( uint256 - , bytes32 - , address - , address - , address - , string memory - ) - { - IexecLibCore_v5.Deal memory deal = m_deals[_id]; - return ( - deal.trust, - deal.tag, - deal.requester, - deal.beneficiary, - deal.callback, - deal.params - ); - } - - function viewConfigABILegacy(bytes32 _id) - external view override returns - ( uint256 - , uint256 - , uint256 - , uint256 - , uint256 - , uint256 - ) - { - IexecLibCore_v5.Deal memory deal = m_deals[_id]; - return ( - deal.category, - deal.startTime, - deal.botFirst, - deal.botSize, - deal.workerStake, - deal.schedulerRewardRatio - ); - } - - function viewAccountABILegacy(address account) - external view override returns (uint256, uint256) - { - return ( m_balances[account], m_frozens[account] ); - } - - function viewTaskABILegacy(bytes32 _taskid) - external view override returns - ( IexecLibCore_v5.TaskStatusEnum - , bytes32 - , uint256 - , uint256 - , uint256 - , uint256 - , uint256 - , bytes32 - , uint256 - , uint256 - , address[] memory - , bytes memory - ) - { - IexecLibCore_v5.Task memory task = m_tasks[_taskid]; - return ( - task.status, - task.dealid, - task.idx, - task.timeref, - task.contributionDeadline, - task.revealDeadline, - task.finalDeadline, - task.consensusValue, - task.revealCounter, - task.winnerCounter, - task.contributors, - task.results - ); - } - - function viewContributionABILegacy(bytes32 _taskid, address _worker) - external view override returns - ( IexecLibCore_v5.ContributionStatusEnum - , bytes32 - , bytes32 - , address - ) - { - IexecLibCore_v5.Contribution memory contribution = m_contributions[_taskid][_worker]; - return ( - contribution.status, - contribution.resultHash, - contribution.resultSeal, - contribution.enclaveChallenge - ); - } - - function viewCategoryABILegacy(uint256 _catid) - external view override returns (string memory, string memory, uint256) - { - IexecLibCore_v5.Category memory category = m_categories[_catid]; - return ( category.name, category.description, category.workClockTimeRef ); - } -} diff --git a/contracts/modules/delegates/IexecAccessorsDelegate.sol b/contracts/modules/delegates/IexecAccessorsDelegate.sol deleted file mode 100644 index 35dce1b66..000000000 --- a/contracts/modules/delegates/IexecAccessorsDelegate.sol +++ /dev/null @@ -1,223 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/****************************************************************************** - * Copyright 2020 IEXEC BLOCKCHAIN TECH * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License is distributed on an "AS IS" BASIS, * - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * - * See the License for the specific language governing permissions and * - * limitations under the License. * - ******************************************************************************/ - -pragma solidity ^0.6.0; -pragma experimental ABIEncoderV2; - -import "../DelegateBase.sol"; -import "../interfaces/IexecAccessors.sol"; - - -contract IexecAccessorsDelegate is IexecAccessors, DelegateBase -{ - - function name() - external view override returns (string memory) - { - return m_name; - } - - function symbol() - external view override returns (string memory) - { - return m_symbol; - } - - function decimals() - external view override returns (uint8) - { - return m_decimals; - } - - function totalSupply() - external view override returns (uint256) - { - return m_totalSupply; - } - - function balanceOf(address account) - external view override returns (uint256) - { - return m_balances[account]; - } - - function frozenOf(address account) - external view override returns (uint256) - { - return m_frozens[account]; - } - - function allowance(address account, address spender) - external view override returns (uint256) - { - return m_allowances[account][spender]; - } - - function viewAccount(address account) - external view override returns (IexecLibCore_v5.Account memory) - { - return IexecLibCore_v5.Account(m_balances[account], m_frozens[account]); - } - - function token() - external view override returns (address) - { - return address(m_baseToken); - } - - function viewDeal(bytes32 _id) - external view override returns (IexecLibCore_v5.Deal memory deal) - { - return m_deals[_id]; - } - - function viewConsumed(bytes32 _id) - external view override returns (uint256 consumed) - { - return m_consumed[_id]; - } - - function viewPresigned(bytes32 _id) - external view override returns (address signer) - { - return m_presigned[_id]; - } - - function viewTask(bytes32 _taskid) - external view override returns (IexecLibCore_v5.Task memory) - { - return m_tasks[_taskid]; - } - - function viewContribution(bytes32 _taskid, address _worker) - external view override returns (IexecLibCore_v5.Contribution memory) - { - return m_contributions[_taskid][_worker]; - } - - function viewScore(address _worker) - external view override returns (uint256) - { - return m_workerScores[_worker]; - } - - function resultFor(bytes32 id) - external view override returns (bytes memory) - { - IexecLibCore_v5.Task storage task = m_tasks[id]; - require(task.status == IexecLibCore_v5.TaskStatusEnum.COMPLETED, 'task-pending'); - return task.resultsCallback; // Expansion - result separation - } - - function viewCategory(uint256 _catid) - external view override returns (IexecLibCore_v5.Category memory category) - { - return m_categories[_catid]; - } - - function countCategory() - external view override returns (uint256 count) - { - return m_categories.length; - } - - - function appregistry() - external view override returns (IRegistry) - { - return m_appregistry; - } - - function datasetregistry() - external view override returns (IRegistry) - { - return m_datasetregistry; - } - - function workerpoolregistry() - external view override returns (IRegistry) - { - return m_workerpoolregistry; - } - - function teebroker() - external view override returns (address) - { - return m_teebroker; - } - - function callbackgas() - external view override returns (uint256) - { - return m_callbackgas; - } - - function contribution_deadline_ratio() - external view override returns (uint256) - { - return CONTRIBUTION_DEADLINE_RATIO; - } - - function reveal_deadline_ratio() - external view override returns (uint256) - { - return REVEAL_DEADLINE_RATIO; - } - - function final_deadline_ratio() - external view override returns (uint256) - { - return FINAL_DEADLINE_RATIO; - } - - function workerpool_stake_ratio() - external view override returns (uint256) - { - return WORKERPOOL_STAKE_RATIO; - } - - function kitty_ratio() - external view override returns (uint256) - { - return KITTY_RATIO; - } - - function kitty_min() - external view override returns (uint256) - { - return KITTY_MIN; - } - - function kitty_address() - external view override returns (address) - { - return KITTY_ADDRESS; - } - - function groupmember_purpose() - external view override returns (uint256) - { - return GROUPMEMBER_PURPOSE; - } - - function eip712domain_separator() - external view override returns (bytes32) - { - return EIP712DOMAIN_SEPARATOR; - } -} diff --git a/contracts/modules/delegates/IexecCategoryManagerDelegate.sol b/contracts/modules/delegates/IexecCategoryManagerDelegate.sol deleted file mode 100644 index 86c5acf5a..000000000 --- a/contracts/modules/delegates/IexecCategoryManagerDelegate.sol +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/****************************************************************************** - * Copyright 2020 IEXEC BLOCKCHAIN TECH * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License is distributed on an "AS IS" BASIS, * - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * - * See the License for the specific language governing permissions and * - * limitations under the License. * - ******************************************************************************/ - -pragma solidity ^0.6.0; -pragma experimental ABIEncoderV2; - -import "../DelegateBase.sol"; -import "../interfaces/IexecCategoryManager.sol"; - - -contract IexecCategoryManagerDelegate is IexecCategoryManager, DelegateBase -{ - /** - * Methods - */ - function createCategory( - string calldata name, - string calldata description, - uint256 workClockTimeRef) - external override onlyOwner returns (uint256) - { - m_categories.push(IexecLibCore_v5.Category( - name, - description, - workClockTimeRef - )); - - uint256 catid = m_categories.length - 1; - - emit CreateCategory( - catid, - name, - description, - workClockTimeRef - ); - return catid; - } -} diff --git a/contracts/modules/delegates/IexecERC20Delegate.sol b/contracts/modules/delegates/IexecERC20Delegate.sol deleted file mode 100644 index 937079e83..000000000 --- a/contracts/modules/delegates/IexecERC20Delegate.sol +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/****************************************************************************** - * Copyright 2020 IEXEC BLOCKCHAIN TECH * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License is distributed on an "AS IS" BASIS, * - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * - * See the License for the specific language governing permissions and * - * limitations under the License. * - ******************************************************************************/ - -pragma solidity ^0.6.0; -pragma experimental ABIEncoderV2; - -import "./IexecERC20Core.sol"; -import "../DelegateBase.sol"; -import "../interfaces/IexecERC20.sol"; -import "../interfaces/IexecTokenSpender.sol"; - - -contract IexecERC20Delegate is IexecERC20, DelegateBase, IexecERC20Core -{ - function transfer(address recipient, uint256 amount) - external override returns (bool) - { - _transfer(_msgSender(), recipient, amount); - return true; - } - - function approve(address spender, uint256 value) - external override returns (bool) - { - _approve(_msgSender(), spender, value); - return true; - } - - function approveAndCall(address spender, uint256 value, bytes calldata extraData) - external override returns (bool) - { - _approve(_msgSender(), spender, value); - require(IexecTokenSpender(spender).receiveApproval(_msgSender(), value, address(this), extraData), 'approval-refused'); - return true; - } - - function transferFrom(address sender, address recipient, uint256 amount) - external override returns (bool) - { - _transfer(sender, recipient, amount); - _approve(sender, _msgSender(), m_allowances[sender][_msgSender()].sub(amount)); - return true; - } - - function increaseAllowance(address spender, uint256 addedValue) - external override returns (bool) - { - _approve(_msgSender(), spender, m_allowances[_msgSender()][spender].add(addedValue)); - return true; - } - - - function decreaseAllowance(address spender, uint256 subtractedValue) - external override returns (bool) - { - _approve(_msgSender(), spender, m_allowances[_msgSender()][spender].sub(subtractedValue)); - return true; - } -} diff --git a/contracts/modules/delegates/IexecEscrowNativeDelegate.sol b/contracts/modules/delegates/IexecEscrowNativeDelegate.sol deleted file mode 100644 index 358dc2c71..000000000 --- a/contracts/modules/delegates/IexecEscrowNativeDelegate.sol +++ /dev/null @@ -1,112 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/****************************************************************************** - * Copyright 2020 IEXEC BLOCKCHAIN TECH * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License is distributed on an "AS IS" BASIS, * - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * - * See the License for the specific language governing permissions and * - * limitations under the License. * - ******************************************************************************/ - -pragma solidity ^0.6.0; -pragma experimental ABIEncoderV2; - -import "./IexecERC20Core.sol"; -import "../DelegateBase.sol"; -import "../interfaces/IexecEscrowNative.sol"; - - -contract IexecEscrowNativeDelegate is IexecEscrowNative, DelegateBase, IexecERC20Core -{ - using SafeMathExtended for uint256; - - uint256 internal constant nRLCtoWei = 10 ** 9; - /*************************************************************************** - * Escrow methods: public * - ***************************************************************************/ - receive() - external override payable - { - _deposit(_msgSender()); - } - - fallback() - external override payable - { - _deposit(_msgSender()); - } - - function deposit() - external override payable returns (bool) - { - _deposit(_msgSender()); - return true; - } - - function depositFor(address target) - external override payable returns (bool) - { - _deposit(target); - return true; - } - - function depositForArray(uint256[] calldata amounts, address[] calldata targets) - external override payable returns (bool) - { - require(amounts.length == targets.length, 'invalid-array-length'); - uint256 remaining = msg.value; - for (uint i = 0; i < amounts.length; ++i) - { - _mint(targets[i], amounts[i]); - remaining = remaining.sub(amounts[i].mul(nRLCtoWei)); - } - _withdraw(_msgSender(), remaining); - return true; - } - - function withdraw(uint256 amount) - external override returns (bool) - { - _burn(_msgSender(), amount); - _withdraw(_msgSender(), amount.mul(nRLCtoWei)); - return true; - } - - function withdrawTo(uint256 amount, address target) - external override returns (bool) - { - _burn(_msgSender(), amount); - _withdraw(target, amount.mul(nRLCtoWei)); - return true; - } - - function recover() - external override onlyOwner returns (uint256) - { - uint256 delta = address(this).balance.div(nRLCtoWei).sub(m_totalSupply); - _mint(owner(), delta); - return delta; - } - - function _deposit(address target) - internal - { - _mint(target, msg.value.div(nRLCtoWei)); - _withdraw(_msgSender(), msg.value.mod(nRLCtoWei)); - } - - function _withdraw(address to, uint256 value) - internal - { - (bool success, ) = to.call{value: value}(''); - require(success, 'native-transfer-failed'); - } -} diff --git a/contracts/modules/delegates/IexecEscrowTokenDelegate.sol b/contracts/modules/delegates/IexecEscrowTokenDelegate.sol deleted file mode 100644 index 12c0818b8..000000000 --- a/contracts/modules/delegates/IexecEscrowTokenDelegate.sol +++ /dev/null @@ -1,120 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/****************************************************************************** - * Copyright 2020 IEXEC BLOCKCHAIN TECH * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License is distributed on an "AS IS" BASIS, * - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * - * See the License for the specific language governing permissions and * - * limitations under the License. * - ******************************************************************************/ - -pragma solidity ^0.6.0; -pragma experimental ABIEncoderV2; - -import "./IexecERC20Core.sol"; -import "../DelegateBase.sol"; -import "../interfaces/IexecEscrowToken.sol"; -import "../interfaces/IexecTokenSpender.sol"; - - -contract IexecEscrowTokenDelegate is IexecEscrowToken, IexecTokenSpender, DelegateBase, IexecERC20Core -{ - using SafeMathExtended for uint256; - - /*************************************************************************** - * Escrow methods: public * - ***************************************************************************/ - receive() - external override payable - { - revert('fallback-disabled'); - } - - fallback() - external override payable - { - revert('fallback-disabled'); - } - - function deposit(uint256 amount) - external override returns (bool) - { - _deposit(_msgSender(), amount); - _mint(_msgSender(), amount); - return true; - } - - function depositFor(uint256 amount, address target) - external override returns (bool) - { - _deposit(_msgSender(), amount); - _mint(target, amount); - return true; - } - - function depositForArray(uint256[] calldata amounts, address[] calldata targets) - external override returns (bool) - { - require(amounts.length == targets.length, 'invalid-array-length'); - for (uint i = 0; i < amounts.length; ++i) - { - _deposit(_msgSender(), amounts[i]); - _mint(targets[i], amounts[i]); - } - return true; - } - - function withdraw(uint256 amount) - external override returns (bool) - { - _burn(_msgSender(), amount); - _withdraw(_msgSender(), amount); - return true; - } - - function withdrawTo(uint256 amount, address target) - external override returns (bool) - { - _burn(_msgSender(), amount); - _withdraw(target, amount); - return true; - } - - function recover() - external override onlyOwner returns (uint256) - { - uint256 delta = m_baseToken.balanceOf(address(this)).sub(m_totalSupply); - _mint(owner(), delta); - return delta; - } - - // Token Spender (endpoint for approveAndCallback calls to the proxy) - function receiveApproval(address sender, uint256 amount, address token, bytes calldata) - external override returns (bool) - { - require(token == address(m_baseToken), 'wrong-token'); - _deposit(sender, amount); - _mint(sender, amount); - return true; - } - - function _deposit(address from, uint256 amount) - internal - { - require(m_baseToken.transferFrom(from, address(this), amount), 'failled-transferFrom'); - } - - function _withdraw(address to, uint256 amount) - internal - { - m_baseToken.transfer(to, amount); - } -} diff --git a/contracts/modules/delegates/IexecEscrowTokenSwapDelegate.sol b/contracts/modules/delegates/IexecEscrowTokenSwapDelegate.sol deleted file mode 100644 index a186cd871..000000000 --- a/contracts/modules/delegates/IexecEscrowTokenSwapDelegate.sol +++ /dev/null @@ -1,163 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/****************************************************************************** - * Copyright 2020 IEXEC BLOCKCHAIN TECH * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License is distributed on an "AS IS" BASIS, * - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * - * See the License for the specific language governing permissions and * - * limitations under the License. * - ******************************************************************************/ - -pragma solidity ^0.6.0; -pragma experimental ABIEncoderV2; - -import "./IexecERC20Core.sol"; -import "./SignatureVerifier.sol"; -import "../DelegateBase.sol"; -import "../interfaces/IexecEscrowTokenSwap.sol"; -import "../interfaces/IexecPoco1.sol"; - - -contract IexecEscrowTokenSwapDelegate is IexecEscrowTokenSwap, DelegateBase, IexecERC20Core, SignatureVerifier -{ - using SafeMathExtended for uint256; - using IexecLibOrders_v5 for IexecLibOrders_v5.AppOrder; - using IexecLibOrders_v5 for IexecLibOrders_v5.DatasetOrder; - using IexecLibOrders_v5 for IexecLibOrders_v5.WorkerpoolOrder; - using IexecLibOrders_v5 for IexecLibOrders_v5.RequestOrder; - - IUniswapV2Router02 internal constant router = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D); - - /*************************************************************************** - * Accessor * - ***************************************************************************/ - function UniswapV2Router() - external view override returns (IUniswapV2Router02) - { - return router; - } - - /*************************************************************************** - * Uniswap path - Internal * - ***************************************************************************/ - function _eth2token() - internal view returns (address[] memory) - { - address[] memory path = new address[](2); - path[0] = router.WETH(); - path[1] = address(m_baseToken); - return path; - } - - function _token2eth() - internal view returns (address[] memory) - { - address[] memory path = new address[](2); - path[0] = address(m_baseToken); - path[1] = router.WETH(); - return path; - } - - /*************************************************************************** - * Prediction methods - Public * - ***************************************************************************/ - function estimateDepositEthSent (uint256 eth ) external view override returns (uint256 token) { return router.getAmountsOut(eth, _eth2token())[1]; } - function estimateDepositTokenWanted(uint256 token) external view override returns (uint256 eth ) { return router.getAmountsIn (token, _eth2token())[0]; } - function estimateWithdrawTokenSent (uint256 token) external view override returns (uint256 eth ) { return router.getAmountsOut(token, _token2eth())[1]; } - function estimateWithdrawEthWanted (uint256 eth ) external view override returns (uint256 token) { return router.getAmountsIn (eth, _token2eth())[0]; } - - /*************************************************************************** - * Swapping methods - Public * - ***************************************************************************/ - receive() - external override payable - { - address sender = _msgSender(); - if (sender != address(router)) - { - _deposit(sender, msg.value, 0); - } - } - - fallback() - external override payable - { - revert('fallback-disabled'); - } - - function depositEth ( ) external override payable { _deposit(_msgSender(), msg.value, 0 ); } - function depositEthFor ( address target) external override payable { _deposit(target, msg.value, 0 ); } - function safeDepositEth ( uint256 minimum ) external override payable { _deposit(_msgSender(), msg.value, minimum); } - function safeDepositEthFor( uint256 minimum, address target) external override payable { _deposit(target, msg.value, minimum); } - function requestToken (uint256 amount ) external override payable { _request(_msgSender(), msg.value, amount ); } - function requestTokenFor (uint256 amount, address target) external override payable { _request(target, msg.value, amount ); } - function withdrawEth (uint256 amount ) external override { _withdraw(_msgSender(), amount, 0 ); } - function withdrawEthTo (uint256 amount, address target) external override { _withdraw(target, amount, 0 ); } - function safeWithdrawEth (uint256 amount, uint256 minimum ) external override { _withdraw(_msgSender(), amount, minimum); } - function safeWithdrawEthTo(uint256 amount, uint256 minimum, address target) external override { _withdraw(target, amount, minimum); } - - /*************************************************************************** - * Swapping methods - Internal * - ***************************************************************************/ - function _deposit(address target, uint256 value, uint256 minimum) - internal - { - uint256[] memory amounts = router.swapExactETHForTokens{value: value}(minimum, _eth2token(), address(this), now+1); - _mint(target, amounts[1]); - } - - function _request(address target, uint256 value, uint256 amount) - internal - { - uint256[] memory amounts = router.swapETHForExactTokens{value: value}(amount, _eth2token(), address(this), now+1); - _mint(target, amounts[1]); - // Refund remaining ETH - (bool success, ) = _msgSender().call{value: value.sub(amounts[0])}(''); - require(success, 'native-transfer-failed'); - } - - function _withdraw(address target, uint256 amount, uint256 minimum) - internal - { - m_baseToken.approve(address(router), amount); - uint256[] memory amounts = router.swapExactTokensForETH(amount, minimum, _token2eth(), target, now+1); - _burn(_msgSender(), amounts[0]); - } - - /*************************************************************************** - * Extra public methods * - ***************************************************************************/ - function matchOrdersWithEth( - IexecLibOrders_v5.AppOrder memory _apporder, - IexecLibOrders_v5.DatasetOrder memory _datasetorder, - IexecLibOrders_v5.WorkerpoolOrder memory _workerpoolorder, - IexecLibOrders_v5.RequestOrder memory _requestorder) - public payable override returns (bytes32) - { - uint256 volume; - volume = _apporder.volume.sub(m_consumed[keccak256(_toEthTypedStruct( _apporder.hash(), EIP712DOMAIN_SEPARATOR))]); - if (_datasetorder.dataset != address(0)) - volume = volume.min( _datasetorder.volume.sub(m_consumed[keccak256(_toEthTypedStruct( _datasetorder.hash(), EIP712DOMAIN_SEPARATOR))])); - volume = volume.min(_workerpoolorder.volume.sub(m_consumed[keccak256(_toEthTypedStruct(_workerpoolorder.hash(), EIP712DOMAIN_SEPARATOR))])); - volume = volume.min( _requestorder.volume.sub(m_consumed[keccak256(_toEthTypedStruct( _requestorder.hash(), EIP712DOMAIN_SEPARATOR))])); - - _request( - _requestorder.requester, - msg.value, - _apporder.appprice - .add(_datasetorder.dataset != address(0) ? _datasetorder.datasetprice : 0) - .add(_workerpoolorder.workerpoolprice) - .mul(volume) - ); - - return IexecPoco1(address(this)).matchOrders(_apporder, _datasetorder, _workerpoolorder, _requestorder); - } -} diff --git a/contracts/modules/delegates/IexecMaintenanceDelegate.sol b/contracts/modules/delegates/IexecMaintenanceDelegate.sol deleted file mode 100644 index 81f1b09d2..000000000 --- a/contracts/modules/delegates/IexecMaintenanceDelegate.sol +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-FileCopyrightText: 2020-2024 IEXEC BLOCKCHAIN TECH -// SPDX-License-Identifier: Apache-2.0 - -pragma solidity ^0.6.0; -pragma experimental ABIEncoderV2; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -import "../DelegateBase.sol"; -import "../interfaces/IexecMaintenance.sol"; - -contract IexecMaintenanceDelegate is IexecMaintenance, DelegateBase -{ - using SafeMathExtended for uint256; - using IexecLibOrders_v5 for IexecLibOrders_v5.EIP712Domain; - - // TODO move this to DiamondInit.init(). - function configure( - address _token, - string calldata _name, - string calldata _symbol, - uint8 _decimal, - address _appregistryAddress, - address _datasetregistryAddress, - address _workerpoolregistryAddress, - address _v3_iexecHubAddress) - external override onlyOwner() - { - require(EIP712DOMAIN_SEPARATOR == bytes32(0), 'already-configured'); - EIP712DOMAIN_SEPARATOR = _domain().hash(); - - m_baseToken = IERC20(_token); - m_name = _name; - m_symbol = _symbol; - m_decimals = _decimal; - m_appregistry = IRegistry(_appregistryAddress); - m_datasetregistry = IRegistry(_datasetregistryAddress); - m_workerpoolregistry = IRegistry(_workerpoolregistryAddress); - m_v3_iexecHub = IexecHubInterface(_v3_iexecHubAddress); - m_callbackgas = 100000; - } - - function domain() - external view override returns (IexecLibOrders_v5.EIP712Domain memory) - { - return _domain(); - } - - function updateDomainSeparator() - external override - { - require(EIP712DOMAIN_SEPARATOR != bytes32(0), 'not-configured'); - EIP712DOMAIN_SEPARATOR = _domain().hash(); - } - - function importScore(address _worker) - external override - { - require(!m_v3_scoreImported[_worker], 'score-already-imported'); - m_workerScores[_worker] = m_workerScores[_worker].max(m_v3_iexecHub.viewScore(_worker)); - m_v3_scoreImported[_worker] = true; - } - - function setTeeBroker(address _teebroker) - external override onlyOwner() - { - m_teebroker = _teebroker; - } - - function setCallbackGas(uint256 _callbackgas) - external override onlyOwner() - { - m_callbackgas = _callbackgas; - } - - function _chainId() - internal pure returns (uint256 id) - { - assembly { id := chainid() } - } - - function _domain() - internal view returns (IexecLibOrders_v5.EIP712Domain memory) - { - return IexecLibOrders_v5.EIP712Domain({ - name: 'iExecODB' - , version: '5.0.0' - , chainId: _chainId() - , verifyingContract: address(this) - }); - } -} diff --git a/contracts/modules/delegates/IexecMaintenanceExtraDelegate.sol b/contracts/modules/delegates/IexecMaintenanceExtraDelegate.sol deleted file mode 100644 index 39d6aa861..000000000 --- a/contracts/modules/delegates/IexecMaintenanceExtraDelegate.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/****************************************************************************** - * Copyright 2020 IEXEC BLOCKCHAIN TECH * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License is distributed on an "AS IS" BASIS, * - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * - * See the License for the specific language governing permissions and * - * limitations under the License. * - ******************************************************************************/ - -pragma solidity ^0.6.0; -pragma experimental ABIEncoderV2; - -import "../DelegateBase.sol"; -import "../interfaces/IexecMaintenanceExtra.sol"; - - -contract IexecMaintenanceExtraDelegate is IexecMaintenanceExtra, DelegateBase -{ - function changeRegistries( - address _appregistryAddress, - address _datasetregistryAddress, - address _workerpoolregistryAddress) - external override onlyOwner() - { - m_appregistry = IRegistry(_appregistryAddress); - m_datasetregistry = IRegistry(_datasetregistryAddress); - m_workerpoolregistry = IRegistry(_workerpoolregistryAddress); - } -} diff --git a/contracts/modules/delegates/IexecRelayDelegate.sol b/contracts/modules/delegates/IexecRelayDelegate.sol deleted file mode 100644 index 2f49797b4..000000000 --- a/contracts/modules/delegates/IexecRelayDelegate.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/****************************************************************************** - * Copyright 2020 IEXEC BLOCKCHAIN TECH * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License is distributed on an "AS IS" BASIS, * - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * - * See the License for the specific language governing permissions and * - * limitations under the License. * - ******************************************************************************/ - -pragma solidity ^0.6.0; -pragma experimental ABIEncoderV2; - -import "../DelegateBase.sol"; -import "../interfaces/IexecRelay.sol"; - - -contract IexecRelayDelegate is IexecRelay, DelegateBase -{ - function broadcastAppOrder (IexecLibOrders_v5.AppOrder calldata _apporder ) external override { emit BroadcastAppOrder (_apporder ); } - function broadcastDatasetOrder (IexecLibOrders_v5.DatasetOrder calldata _datasetorder ) external override { emit BroadcastDatasetOrder (_datasetorder ); } - function broadcastWorkerpoolOrder(IexecLibOrders_v5.WorkerpoolOrder calldata _workerpoolorder) external override { emit BroadcastWorkerpoolOrder(_workerpoolorder); } - function broadcastRequestOrder (IexecLibOrders_v5.RequestOrder calldata _requestorder ) external override { emit BroadcastRequestOrder (_requestorder ); } -} diff --git a/contracts/modules/delegates/SignatureVerifier.sol b/contracts/modules/delegates/SignatureVerifier.sol deleted file mode 100644 index 7714011a9..000000000 --- a/contracts/modules/delegates/SignatureVerifier.sol +++ /dev/null @@ -1,177 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/****************************************************************************** - * Copyright 2020 IEXEC BLOCKCHAIN TECH * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License is distributed on an "AS IS" BASIS, * - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * - * See the License for the specific language governing permissions and * - * limitations under the License. * - ******************************************************************************/ - -pragma solidity ^0.6.0; -pragma experimental ABIEncoderV2; - -import "@iexec/solidity/contracts/ERC734/IERC734.sol"; -import "@iexec/solidity/contracts/ERC1271/IERC1271.sol"; -import "@iexec/solidity/contracts/ERC1654/IERC1654.sol"; -import "../DelegateBase.sol"; - - -contract SignatureVerifier is DelegateBase -{ - /** - * Prepare message/structure predicat used for signing - */ - function _toEthSignedMessage(bytes32 _msgHash) - internal pure returns (bytes memory) - { - return abi.encodePacked('\x19Ethereum Signed Message:\n32', _msgHash); - } - - function _toEthTypedStruct(bytes32 _structHash, bytes32 _domainHash) - internal pure returns (bytes memory) - { - return abi.encodePacked('\x19\x01', _domainHash, _structHash); - } - - /** - * recover EOA signature (support both 65 bytes traditional and 64 bytes format EIP2098 format) - */ - function _recover(bytes32 _hash, bytes memory _sign) - internal pure returns (address) - { - bytes32 r; - bytes32 s; - uint8 v; - - if (_sign.length == 65) // 65bytes: (r,s,v) form - { - assembly - { - r := mload(add(_sign, 0x20)) - s := mload(add(_sign, 0x40)) - v := byte(0, mload(add(_sign, 0x60))) - } - } - else if (_sign.length == 64) // 64bytes: (r,vs) form → see EIP2098 - { - assembly - { - r := mload(add(_sign, 0x20)) - s := and( mload(add(_sign, 0x40)), 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) - v := shr(7, byte(0, mload(add(_sign, 0x40)))) - } - } - else - { - revert('invalid-signature-format'); - } - - if (v < 27) v += 27; - require(v == 27 || v == 28, 'invalid-signature-v'); - return ecrecover(_hash, v, r, s); - } - - /** - * Check if contract exist, otherwize assumed to be EOA - */ - function _isContract(address account) - internal view returns (bool) - { - // According to EIP-1052, 0x0 is the value returned for not-yet created accounts - // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned - // for accounts without code, i.e. `keccak256('')` - bytes32 codehash; - bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; - // solhint-disable-next-line no-inline-assembly - assembly { codehash := extcodehash(account) } - return (codehash != accountHash && codehash != 0x0); - } - - /** - * Address to bytes32 casting to ERC734 - */ - function _addrToKey(address _addr) - internal pure returns (bytes32) - { - return bytes32(uint256(_addr)); - } - - /** - * Identity verification - */ - function _checkIdentity(address _identity, address _candidate, uint256 _purpose) - internal view returns (bool valid) - { - return _identity == _candidate || IERC734(_identity).keyHasPurpose(_addrToKey(_candidate), _purpose); // Simple address || ERC 734 identity contract - } - - function _checkPresignature(address _identity, bytes32 _hash) - internal view returns (bool) - { - return _identity != address(0) && _identity == m_presigned[_hash]; - } - - function _checkSignature(address _identity, bytes32 _hash, bytes memory _signature) - internal view returns (bool) - { - if (_isContract(_identity)) - { - try IERC1654(_identity).isValidSignature(_hash, _signature) returns (bytes4 value) - { - return value == IERC1654(0).isValidSignature.selector; - } catch (bytes memory /*lowLevelData*/) {} - - return false; - } - else - { - return _recover(_hash, _signature) == _identity; - } - } - - function _checkSignature(address _identity, bytes memory _predicat, bytes memory _signature) - internal view returns (bool) - { - if (_isContract(_identity)) - { - try IERC1271(_identity).isValidSignature(_predicat, _signature) returns (bytes4 value) - { - return value == IERC1271(0).isValidSignature.selector; - } - catch (bytes memory /*lowLevelData*/) {} - - try IERC1654(_identity).isValidSignature(keccak256(_predicat), _signature) returns (bytes4 value) - { - return value == IERC1654(0).isValidSignature.selector; - } - catch (bytes memory /*lowLevelData*/) {} - - return false; - } - else - { - return _recover(keccak256(_predicat), _signature) == _identity; - } - } - - function _checkPresignatureOrSignature(address _identity, bytes32 _hash, bytes memory _signature) - internal view returns (bool) - { - return _checkPresignature(_identity, _hash) || _checkSignature(_identity, _hash, _signature); - } - - function _checkPresignatureOrSignature(address _identity, bytes memory _predicat, bytes memory _signature) - internal view returns (bool) - { - return _checkPresignature(_identity, keccak256(_predicat)) || _checkSignature(_identity, _predicat, _signature); - } -} diff --git a/contracts/modules/facets/ENSIntegrationFacet.sol b/contracts/modules/facets/ENSIntegrationFacet.sol new file mode 100644 index 000000000..f75799d94 --- /dev/null +++ b/contracts/modules/facets/ENSIntegrationFacet.sol @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.6.0; +pragma experimental ABIEncoderV2; + +import "@iexec/solidity/contracts/ENStools/ENSReverseRegistration.sol"; +import "../FacetBase.sol"; +import "../interfaces/ENSIntegration.sol"; + +// TODO don't deploy this as ENSReverseRegistration.ADDR_REVERSE_NODE is not defined on Arbitrum. +// TODO update this to use ENS on Arbitrum (update everywhere this is used). +contract ENSIntegrationFacet is ENSIntegration, ENSReverseRegistration, FacetBase { + function setName(address _ens, string calldata _name) external override onlyOwner { + _setName(IENS(_ens), _name); + } +} diff --git a/contracts/modules/facets/IexecAccessorsABILegacyFacet.sol b/contracts/modules/facets/IexecAccessorsABILegacyFacet.sol new file mode 100644 index 000000000..5a105138a --- /dev/null +++ b/contracts/modules/facets/IexecAccessorsABILegacyFacet.sol @@ -0,0 +1,122 @@ +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.6.0; +pragma experimental ABIEncoderV2; + +import "../FacetBase.sol"; +import "../interfaces/IexecAccessorsABILegacy.sol"; + +contract IexecAccessorsABILegacyFacet is IexecAccessorsABILegacy, FacetBase { + function viewDealABILegacy_pt1( + bytes32 _id + ) + external + view + override + returns (address, address, uint256, address, address, uint256, address, address, uint256) + { + IexecLibCore_v5.Deal memory deal = m_deals[_id]; + return ( + deal.app.pointer, + deal.app.owner, + deal.app.price, + deal.dataset.pointer, + deal.dataset.owner, + deal.dataset.price, + deal.workerpool.pointer, + deal.workerpool.owner, + deal.workerpool.price + ); + } + + function viewDealABILegacy_pt2( + bytes32 _id + ) external view override returns (uint256, bytes32, address, address, address, string memory) { + IexecLibCore_v5.Deal memory deal = m_deals[_id]; + return (deal.trust, deal.tag, deal.requester, deal.beneficiary, deal.callback, deal.params); + } + + function viewConfigABILegacy( + bytes32 _id + ) external view override returns (uint256, uint256, uint256, uint256, uint256, uint256) { + IexecLibCore_v5.Deal memory deal = m_deals[_id]; + return ( + deal.category, + deal.startTime, + deal.botFirst, + deal.botSize, + deal.workerStake, + deal.schedulerRewardRatio + ); + } + + function viewAccountABILegacy( + address account + ) external view override returns (uint256, uint256) { + return (m_balances[account], m_frozens[account]); + } + + function viewTaskABILegacy( + bytes32 _taskid + ) + external + view + override + returns ( + IexecLibCore_v5.TaskStatusEnum, + bytes32, + uint256, + uint256, + uint256, + uint256, + uint256, + bytes32, + uint256, + uint256, + address[] memory, + bytes memory + ) + { + IexecLibCore_v5.Task memory task = m_tasks[_taskid]; + return ( + task.status, + task.dealid, + task.idx, + task.timeref, + task.contributionDeadline, + task.revealDeadline, + task.finalDeadline, + task.consensusValue, + task.revealCounter, + task.winnerCounter, + task.contributors, + task.results + ); + } + + function viewContributionABILegacy( + bytes32 _taskid, + address _worker + ) + external + view + override + returns (IexecLibCore_v5.ContributionStatusEnum, bytes32, bytes32, address) + { + IexecLibCore_v5.Contribution memory contribution = m_contributions[_taskid][_worker]; + return ( + contribution.status, + contribution.resultHash, + contribution.resultSeal, + contribution.enclaveChallenge + ); + } + + function viewCategoryABILegacy( + uint256 _catid + ) external view override returns (string memory, string memory, uint256) { + IexecLibCore_v5.Category memory category = m_categories[_catid]; + return (category.name, category.description, category.workClockTimeRef); + } +} diff --git a/contracts/modules/facets/IexecAccessorsFacet.sol b/contracts/modules/facets/IexecAccessorsFacet.sol new file mode 100644 index 000000000..1ed9855b2 --- /dev/null +++ b/contracts/modules/facets/IexecAccessorsFacet.sol @@ -0,0 +1,151 @@ +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.6.0; +pragma experimental ABIEncoderV2; + +import "../FacetBase.sol"; +import "../interfaces/IexecAccessors.sol"; + +contract IexecAccessorsFacet is IexecAccessors, FacetBase { + function name() external view override returns (string memory) { + return m_name; + } + + function symbol() external view override returns (string memory) { + return m_symbol; + } + + function decimals() external view override returns (uint8) { + return m_decimals; + } + + function totalSupply() external view override returns (uint256) { + return m_totalSupply; + } + + function balanceOf(address account) external view override returns (uint256) { + return m_balances[account]; + } + + function frozenOf(address account) external view override returns (uint256) { + return m_frozens[account]; + } + + function allowance(address account, address spender) external view override returns (uint256) { + return m_allowances[account][spender]; + } + + function viewAccount( + address account + ) external view override returns (IexecLibCore_v5.Account memory) { + return IexecLibCore_v5.Account(m_balances[account], m_frozens[account]); + } + + function token() external view override returns (address) { + return address(m_baseToken); + } + + function viewDeal( + bytes32 _id + ) external view override returns (IexecLibCore_v5.Deal memory deal) { + return m_deals[_id]; + } + + function viewConsumed(bytes32 _id) external view override returns (uint256 consumed) { + return m_consumed[_id]; + } + + function viewPresigned(bytes32 _id) external view override returns (address signer) { + return m_presigned[_id]; + } + + function viewTask( + bytes32 _taskid + ) external view override returns (IexecLibCore_v5.Task memory) { + return m_tasks[_taskid]; + } + + function viewContribution( + bytes32 _taskid, + address _worker + ) external view override returns (IexecLibCore_v5.Contribution memory) { + return m_contributions[_taskid][_worker]; + } + + function viewScore(address _worker) external view override returns (uint256) { + return m_workerScores[_worker]; + } + + function resultFor(bytes32 id) external view override returns (bytes memory) { + IexecLibCore_v5.Task storage task = m_tasks[id]; + require(task.status == IexecLibCore_v5.TaskStatusEnum.COMPLETED, "task-pending"); + return task.resultsCallback; // Expansion - result separation + } + + function viewCategory( + uint256 _catid + ) external view override returns (IexecLibCore_v5.Category memory category) { + return m_categories[_catid]; + } + + function countCategory() external view override returns (uint256 count) { + return m_categories.length; + } + + function appregistry() external view override returns (IRegistry) { + return m_appregistry; + } + + function datasetregistry() external view override returns (IRegistry) { + return m_datasetregistry; + } + + function workerpoolregistry() external view override returns (IRegistry) { + return m_workerpoolregistry; + } + + function teebroker() external view override returns (address) { + return m_teebroker; + } + + function callbackgas() external view override returns (uint256) { + return m_callbackgas; + } + + function contribution_deadline_ratio() external view override returns (uint256) { + return CONTRIBUTION_DEADLINE_RATIO; + } + + function reveal_deadline_ratio() external view override returns (uint256) { + return REVEAL_DEADLINE_RATIO; + } + + function final_deadline_ratio() external view override returns (uint256) { + return FINAL_DEADLINE_RATIO; + } + + function workerpool_stake_ratio() external view override returns (uint256) { + return WORKERPOOL_STAKE_RATIO; + } + + function kitty_ratio() external view override returns (uint256) { + return KITTY_RATIO; + } + + function kitty_min() external view override returns (uint256) { + return KITTY_MIN; + } + + function kitty_address() external view override returns (address) { + return KITTY_ADDRESS; + } + + function groupmember_purpose() external view override returns (uint256) { + return GROUPMEMBER_PURPOSE; + } + + function eip712domain_separator() external view override returns (bytes32) { + return EIP712DOMAIN_SEPARATOR; + } +} diff --git a/contracts/modules/facets/IexecCategoryManagerFacet.sol b/contracts/modules/facets/IexecCategoryManagerFacet.sol new file mode 100644 index 000000000..827b6c907 --- /dev/null +++ b/contracts/modules/facets/IexecCategoryManagerFacet.sol @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.6.0; +pragma experimental ABIEncoderV2; + +import "../FacetBase.sol"; +import "../interfaces/IexecCategoryManager.sol"; + +contract IexecCategoryManagerFacet is IexecCategoryManager, FacetBase { + /** + * Methods + */ + function createCategory( + string calldata name, + string calldata description, + uint256 workClockTimeRef + ) external override onlyOwner returns (uint256) { + m_categories.push(IexecLibCore_v5.Category(name, description, workClockTimeRef)); + + uint256 catid = m_categories.length - 1; + + emit CreateCategory(catid, name, description, workClockTimeRef); + return catid; + } +} diff --git a/contracts/modules/delegates/IexecERC20Core.sol b/contracts/modules/facets/IexecERC20Core.sol similarity index 93% rename from contracts/modules/delegates/IexecERC20Core.sol rename to contracts/modules/facets/IexecERC20Core.sol index c0ee1d1bd..c558cf0ea 100644 --- a/contracts/modules/delegates/IexecERC20Core.sol +++ b/contracts/modules/facets/IexecERC20Core.sol @@ -1,12 +1,12 @@ -// SPDX-FileCopyrightText: 2020-2024 IEXEC BLOCKCHAIN TECH +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.6.0; pragma experimental ABIEncoderV2; -import "../DelegateBase.sol"; +import "../FacetBase.sol"; -contract IexecERC20Core is DelegateBase { +contract IexecERC20Core is FacetBase { using SafeMathExtended for uint256; event Transfer(address indexed from, address indexed to, uint256 value); diff --git a/contracts/modules/facets/IexecERC20Facet.sol b/contracts/modules/facets/IexecERC20Facet.sol new file mode 100644 index 000000000..19d082fce --- /dev/null +++ b/contracts/modules/facets/IexecERC20Facet.sol @@ -0,0 +1,66 @@ +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.6.0; +pragma experimental ABIEncoderV2; + +import "./IexecERC20Core.sol"; +import "../FacetBase.sol"; +import "../interfaces/IexecERC20.sol"; +import "../interfaces/IexecTokenSpender.sol"; + +contract IexecERC20Facet is IexecERC20, FacetBase, IexecERC20Core { + function transfer(address recipient, uint256 amount) external override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + function approve(address spender, uint256 value) external override returns (bool) { + _approve(_msgSender(), spender, value); + return true; + } + + function approveAndCall( + address spender, + uint256 value, + bytes calldata extraData + ) external override returns (bool) { + _approve(_msgSender(), spender, value); + require( + IexecTokenSpender(spender).receiveApproval( + _msgSender(), + value, + address(this), + extraData + ), + "approval-refused" + ); + return true; + } + + function transferFrom( + address sender, + address recipient, + uint256 amount + ) external override returns (bool) { + _transfer(sender, recipient, amount); + _approve(sender, _msgSender(), m_allowances[sender][_msgSender()].sub(amount)); + return true; + } + + function increaseAllowance( + address spender, + uint256 addedValue + ) external override returns (bool) { + _approve(_msgSender(), spender, m_allowances[_msgSender()][spender].add(addedValue)); + return true; + } + + function decreaseAllowance( + address spender, + uint256 subtractedValue + ) external override returns (bool) { + _approve(_msgSender(), spender, m_allowances[_msgSender()][spender].sub(subtractedValue)); + return true; + } +} diff --git a/contracts/modules/delegates/IexecEscrow.v8.sol b/contracts/modules/facets/IexecEscrow.v8.sol similarity index 97% rename from contracts/modules/delegates/IexecEscrow.v8.sol rename to contracts/modules/facets/IexecEscrow.v8.sol index 540459909..9018742d2 100644 --- a/contracts/modules/delegates/IexecEscrow.v8.sol +++ b/contracts/modules/facets/IexecEscrow.v8.sol @@ -3,12 +3,12 @@ pragma solidity ^0.8.0; -import {DelegateBase} from "../DelegateBase.v8.sol"; +import {FacetBase} from "../FacetBase.v8.sol"; /** * @title Manage (lock/unlock/reward/seize) user funds. */ -contract IexecEscrow is DelegateBase { +contract IexecEscrow is FacetBase { event Transfer(address indexed from, address indexed to, uint256 value); event Lock(address owner, uint256 amount); event Unlock(address owner, uint256 amount); diff --git a/contracts/modules/facets/IexecEscrowNativeFacet.sol b/contracts/modules/facets/IexecEscrowNativeFacet.sol new file mode 100644 index 000000000..47fe3bf29 --- /dev/null +++ b/contracts/modules/facets/IexecEscrowNativeFacet.sol @@ -0,0 +1,77 @@ +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.6.0; +pragma experimental ABIEncoderV2; + +import "./IexecERC20Core.sol"; +import "../FacetBase.sol"; +import "../interfaces/IexecEscrowNative.sol"; + +contract IexecEscrowNativeFacet is IexecEscrowNative, FacetBase, IexecERC20Core { + using SafeMathExtended for uint256; + + uint256 internal constant nRLCtoWei = 10 ** 9; + /*************************************************************************** + * Escrow methods: public * + ***************************************************************************/ + receive() external payable override { + _deposit(_msgSender()); + } + + fallback() external payable override { + _deposit(_msgSender()); + } + + function deposit() external payable override returns (bool) { + _deposit(_msgSender()); + return true; + } + + function depositFor(address target) external payable override returns (bool) { + _deposit(target); + return true; + } + + function depositForArray( + uint256[] calldata amounts, + address[] calldata targets + ) external payable override returns (bool) { + require(amounts.length == targets.length, "invalid-array-length"); + uint256 remaining = msg.value; + for (uint i = 0; i < amounts.length; ++i) { + _mint(targets[i], amounts[i]); + remaining = remaining.sub(amounts[i].mul(nRLCtoWei)); + } + _withdraw(_msgSender(), remaining); + return true; + } + + function withdraw(uint256 amount) external override returns (bool) { + _burn(_msgSender(), amount); + _withdraw(_msgSender(), amount.mul(nRLCtoWei)); + return true; + } + + function withdrawTo(uint256 amount, address target) external override returns (bool) { + _burn(_msgSender(), amount); + _withdraw(target, amount.mul(nRLCtoWei)); + return true; + } + + function recover() external override onlyOwner returns (uint256) { + uint256 delta = address(this).balance.div(nRLCtoWei).sub(m_totalSupply); + _mint(owner(), delta); + return delta; + } + + function _deposit(address target) internal { + _mint(target, msg.value.div(nRLCtoWei)); + _withdraw(_msgSender(), msg.value.mod(nRLCtoWei)); + } + + function _withdraw(address to, uint256 value) internal { + (bool success, ) = to.call{value: value}(""); + require(success, "native-transfer-failed"); + } +} diff --git a/contracts/modules/facets/IexecEscrowTokenFacet.sol b/contracts/modules/facets/IexecEscrowTokenFacet.sol new file mode 100644 index 000000000..656bbdec4 --- /dev/null +++ b/contracts/modules/facets/IexecEscrowTokenFacet.sol @@ -0,0 +1,88 @@ +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.6.0; +pragma experimental ABIEncoderV2; + +import "./IexecERC20Core.sol"; +import "../FacetBase.sol"; +import "../interfaces/IexecEscrowToken.sol"; +import "../interfaces/IexecTokenSpender.sol"; + +contract IexecEscrowTokenFacet is IexecEscrowToken, IexecTokenSpender, FacetBase, IexecERC20Core { + using SafeMathExtended for uint256; + + /*************************************************************************** + * Escrow methods: public * + ***************************************************************************/ + receive() external payable override { + revert("fallback-disabled"); + } + + fallback() external payable override { + revert("fallback-disabled"); + } + + function deposit(uint256 amount) external override returns (bool) { + _deposit(_msgSender(), amount); + _mint(_msgSender(), amount); + return true; + } + + function depositFor(uint256 amount, address target) external override returns (bool) { + _deposit(_msgSender(), amount); + _mint(target, amount); + return true; + } + + function depositForArray( + uint256[] calldata amounts, + address[] calldata targets + ) external override returns (bool) { + require(amounts.length == targets.length, "invalid-array-length"); + for (uint i = 0; i < amounts.length; ++i) { + _deposit(_msgSender(), amounts[i]); + _mint(targets[i], amounts[i]); + } + return true; + } + + function withdraw(uint256 amount) external override returns (bool) { + _burn(_msgSender(), amount); + _withdraw(_msgSender(), amount); + return true; + } + + function withdrawTo(uint256 amount, address target) external override returns (bool) { + _burn(_msgSender(), amount); + _withdraw(target, amount); + return true; + } + + function recover() external override onlyOwner returns (uint256) { + uint256 delta = m_baseToken.balanceOf(address(this)).sub(m_totalSupply); + _mint(owner(), delta); + return delta; + } + + // Token Spender (endpoint for approveAndCallback calls to the proxy) + function receiveApproval( + address sender, + uint256 amount, + address token, + bytes calldata + ) external override returns (bool) { + require(token == address(m_baseToken), "wrong-token"); + _deposit(sender, amount); + _mint(sender, amount); + return true; + } + + function _deposit(address from, uint256 amount) internal { + require(m_baseToken.transferFrom(from, address(this), amount), "failled-transferFrom"); + } + + function _withdraw(address to, uint256 amount) internal { + m_baseToken.transfer(to, amount); + } +} diff --git a/contracts/modules/facets/IexecEscrowTokenSwapFacet.sol b/contracts/modules/facets/IexecEscrowTokenSwapFacet.sol new file mode 100644 index 000000000..253c1f060 --- /dev/null +++ b/contracts/modules/facets/IexecEscrowTokenSwapFacet.sol @@ -0,0 +1,206 @@ +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.6.0; +pragma experimental ABIEncoderV2; + +import "./IexecERC20Core.sol"; +import "./SignatureVerifier.sol"; +import "../FacetBase.sol"; +import "../interfaces/IexecEscrowTokenSwap.sol"; +import "../interfaces/IexecPoco1.sol"; + +contract IexecEscrowTokenSwapFacet is + IexecEscrowTokenSwap, + FacetBase, + IexecERC20Core, + SignatureVerifier +{ + using SafeMathExtended for uint256; + using IexecLibOrders_v5 for IexecLibOrders_v5.AppOrder; + using IexecLibOrders_v5 for IexecLibOrders_v5.DatasetOrder; + using IexecLibOrders_v5 for IexecLibOrders_v5.WorkerpoolOrder; + using IexecLibOrders_v5 for IexecLibOrders_v5.RequestOrder; + + IUniswapV2Router02 internal constant router = + IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D); + + /*************************************************************************** + * Accessor * + ***************************************************************************/ + function UniswapV2Router() external view override returns (IUniswapV2Router02) { + return router; + } + + /*************************************************************************** + * Uniswap path - Internal * + ***************************************************************************/ + function _eth2token() internal view returns (address[] memory) { + address[] memory path = new address[](2); + path[0] = router.WETH(); + path[1] = address(m_baseToken); + return path; + } + + function _token2eth() internal view returns (address[] memory) { + address[] memory path = new address[](2); + path[0] = address(m_baseToken); + path[1] = router.WETH(); + return path; + } + + /*************************************************************************** + * Prediction methods - Public * + ***************************************************************************/ + function estimateDepositEthSent(uint256 eth) external view override returns (uint256 token) { + return router.getAmountsOut(eth, _eth2token())[1]; + } + function estimateDepositTokenWanted( + uint256 token + ) external view override returns (uint256 eth) { + return router.getAmountsIn(token, _eth2token())[0]; + } + function estimateWithdrawTokenSent(uint256 token) external view override returns (uint256 eth) { + return router.getAmountsOut(token, _token2eth())[1]; + } + function estimateWithdrawEthWanted(uint256 eth) external view override returns (uint256 token) { + return router.getAmountsIn(eth, _token2eth())[0]; + } + + /*************************************************************************** + * Swapping methods - Public * + ***************************************************************************/ + receive() external payable override { + address sender = _msgSender(); + if (sender != address(router)) { + _deposit(sender, msg.value, 0); + } + } + + fallback() external payable override { + revert("fallback-disabled"); + } + + function depositEth() external payable override { + _deposit(_msgSender(), msg.value, 0); + } + function depositEthFor(address target) external payable override { + _deposit(target, msg.value, 0); + } + function safeDepositEth(uint256 minimum) external payable override { + _deposit(_msgSender(), msg.value, minimum); + } + function safeDepositEthFor(uint256 minimum, address target) external payable override { + _deposit(target, msg.value, minimum); + } + function requestToken(uint256 amount) external payable override { + _request(_msgSender(), msg.value, amount); + } + function requestTokenFor(uint256 amount, address target) external payable override { + _request(target, msg.value, amount); + } + function withdrawEth(uint256 amount) external override { + _withdraw(_msgSender(), amount, 0); + } + function withdrawEthTo(uint256 amount, address target) external override { + _withdraw(target, amount, 0); + } + function safeWithdrawEth(uint256 amount, uint256 minimum) external override { + _withdraw(_msgSender(), amount, minimum); + } + function safeWithdrawEthTo(uint256 amount, uint256 minimum, address target) external override { + _withdraw(target, amount, minimum); + } + + /*************************************************************************** + * Swapping methods - Internal * + ***************************************************************************/ + function _deposit(address target, uint256 value, uint256 minimum) internal { + uint256[] memory amounts = router.swapExactETHForTokens{value: value}( + minimum, + _eth2token(), + address(this), + now + 1 + ); + _mint(target, amounts[1]); + } + + function _request(address target, uint256 value, uint256 amount) internal { + uint256[] memory amounts = router.swapETHForExactTokens{value: value}( + amount, + _eth2token(), + address(this), + now + 1 + ); + _mint(target, amounts[1]); + // Refund remaining ETH + (bool success, ) = _msgSender().call{value: value.sub(amounts[0])}(""); + require(success, "native-transfer-failed"); + } + + function _withdraw(address target, uint256 amount, uint256 minimum) internal { + m_baseToken.approve(address(router), amount); + uint256[] memory amounts = router.swapExactTokensForETH( + amount, + minimum, + _token2eth(), + target, + now + 1 + ); + _burn(_msgSender(), amounts[0]); + } + + /*************************************************************************** + * Extra public methods * + ***************************************************************************/ + function matchOrdersWithEth( + IexecLibOrders_v5.AppOrder memory _apporder, + IexecLibOrders_v5.DatasetOrder memory _datasetorder, + IexecLibOrders_v5.WorkerpoolOrder memory _workerpoolorder, + IexecLibOrders_v5.RequestOrder memory _requestorder + ) public payable override returns (bytes32) { + uint256 volume; + volume = _apporder.volume.sub( + m_consumed[keccak256(_toEthTypedStruct(_apporder.hash(), EIP712DOMAIN_SEPARATOR))] + ); + if (_datasetorder.dataset != address(0)) + volume = volume.min( + _datasetorder.volume.sub( + m_consumed[ + keccak256(_toEthTypedStruct(_datasetorder.hash(), EIP712DOMAIN_SEPARATOR)) + ] + ) + ); + volume = volume.min( + _workerpoolorder.volume.sub( + m_consumed[ + keccak256(_toEthTypedStruct(_workerpoolorder.hash(), EIP712DOMAIN_SEPARATOR)) + ] + ) + ); + volume = volume.min( + _requestorder.volume.sub( + m_consumed[ + keccak256(_toEthTypedStruct(_requestorder.hash(), EIP712DOMAIN_SEPARATOR)) + ] + ) + ); + + _request( + _requestorder.requester, + msg.value, + _apporder + .appprice + .add(_datasetorder.dataset != address(0) ? _datasetorder.datasetprice : 0) + .add(_workerpoolorder.workerpoolprice) + .mul(volume) + ); + + return + IexecPoco1(address(this)).matchOrders( + _apporder, + _datasetorder, + _workerpoolorder, + _requestorder + ); + } +} diff --git a/contracts/modules/facets/IexecMaintenanceExtraFacet.sol b/contracts/modules/facets/IexecMaintenanceExtraFacet.sol new file mode 100644 index 000000000..ee5ef60f5 --- /dev/null +++ b/contracts/modules/facets/IexecMaintenanceExtraFacet.sol @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.6.0; +pragma experimental ABIEncoderV2; + +import "../FacetBase.sol"; +import "../interfaces/IexecMaintenanceExtra.sol"; + +contract IexecMaintenanceExtraFacet is IexecMaintenanceExtra, FacetBase { + function changeRegistries( + address _appregistryAddress, + address _datasetregistryAddress, + address _workerpoolregistryAddress + ) external override onlyOwner { + m_appregistry = IRegistry(_appregistryAddress); + m_datasetregistry = IRegistry(_datasetregistryAddress); + m_workerpoolregistry = IRegistry(_workerpoolregistryAddress); + } +} diff --git a/contracts/modules/facets/IexecMaintenanceFacet.sol b/contracts/modules/facets/IexecMaintenanceFacet.sol new file mode 100644 index 000000000..540be7e20 --- /dev/null +++ b/contracts/modules/facets/IexecMaintenanceFacet.sol @@ -0,0 +1,79 @@ +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.6.0; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +import "../FacetBase.sol"; +import "../interfaces/IexecMaintenance.sol"; + +contract IexecMaintenanceFacet is IexecMaintenance, FacetBase { + using SafeMathExtended for uint256; + using IexecLibOrders_v5 for IexecLibOrders_v5.EIP712Domain; + + // TODO move this to DiamondInit.init(). + function configure( + address _token, + string calldata _name, + string calldata _symbol, + uint8 _decimal, + address _appregistryAddress, + address _datasetregistryAddress, + address _workerpoolregistryAddress, + address _v3_iexecHubAddress + ) external override onlyOwner { + require(EIP712DOMAIN_SEPARATOR == bytes32(0), "already-configured"); + EIP712DOMAIN_SEPARATOR = _domain().hash(); + + m_baseToken = IERC20(_token); + m_name = _name; + m_symbol = _symbol; + m_decimals = _decimal; + m_appregistry = IRegistry(_appregistryAddress); + m_datasetregistry = IRegistry(_datasetregistryAddress); + m_workerpoolregistry = IRegistry(_workerpoolregistryAddress); + m_v3_iexecHub = IexecHubInterface(_v3_iexecHubAddress); + m_callbackgas = 100000; + } + + function domain() external view override returns (IexecLibOrders_v5.EIP712Domain memory) { + return _domain(); + } + + function updateDomainSeparator() external override { + require(EIP712DOMAIN_SEPARATOR != bytes32(0), "not-configured"); + EIP712DOMAIN_SEPARATOR = _domain().hash(); + } + + function importScore(address _worker) external override { + require(!m_v3_scoreImported[_worker], "score-already-imported"); + m_workerScores[_worker] = m_workerScores[_worker].max(m_v3_iexecHub.viewScore(_worker)); + m_v3_scoreImported[_worker] = true; + } + + function setTeeBroker(address _teebroker) external override onlyOwner { + m_teebroker = _teebroker; + } + + function setCallbackGas(uint256 _callbackgas) external override onlyOwner { + m_callbackgas = _callbackgas; + } + + function _chainId() internal pure returns (uint256 id) { + assembly { + id := chainid() + } + } + + function _domain() internal view returns (IexecLibOrders_v5.EIP712Domain memory) { + return + IexecLibOrders_v5.EIP712Domain({ + name: "iExecODB", + version: "5.0.0", + chainId: _chainId(), + verifyingContract: address(this) + }); + } +} diff --git a/contracts/modules/delegates/IexecOrderManagementDelegate.sol b/contracts/modules/facets/IexecOrderManagementFacet.sol similarity index 96% rename from contracts/modules/delegates/IexecOrderManagementDelegate.sol rename to contracts/modules/facets/IexecOrderManagementFacet.sol index 3ebba8a13..b412c9a77 100644 --- a/contracts/modules/delegates/IexecOrderManagementDelegate.sol +++ b/contracts/modules/facets/IexecOrderManagementFacet.sol @@ -1,15 +1,15 @@ -// SPDX-FileCopyrightText: 2020-2024 IEXEC BLOCKCHAIN TECH +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; import {IERC5313} from "@openzeppelin/contracts-v5/interfaces/IERC5313.sol"; import {SignatureVerifier} from "./SignatureVerifier.v8.sol"; -import {DelegateBase} from "../DelegateBase.v8.sol"; +import {FacetBase} from "../FacetBase.v8.sol"; import {IexecOrderManagement} from "../interfaces/IexecOrderManagement.v8.sol"; import {IexecLibOrders_v5} from "../../libs/IexecLibOrders_v5.sol"; -contract IexecOrderManagementDelegate is IexecOrderManagement, DelegateBase, SignatureVerifier { +contract IexecOrderManagementFacet is IexecOrderManagement, FacetBase, SignatureVerifier { using IexecLibOrders_v5 for IexecLibOrders_v5.AppOrder; using IexecLibOrders_v5 for IexecLibOrders_v5.DatasetOrder; using IexecLibOrders_v5 for IexecLibOrders_v5.WorkerpoolOrder; diff --git a/contracts/modules/delegates/IexecPoco1Delegate.sol b/contracts/modules/facets/IexecPoco1Facet.sol similarity index 98% rename from contracts/modules/delegates/IexecPoco1Delegate.sol rename to contracts/modules/facets/IexecPoco1Facet.sol index 066cdf0a4..f4e8804b2 100644 --- a/contracts/modules/delegates/IexecPoco1Delegate.sol +++ b/contracts/modules/facets/IexecPoco1Facet.sol @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2020-2024 IEXEC BLOCKCHAIN TECH +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; @@ -9,10 +9,10 @@ import {Math} from "@openzeppelin/contracts-v5/utils/math/Math.sol"; import {IexecLibCore_v5} from "../../libs/IexecLibCore_v5.sol"; import {IexecLibOrders_v5} from "../../libs/IexecLibOrders_v5.sol"; import {IWorkerpool} from "../../registries/workerpools/IWorkerpool.v8.sol"; -import {DelegateBase} from "../DelegateBase.v8.sol"; +import {FacetBase} from "../FacetBase.v8.sol"; import {IexecPoco1} from "../interfaces/IexecPoco1.v8.sol"; import {IexecEscrow} from "./IexecEscrow.v8.sol"; -import {IexecPocoCommonDelegate} from "./IexecPocoCommonDelegate.sol"; +import {IexecPocoCommonFacet} from "./IexecPocoCommonFacet.sol"; import {SignatureVerifier} from "./SignatureVerifier.v8.sol"; struct Matching { @@ -26,12 +26,12 @@ struct Matching { bool hasDataset; } -contract IexecPoco1Delegate is +contract IexecPoco1Facet is IexecPoco1, - DelegateBase, + FacetBase, IexecEscrow, SignatureVerifier, - IexecPocoCommonDelegate + IexecPocoCommonFacet { using Math for uint256; using IexecLibOrders_v5 for IexecLibOrders_v5.AppOrder; diff --git a/contracts/modules/delegates/IexecPoco2Delegate.sol b/contracts/modules/facets/IexecPoco2Facet.sol similarity index 99% rename from contracts/modules/delegates/IexecPoco2Delegate.sol rename to contracts/modules/facets/IexecPoco2Facet.sol index fa6447edf..c59387715 100644 --- a/contracts/modules/delegates/IexecPoco2Delegate.sol +++ b/contracts/modules/facets/IexecPoco2Facet.sol @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2020-2024 IEXEC BLOCKCHAIN TECH +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; @@ -7,14 +7,14 @@ import {Math} from "@openzeppelin/contracts-v5/utils/math/Math.sol"; import {IOracleConsumer} from "../../external/interfaces/IOracleConsumer.sol"; import {IexecLibCore_v5} from "../../libs/IexecLibCore_v5.sol"; import {IexecLibOrders_v5} from "../../libs/IexecLibOrders_v5.sol"; -import {DelegateBase} from "../DelegateBase.v8.sol"; +import {FacetBase} from "../FacetBase.v8.sol"; import {IexecPoco2} from "../interfaces/IexecPoco2.v8.sol"; import {IexecEscrow} from "./IexecEscrow.v8.sol"; import {SignatureVerifier} from "./SignatureVerifier.v8.sol"; // TODO: Revert with custom errors -contract IexecPoco2Delegate is IexecPoco2, DelegateBase, IexecEscrow, SignatureVerifier { +contract IexecPoco2Facet is IexecPoco2, FacetBase, IexecEscrow, SignatureVerifier { modifier onlyScheduler(bytes32 _taskId) { require(_msgSender() == m_deals[m_tasks[_taskId].dealid].workerpool.owner); _; diff --git a/contracts/modules/delegates/IexecPocoAccessorsDelegate.sol b/contracts/modules/facets/IexecPocoAccessorsFacet.sol similarity index 89% rename from contracts/modules/delegates/IexecPocoAccessorsDelegate.sol rename to contracts/modules/facets/IexecPocoAccessorsFacet.sol index 1f871ab2b..7b6c1905d 100644 --- a/contracts/modules/delegates/IexecPocoAccessorsDelegate.sol +++ b/contracts/modules/facets/IexecPocoAccessorsFacet.sol @@ -1,23 +1,23 @@ -// SPDX-FileCopyrightText: 2024 IEXEC BLOCKCHAIN TECH +// SPDX-FileCopyrightText: 2024-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; -import {DelegateBase} from "../DelegateBase.v8.sol"; +import {FacetBase} from "../FacetBase.v8.sol"; import {IexecLibCore_v5} from "../../libs/IexecLibCore_v5.sol"; import {IexecLibOrders_v5} from "../../libs/IexecLibOrders_v5.sol"; import {IexecPocoAccessors} from "../interfaces/IexecPocoAccessors.sol"; -import {IexecPocoCommonDelegate} from "./IexecPocoCommonDelegate.sol"; +import {IexecPocoCommonFacet} from "./IexecPocoCommonFacet.sol"; import {SignatureVerifier} from "./SignatureVerifier.v8.sol"; /** * @title Getters contract for PoCo module. */ -contract IexecPocoAccessorsDelegate is +contract IexecPocoAccessorsFacet is IexecPocoAccessors, - DelegateBase, + FacetBase, SignatureVerifier, - IexecPocoCommonDelegate + IexecPocoCommonFacet { using IexecLibOrders_v5 for IexecLibOrders_v5.AppOrder; using IexecLibOrders_v5 for IexecLibOrders_v5.DatasetOrder; diff --git a/contracts/modules/delegates/IexecPocoBoostAccessorsDelegate.sol b/contracts/modules/facets/IexecPocoBoostAccessorsFacet.sol similarity index 74% rename from contracts/modules/delegates/IexecPocoBoostAccessorsDelegate.sol rename to contracts/modules/facets/IexecPocoBoostAccessorsFacet.sol index fa3f47cbc..5242a4fcf 100644 --- a/contracts/modules/delegates/IexecPocoBoostAccessorsDelegate.sol +++ b/contracts/modules/facets/IexecPocoBoostAccessorsFacet.sol @@ -1,17 +1,17 @@ -// SPDX-FileCopyrightText: 2023 IEXEC BLOCKCHAIN TECH +// SPDX-FileCopyrightText: 2023-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; import {IexecLibCore_v5} from "../../libs/IexecLibCore_v5.sol"; -import {DelegateBase} from "../DelegateBase.v8.sol"; +import {FacetBase} from "../FacetBase.v8.sol"; import {IexecPocoBoostAccessors} from "../interfaces/IexecPocoBoostAccessors.sol"; /** * @title Getters contract for PoCo Boost module. * @notice Access to PoCo Boost tasks must be done with PoCo Classic `IexecAccessors`. */ -contract IexecPocoBoostAccessorsDelegate is IexecPocoBoostAccessors, DelegateBase { +contract IexecPocoBoostAccessorsFacet is IexecPocoBoostAccessors, FacetBase { /** * Get a deal created by PoCo Boost module. * @param id The ID of the deal. diff --git a/contracts/modules/delegates/IexecPocoBoostDelegate.sol b/contracts/modules/facets/IexecPocoBoostFacet.sol similarity index 98% rename from contracts/modules/delegates/IexecPocoBoostDelegate.sol rename to contracts/modules/facets/IexecPocoBoostFacet.sol index 11cee8be1..28caf7368 100644 --- a/contracts/modules/delegates/IexecPocoBoostDelegate.sol +++ b/contracts/modules/facets/IexecPocoBoostFacet.sol @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023-2024 IEXEC BLOCKCHAIN TECH +// SPDX-FileCopyrightText: 2023-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; @@ -13,22 +13,22 @@ import {IOracleConsumer} from "../../external/interfaces/IOracleConsumer.sol"; import {IexecLibCore_v5} from "../../libs/IexecLibCore_v5.sol"; import {IexecLibOrders_v5} from "../../libs/IexecLibOrders_v5.sol"; import {IWorkerpool} from "../../registries/workerpools/IWorkerpool.v8.sol"; -import {DelegateBase} from "../DelegateBase.v8.sol"; +import {FacetBase} from "../FacetBase.v8.sol"; import {IexecPocoBoost} from "../interfaces/IexecPocoBoost.sol"; import {IexecEscrow} from "./IexecEscrow.v8.sol"; -import {IexecPocoCommonDelegate} from "./IexecPocoCommonDelegate.sol"; +import {IexecPocoCommonFacet} from "./IexecPocoCommonFacet.sol"; import {SignatureVerifier} from "./SignatureVerifier.v8.sol"; /** * @title PoCo Boost to reduce latency and increase throughput of deals. * @notice Works for deals with requested trust = 0. */ -contract IexecPocoBoostDelegate is +contract IexecPocoBoostFacet is IexecPocoBoost, - DelegateBase, + FacetBase, IexecEscrow, SignatureVerifier, - IexecPocoCommonDelegate + IexecPocoCommonFacet { using ECDSA for bytes32; using MessageHashUtils for bytes32; diff --git a/contracts/modules/delegates/IexecPocoCommonDelegate.sol b/contracts/modules/facets/IexecPocoCommonFacet.sol similarity index 93% rename from contracts/modules/delegates/IexecPocoCommonDelegate.sol rename to contracts/modules/facets/IexecPocoCommonFacet.sol index 4f7eef766..3bba0a733 100644 --- a/contracts/modules/delegates/IexecPocoCommonDelegate.sol +++ b/contracts/modules/facets/IexecPocoCommonFacet.sol @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2024 IEXEC BLOCKCHAIN TECH +// SPDX-FileCopyrightText: 2024-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; @@ -6,9 +6,9 @@ pragma solidity ^0.8.0; import {Math} from "@openzeppelin/contracts-v5/utils/math/Math.sol"; import {IexecLibOrders_v5} from "../../libs/IexecLibOrders_v5.sol"; -import {DelegateBase} from "../DelegateBase.v8.sol"; +import {FacetBase} from "../FacetBase.v8.sol"; -contract IexecPocoCommonDelegate is DelegateBase { +contract IexecPocoCommonFacet is FacetBase { using Math for uint256; using IexecLibOrders_v5 for IexecLibOrders_v5.AppOrder; using IexecLibOrders_v5 for IexecLibOrders_v5.DatasetOrder; diff --git a/contracts/modules/facets/IexecRelayFacet.sol b/contracts/modules/facets/IexecRelayFacet.sol new file mode 100644 index 000000000..b97d9baf5 --- /dev/null +++ b/contracts/modules/facets/IexecRelayFacet.sol @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.6.0; +pragma experimental ABIEncoderV2; + +import "../FacetBase.sol"; +import "../interfaces/IexecRelay.sol"; + +contract IexecRelayFacet is IexecRelay, FacetBase { + function broadcastAppOrder(IexecLibOrders_v5.AppOrder calldata _apporder) external override { + emit BroadcastAppOrder(_apporder); + } + function broadcastDatasetOrder( + IexecLibOrders_v5.DatasetOrder calldata _datasetorder + ) external override { + emit BroadcastDatasetOrder(_datasetorder); + } + function broadcastWorkerpoolOrder( + IexecLibOrders_v5.WorkerpoolOrder calldata _workerpoolorder + ) external override { + emit BroadcastWorkerpoolOrder(_workerpoolorder); + } + function broadcastRequestOrder( + IexecLibOrders_v5.RequestOrder calldata _requestorder + ) external override { + emit BroadcastRequestOrder(_requestorder); + } +} diff --git a/contracts/modules/facets/SignatureVerifier.sol b/contracts/modules/facets/SignatureVerifier.sol new file mode 100644 index 000000000..b8e297d8d --- /dev/null +++ b/contracts/modules/facets/SignatureVerifier.sol @@ -0,0 +1,157 @@ +// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.6.0; +pragma experimental ABIEncoderV2; + +import "@iexec/solidity/contracts/ERC734/IERC734.sol"; +import "@iexec/solidity/contracts/ERC1271/IERC1271.sol"; +import "@iexec/solidity/contracts/ERC1654/IERC1654.sol"; +import "../FacetBase.sol"; + +contract SignatureVerifier is FacetBase { + /** + * Prepare message/structure predicat used for signing + */ + function _toEthSignedMessage(bytes32 _msgHash) internal pure returns (bytes memory) { + return abi.encodePacked("\x19Ethereum Signed Message:\n32", _msgHash); + } + + function _toEthTypedStruct( + bytes32 _structHash, + bytes32 _domainHash + ) internal pure returns (bytes memory) { + return abi.encodePacked("\x19\x01", _domainHash, _structHash); + } + + /** + * recover EOA signature (support both 65 bytes traditional and 64 bytes format EIP2098 format) + */ + function _recover(bytes32 _hash, bytes memory _sign) internal pure returns (address) { + bytes32 r; + bytes32 s; + uint8 v; + + if (_sign.length == 65) // 65bytes: (r,s,v) form + { + assembly { + r := mload(add(_sign, 0x20)) + s := mload(add(_sign, 0x40)) + v := byte(0, mload(add(_sign, 0x60))) + } + } else if (_sign.length == 64) // 64bytes: (r,vs) form → see EIP2098 + { + assembly { + r := mload(add(_sign, 0x20)) + s := and( + mload(add(_sign, 0x40)), + 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + ) + v := shr(7, byte(0, mload(add(_sign, 0x40)))) + } + } else { + revert("invalid-signature-format"); + } + + if (v < 27) v += 27; + require(v == 27 || v == 28, "invalid-signature-v"); + return ecrecover(_hash, v, r, s); + } + + /** + * Check if contract exist, otherwize assumed to be EOA + */ + function _isContract(address account) internal view returns (bool) { + // According to EIP-1052, 0x0 is the value returned for not-yet created accounts + // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned + // for accounts without code, i.e. `keccak256('')` + bytes32 codehash; + bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; + // solhint-disable-next-line no-inline-assembly + assembly { + codehash := extcodehash(account) + } + return (codehash != accountHash && codehash != 0x0); + } + + /** + * Address to bytes32 casting to ERC734 + */ + function _addrToKey(address _addr) internal pure returns (bytes32) { + return bytes32(uint256(_addr)); + } + + /** + * Identity verification + */ + function _checkIdentity( + address _identity, + address _candidate, + uint256 _purpose + ) internal view returns (bool valid) { + return + _identity == _candidate || + IERC734(_identity).keyHasPurpose(_addrToKey(_candidate), _purpose); // Simple address || ERC 734 identity contract + } + + function _checkPresignature(address _identity, bytes32 _hash) internal view returns (bool) { + return _identity != address(0) && _identity == m_presigned[_hash]; + } + + function _checkSignature( + address _identity, + bytes32 _hash, + bytes memory _signature + ) internal view returns (bool) { + if (_isContract(_identity)) { + try IERC1654(_identity).isValidSignature(_hash, _signature) returns (bytes4 value) { + return value == IERC1654(0).isValidSignature.selector; + } catch (bytes memory /*lowLevelData*/) {} + + return false; + } else { + return _recover(_hash, _signature) == _identity; + } + } + + function _checkSignature( + address _identity, + bytes memory _predicat, + bytes memory _signature + ) internal view returns (bool) { + if (_isContract(_identity)) { + try IERC1271(_identity).isValidSignature(_predicat, _signature) returns (bytes4 value) { + return value == IERC1271(0).isValidSignature.selector; + } catch (bytes memory /*lowLevelData*/) {} + + try IERC1654(_identity).isValidSignature(keccak256(_predicat), _signature) returns ( + bytes4 value + ) { + return value == IERC1654(0).isValidSignature.selector; + } catch (bytes memory /*lowLevelData*/) {} + + return false; + } else { + return _recover(keccak256(_predicat), _signature) == _identity; + } + } + + function _checkPresignatureOrSignature( + address _identity, + bytes32 _hash, + bytes memory _signature + ) internal view returns (bool) { + return + _checkPresignature(_identity, _hash) || _checkSignature(_identity, _hash, _signature); + } + + function _checkPresignatureOrSignature( + address _identity, + bytes memory _predicat, + bytes memory _signature + ) internal view returns (bool) { + return + _checkPresignature(_identity, keccak256(_predicat)) || + _checkSignature(_identity, _predicat, _signature); + } +} diff --git a/contracts/modules/delegates/SignatureVerifier.v8.sol b/contracts/modules/facets/SignatureVerifier.v8.sol similarity index 97% rename from contracts/modules/delegates/SignatureVerifier.v8.sol rename to contracts/modules/facets/SignatureVerifier.v8.sol index bf91b909b..71450dbb3 100644 --- a/contracts/modules/delegates/SignatureVerifier.v8.sol +++ b/contracts/modules/facets/SignatureVerifier.v8.sol @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2024 IEXEC BLOCKCHAIN TECH +// SPDX-FileCopyrightText: 2024-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; @@ -7,9 +7,9 @@ import {IERC1271} from "@openzeppelin/contracts-v5/interfaces/IERC1271.sol"; import {ECDSA} from "@openzeppelin/contracts-v5/utils/cryptography/ECDSA.sol"; import {MessageHashUtils} from "@openzeppelin/contracts-v5/utils/cryptography/MessageHashUtils.sol"; import {IERC734} from "../../external/interfaces/IERC734.sol"; -import {DelegateBase} from "../DelegateBase.v8.sol"; +import {FacetBase} from "../FacetBase.v8.sol"; -contract SignatureVerifier is DelegateBase { +contract SignatureVerifier is FacetBase { using ECDSA for bytes32; /** diff --git a/contracts/tools/testing/IexecEscrowTestContract.sol b/contracts/tools/testing/IexecEscrowTestContract.sol index 58098036f..34f59e25f 100644 --- a/contracts/tools/testing/IexecEscrowTestContract.sol +++ b/contracts/tools/testing/IexecEscrowTestContract.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; -import {IexecEscrow} from "../../modules/delegates/IexecEscrow.v8.sol"; +import {IexecEscrow} from "../../modules/facets/IexecEscrow.v8.sol"; /** * @notice a wrapper contract to make internal functions of diff --git a/contracts/tools/testing/IexecPocoBoostCompositeDelegate.sol b/contracts/tools/testing/IexecPocoBoostCompositeDelegate.sol deleted file mode 100644 index 4b465850d..000000000 --- a/contracts/tools/testing/IexecPocoBoostCompositeDelegate.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-FileCopyrightText: 2023 IEXEC BLOCKCHAIN TECH -// SPDX-License-Identifier: Apache-2.0 - -pragma solidity ^0.8.0; - -import {IexecPocoAccessorsDelegate} from "../../modules/delegates/IexecPocoAccessorsDelegate.sol"; -import {IexecPocoBoostAccessorsDelegate} from "../../modules/delegates/IexecPocoBoostAccessorsDelegate.sol"; -import {IexecPocoBoostDelegate} from "../../modules/delegates/IexecPocoBoostDelegate.sol"; - -/** - * @notice This contract is dedicated to unit testing. - */ -contract IexecPocoBoostCompositeDelegate is - IexecPocoAccessorsDelegate, - IexecPocoBoostAccessorsDelegate, - IexecPocoBoostDelegate -{} diff --git a/contracts/tools/testing/IexecPocoBoostCompositeFacet.sol b/contracts/tools/testing/IexecPocoBoostCompositeFacet.sol new file mode 100644 index 000000000..a675d74ac --- /dev/null +++ b/contracts/tools/testing/IexecPocoBoostCompositeFacet.sol @@ -0,0 +1,17 @@ +// SPDX-FileCopyrightText: 2023 IEXEC BLOCKCHAIN TECH +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import {IexecPocoAccessorsFacet} from "../../modules/facets/IexecPocoAccessorsFacet.sol"; +import {IexecPocoBoostAccessorsFacet} from "../../modules/facets/IexecPocoBoostAccessorsFacet.sol"; +import {IexecPocoBoostFacet} from "../../modules/facets/IexecPocoBoostFacet.sol"; + +/** + * @notice This contract is dedicated to unit testing. + */ +contract IexecPocoBoostCompositeFacet is + IexecPocoAccessorsFacet, + IexecPocoBoostAccessorsFacet, + IexecPocoBoostFacet +{} diff --git a/contracts/tools/testing/slither/Slither.sol b/contracts/tools/testing/slither/Slither.sol index 18f086949..b835e3574 100644 --- a/contracts/tools/testing/slither/Slither.sol +++ b/contracts/tools/testing/slither/Slither.sol @@ -3,9 +3,9 @@ pragma solidity ^0.8.0; -import {IexecPocoAccessorsDelegate} from "../../../modules/delegates/IexecPocoAccessorsDelegate.sol"; -import {IexecPoco1Delegate} from "../../../modules/delegates/IexecPoco1Delegate.sol"; -import {IexecPoco2Delegate} from "../../../modules/delegates/IexecPoco2Delegate.sol"; +import {IexecPocoAccessorsFacet} from "../../../modules/facets/IexecPocoAccessorsFacet.sol"; +import {IexecPoco1Facet} from "../../../modules/facets/IexecPoco1Facet.sol"; +import {IexecPoco2Facet} from "../../../modules/facets/IexecPoco2Facet.sol"; /** * @notice This contract is dedicated to slither analysis. @@ -14,5 +14,5 @@ import {IexecPoco2Delegate} from "../../../modules/delegates/IexecPoco2Delegate. * to facilitate static analysis using Slither. */ //slither-disable-start unused-state -contract Slither is IexecPocoAccessorsDelegate, IexecPoco1Delegate, IexecPoco2Delegate {} +contract Slither is IexecPocoAccessorsFacet, IexecPoco1Facet, IexecPoco2Facet {} //slither-disable-end unused-state diff --git a/contracts/tools/testing/slither/SlitherBoost.sol b/contracts/tools/testing/slither/SlitherBoost.sol index 94b466937..048945ad8 100644 --- a/contracts/tools/testing/slither/SlitherBoost.sol +++ b/contracts/tools/testing/slither/SlitherBoost.sol @@ -3,8 +3,8 @@ pragma solidity ^0.8.0; -import {IexecPocoBoostAccessorsDelegate} from "../../../modules/delegates/IexecPocoBoostAccessorsDelegate.sol"; -import {IexecPocoBoostDelegate} from "../../../modules/delegates/IexecPocoBoostDelegate.sol"; +import {IexecPocoBoostAccessorsFacet} from "../../../modules/facets/IexecPocoBoostAccessorsFacet.sol"; +import {IexecPocoBoostFacet} from "../../../modules/facets/IexecPocoBoostFacet.sol"; /** * @notice This contract is dedicated to slither analysis. @@ -13,5 +13,5 @@ import {IexecPocoBoostDelegate} from "../../../modules/delegates/IexecPocoBoostD * to facilitate static analysis using Slither. */ //slither-disable-start unused-state -contract SlitherBoost is IexecPocoBoostDelegate, IexecPocoBoostAccessorsDelegate {} +contract SlitherBoost is IexecPocoBoostFacet, IexecPocoBoostAccessorsFacet {} //slither-disable-end unused-state diff --git a/deploy/0_deploy.ts b/deploy/0_deploy.ts index be7583351..161232383 100644 --- a/deploy/0_deploy.ts +++ b/deploy/0_deploy.ts @@ -13,35 +13,35 @@ import { DiamondLoupeFacet, DiamondLoupeFacet__factory, Diamond__factory, - ENSIntegrationDelegate__factory, - IexecAccessorsABILegacyDelegate__factory, - IexecAccessorsDelegate__factory, + ENSIntegrationFacet__factory, + IexecAccessorsABILegacyFacet__factory, + IexecAccessorsFacet__factory, IexecAccessors__factory, - IexecCategoryManagerDelegate__factory, + IexecCategoryManagerFacet__factory, IexecCategoryManager__factory, - IexecERC20Delegate__factory, - IexecEscrowNativeDelegate__factory, - IexecEscrowTokenDelegate__factory, + IexecERC20Facet__factory, + IexecEscrowNativeFacet__factory, + IexecEscrowTokenFacet__factory, IexecLibOrders_v5__factory, - IexecMaintenanceDelegate__factory, - IexecMaintenanceExtraDelegate__factory, - IexecOrderManagementDelegate__factory, - IexecPoco1Delegate__factory, - IexecPoco2Delegate__factory, - IexecPocoAccessorsDelegate__factory, - IexecPocoBoostAccessorsDelegate__factory, - IexecPocoBoostDelegate__factory, - IexecRelayDelegate__factory, + IexecMaintenanceExtraFacet__factory, + IexecMaintenanceFacet__factory, + IexecOrderManagementFacet__factory, + IexecPoco1Facet__factory, + IexecPoco2Facet__factory, + IexecPocoAccessorsFacet__factory, + IexecPocoBoostAccessorsFacet__factory, + IexecPocoBoostFacet__factory, + IexecRelayFacet__factory, LibDiamond__factory, OwnershipFacet__factory, RLC__factory, WorkerpoolRegistry__factory, } from '../typechain'; +import { DiamondArgsStruct } from '../typechain/@mudgen/diamond-1/contracts/Diamond'; import { Ownable__factory } from '../typechain/factories/@openzeppelin/contracts/access'; import { FactoryDeployer } from '../utils/FactoryDeployer'; import config from '../utils/config'; import { getFunctionSelectors, linkContractToProxy } from '../utils/proxy-tools'; -import { DiamondArgsStruct } from '../typechain/@mudgen/diamond-1/contracts/Diamond'; let factoryDeployer: FactoryDeployer; @@ -71,12 +71,12 @@ export default async function deploy() { .catch(() => { throw new Error('Failed to prepare transferOwnership data'); }); - const erc1538ProxyAddress = await deployDiamondProxyWithDefaultFacets( + const diamondProxyAddress = await deployDiamondProxyWithDefaultFacets( owner.address, // transferOwnershipCall, //TODO ); - const erc1538 = DiamondCutFacet__factory.connect(erc1538ProxyAddress, owner); - console.log(`IexecInstance found at address: ${await erc1538.getAddress()}`); + const diamondProxy = DiamondCutFacet__factory.connect(diamondProxyAddress, owner); + console.log(`IexecInstance found at address: ${await diamondProxy.getAddress()}`); // Deploy library & modules const iexecLibOrdersAddress = await factoryDeployer.deployContract( new IexecLibOrders_v5__factory(), @@ -85,41 +85,39 @@ export default async function deploy() { ['contracts/libs/IexecLibOrders_v5.sol:IexecLibOrders_v5']: iexecLibOrdersAddress, }; const modules = [ - new IexecAccessorsDelegate__factory(), - new IexecAccessorsABILegacyDelegate__factory(), - new IexecCategoryManagerDelegate__factory(), - new IexecERC20Delegate__factory(), - isTokenMode - ? new IexecEscrowTokenDelegate__factory() - : new IexecEscrowNativeDelegate__factory(), - new IexecMaintenanceDelegate__factory(iexecLibOrders), - new IexecOrderManagementDelegate__factory(iexecLibOrders), - new IexecPoco1Delegate__factory(iexecLibOrders), - new IexecPoco2Delegate__factory(), - new IexecRelayDelegate__factory(), - new ENSIntegrationDelegate__factory(), - new IexecMaintenanceExtraDelegate__factory(), - new IexecPocoAccessorsDelegate__factory(iexecLibOrders), - new IexecPocoBoostDelegate__factory(iexecLibOrders), - new IexecPocoBoostAccessorsDelegate__factory(), + new IexecAccessorsFacet__factory(), + new IexecAccessorsABILegacyFacet__factory(), + new IexecCategoryManagerFacet__factory(), + new IexecERC20Facet__factory(), + isTokenMode ? new IexecEscrowTokenFacet__factory() : new IexecEscrowNativeFacet__factory(), + new IexecMaintenanceFacet__factory(iexecLibOrders), + new IexecOrderManagementFacet__factory(iexecLibOrders), + new IexecPoco1Facet__factory(iexecLibOrders), + new IexecPoco2Facet__factory(), + new IexecRelayFacet__factory(), + new ENSIntegrationFacet__factory(), + new IexecMaintenanceExtraFacet__factory(), + new IexecPocoAccessorsFacet__factory(iexecLibOrders), + new IexecPocoBoostFacet__factory(iexecLibOrders), + new IexecPocoBoostAccessorsFacet__factory(), ]; for (const module of modules) { const address = await factoryDeployer.deployContract(module); - await linkContractToProxy(erc1538, address, module); + await linkContractToProxy(diamondProxy, address, module); } - // Verify linking on ERC1538Proxy - const erc1538QueryInstance: DiamondLoupeFacet = DiamondLoupeFacet__factory.connect( - erc1538ProxyAddress, + // Verify linking on DiamondProxy + const diamondloupeFacetInstance: DiamondLoupeFacet = DiamondLoupeFacet__factory.connect( + diamondProxyAddress, owner, ); - const facets = await erc1538QueryInstance.facets(); + const facets = await diamondloupeFacetInstance.facets(); const functionCount = facets .map((facet) => facet.functionSelectors.length) .reduce((acc, curr) => acc + curr, 0); - console.log(`The deployed ERC1538Proxy now supports ${functionCount} functions:`); + console.log(`The deployed DiamondProxy now supports ${functionCount} functions:`); // TODO // for (let i = 0; i < Number(functionCount); i++) { - // const [method, , contract] = await erc1538QueryInstance.functionByIndex(i); + // const [method, , contract] = await diamondloupeFacetInstance.functionByIndex(i); // console.log(`[${i}] ${contract} ${method}`); // } /** @@ -176,11 +174,11 @@ export default async function deploy() { } // Set main configuration - const iexecAccessorsInstance = IexecAccessors__factory.connect(erc1538ProxyAddress, owner); + const iexecAccessorsInstance = IexecAccessors__factory.connect(diamondProxyAddress, owner); const iexecInitialized = (await iexecAccessorsInstance.eip712domain_separator()) != ZeroHash; if (!iexecInitialized) { // TODO replace this with DiamondInit.init(). - await IexecMaintenanceDelegate__factory.connect(erc1538ProxyAddress, owner) + await IexecMaintenanceFacet__factory.connect(diamondProxyAddress, owner) .configure( rlcInstanceAddress, 'Staked RLC', @@ -197,7 +195,7 @@ export default async function deploy() { const catCountBefore = await iexecAccessorsInstance.countCategory(); for (let i = Number(catCountBefore); i < config.categories.length; i++) { const category = config.categories[i]; - await IexecCategoryManager__factory.connect(erc1538ProxyAddress, owner) + await IexecCategoryManager__factory.connect(diamondProxyAddress, owner) .createCategory( category.name, JSON.stringify(category.description), diff --git a/deploy/1_deploy-ens.ts b/deploy/1_deploy-ens.ts index 4527fd95b..ff835e944 100644 --- a/deploy/1_deploy-ens.ts +++ b/deploy/1_deploy-ens.ts @@ -26,8 +26,8 @@ export default async function deployEns() { return; } const [owner] = await ethers.getSigners(); - const erc1538ProxyAddress = (await deployments.get('Diamond')).address; - const iexecAccessorsInstance = IexecAccessors__factory.connect(erc1538ProxyAddress, owner); + const diamondProxyAddress = (await deployments.get('Diamond')).address; + const iexecAccessorsInstance = IexecAccessors__factory.connect(diamondProxyAddress, owner); const appRegistryAddress = await iexecAccessorsInstance.appregistry(); const datasetRegistryAddress = await iexecAccessorsInstance.datasetregistry(); const workerpoolRegistryAddress = await iexecAccessorsInstance.workerpoolregistry(); @@ -61,12 +61,12 @@ export default async function deployEns() { await registerDomain('pools', 'iexec.eth'); await registerAddress('admin', 'iexec.eth', owner.address); await registerAddress('rlc', 'iexec.eth', await iexecAccessorsInstance.token()); - await registerAddress('core', 'v5.iexec.eth', erc1538ProxyAddress); + await registerAddress('core', 'v5.iexec.eth', diamondProxyAddress); await registerAddress('apps', 'v5.iexec.eth', appRegistryAddress); await registerAddress('datasets', 'v5.iexec.eth', datasetRegistryAddress); await registerAddress('workerpools', 'v5.iexec.eth', workerpoolRegistryAddress); await reverseRegistrar.setName('admin.iexec.eth').then((tx) => tx.wait()); - await setReverseName(erc1538ProxyAddress, 'core.v5.iexec.eth'); + await setReverseName(diamondProxyAddress, 'core.v5.iexec.eth'); await setReverseName(appRegistryAddress, 'apps.v5.iexec.eth'); await setReverseName(datasetRegistryAddress, 'datasets.v5.iexec.eth'); await setReverseName(workerpoolRegistryAddress, 'workerpools.v5.iexec.eth'); diff --git a/hardhat.config.ts b/hardhat.config.ts index 87f985742..7a6e3c2f0 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -277,10 +277,10 @@ const config: HardhatUserConfig = { templates: 'docs/solidity/templates', exclude: [ 'external', - 'modules/delegates/IexecAccessorsABILegacyDelegate.sol', // not relevant - 'modules/delegates/IexecEscrowTokenSwapDelegate.sol', // not relevant - 'modules/delegates/SignatureVerifier.sol', // contains only internal/private - 'modules/delegates/SignatureVerifier.v8.sol', + 'modules/facets/IexecAccessorsABILegacyFacet.sol', // not relevant + 'modules/facets/IexecEscrowTokenSwapFacet.sol', // not relevant + 'modules/facets/SignatureVerifier.sol', // contains only internal/private + 'modules/facets/SignatureVerifier.v8.sol', 'modules/interfaces', // interesting for events but too much doc duplication if enabled 'registries', // ignore them for now 'tools', diff --git a/scripts/set-callback-gas.ts b/scripts/set-callback-gas.ts index 2480c6941..c03d38e8b 100644 --- a/scripts/set-callback-gas.ts +++ b/scripts/set-callback-gas.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { deployments, ethers } from 'hardhat'; -import { IexecAccessors__factory, IexecMaintenanceDelegate__factory } from '../typechain'; +import { IexecAccessors__factory, IexecMaintenanceFacet__factory } from '../typechain'; (async () => { const requestedCallbackGas = Number(process.env.CALLBACK_GAS); @@ -12,13 +12,13 @@ import { IexecAccessors__factory, IexecMaintenanceDelegate__factory } from '../t } console.log(`Setting callback-gas to ${requestedCallbackGas.toLocaleString()} ..`); const [owner] = await ethers.getSigners(); - const erc1538ProxyAddress = (await deployments.get('ERC1538Proxy')).address; + const diamondProxyAddress = (await deployments.get('Diamond')).address; const viewCallbackGas = async () => - (await IexecAccessors__factory.connect(erc1538ProxyAddress, owner).callbackgas()) - .toNumber() - .toLocaleString(); + Number( + await IexecAccessors__factory.connect(diamondProxyAddress, owner).callbackgas(), + ).toLocaleString(); const callbackGasBefore = await viewCallbackGas(); - await IexecMaintenanceDelegate__factory.connect(erc1538ProxyAddress, owner) + await IexecMaintenanceFacet__factory.connect(diamondProxyAddress, owner) .setCallbackGas(requestedCallbackGas) .then((tx) => tx.wait()); console.log(`Changed callback-gas from ${callbackGasBefore} to ${await viewCallbackGas()}`); diff --git a/scripts/tools/update-config.ts b/scripts/tools/update-config.ts index 0b0094ce6..89de79e5c 100644 --- a/scripts/tools/update-config.ts +++ b/scripts/tools/update-config.ts @@ -13,15 +13,15 @@ async function main(): Promise { const chainId = network.chainId.toString(); console.log(`Working with network: ${networkName} (Chain ID: ${chainId})`); - const deployment = await deployments.get('ERC1538Proxy'); + const deployment = await deployments.get('Diamond'); const contractAddress = deployment.address; if (!contractAddress || contractAddress === 'null') { - console.error(`Failed to extract a valid ERC1538Proxy address from deployment file`); + console.error(`Failed to extract a valid DiamondProxy address from deployment file`); process.exit(1); } - console.log(`Found ERC1538Proxy address: ${contractAddress}`); + console.log(`Found DiamondProxy address: ${contractAddress}`); const localConfig = config; // Ensure the chain structure exists @@ -47,7 +47,7 @@ async function main(): Promise { localConfig.chains[chainId].v5 = {}; } - const contractKey = 'ERC1538Proxy'; + const contractKey = 'DiamondProxy'; const previousValue = localConfig.chains[chainId].v5[contractKey] || 'null'; localConfig.chains[chainId].v5[contractKey] = contractAddress; diff --git a/test/000_fullchain-boost.test.ts b/test/000_fullchain-boost.test.ts index 14fce3fcb..501eb6948 100644 --- a/test/000_fullchain-boost.test.ts +++ b/test/000_fullchain-boost.test.ts @@ -10,9 +10,9 @@ import { IexecAccessors, IexecAccessors__factory, IexecOrderManagement__factory, - IexecPocoBoostAccessorsDelegate__factory, - IexecPocoBoostDelegate, - IexecPocoBoostDelegate__factory, + IexecPocoBoostAccessorsFacet__factory, + IexecPocoBoostFacet, + IexecPocoBoostFacet__factory, TestClient__factory, WorkerpoolInterface__factory, } from '../typechain'; @@ -46,11 +46,11 @@ const appPrice = 1000n; const datasetPrice = 1_000_000n; const workerpoolPrice = 1_000_000_000n; -describe('IexecPocoBoostDelegate (IT)', function () { +describe('IexecPocoBoostFacet (IT)', function () { let domain: TypedDataDomain; let proxyAddress: string; let iexecInstance: IexecAccessors; - let iexecPocoBoostInstance: IexecPocoBoostDelegate; + let iexecPocoBoostInstance: IexecPocoBoostFacet; let iexecWrapper: IexecWrapper; let appAddress = ''; let workerpoolAddress = ''; @@ -72,7 +72,7 @@ describe('IexecPocoBoostDelegate (IT)', function () { let ordersAssets: OrdersAssets; let ordersPrices: OrdersPrices; - beforeEach('Deploy IexecPocoBoostDelegate', async () => { + beforeEach('Deploy IexecPocoBoostFacet', async () => { // We define a fixture to reuse the same setup in every test. // We use loadFixture to run this setup once, snapshot that state, // and reset Hardhat Network to that snapshot in every test. @@ -86,7 +86,7 @@ describe('IexecPocoBoostDelegate (IT)', function () { workerpoolOwner: scheduler, requester: requester, }; - iexecPocoBoostInstance = IexecPocoBoostDelegate__factory.connect(proxyAddress, owner); + iexecPocoBoostInstance = IexecPocoBoostFacet__factory.connect(proxyAddress, owner); iexecInstance = IexecAccessors__factory.connect(proxyAddress, anyone); domain = { name: 'iExecODB', @@ -773,7 +773,7 @@ describe('IexecPocoBoostDelegate (IT)', function () { }); async function viewDealBoost(dealId: string) { - return await IexecPocoBoostAccessorsDelegate__factory.connect( + return await IexecPocoBoostAccessorsFacet__factory.connect( proxyAddress, anyone, ).viewDealBoost(dealId); diff --git a/test/byContract/IexecPocoBoost/IexecPocoBoost.test.ts b/test/byContract/IexecPocoBoost/IexecPocoBoost.test.ts index 1e7a6fcde..bbfb6e763 100644 --- a/test/byContract/IexecPocoBoost/IexecPocoBoost.test.ts +++ b/test/byContract/IexecPocoBoost/IexecPocoBoost.test.ts @@ -21,9 +21,9 @@ import { IexecOrderManagement__factory, IexecPoco2__factory, IexecPocoAccessors__factory, - IexecPocoBoostAccessorsDelegate__factory, - IexecPocoBoostDelegate, - IexecPocoBoostDelegate__factory, + IexecPocoBoostAccessorsFacet__factory, + IexecPocoBoostFacet, + IexecPocoBoostFacet__factory, OwnableMock__factory, TestClient, TestClient__factory, @@ -72,7 +72,7 @@ const someSignature = '0xabcd'; // contract signatures could have arbitrary form const randomEOAAddress = ethers.Wallet.createRandom().address; let proxyAddress: string; -let iexecPocoBoostInstance: IexecPocoBoostDelegate; +let iexecPocoBoostInstance: IexecPocoBoostFacet; let iexecMaintenanceAsAdmin: IexecMaintenance; let iexecAccessor: IexecAccessors; let oracleConsumerInstance: TestClient; @@ -124,7 +124,7 @@ describe('IexecPocoBoost', function () { iexecWrapper = new IexecWrapper(proxyAddress, accounts); domain = iexecWrapper.getDomain(); ({ appAddress, datasetAddress, workerpoolAddress } = await iexecWrapper.createAssets()); - iexecPocoBoostInstance = IexecPocoBoostDelegate__factory.connect(proxyAddress, anyone); + iexecPocoBoostInstance = IexecPocoBoostFacet__factory.connect(proxyAddress, anyone); iexecMaintenanceAsAdmin = IexecMaintenance__factory.connect( proxyAddress, accounts.iexecAdmin, @@ -2442,7 +2442,7 @@ async function expectFrozen(account: string, expectedFrozenValue: bigint) { } async function viewDealBoost(dealId: string) { - return await IexecPocoBoostAccessorsDelegate__factory.connect( + return await IexecPocoBoostAccessorsFacet__factory.connect( proxyAddress, ethers.provider, ).viewDealBoost(dealId); diff --git a/test/utils/IexecWrapper.ts b/test/utils/IexecWrapper.ts index 537e531ed..63843cda5 100644 --- a/test/utils/IexecWrapper.ts +++ b/test/utils/IexecWrapper.ts @@ -21,7 +21,7 @@ import { IexecAccessors__factory, IexecInterfaceNative__factory, IexecLibOrders_v5, - IexecMaintenanceDelegate__factory, + IexecMaintenanceFacet__factory, IexecPoco2__factory, IexecPocoAccessors__factory, IexecPocoBoostAccessors__factory, @@ -33,6 +33,7 @@ import { } from '../../typechain'; import { TransferEvent } from '../../typechain/contracts/registries/IRegistry'; import { IexecPoco1__factory } from '../../typechain/factories/contracts/modules/interfaces/IexecPoco1.v8.sol/IexecPoco1__factory'; +import config from '../../utils/config'; import { IexecOrders, OrderOperation, @@ -50,7 +51,6 @@ import { getTaskId, setNextBlockTimestamp, } from '../../utils/poco-tools'; -import config from '../../utils/config'; export class IexecWrapper { proxyAddress: string; @@ -176,7 +176,7 @@ export class IexecWrapper { } async setTeeBroker(brokerAddress: string) { - await IexecMaintenanceDelegate__factory.connect(this.proxyAddress, this.accounts.iexecAdmin) + await IexecMaintenanceFacet__factory.connect(this.proxyAddress, this.accounts.iexecAdmin) .setTeeBroker(brokerAddress) .then((tx) => tx.wait()); } diff --git a/test/utils/fixture-helpers.ts b/test/utils/fixture-helpers.ts index 360ae4670..65d061593 100644 --- a/test/utils/fixture-helpers.ts +++ b/test/utils/fixture-helpers.ts @@ -50,9 +50,9 @@ export async function fundAccounts( * Transfers ownership of all contracts */ export async function transferAllOwnerships(chainConfig: any) { - if (chainConfig.v5.ERC1538Proxy) { - // Transfer proxy ownership from Timelock or current owner to a known EOA. - await transferProxyOwnership(chainConfig.v5.ERC1538Proxy); + if (chainConfig.v5.DiamondProxy) { + console.log('Transferring proxy ownership...'); + await transferProxyOwnership(chainConfig.v5.DiamondProxy); } const registries = [ { name: 'AppRegistry', address: (await deployments.get('AppRegistry')).address }, diff --git a/test/utils/hardhat-fixture-deployer.ts b/test/utils/hardhat-fixture-deployer.ts index fe1561c74..ece48681a 100644 --- a/test/utils/hardhat-fixture-deployer.ts +++ b/test/utils/hardhat-fixture-deployer.ts @@ -25,9 +25,9 @@ async function deployAll() { */ async function setUpLocalForkInNativeMode() { const chainId = (await ethers.provider.getNetwork()).chainId; - const proxyAddress = config.getChainConfig(chainId).v5.ERC1538Proxy; + const proxyAddress = config.getChainConfig(chainId).v5.DiamondProxy; if (!proxyAddress) { - throw new Error('ERC1538Proxy is required'); + throw new Error('DiamondProxy is required'); } await fundAccounts(proxyAddress, proxyAddress, true); await transferAllOwnerships(config.getChainConfig(chainId)); @@ -50,17 +50,17 @@ async function setUpLocalForkInTokenMode() { } await transferAllOwnerships(chainConfig); - const proxyAddress = chainConfig.v5.ERC1538Proxy; + const proxyAddress = chainConfig.v5.DiamondProxy; if (proxyAddress) { - console.log(`Using existing ERC1538Proxy at ${proxyAddress}`); + console.log(`Using existing DiamondProxy at ${proxyAddress}`); return proxyAddress; } else { - console.log('No existing ERC1538Proxy found, deploying new contracts'); + console.log('No existing DiamondProxy found, deploying new contracts'); // Deploy all contracts await deploy(); await deployEns(); - const newProxyAddress = (await deployments.get('ERC1538Proxy')).address; - console.log(`Deployed new ERC1538Proxy at ${newProxyAddress}`); + const newProxyAddress = (await deployments.get('Diamond')).address; + console.log(`Deployed new DiamondProxy at ${newProxyAddress}`); return newProxyAddress; } } diff --git a/utils/config.ts b/utils/config.ts index d7f7ffd68..9ea99955c 100644 --- a/utils/config.ts +++ b/utils/config.ts @@ -55,7 +55,8 @@ type ChainConfig = { AppRegistry?: string; DatasetRegistry?: string; WorkerpoolRegistry?: string; - ERC1538Proxy?: string; + ERC1538Proxy?: string; // Deprecated, use DiamondProxy instead + DiamondProxy?: string; IexecLibOrders_v5?: string; }; }; diff --git a/utils/proxy-tools.ts b/utils/proxy-tools.ts index a34e65d3b..54304d1ce 100644 --- a/utils/proxy-tools.ts +++ b/utils/proxy-tools.ts @@ -13,8 +13,8 @@ interface AbiParameter { } /** - * Link a contract to an ERC1538 proxy. - * @param proxy contract to ERC1538 proxy. + * Link a contract to a Diamond proxy. + * @param proxy contract to Diamond proxy. * @param contractAddress The contract address to link to the proxy. * @param contractFactory The contract factory to link to the proxy. */ From e03c6b317647fb8369628b664ff44d6ba57c81eb Mon Sep 17 00:00:00 2001 From: gfournieriExec Date: Fri, 25 Jul 2025 12:16:13 +0200 Subject: [PATCH 2/3] feat: rename ERC1538Proxy to DiamondProxy in configuration and scripts --- config/config.json | 2 +- scripts/boost/1_add-modules-to-proxy.ts | 14 ++--- scripts/sponsoring/1_add-modules-to-proxy.ts | 18 +++---- scripts/upgrades/upgrade-helper.ts | 57 ++++++++++++++------ 4 files changed, 59 insertions(+), 32 deletions(-) diff --git a/config/config.json b/config/config.json index e64922f1d..1be835750 100644 --- a/config/config.json +++ b/config/config.json @@ -175,7 +175,7 @@ "v5": { "factory": "0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed", "factoryType": "createx", - "ERC1538Proxy": "0x14B465079537655E1662F012e99EBa3863c8B9E0", + "DiamondProxy": "0x14B465079537655E1662F012e99EBa3863c8B9E0", "salt": "0x0000000000000000000000000000000000000000000000000000000000000000" } }, diff --git a/scripts/boost/1_add-modules-to-proxy.ts b/scripts/boost/1_add-modules-to-proxy.ts index 98b8a02ed..ff3734354 100644 --- a/scripts/boost/1_add-modules-to-proxy.ts +++ b/scripts/boost/1_add-modules-to-proxy.ts @@ -21,16 +21,16 @@ import { const chainId = (await ethers.provider.getNetwork()).chainId; const deploymentOptions = config.getChainConfig(chainId).v5; console.log('Link Boost functions to proxy:'); - if (!deploymentOptions.ERC1538Proxy) { - throw new Error('ERC1538Proxy is required'); + if (!deploymentOptions.DiamondProxy) { + throw new Error('DiamondProxy is required'); } - const erc1538ProxyAddress = deploymentOptions.ERC1538Proxy; + const diamondProxyAddress = deploymentOptions.DiamondProxy; const iexecPocoBoostDelegateAddress = (await deployments.get('IexecPocoBoostDelegate')).address; // Bellecour: 0x8425229f979AB3b0dDDe00D475D762cA4d6a5eFc const iexecPocoBoostAccessorsDelegateAddress = ( await deployments.get('IexecPocoBoostAccessorsDelegate') ).address; // Bellecour: 0x56185a2b0dc8b556BBfBAFB702BC971Ed75e868C const [account] = await ethers.getSigners(); - const timelockAddress = await Ownable__factory.connect(erc1538ProxyAddress, account).owner(); // Bellecour: 0x4611B943AA1d656Fc669623b5DA08756A7e288E9 + const timelockAddress = await Ownable__factory.connect(diamondProxyAddress, account).owner(); // Bellecour: 0x4611B943AA1d656Fc669623b5DA08756A7e288E9 const iexecPocoBoostProxyUpdate = encodeModuleProxyUpdate( IexecPocoBoost__factory.createInterface(), iexecPocoBoostDelegateAddress, @@ -43,7 +43,7 @@ import { const operationSalt = '0x0be814a62c44af32241a2c964e5680d1b25c783473c6e7875cbc8071770d7ff0'; // Random const delay = BigInt(60 * 60 * 24 * 7); const updateProxyArgs = [ - Array(2).fill(erc1538ProxyAddress), + Array(2).fill(diamondProxyAddress), Array(2).fill(0), [iexecPocoBoostProxyUpdate, iexecPocoBoostAccessorsProxyUpdate], ZeroHash, @@ -68,7 +68,7 @@ import { await time.increase(delay); console.log('Time traveling..'); await printBlockTime(); - await printFunctions(erc1538ProxyAddress); + await printFunctions(diamondProxyAddress); console.log('Executing proxy update..'); await timelockInstance .connect(timelockAdminSigner) @@ -77,5 +77,5 @@ import { console.log(tx); tx.wait(); }); - await printFunctions(erc1538ProxyAddress); + await printFunctions(diamondProxyAddress); })(); diff --git a/scripts/sponsoring/1_add-modules-to-proxy.ts b/scripts/sponsoring/1_add-modules-to-proxy.ts index 61d681e61..04f01a2cc 100644 --- a/scripts/sponsoring/1_add-modules-to-proxy.ts +++ b/scripts/sponsoring/1_add-modules-to-proxy.ts @@ -29,10 +29,10 @@ export async function addModulesToProxy() { const chainId = (await ethers.provider.getNetwork()).chainId; const deploymentOptions = config.getChainConfig(chainId).v5; console.log('Link functions to proxy:'); - if (!deploymentOptions.ERC1538Proxy) { - throw new Error('ERC1538Proxy is required'); + if (!deploymentOptions.DiamondProxy) { + throw new Error('DiamondProxy is required'); } - const erc1538ProxyAddress = deploymentOptions.ERC1538Proxy; + const diamondProxyAddress = deploymentOptions.DiamondProxy; const iexecOrderManagementAddress = (await hre.deployments.get('IexecOrderManagementDelegate')) .address; const iexecPoco1DelegateAddress = (await hre.deployments.get('IexecPoco1Delegate')).address; @@ -40,11 +40,11 @@ export async function addModulesToProxy() { const iexecPocoAccessorsDelegateAddress = ( await hre.deployments.get('IexecPocoAccessorsDelegate') ).address; - await printFunctions(erc1538ProxyAddress); + await printFunctions(diamondProxyAddress); console.log('Functions about to be added to proxy:'); const timelockAddress = await Ownable__factory.connect( - erc1538ProxyAddress, + diamondProxyAddress, ethers.provider, ).owner(); const iexecOrderManagementProxyUpdate = encodeModuleProxyUpdate( @@ -73,7 +73,7 @@ export async function addModulesToProxy() { iexecPocoAccessorsProxyUpdate, ]; const updateProxyArgs = [ - Array(updates.length).fill(erc1538ProxyAddress), + Array(updates.length).fill(diamondProxyAddress), Array(updates.length).fill(0), updates, ZeroHash, @@ -104,7 +104,7 @@ export async function addModulesToProxy() { console.log('Time traveling..'); await executeUpgrade(); - return erc1538ProxyAddress; + return diamondProxyAddress; async function scheduleUpgrade() { await timelockInstance @@ -118,7 +118,7 @@ export async function addModulesToProxy() { async function executeUpgrade() { await printBlockTime(); - await printFunctions(erc1538ProxyAddress); + await printFunctions(diamondProxyAddress); console.log('Executing proxy update..'); await timelockInstance .connect(timelockAdminSigner) @@ -127,6 +127,6 @@ export async function addModulesToProxy() { console.log(x); return x.wait(); }); - await printFunctions(erc1538ProxyAddress); + await printFunctions(diamondProxyAddress); } } diff --git a/scripts/upgrades/upgrade-helper.ts b/scripts/upgrades/upgrade-helper.ts index 57b628d26..eccd9d65e 100644 --- a/scripts/upgrades/upgrade-helper.ts +++ b/scripts/upgrades/upgrade-helper.ts @@ -1,20 +1,34 @@ // SPDX-FileCopyrightText: 2024-2025 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 -import { Interface } from 'ethers'; +import { Interface, ZeroAddress } from 'ethers'; import { ethers } from 'hardhat'; -import { ERC1538Query, ERC1538Query__factory, ERC1538Update__factory } from '../../typechain'; +import { FacetCutAction } from 'hardhat-deploy/dist/types'; +import { DiamondCutFacet__factory, DiamondLoupeFacet__factory } from '../../typechain'; function encodeModuleProxyUpdate(ModuleInterface: Interface, moduleAddress: string) { - let moduleFunctions = ''; + // Get function selectors from the interface + const functionSelectors: string[] = []; ModuleInterface.forEachFunction((functionFragment) => { const func = functionFragment.format(); console.log(`- ${func}`); - moduleFunctions += func + ';'; + const selector = ModuleInterface.getFunction(functionFragment.name)?.selector; + if (selector) { + functionSelectors.push(selector); + } }); - const moduleProxyUpdateData = ERC1538Update__factory.createInterface().encodeFunctionData( - 'updateContract', - [moduleAddress, moduleFunctions, ''], + + // Create FacetCut for adding the module + const facetCut = { + facetAddress: moduleAddress, + action: FacetCutAction.Add, + functionSelectors: functionSelectors, + }; + + // Encode diamondCut call + const moduleProxyUpdateData = DiamondCutFacet__factory.createInterface().encodeFunctionData( + 'diamondCut', + [[facetCut], ZeroAddress, '0x'], ); return moduleProxyUpdateData; } @@ -29,16 +43,29 @@ async function printBlockTime() { } } -async function printFunctions(erc1538ProxyAddress: string) { - const erc1538QueryInstance: ERC1538Query = ERC1538Query__factory.connect( - erc1538ProxyAddress, +async function printFunctions(diamondProxyAddress: string) { + const diamondLoupeInstance = DiamondLoupeFacet__factory.connect( + diamondProxyAddress, ethers.provider, ); - const functionCount = Number(await erc1538QueryInstance.totalFunctions()); - console.log(`ERC1538Proxy supports ${functionCount} functions:`); - for (let i = 0; i < functionCount; i++) { - const [method, , contract] = await erc1538QueryInstance.functionByIndex(i); - console.log(`[${i}] ${contract} ${method}`); + const facets = await diamondLoupeInstance.facets(); + + let totalFunctions = 0; + facets.forEach((facet) => { + totalFunctions += facet.functionSelectors.length; + }); + + console.log(`DiamondProxy supports ${totalFunctions} functions:`); + + let functionIndex = 0; + for (const facet of facets) { + for (const selector of facet.functionSelectors) { + // Try to decode the selector to a readable function signature + // Note: We can't easily get the full function signature from just the selector + // This is a limitation compared to ERC1538Query.functionByIndex + console.log(`[${functionIndex}] ${facet.facetAddress} ${selector}`); + functionIndex++; + } } } From 4da1c5674114f025583a40968118f64751ca31a3 Mon Sep 17 00:00:00 2001 From: gfournieriExec Date: Fri, 25 Jul 2025 12:31:03 +0200 Subject: [PATCH 3/3] fix: add TODO comment to remove deprecated ERC1538Proxy in ChainConfig --- utils/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/config.ts b/utils/config.ts index 9ea99955c..b20f12d51 100644 --- a/utils/config.ts +++ b/utils/config.ts @@ -55,7 +55,7 @@ type ChainConfig = { AppRegistry?: string; DatasetRegistry?: string; WorkerpoolRegistry?: string; - ERC1538Proxy?: string; // Deprecated, use DiamondProxy instead + ERC1538Proxy?: string; // Deprecated, use DiamondProxy instead TODO: to remove DiamondProxy?: string; IexecLibOrders_v5?: string; };