From 20fb851a8c042d076ef7352f5a079098478a4c9c Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Fri, 5 Sep 2025 14:26:17 +0200 Subject: [PATCH 1/4] Remove unused imports --- contracts/account/extensions/draft-AccountERC7579.sol | 1 - contracts/mocks/account/AccountMock.sol | 1 - contracts/mocks/governance/GovernorNoncesKeyedMock.sol | 1 - contracts/mocks/token/ERC20BridgeableMock.sol | 2 +- contracts/mocks/utils/cryptography/ERC7739Mock.sol | 1 - contracts/utils/cryptography/signers/draft-ERC7739.sol | 1 - 6 files changed, 1 insertion(+), 6 deletions(-) diff --git a/contracts/account/extensions/draft-AccountERC7579.sol b/contracts/account/extensions/draft-AccountERC7579.sol index 46a2234dc68..12ac9df1747 100644 --- a/contracts/account/extensions/draft-AccountERC7579.sol +++ b/contracts/account/extensions/draft-AccountERC7579.sol @@ -19,7 +19,6 @@ import {ERC7579Utils, Mode, CallType, ExecType} from "../../account/utils/draft- import {EnumerableSet} from "../../utils/structs/EnumerableSet.sol"; import {Bytes} from "../../utils/Bytes.sol"; import {Packing} from "../../utils/Packing.sol"; -import {Address} from "../../utils/Address.sol"; import {Calldata} from "../../utils/Calldata.sol"; import {Account} from "../Account.sol"; diff --git a/contracts/mocks/account/AccountMock.sol b/contracts/mocks/account/AccountMock.sol index 6a8ae7e750b..803f3e53cf6 100644 --- a/contracts/mocks/account/AccountMock.sol +++ b/contracts/mocks/account/AccountMock.sol @@ -7,7 +7,6 @@ import {AccountERC7579} from "../../account/extensions/draft-AccountERC7579.sol" import {AccountERC7579Hooked} from "../../account/extensions/draft-AccountERC7579Hooked.sol"; import {ERC721Holder} from "../../token/ERC721/utils/ERC721Holder.sol"; import {ERC1155Holder} from "../../token/ERC1155/utils/ERC1155Holder.sol"; -import {ERC4337Utils} from "../../account/utils/draft-ERC4337Utils.sol"; import {ERC7739} from "../../utils/cryptography/signers/draft-ERC7739.sol"; import {ERC7821} from "../../account/extensions/draft-ERC7821.sol"; import {MODULE_TYPE_VALIDATOR} from "../../interfaces/draft-IERC7579.sol"; diff --git a/contracts/mocks/governance/GovernorNoncesKeyedMock.sol b/contracts/mocks/governance/GovernorNoncesKeyedMock.sol index 91021cc318e..d5cf78b4f89 100644 --- a/contracts/mocks/governance/GovernorNoncesKeyedMock.sol +++ b/contracts/mocks/governance/GovernorNoncesKeyedMock.sol @@ -6,7 +6,6 @@ import {Governor, Nonces} from "../../governance/Governor.sol"; import {GovernorSettings} from "../../governance/extensions/GovernorSettings.sol"; import {GovernorCountingSimple} from "../../governance/extensions/GovernorCountingSimple.sol"; import {GovernorVotesQuorumFraction} from "../../governance/extensions/GovernorVotesQuorumFraction.sol"; -import {GovernorProposalGuardian} from "../../governance/extensions/GovernorProposalGuardian.sol"; import {GovernorNoncesKeyed} from "../../governance/extensions/GovernorNoncesKeyed.sol"; abstract contract GovernorNoncesKeyedMock is diff --git a/contracts/mocks/token/ERC20BridgeableMock.sol b/contracts/mocks/token/ERC20BridgeableMock.sol index 6249cb66875..ef99f2e9d80 100644 --- a/contracts/mocks/token/ERC20BridgeableMock.sol +++ b/contracts/mocks/token/ERC20BridgeableMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.20; -import {ERC20, ERC20Bridgeable} from "../../token/ERC20/extensions/draft-ERC20Bridgeable.sol"; +import {ERC20Bridgeable} from "../../token/ERC20/extensions/draft-ERC20Bridgeable.sol"; abstract contract ERC20BridgeableMock is ERC20Bridgeable { address private _bridge; diff --git a/contracts/mocks/utils/cryptography/ERC7739Mock.sol b/contracts/mocks/utils/cryptography/ERC7739Mock.sol index ba7d04b5052..5cce444ed82 100644 --- a/contracts/mocks/utils/cryptography/ERC7739Mock.sol +++ b/contracts/mocks/utils/cryptography/ERC7739Mock.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.24; -import {ECDSA} from "../../../utils/cryptography/ECDSA.sol"; import {ERC7739} from "../../../utils/cryptography/signers/draft-ERC7739.sol"; import {SignerECDSA} from "../../../utils/cryptography/signers/SignerECDSA.sol"; import {SignerP256} from "../../../utils/cryptography/signers/SignerP256.sol"; diff --git a/contracts/utils/cryptography/signers/draft-ERC7739.sol b/contracts/utils/cryptography/signers/draft-ERC7739.sol index 0e4a9104e43..ffbf6a35fac 100644 --- a/contracts/utils/cryptography/signers/draft-ERC7739.sol +++ b/contracts/utils/cryptography/signers/draft-ERC7739.sol @@ -8,7 +8,6 @@ import {EIP712} from "../EIP712.sol"; import {ERC7739Utils} from "../draft-ERC7739Utils.sol"; import {IERC1271} from "../../../interfaces/IERC1271.sol"; import {MessageHashUtils} from "../MessageHashUtils.sol"; -import {ShortStrings} from "../../ShortStrings.sol"; /** * @dev Validates signatures wrapping the message hash in a nested EIP712 type. See {ERC7739Utils}. From 67db1b69cee807aa8257490b9398d471aac2d895 Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Fri, 5 Sep 2025 14:26:49 +0200 Subject: [PATCH 2/4] Add names to return params --- contracts/mocks/account/modules/ERC7579Mock.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/mocks/account/modules/ERC7579Mock.sol b/contracts/mocks/account/modules/ERC7579Mock.sol index 41083186cb2..3b936ee210e 100644 --- a/contracts/mocks/account/modules/ERC7579Mock.sol +++ b/contracts/mocks/account/modules/ERC7579Mock.sol @@ -77,7 +77,7 @@ abstract contract ERC7579FallbackHandlerMock is ERC7579ModuleMock(MODULE_TYPE_FA emit ERC7579FallbackHandlerMockCalled(_msgAccount(), _msgSender(), msg.value, _msgData()); } - function callView() public view returns (address, address) { + function callView() public view returns (address account, address sender) { return (_msgAccount(), _msgSender()); } From f8ea91e7b246e1d46ed13e61b180b3a469752d9e Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Fri, 5 Sep 2025 15:34:33 +0200 Subject: [PATCH 3/4] Add slippy --- contracts/mocks/Stateless.sol | 1 + package-lock.json | 74 ++++++++++++++++++++- package.json | 1 + slippy.config.js | 39 +++++++++++ test/account/utils/draft-ERC7579Utils.t.sol | 1 + 5 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 slippy.config.js diff --git a/contracts/mocks/Stateless.sol b/contracts/mocks/Stateless.sol index fd0cf398eb0..3981dbb4b74 100644 --- a/contracts/mocks/Stateless.sol +++ b/contracts/mocks/Stateless.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.26; +// slippy-disable no-unused-vars // We keep these imports and a dummy contract just to we can run the test suite after transpilation. import {Address} from "../utils/Address.sol"; diff --git a/package-lock.json b/package-lock.json index 147729268ca..f9cd0174114 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "@openzeppelin/merkle-tree": "^1.0.7", "@openzeppelin/upgrade-safe-transpiler": "^0.3.32", "@openzeppelin/upgrades-core": "^1.20.6", + "@slippy-lint/slippy": "^0.1.2", "chai": "^4.2.0", "eslint": "^9.0.0", "eslint-config-prettier": "^10.0.0", @@ -2403,6 +2404,73 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, + "node_modules/@slippy-lint/slippy": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@slippy-lint/slippy/-/slippy-0.1.2.tgz", + "integrity": "sha512-TC5E6eMXwPr09tp2KFlwhxulWeu7QelA6fGx3I3JHgYgcppXMjCad8NlEi71UEWnQVDtHy2+ebLL9sBoZa8SsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nomicfoundation/slang": "^1.2.1", + "chalk": "^5.4.1", + "fast-glob": "^3.3.3", + "micromatch": "^4.0.8", + "minimist": "^1.2.8", + "semver": "^7.7.2", + "workerpool": "^9.3.3", + "zod": "^4.0.10" + }, + "bin": { + "slippy": "dist/cli/cli.js" + } + }, + "node_modules/@slippy-lint/slippy/node_modules/@bytecodealliance/preview2-shim": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/@bytecodealliance/preview2-shim/-/preview2-shim-0.17.2.tgz", + "integrity": "sha512-mNm/lblgES8UkVle8rGImXOz4TtL3eU3inHay/7TVchkKrb/lgcVvTK0+VAw8p5zQ0rgQsXm1j5dOlAAd+MeoA==", + "dev": true, + "license": "(Apache-2.0 WITH LLVM-exception)" + }, + "node_modules/@slippy-lint/slippy/node_modules/@nomicfoundation/slang": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/slang/-/slang-1.2.1.tgz", + "integrity": "sha512-XQirzqDGxMnhOZtGPRLdc1F6UymU0N/lhXUcWsf6bqy29Pq+g6ougvbSTTCTXjgWXjBp6zQ1gaJmzWmMBvMgOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bytecodealliance/preview2-shim": "0.17.2" + } + }, + "node_modules/@slippy-lint/slippy/node_modules/chalk": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.0.tgz", + "integrity": "sha512-46QrSQFyVSEyYAgQ22hQ+zDa60YHA4fBstHmtSApj1Y5vKtG27fWowW03jCk5KcbXEWPZUIR894aARCA/G1kfQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@slippy-lint/slippy/node_modules/workerpool": { + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.3.tgz", + "integrity": "sha512-slxCaKbYjEdFT/o2rH9xS1hf4uRDch1w7Uo+apxhZ+sf/1d9e0ZVkn42kPNGP2dgjIx6YFvSevj0zHvbWe2jdw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@slippy-lint/slippy/node_modules/zod": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.5.tgz", + "integrity": "sha512-rcUUZqlLJgBC33IT3PNMgsCq6TzLQEG/Ei/KTCU0PedSWRMAXoOUN+4t/0H+Q8bdnLPdqUYnvboJT0bn/229qg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/@solidity-parser/parser": { "version": "0.19.0", "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.19.0.tgz", @@ -9168,9 +9236,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, "license": "ISC", "bin": { diff --git a/package.json b/package.json index b058a0aaa81..1e4fbe3309b 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "@openzeppelin/merkle-tree": "^1.0.7", "@openzeppelin/upgrade-safe-transpiler": "^0.3.32", "@openzeppelin/upgrades-core": "^1.20.6", + "@slippy-lint/slippy": "^0.1.2", "chai": "^4.2.0", "eslint": "^9.0.0", "eslint-config-prettier": "^10.0.0", diff --git a/slippy.config.js b/slippy.config.js new file mode 100644 index 00000000000..6258fe76180 --- /dev/null +++ b/slippy.config.js @@ -0,0 +1,39 @@ +module.exports = [ + { + rules: { + 'compatible-pragma': 'error', + curly: 'off', + 'explicit-types': 'error', + 'id-denylist': 'error', + 'imports-on-top': 'error', + 'max-state-vars': 'error', + 'named-return-params': 'error', + 'naming-convention': 'off', + 'no-console': 'error', + 'no-default-visibility': 'off', + 'no-duplicate-imports': 'error', + 'no-empty-blocks': 'off', + 'no-global-imports': 'error', + 'no-restricted-syntax': 'off', + 'no-send': 'error', + 'no-tx-origin': 'error', + 'no-unchecked-calls': 'error', + 'no-uninitialized-immutable-references': 'error', + 'no-unused-vars': 'error', + 'one-contract-per-file': 'off', + 'private-vars': 'off', + 'require-revert-reason': 'off', + 'sort-imports': 'off', + 'sort-members': 'off', + 'sort-modifiers': 'error', + }, + }, + { + ignores: ['contracts/mocks/**/*', 'test/**/*'], + rules: { + 'no-default-visibility': 'error', + 'private-vars': 'error', + 'require-revert-reason': 'error', + }, + }, +]; diff --git a/test/account/utils/draft-ERC7579Utils.t.sol b/test/account/utils/draft-ERC7579Utils.t.sol index c89f1ff1649..1c1d7fa4b82 100644 --- a/test/account/utils/draft-ERC7579Utils.t.sol +++ b/test/account/utils/draft-ERC7579Utils.t.sol @@ -5,6 +5,7 @@ pragma solidity ^0.8.24; // https://github.com/adamegyed/erc7579-execute-vulnerability/tree/4589a30ff139e143d6c57183ac62b5c029217a90 // // solhint-disable no-console +// slippy-disable no-console import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; From 55122e8e6b5906a78ca9b36dcc00cbf6b8f72851 Mon Sep 17 00:00:00 2001 From: Franco Victorio Date: Fri, 5 Sep 2025 15:55:34 +0200 Subject: [PATCH 4/4] Add naming-convention --- contracts/governance/Governor.sol | 2 +- contracts/governance/IGovernor.sol | 2 +- .../extensions/GovernorCountingFractional.sol | 1 + .../GovernorCountingOverridable.sol | 1 + .../extensions/GovernorCountingSimple.sol | 1 + .../governance/extensions/GovernorVotes.sol | 1 + contracts/governance/utils/Votes.sol | 1 + contracts/interfaces/IERC6372.sol | 2 +- .../MultipleInheritanceInitializableMocks.sol | 10 +++ contracts/mocks/VotesExtendedMock.sol | 1 + contracts/mocks/VotesMock.sol | 1 + .../docs/governance/MyTokenTimestampBased.sol | 1 + .../ERC20VotesAdditionalCheckpointsMock.sol | 1 + .../mocks/token/ERC20VotesTimestampMock.sol | 2 + contracts/proxy/utils/UUPSUpgradeable.sol | 2 +- .../token/ERC20/extensions/ERC20Permit.sol | 1 + .../token/ERC20/extensions/IERC20Permit.sol | 2 +- contracts/utils/Packing.sol | 1 + contracts/utils/cryptography/EIP712.sol | 2 + .../vendor/compound/ICompoundTimelock.sol | 6 +- scripts/generate/templates/Packing.js | 1 + slippy.config.js | 85 ++++++++++++++++++- test/governance/Governor.t.sol | 4 +- ...GovernorSuperQuorumGreaterThanQuorum.t.sol | 3 + 24 files changed, 123 insertions(+), 11 deletions(-) diff --git a/contracts/governance/Governor.sol b/contracts/governance/Governor.sol index 05564b8352f..92a001bda73 100644 --- a/contracts/governance/Governor.sol +++ b/contracts/governance/Governor.sol @@ -792,7 +792,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72 /// @inheritdoc IERC6372 // solhint-disable-next-line func-name-mixedcase - function CLOCK_MODE() public view virtual returns (string memory); + function CLOCK_MODE() public view virtual returns (string memory); // slippy-disable-line naming-convention /// @inheritdoc IGovernor function votingDelay() public view virtual returns (uint256); diff --git a/contracts/governance/IGovernor.sol b/contracts/governance/IGovernor.sol index b3f0feb9814..d38a7af21b3 100644 --- a/contracts/governance/IGovernor.sol +++ b/contracts/governance/IGovernor.sol @@ -199,7 +199,7 @@ interface IGovernor is IERC165, IERC6372 { * JavaScript class. */ // solhint-disable-next-line func-name-mixedcase - function COUNTING_MODE() external view returns (string memory); + function COUNTING_MODE() external view returns (string memory); // slippy-disable-line naming-convention /** * @notice module:core diff --git a/contracts/governance/extensions/GovernorCountingFractional.sol b/contracts/governance/extensions/GovernorCountingFractional.sol index 1460d2ddef7..42ce846a1bc 100644 --- a/contracts/governance/extensions/GovernorCountingFractional.sol +++ b/contracts/governance/extensions/GovernorCountingFractional.sol @@ -56,6 +56,7 @@ abstract contract GovernorCountingFractional is Governor { /// @inheritdoc IGovernor // solhint-disable-next-line func-name-mixedcase function COUNTING_MODE() public pure virtual override returns (string memory) { + // slippy-disable-previous-line naming-convention return "support=bravo,fractional&quorum=for,abstain¶ms=fractional"; } diff --git a/contracts/governance/extensions/GovernorCountingOverridable.sol b/contracts/governance/extensions/GovernorCountingOverridable.sol index 45a72ea780c..b490632960c 100644 --- a/contracts/governance/extensions/GovernorCountingOverridable.sol +++ b/contracts/governance/extensions/GovernorCountingOverridable.sol @@ -50,6 +50,7 @@ abstract contract GovernorCountingOverridable is GovernorVotes { /// @inheritdoc IGovernor // solhint-disable-next-line func-name-mixedcase function COUNTING_MODE() public pure virtual override returns (string memory) { + // slippy-disable-previous-line naming-convention return "support=bravo,override&quorum=for,abstain&overridable=true"; } diff --git a/contracts/governance/extensions/GovernorCountingSimple.sol b/contracts/governance/extensions/GovernorCountingSimple.sol index 3f24a657cee..11b2d94a643 100644 --- a/contracts/governance/extensions/GovernorCountingSimple.sol +++ b/contracts/governance/extensions/GovernorCountingSimple.sol @@ -30,6 +30,7 @@ abstract contract GovernorCountingSimple is Governor { /// @inheritdoc IGovernor // solhint-disable-next-line func-name-mixedcase function COUNTING_MODE() public pure virtual override returns (string memory) { + // slippy-disable-previous-line naming-convention return "support=bravo&quorum=for,abstain"; } diff --git a/contracts/governance/extensions/GovernorVotes.sol b/contracts/governance/extensions/GovernorVotes.sol index 4ad5870a448..da8801dcd20 100644 --- a/contracts/governance/extensions/GovernorVotes.sol +++ b/contracts/governance/extensions/GovernorVotes.sol @@ -43,6 +43,7 @@ abstract contract GovernorVotes is Governor { */ // solhint-disable-next-line func-name-mixedcase function CLOCK_MODE() public view virtual override returns (string memory) { + // slippy-disable-previous-line naming-convention try token().CLOCK_MODE() returns (string memory clockmode) { return clockmode; } catch { diff --git a/contracts/governance/utils/Votes.sol b/contracts/governance/utils/Votes.sol index 02c68d028c0..1cab1c2721e 100644 --- a/contracts/governance/utils/Votes.sol +++ b/contracts/governance/utils/Votes.sol @@ -64,6 +64,7 @@ abstract contract Votes is Context, EIP712, Nonces, IERC5805 { */ // solhint-disable-next-line func-name-mixedcase function CLOCK_MODE() public view virtual returns (string memory) { + // slippy-disable-previous-line naming-convention // Check that the clock was not modified if (clock() != Time.blockNumber()) { revert ERC6372InconsistentClock(); diff --git a/contracts/interfaces/IERC6372.sol b/contracts/interfaces/IERC6372.sol index 447a8ea33a9..5210ba58ed0 100644 --- a/contracts/interfaces/IERC6372.sol +++ b/contracts/interfaces/IERC6372.sol @@ -13,5 +13,5 @@ interface IERC6372 { * @dev Description of the clock */ // solhint-disable-next-line func-name-mixedcase - function CLOCK_MODE() external view returns (string memory); + function CLOCK_MODE() external view returns (string memory); // slippy-disable-line naming-convention } diff --git a/contracts/mocks/MultipleInheritanceInitializableMocks.sol b/contracts/mocks/MultipleInheritanceInitializableMocks.sol index 51030acd68a..8f2c127ebd1 100644 --- a/contracts/mocks/MultipleInheritanceInitializableMocks.sol +++ b/contracts/mocks/MultipleInheritanceInitializableMocks.sol @@ -27,11 +27,13 @@ contract SampleHuman is Initializable { // solhint-disable-next-line func-name-mixedcase function __SampleHuman_init() internal onlyInitializing { + // slippy-disable-previous-line naming-convention __SampleHuman_init_unchained(); } // solhint-disable-next-line func-name-mixedcase function __SampleHuman_init_unchained() internal onlyInitializing { + // slippy-disable-previous-line naming-convention isHuman = true; } } @@ -48,12 +50,14 @@ contract SampleMother is Initializable, SampleHuman { // solhint-disable-next-line func-name-mixedcase function __SampleMother_init(uint256 value) internal onlyInitializing { + // slippy-disable-previous-line naming-convention __SampleHuman_init(); __SampleMother_init_unchained(value); } // solhint-disable-next-line func-name-mixedcase function __SampleMother_init_unchained(uint256 value) internal onlyInitializing { + // slippy-disable-previous-line naming-convention mother = value; } } @@ -70,12 +74,14 @@ contract SampleGramps is Initializable, SampleHuman { // solhint-disable-next-line func-name-mixedcase function __SampleGramps_init(string memory value) internal onlyInitializing { + // slippy-disable-previous-line naming-convention __SampleHuman_init(); __SampleGramps_init_unchained(value); } // solhint-disable-next-line func-name-mixedcase function __SampleGramps_init_unchained(string memory value) internal onlyInitializing { + // slippy-disable-previous-line naming-convention gramps = value; } } @@ -92,12 +98,14 @@ contract SampleFather is Initializable, SampleGramps { // solhint-disable-next-line func-name-mixedcase function __SampleFather_init(string memory _gramps, uint256 _father) internal onlyInitializing { + // slippy-disable-previous-line naming-convention __SampleGramps_init(_gramps); __SampleFather_init_unchained(_father); } // solhint-disable-next-line func-name-mixedcase function __SampleFather_init_unchained(uint256 _father) internal onlyInitializing { + // slippy-disable-previous-line naming-convention father = _father; } } @@ -114,6 +122,7 @@ contract SampleChild is Initializable, SampleMother, SampleFather { // solhint-disable-next-line func-name-mixedcase function __SampleChild_init( + // slippy-disable-previous-line naming-convention uint256 _mother, string memory _gramps, uint256 _father, @@ -126,6 +135,7 @@ contract SampleChild is Initializable, SampleMother, SampleFather { // solhint-disable-next-line func-name-mixedcase function __SampleChild_init_unchained(uint256 _child) internal onlyInitializing { + // slippy-disable-previous-line naming-convention child = _child; } } diff --git a/contracts/mocks/VotesExtendedMock.sol b/contracts/mocks/VotesExtendedMock.sol index e9c11da5492..ad669b20848 100644 --- a/contracts/mocks/VotesExtendedMock.sol +++ b/contracts/mocks/VotesExtendedMock.sol @@ -37,6 +37,7 @@ abstract contract VotesExtendedTimestampMock is VotesExtendedMock { // solhint-disable-next-line func-name-mixedcase function CLOCK_MODE() public view virtual override returns (string memory) { + // slippy-disable-previous-line naming-convention return "mode=timestamp"; } } diff --git a/contracts/mocks/VotesMock.sol b/contracts/mocks/VotesMock.sol index afef5ab7cf0..95643be451a 100644 --- a/contracts/mocks/VotesMock.sol +++ b/contracts/mocks/VotesMock.sol @@ -37,6 +37,7 @@ abstract contract VotesTimestampMock is VotesMock { // solhint-disable-next-line func-name-mixedcase function CLOCK_MODE() public view virtual override returns (string memory) { + // slippy-disable-previous-line naming-convention return "mode=timestamp"; } } diff --git a/contracts/mocks/docs/governance/MyTokenTimestampBased.sol b/contracts/mocks/docs/governance/MyTokenTimestampBased.sol index 60f206414c5..1c5eac77f61 100644 --- a/contracts/mocks/docs/governance/MyTokenTimestampBased.sol +++ b/contracts/mocks/docs/governance/MyTokenTimestampBased.sol @@ -17,6 +17,7 @@ contract MyTokenTimestampBased is ERC20, ERC20Permit, ERC20Votes { // solhint-disable-next-line func-name-mixedcase function CLOCK_MODE() public pure override returns (string memory) { + // slippy-disable-previous-line naming-convention return "mode=timestamp"; } diff --git a/contracts/mocks/token/ERC20VotesAdditionalCheckpointsMock.sol b/contracts/mocks/token/ERC20VotesAdditionalCheckpointsMock.sol index e965b17bd87..c363a85c5fc 100644 --- a/contracts/mocks/token/ERC20VotesAdditionalCheckpointsMock.sol +++ b/contracts/mocks/token/ERC20VotesAdditionalCheckpointsMock.sol @@ -26,6 +26,7 @@ abstract contract ERC20VotesExtendedTimestampMock is ERC20VotesExtendedMock { // solhint-disable-next-line func-name-mixedcase function CLOCK_MODE() public view virtual override returns (string memory) { + // slippy-disable-previous-line naming-convention return "mode=timestamp"; } } diff --git a/contracts/mocks/token/ERC20VotesTimestampMock.sol b/contracts/mocks/token/ERC20VotesTimestampMock.sol index bebdef82184..549bc20e521 100644 --- a/contracts/mocks/token/ERC20VotesTimestampMock.sol +++ b/contracts/mocks/token/ERC20VotesTimestampMock.sol @@ -13,6 +13,7 @@ abstract contract ERC20VotesTimestampMock is ERC20Votes { // solhint-disable-next-line func-name-mixedcase function CLOCK_MODE() public view virtual override returns (string memory) { + // slippy-disable-previous-line naming-convention return "mode=timestamp"; } } @@ -24,6 +25,7 @@ abstract contract ERC721VotesTimestampMock is ERC721Votes { // solhint-disable-next-line func-name-mixedcase function CLOCK_MODE() public view virtual override returns (string memory) { + // slippy-disable-previous-line naming-convention return "mode=timestamp"; } } diff --git a/contracts/proxy/utils/UUPSUpgradeable.sol b/contracts/proxy/utils/UUPSUpgradeable.sol index d0f58427f9b..b56b8597660 100644 --- a/contracts/proxy/utils/UUPSUpgradeable.sol +++ b/contracts/proxy/utils/UUPSUpgradeable.sol @@ -18,7 +18,7 @@ import {ERC1967Utils} from "../ERC1967/ERC1967Utils.sol"; */ abstract contract UUPSUpgradeable is IERC1822Proxiable { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable - address private immutable __self = address(this); + address private immutable __self = address(this); // slippy-disable-line naming-convention /** * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)` diff --git a/contracts/token/ERC20/extensions/ERC20Permit.sol b/contracts/token/ERC20/extensions/ERC20Permit.sol index 3b181640030..56eb6f34058 100644 --- a/contracts/token/ERC20/extensions/ERC20Permit.sol +++ b/contracts/token/ERC20/extensions/ERC20Permit.sol @@ -72,6 +72,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) { + // slippy-disable-previous-line naming-convention return _domainSeparatorV4(); } } diff --git a/contracts/token/ERC20/extensions/IERC20Permit.sol b/contracts/token/ERC20/extensions/IERC20Permit.sol index 65488babebd..a48addd9f46 100644 --- a/contracts/token/ERC20/extensions/IERC20Permit.sol +++ b/contracts/token/ERC20/extensions/IERC20Permit.sol @@ -86,5 +86,5 @@ interface IERC20Permit { * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase - function DOMAIN_SEPARATOR() external view returns (bytes32); + function DOMAIN_SEPARATOR() external view returns (bytes32); // slippy-disable-line naming-convention } diff --git a/contracts/utils/Packing.sol b/contracts/utils/Packing.sol index f7c5d6fcc3c..474d4014b3e 100644 --- a/contracts/utils/Packing.sol +++ b/contracts/utils/Packing.sol @@ -33,6 +33,7 @@ pragma solidity ^0.8.20; * _Available since v5.1._ */ // solhint-disable func-name-mixedcase +// slippy-disable naming-convention library Packing { error OutOfRangeAccess(); diff --git a/contracts/utils/cryptography/EIP712.sol b/contracts/utils/cryptography/EIP712.sol index 0eaef9d27e0..516aa552b4c 100644 --- a/contracts/utils/cryptography/EIP712.sol +++ b/contracts/utils/cryptography/EIP712.sol @@ -144,6 +144,7 @@ abstract contract EIP712 is IERC5267 { */ // solhint-disable-next-line func-name-mixedcase function _EIP712Name() internal view returns (string memory) { + // slippy-disable-previous-line naming-convention return _name.toStringWithFallback(_nameFallback); } @@ -155,6 +156,7 @@ abstract contract EIP712 is IERC5267 { */ // solhint-disable-next-line func-name-mixedcase function _EIP712Version() internal view returns (string memory) { + // slippy-disable-previous-line naming-convention return _version.toStringWithFallback(_versionFallback); } } diff --git a/contracts/vendor/compound/ICompoundTimelock.sol b/contracts/vendor/compound/ICompoundTimelock.sol index 84cd62ed12c..67f6ca31e16 100644 --- a/contracts/vendor/compound/ICompoundTimelock.sol +++ b/contracts/vendor/compound/ICompoundTimelock.sol @@ -38,13 +38,13 @@ interface ICompoundTimelock { receive() external payable; // solhint-disable-next-line func-name-mixedcase - function GRACE_PERIOD() external view returns (uint256); + function GRACE_PERIOD() external view returns (uint256); // slippy-disable-line naming-convention // solhint-disable-next-line func-name-mixedcase - function MINIMUM_DELAY() external view returns (uint256); + function MINIMUM_DELAY() external view returns (uint256); // slippy-disable-line naming-convention // solhint-disable-next-line func-name-mixedcase - function MAXIMUM_DELAY() external view returns (uint256); + function MAXIMUM_DELAY() external view returns (uint256); // slippy-disable-line naming-convention function admin() external view returns (address); diff --git a/scripts/generate/templates/Packing.js b/scripts/generate/templates/Packing.js index 9f3b7716a6a..8f7fbd50983 100644 --- a/scripts/generate/templates/Packing.js +++ b/scripts/generate/templates/Packing.js @@ -36,6 +36,7 @@ pragma solidity ^0.8.20; * _Available since v5.1._ */ // solhint-disable func-name-mixedcase +// slippy-disable naming-convention `; const errors = `\ diff --git a/slippy.config.js b/slippy.config.js index 6258fe76180..b4422aa38c0 100644 --- a/slippy.config.js +++ b/slippy.config.js @@ -1,3 +1,79 @@ +const namingConventionCommon = [ + { + selector: 'variableLike', + format: ['camelCase'], + leadingUnderscore: 'allowSingleOrDouble', + trailingUnderscore: 'allow', + }, + { + selector: 'typeLike', + format: ['PascalCase'], + }, + { + selector: 'stateVariable', + format: ['UPPER_CASE'], + modifiers: ['constant'], + leadingUnderscore: 'allow', + }, + // interface should start with I + { + selector: 'interface', + format: ['PascalCase'], + custom: { + match: true, + regex: '^I[A-Z]', + }, + }, +]; + +const namingConventionSources = [ + ...namingConventionCommon, + // constant and private state variables should not have a leading underscore + { + selector: 'stateVariable', + format: ['camelCase', 'UPPER_CASE'], + modifiers: ['private', 'constant'], + leadingUnderscore: 'forbid', + }, + // non-constant private state variables should have a leading underscore + { + selector: 'stateVariable', + format: ['camelCase', 'UPPER_CASE'], + modifiers: ['private'], + leadingUnderscore: 'require', + }, + // private functions and non-library internal functions should have a leading underscore + { + selector: 'function', + modifiers: ['private'], + format: ['camelCase'], + leadingUnderscore: 'require', + }, + { + selector: 'function', + modifiers: ['internal'], + format: ['camelCase'], + leadingUnderscore: 'require', + }, + // library internal functions should not have a leading underscore + { + selector: 'function', + modifiers: ['internal', 'library'], + format: ['camelCase'], + leadingUnderscore: 'forbid', + }, +]; + +const namingConventionTests = [ + ...namingConventionCommon, + // allow snake_case in tests + { + selector: 'function', + format: ['camelCase', 'snake_case'], + leadingUnderscore: 'allow', + }, +]; + module.exports = [ { rules: { @@ -8,7 +84,7 @@ module.exports = [ 'imports-on-top': 'error', 'max-state-vars': 'error', 'named-return-params': 'error', - 'naming-convention': 'off', + 'naming-convention': ['error', namingConventionCommon], 'no-console': 'error', 'no-default-visibility': 'off', 'no-duplicate-imports': 'error', @@ -31,9 +107,16 @@ module.exports = [ { ignores: ['contracts/mocks/**/*', 'test/**/*'], rules: { + 'naming-convention': ['error', namingConventionSources], 'no-default-visibility': 'error', 'private-vars': 'error', 'require-revert-reason': 'error', }, }, + { + files: ['test/**/*'], + rules: { + 'naming-convention': ['error', namingConventionTests], + }, + }, ]; diff --git a/test/governance/Governor.t.sol b/test/governance/Governor.t.sol index 66b684d26e4..6ffbe81c6d4 100644 --- a/test/governance/Governor.t.sol +++ b/test/governance/Governor.t.sol @@ -36,10 +36,10 @@ contract GovernorInternalTest is Test, Governor { function clock() public pure override returns (uint48) {} // solhint-disable-next-line func-name-mixedcase - function CLOCK_MODE() public pure override returns (string memory) {} + function CLOCK_MODE() public pure override returns (string memory) {} // slippy-disable-line naming-convention // solhint-disable-next-line func-name-mixedcase - function COUNTING_MODE() public pure virtual override returns (string memory) {} + function COUNTING_MODE() public pure virtual override returns (string memory) {} // slippy-disable-line naming-convention function votingDelay() public pure virtual override returns (uint256) {} diff --git a/test/governance/extensions/GovernorSuperQuorumGreaterThanQuorum.t.sol b/test/governance/extensions/GovernorSuperQuorumGreaterThanQuorum.t.sol index 25fd846830d..2236f3bb1a4 100644 --- a/test/governance/extensions/GovernorSuperQuorumGreaterThanQuorum.t.sol +++ b/test/governance/extensions/GovernorSuperQuorumGreaterThanQuorum.t.sol @@ -44,11 +44,13 @@ contract GovernorHandler is GovernorVotesSuperQuorumFractionMock { // solhint-disable-next-line func-name-mixedcase function $_updateSuperQuorumNumerator(uint256 newSuperQuorumNumerator) public { + // slippy-disable-previous-line naming-convention _updateSuperQuorumNumerator(newSuperQuorumNumerator); } // solhint-disable-next-line func-name-mixedcase function $_updateQuorumNumerator(uint256 newQuorumNumerator) public { + // slippy-disable-previous-line naming-convention _updateQuorumNumerator(newQuorumNumerator); } } @@ -78,6 +80,7 @@ contract GovernorSuperQuorumGreaterThanQuorum is Test { // solhint-disable-next-line func-name-mixedcase function invariant_superQuorumGreaterThanQuorum() external view { + // slippy-disable-previous-line naming-convention assertGe(_governorHandler.superQuorumNumerator(), _governorHandler.quorumNumerator()); } }