Browse Source

Merge branch 'master' into typo-fixes

Hadrien Croubois 3 months ago
parent
commit
0b9edd4a65

+ 1 - 1
contracts/mocks/DummyImplementation.sol

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
 
-pragma solidity ^0.8.22;
+pragma solidity ^0.8.21;
 
 import {ERC1967Utils} from "../proxy/ERC1967/ERC1967Utils.sol";
 import {StorageSlot} from "../utils/StorageSlot.sol";

+ 1 - 1
contracts/mocks/account/AccountMock.sol

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
 
-pragma solidity ^0.8.27;
+pragma solidity ^0.8.26;
 
 import {Account} from "../../account/Account.sol";
 import {AccountERC7579} from "../../account/extensions/draft-AccountERC7579.sol";

+ 4 - 0
contracts/utils/cryptography/signers/MultiSignerERC7913.sol

@@ -66,6 +66,9 @@ abstract contract MultiSignerERC7913 is AbstractSigner {
     /// @dev The `signer` is less than 20 bytes long.
     error MultiSignerERC7913InvalidSigner(bytes signer);
 
+    /// @dev The `threshold` is zero.
+    error MultiSignerERC7913ZeroThreshold();
+
     /// @dev The `threshold` is unreachable given the number of `signers`.
     error MultiSignerERC7913UnreachableThreshold(uint64 signers, uint64 threshold);
 
@@ -146,6 +149,7 @@ abstract contract MultiSignerERC7913 is AbstractSigner {
      * * See {_validateReachableThreshold} for the threshold validation.
      */
     function _setThreshold(uint64 newThreshold) internal virtual {
+        require(newThreshold > 0, MultiSignerERC7913ZeroThreshold());
         _threshold = newThreshold;
         _validateReachableThreshold();
         emit ERC7913ThresholdSet(newThreshold);

+ 1 - 1
fv-requirements.txt

@@ -1,4 +1,4 @@
 certora-cli==4.13.1
 # File uses a custom name (fv-requirements.txt) so that it isn't picked by Netlify's build
 # whose latest Python version is 0.3.8, incompatible with most recent versions of Halmos
-halmos==0.2.6
+halmos==0.3.0

+ 303 - 53
package-lock.json

@@ -15,8 +15,8 @@
         "@changesets/read": "^0.6.0",
         "@eslint/compat": "^1.2.1",
         "@nomicfoundation/hardhat-chai-matchers": "^2.0.6",
-        "@nomicfoundation/hardhat-ethers": "^3.0.4",
-        "@nomicfoundation/hardhat-network-helpers": "^1.0.3",
+        "@nomicfoundation/hardhat-ethers": "^3.0.9",
+        "@nomicfoundation/hardhat-network-helpers": "^1.0.13",
         "@openzeppelin/docs-utils": "^0.1.5",
         "@openzeppelin/merkle-tree": "^1.0.7",
         "@openzeppelin/upgrade-safe-transpiler": "^0.3.32",
@@ -28,7 +28,7 @@
         "glob": "^11.0.0",
         "globals": "^16.0.0",
         "graphlib": "^2.1.8",
-        "hardhat": "^2.24.0",
+        "hardhat": "^2.24.3",
         "hardhat-exposed": "^0.3.15",
         "hardhat-gas-reporter": "^2.1.0",
         "hardhat-ignore-warnings": "^0.2.11",
@@ -1723,28 +1723,28 @@
       }
     },
     "node_modules/@nomicfoundation/edr": {
-      "version": "0.11.0",
-      "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.11.0.tgz",
-      "integrity": "sha512-36WERf8ldvyHR6UAbcYsa+vpbW7tCrJGBwF4gXSsb8+STj1n66Hz85Y/O7B9+8AauX3PhglvV5dKl91tk43mWw==",
+      "version": "0.11.1",
+      "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.11.1.tgz",
+      "integrity": "sha512-P97XwcD9DdMMZm9aqw89+mzqzlKmqzSPM3feBES2WVRm5/LOiBYorhpeAX+ANj0X8532SKgxoZK/CN5OWv9vZA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "@nomicfoundation/edr-darwin-arm64": "0.11.0",
-        "@nomicfoundation/edr-darwin-x64": "0.11.0",
-        "@nomicfoundation/edr-linux-arm64-gnu": "0.11.0",
-        "@nomicfoundation/edr-linux-arm64-musl": "0.11.0",
-        "@nomicfoundation/edr-linux-x64-gnu": "0.11.0",
-        "@nomicfoundation/edr-linux-x64-musl": "0.11.0",
-        "@nomicfoundation/edr-win32-x64-msvc": "0.11.0"
+        "@nomicfoundation/edr-darwin-arm64": "0.11.1",
+        "@nomicfoundation/edr-darwin-x64": "0.11.1",
+        "@nomicfoundation/edr-linux-arm64-gnu": "0.11.1",
+        "@nomicfoundation/edr-linux-arm64-musl": "0.11.1",
+        "@nomicfoundation/edr-linux-x64-gnu": "0.11.1",
+        "@nomicfoundation/edr-linux-x64-musl": "0.11.1",
+        "@nomicfoundation/edr-win32-x64-msvc": "0.11.1"
       },
       "engines": {
         "node": ">= 18"
       }
     },
     "node_modules/@nomicfoundation/edr-darwin-arm64": {
-      "version": "0.11.0",
-      "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.11.0.tgz",
-      "integrity": "sha512-aYTVdcSs27XG7ayTzvZ4Yn9z/ABSaUwicrtrYK2NR8IH0ik4N4bWzo/qH8rax6rewVLbHUkGyGYnsy5ZN4iiMw==",
+      "version": "0.11.1",
+      "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.11.1.tgz",
+      "integrity": "sha512-vjca7gkl1o0yYqMjwxQpMEtdsb20nWHBnnxDO8ZBCTD5IwfYT5LiMxFaJo8NUJ7ODIRkF/zuEtAF3W7+ZlC5RA==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -1752,9 +1752,9 @@
       }
     },
     "node_modules/@nomicfoundation/edr-darwin-x64": {
-      "version": "0.11.0",
-      "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.11.0.tgz",
-      "integrity": "sha512-RxX7UYgvJrfcyT/uHUn44Nsy1XaoW+Q1khKMdHKxeW7BrgIi+Lz+siz3bX5vhSoAnKilDPhIVLrnC8zxQhjR2A==",
+      "version": "0.11.1",
+      "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.11.1.tgz",
+      "integrity": "sha512-0aGStHq9XePXX9UqdU1w60HGO9AfYCgkNEir5sBpntU5E0TvZEK6jwyYr667+s90n2mihdeP97QSA0O/6PT6PA==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -1762,9 +1762,9 @@
       }
     },
     "node_modules/@nomicfoundation/edr-linux-arm64-gnu": {
-      "version": "0.11.0",
-      "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.11.0.tgz",
-      "integrity": "sha512-J0j+rs0s11FuSipt/ymqrFmpJ7c0FSz1/+FohCIlUXDxFv//+1R/8lkGPjEYFmy8DPpk/iO8mcpqHTGckREbqA==",
+      "version": "0.11.1",
+      "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.11.1.tgz",
+      "integrity": "sha512-OWhCETc03PVdtzatW/c2tpOPx+GxlBfBaLmMuGRD1soAr1nMOmg2WZAlo4i6Up9fkQYl+paiYMMFVat1meaMvQ==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -1772,9 +1772,9 @@
       }
     },
     "node_modules/@nomicfoundation/edr-linux-arm64-musl": {
-      "version": "0.11.0",
-      "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.11.0.tgz",
-      "integrity": "sha512-4r32zkGMN7WT/CMEuW0VjbuEdIeCskHNDMW4SSgQSJOE/N9L1KSLJCSsAbPD3aYE+e4WRDTyOwmuLjeUTcLZKQ==",
+      "version": "0.11.1",
+      "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.11.1.tgz",
+      "integrity": "sha512-p0qvtIvDA2eZ8pQ5XUKnWdW1IrwFzSrjyrO88oYx6Lkw8nYwf2JEeETo5o5W84DDfimfoBGP7RWPTPcTBKCaLQ==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -1782,9 +1782,9 @@
       }
     },
     "node_modules/@nomicfoundation/edr-linux-x64-gnu": {
-      "version": "0.11.0",
-      "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.11.0.tgz",
-      "integrity": "sha512-SmdncQHLYtVNWLIMyGaY6LpAfamzTDe3fxjkirmJv3CWR5tcEyC6LMui/GsIVnJzXeNJBXAzwl8hTUAxHTM6kQ==",
+      "version": "0.11.1",
+      "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.11.1.tgz",
+      "integrity": "sha512-V4Us7Q0E8kng3O/czd5GRcxmZxWX+USgqz9yQ3o7DVq7FP96idaKvtcbMQp64tjHf2zNtX2y77sGzgbVau7Bww==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -1792,9 +1792,9 @@
       }
     },
     "node_modules/@nomicfoundation/edr-linux-x64-musl": {
-      "version": "0.11.0",
-      "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.11.0.tgz",
-      "integrity": "sha512-w6hUqpn/trwiH6SRuRGysj37LsQVCX5XDCA3Xi81sbOaLhbHrNvK9TXWyZmcuzbdTKQQW6VNywcSxDdOiChcJg==",
+      "version": "0.11.1",
+      "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.11.1.tgz",
+      "integrity": "sha512-lCSXsF10Kjjvs5duGbM6pi1WciWHXFNWkMgDAY4pg6ZRIy4gh+uGC6CONMfP4BDZwfrALo2p6+LwyotrJEqpyg==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -1802,9 +1802,9 @@
       }
     },
     "node_modules/@nomicfoundation/edr-win32-x64-msvc": {
-      "version": "0.11.0",
-      "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.11.0.tgz",
-      "integrity": "sha512-BLmULjRKoH9BsX+c4Na2ypV7NGeJ+M6Zpqj/faPOwleVscDdSr/IhriyPaXCe8dyfwbge7lWsbekiADtPSnB2Q==",
+      "version": "0.11.1",
+      "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.11.1.tgz",
+      "integrity": "sha512-sNSmmRTURAd1sdKuyO5tqrFiJvHHVPZLM4HB53F21makGoyInFGhejdo3qZrkoinM8k0ewEJDbUp0YuMEgMOhQ==",
       "dev": true,
       "license": "MIT",
       "engines": {
@@ -1831,9 +1831,9 @@
       }
     },
     "node_modules/@nomicfoundation/hardhat-ethers": {
-      "version": "3.0.8",
-      "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.8.tgz",
-      "integrity": "sha512-zhOZ4hdRORls31DTOqg+GmEZM0ujly8GGIuRY7t7szEk2zW/arY1qDug/py8AEktT00v5K+b6RvbVog+va51IA==",
+      "version": "3.0.9",
+      "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.9.tgz",
+      "integrity": "sha512-xBJdRUiCwKpr0OYrOzPwAyNGtsVzoBx32HFPJVv6S+sFA9TmBIBDaqNlFPmBH58ZjgNnGhEr/4oBZvGr4q4TjQ==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -1841,14 +1841,14 @@
         "lodash.isequal": "^4.5.0"
       },
       "peerDependencies": {
-        "ethers": "^6.1.0",
+        "ethers": "^6.14.0",
         "hardhat": "^2.0.0"
       }
     },
     "node_modules/@nomicfoundation/hardhat-network-helpers": {
-      "version": "1.0.12",
-      "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.12.tgz",
-      "integrity": "sha512-xTNQNI/9xkHvjmCJnJOTyqDSl8uq1rKb2WOVmixQxFtRd7Oa3ecO8zM0cyC2YmOK+jHB9WPZ+F/ijkHg1CoORA==",
+      "version": "1.0.13",
+      "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.13.tgz",
+      "integrity": "sha512-ptg0+SH8jnfoYHlR3dKWTNTB43HZSxkuy3OeDk+AufEKQvQ7Ru9LQEbJtLuDTQ4HGRBkhl4oJ9RABsEIbn7Taw==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
@@ -2810,6 +2810,22 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/available-typed-arrays": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+      "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "possible-typed-array-names": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/axios": {
       "version": "1.9.0",
       "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz",
@@ -3089,6 +3105,25 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/call-bind": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
+      "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.0",
+        "es-define-property": "^1.0.0",
+        "get-intrinsic": "^1.2.4",
+        "set-function-length": "^1.2.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/call-bind-apply-helpers": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
@@ -3103,6 +3138,23 @@
         "node": ">= 0.4"
       }
     },
