From 37c7a5216f8903629c20cfa4bdfa0203541c12a9 Mon Sep 17 00:00:00 2001 From: Gonzalo Othacehe Date: Thu, 10 Jul 2025 16:53:03 -0300 Subject: [PATCH 01/18] up rules --- scripts/solhint-custom/index.js | 64 +++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/scripts/solhint-custom/index.js b/scripts/solhint-custom/index.js index 9625027eefe..28d5ebf4fef 100644 --- a/scripts/solhint-custom/index.js +++ b/scripts/solhint-custom/index.js @@ -23,11 +23,11 @@ class Base { module.exports = [ class extends Base { - static ruleId = 'interface-names'; + static ruleId = 'interface-only-external-functions'; - ContractDefinition(node) { - if (node.kind === 'interface' && !/^I[A-Z]/.test(node.name)) { - this.error(node, 'Interface names should have a capital I prefix'); + FunctionDefinition(node) { + if (node.parent.kind === 'interface' && node.visibility !== 'external') { + this.error(node, 'Interface functions must be external'); } } }, @@ -47,20 +47,36 @@ module.exports = [ static ruleId = 'leading-underscore'; VariableDeclaration(node) { - if (node.isDeclaredConst) { - // TODO: expand visibility and fix - if (node.visibility === 'private' && /^_/.test(node.name)) { - this.error(node, 'Constant variables should not have leading underscore'); + if (node.isDeclaredConst || node.isImmutable) { + if (/^_/.test(node.name)) { + this.error(node, 'Constant and immutable variables should not have leading underscore'); + } + } + else { + if (node.isStateVar) { + if (node.visibility === 'private' || node.visibility === 'internal') { + if (!/^_/.test(node.name)) { + this.error(node, 'Private and internal state variables must have leading underscore'); + } + } + else { + if (/^_/.test(node.name)) { + this.error(node, 'Public state variables should not have leading underscore'); + } + } } - } else if (node.visibility === 'private' && !/^_/.test(node.name)) { - this.error(node, 'Non-constant private variables must have leading underscore'); } } FunctionDefinition(node) { - if (node.visibility === 'private' || (node.visibility === 'internal' && node.parent.kind !== 'library')) { + if (node.visibility === 'private') { if (!/^_/.test(node.name)) { - this.error(node, 'Private and internal functions must have leading underscore'); + this.error(node, 'Private functions must have leading underscore'); + } + } + if (node.visibility === 'internal' && node.parent.kind !== 'library') { + if (!/^_/.test(node.name)) { + this.error(node, 'Non-library internal functions must have leading underscore'); } } if (node.visibility === 'internal' && node.parent.kind === 'library') { @@ -68,17 +84,21 @@ module.exports = [ this.error(node, 'Library internal functions should not have leading underscore'); } } + if (node.visibility === 'public' || node.visibility === 'external') { + if (/^_/.test(node.name)) { + this.error(node, 'Public and external functions should not have leading underscore'); + } + } } }, - // TODO: re-enable and fix - // class extends Base { - // static ruleId = 'no-external-virtual'; - // - // FunctionDefinition(node) { - // if (node.visibility == 'external' && node.isVirtual) { - // this.error(node, 'Functions should not be external and virtual'); - // } - // } - // }, + class extends Base { + static ruleId = 'no-external-virtual'; + + FunctionDefinition(node) { + if (node.visibility == 'external' && node.isVirtual) { + this.error(node, 'Functions should not be external and virtual'); + } + } + }, ]; From 6e13ca783a60367f7d23b93b719a548b96586c41 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 10 Jul 2025 23:38:29 +0200 Subject: [PATCH 02/18] Update index.js --- scripts/solhint-custom/index.js | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/scripts/solhint-custom/index.js b/scripts/solhint-custom/index.js index 28d5ebf4fef..7f6cb5d5b9a 100644 --- a/scripts/solhint-custom/index.js +++ b/scripts/solhint-custom/index.js @@ -47,23 +47,19 @@ module.exports = [ static ruleId = 'leading-underscore'; VariableDeclaration(node) { - if (node.isDeclaredConst || node.isImmutable) { - if (/^_/.test(node.name)) { - this.error(node, 'Constant and immutable variables should not have leading underscore'); - } + if (node.isDeclaredConst || node.isImmutable) { + if (/^_/.test(node.name)) { + this.error(node, 'Constant and immutable variables should not have leading underscore'); } - else { - if (node.isStateVar) { - if (node.visibility === 'private' || node.visibility === 'internal') { - if (!/^_/.test(node.name)) { - this.error(node, 'Private and internal state variables must have leading underscore'); - } - } - else { - if (/^_/.test(node.name)) { - this.error(node, 'Public state variables should not have leading underscore'); - } - } + } else if (node.isStateVar) { + if (node.visibility === 'private' || node.visibility === 'internal') { + if (!/^_/.test(node.name)) { + this.error(node, 'Private and internal state variables must have leading underscore'); + } + } else { + if (/^_/.test(node.name)) { + this.error(node, 'Public state variables should not have leading underscore'); + } } } } From 56b120f607f79a30afa37091e83edf527f724fe3 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 10 Jul 2025 23:40:26 +0200 Subject: [PATCH 03/18] Update index.js --- scripts/solhint-custom/index.js | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/scripts/solhint-custom/index.js b/scripts/solhint-custom/index.js index 7f6cb5d5b9a..03a33779e8e 100644 --- a/scripts/solhint-custom/index.js +++ b/scripts/solhint-custom/index.js @@ -65,25 +65,17 @@ module.exports = [ } FunctionDefinition(node) { - if (node.visibility === 'private') { - if (!/^_/.test(node.name)) { - this.error(node, 'Private functions must have leading underscore'); - } + if (node.visibility === 'private' && !/^_/.test(node.name)) { + this.error(node, 'Private functions must have leading underscore'); } - if (node.visibility === 'internal' && node.parent.kind !== 'library') { - if (!/^_/.test(node.name)) { - this.error(node, 'Non-library internal functions must have leading underscore'); - } + if (node.visibility === 'internal' && node.parent.kind !== 'library' && !/^_/.test(node.name)) { + this.error(node, 'Non-library internal functions must have leading underscore'); } - if (node.visibility === 'internal' && node.parent.kind === 'library') { - if (/^_/.test(node.name)) { - this.error(node, 'Library internal functions should not have leading underscore'); - } + if (node.visibility === 'internal' && node.parent.kind === 'library' && /^_/.test(node.name)) { + this.error(node, 'Library internal functions should not have leading underscore'); } - if (node.visibility === 'public' || node.visibility === 'external') { - if (/^_/.test(node.name)) { - this.error(node, 'Public and external functions should not have leading underscore'); - } + if (node.visibility === 'public' || node.visibility === 'external' && /^_/.test(node.name)) { + this.error(node, 'Public and external functions should not have leading underscore'); } } }, From ba351f3211ed3d990aa1c822426966c41d13c7bd Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 10 Jul 2025 23:41:44 +0200 Subject: [PATCH 04/18] Update index.js --- scripts/solhint-custom/index.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/solhint-custom/index.js b/scripts/solhint-custom/index.js index 03a33779e8e..a586790aadd 100644 --- a/scripts/solhint-custom/index.js +++ b/scripts/solhint-custom/index.js @@ -74,8 +74,11 @@ module.exports = [ if (node.visibility === 'internal' && node.parent.kind === 'library' && /^_/.test(node.name)) { this.error(node, 'Library internal functions should not have leading underscore'); } - if (node.visibility === 'public' || node.visibility === 'external' && /^_/.test(node.name)) { - this.error(node, 'Public and external functions should not have leading underscore'); + if (node.visibility === 'public' && /^_/.test(node.name)) { + this.error(node, 'Public functions should not have leading underscore'); + } + if (node.visibility === 'external' && /^_/.test(node.name)) { + this.error(node, 'External functions should not have leading underscore'); } } }, From bee7bc3b497857e2a182b379900c8b396b8d80bc Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Wed, 16 Jul 2025 22:31:26 +0200 Subject: [PATCH 05/18] Update index.js --- scripts/solhint-custom/index.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/solhint-custom/index.js b/scripts/solhint-custom/index.js index a586790aadd..6718ab7b858 100644 --- a/scripts/solhint-custom/index.js +++ b/scripts/solhint-custom/index.js @@ -52,14 +52,14 @@ module.exports = [ this.error(node, 'Constant and immutable variables should not have leading underscore'); } } else if (node.isStateVar) { - if (node.visibility === 'private' || node.visibility === 'internal') { - if (!/^_/.test(node.name)) { - this.error(node, 'Private and internal state variables must have leading underscore'); - } - } else { - if (/^_/.test(node.name)) { - this.error(node, 'Public state variables should not have leading underscore'); - } + if (node.visibility === 'private' && !/^_/.test(node.name)) + this.error(node, 'Private state variables must have leading underscore'); + } + if (node.visibility === 'internal' && !/^_/.test(node.name)) { + this.error(node, 'Internal state variables must have leading underscore'); + } + if (node.visibility === 'public' && /^_/.test(node.name)) { + this.error(node, 'Public state variables should not have leading underscore'); } } } From f859dd7933f7a1e6fc18ac6c7c129e24ef2497b2 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Wed, 16 Jul 2025 22:33:10 +0200 Subject: [PATCH 06/18] Update index.js --- scripts/solhint-custom/index.js | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/scripts/solhint-custom/index.js b/scripts/solhint-custom/index.js index 6718ab7b858..060ee81d6a3 100644 --- a/scripts/solhint-custom/index.js +++ b/scripts/solhint-custom/index.js @@ -47,20 +47,20 @@ module.exports = [ static ruleId = 'leading-underscore'; VariableDeclaration(node) { - if (node.isDeclaredConst || node.isImmutable) { - if (/^_/.test(node.name)) { - this.error(node, 'Constant and immutable variables should not have leading underscore'); - } - } else if (node.isStateVar) { - if (node.visibility === 'private' && !/^_/.test(node.name)) - this.error(node, 'Private state variables must have leading underscore'); - } - if (node.visibility === 'internal' && !/^_/.test(node.name)) { - this.error(node, 'Internal state variables must have leading underscore'); - } - if (node.visibility === 'public' && /^_/.test(node.name)) { - this.error(node, 'Public state variables should not have leading underscore'); - } + if (node.isDeclaredConst && /^_/.test(node.name)) { + this.error(node, 'Constant variables should not have leading underscore'); + } + if (node.isImmutable && /^_/.test(node.name)) { + this.error(node, 'Immutable variables should not have leading underscore'); + } + if (node.isStateVar && node.visibility === 'private' && !/^_/.test(node.name)) { + this.error(node, 'Private state variables must have leading underscore'); + } + if (node.isStateVar && node.visibility === 'internal' && !/^_/.test(node.name)) { + this.error(node, 'Internal state variables must have leading underscore'); + } + if (node.isStateVar && node.visibility === 'public' && /^_/.test(node.name)) { + this.error(node, 'Public state variables should not have leading underscore'); } } From d807d85c14ea35ac533bfc46d5453d65c9ee9d79 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Wed, 16 Jul 2025 22:36:28 +0200 Subject: [PATCH 07/18] Update index.js --- scripts/solhint-custom/index.js | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/scripts/solhint-custom/index.js b/scripts/solhint-custom/index.js index 060ee81d6a3..5fe96ee1b3b 100644 --- a/scripts/solhint-custom/index.js +++ b/scripts/solhint-custom/index.js @@ -36,8 +36,7 @@ module.exports = [ static ruleId = 'private-variables'; VariableDeclaration(node) { - const constantOrImmutable = node.isDeclaredConst || node.isImmutable; - if (node.isStateVar && !constantOrImmutable && node.visibility !== 'private') { + if (node.isStateVar && !node.isDeclaredConst && !node.isImmutable && node.visibility !== 'private') { this.error(node, 'State variables must be private'); } } @@ -47,37 +46,37 @@ module.exports = [ static ruleId = 'leading-underscore'; VariableDeclaration(node) { - if (node.isDeclaredConst && /^_/.test(node.name)) { + if (node.isDeclaredConst && node.name.startsWith('_')) { this.error(node, 'Constant variables should not have leading underscore'); } - if (node.isImmutable && /^_/.test(node.name)) { + if (node.isImmutable && node.name.startsWith('_')) { this.error(node, 'Immutable variables should not have leading underscore'); } - if (node.isStateVar && node.visibility === 'private' && !/^_/.test(node.name)) { + if (node.isStateVar && node.visibility === 'private' && !node.name.startsWith('_')) { this.error(node, 'Private state variables must have leading underscore'); } - if (node.isStateVar && node.visibility === 'internal' && !/^_/.test(node.name)) { + if (node.isStateVar && node.visibility === 'internal' && !node.name.startsWith('_')) { this.error(node, 'Internal state variables must have leading underscore'); } - if (node.isStateVar && node.visibility === 'public' && /^_/.test(node.name)) { + if (node.isStateVar && node.visibility === 'public' && node.name.startsWith('_')) { this.error(node, 'Public state variables should not have leading underscore'); } } FunctionDefinition(node) { - if (node.visibility === 'private' && !/^_/.test(node.name)) { + if (node.visibility === 'private' && !node.name.startsWith('_')) { this.error(node, 'Private functions must have leading underscore'); } - if (node.visibility === 'internal' && node.parent.kind !== 'library' && !/^_/.test(node.name)) { + if (node.visibility === 'internal' && node.parent.kind !== 'library' && !node.name.startsWith('_')) { this.error(node, 'Non-library internal functions must have leading underscore'); } - if (node.visibility === 'internal' && node.parent.kind === 'library' && /^_/.test(node.name)) { + if (node.visibility === 'internal' && node.parent.kind === 'library' && node.name.startsWith('_')) { this.error(node, 'Library internal functions should not have leading underscore'); } - if (node.visibility === 'public' && /^_/.test(node.name)) { + if (node.visibility === 'public' && node.name.startsWith('_')) { this.error(node, 'Public functions should not have leading underscore'); } - if (node.visibility === 'external' && /^_/.test(node.name)) { + if (node.visibility === 'external' && node.name.startsWith('_')) { this.error(node, 'External functions should not have leading underscore'); } } From add0ff0fbd91a087855f5ff1d84cf11b21faf6e1 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 17 Jul 2025 21:37:05 +0200 Subject: [PATCH 08/18] fix lint --- scripts/solhint-custom/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/solhint-custom/index.js b/scripts/solhint-custom/index.js index 5fe96ee1b3b..cfd6dc994a1 100644 --- a/scripts/solhint-custom/index.js +++ b/scripts/solhint-custom/index.js @@ -84,7 +84,7 @@ module.exports = [ class extends Base { static ruleId = 'no-external-virtual'; - + FunctionDefinition(node) { if (node.visibility == 'external' && node.isVirtual) { this.error(node, 'Functions should not be external and virtual'); From 101f119aa4e6a6c4258c09a9f78653ea41d0e21b Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 24 Jul 2025 16:08:52 +0200 Subject: [PATCH 09/18] improve --- scripts/solhint-custom/index.js | 87 +++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 36 deletions(-) diff --git a/scripts/solhint-custom/index.js b/scripts/solhint-custom/index.js index cfd6dc994a1..39b99be5086 100644 --- a/scripts/solhint-custom/index.js +++ b/scripts/solhint-custom/index.js @@ -14,8 +14,8 @@ class Base { } } - error(node, message) { - if (!this.ignored) { + require(condition, node, message) { + if (!condition && !this.ignored) { this.reporter.error(node, this.ruleId, message); } } @@ -26,8 +26,8 @@ module.exports = [ static ruleId = 'interface-only-external-functions'; FunctionDefinition(node) { - if (node.parent.kind === 'interface' && node.visibility !== 'external') { - this.error(node, 'Interface functions must be external'); + if (node.parent.kind === 'interface') { + this.require(node.visibility === 'external', node, 'Interface functions must be external'); } } }, @@ -36,8 +36,12 @@ module.exports = [ static ruleId = 'private-variables'; VariableDeclaration(node) { - if (node.isStateVar && !node.isDeclaredConst && !node.isImmutable && node.visibility !== 'private') { - this.error(node, 'State variables must be private'); + if (node.isStateVar) { + this.require( + node.isDeclaredConst || node.isImmutable || node.visibility === 'private', + node, + 'State variables must be private', + ); } } }, @@ -46,38 +50,45 @@ module.exports = [ static ruleId = 'leading-underscore'; VariableDeclaration(node) { - if (node.isDeclaredConst && node.name.startsWith('_')) { - this.error(node, 'Constant variables should not have leading underscore'); - } - if (node.isImmutable && node.name.startsWith('_')) { - this.error(node, 'Immutable variables should not have leading underscore'); - } - if (node.isStateVar && node.visibility === 'private' && !node.name.startsWith('_')) { - this.error(node, 'Private state variables must have leading underscore'); - } - if (node.isStateVar && node.visibility === 'internal' && !node.name.startsWith('_')) { - this.error(node, 'Internal state variables must have leading underscore'); - } - if (node.isStateVar && node.visibility === 'public' && node.name.startsWith('_')) { - this.error(node, 'Public state variables should not have leading underscore'); + if (node.isDeclaredConst) { + this.require(!node.name.startsWith('_'), node, 'Constant variables should not have leading underscore'); + } else if (node.isImmutable) { + this.require(!node.name.startsWith('_'), node, 'Immutable variables should not have leading underscore'); + } else if (node.isStateVar) { + switch (node.visibility) { + case 'private': + this.require(node.name.startsWith('_'), node, 'Private state variables must have leading underscore'); + break; + case 'internal': + this.require(node.name.startsWith('_'), node, 'Internal state variables must have leading underscore'); + break; + case 'public': + this.require(!node.name.startsWith('_'), node, 'Public state variables should not have leading underscore'); + break; + } } } FunctionDefinition(node) { - if (node.visibility === 'private' && !node.name.startsWith('_')) { - this.error(node, 'Private functions must have leading underscore'); - } - if (node.visibility === 'internal' && node.parent.kind !== 'library' && !node.name.startsWith('_')) { - this.error(node, 'Non-library internal functions must have leading underscore'); - } - if (node.visibility === 'internal' && node.parent.kind === 'library' && node.name.startsWith('_')) { - this.error(node, 'Library internal functions should not have leading underscore'); - } - if (node.visibility === 'public' && node.name.startsWith('_')) { - this.error(node, 'Public functions should not have leading underscore'); - } - if (node.visibility === 'external' && node.name.startsWith('_')) { - this.error(node, 'External functions should not have leading underscore'); + switch (node.visibility) { + case 'external': + this.require(!node.name.startsWith('_'), node, 'External functions should not have leading underscore'); + break; + case 'public': + this.require(!node.name.startsWith('_'), node, 'Public functions should not have leading underscore'); + break; + case 'internal': + this.require( + node.name.startsWith('_') !== (node.parent.kind === 'library'), + node, + node.parent.kind === 'library' + ? 'Library internal functions should not have leading underscore' + : 'Non-library internal functions must have leading underscore', + ); + break; + case 'private': + this.require(node.name.startsWith('_'), node, 'Private functions must have leading underscore'); + break; } } }, @@ -86,8 +97,12 @@ module.exports = [ static ruleId = 'no-external-virtual'; FunctionDefinition(node) { - if (node.visibility == 'external' && node.isVirtual) { - this.error(node, 'Functions should not be external and virtual'); + if (node.visibility == 'external') { + this.require( + node.isReceiveEther || node.isFallback || !node.isVirtual, + node, + 'Functions should not be external and virtual', + ); } } }, From ca766d7a161ddabdeaa07eda67d1aa57657d7eab Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 24 Jul 2025 16:18:47 +0200 Subject: [PATCH 10/18] fix code to match new rules --- contracts/governance/Governor.sol | 2 +- contracts/governance/TimelockController.sol | 8 ++++---- .../governance/extensions/GovernorTimelockCompound.sol | 4 ++-- .../governance/extensions/GovernorTimelockControl.sol | 2 +- .../governance/extensions/GovernorVotesQuorumFraction.sol | 2 +- contracts/metatx/ERC2771Forwarder.sol | 4 ++-- contracts/mocks/proxy/UUPSUpgradeableMock.sol | 2 +- contracts/proxy/utils/UUPSUpgradeable.sol | 2 +- contracts/token/ERC20/extensions/ERC20Permit.sol | 2 +- contracts/utils/Base64.sol | 8 ++++---- contracts/utils/Multicall.sol | 2 +- scripts/solhint-custom/index.js | 7 +++++-- test/metatx/ERC2771Forwarder.t.sol | 2 +- 13 files changed, 25 insertions(+), 22 deletions(-) diff --git a/contracts/governance/Governor.sol b/contracts/governance/Governor.sol index 5a7b1617041..c80a82f5b0b 100644 --- a/contracts/governance/Governor.sol +++ b/contracts/governance/Governor.sol @@ -653,7 +653,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 * in a governance proposal to recover tokens or Ether that was sent to the governor contract by mistake. * Note that if the executor is simply the governor itself, use of `relay` is redundant. */ - function relay(address target, uint256 value, bytes calldata data) external payable virtual onlyGovernance { + function relay(address target, uint256 value, bytes calldata data) public payable virtual onlyGovernance { (bool success, bytes memory returndata) = target.call{value: value}(data); Address.verifyCallResult(success, returndata); } diff --git a/contracts/governance/TimelockController.sol b/contracts/governance/TimelockController.sol index e608d393d98..93996cc9735 100644 --- a/contracts/governance/TimelockController.sol +++ b/contracts/governance/TimelockController.sol @@ -26,7 +26,7 @@ contract TimelockController is AccessControl, ERC721Holder, ERC1155Holder { bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE"); bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE"); bytes32 public constant CANCELLER_ROLE = keccak256("CANCELLER_ROLE"); - uint256 internal constant _DONE_TIMESTAMP = uint256(1); + uint256 internal constant DONE_TIMESTAMP = uint256(1); mapping(bytes32 id => uint256) private _timestamps; uint256 private _minDelay; @@ -207,7 +207,7 @@ contract TimelockController is AccessControl, ERC721Holder, ERC1155Holder { uint256 timestamp = getTimestamp(id); if (timestamp == 0) { return OperationState.Unset; - } else if (timestamp == _DONE_TIMESTAMP) { + } else if (timestamp == DONE_TIMESTAMP) { return OperationState.Done; } else if (timestamp > block.timestamp) { return OperationState.Waiting; @@ -432,7 +432,7 @@ contract TimelockController is AccessControl, ERC721Holder, ERC1155Holder { if (!isOperationReady(id)) { revert TimelockUnexpectedOperationState(id, _encodeStateBitmap(OperationState.Ready)); } - _timestamps[id] = _DONE_TIMESTAMP; + _timestamps[id] = DONE_TIMESTAMP; } /** @@ -445,7 +445,7 @@ contract TimelockController is AccessControl, ERC721Holder, ERC1155Holder { * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing * an operation where the timelock is the target and the data is the ABI-encoded call to this function. */ - function updateDelay(uint256 newDelay) external virtual { + function updateDelay(uint256 newDelay) public virtual { address sender = _msgSender(); if (sender != address(this)) { revert TimelockUnauthorizedCaller(sender); diff --git a/contracts/governance/extensions/GovernorTimelockCompound.sol b/contracts/governance/extensions/GovernorTimelockCompound.sol index ea705a76e43..e8572e219b6 100644 --- a/contracts/governance/extensions/GovernorTimelockCompound.sol +++ b/contracts/governance/extensions/GovernorTimelockCompound.sol @@ -136,7 +136,7 @@ abstract contract GovernorTimelockCompound is Governor { /** * @dev Accept admin right over the timelock. */ - // solhint-disable-next-line private-vars-leading-underscore + // solhint-disable-next-line openzeppelin/leading-underscore function __acceptAdmin() public { _timelock.acceptAdmin(); } @@ -154,7 +154,7 @@ abstract contract GovernorTimelockCompound is Governor { * CAUTION: It is not recommended to change the timelock while there are other queued governance proposals. */ - function updateTimelock(ICompoundTimelock newTimelock) external virtual onlyGovernance { + function updateTimelock(ICompoundTimelock newTimelock) public virtual onlyGovernance { _updateTimelock(newTimelock); } diff --git a/contracts/governance/extensions/GovernorTimelockControl.sol b/contracts/governance/extensions/GovernorTimelockControl.sol index 6aab59c9470..ff963adffaa 100644 --- a/contracts/governance/extensions/GovernorTimelockControl.sol +++ b/contracts/governance/extensions/GovernorTimelockControl.sol @@ -146,7 +146,7 @@ abstract contract GovernorTimelockControl is Governor { * * CAUTION: It is not recommended to change the timelock while there are other queued governance proposals. */ - function updateTimelock(TimelockController newTimelock) external virtual onlyGovernance { + function updateTimelock(TimelockController newTimelock) public virtual onlyGovernance { _updateTimelock(newTimelock); } diff --git a/contracts/governance/extensions/GovernorVotesQuorumFraction.sol b/contracts/governance/extensions/GovernorVotesQuorumFraction.sol index 5abd7c129b0..c225fe85fa9 100644 --- a/contracts/governance/extensions/GovernorVotesQuorumFraction.sol +++ b/contracts/governance/extensions/GovernorVotesQuorumFraction.sol @@ -73,7 +73,7 @@ abstract contract GovernorVotesQuorumFraction is GovernorVotes { * - Must be called through a governance proposal. * - New numerator must be smaller or equal to the denominator. */ - function updateQuorumNumerator(uint256 newQuorumNumerator) external virtual onlyGovernance { + function updateQuorumNumerator(uint256 newQuorumNumerator) public virtual onlyGovernance { _updateQuorumNumerator(newQuorumNumerator); } diff --git a/contracts/metatx/ERC2771Forwarder.sol b/contracts/metatx/ERC2771Forwarder.sol index a463e70e019..b1448acf084 100644 --- a/contracts/metatx/ERC2771Forwarder.sol +++ b/contracts/metatx/ERC2771Forwarder.sol @@ -61,7 +61,7 @@ contract ERC2771Forwarder is EIP712, Nonces { bytes signature; } - bytes32 internal constant _FORWARD_REQUEST_TYPEHASH = + bytes32 internal constant FORWARD_REQUEST_TYPEHASH = keccak256( "ForwardRequest(address from,address to,uint256 value,uint256 gas,uint256 nonce,uint48 deadline,bytes data)" ); @@ -222,7 +222,7 @@ contract ERC2771Forwarder is EIP712, Nonces { (address recovered, ECDSA.RecoverError err, ) = _hashTypedDataV4( keccak256( abi.encode( - _FORWARD_REQUEST_TYPEHASH, + FORWARD_REQUEST_TYPEHASH, request.from, request.to, request.value, diff --git a/contracts/mocks/proxy/UUPSUpgradeableMock.sol b/contracts/mocks/proxy/UUPSUpgradeableMock.sol index 8c5641e6ca3..b5e8f506ce4 100644 --- a/contracts/mocks/proxy/UUPSUpgradeableMock.sol +++ b/contracts/mocks/proxy/UUPSUpgradeableMock.sol @@ -29,7 +29,7 @@ contract UUPSUpgradeableUnsafeMock is UUPSUpgradeableMock { } contract UUPSUnsupportedProxiableUUID is UUPSUpgradeableMock { - function proxiableUUID() external pure override returns (bytes32) { + function proxiableUUID() public pure override returns (bytes32) { return keccak256("invalid UUID"); } } diff --git a/contracts/proxy/utils/UUPSUpgradeable.sol b/contracts/proxy/utils/UUPSUpgradeable.sol index d0f58427f9b..7717637fd1b 100644 --- a/contracts/proxy/utils/UUPSUpgradeable.sol +++ b/contracts/proxy/utils/UUPSUpgradeable.sol @@ -69,7 +69,7 @@ abstract contract UUPSUpgradeable is IERC1822Proxiable { * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ - function proxiableUUID() external view virtual notDelegated returns (bytes32) { + function proxiableUUID() public view virtual notDelegated returns (bytes32) { return ERC1967Utils.IMPLEMENTATION_SLOT; } diff --git a/contracts/token/ERC20/extensions/ERC20Permit.sol b/contracts/token/ERC20/extensions/ERC20Permit.sol index d593191966a..fc213415112 100644 --- a/contracts/token/ERC20/extensions/ERC20Permit.sol +++ b/contracts/token/ERC20/extensions/ERC20Permit.sol @@ -71,7 +71,7 @@ abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712, Nonces { /// @inheritdoc IERC20Permit // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view virtual returns (bytes32) { + function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return _domainSeparatorV4(); } } diff --git a/contracts/utils/Base64.sol b/contracts/utils/Base64.sol index c6ee6a524aa..4f3e493859e 100644 --- a/contracts/utils/Base64.sol +++ b/contracts/utils/Base64.sol @@ -11,14 +11,14 @@ library Base64 { * @dev Base64 Encoding/Decoding Table * See sections 4 and 5 of https://datatracker.ietf.org/doc/html/rfc4648 */ - string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - string internal constant _TABLE_URL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + string internal constant TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + string internal constant TABLE_URL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; /** * @dev Converts a `bytes` to its Bytes64 `string` representation. */ function encode(bytes memory data) internal pure returns (string memory) { - return _encode(data, _TABLE, true); + return _encode(data, TABLE, true); } /** @@ -26,7 +26,7 @@ library Base64 { * Output is not padded with `=` as specified in https://www.rfc-editor.org/rfc/rfc4648[rfc4648]. */ function encodeURL(bytes memory data) internal pure returns (string memory) { - return _encode(data, _TABLE_URL, false); + return _encode(data, TABLE_URL, false); } /** diff --git a/contracts/utils/Multicall.sol b/contracts/utils/Multicall.sol index 94222feb0f4..c986c3c7cde 100644 --- a/contracts/utils/Multicall.sol +++ b/contracts/utils/Multicall.sol @@ -23,7 +23,7 @@ abstract contract Multicall is Context { * @dev Receives and executes a batch of function calls on this contract. * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ - function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) { + function multicall(bytes[] calldata data) public virtual returns (bytes[] memory results) { bytes memory context = msg.sender == _msgSender() ? new bytes(0) : msg.data[msg.data.length - _contextSuffixLength():]; diff --git a/scripts/solhint-custom/index.js b/scripts/solhint-custom/index.js index 39b99be5086..8a86f9aa320 100644 --- a/scripts/solhint-custom/index.js +++ b/scripts/solhint-custom/index.js @@ -50,10 +50,13 @@ module.exports = [ static ruleId = 'leading-underscore'; VariableDeclaration(node) { + // TODO: do we want that rule ? Should no immutable variable have a prefix regardless of visibility ? + // + // else if (node.isImmutable) { + // this.require(!node.name.startsWith('_'), node, 'Immutable variables should not have leading underscore'); + // } if (node.isDeclaredConst) { this.require(!node.name.startsWith('_'), node, 'Constant variables should not have leading underscore'); - } else if (node.isImmutable) { - this.require(!node.name.startsWith('_'), node, 'Immutable variables should not have leading underscore'); } else if (node.isStateVar) { switch (node.visibility) { case 'private': diff --git a/test/metatx/ERC2771Forwarder.t.sol b/test/metatx/ERC2771Forwarder.t.sol index 605ae62097e..224367377ff 100644 --- a/test/metatx/ERC2771Forwarder.t.sol +++ b/test/metatx/ERC2771Forwarder.t.sol @@ -27,7 +27,7 @@ contract ERC2771ForwarderMock is ERC2771Forwarder { _hashTypedDataV4( keccak256( abi.encode( - _FORWARD_REQUEST_TYPEHASH, + FORWARD_REQUEST_TYPEHASH, request.from, request.to, request.value, From 1525a7b15af7398aa7cd8acc3a8a1cc822747830 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Fri, 19 Sep 2025 16:52:50 +0200 Subject: [PATCH 11/18] Remove interface-only-external-functions that is already enforced by the compiler --- scripts/solhint-custom/index.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/scripts/solhint-custom/index.js b/scripts/solhint-custom/index.js index 8a86f9aa320..3a0e01bfa40 100644 --- a/scripts/solhint-custom/index.js +++ b/scripts/solhint-custom/index.js @@ -22,16 +22,6 @@ class Base { } module.exports = [ - class extends Base { - static ruleId = 'interface-only-external-functions'; - - FunctionDefinition(node) { - if (node.parent.kind === 'interface') { - this.require(node.visibility === 'external', node, 'Interface functions must be external'); - } - } - }, - class extends Base { static ruleId = 'private-variables'; From 34e6f7d2c61efe6a8ba878b5b1187ef3afbd9635 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Fri, 19 Sep 2025 17:04:42 +0200 Subject: [PATCH 12/18] Update scripts/solhint-custom/index.js --- scripts/solhint-custom/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/solhint-custom/index.js b/scripts/solhint-custom/index.js index 3a0e01bfa40..b18c13b4405 100644 --- a/scripts/solhint-custom/index.js +++ b/scripts/solhint-custom/index.js @@ -90,9 +90,9 @@ module.exports = [ static ruleId = 'no-external-virtual'; FunctionDefinition(node) { - if (node.visibility == 'external') { + if (node.visibility == 'external' && node.isVirtual) { this.require( - node.isReceiveEther || node.isFallback || !node.isVirtual, + node.isReceiveEther || node.isFallback, node, 'Functions should not be external and virtual', ); From 1c5046b5d0e5253889397ade4cc42e0aac5a53fa Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Fri, 19 Sep 2025 17:07:32 +0200 Subject: [PATCH 13/18] js lint --- scripts/solhint-custom/index.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/scripts/solhint-custom/index.js b/scripts/solhint-custom/index.js index b18c13b4405..8191388accc 100644 --- a/scripts/solhint-custom/index.js +++ b/scripts/solhint-custom/index.js @@ -91,11 +91,7 @@ module.exports = [ FunctionDefinition(node) { if (node.visibility == 'external' && node.isVirtual) { - this.require( - node.isReceiveEther || node.isFallback, - node, - 'Functions should not be external and virtual', - ); + this.require(node.isReceiveEther || node.isFallback, node, 'Functions should not be external and virtual'); } } }, From 01d53b16c8c8f50eea92eb1ed0e4499c4280291a Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Fri, 19 Sep 2025 17:40:12 +0200 Subject: [PATCH 14/18] add no-public-library rule --- scripts/solhint-custom/index.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/scripts/solhint-custom/index.js b/scripts/solhint-custom/index.js index 8191388accc..0306c98ef01 100644 --- a/scripts/solhint-custom/index.js +++ b/scripts/solhint-custom/index.js @@ -95,4 +95,18 @@ module.exports = [ } } }, + + class extends Base { + static ruleId = 'no-public-library'; + + FunctionDefinition(node) { + if (node.parent.kind === 'library') { + this.require( + node.visibility === 'internal' || node.visibility === 'private', + node, + 'Library functions should not be internal or private', + ); + } + } + }, ]; From 00550a7df76cfd4db17074627152e32fbabf412a Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Fri, 19 Sep 2025 17:40:50 +0200 Subject: [PATCH 15/18] update solhint --- package-lock.json | 56 +++++++---------------------------------------- package.json | 2 +- 2 files changed, 9 insertions(+), 49 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8e6df71f0d1..ac6c165a06b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,7 +43,7 @@ "prettier-plugin-solidity": "^2.0.0", "rimraf": "^6.0.0", "semver": "^7.3.5", - "solhint": "^6.0.0", + "solhint": "^6.0.1", "solhint-plugin-openzeppelin": "file:scripts/solhint-custom", "solidity-ast": "^0.4.50", "solidity-coverage": "^0.8.14", @@ -9408,13 +9408,13 @@ } }, "node_modules/solhint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/solhint/-/solhint-6.0.0.tgz", - "integrity": "sha512-PQGfwFqfeYdebi2tEG1fhVfMjqSzbW3Noz+LYf8UusKe5nkikCghdgEjYQPcGfFZj4snlVyJQt//AaxkubOtVQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/solhint/-/solhint-6.0.1.tgz", + "integrity": "sha512-Lew5nhmkXqHPybzBzkMzvvWkpOJSSLTkfTZwRriWvfR2naS4YW2PsjVGaoX9tZFmHh7SuS+e2GEGo5FPYYmJ8g==", "dev": true, "license": "MIT", "dependencies": { - "@solidity-parser/parser": "^0.20.0", + "@solidity-parser/parser": "^0.20.2", "ajv": "^6.12.6", "ajv-errors": "^1.0.1", "antlr4": "^4.13.1-patch-1", @@ -9424,7 +9424,6 @@ "commander": "^10.0.0", "cosmiconfig": "^8.0.0", "fast-diff": "^1.2.0", - "fs-extra": "^11.1.0", "glob": "^8.0.3", "ignore": "^5.2.4", "js-yaml": "^4.1.0", @@ -9432,7 +9431,6 @@ "lodash": "^4.17.21", "pluralize": "^8.0.0", "semver": "^7.5.2", - "strip-ansi": "^6.0.1", "table": "^6.8.1", "text-table": "^0.2.0" }, @@ -9448,9 +9446,9 @@ "link": true }, "node_modules/solhint/node_modules/@solidity-parser/parser": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.20.1.tgz", - "integrity": "sha512-58I2sRpzaQUN+jJmWbHfbWf9AKfzqCI8JAdFB0vbyY+u8tBRcuTt9LxzasvR0LGQpcRv97eyV7l61FQ3Ib7zVw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.20.2.tgz", + "integrity": "sha512-rbu0bzwNvMcwAjH86hiEAcOeRI2EeK8zCkHDrFykh/Al8mvJeFmjy3UrE7GYQjNwOgbGUUtCn5/k8CB8zIu7QA==", "dev": true, "license": "MIT" }, @@ -9505,21 +9503,6 @@ "node": ">=14" } }, - "node_modules/solhint/node_modules/fs-extra": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", - "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, "node_modules/solhint/node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", @@ -9561,19 +9544,6 @@ "dev": true, "license": "MIT" }, - "node_modules/solhint/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/solhint/node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", @@ -9604,16 +9574,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/solhint/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/solidity-ast": { "version": "0.4.60", "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.60.tgz", diff --git a/package.json b/package.json index f6960972ad5..c01775bd963 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "prettier-plugin-solidity": "^2.0.0", "rimraf": "^6.0.0", "semver": "^7.3.5", - "solhint": "^6.0.0", + "solhint": "^6.0.1", "solhint-plugin-openzeppelin": "file:scripts/solhint-custom", "solidity-ast": "^0.4.50", "solidity-coverage": "^0.8.14", From 728bb002b5d744c28ec7e121f68bb4446508142e Mon Sep 17 00:00:00 2001 From: Arr00 <13561405+arr00@users.noreply.github.com> Date: Fri, 19 Sep 2025 19:07:59 +0200 Subject: [PATCH 16/18] Update scripts/solhint-custom/index.js --- scripts/solhint-custom/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/solhint-custom/index.js b/scripts/solhint-custom/index.js index 0306c98ef01..f89052a75cd 100644 --- a/scripts/solhint-custom/index.js +++ b/scripts/solhint-custom/index.js @@ -104,7 +104,7 @@ module.exports = [ this.require( node.visibility === 'internal' || node.visibility === 'private', node, - 'Library functions should not be internal or private', + 'Library functions should be internal or private', ); } } From 47b57c07c887c9bd75d6a7727baadb50c95f2f11 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Fri, 19 Sep 2025 21:47:20 +0200 Subject: [PATCH 17/18] use solhint commons --- scripts/solhint-custom/index.js | 34 +++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/scripts/solhint-custom/index.js b/scripts/solhint-custom/index.js index 0306c98ef01..7acc20c1eb4 100644 --- a/scripts/solhint-custom/index.js +++ b/scripts/solhint-custom/index.js @@ -1,6 +1,9 @@ const path = require('path'); const minimatch = require('minimatch'); +const { isFallbackFunction } = require('solhint/lib/common/ast-types'); +const { hasLeadingUnderscore } = require('solhint/lib/common/identifier-naming'); + // Files matching these patterns will be ignored unless a rule has `static global = true` const ignore = ['contracts/mocks/**/*', 'test/**/*']; @@ -40,23 +43,26 @@ module.exports = [ static ruleId = 'leading-underscore'; VariableDeclaration(node) { - // TODO: do we want that rule ? Should no immutable variable have a prefix regardless of visibility ? - // - // else if (node.isImmutable) { - // this.require(!node.name.startsWith('_'), node, 'Immutable variables should not have leading underscore'); - // } if (node.isDeclaredConst) { - this.require(!node.name.startsWith('_'), node, 'Constant variables should not have leading underscore'); + this.require(!hasLeadingUnderscore(node.name), node, 'Constant variables should not have leading underscore'); } else if (node.isStateVar) { switch (node.visibility) { case 'private': - this.require(node.name.startsWith('_'), node, 'Private state variables must have leading underscore'); + this.require(hasLeadingUnderscore(node.name), node, 'Private state variables must have leading underscore'); break; case 'internal': - this.require(node.name.startsWith('_'), node, 'Internal state variables must have leading underscore'); + this.require( + hasLeadingUnderscore(node.name), + node, + 'Internal state variables must have leading underscore', + ); break; case 'public': - this.require(!node.name.startsWith('_'), node, 'Public state variables should not have leading underscore'); + this.require( + !hasLeadingUnderscore(node.name), + node, + 'Public state variables should not have leading underscore', + ); break; } } @@ -65,14 +71,14 @@ module.exports = [ FunctionDefinition(node) { switch (node.visibility) { case 'external': - this.require(!node.name.startsWith('_'), node, 'External functions should not have leading underscore'); + this.require(!hasLeadingUnderscore(node.name), node, 'External functions should not have leading underscore'); break; case 'public': - this.require(!node.name.startsWith('_'), node, 'Public functions should not have leading underscore'); + this.require(!hasLeadingUnderscore(node.name), node, 'Public functions should not have leading underscore'); break; case 'internal': this.require( - node.name.startsWith('_') !== (node.parent.kind === 'library'), + hasLeadingUnderscore(node.name) !== (node.parent.kind === 'library'), node, node.parent.kind === 'library' ? 'Library internal functions should not have leading underscore' @@ -80,7 +86,7 @@ module.exports = [ ); break; case 'private': - this.require(node.name.startsWith('_'), node, 'Private functions must have leading underscore'); + this.require(hasLeadingUnderscore(node.name), node, 'Private functions must have leading underscore'); break; } } @@ -91,7 +97,7 @@ module.exports = [ FunctionDefinition(node) { if (node.visibility == 'external' && node.isVirtual) { - this.require(node.isReceiveEther || node.isFallback, node, 'Functions should not be external and virtual'); + this.require(isFallbackFunction(node), node, 'Functions should not be external and virtual'); } } }, From eb66607930cb93376ca264ebaa45e06785eab4e1 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Mon, 22 Sep 2025 22:01:52 +0200 Subject: [PATCH 18/18] external non virtual --- contracts/mocks/proxy/UUPSUpgradeableMock.sol | 4 ++-- contracts/proxy/utils/UUPSUpgradeable.sol | 2 +- contracts/token/ERC20/extensions/ERC20Permit.sol | 2 +- test/proxy/utils/UUPSUpgradeable.test.js | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/contracts/mocks/proxy/UUPSUpgradeableMock.sol b/contracts/mocks/proxy/UUPSUpgradeableMock.sol index b5e8f506ce4..b44c2be606d 100644 --- a/contracts/mocks/proxy/UUPSUpgradeableMock.sol +++ b/contracts/mocks/proxy/UUPSUpgradeableMock.sol @@ -28,8 +28,8 @@ contract UUPSUpgradeableUnsafeMock is UUPSUpgradeableMock { } } -contract UUPSUnsupportedProxiableUUID is UUPSUpgradeableMock { - function proxiableUUID() public pure override returns (bytes32) { +contract UUPSUnsupportedProxiableUUIDMock is NonUpgradeableMock { + function proxiableUUID() external pure returns (bytes32) { return keccak256("invalid UUID"); } } diff --git a/contracts/proxy/utils/UUPSUpgradeable.sol b/contracts/proxy/utils/UUPSUpgradeable.sol index ce53745ca21..2a88b021156 100644 --- a/contracts/proxy/utils/UUPSUpgradeable.sol +++ b/contracts/proxy/utils/UUPSUpgradeable.sol @@ -71,7 +71,7 @@ abstract contract UUPSUpgradeable is IERC1822Proxiable { * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ - function proxiableUUID() public view virtual notDelegated returns (bytes32) { + function proxiableUUID() external view notDelegated returns (bytes32) { return ERC1967Utils.IMPLEMENTATION_SLOT; } diff --git a/contracts/token/ERC20/extensions/ERC20Permit.sol b/contracts/token/ERC20/extensions/ERC20Permit.sol index 17e16bdd94e..b89df28be9e 100644 --- a/contracts/token/ERC20/extensions/ERC20Permit.sol +++ b/contracts/token/ERC20/extensions/ERC20Permit.sol @@ -71,7 +71,7 @@ abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712, Nonces { /// @inheritdoc IERC20Permit // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { + function DOMAIN_SEPARATOR() external view returns (bytes32) { return _domainSeparatorV4(); } } diff --git a/test/proxy/utils/UUPSUpgradeable.test.js b/test/proxy/utils/UUPSUpgradeable.test.js index 17f86576168..476d1e67663 100644 --- a/test/proxy/utils/UUPSUpgradeable.test.js +++ b/test/proxy/utils/UUPSUpgradeable.test.js @@ -9,7 +9,7 @@ async function fixture() { const implUpgradeOk = await ethers.deployContract('UUPSUpgradeableMock'); const implUpgradeUnsafe = await ethers.deployContract('UUPSUpgradeableUnsafeMock'); const implUpgradeNonUUPS = await ethers.deployContract('NonUpgradeableMock'); - const implUnsupportedUUID = await ethers.deployContract('UUPSUnsupportedProxiableUUID'); + const implUnsupportedUUID = await ethers.deployContract('UUPSUnsupportedProxiableUUIDMock'); // Used for testing non ERC1967 compliant proxies (clones are proxies that don't use the ERC1967 implementation slot) const cloneFactory = await ethers.deployContract('$Clones');