From aafca7d59850d590a96129e501447e53701efb66 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 28 Mar 2024 15:28:59 +0100 Subject: [PATCH 01/14] Add storage slot support in StorageSlot.sol --- .changeset/kind-planets-cough.md | 5 + contracts/utils/README.adoc | 2 +- contracts/utils/StorageSlot.sol | 178 ++++++++++++++++++ scripts/generate/templates/StorageSlot.js | 56 +++++- scripts/helpers.js | 7 +- .../extensions/GovernorTimelockAccess.test.js | 2 +- test/helpers/strings.js | 5 + 7 files changed, 247 insertions(+), 8 deletions(-) create mode 100644 .changeset/kind-planets-cough.md create mode 100644 test/helpers/strings.js diff --git a/.changeset/kind-planets-cough.md b/.changeset/kind-planets-cough.md new file mode 100644 index 00000000000..988e24c4ad2 --- /dev/null +++ b/.changeset/kind-planets-cough.md @@ -0,0 +1,5 @@ +--- +'openzeppelin-solidity': minor +--- + +`StorageSlot`: Add primitives for operating on the transient storage space using a typed-slot representation. diff --git a/contracts/utils/README.adoc b/contracts/utils/README.adoc index 83ba6241414..2ab1fd981be 100644 --- a/contracts/utils/README.adoc +++ b/contracts/utils/README.adoc @@ -29,7 +29,7 @@ Miscellaneous contracts and libraries containing utility functions you can use t * {Strings}: Common operations for strings formatting. * {ShortString}: Library to encode (and decode) short strings into (or from) a single bytes32 slot for optimizing costs. Short strings are limited to 31 characters. * {SlotDerivation}: Methods for deriving storage slot from ERC-7201 namespaces as well as from constructions such as mapping and arrays. - * {StorageSlot}: Methods for accessing specific storage slots formatted as common primitive types. + * {StorageSlot}: Methods for accessing specific storage slots formatted as common primitive types. Also include primitives for reading to and writting from transient storage (only value types are currently supported). * {Multicall}: Abstract contract with an utility to allow batching together multiple calls in a single transaction. Useful for allowing EOAs to perform multiple operations at once. * {Context}: An utility for abstracting the sender and calldata in the current execution context. * {Panic}: A library to revert with https://docs.soliditylang.org/en/v0.8.20/control-structures.html#panic-via-assert-and-error-via-require[Solidity panic codes]. diff --git a/contracts/utils/StorageSlot.sol b/contracts/utils/StorageSlot.sol index bb54de13a1f..ccc0d1a4c1d 100644 --- a/contracts/utils/StorageSlot.sol +++ b/contracts/utils/StorageSlot.sol @@ -29,6 +29,24 @@ pragma solidity ^0.8.20; * } * ``` * + * Since version 5.1, this library also support writting and reading value types to and from transient storage. + * + * * Example usaging transiant storage: + * ```solidity + * contract Lock { + * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot. + * bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542; + * + * modifier locked() { + * require(!_LOCK_SLOT.asBoolean().tload()); + * + * _LOCK_SLOT.asBoolean().tstore(true); + * _; + * _LOCK_SLOT.asBoolean().tstore(false); + * } + * } + * ``` + * * TIP: Consider using this library along with {SlotDerivation}. */ library StorageSlot { @@ -149,4 +167,164 @@ library StorageSlot { r.slot := store.slot } } + + /** + * @dev UDVT that represent a slot holding a address. + */ + type AddressSlotType is bytes32; + + /** + * @dev Cast an arbitrary slot to a AddressSlotType. + */ + function asAddress(bytes32 slot) internal pure returns (AddressSlotType) { + return AddressSlotType.wrap(slot); + } + + /** + * @dev UDVT that represent a slot holding a bool. + */ + type BooleanSlotType is bytes32; + + /** + * @dev Cast an arbitrary slot to a BooleanSlotType. + */ + function asBoolean(bytes32 slot) internal pure returns (BooleanSlotType) { + return BooleanSlotType.wrap(slot); + } + + /** + * @dev UDVT that represent a slot holding a bytes32. + */ + type Bytes32SlotType is bytes32; + + /** + * @dev Cast an arbitrary slot to a Bytes32SlotType. + */ + function asBytes32(bytes32 slot) internal pure returns (Bytes32SlotType) { + return Bytes32SlotType.wrap(slot); + } + + /** + * @dev UDVT that represent a slot holding a uint256. + */ + type Uint256SlotType is bytes32; + + /** + * @dev Cast an arbitrary slot to a Uint256SlotType. + */ + function asUint256(bytes32 slot) internal pure returns (Uint256SlotType) { + return Uint256SlotType.wrap(slot); + } + + /** + * @dev UDVT that represent a slot holding a int256. + */ + type Int256SlotType is bytes32; + + /** + * @dev Cast an arbitrary slot to a Int256SlotType. + */ + function asInt256(bytes32 slot) internal pure returns (Int256SlotType) { + return Int256SlotType.wrap(slot); + } + + /** + * @dev Load the value held at location `slot` in transient storage. + */ + function tload(TypedSlot.AddressSlotType slot) internal view returns (address value) { + /// @solidity memory-safe-assembly + assembly { + value := tload(slot) + } + } + + /** + * @dev Store `value` at location `slot` in transient storage. + */ + function tstore(TypedSlot.AddressSlotType slot, address value) internal { + /// @solidity memory-safe-assembly + assembly { + tstore(slot, value) + } + } + + /** + * @dev Load the value held at location `slot` in transient storage. + */ + function tload(TypedSlot.BooleanSlotType slot) internal view returns (bool value) { + /// @solidity memory-safe-assembly + assembly { + value := tload(slot) + } + } + + /** + * @dev Store `value` at location `slot` in transient storage. + */ + function tstore(TypedSlot.BooleanSlotType slot, bool value) internal { + /// @solidity memory-safe-assembly + assembly { + tstore(slot, value) + } + } + + /** + * @dev Load the value held at location `slot` in transient storage. + */ + function tload(TypedSlot.Bytes32SlotType slot) internal view returns (bytes32 value) { + /// @solidity memory-safe-assembly + assembly { + value := tload(slot) + } + } + + /** + * @dev Store `value` at location `slot` in transient storage. + */ + function tstore(TypedSlot.Bytes32SlotType slot, bytes32 value) internal { + /// @solidity memory-safe-assembly + assembly { + tstore(slot, value) + } + } + + /** + * @dev Load the value held at location `slot` in transient storage. + */ + function tload(TypedSlot.Uint256SlotType slot) internal view returns (uint256 value) { + /// @solidity memory-safe-assembly + assembly { + value := tload(slot) + } + } + + /** + * @dev Store `value` at location `slot` in transient storage. + */ + function tstore(TypedSlot.Uint256SlotType slot, uint256 value) internal { + /// @solidity memory-safe-assembly + assembly { + tstore(slot, value) + } + } + + /** + * @dev Load the value held at location `slot` in transient storage. + */ + function tload(TypedSlot.Int256SlotType slot) internal view returns (int256 value) { + /// @solidity memory-safe-assembly + assembly { + value := tload(slot) + } + } + + /** + * @dev Store `value` at location `slot` in transient storage. + */ + function tstore(TypedSlot.Int256SlotType slot, int256 value) internal { + /// @solidity memory-safe-assembly + assembly { + tstore(slot, value) + } + } } diff --git a/scripts/generate/templates/StorageSlot.js b/scripts/generate/templates/StorageSlot.js index 80e5ab1395c..9d1f61f24e4 100644 --- a/scripts/generate/templates/StorageSlot.js +++ b/scripts/generate/templates/StorageSlot.js @@ -28,7 +28,25 @@ pragma solidity ^0.8.20; * } * } * \`\`\` - * + * + * Since version 5.1, this library also support writting and reading value types to and from transient storage. + * + * * Example usaging transiant storage: + * \`\`\`solidity + * contract Lock { + * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot. + * bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542; + * + * modifier locked() { + * require(!_LOCK_SLOT.asBoolean().tload()); + * + * _LOCK_SLOT.asBoolean().tstore(true); + * _; + * _LOCK_SLOT.asBoolean().tstore(false); + * } + * } + * \`\`\` + * * TIP: Consider using this library along with {SlotDerivation}. */ `; @@ -63,11 +81,47 @@ function get${name}Slot(${type} storage store) internal pure returns (${name}Slo } `; +const udvt = ({ type, name }) => `\ +/** + * @dev UDVT that represent a slot holding a ${type}. + */ +type ${name}SlotType is bytes32; +/** + * @dev Cast an arbitrary slot to a ${name}SlotType. + */ +function as${name}(bytes32 slot) internal pure returns (${name}SlotType) { + return ${name}SlotType.wrap(slot); +} +`; + +const transient = ({ type, name }) => `\ +/** + * @dev Load the value held at location \`slot\` in transient storage. + */ +function tload(TypedSlot.${name}SlotType slot) internal view returns (${type} value) { + /// @solidity memory-safe-assembly + assembly { + value := tload(slot) + } +} +/** + * @dev Store \`value\` at location \`slot\` in transient storage. + */ +function tstore(TypedSlot.${name}SlotType slot, ${type} value) internal { + /// @solidity memory-safe-assembly + assembly { + tstore(slot, value) + } +} +`; + // GENERATE module.exports = format( header.trimEnd(), 'library StorageSlot {', TYPES.map(type => struct(type)), TYPES.flatMap(type => [get(type), type.isValueType ? '' : getStorage(type)]), + TYPES.filter(type => type.isValueType).map(type => udvt(type)), + TYPES.filter(type => type.isValueType).map(type => transient(type)), '}', ); diff --git a/scripts/helpers.js b/scripts/helpers.js index 52102bdaf1b..d28c0866d1c 100644 --- a/scripts/helpers.js +++ b/scripts/helpers.js @@ -1,10 +1,7 @@ const iterate = require('../test/helpers/iterate'); +const strings = require('../test/helpers/strings'); module.exports = { - // Capitalize the first char of a string - // Example: capitalize('uint256') → 'Uint256' - capitalize: str => str.charAt(0).toUpperCase() + str.slice(1), - - // Iterate tools for the test helpers ...iterate, + ...strings, }; diff --git a/test/governance/extensions/GovernorTimelockAccess.test.js b/test/governance/extensions/GovernorTimelockAccess.test.js index 72394e92822..c3d3b32684e 100644 --- a/test/governance/extensions/GovernorTimelockAccess.test.js +++ b/test/governance/extensions/GovernorTimelockAccess.test.js @@ -375,7 +375,7 @@ describe('GovernorTimelockAccess', function () { if (delay > 0) { await this.helper.waitForEta(); } - expect(await this.helper.execute()) + await expect(this.helper.execute()) .to.emit(this.mock, 'ProposalExecuted') .withArgs(this.proposal.id) .to.emit(this.receiver, 'CalledUnrestricted'); diff --git a/test/helpers/strings.js b/test/helpers/strings.js new file mode 100644 index 00000000000..4f34099d7df --- /dev/null +++ b/test/helpers/strings.js @@ -0,0 +1,5 @@ +module.exports = { + // Capitalize the first char of a string + // Example: capitalize('uint256') → 'Uint256' + capitalize: str => str.charAt(0).toUpperCase() + str.slice(1), +}; From 8b8f2c5e224c6a66c450a790de050c6fec84672d Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 28 Mar 2024 15:37:08 +0100 Subject: [PATCH 02/14] update dependencies --- contracts/utils/StorageSlot.sol | 20 +- foundry.toml | 2 + hardhat.config.js | 12 +- package-lock.json | 1101 +++++++++------------ package.json | 4 +- scripts/generate/templates/StorageSlot.js | 6 +- 6 files changed, 480 insertions(+), 665 deletions(-) diff --git a/contracts/utils/StorageSlot.sol b/contracts/utils/StorageSlot.sol index ccc0d1a4c1d..52f50adde6c 100644 --- a/contracts/utils/StorageSlot.sol +++ b/contracts/utils/StorageSlot.sol @@ -231,7 +231,7 @@ library StorageSlot { /** * @dev Load the value held at location `slot` in transient storage. */ - function tload(TypedSlot.AddressSlotType slot) internal view returns (address value) { + function tload(AddressSlotType slot) internal view returns (address value) { /// @solidity memory-safe-assembly assembly { value := tload(slot) @@ -241,7 +241,7 @@ library StorageSlot { /** * @dev Store `value` at location `slot` in transient storage. */ - function tstore(TypedSlot.AddressSlotType slot, address value) internal { + function tstore(AddressSlotType slot, address value) internal { /// @solidity memory-safe-assembly assembly { tstore(slot, value) @@ -251,7 +251,7 @@ library StorageSlot { /** * @dev Load the value held at location `slot` in transient storage. */ - function tload(TypedSlot.BooleanSlotType slot) internal view returns (bool value) { + function tload(BooleanSlotType slot) internal view returns (bool value) { /// @solidity memory-safe-assembly assembly { value := tload(slot) @@ -261,7 +261,7 @@ library StorageSlot { /** * @dev Store `value` at location `slot` in transient storage. */ - function tstore(TypedSlot.BooleanSlotType slot, bool value) internal { + function tstore(BooleanSlotType slot, bool value) internal { /// @solidity memory-safe-assembly assembly { tstore(slot, value) @@ -271,7 +271,7 @@ library StorageSlot { /** * @dev Load the value held at location `slot` in transient storage. */ - function tload(TypedSlot.Bytes32SlotType slot) internal view returns (bytes32 value) { + function tload(Bytes32SlotType slot) internal view returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { value := tload(slot) @@ -281,7 +281,7 @@ library StorageSlot { /** * @dev Store `value` at location `slot` in transient storage. */ - function tstore(TypedSlot.Bytes32SlotType slot, bytes32 value) internal { + function tstore(Bytes32SlotType slot, bytes32 value) internal { /// @solidity memory-safe-assembly assembly { tstore(slot, value) @@ -291,7 +291,7 @@ library StorageSlot { /** * @dev Load the value held at location `slot` in transient storage. */ - function tload(TypedSlot.Uint256SlotType slot) internal view returns (uint256 value) { + function tload(Uint256SlotType slot) internal view returns (uint256 value) { /// @solidity memory-safe-assembly assembly { value := tload(slot) @@ -301,7 +301,7 @@ library StorageSlot { /** * @dev Store `value` at location `slot` in transient storage. */ - function tstore(TypedSlot.Uint256SlotType slot, uint256 value) internal { + function tstore(Uint256SlotType slot, uint256 value) internal { /// @solidity memory-safe-assembly assembly { tstore(slot, value) @@ -311,7 +311,7 @@ library StorageSlot { /** * @dev Load the value held at location `slot` in transient storage. */ - function tload(TypedSlot.Int256SlotType slot) internal view returns (int256 value) { + function tload(Int256SlotType slot) internal view returns (int256 value) { /// @solidity memory-safe-assembly assembly { value := tload(slot) @@ -321,7 +321,7 @@ library StorageSlot { /** * @dev Store `value` at location `slot` in transient storage. */ - function tstore(TypedSlot.Int256SlotType slot, int256 value) internal { + function tstore(Int256SlotType slot, int256 value) internal { /// @solidity memory-safe-assembly assembly { tstore(slot, value) diff --git a/foundry.toml b/foundry.toml index cf207ffe984..391c40e6f11 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,4 +1,6 @@ [profile.default] +solc_version = '0.8.24' +evm_version = 'cancun' src = 'contracts' out = 'out' libs = ['node_modules', 'lib'] diff --git a/hardhat.config.js b/hardhat.config.js index b91a8865836..9bfc5e3d496 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -18,7 +18,7 @@ const { argv } = require('yargs/yargs')() compiler: { alias: 'compileVersion', type: 'string', - default: '0.8.20', + default: '0.8.24', }, src: { alias: 'source', @@ -36,6 +36,11 @@ const { argv } = require('yargs/yargs')() type: 'boolean', default: false, }, + evm: { + alias: 'evmVersion', + type: 'string', + default: 'cancun', + }, // Extra modules coverage: { type: 'boolean', @@ -78,6 +83,7 @@ module.exports = { enabled: withOptimizations, runs: 200, }, + evmVersion: argv.evm, viaIR: withOptimizations && argv.ir, outputSelection: { '*': { '*': ['storageLayout'] } }, }, @@ -90,11 +96,13 @@ module.exports = { '*': { 'code-size': withOptimizations, 'unused-param': !argv.coverage, // coverage causes unused-param warnings + 'transient-storage': false, default: 'error', }, }, networks: { hardhat: { + hardfork: argv.evm, allowUnlimitedContractSize, initialBaseFeePerGas: argv.coverage ? 0 : undefined, }, @@ -102,7 +110,7 @@ module.exports = { exposed: { imports: true, initializers: true, - exclude: ['vendor/**/*', '**/*WithInit.sol'], + exclude: ['vendor/**/*', '**/*WithInit.sol', 'utils/TransientSlot.sol'], }, gasReporter: { enabled: argv.gas, diff --git a/package-lock.json b/package-lock.json index 0fce44f1f07..46b1909e986 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,10 +26,10 @@ "ethers": "^6.7.1", "glob": "^10.3.5", "graphlib": "^2.1.8", - "hardhat": "^2.17.4", + "hardhat": "^2.22.2", "hardhat-exposed": "^0.3.14-0", "hardhat-gas-reporter": "^1.0.9", - "hardhat-ignore-warnings": "^0.2.0", + "hardhat-ignore-warnings": "^0.2.11", "lodash.startcase": "^4.4.0", "micromatch": "^4.0.2", "p-limit": "^3.1.0", @@ -109,32 +109,6 @@ "node": ">=6.9.0" } }, - "node_modules/@chainsafe/as-sha256": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz", - "integrity": "sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg==", - "dev": true - }, - "node_modules/@chainsafe/persistent-merkle-tree": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.4.2.tgz", - "integrity": "sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ==", - "dev": true, - "dependencies": { - "@chainsafe/as-sha256": "^0.3.1" - } - }, - "node_modules/@chainsafe/ssz": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.9.4.tgz", - "integrity": "sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ==", - "dev": true, - "dependencies": { - "@chainsafe/as-sha256": "^0.3.1", - "@chainsafe/persistent-merkle-tree": "^0.4.2", - "case": "^1.6.3" - } - }, "node_modules/@changesets/apply-release-plan": { "version": "6.1.4", "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-6.1.4.tgz", @@ -1779,304 +1753,233 @@ "node": ">= 8" } }, - "node_modules/@nomicfoundation/ethereumjs-block": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.2.tgz", - "integrity": "sha512-hSe6CuHI4SsSiWWjHDIzWhSiAVpzMUcDRpWYzN0T9l8/Rz7xNn3elwVOJ/tAyS0LqL6vitUD78Uk7lQDXZun7Q==", + "node_modules/@nomicfoundation/edr": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.3.3.tgz", + "integrity": "sha512-zP+e+3B1nEUx6bW5BPnIzCQbkhmYfdMBJdiVggTqqTfAA82sOkdOG7wsOMcz5qF3fYfx/irNRM1kgc9HVFIbpQ==", "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-trie": "6.0.2", - "@nomicfoundation/ethereumjs-tx": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "ethereum-cryptography": "0.1.3", - "ethers": "^5.7.1" + "engines": { + "node": ">= 18" }, + "optionalDependencies": { + "@nomicfoundation/edr-darwin-arm64": "0.3.3", + "@nomicfoundation/edr-darwin-x64": "0.3.3", + "@nomicfoundation/edr-linux-arm64-gnu": "0.3.3", + "@nomicfoundation/edr-linux-arm64-musl": "0.3.3", + "@nomicfoundation/edr-linux-x64-gnu": "0.3.3", + "@nomicfoundation/edr-linux-x64-musl": "0.3.3", + "@nomicfoundation/edr-win32-arm64-msvc": "0.3.3", + "@nomicfoundation/edr-win32-ia32-msvc": "0.3.3", + "@nomicfoundation/edr-win32-x64-msvc": "0.3.3" + } + }, + "node_modules/@nomicfoundation/edr-darwin-arm64": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.3.3.tgz", + "integrity": "sha512-E9VGsUD+1Ga4mn/5ooHsMi8JEfhZbKP6CXN/BhJ8kXbIC10NqTD1RuhCKGRtYq4vqH/3Nfq25Xg8E8RWOF4KBQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=14" + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-block/node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "node_modules/@nomicfoundation/edr-darwin-x64": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.3.3.tgz", + "integrity": "sha512-vkZXZ1ydPg+Ijb2iyqENA+KCkxGTCUWG5itCSliiA0Li2YE7ujDMGhheEpFp1WVlZadviz0bfk1rZXbCqlirpg==", + "cpu": [ + "x64" + ], "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "optional": true, + "os": [ + "darwin" ], - "dependencies": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" + "engines": { + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-blockchain": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.2.tgz", - "integrity": "sha512-8UUsSXJs+MFfIIAKdh3cG16iNmWzWC/91P40sazNvrqhhdR/RtGDlFk2iFTGbBAZPs2+klZVzhRX8m2wvuvz3w==", + "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.3.3.tgz", + "integrity": "sha512-gdIg0Yj1qqS9wVuywc5B/+DqKylfUGB6/CQn/shMqwAfsAVAVpchkhy66PR+REEx7fh/GkNctxLlENXPeLzDiA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-block": "5.0.2", - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-ethash": "3.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-trie": "6.0.2", - "@nomicfoundation/ethereumjs-tx": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "abstract-level": "^1.0.3", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "level": "^8.0.0", - "lru-cache": "^5.1.1", - "memory-level": "^1.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-common": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.2.tgz", - "integrity": "sha512-I2WGP3HMGsOoycSdOTSqIaES0ughQTueOsddJ36aYVpI3SN8YSusgRFLwzDJwRFVIYDKx/iJz0sQ5kBHVgdDwg==", + "node_modules/@nomicfoundation/edr-linux-arm64-musl": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.3.3.tgz", + "integrity": "sha512-AXZ08MFvhNeBZbOBNmz1SJ/DMrMOE2mHEJtaNnsctlxIunjxfrWww4q+WXB34jbr9iaVYYlPsaWe5sueuw6s3Q==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-util": "9.0.2", - "crc-32": "^1.2.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-ethash": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.2.tgz", - "integrity": "sha512-8PfoOQCcIcO9Pylq0Buijuq/O73tmMVURK0OqdjhwqcGHYC2PwhbajDh7GZ55ekB0Px197ajK3PQhpKoiI/UPg==", + "node_modules/@nomicfoundation/edr-linux-x64-gnu": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.3.3.tgz", + "integrity": "sha512-xElOs1U+E6lBLtv1mnJ+E8nr2MxZgKiLo8bZAgBboy9odYtmkDVwhMjtsFKSuZbGxFtsSyGRT4cXw3JAbtUDeA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-block": "5.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "abstract-level": "^1.0.3", - "bigint-crypto-utils": "^3.0.23", - "ethereum-cryptography": "0.1.3" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-evm": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.2.tgz", - "integrity": "sha512-rBLcUaUfANJxyOx9HIdMX6uXGin6lANCulIm/pjMgRqfiCRMZie3WKYxTSd8ZE/d+qT+zTedBF4+VHTdTSePmQ==", + "node_modules/@nomicfoundation/edr-linux-x64-musl": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.3.3.tgz", + "integrity": "sha512-2Fe6gwm1RAGQ/PfMYiaSba2OrFp8zzYWh+am9lYObOFjV9D+A1zhIzfy0UC74glPks5eV8eY4pBPrVR042m2Nw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@ethersproject/providers": "^5.7.1", - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-tx": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "mcl-wasm": "^0.7.1", - "rustbn.js": "~0.2.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-rlp": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.2.tgz", - "integrity": "sha512-QwmemBc+MMsHJ1P1QvPl8R8p2aPvvVcKBbvHnQOKBpBztEo0omN0eaob6FeZS/e3y9NSe+mfu3nNFBHszqkjTA==", + "node_modules/@nomicfoundation/edr-win32-arm64-msvc": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-arm64-msvc/-/edr-win32-arm64-msvc-0.3.3.tgz", + "integrity": "sha512-8NHyxIsFrl0ufSQ/ErqF2lKIa/gz1gaaa1a2vKkDEqvqCUcPhBTYhA5NHgTPhLETFTnCFr0z+YbctFCyjh4qrA==", + "cpu": [ + "arm64" + ], "dev": true, - "bin": { - "rlp": "bin/rlp" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=14" + "node": ">= 10" } }, - "node_modules/@nomicfoundation/ethereumjs-statemanager": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.2.tgz", - "integrity": "sha512-dlKy5dIXLuDubx8Z74sipciZnJTRSV/uHG48RSijhgm1V7eXYFC567xgKtsKiVZB1ViTP9iFL4B6Je0xD6X2OA==", + "node_modules/@nomicfoundation/edr-win32-ia32-msvc": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-ia32-msvc/-/edr-win32-ia32-msvc-0.3.3.tgz", + "integrity": "sha512-0F6hM0kGia4dQVb/kauho9JcP1ozWisY2/She+ISR5ceuhzmAwQJluM0g+0TYDME0LtxBxiMPq/yPiZMQeq31w==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "ethers": "^5.7.1", - "js-sdsl": "^4.1.4" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-statemanager/node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "node_modules/@nomicfoundation/edr-win32-x64-msvc": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.3.3.tgz", + "integrity": "sha512-d75q1uaMb6z9i+GQZoblbOfFBvlBnWc+5rB13UWRkCOJSnoYwyFWhGJx5GeM59gC7aIblc5VD9qOAhHuvM9N+w==", + "cpu": [ + "x64" + ], "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } + "optional": true, + "os": [ + "win32" ], - "dependencies": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" + "engines": { + "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-trie": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.2.tgz", - "integrity": "sha512-yw8vg9hBeLYk4YNg5MrSJ5H55TLOv2FSWUTROtDtTMMmDGROsAu+0tBjiNGTnKRi400M6cEzoFfa89Fc5k8NTQ==", + "node_modules/@nomicfoundation/ethereumjs-common": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz", + "integrity": "sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==", "dev": true, "dependencies": { - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "@types/readable-stream": "^2.3.13", - "ethereum-cryptography": "0.1.3", - "readable-stream": "^3.6.0" + "@nomicfoundation/ethereumjs-util": "9.0.4" + } + }, + "node_modules/@nomicfoundation/ethereumjs-rlp": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz", + "integrity": "sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==", + "dev": true, + "bin": { + "rlp": "bin/rlp.cjs" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/@nomicfoundation/ethereumjs-tx": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.2.tgz", - "integrity": "sha512-T+l4/MmTp7VhJeNloMkM+lPU3YMUaXdcXgTGCf8+ZFvV9NYZTRLFekRwlG6/JMmVfIfbrW+dRRJ9A6H5Q/Z64g==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz", + "integrity": "sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==", "dev": true, "dependencies": { - "@chainsafe/ssz": "^0.9.2", - "@ethersproject/providers": "^5.7.2", - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", + "@nomicfoundation/ethereumjs-common": "4.0.4", + "@nomicfoundation/ethereumjs-rlp": "5.0.4", + "@nomicfoundation/ethereumjs-util": "9.0.4", "ethereum-cryptography": "0.1.3" }, "engines": { - "node": ">=14" + "node": ">=18" + }, + "peerDependencies": { + "c-kzg": "^2.1.2" + }, + "peerDependenciesMeta": { + "c-kzg": { + "optional": true + } } }, "node_modules/@nomicfoundation/ethereumjs-util": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.2.tgz", - "integrity": "sha512-4Wu9D3LykbSBWZo8nJCnzVIYGvGCuyiYLIJa9XXNVt1q1jUzHdB+sJvx95VGCpPkCT+IbLecW6yfzy3E1bQrwQ==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz", + "integrity": "sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==", "dev": true, "dependencies": { - "@chainsafe/ssz": "^0.10.0", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", + "@nomicfoundation/ethereumjs-rlp": "5.0.4", "ethereum-cryptography": "0.1.3" }, "engines": { - "node": ">=14" - } - }, - "node_modules/@nomicfoundation/ethereumjs-util/node_modules/@chainsafe/persistent-merkle-tree": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.5.0.tgz", - "integrity": "sha512-l0V1b5clxA3iwQLXP40zYjyZYospQLZXzBVIhhr9kDg/1qHZfzzHw0jj4VPBijfYCArZDlPkRi1wZaV2POKeuw==", - "dev": true, - "dependencies": { - "@chainsafe/as-sha256": "^0.3.1" - } - }, - "node_modules/@nomicfoundation/ethereumjs-util/node_modules/@chainsafe/ssz": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.10.2.tgz", - "integrity": "sha512-/NL3Lh8K+0q7A3LsiFq09YXS9fPE+ead2rr7vM2QK8PLzrNsw3uqrif9bpRX5UxgeRjM+vYi+boCM3+GM4ovXg==", - "dev": true, - "dependencies": { - "@chainsafe/as-sha256": "^0.3.1", - "@chainsafe/persistent-merkle-tree": "^0.5.0" - } - }, - "node_modules/@nomicfoundation/ethereumjs-vm": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.2.tgz", - "integrity": "sha512-Bj3KZT64j54Tcwr7Qm/0jkeZXJMfdcAtRBedou+Hx0dPOSIgqaIr0vvLwP65TpHbak2DmAq+KJbW2KNtIoFwvA==", - "dev": true, - "dependencies": { - "@nomicfoundation/ethereumjs-block": "5.0.2", - "@nomicfoundation/ethereumjs-blockchain": "7.0.2", - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-evm": "2.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-statemanager": "2.0.2", - "@nomicfoundation/ethereumjs-trie": "6.0.2", - "@nomicfoundation/ethereumjs-tx": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "mcl-wasm": "^0.7.1", - "rustbn.js": "~0.2.0" + "node": ">=18" }, - "engines": { - "node": ">=14" + "peerDependencies": { + "c-kzg": "^2.1.2" + }, + "peerDependenciesMeta": { + "c-kzg": { + "optional": true + } } }, "node_modules/@nomicfoundation/hardhat-chai-matchers": { @@ -2930,22 +2833,6 @@ "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==", "dev": true }, - "node_modules/@types/readable-stream": { - "version": "2.3.15", - "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.15.tgz", - "integrity": "sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "safe-buffer": "~5.1.1" - } - }, - "node_modules/@types/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "node_modules/@types/secp256k1": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.3.tgz", @@ -2967,48 +2854,6 @@ "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==", "dev": true }, - "node_modules/abstract-level": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.3.tgz", - "integrity": "sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA==", - "dev": true, - "dependencies": { - "buffer": "^6.0.3", - "catering": "^2.1.0", - "is-buffer": "^2.0.5", - "level-supports": "^4.0.0", - "level-transcoder": "^1.0.1", - "module-error": "^1.0.1", - "queue-microtask": "^1.2.3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/abstract-level/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -3110,6 +2955,59 @@ "node": ">=0.4.2" } }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-align/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-align/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-align/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -3404,26 +3302,6 @@ "safe-buffer": "^5.0.1" } }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/bech32": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", @@ -3442,15 +3320,6 @@ "node": ">=4" } }, - "node_modules/bigint-crypto-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/bigint-crypto-utils/-/bigint-crypto-utils-3.3.0.tgz", - "integrity": "sha512-jOTSb+drvEDxEq6OuUybOAv/xxoh3cuYRUIPyu8sSHQNKM303UQ2R1DAo45o1AkcIXw6fzbaFI1+xGGdaXs2lg==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -3472,6 +3341,142 @@ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true }, + "node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/boxen/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/boxen/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/boxen/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/boxen/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/boxen/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/boxen/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/boxen/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/boxen/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/boxen/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3509,18 +3514,6 @@ "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", "dev": true }, - "node_modules/browser-level": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browser-level/-/browser-level-1.0.1.tgz", - "integrity": "sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ==", - "dev": true, - "dependencies": { - "abstract-level": "^1.0.2", - "catering": "^2.1.1", - "module-error": "^1.0.2", - "run-parallel-limit": "^1.1.0" - } - }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", @@ -3619,6 +3612,18 @@ "node": ">=6" } }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/camelcase-keys": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", @@ -3645,30 +3650,12 @@ "node": ">=6" } }, - "node_modules/case": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/case/-/case-1.6.3.tgz", - "integrity": "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "dev": true }, - "node_modules/catering": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/catering/-/catering-2.1.1.tgz", - "integrity": "sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/cbor": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.1.tgz", @@ -3801,23 +3788,6 @@ "safe-buffer": "^5.0.1" } }, - "node_modules/classic-level": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/classic-level/-/classic-level-1.3.0.tgz", - "integrity": "sha512-iwFAJQYtqRTRM0F6L8h4JCt00ZSGdOyqh7yVrhhjrOpFhmBjNlRUey64MCiyo6UmQHMJ+No3c81nujPv+n9yrg==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "abstract-level": "^1.0.2", - "catering": "^2.1.0", - "module-error": "^1.0.1", - "napi-macros": "^2.2.2", - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -3827,6 +3797,18 @@ "node": ">=6" } }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/cli-table3": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", @@ -4083,18 +4065,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "dev": true, - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", @@ -5701,12 +5671,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true - }, "node_modules/functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", @@ -6021,23 +5985,17 @@ } }, "node_modules/hardhat": { - "version": "2.17.4", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.17.4.tgz", - "integrity": "sha512-YTyHjVc9s14CY/O7Dbtzcr/92fcz6AzhrMaj6lYsZpYPIPLzOrFCZHHPxfGQB6FiE6IPNE0uJaAbr7zGF79goA==", + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.2.tgz", + "integrity": "sha512-0xZ7MdCZ5sJem4MrvpQWLR3R3zGDoHw5lsR+pBFimqwagimIOn3bWuZv69KA+veXClwI1s/zpqgwPwiFrd4Dxw==", "dev": true, "dependencies": { "@ethersproject/abi": "^5.1.2", "@metamask/eth-sig-util": "^4.0.0", - "@nomicfoundation/ethereumjs-block": "5.0.2", - "@nomicfoundation/ethereumjs-blockchain": "7.0.2", - "@nomicfoundation/ethereumjs-common": "4.0.2", - "@nomicfoundation/ethereumjs-evm": "2.0.2", - "@nomicfoundation/ethereumjs-rlp": "5.0.2", - "@nomicfoundation/ethereumjs-statemanager": "2.0.2", - "@nomicfoundation/ethereumjs-trie": "6.0.2", - "@nomicfoundation/ethereumjs-tx": "5.0.2", - "@nomicfoundation/ethereumjs-util": "9.0.2", - "@nomicfoundation/ethereumjs-vm": "7.0.2", + "@nomicfoundation/edr": "^0.3.1", + "@nomicfoundation/ethereumjs-common": "4.0.4", + "@nomicfoundation/ethereumjs-tx": "5.0.4", + "@nomicfoundation/ethereumjs-util": "9.0.4", "@nomicfoundation/solidity-analyzer": "^0.1.0", "@sentry/node": "^5.18.1", "@types/bn.js": "^5.1.0", @@ -6045,6 +6003,7 @@ "adm-zip": "^0.4.16", "aggregate-error": "^3.0.0", "ansi-escapes": "^4.3.0", + "boxen": "^5.1.2", "chalk": "^2.4.2", "chokidar": "^3.4.0", "ci-info": "^2.0.0", @@ -6119,9 +6078,9 @@ } }, "node_modules/hardhat-ignore-warnings": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/hardhat-ignore-warnings/-/hardhat-ignore-warnings-0.2.9.tgz", - "integrity": "sha512-q1oj6/ixiAx+lgIyGLBajVCSC7qUtAoK7LS9Nr8UVHYo8Iuh5naBiVGo4RDJ6wxbDGYBkeSukUGZrMqzC2DWwA==", + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/hardhat-ignore-warnings/-/hardhat-ignore-warnings-0.2.11.tgz", + "integrity": "sha512-+nHnRbP6COFZaXE7HAY7TZNE3au5vHe5dkcnyq0XaP07ikT2fJ3NhFY0vn7Deh4Qbz0Z/9Xpnj2ki6Ktgk61pg==", "dev": true, "dependencies": { "minimatch": "^5.1.0", @@ -6604,26 +6563,6 @@ "node": ">=0.10.0" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", @@ -6796,29 +6735,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=4" - } - }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -7109,16 +7025,6 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/js-sdsl": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.2.tgz", - "integrity": "sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, "node_modules/js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", @@ -7237,69 +7143,6 @@ "node": ">=6" } }, - "node_modules/level": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/level/-/level-8.0.0.tgz", - "integrity": "sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ==", - "dev": true, - "dependencies": { - "browser-level": "^1.0.1", - "classic-level": "^1.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/level" - } - }, - "node_modules/level-supports": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-4.0.1.tgz", - "integrity": "sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/level-transcoder": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/level-transcoder/-/level-transcoder-1.0.1.tgz", - "integrity": "sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w==", - "dev": true, - "dependencies": { - "buffer": "^6.0.3", - "module-error": "^1.0.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/level-transcoder/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -7477,15 +7320,6 @@ "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", "dev": true }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -7512,15 +7346,6 @@ "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", "dev": true }, - "node_modules/mcl-wasm": { - "version": "0.7.9", - "resolved": "https://registry.npmjs.org/mcl-wasm/-/mcl-wasm-0.7.9.tgz", - "integrity": "sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ==", - "dev": true, - "engines": { - "node": ">=8.9.0" - } - }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -7532,20 +7357,6 @@ "safe-buffer": "^5.1.2" } }, - "node_modules/memory-level": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/memory-level/-/memory-level-1.0.0.tgz", - "integrity": "sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og==", - "dev": true, - "dependencies": { - "abstract-level": "^1.0.0", - "functional-red-black-tree": "^1.0.1", - "module-error": "^1.0.1" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", @@ -8017,15 +7828,6 @@ "node": ">=10" } }, - "node_modules/module-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/module-error/-/module-error-1.0.2.tgz", - "integrity": "sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -8044,12 +7846,6 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/napi-macros": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.2.2.tgz", - "integrity": "sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==", - "dev": true - }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -9095,35 +8891,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/run-parallel-limit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz", - "integrity": "sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rustbn.js": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz", - "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==", - "dev": true - }, "node_modules/safe-array-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", @@ -11360,6 +11127,62 @@ "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", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/widest-line/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/widest-line/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/widest-line/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/widest-line/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -11606,12 +11429,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -11667,18 +11484,6 @@ "node": ">=10" } }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/yargs-unparser/node_modules/decamelize": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", diff --git a/package.json b/package.json index cc5d8a77450..b963ad556ec 100644 --- a/package.json +++ b/package.json @@ -67,10 +67,10 @@ "ethers": "^6.7.1", "glob": "^10.3.5", "graphlib": "^2.1.8", - "hardhat": "^2.17.4", + "hardhat": "^2.22.2", "hardhat-exposed": "^0.3.14-0", "hardhat-gas-reporter": "^1.0.9", - "hardhat-ignore-warnings": "^0.2.0", + "hardhat-ignore-warnings": "^0.2.11", "lodash.startcase": "^4.4.0", "micromatch": "^4.0.2", "p-limit": "^3.1.0", diff --git a/scripts/generate/templates/StorageSlot.js b/scripts/generate/templates/StorageSlot.js index 9d1f61f24e4..2e865140dae 100644 --- a/scripts/generate/templates/StorageSlot.js +++ b/scripts/generate/templates/StorageSlot.js @@ -2,7 +2,7 @@ const format = require('../format-lines'); const { TYPES } = require('./Slot.opts'); const header = `\ -pragma solidity ^0.8.20; +pragma solidity ^0.8.25; /** * @dev Library for reading and writing primitive types to specific storage slots. @@ -98,7 +98,7 @@ const transient = ({ type, name }) => `\ /** * @dev Load the value held at location \`slot\` in transient storage. */ -function tload(TypedSlot.${name}SlotType slot) internal view returns (${type} value) { +function tload(${name}SlotType slot) internal view returns (${type} value) { /// @solidity memory-safe-assembly assembly { value := tload(slot) @@ -107,7 +107,7 @@ function tload(TypedSlot.${name}SlotType slot) internal view returns (${type} va /** * @dev Store \`value\` at location \`slot\` in transient storage. */ -function tstore(TypedSlot.${name}SlotType slot, ${type} value) internal { +function tstore(${name}SlotType slot, ${type} value) internal { /// @solidity memory-safe-assembly assembly { tstore(slot, value) From 475cce43c9699e8ef646bc3a96e5768588e8598d Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 28 Mar 2024 20:43:15 +0100 Subject: [PATCH 03/14] update hardhat-exposed --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 46b1909e986..97f0d6a7bf7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,7 @@ "glob": "^10.3.5", "graphlib": "^2.1.8", "hardhat": "^2.22.2", - "hardhat-exposed": "^0.3.14-0", + "hardhat-exposed": "^0.3.15", "hardhat-gas-reporter": "^1.0.9", "hardhat-ignore-warnings": "^0.2.11", "lodash.startcase": "^4.4.0", @@ -6051,9 +6051,9 @@ } }, "node_modules/hardhat-exposed": { - "version": "0.3.14-0", - "resolved": "https://registry.npmjs.org/hardhat-exposed/-/hardhat-exposed-0.3.14-0.tgz", - "integrity": "sha512-NvosgpUOGkum+m6oWPweoUDu5XErJpdGhdb9/bhgppVQfbBDA10e1tcvqiVqgc6K1XQT43roVGQ96WO0SU33Sg==", + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/hardhat-exposed/-/hardhat-exposed-0.3.15.tgz", + "integrity": "sha512-jqxErCnSWGYf4vAkLmh3H3u+IuLuCLw/EVeV13z1JKJMJAd/iO+G283n8T124S/Q2BF/BoA2zgzYAlqXgNyKew==", "dev": true, "dependencies": { "micromatch": "^4.0.4", diff --git a/package.json b/package.json index b963ad556ec..743c2526f42 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "glob": "^10.3.5", "graphlib": "^2.1.8", "hardhat": "^2.22.2", - "hardhat-exposed": "^0.3.14-0", + "hardhat-exposed": "^0.3.15", "hardhat-gas-reporter": "^1.0.9", "hardhat-ignore-warnings": "^0.2.11", "lodash.startcase": "^4.4.0", From eac331ad80eff93039a01762c803bd8d4cf658df Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 28 Mar 2024 21:18:45 +0100 Subject: [PATCH 04/14] prepare mocks for transient testing --- contracts/mocks/StorageSlotMock.sol | 72 ++++++++++++++++--- contracts/utils/StorageSlot.sol | 2 +- scripts/generate/run.js | 1 + scripts/generate/templates/StorageSlot.js | 2 +- scripts/generate/templates/StorageSlotMock.js | 65 +++++++++++++++++ 5 files changed, 130 insertions(+), 12 deletions(-) create mode 100644 scripts/generate/templates/StorageSlotMock.js diff --git a/contracts/mocks/StorageSlotMock.sol b/contracts/mocks/StorageSlotMock.sol index c02378b4688..e69bd36a249 100644 --- a/contracts/mocks/StorageSlotMock.sol +++ b/contracts/mocks/StorageSlotMock.sol @@ -1,20 +1,22 @@ // SPDX-License-Identifier: MIT +// This file was procedurally generated from scripts/generate/templates/StorageSlotMock.js. -pragma solidity ^0.8.20; +pragma solidity ^0.8.24; +import {Multicall} from "../utils/Multicall.sol"; import {StorageSlot} from "../utils/StorageSlot.sol"; -contract StorageSlotMock { +contract StorageSlotMock is Multicall { using StorageSlot for *; - function setBooleanSlot(bytes32 slot, bool value) public { - slot.getBooleanSlot().value = value; - } - function setAddressSlot(bytes32 slot, address value) public { slot.getAddressSlot().value = value; } + function setBooleanSlot(bytes32 slot, bool value) public { + slot.getBooleanSlot().value = value; + } + function setBytes32Slot(bytes32 slot, bytes32 value) public { slot.getBytes32Slot().value = value; } @@ -27,14 +29,14 @@ contract StorageSlotMock { slot.getInt256Slot().value = value; } - function getBooleanSlot(bytes32 slot) public view returns (bool) { - return slot.getBooleanSlot().value; - } - function getAddressSlot(bytes32 slot) public view returns (address) { return slot.getAddressSlot().value; } + function getBooleanSlot(bytes32 slot) public view returns (bool) { + return slot.getBooleanSlot().value; + } + function getBytes32Slot(bytes32 slot) public view returns (bytes32) { return slot.getBytes32Slot().value; } @@ -82,4 +84,54 @@ contract StorageSlotMock { function getBytesStorage(uint256 key) public view returns (bytes memory) { return bytesMap[key].getBytesSlot().value; } + + event AddressValue(bytes32 slot, address value); + + function tloadAddress(bytes32 slot) public { + emit AddressValue(slot, slot.asAddress().tload()); + } + + function tstore(bytes32 slot, address value) public { + slot.asAddress().tstore(value); + } + + event BooleanValue(bytes32 slot, bool value); + + function tloadBoolean(bytes32 slot) public { + emit BooleanValue(slot, slot.asBoolean().tload()); + } + + function tstore(bytes32 slot, bool value) public { + slot.asBoolean().tstore(value); + } + + event Bytes32Value(bytes32 slot, bytes32 value); + + function tloadBytes32(bytes32 slot) public { + emit Bytes32Value(slot, slot.asBytes32().tload()); + } + + function tstore(bytes32 slot, bytes32 value) public { + slot.asBytes32().tstore(value); + } + + event Uint256Value(bytes32 slot, uint256 value); + + function tloadUint256(bytes32 slot) public { + emit Uint256Value(slot, slot.asUint256().tload()); + } + + function tstore(bytes32 slot, uint256 value) public { + slot.asUint256().tstore(value); + } + + event Int256Value(bytes32 slot, int256 value); + + function tloadInt256(bytes32 slot) public { + emit Int256Value(slot, slot.asInt256().tload()); + } + + function tstore(bytes32 slot, int256 value) public { + slot.asInt256().tstore(value); + } } diff --git a/contracts/utils/StorageSlot.sol b/contracts/utils/StorageSlot.sol index 52f50adde6c..45768b42399 100644 --- a/contracts/utils/StorageSlot.sol +++ b/contracts/utils/StorageSlot.sol @@ -2,7 +2,7 @@ // OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. -pragma solidity ^0.8.20; +pragma solidity ^0.8.24; /** * @dev Library for reading and writing primitive types to specific storage slots. diff --git a/scripts/generate/run.js b/scripts/generate/run.js index e4ec8dc0516..1b7d81094d5 100755 --- a/scripts/generate/run.js +++ b/scripts/generate/run.js @@ -39,6 +39,7 @@ for (const [file, template] of Object.entries({ 'utils/SlotDerivation.sol': './templates/SlotDerivation.js', 'utils/StorageSlot.sol': './templates/StorageSlot.js', 'utils/Arrays.sol': './templates/Arrays.js', + 'mocks/StorageSlotMock.sol': './templates/StorageSlotMock.js', })) { generateFromTemplate(file, template, './contracts/'); } diff --git a/scripts/generate/templates/StorageSlot.js b/scripts/generate/templates/StorageSlot.js index 2e865140dae..5277345f480 100644 --- a/scripts/generate/templates/StorageSlot.js +++ b/scripts/generate/templates/StorageSlot.js @@ -2,7 +2,7 @@ const format = require('../format-lines'); const { TYPES } = require('./Slot.opts'); const header = `\ -pragma solidity ^0.8.25; +pragma solidity ^0.8.24; /** * @dev Library for reading and writing primitive types to specific storage slots. diff --git a/scripts/generate/templates/StorageSlotMock.js b/scripts/generate/templates/StorageSlotMock.js new file mode 100644 index 00000000000..62506e1729a --- /dev/null +++ b/scripts/generate/templates/StorageSlotMock.js @@ -0,0 +1,65 @@ +const format = require('../format-lines'); +const { TYPES } = require('./Slot.opts'); + +const header = `\ +pragma solidity ^0.8.24; + +import {Multicall} from "../utils/Multicall.sol"; +import {StorageSlot} from "../utils/StorageSlot.sol"; +`; + +const storageSetValueType = ({ type, name }) => `\ +function set${name}Slot(bytes32 slot, ${type} value) public { + slot.get${name}Slot().value = value; +} +`; + +const storageGetValueType = ({ type, name }) => `\ +function get${name}Slot(bytes32 slot) public view returns (${type}) { + return slot.get${name}Slot().value; +} +`; + +const storageSetNonValueType = ({ type, name }) => `\ +mapping(uint256 key => ${type}) public ${type}Map; + +function set${name}Slot(bytes32 slot, ${type} calldata value) public { + slot.get${name}Slot().value = value; +} + +function set${name}Storage(uint256 key, ${type} calldata value) public { + ${type}Map[key].get${name}Slot().value = value; +} + +function get${name}Slot(bytes32 slot) public view returns (${type} memory) { + return slot.get${name}Slot().value; +} + +function get${name}Storage(uint256 key) public view returns (${type} memory) { + return ${type}Map[key].get${name}Slot().value; +} +`; + +const transient = ({ type, name }) => `\ +event ${name}Value(bytes32 slot, ${type} value); + +function tload${name}(bytes32 slot) public { + emit ${name}Value(slot, slot.as${name}().tload()); +} + +function tstore(bytes32 slot, ${type} value) public { + slot.as${name}().tstore(value); +} +`; + +// GENERATE +module.exports = format( + header.trimEnd(), + 'contract StorageSlotMock is Multicall {', + 'using StorageSlot for *;', + TYPES.filter(type => type.isValueType).map(type => storageSetValueType(type)), + TYPES.filter(type => type.isValueType).map(type => storageGetValueType(type)), + TYPES.filter(type => !type.isValueType).map(type => storageSetNonValueType(type)), + TYPES.filter(type => type.isValueType).map(type => transient(type)), + '}', +); From 25d241f55ec3948eed1d6eac6e06ba995390454e Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 28 Mar 2024 21:36:40 +0100 Subject: [PATCH 05/14] test transient slot --- test/utils/StorageSlot.test.js | 82 +++++++++++++++++++++++----------- 1 file changed, 56 insertions(+), 26 deletions(-) diff --git a/test/utils/StorageSlot.test.js b/test/utils/StorageSlot.test.js index bb218ee446f..35e83e29e63 100644 --- a/test/utils/StorageSlot.test.js +++ b/test/utils/StorageSlot.test.js @@ -6,10 +6,18 @@ const { generators } = require('../helpers/random'); const slot = ethers.id('some.storage.slot'); const otherSlot = ethers.id('some.other.storage.slot'); +const TYPES = [ + { name: 'Boolean', type: 'bool', value: true, isValueType: true, zero: false }, + { name: 'Address', type: 'address', value: generators.address(), isValueType: true, zero: generators.address.zero }, + { name: 'Bytes32', type: 'bytes32', value: generators.bytes32(), isValueType: true, zero: generators.bytes32.zero }, + { name: 'Uint256', type: 'uint256', value: generators.uint256(), isValueType: true, zero: generators.uint256.zero }, + { name: 'Int256', type: 'int256', value: generators.int256(), isValueType: true, zero: generators.int256.zero }, + { name: 'Bytes', type: 'bytes', value: generators.hexBytes(128), isValueType: false, zero: generators.hexBytes.zero }, + { name: 'String', type: 'string', value: 'lorem ipsum', isValueType: false, zero: '' }, +]; + async function fixture() { - const [account] = await ethers.getSigners(); - const mock = await ethers.deployContract('StorageSlotMock'); - return { mock, account }; + return { mock: await ethers.deployContract('StorageSlotMock') }; } describe('StorageSlot', function () { @@ -17,60 +25,82 @@ describe('StorageSlot', function () { Object.assign(this, await loadFixture(fixture)); }); - for (const { type, value, zero } of [ - { type: 'Boolean', value: true, zero: false }, - { type: 'Address', value: generators.address(), zero: generators.address.zero }, - { type: 'Bytes32', value: generators.bytes32(), zero: generators.bytes32.zero }, - { type: 'Uint256', value: generators.uint256(), zero: generators.uint256.zero }, - { type: 'Int256', value: generators.int256(), zero: generators.int256.zero }, - { type: 'Bytes', value: generators.hexBytes(128), zero: generators.hexBytes.zero }, - { type: 'String', value: 'lorem ipsum', zero: '' }, - ]) { + for (const { name, type, value, zero } of TYPES) { describe(`${type} storage slot`, function () { it('set', async function () { - await this.mock.getFunction(`set${type}Slot`)(slot, value); + await this.mock.getFunction(`set${name}Slot`)(slot, value); }); describe('get', function () { beforeEach(async function () { - await this.mock.getFunction(`set${type}Slot`)(slot, value); + await this.mock.getFunction(`set${name}Slot`)(slot, value); }); it('from right slot', async function () { - expect(await this.mock.getFunction(`get${type}Slot`)(slot)).to.equal(value); + expect(await this.mock.getFunction(`get${name}Slot`)(slot)).to.equal(value); }); it('from other slot', async function () { - expect(await this.mock.getFunction(`get${type}Slot`)(otherSlot)).to.equal(zero); + expect(await this.mock.getFunction(`get${name}Slot`)(otherSlot)).to.equal(zero); }); }); }); } - for (const { type, value, zero } of [ - { type: 'String', value: 'lorem ipsum', zero: '' }, - { type: 'Bytes', value: generators.hexBytes(128), zero: '0x' }, - ]) { + for (const { name, type, value, zero } of TYPES.filter(type => !type.isValueType)) { describe(`${type} storage pointer`, function () { it('set', async function () { - await this.mock.getFunction(`set${type}Storage`)(slot, value); + await this.mock.getFunction(`set${name}Storage`)(slot, value); }); describe('get', function () { beforeEach(async function () { - await this.mock.getFunction(`set${type}Storage`)(slot, value); + await this.mock.getFunction(`set${name}Storage`)(slot, value); }); it('from right slot', async function () { - expect(await this.mock.getFunction(`${type.toLowerCase()}Map`)(slot)).to.equal(value); - expect(await this.mock.getFunction(`get${type}Storage`)(slot)).to.equal(value); + expect(await this.mock.getFunction(`${type}Map`)(slot)).to.equal(value); + expect(await this.mock.getFunction(`get${name}Storage`)(slot)).to.equal(value); }); it('from other slot', async function () { - expect(await this.mock.getFunction(`${type.toLowerCase()}Map`)(otherSlot)).to.equal(zero); - expect(await this.mock.getFunction(`get${type}Storage`)(otherSlot)).to.equal(zero); + expect(await this.mock.getFunction(`${type}Map`)(otherSlot)).to.equal(zero); + expect(await this.mock.getFunction(`get${name}Storage`)(otherSlot)).to.equal(zero); }); }); }); } + + for (const { name, type, value, zero } of TYPES.filter(type => type.isValueType)) { + describe(`${type} transient slot`, function () { + const load = `tload${name}(bytes32)`; + const store = `tstore(bytes32,${type})`; + const event = `${name}Value`; + + it('load', async function () { + await expect(this.mock[load](slot)).to.emit(this.mock, event).withArgs(slot, zero); + }); + + it('store and load (2 txs)', async function () { + await this.mock[store](slot, value); + await expect(this.mock[load](slot)).to.emit(this.mock, event).withArgs(slot, zero); + }); + + it('store and load (batched)', async function () { + await expect( + this.mock.multicall([ + this.mock.interface.encodeFunctionData(store, [slot, value]), + this.mock.interface.encodeFunctionData(load, [slot]), + this.mock.interface.encodeFunctionData(load, [otherSlot]), + ]), + ) + .to.emit(this.mock, event) + .withArgs(slot, value) + .to.emit(this.mock, event) + .withArgs(otherSlot, zero); + + await expect(this.mock[load](slot)).to.emit(this.mock, event).withArgs(slot, zero); + }); + }); + } }); From 017421d0b8059dfb719f7573be532fa9961fc167 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 28 Mar 2024 21:40:20 +0100 Subject: [PATCH 06/14] codespell --- contracts/utils/README.adoc | 2 +- contracts/utils/StorageSlot.sol | 2 +- scripts/generate/templates/StorageSlot.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/utils/README.adoc b/contracts/utils/README.adoc index 2ab1fd981be..98747b41f78 100644 --- a/contracts/utils/README.adoc +++ b/contracts/utils/README.adoc @@ -29,7 +29,7 @@ Miscellaneous contracts and libraries containing utility functions you can use t * {Strings}: Common operations for strings formatting. * {ShortString}: Library to encode (and decode) short strings into (or from) a single bytes32 slot for optimizing costs. Short strings are limited to 31 characters. * {SlotDerivation}: Methods for deriving storage slot from ERC-7201 namespaces as well as from constructions such as mapping and arrays. - * {StorageSlot}: Methods for accessing specific storage slots formatted as common primitive types. Also include primitives for reading to and writting from transient storage (only value types are currently supported). + * {StorageSlot}: Methods for accessing specific storage slots formatted as common primitive types. Also include primitives for reading from and writing to transient storage (only value types are currently supported). * {Multicall}: Abstract contract with an utility to allow batching together multiple calls in a single transaction. Useful for allowing EOAs to perform multiple operations at once. * {Context}: An utility for abstracting the sender and calldata in the current execution context. * {Panic}: A library to revert with https://docs.soliditylang.org/en/v0.8.20/control-structures.html#panic-via-assert-and-error-via-require[Solidity panic codes]. diff --git a/contracts/utils/StorageSlot.sol b/contracts/utils/StorageSlot.sol index 45768b42399..35bb094e732 100644 --- a/contracts/utils/StorageSlot.sol +++ b/contracts/utils/StorageSlot.sol @@ -29,7 +29,7 @@ pragma solidity ^0.8.24; * } * ``` * - * Since version 5.1, this library also support writting and reading value types to and from transient storage. + * Since version 5.1, this library also support writing and reading value types to and from transient storage. * * * Example usaging transiant storage: * ```solidity diff --git a/scripts/generate/templates/StorageSlot.js b/scripts/generate/templates/StorageSlot.js index 5277345f480..1cde3cc6fd0 100644 --- a/scripts/generate/templates/StorageSlot.js +++ b/scripts/generate/templates/StorageSlot.js @@ -29,7 +29,7 @@ pragma solidity ^0.8.24; * } * \`\`\` * - * Since version 5.1, this library also support writting and reading value types to and from transient storage. + * Since version 5.1, this library also support writing and reading value types to and from transient storage. * * * Example usaging transiant storage: * \`\`\`solidity From 54fe11a56d699c5d83fa24c480632ae015aedbb6 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 28 Mar 2024 21:43:00 +0100 Subject: [PATCH 07/14] Update contracts/utils/StorageSlot.sol --- contracts/utils/StorageSlot.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/utils/StorageSlot.sol b/contracts/utils/StorageSlot.sol index 35bb094e732..85055ea0f29 100644 --- a/contracts/utils/StorageSlot.sol +++ b/contracts/utils/StorageSlot.sol @@ -31,7 +31,7 @@ pragma solidity ^0.8.24; * * Since version 5.1, this library also support writing and reading value types to and from transient storage. * - * * Example usaging transiant storage: + * * Example using transient storage: * ```solidity * contract Lock { * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot. From 4cd042ebcbf47eb9c55b7159a0c814cec5c53ed3 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 28 Mar 2024 21:44:32 +0100 Subject: [PATCH 08/14] Update hardhat.config.js --- hardhat.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardhat.config.js b/hardhat.config.js index 9bfc5e3d496..4f907ed231b 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -110,7 +110,7 @@ module.exports = { exposed: { imports: true, initializers: true, - exclude: ['vendor/**/*', '**/*WithInit.sol', 'utils/TransientSlot.sol'], + exclude: ['vendor/**/*', '**/*WithInit.sol'], }, gasReporter: { enabled: argv.gas, From f0c014c92002b2430b50ec518ccb1e574c5f5bf5 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 28 Mar 2024 21:45:14 +0100 Subject: [PATCH 09/14] Update scripts/generate/templates/StorageSlot.js --- scripts/generate/templates/StorageSlot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/generate/templates/StorageSlot.js b/scripts/generate/templates/StorageSlot.js index 1cde3cc6fd0..54cb4ec2693 100644 --- a/scripts/generate/templates/StorageSlot.js +++ b/scripts/generate/templates/StorageSlot.js @@ -31,7 +31,7 @@ pragma solidity ^0.8.24; * * Since version 5.1, this library also support writing and reading value types to and from transient storage. * - * * Example usaging transiant storage: + * * Example using transient storage: * \`\`\`solidity * contract Lock { * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot. From 684dfcb36a755b1cde1548073b2ec0cacdb84207 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Fri, 29 Mar 2024 10:35:29 +0100 Subject: [PATCH 10/14] pass gas comparaison --- scripts/checks/compareGasReports.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/checks/compareGasReports.js b/scripts/checks/compareGasReports.js index 1afe1d3686e..fd94dc266dc 100755 --- a/scripts/checks/compareGasReports.js +++ b/scripts/checks/compareGasReports.js @@ -50,7 +50,7 @@ class Report { // Compare two reports static compare(update, ref, opts = { hideEqual: true, strictTesting: false }) { if (JSON.stringify(update.config.metadata) !== JSON.stringify(ref.config.metadata)) { - throw new Error('Reports produced with non matching metadata'); + console.warn('WARNING: Reports produced with non matching metadata'); } const deployments = update.info.deployments From ce497cb05ca05bb9aa2b86ec1d99e6454e7ab2e9 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Fri, 29 Mar 2024 10:44:32 +0100 Subject: [PATCH 11/14] increase memory size for coverage --- .github/workflows/checks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 229c7f30d86..adddb9ed9bc 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -14,7 +14,7 @@ concurrency: cancel-in-progress: true env: - NODE_OPTIONS: --max_old_space_size=5120 + NODE_OPTIONS: --max_old_space_size=8192 jobs: lint: From 023ba8965fc13beb474f1886522c87cf3d9bb9b1 Mon Sep 17 00:00:00 2001 From: ernestognw Date: Tue, 2 Apr 2024 19:21:14 -0600 Subject: [PATCH 12/14] Update example in utilities.adoc --- docs/modules/ROOT/pages/utilities.adoc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/modules/ROOT/pages/utilities.adoc b/docs/modules/ROOT/pages/utilities.adoc index 5e69b8ba385..c82a15c9196 100644 --- a/docs/modules/ROOT/pages/utilities.adoc +++ b/docs/modules/ROOT/pages/utilities.adoc @@ -166,6 +166,21 @@ function _setImplementation(address newImplementation) internal { } ---- +The xref:api:utils.adoc#StorageSlot[`StorageSlot`] library also supports transient storage through user defined value types (UDVTs[https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types]), which enables the same value types as in Solidity. + +[source,solidity] +---- +bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542; + +function _getTransientLock() internal view returns (bool) { + return _LOCK_SLOT.asBoolean().tload(); +} + +function _setTransientLock(bool lock) internal { + _LOCK_SLOT.asBoolean().tstore(lock); +} +---- + WARNING: Manipulating storage slots directly is an advanced practice. Developers MUST make sure that the storage pointer is not colliding with other variables. One of the most common use cases for writing directly to storage slots is ERC-7201 for namespaced storage, which is guaranteed to not collide with other storage slots derived by Solidity. From 8853203ca8339421cfb6a279ff68b6e36db59fb5 Mon Sep 17 00:00:00 2001 From: ernestognw Date: Wed, 3 Apr 2024 10:18:19 -0600 Subject: [PATCH 13/14] Remove gas report bypass --- scripts/checks/compareGasReports.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/checks/compareGasReports.js b/scripts/checks/compareGasReports.js index 2c7b4dc24df..8c9cfc4d053 100755 --- a/scripts/checks/compareGasReports.js +++ b/scripts/checks/compareGasReports.js @@ -50,7 +50,7 @@ class Report { // Compare two reports static compare(update, ref, opts = { hideEqual: true, strictTesting: false }) { if (JSON.stringify(update.options?.solcInfo) !== JSON.stringify(ref.options?.solcInfo)) { - console.warn('WARNING: Reports produced with non matching metadata'); + throw new Error('Reports produced with non matching metadata'); } // gasReporter 1.0.0 uses ".info", but 2.0.0 uses ".data" From 85135385fedf62983db306c667a882ed15ae74a4 Mon Sep 17 00:00:00 2001 From: ernestognw Date: Wed, 3 Apr 2024 10:54:27 -0600 Subject: [PATCH 14/14] Revert "Remove gas report bypass" This reverts commit 8853203ca8339421cfb6a279ff68b6e36db59fb5. --- scripts/checks/compareGasReports.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/checks/compareGasReports.js b/scripts/checks/compareGasReports.js index 8c9cfc4d053..2c7b4dc24df 100755 --- a/scripts/checks/compareGasReports.js +++ b/scripts/checks/compareGasReports.js @@ -50,7 +50,7 @@ class Report { // Compare two reports static compare(update, ref, opts = { hideEqual: true, strictTesting: false }) { if (JSON.stringify(update.options?.solcInfo) !== JSON.stringify(ref.options?.solcInfo)) { - throw new Error('Reports produced with non matching metadata'); + console.warn('WARNING: Reports produced with non matching metadata'); } // gasReporter 1.0.0 uses ".info", but 2.0.0 uses ".data"