+    "node_modules/call-bound": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+      "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.2",
+        "get-intrinsic": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/callsites": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -3815,6 +3867,24 @@
         "node": ">=10"
       }
     },
+    "node_modules/define-data-property": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+      "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "es-define-property": "^1.0.0",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/delayed-stream": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -4859,6 +4929,22 @@
         }
       }
     },
+    "node_modules/for-each": {
+      "version": "0.3.5",
+      "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+      "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "is-callable": "^1.2.7"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/foreground-child": {
       "version": "3.3.1",
       "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
@@ -5350,15 +5436,15 @@
       }
     },
     "node_modules/hardhat": {
-      "version": "2.24.0",
-      "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.24.0.tgz",
-      "integrity": "sha512-wDkD5GPmttYv21MR7tGDkyQ22tO2V86OEV8pA7NcXWYUpibe8XZ2EanXCeRHO61vwEx0f7/M+NqrhJwasaNMJg==",
+      "version": "2.24.3",
+      "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.24.3.tgz",
+      "integrity": "sha512-2dhniQ1wW8/Wh3mP91kKcEnVva93mWYRaYLkV+a0ATkUEKrByGF2P5hCrlNHbqYP//D7L0CGYLtDjPQY6ILaVA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
         "@ethereumjs/util": "^9.1.0",
         "@ethersproject/abi": "^5.1.2",
-        "@nomicfoundation/edr": "^0.11.0",
+        "@nomicfoundation/edr": "^0.11.1",
         "@nomicfoundation/solidity-analyzer": "^0.1.0",
         "@sentry/node": "^5.18.1",
         "@types/bn.js": "^5.1.0",
@@ -5995,6 +6081,19 @@
         "node": ">=8"
       }
     },
