diff --git a/abis/contracts/facets/IexecERC20Facet.json b/abis/contracts/abstract/IexecERC20Base.json similarity index 100% rename from abis/contracts/facets/IexecERC20Facet.json rename to abis/contracts/abstract/IexecERC20Base.json diff --git a/abis/contracts/facets/IexecERC20Core.json b/abis/contracts/facets/IexecERC20Core.json deleted file mode 100644 index 0c2a6141..00000000 --- a/abis/contracts/facets/IexecERC20Core.json +++ /dev/null @@ -1,140 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Lock", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "ref", - "type": "bytes32" - } - ], - "name": "Reward", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "ref", - "type": "bytes32" - } - ], - "name": "Seize", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Unlock", - "type": "event" - } -] diff --git a/abis/contracts/facets/IexecEscrowNativeFacet.json b/abis/contracts/facets/IexecEscrowNativeFacet.json index 40a03475..9adab9a0 100644 --- a/abis/contracts/facets/IexecEscrowNativeFacet.json +++ b/abis/contracts/facets/IexecEscrowNativeFacet.json @@ -141,6 +141,83 @@ "stateMutability": "payable", "type": "fallback" }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "approveAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "deposit", @@ -197,6 +274,30 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "recover", @@ -210,6 +311,59 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { diff --git a/abis/contracts/facets/IexecEscrowTokenFacet.json b/abis/contracts/facets/IexecEscrowTokenFacet.json index 447db1c4..d3683911 100644 --- a/abis/contracts/facets/IexecEscrowTokenFacet.json +++ b/abis/contracts/facets/IexecEscrowTokenFacet.json @@ -141,6 +141,83 @@ "stateMutability": "payable", "type": "fallback" }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "extraData", + "type": "bytes" + } + ], + "name": "approveAndCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -208,6 +285,30 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -255,6 +356,59 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { diff --git a/abis/contracts/interfaces/IexecERC20Common.json b/abis/contracts/interfaces/IexecERC20Common.json deleted file mode 100644 index 0c2a6141..00000000 --- a/abis/contracts/interfaces/IexecERC20Common.json +++ /dev/null @@ -1,140 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Lock", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "ref", - "type": "bytes32" - } - ], - "name": "Reward", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "ref", - "type": "bytes32" - } - ], - "name": "Seize", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "Unlock", - "type": "event" - } -] diff --git a/abis/human-readable-abis/contracts/facets/IexecERC20Facet.sol/IexecERC20Facet.json b/abis/human-readable-abis/contracts/abstract/IexecERC20Base.sol/IexecERC20Base.json similarity index 100% rename from abis/human-readable-abis/contracts/facets/IexecERC20Facet.sol/IexecERC20Facet.json rename to abis/human-readable-abis/contracts/abstract/IexecERC20Base.sol/IexecERC20Base.json diff --git a/abis/human-readable-abis/contracts/facets/IexecERC20Core.sol/IexecERC20Core.json b/abis/human-readable-abis/contracts/facets/IexecERC20Core.sol/IexecERC20Core.json deleted file mode 100644 index ca70d06c..00000000 --- a/abis/human-readable-abis/contracts/facets/IexecERC20Core.sol/IexecERC20Core.json +++ /dev/null @@ -1,8 +0,0 @@ -[ - "event Approval(address indexed,address indexed,uint256)", - "event Lock(address,uint256)", - "event Reward(address,uint256,bytes32)", - "event Seize(address,uint256,bytes32)", - "event Transfer(address indexed,address indexed,uint256)", - "event Unlock(address,uint256)" -] diff --git a/abis/human-readable-abis/contracts/facets/IexecEscrowNativeFacet.sol/IexecEscrowNativeFacet.json b/abis/human-readable-abis/contracts/facets/IexecEscrowNativeFacet.sol/IexecEscrowNativeFacet.json index ea96861e..a2f7a9cd 100644 --- a/abis/human-readable-abis/contracts/facets/IexecEscrowNativeFacet.sol/IexecEscrowNativeFacet.json +++ b/abis/human-readable-abis/contracts/facets/IexecEscrowNativeFacet.sol/IexecEscrowNativeFacet.json @@ -5,10 +5,16 @@ "event Seize(address,uint256,bytes32)", "event Transfer(address indexed,address indexed,uint256)", "event Unlock(address,uint256)", + "function approve(address,uint256) returns (bool)", + "function approveAndCall(address,uint256,bytes) returns (bool)", + "function decreaseAllowance(address,uint256) returns (bool)", "function deposit() payable returns (bool)", "function depositFor(address) payable returns (bool)", "function depositForArray(uint256[],address[]) payable returns (bool)", + "function increaseAllowance(address,uint256) returns (bool)", "function recover() returns (uint256)", + "function transfer(address,uint256) returns (bool)", + "function transferFrom(address,address,uint256) returns (bool)", "function withdraw(uint256) returns (bool)", "function withdrawTo(uint256,address) returns (bool)" ] diff --git a/abis/human-readable-abis/contracts/facets/IexecEscrowTokenFacet.sol/IexecEscrowTokenFacet.json b/abis/human-readable-abis/contracts/facets/IexecEscrowTokenFacet.sol/IexecEscrowTokenFacet.json index 236d56a2..80d2d953 100644 --- a/abis/human-readable-abis/contracts/facets/IexecEscrowTokenFacet.sol/IexecEscrowTokenFacet.json +++ b/abis/human-readable-abis/contracts/facets/IexecEscrowTokenFacet.sol/IexecEscrowTokenFacet.json @@ -5,11 +5,17 @@ "event Seize(address,uint256,bytes32)", "event Transfer(address indexed,address indexed,uint256)", "event Unlock(address,uint256)", + "function approve(address,uint256) returns (bool)", + "function approveAndCall(address,uint256,bytes) returns (bool)", + "function decreaseAllowance(address,uint256) returns (bool)", "function deposit(uint256) returns (bool)", "function depositFor(uint256,address) returns (bool)", "function depositForArray(uint256[],address[]) returns (bool)", + "function increaseAllowance(address,uint256) returns (bool)", "function receiveApproval(address,uint256,address,bytes) returns (bool)", "function recover() returns (uint256)", + "function transfer(address,uint256) returns (bool)", + "function transferFrom(address,address,uint256) returns (bool)", "function withdraw(uint256) returns (bool)", "function withdrawTo(uint256,address) returns (bool)" ] diff --git a/abis/human-readable-abis/contracts/interfaces/IexecERC20Common.sol/IexecERC20Common.json b/abis/human-readable-abis/contracts/interfaces/IexecERC20Common.sol/IexecERC20Common.json deleted file mode 100644 index ca70d06c..00000000 --- a/abis/human-readable-abis/contracts/interfaces/IexecERC20Common.sol/IexecERC20Common.json +++ /dev/null @@ -1,8 +0,0 @@ -[ - "event Approval(address indexed,address indexed,uint256)", - "event Lock(address,uint256)", - "event Reward(address,uint256,bytes32)", - "event Seize(address,uint256,bytes32)", - "event Transfer(address indexed,address indexed,uint256)", - "event Unlock(address,uint256)" -] diff --git a/contracts/IexecInterfaceNative.sol b/contracts/IexecInterfaceNative.sol index 88c99f54..e02a9063 100644 --- a/contracts/IexecInterfaceNative.sol +++ b/contracts/IexecInterfaceNative.sol @@ -8,7 +8,6 @@ import {IexecCategoryManager} from "./interfaces/IexecCategoryManager.sol"; import {IexecConfiguration} from "./interfaces/IexecConfiguration.sol"; import {IexecConfigurationExtra} from "./interfaces/IexecConfigurationExtra.sol"; import {IexecERC20} from "./interfaces/IexecERC20.sol"; -import {IexecERC20Common} from "./interfaces/IexecERC20Common.sol"; import {IexecEscrowNative} from "./interfaces/IexecEscrowNative.sol"; import {IexecOrderManagement} from "./interfaces/IexecOrderManagement.sol"; import {IexecPoco1} from "./interfaces/IexecPoco1.sol"; @@ -32,7 +31,6 @@ interface IexecInterfaceNative is IexecCategoryManager, IexecConfiguration, IexecConfigurationExtra, - IexecERC20Common, IexecERC20, IexecEscrowNative, IexecOrderManagement, diff --git a/contracts/IexecInterfaceToken.sol b/contracts/IexecInterfaceToken.sol index 84897150..c5ae7109 100644 --- a/contracts/IexecInterfaceToken.sol +++ b/contracts/IexecInterfaceToken.sol @@ -8,7 +8,6 @@ import {IexecCategoryManager} from "./interfaces/IexecCategoryManager.sol"; import {IexecConfiguration} from "./interfaces/IexecConfiguration.sol"; import {IexecConfigurationExtra} from "./interfaces/IexecConfigurationExtra.sol"; import {IexecERC20} from "./interfaces/IexecERC20.sol"; -import {IexecERC20Common} from "./interfaces/IexecERC20Common.sol"; import {IexecEscrowToken} from "./interfaces/IexecEscrowToken.sol"; import {IexecOrderManagement} from "./interfaces/IexecOrderManagement.sol"; import {IexecPoco1} from "./interfaces/IexecPoco1.sol"; @@ -35,7 +34,6 @@ interface IexecInterfaceToken is IexecCategoryManager, IexecConfiguration, IexecConfigurationExtra, - IexecERC20Common, IexecERC20, IexecEscrowToken, IexecOrderManagement, diff --git a/contracts/facets/FacetBase.sol b/contracts/abstract/FacetBase.sol similarity index 100% rename from contracts/facets/FacetBase.sol rename to contracts/abstract/FacetBase.sol diff --git a/contracts/facets/IexecERC20Facet.sol b/contracts/abstract/IexecERC20Base.sol similarity index 51% rename from contracts/facets/IexecERC20Facet.sol rename to contracts/abstract/IexecERC20Base.sol index eeff38ab..61c1c9c5 100644 --- a/contracts/facets/IexecERC20Facet.sol +++ b/contracts/abstract/IexecERC20Base.sol @@ -3,13 +3,14 @@ pragma solidity ^0.8.0; -import {IexecERC20Core} from "./IexecERC20Core.sol"; import {FacetBase} from "./FacetBase.sol"; import {IexecERC20} from "../interfaces/IexecERC20.sol"; import {IexecTokenSpender} from "../interfaces/IexecTokenSpender.sol"; import {PocoStorageLib} from "../libs/PocoStorageLib.sol"; -contract IexecERC20Facet is IexecERC20, FacetBase, IexecERC20Core { +// TODO: Merge this abstract contract with IexecEscrowTokenFacet +// once IexecEscrowNativeFacet is deprecated and removed in a future major version. +abstract contract IexecERC20Base is IexecERC20, FacetBase { function transfer(address recipient, uint256 amount) external override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; @@ -78,4 +79,53 @@ contract IexecERC20Facet is IexecERC20, FacetBase, IexecERC20Core { _approve(_msgSender(), spender, currentAllowance - subtractedValue); return true; } + + function _transferUnchecked(address sender, address recipient, uint256 amount) internal { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + uint256 senderBalance = $.m_balances[sender]; + // TEMPORARY MIGRATION FIX: Check balance to prevent underflow and revert without reason for backward compatibility + // TODO: Remove this in the next major version + if (senderBalance < amount) { + revert(); + } + $.m_balances[sender] = senderBalance - amount; + $.m_balances[recipient] = $.m_balances[recipient] + amount; + emit Transfer(sender, recipient, amount); + } + + function _transfer(address sender, address recipient, uint256 amount) internal { + _transferUnchecked(sender, recipient, amount); + } + + function _mint(address account, uint256 amount) internal { + require(account != address(0), "ERC20: mint to the zero address"); + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + $.m_totalSupply = $.m_totalSupply + amount; + $.m_balances[account] = $.m_balances[account] + amount; + emit Transfer(address(0), account, amount); + } + + function _burn(address account, uint256 amount) internal { + require(account != address(0), "ERC20: burn from the zero address"); + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + uint256 accountBalance = $.m_balances[account]; + // TEMPORARY MIGRATION FIX: Check balance to prevent underflow and revert without reason for backward compatibility + // TODO: Remove this in the next major version + if (accountBalance < amount) { + revert(); + } + $.m_totalSupply = $.m_totalSupply - amount; + $.m_balances[account] = accountBalance - amount; + emit Transfer(account, address(0), amount); + } + + function _approve(address owner, address spender, uint256 amount) internal { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); + $.m_allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } } diff --git a/contracts/facets/IexecAccessorsABILegacyFacet.sol b/contracts/facets/IexecAccessorsABILegacyFacet.sol index ecd6807d..64c746bf 100644 --- a/contracts/facets/IexecAccessorsABILegacyFacet.sol +++ b/contracts/facets/IexecAccessorsABILegacyFacet.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; -import {FacetBase} from "./FacetBase.sol"; +import {FacetBase} from "../abstract/FacetBase.sol"; import {IexecAccessorsABILegacy} from "../interfaces/IexecAccessorsABILegacy.sol"; import {PocoStorageLib} from "../libs/PocoStorageLib.sol"; import {IexecLibCore_v5} from "../libs/IexecLibCore_v5.sol"; diff --git a/contracts/facets/IexecCategoryManagerFacet.sol b/contracts/facets/IexecCategoryManagerFacet.sol index a1053f22..0a4c9c21 100644 --- a/contracts/facets/IexecCategoryManagerFacet.sol +++ b/contracts/facets/IexecCategoryManagerFacet.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; -import {FacetBase} from "./FacetBase.sol"; +import {FacetBase} from "../abstract/FacetBase.sol"; import {PocoStorageLib} from "../libs/PocoStorageLib.sol"; import {IexecCategoryManager} from "../interfaces/IexecCategoryManager.sol"; import {IexecLibCore_v5} from "../libs/IexecLibCore_v5.sol"; diff --git a/contracts/facets/IexecConfigurationExtraFacet.sol b/contracts/facets/IexecConfigurationExtraFacet.sol index 97f24c22..bf7000a6 100644 --- a/contracts/facets/IexecConfigurationExtraFacet.sol +++ b/contracts/facets/IexecConfigurationExtraFacet.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; -import {FacetBase} from "./FacetBase.sol"; +import {FacetBase} from "../abstract/FacetBase.sol"; import {IexecConfigurationExtra} from "../interfaces/IexecConfigurationExtra.sol"; import {IRegistry} from "../registries/IRegistry.sol"; import {PocoStorageLib} from "../libs/PocoStorageLib.sol"; diff --git a/contracts/facets/IexecConfigurationFacet.sol b/contracts/facets/IexecConfigurationFacet.sol index 48bebb6a..c057656f 100644 --- a/contracts/facets/IexecConfigurationFacet.sol +++ b/contracts/facets/IexecConfigurationFacet.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; -import {FacetBase} from "./FacetBase.sol"; +import {FacetBase} from "../abstract/FacetBase.sol"; import {IexecConfiguration} from "../interfaces/IexecConfiguration.sol"; import {IexecHubV3Interface} from "../interfaces/IexecHubV3Interface.sol"; import {IRegistry} from "../registries/IRegistry.sol"; diff --git a/contracts/facets/IexecERC20Core.sol b/contracts/facets/IexecERC20Core.sol deleted file mode 100644 index 6f44d11b..00000000 --- a/contracts/facets/IexecERC20Core.sol +++ /dev/null @@ -1,59 +0,0 @@ -// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH -// SPDX-License-Identifier: Apache-2.0 - -pragma solidity ^0.8.0; - -import {PocoStorageLib} from "../libs/PocoStorageLib.sol"; -import {FacetBase} from "./FacetBase.sol"; -import {IexecERC20Common} from "../interfaces/IexecERC20Common.sol"; - -contract IexecERC20Core is IexecERC20Common, FacetBase { - function _transferUnchecked(address sender, address recipient, uint256 amount) internal { - require(sender != address(0), "ERC20: transfer from the zero address"); - require(recipient != address(0), "ERC20: transfer to the zero address"); - PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); - uint256 senderBalance = $.m_balances[sender]; - // TEMPORARY MIGRATION FIX: Check balance to prevent underflow and revert without reason for backward compatibility - // TODO: Remove this in the next major version - if (senderBalance < amount) { - revert(); - } - $.m_balances[sender] = senderBalance - amount; - $.m_balances[recipient] = $.m_balances[recipient] + amount; - emit Transfer(sender, recipient, amount); - } - - function _transfer(address sender, address recipient, uint256 amount) internal { - _transferUnchecked(sender, recipient, amount); - } - - function _mint(address account, uint256 amount) internal { - require(account != address(0), "ERC20: mint to the zero address"); - PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); - $.m_totalSupply = $.m_totalSupply + amount; - $.m_balances[account] = $.m_balances[account] + amount; - emit Transfer(address(0), account, amount); - } - - function _burn(address account, uint256 amount) internal { - require(account != address(0), "ERC20: burn from the zero address"); - PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); - uint256 accountBalance = $.m_balances[account]; - // TEMPORARY MIGRATION FIX: Check balance to prevent underflow and revert without reason for backward compatibility - // TODO: Remove this in the next major version - if (accountBalance < amount) { - revert(); - } - $.m_totalSupply = $.m_totalSupply - amount; - $.m_balances[account] = accountBalance - amount; - emit Transfer(account, address(0), amount); - } - - function _approve(address owner, address spender, uint256 amount) internal { - require(owner != address(0), "ERC20: approve from the zero address"); - require(spender != address(0), "ERC20: approve to the zero address"); - PocoStorageLib.PocoStorage storage $ = PocoStorageLib.getPocoStorage(); - $.m_allowances[owner][spender] = amount; - emit Approval(owner, spender, amount); - } -} diff --git a/contracts/facets/IexecEscrow.v8.sol b/contracts/facets/IexecEscrow.v8.sol index e0efc2b1..6850975e 100644 --- a/contracts/facets/IexecEscrow.v8.sol +++ b/contracts/facets/IexecEscrow.v8.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; import {PocoStorageLib} from "../libs/PocoStorageLib.sol"; -import {FacetBase} from "./FacetBase.sol"; +import {FacetBase} from "../abstract/FacetBase.sol"; /** * @title Manage (lock/unlock/reward/seize) user funds. diff --git a/contracts/facets/IexecEscrowNativeFacet.sol b/contracts/facets/IexecEscrowNativeFacet.sol index cf904f5b..1d8b2c1b 100644 --- a/contracts/facets/IexecEscrowNativeFacet.sol +++ b/contracts/facets/IexecEscrowNativeFacet.sol @@ -3,12 +3,11 @@ pragma solidity ^0.8.0; -import {IexecERC20Core} from "./IexecERC20Core.sol"; -import {FacetBase} from "./FacetBase.sol"; +import {IexecERC20Base} from "../abstract/IexecERC20Base.sol"; import {IexecEscrowNative} from "../interfaces/IexecEscrowNative.sol"; import {PocoStorageLib} from "../libs/PocoStorageLib.sol"; -contract IexecEscrowNativeFacet is IexecEscrowNative, FacetBase, IexecERC20Core { +contract IexecEscrowNativeFacet is IexecEscrowNative, IexecERC20Base { uint256 internal constant nRLCtoWei = 10 ** 9; /*************************************************************************** * Escrow methods: public * diff --git a/contracts/facets/IexecEscrowTokenFacet.sol b/contracts/facets/IexecEscrowTokenFacet.sol index f4e56cf1..3e801f29 100644 --- a/contracts/facets/IexecEscrowTokenFacet.sol +++ b/contracts/facets/IexecEscrowTokenFacet.sol @@ -3,15 +3,14 @@ pragma solidity ^0.8.0; -import {IexecERC20Core} from "./IexecERC20Core.sol"; -import {FacetBase} from "./FacetBase.sol"; +import {IexecERC20Base} from "../abstract/IexecERC20Base.sol"; import {IexecEscrowToken} from "../interfaces/IexecEscrowToken.sol"; import {IexecTokenSpender} from "../interfaces/IexecTokenSpender.sol"; import {IexecPoco1} from "../interfaces/IexecPoco1.sol"; import {IexecLibOrders_v5} from "../libs/IexecLibOrders_v5.sol"; import {PocoStorageLib} from "../libs/PocoStorageLib.sol"; -contract IexecEscrowTokenFacet is IexecEscrowToken, IexecTokenSpender, FacetBase, IexecERC20Core { +contract IexecEscrowTokenFacet is IexecEscrowToken, IexecTokenSpender, IexecERC20Base { /*************************************************************************** * Escrow methods: public * ***************************************************************************/ diff --git a/contracts/facets/IexecOrderManagementFacet.sol b/contracts/facets/IexecOrderManagementFacet.sol index 8c51eb7a..59bf704e 100644 --- a/contracts/facets/IexecOrderManagementFacet.sol +++ b/contracts/facets/IexecOrderManagementFacet.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import {IERC5313} from "@openzeppelin/contracts/interfaces/IERC5313.sol"; -import {FacetBase} from "./FacetBase.sol"; +import {FacetBase} from "../abstract/FacetBase.sol"; import {SignatureVerifier} from "./SignatureVerifier.sol"; import {IexecOrderManagement} from "../interfaces/IexecOrderManagement.sol"; import {PocoStorageLib} from "../libs/PocoStorageLib.sol"; diff --git a/contracts/facets/IexecPoco1Facet.sol b/contracts/facets/IexecPoco1Facet.sol index a06d6e17..d3091ed4 100644 --- a/contracts/facets/IexecPoco1Facet.sol +++ b/contracts/facets/IexecPoco1Facet.sol @@ -8,7 +8,7 @@ import {Math} from "@openzeppelin/contracts/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 {FacetBase} from "./FacetBase.sol"; +import {FacetBase} from "../abstract/FacetBase.sol"; import {PocoStorageLib} from "../libs/PocoStorageLib.sol"; import {IexecPoco1} from "../interfaces/IexecPoco1.sol"; import {IexecPoco1Errors} from "../interfaces/IexecPoco1Errors.sol"; diff --git a/contracts/facets/IexecPoco2Facet.sol b/contracts/facets/IexecPoco2Facet.sol index 48f47eb5..a9ad3439 100644 --- a/contracts/facets/IexecPoco2Facet.sol +++ b/contracts/facets/IexecPoco2Facet.sol @@ -8,7 +8,7 @@ import {PocoStorageLib} from "../libs/PocoStorageLib.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 {FacetBase} from "./FacetBase.sol"; +import {FacetBase} from "../abstract/FacetBase.sol"; import {IexecPoco2} from "../interfaces/IexecPoco2.sol"; import {IexecEscrow} from "./IexecEscrow.v8.sol"; import {SignatureVerifier} from "./SignatureVerifier.sol"; diff --git a/contracts/facets/IexecPocoAccessorsFacet.sol b/contracts/facets/IexecPocoAccessorsFacet.sol index b2859f2f..a6ea8e09 100644 --- a/contracts/facets/IexecPocoAccessorsFacet.sol +++ b/contracts/facets/IexecPocoAccessorsFacet.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import {PocoStorageLib} from "../libs/PocoStorageLib.sol"; -import {FacetBase} from "./FacetBase.sol"; +import {FacetBase} from "../abstract/FacetBase.sol"; import {IexecLibCore_v5} from "../libs/IexecLibCore_v5.sol"; import {IexecLibOrders_v5} from "../libs/IexecLibOrders_v5.sol"; import {IDataset} from "../registries/datasets/IDataset.v8.sol"; diff --git a/contracts/facets/IexecPocoBoostAccessorsFacet.sol b/contracts/facets/IexecPocoBoostAccessorsFacet.sol index 27ef29e0..37e5de7b 100644 --- a/contracts/facets/IexecPocoBoostAccessorsFacet.sol +++ b/contracts/facets/IexecPocoBoostAccessorsFacet.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import {IexecLibCore_v5} from "../libs/IexecLibCore_v5.sol"; -import {FacetBase} from "./FacetBase.sol"; +import {FacetBase} from "../abstract/FacetBase.sol"; import {IexecPocoBoostAccessors} from "../interfaces/IexecPocoBoostAccessors.sol"; import {PocoStorageLib} from "../libs/PocoStorageLib.sol"; diff --git a/contracts/facets/IexecPocoBoostFacet.sol b/contracts/facets/IexecPocoBoostFacet.sol index 3189c9ab..babd1758 100644 --- a/contracts/facets/IexecPocoBoostFacet.sol +++ b/contracts/facets/IexecPocoBoostFacet.sol @@ -13,7 +13,7 @@ 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 {FacetBase} from "./FacetBase.sol"; +import {FacetBase} from "../abstract/FacetBase.sol"; import {IexecPocoBoost} from "../interfaces/IexecPocoBoost.sol"; import {IexecEscrow} from "./IexecEscrow.v8.sol"; import {IexecPocoCommon} from "./IexecPocoCommon.sol"; diff --git a/contracts/facets/IexecPocoCommon.sol b/contracts/facets/IexecPocoCommon.sol index 0c408428..1a93cb2a 100644 --- a/contracts/facets/IexecPocoCommon.sol +++ b/contracts/facets/IexecPocoCommon.sol @@ -6,7 +6,7 @@ pragma solidity ^0.8.0; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import {PocoStorageLib} from "../libs/PocoStorageLib.sol"; import {IexecLibOrders_v5} from "../libs/IexecLibOrders_v5.sol"; -import {FacetBase} from "./FacetBase.sol"; +import {FacetBase} from "../abstract/FacetBase.sol"; contract IexecPocoCommon is FacetBase { using Math for uint256; diff --git a/contracts/facets/IexecRelayFacet.sol b/contracts/facets/IexecRelayFacet.sol index a5273dfc..0be5e25b 100644 --- a/contracts/facets/IexecRelayFacet.sol +++ b/contracts/facets/IexecRelayFacet.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; -import {FacetBase} from "./FacetBase.sol"; +import {FacetBase} from "../abstract/FacetBase.sol"; import {IexecRelay} from "../interfaces/IexecRelay.sol"; import {IexecLibOrders_v5} from "../libs/IexecLibOrders_v5.sol"; diff --git a/contracts/facets/SignatureVerifier.sol b/contracts/facets/SignatureVerifier.sol index 059ce4fa..3dbaf2ea 100644 --- a/contracts/facets/SignatureVerifier.sol +++ b/contracts/facets/SignatureVerifier.sol @@ -6,7 +6,7 @@ pragma solidity ^0.8.0; import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol"; import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; -import {FacetBase} from "./FacetBase.sol"; +import {FacetBase} from "../abstract/FacetBase.sol"; import {IERC734} from "../external/interfaces/IERC734.sol"; import {PocoStorageLib} from "../libs/PocoStorageLib.sol"; diff --git a/contracts/interfaces/IexecERC20.sol b/contracts/interfaces/IexecERC20.sol index aebff2ce..9344174d 100644 --- a/contracts/interfaces/IexecERC20.sol +++ b/contracts/interfaces/IexecERC20.sol @@ -3,9 +3,16 @@ pragma solidity ^0.8.0; -import {IexecERC20Common} from "./IexecERC20Common.sol"; +interface IexecERC20 { + // ERC20 standard events + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval(address indexed owner, address indexed spender, uint256 value); + // iExec specific events + event Reward(address owner, uint256 amount, bytes32 ref); + event Seize(address owner, uint256 amount, bytes32 ref); + event Lock(address owner, uint256 amount); + event Unlock(address owner, uint256 amount); -interface IexecERC20 is IexecERC20Common { function transfer(address, uint256) external returns (bool); function approve(address, uint256) external returns (bool); function transferFrom(address, address, uint256) external returns (bool); diff --git a/contracts/interfaces/IexecERC20Common.sol b/contracts/interfaces/IexecERC20Common.sol deleted file mode 100644 index b17c7558..00000000 --- a/contracts/interfaces/IexecERC20Common.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-FileCopyrightText: 2020-2025 IEXEC BLOCKCHAIN TECH -// SPDX-License-Identifier: Apache-2.0 - -pragma solidity ^0.8.0; -// TODO merge with IexecERC20 interface. -interface IexecERC20Common { - event Transfer(address indexed from, address indexed to, uint256 value); - event Approval(address indexed owner, address indexed spender, uint256 value); - event Reward(address owner, uint256 amount, bytes32 ref); - event Seize(address owner, uint256 amount, bytes32 ref); - event Lock(address owner, uint256 amount); - event Unlock(address owner, uint256 amount); -} diff --git a/deploy/0_deploy.ts b/deploy/0_deploy.ts index f4b50759..6553b4f4 100644 --- a/deploy/0_deploy.ts +++ b/deploy/0_deploy.ts @@ -19,7 +19,6 @@ import { IexecCategoryManager__factory, IexecConfigurationExtraFacet__factory, IexecConfigurationFacet__factory, - IexecERC20Facet__factory, IexecEscrowNativeFacet__factory, IexecEscrowTokenFacet__factory, IexecLibOrders_v5__factory, @@ -100,7 +99,6 @@ export default async function deploy() { new IexecCategoryManagerFacet__factory(), new IexecConfigurationExtraFacet__factory(), new IexecConfigurationFacet__factory(iexecLibOrders), - new IexecERC20Facet__factory(), isTokenMode ? new IexecEscrowTokenFacet__factory() : new IexecEscrowNativeFacet__factory(), new IexecOrderManagementFacet__factory(iexecLibOrders), new IexecPoco1Facet__factory(iexecLibOrders), diff --git a/docs/solidity/index.md b/docs/solidity/index.md index 8490aa84..b10c3933 100644 --- a/docs/solidity/index.md +++ b/docs/solidity/index.md @@ -16,100 +16,102 @@ the PoCo contracts in token mode. _Referenced in the SDK with the current path `contracts/IexecInterfaceToken.sol`. Changing the name or the path would cause a breaking change in the SDK._ -## IexecCategoryManagerFacet +## FacetBase -### createCategory +_Every facet must inherit from this contract._ -```solidity -function createCategory(string name, string description, uint256 workClockTimeRef) external returns (uint256) -``` +## IexecERC20Base -Methods +### transfer -## IexecConfigurationExtraFacet +```solidity +function transfer(address recipient, uint256 amount) external returns (bool) +``` -### changeRegistries +### approve ```solidity -function changeRegistries(address _appregistryAddress, address _datasetregistryAddress, address _workerpoolregistryAddress) external +function approve(address spender, uint256 value) external returns (bool) ``` -## IexecConfigurationFacet - -### configure +### approveAndCall ```solidity -function configure(address _token, string _name, string _symbol, uint8 _decimal, address _appregistryAddress, address _datasetregistryAddress, address _workerpoolregistryAddress, address _v3_iexecHubAddress) external +function approveAndCall(address spender, uint256 value, bytes extraData) external returns (bool) ``` -### domain +### transferFrom ```solidity -function domain() external view returns (struct IexecLibOrders_v5.EIP712Domain) +function transferFrom(address sender, address recipient, uint256 amount) external returns (bool) ``` -### updateDomainSeparator +### increaseAllowance ```solidity -function updateDomainSeparator() external +function increaseAllowance(address spender, uint256 addedValue) external returns (bool) ``` -### importScore +### decreaseAllowance ```solidity -function importScore(address _worker) external +function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool) ``` -### setTeeBroker +## IexecCategoryManagerFacet + +### createCategory ```solidity -function setTeeBroker(address _teebroker) external +function createCategory(string name, string description, uint256 workClockTimeRef) external returns (uint256) ``` -### setCallbackGas +Methods + +## IexecConfigurationExtraFacet + +### changeRegistries ```solidity -function setCallbackGas(uint256 _callbackgas) external +function changeRegistries(address _appregistryAddress, address _datasetregistryAddress, address _workerpoolregistryAddress) external ``` -## IexecERC20Core - -## IexecERC20Facet +## IexecConfigurationFacet -### transfer +### configure ```solidity -function transfer(address recipient, uint256 amount) external returns (bool) +function configure(address _token, string _name, string _symbol, uint8 _decimal, address _appregistryAddress, address _datasetregistryAddress, address _workerpoolregistryAddress, address _v3_iexecHubAddress) external ``` -### approve +### domain ```solidity -function approve(address spender, uint256 value) external returns (bool) +function domain() external view returns (struct IexecLibOrders_v5.EIP712Domain) ``` -### approveAndCall +### updateDomainSeparator ```solidity -function approveAndCall(address spender, uint256 value, bytes extraData) external returns (bool) +function updateDomainSeparator() external ``` -### transferFrom +### importScore ```solidity -function transferFrom(address sender, address recipient, uint256 amount) external returns (bool) +function importScore(address _worker) external ``` -### increaseAllowance +### setTeeBroker ```solidity -function increaseAllowance(address spender, uint256 addedValue) external returns (bool) +function setTeeBroker(address _teebroker) external ``` -### decreaseAllowance +### setCallbackGas ```solidity -function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool) +function setCallbackGas(uint256 _callbackgas) external ``` ## IexecEscrow diff --git a/scripts/upgrades/v6.2.0.ts b/scripts/upgrades/v6.2.0.ts new file mode 100644 index 00000000..194b0cb0 --- /dev/null +++ b/scripts/upgrades/v6.2.0.ts @@ -0,0 +1,3 @@ +// NOTE: The IexecERC20Facet__factory has been removed. +// Remember to manually remove the corresponding facet - contract address is: +// 0xB0152eC6f48E64a92B66D4736aFA1b02d8D45169 diff --git a/utils/proxy-tools.ts b/utils/proxy-tools.ts index b678d452..de4f1036 100644 --- a/utils/proxy-tools.ts +++ b/utils/proxy-tools.ts @@ -15,7 +15,6 @@ import { IexecCategoryManagerFacet__factory, IexecConfigurationExtraFacet__factory, IexecConfigurationFacet__factory, - IexecERC20Facet__factory, IexecEscrowNativeFacet__factory, IexecEscrowTokenFacet__factory, IexecOrderManagementFacet__factory, @@ -141,7 +140,6 @@ function getAllLocalFacetFunctions(): Map { IexecCategoryManagerFacet__factory.createInterface(), IexecConfigurationExtraFacet__factory.createInterface(), IexecConfigurationFacet__factory.createInterface(), - IexecERC20Facet__factory.createInterface(), IexecEscrowNativeFacet__factory.createInterface(), IexecEscrowTokenFacet__factory.createInterface(), IexecOrderManagementFacet__factory.createInterface(),