+    "node_modules/has-property-descriptors": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+      "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "es-define-property": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/has-symbols": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
@@ -6325,6 +6424,19 @@
         "node": ">=8"
       }
     },
+    "node_modules/is-callable": {
+      "version": "1.2.7",
+      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+      "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/is-extglob": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -6415,6 +6527,22 @@
         "node": ">=4"
       }
     },
+    "node_modules/is-typed-array": {
+      "version": "1.1.15",
+      "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
+      "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "which-typed-array": "^1.1.16"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/is-unicode-supported": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
@@ -6438,6 +6566,13 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/isarray": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+      "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+      "dev": true,
+      "license": "MIT"
+    },
     "node_modules/isexe": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -8048,22 +8183,57 @@
       }
     },
     "node_modules/pbkdf2": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz",
-      "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==",
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.3.tgz",
+      "integrity": "sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==",
       "dev": true,
       "license": "MIT",
       "dependencies": {
-        "create-hash": "^1.1.2",
-        "create-hmac": "^1.1.4",
-        "ripemd160": "^2.0.1",
-        "safe-buffer": "^5.0.1",
-        "sha.js": "^2.4.8"
+        "create-hash": "~1.1.3",
+        "create-hmac": "^1.1.7",
+        "ripemd160": "=2.0.1",
+        "safe-buffer": "^5.2.1",
+        "sha.js": "^2.4.11",
+        "to-buffer": "^1.2.0"
       },
       "engines": {
         "node": ">=0.12"
       }
     },
+    "node_modules/pbkdf2/node_modules/create-hash": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz",
+      "integrity": "sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "cipher-base": "^1.0.1",
+        "inherits": "^2.0.1",
+        "ripemd160": "^2.0.0",
+        "sha.js": "^2.4.0"
+      }
+    },
+    "node_modules/pbkdf2/node_modules/hash-base": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz",
+      "integrity": "sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "inherits": "^2.0.1"
+      }
+    },
+    "node_modules/pbkdf2/node_modules/ripemd160": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz",
+      "integrity": "sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "hash-base": "^2.0.0",
+        "inherits": "^2.0.1"
+      }
+    },
     "node_modules/picocolors": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -8127,6 +8297,16 @@
         "node": ">=12.0.0"
       }
     },
+    "node_modules/possible-typed-array-names": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
+      "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
     "node_modules/prelude-ls": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -8874,6 +9054,24 @@
         "randombytes": "^2.1.0"
       }
     },
+    "node_modules/set-function-length": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+      "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "define-data-property": "^1.1.4",
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2",
+        "get-intrinsic": "^1.2.4",
+        "gopd": "^1.0.1",
+        "has-property-descriptors": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
     "node_modules/setimmediate": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
@@ -10026,6 +10224,21 @@
         "node": ">=0.6.0"
       }
     },
+    "node_modules/to-buffer": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz",
+      "integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "isarray": "^2.0.5",
+        "safe-buffer": "^5.2.1",
+        "typed-array-buffer": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
     "node_modules/to-regex-range": {
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -10106,6 +10319,21 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/typed-array-buffer": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
+      "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "call-bound": "^1.0.3",
+        "es-errors": "^1.3.0",
+        "is-typed-array": "^1.1.14"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
     "node_modules/typed-regex": {
       "version": "0.0.8",
       "resolved": "https://registry.npmjs.org/typed-regex/-/typed-regex-0.0.8.tgz",
@@ -10445,6 +10673,28 @@
         "node": ">= 8"
       }
     },
+    "node_modules/which-typed-array": {
+      "version": "1.1.19",
+      "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
+      "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "available-typed-arrays": "^1.0.7",
+        "call-bind": "^1.0.8",
+        "call-bound": "^1.0.4",
+        "for-each": "^0.3.5",
+        "get-proto": "^1.0.1",
+        "gopd": "^1.2.0",
+        "has-tostringtag": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/widest-line": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz",

+ 6 - 5
package.json

@@ -24,11 +24,12 @@
     "clean": "hardhat clean && rimraf build contracts/build",
     "prepack": "scripts/prepack.sh",
     "generate": "scripts/generate/run.js",
+    "pragma": "npm run compile && scripts/minimize-pragma.js artifacts/build-info/*",
     "version": "scripts/release/version.sh",
     "test": ". scripts/set-max-old-space-size.sh && hardhat test",
     "test:generation": "scripts/checks/generation.sh",
-    "test:inheritance": "scripts/checks/inheritance-ordering.js artifacts/build-info/*",
-    "test:pragma": "scripts/checks/pragma-validity.js artifacts/build-info/*",
+    "test:inheritance": "npm run compile && scripts/checks/inheritance-ordering.js artifacts/build-info/*",
+    "test:pragma": "npm run compile && scripts/checks/pragma-validity.js artifacts/build-info/*",
     "gas-report": "env ENABLE_GAS_REPORT=true npm run test",
     "slither": "npm run clean && slither ."
   },
@@ -57,8 +58,8 @@
     "@changesets/read": "^0.6.0",
     "@eslint/compat": "^1.2.1",
     "@nomicfoundation/hardhat-chai-matchers": "^2.0.6",
-    "@nomicfoundation/hardhat-ethers": "^3.0.4",
-    "@nomicfoundation/hardhat-network-helpers": "^1.0.3",
+    "@nomicfoundation/hardhat-ethers": "^3.0.9",
+    "@nomicfoundation/hardhat-network-helpers": "^1.0.13",
     "@openzeppelin/docs-utils": "^0.1.5",
     "@openzeppelin/merkle-tree": "^1.0.7",
     "@openzeppelin/upgrade-safe-transpiler": "^0.3.32",
@@ -70,7 +71,7 @@
     "glob": "^11.0.0",
     "globals": "^16.0.0",
     "graphlib": "^2.1.8",
-    "hardhat": "^2.24.0",
+    "hardhat": "^2.24.3",
     "hardhat-exposed": "^0.3.15",
     "hardhat-gas-reporter": "^2.1.0",
     "hardhat-ignore-warnings": "^0.2.11",

+ 138 - 0
scripts/minimize-pragma.js

@@ -0,0 +1,138 @@
+#!/usr/bin/env node
+
+const fs = require('fs');
+const graphlib = require('graphlib');
+const semver = require('semver');
+const pLimit = require('p-limit').default;
+const { hideBin } = require('yargs/helpers');
+const yargs = require('yargs/yargs');
+
+const getContractsMetadata = require('./get-contracts-metadata');
+const { versions: allSolcVersions, compile } = require('./solc-versions');
+
+const {
+  argv: { pattern, skipPatterns, minVersionForContracts, minVersionForInterfaces, concurrency, _: artifacts },
+} = yargs(hideBin(process.argv))
+  .env('')
+  .options({
+    pattern: { alias: 'p', type: 'string', default: 'contracts/**/*.sol' },
+    skipPatterns: { alias: 's', type: 'string', default: 'contracts/mocks/**/*.sol' },
+    minVersionForContracts: { type: 'string', default: '0.8.20' },
+    minVersionForInterfaces: { type: 'string', default: '0.0.0' },
+    concurrency: { alias: 'c', type: 'number', default: 8 },
+  });
+
+// limit concurrency
+const limit = pLimit(concurrency);
+
+/********************************************************************************************************************
+ *                                                     HELPERS                                                      *
+ ********************************************************************************************************************/
+
+/**
+ * Updates the pragma in the given file to the newPragma version.
+ * @param {*} file Absolute path to the file to update.
+ * @param {*} pragma New pragma version to set. (ex: '>=0.8.4')
+ */
+const updatePragma = (file, pragma) =>
+  fs.writeFileSync(
+    file,
+    fs.readFileSync(file, 'utf8').replace(/pragma solidity [><=^]*[0-9]+.[0-9]+.[0-9]+;/, `pragma solidity ${pragma};`),
+    'utf8',
+  );
+
+/**
+ * Get the applicable pragmas for a given file by compiling it with all solc versions.
+ * @param {*} file Absolute path to the file to compile.
+ * @param {*} candidates List of solc version to test. (ex: ['0.8.4','0.8.5'])
+ * @returns {Promise<string[]>} List of applicable pragmas.
+ */
+const getApplicablePragmas = (file, candidates = allSolcVersions) =>
+  Promise.all(
+    candidates.map(version =>
+      limit(() =>
+        compile(file, version).then(
+          () => version,
+          () => null,
+        ),
+      ),
+    ),
+  ).then(versions => versions.filter(Boolean));
+
+/**
+ * Get the minimum applicable pragmas for a given file.
+ * @param {*} file Absolute path to the file to compile.
+ * @param {*} candidates List of solc version to test. (ex: ['0.8.4','0.8.5'])
+ * @returns {Promise<string>} Smallest applicable pragma out of the list.
+ */
+const getMinimalApplicablePragma = (file, candidates = allSolcVersions) =>
+  getApplicablePragmas(file, candidates).then(valid => {
+    if (valid.length == 0) {
+      throw new Error(`No valid pragma found for ${file}`);
+    } else {
+      return valid.sort(semver.compare).at(0);
+    }
+  });
+
+/**
+ * Get the minimum applicable pragmas for a given file, and update the file to use it.
+ * @param {*} file Absolute path to the file to compile.
+ * @param {*} candidates List of solc version to test. (ex: ['0.8.4','0.8.5'])
+ * @param {*} prefix Prefix to use when building the pragma (ex: '^')
+ * @returns {Promise<string>} Version that was used and set in the file
+ */
+const setMinimalApplicablePragma = (file, candidates = allSolcVersions, prefix = '>=') =>
+  getMinimalApplicablePragma(file, candidates)
+    .then(version => `${prefix}${version}`)
+    .then(pragma => {
+      updatePragma(file, pragma);
+      return pragma;
+    });
+
+/********************************************************************************************************************
+ *                                                       MAIN                                                       *
+ ********************************************************************************************************************/
+
+// Build metadata from artifact files (hardhat compilation)
+const metadata = getContractsMetadata(pattern, skipPatterns, artifacts);
+
+// Build dependency graph
+const graph = new graphlib.Graph({ directed: true });
+Object.keys(metadata).forEach(file => {
+  graph.setNode(file);
+  metadata[file].sources.forEach(dep => graph.setEdge(dep, file));
+});
+
+// Weaken all pragma to allow exploration
+Object.keys(metadata).forEach(file => updatePragma(file, '>=0.0.0'));
+
+// Do a topological traversal of the dependency graph, minimizing pragma for each file we encounter
+(async () => {
+  const queue = graph.sources();
+  const pragmas = {};
+  while (queue.length) {
+    const file = queue.shift();
+    if (!Object.hasOwn(pragmas, file)) {
+      if (Object.hasOwn(metadata, file)) {
+        const minVersion = metadata[file].interface ? minVersionForInterfaces : minVersionForContracts;
+        const parentsPragmas = graph
+          .predecessors(file)
+          .map(file => pragmas[file])
+          .filter(Boolean);
+        const candidates = allSolcVersions.filter(
+          v => semver.gte(v, minVersion) && parentsPragmas.every(p => semver.satisfies(v, p)),
+        );
+        const pragmaPrefix = metadata[file].interface ? '>=' : '^';
+
+        process.stdout.write(
+          `[${Object.keys(pragmas).length + 1}/${Object.keys(metadata).length}] Searching minimal version for ${file} ... `,
+        );
+        const pragma = await setMinimalApplicablePragma(file, candidates, pragmaPrefix);
+        console.log(pragma);
+
+        pragmas[file] = pragma;
+      }
+      queue.push(...graph.successors(file));
+    }
+  }
+})();

+ 7 - 2
test/account/AccountMultiSigner.test.js

@@ -176,9 +176,14 @@ describe('AccountMultiSigner', function () {
       await expect(this.mock.$_setThreshold(2)).to.emit(this.mock, 'ERC7913ThresholdSet');
 
       // Unreachable threshold reverts
-      await expect(this.mock.$_setThreshold(3)).to.revertedWithCustomError(
+      await expect(this.mock.$_setThreshold(3))
+        .to.revertedWithCustomError(this.mock, 'MultiSignerERC7913UnreachableThreshold')
+        .withArgs(2, 3);
+
+      // Zero threshold reverts
+      await expect(this.mock.$_setThreshold(0)).to.revertedWithCustomError(
         this.mock,
-        'MultiSignerERC7913UnreachableThreshold',
+        'MultiSignerERC7913ZeroThreshold',
       );
     });
 

+ 4 - 6
test/utils/Blockhash.test.js

@@ -1,9 +1,8 @@
-const { ethers, network } = require('hardhat');
+const { ethers, eip2935 } = require('hardhat');
 const { expect } = require('chai');
-const { loadFixture, mineUpTo } = require('@nomicfoundation/hardhat-network-helpers');
+const { loadFixture, mineUpTo, setCode } = require('@nomicfoundation/hardhat-network-helpers');
 const { impersonate } = require('../helpers/account');
 
-const HISTORY_STORAGE_ADDRESS = '0x0000F90827F1C53a10cb7A02335B175320002935';
 const SYSTEM_ADDRESS = '0xfffffffffffffffffffffffffffffffffffffffe';
 const HISTORY_SERVE_WINDOW = 8191;
 const BLOCKHASH_SERVE_WINDOW = 256;
@@ -25,10 +24,9 @@ describe('Blockhash', function () {
     describe(`${supported ? 'supported' : 'unsupported'} chain`, function () {
       beforeEach(async function () {
         if (supported) {
-          await this.systemSigner.sendTransaction({ to: HISTORY_STORAGE_ADDRESS, data: this.latestBlock.hash });
+          await this.systemSigner.sendTransaction({ to: eip2935, data: this.latestBlock.hash });
         } else {
-          // `setCode` in hardhat-network-helpers doesn't support empty code :/
-          await network.provider.request({ method: 'hardhat_setCode', params: [HISTORY_STORAGE_ADDRESS, '0x'] });
+          await setCode(eip2935.target, '0x');
         }
       });