diff --git a/package.json b/package.json index 8b1cddbd..8997a1d5 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "global-modules": "^2.0.0", "globby": "^10.0.1", "jsonschema": "^1.2.4", - "lodash": "^4.17.15", + "lodash": "^4.17.21", "mocha": "^10.2.0", "node-emoji": "^1.10.0", "pify": "^4.0.1", @@ -46,18 +46,22 @@ "web3-utils": "^1.3.6" }, "devDependencies": { + "@nomicfoundation/hardhat-network-helpers": "^1.0.10", + "@nomicfoundation/hardhat-viem": "^2.0.0", "@nomiclabs/hardhat-ethers": "^2.0.4", "@nomiclabs/hardhat-truffle5": "^2.0.0", "@nomiclabs/hardhat-waffle": "^2.0.1", "@nomiclabs/hardhat-web3": "^2.0.0", "chai": "^4.3.4", + "chai-as-promised": "^7.1.1", "decache": "^4.5.1", "ethereum-waffle": "^3.4.0", "ethers": "^5.5.3", "hardhat": "^2.22.2", "hardhat-gas-reporter": "^1.0.1", "nyc": "^14.1.1", - "solc": "0.8.24" + "solc": "0.8.24", + "viem": "^2.9.9" }, "peerDependencies": { "hardhat": "^2.11.0" diff --git a/plugins/hardhat.plugin.js b/plugins/hardhat.plugin.js index ab8805f5..c14dc82d 100644 --- a/plugins/hardhat.plugin.js +++ b/plugins/hardhat.plugin.js @@ -1,7 +1,7 @@ const path = require('path'); const PluginUI = require('./resources/nomiclabs.ui'); -const { task, types } = require("hardhat/config"); +const { extendConfig, task, types } = require("hardhat/config"); const { HardhatPluginError } = require("hardhat/plugins") const {HARDHAT_NETWORK_RESET_EVENT} = require("hardhat/internal/constants"); const { @@ -21,6 +21,24 @@ let optimizerDetails; // UI for the task flags... const ui = new PluginUI(); +// Workaround for hardhat-viem-plugin and other provider redefinition conflicts +extendConfig((config, userConfig) => { + if (Boolean(process.env.SOLIDITY_COVERAGE)) { + const { cloneDeep } = require("lodash"); + const { configureHardhatEVMGas } = require('./resources/nomiclabs.utils'); + const API = require('./../lib/api'); + const api = new API({}); + + let hardhatNetworkForCoverage = {}; + if (userConfig.networks && userConfig.networks.hardhat) { + hardhatNetworkForCoverage = cloneDeep(userConfig.networks.hardhat); + }; + + configureHardhatEVMGas(hardhatNetworkForCoverage, api); + config.networks.hardhat = Object.assign(config.networks.hardhat, hardhatNetworkForCoverage); + } +}); + subtask(TASK_COMPILE_SOLIDITY_GET_COMPILER_INPUT).setAction(async (_, { config }, runSuper) => { const solcInput = await runSuper(); if (measureCoverage) { @@ -133,6 +151,12 @@ task("coverage", "Generates a code coverage report for tests") // Catch interrupt signals process.on("SIGINT", nomiclabsUtils.finish.bind(null, config, api, true)); + // Warn about hardhat-viem plugin if present and config hasn't happened + if (env.viem !== undefined && nomiclabsUtils.requiresEVMConfiguration(env.network.config, api)) { + ui.report('hardhat-viem', []); + throw new Error(ui.generate('hardhat-viem')); + } + // Version Info ui.report('hardhat-versions', [pkg.version]); @@ -208,7 +232,13 @@ task("coverage", "Generates a code coverage report for tests") // ============== // Server launch // ============== - let network = await nomiclabsUtils.setupHardhatNetwork(env, api, ui); + let network + + if (nomiclabsUtils.requiresEVMConfiguration(env.network.config, api)) { + network = await nomiclabsUtils.setupHardhatNetwork(env, api, ui); + } else { + network = env.network; + } accounts = await utils.getAccountsHardhat(network.provider); nodeInfo = await utils.getNodeInfoHardhat(network.provider); diff --git a/plugins/resources/nomiclabs.ui.js b/plugins/resources/nomiclabs.ui.js index 8ec5d78a..9c824e5f 100644 --- a/plugins/resources/nomiclabs.ui.js +++ b/plugins/resources/nomiclabs.ui.js @@ -54,6 +54,12 @@ class PluginUI extends UI { `${ct} ${c.bold('HardhatEVM')}: v${args[0]}\n` + `${ct} ${c.bold('network')}: ${args[1]}\n`, + 'hardhat-viem': `\n${w}${c.red(" Coverage requires a special environment variable when used with 'hardhat-viem' ")}${w}` + + `\n${c.red( "====================================================================================")}` + + `\n${c.bold( "Please run the coverage command as:" )}` + + `\n${c( "SOLIDITY_COVERAGE=true npx hardhat coverage")}` + + `\n${c.red( "====================================================================================")}` + , } this._write(kinds[kind]); @@ -81,12 +87,14 @@ class PluginUI extends UI { 'tests-fail': `${x} ${c.bold(args[0])} ${c.red('test(s) failed under coverage.')}`, - + 'hardhat-viem': "'hardhat-viem' requires an environment variable to be set when used with the solidity-coverage plugin" } return this._format(kinds[kind]) } + + } -module.exports = PluginUI; \ No newline at end of file +module.exports = PluginUI; diff --git a/plugins/resources/nomiclabs.utils.js b/plugins/resources/nomiclabs.utils.js index d044d630..fa77b345 100644 --- a/plugins/resources/nomiclabs.utils.js +++ b/plugins/resources/nomiclabs.utils.js @@ -104,7 +104,7 @@ async function setupHardhatNetwork(env, api, ui){ // after 2.15.0, the internal createProvider function has a different signature const newCreateProviderSignature = semver.satisfies(hardhatPackage.version, "^2.15.0"); - let provider, networkName, networkConfig; + let provider, networkConfig; // HardhatEVM networkConfig = env.network.config; @@ -133,6 +133,16 @@ async function setupHardhatNetwork(env, api, ui){ ) } +function requiresEVMConfiguration(networkConfig, api) { + return ( + networkConfig.allowUnlimitedContractSize !== true || + networkConfig.blockGasLimit !== api.gasLimitNumber || + networkConfig.gas !== api.gasLimit || + networkConfig.gasPrice !== api.gasPrice || + networkConfig.initialBaseFeePerGas !== 0 + ) +} + function configureHardhatEVMGas(networkConfig, api){ networkConfig.allowUnlimitedContractSize = true; networkConfig.blockGasLimit = api.gasLimitNumber; @@ -249,6 +259,8 @@ async function finish(config, api, shouldKill){ } module.exports = { + configureHardhatEVMGas, + requiresEVMConfiguration, normalizeConfig, finish, tempCacheDir, diff --git a/test/integration/errors.js b/test/integration/errors.js index 2451b58b..b78b268f 100644 --- a/test/integration/errors.js +++ b/test/integration/errors.js @@ -167,4 +167,21 @@ describe('Hardhat Plugin: error cases', function() { verify.coverageNotGenerated(hardhatConfig); }) + + it('viem plugin (when SOLIDITY_COVERAGE is undefined)', async function(){ + mock.installFullProject('viem'); + mock.hardhatSetupEnv(this); + + try { + await this.env.run("coverage"); + assert.fail() + } catch(err){ + assert( + err.message.includes('requires an environment variable'), + `Should error when viem plugin is used without env variable:: ${err.message}` + ); + } + + verify.coverageNotGenerated(hardhatConfig); + }); }) diff --git a/test/integration/standard.js b/test/integration/standard.js index bddeec60..a23b34e5 100644 --- a/test/integration/standard.js +++ b/test/integration/standard.js @@ -481,4 +481,22 @@ describe('Hardhat Plugin: standard use cases', function() { verify.branchCoverage(expected); }); + + it('viem plugin (when SOLIDITY_COVERAGE="true")', async function(){ + process.env.SOLIDITY_COVERAGE = "true"; + + mock.installFullProject('viem'); + mock.hardhatSetupEnv(this); + + await this.env.run("coverage"); + + const expected = [ + { + file: mock.pathToContract(hardhatConfig, 'Lock.sol'), + pct: 100 + } + ]; + + verify.branchCoverage(expected); + }); }) diff --git a/test/sources/projects/viem/.solcover.js b/test/sources/projects/viem/.solcover.js new file mode 100644 index 00000000..2bcb9670 --- /dev/null +++ b/test/sources/projects/viem/.solcover.js @@ -0,0 +1,5 @@ +module.exports = { + silent: process.env.SILENT ? true : false, + skipFiles: [], + istanbulReporter: ['json-summary', 'text'] +} diff --git a/test/sources/projects/viem/contracts/Lock.sol b/test/sources/projects/viem/contracts/Lock.sol new file mode 100644 index 00000000..ced5d511 --- /dev/null +++ b/test/sources/projects/viem/contracts/Lock.sol @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: MIT */ +pragma solidity >=0.8.0 <0.9.0; + +contract Lock { + uint public unlockTime; + address payable public owner; + + event Withdrawal(uint amount, uint when); + + constructor(uint _unlockTime) payable { + require( + block.timestamp < _unlockTime, + "Unlock time should be in the future" + ); + + unlockTime = _unlockTime; + owner = payable(msg.sender); + } + + function withdraw() public { + // Uncomment this line, and the import of "hardhat/console.sol", to print a log in your terminal + // console.log("Unlock time is %o and block timestamp is %o", unlockTime, block.timestamp); + + require(block.timestamp >= unlockTime, "You can't withdraw yet"); + require(msg.sender == owner, "You aren't the owner"); + + emit Withdrawal(address(this).balance, block.timestamp); + + owner.transfer(address(this).balance); + } +} diff --git a/test/sources/projects/viem/hardhat.config.js b/test/sources/projects/viem/hardhat.config.js new file mode 100644 index 00000000..be91551c --- /dev/null +++ b/test/sources/projects/viem/hardhat.config.js @@ -0,0 +1,20 @@ +require(__dirname + "/../plugins/nomiclabs.plugin"); +require("@nomicfoundation/hardhat-viem"); + +module.exports = { + networks: { + hardhat: { + gasPrice: 50_000_000_000 + } + }, + solidity: { + version: "0.8.17", + settings: { + optimizer: { + enabled: true + }, + viaIR: process.env.VIA_IR === "true" + } + }, + logger: process.env.SILENT ? { log: () => {} } : console, +}; diff --git a/test/sources/projects/viem/test/lock.js b/test/sources/projects/viem/test/lock.js new file mode 100644 index 00000000..5ae4f650 --- /dev/null +++ b/test/sources/projects/viem/test/lock.js @@ -0,0 +1,137 @@ +const { + time, + loadFixture, +} = require("@nomicfoundation/hardhat-network-helpers"); +const { expect, use } = require ("chai"); +const chaiAsPromised = require("chai-as-promised"); +const hre = require("hardhat"); +const { getAddress, parseGwei } = require("viem"); + +use(chaiAsPromised); + +describe("Lock", function () { + // We define a fixture to reuse the same setup in every test. + // We use loadFixture to run this setup once, snapshot that state, + // and reset Hardhat Network to that snapshot in every test. + async function deployOneYearLockFixture() { + const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60; + + const lockedAmount = parseGwei("1"); + const unlockTime = BigInt((await time.latest()) + ONE_YEAR_IN_SECS); + + // Contracts are deployed using the first signer/account by default + const [owner, otherAccount] = await hre.viem.getWalletClients(); + + const lock = await hre.viem.deployContract("Lock", [unlockTime], { + value: lockedAmount, + }); + + const publicClient = await hre.viem.getPublicClient(); + + return { + lock, + unlockTime, + lockedAmount, + owner, + otherAccount, + publicClient, + }; + } + + describe("Deployment", function () { + it("Should set the right unlockTime", async function () { + const { lock, unlockTime } = await loadFixture(deployOneYearLockFixture); + + expect(await lock.read.unlockTime()).to.equal(unlockTime); + }); + + it("Should set the right owner", async function () { + const { lock, owner } = await loadFixture(deployOneYearLockFixture); + + expect(await lock.read.owner()).to.equal( + getAddress(owner.account.address) + ); + }); + + it("Should receive and store the funds to lock", async function () { + const { lock, lockedAmount, publicClient } = await loadFixture( + deployOneYearLockFixture + ); + + expect( + await publicClient.getBalance({ + address: lock.address, + }) + ).to.equal(lockedAmount); + }); + + it("Should fail if the unlockTime is not in the future", async function () { + // We don't use the fixture here because we want a different deployment + const latestTime = BigInt(await time.latest()); + await expect( + hre.viem.deployContract("Lock", [latestTime], { + value: 1n, + }) + ).to.be.rejectedWith("Unlock time should be in the future"); + }); + }); + + describe("Withdrawals", function () { + describe("Validations", function () { + it("Should revert with the right error if called too soon", async function () { + const { lock } = await loadFixture(deployOneYearLockFixture); + + await expect(lock.write.withdraw()).to.be.rejectedWith( + "You can't withdraw yet" + ); + }); + + it("Should revert with the right error if called from another account", async function () { + const { lock, unlockTime, otherAccount } = await loadFixture( + deployOneYearLockFixture + ); + + // We can increase the time in Hardhat Network + await time.increaseTo(unlockTime); + + // We retrieve the contract with a different account to send a transaction + const lockAsOtherAccount = await hre.viem.getContractAt( + "Lock", + lock.address, + { client: { wallet: otherAccount } } + ); + await expect(lockAsOtherAccount.write.withdraw()).to.be.rejectedWith( + "You aren't the owner" + ); + }); + + it("Shouldn't fail if the unlockTime has arrived and the owner calls it", async function () { + const { lock, unlockTime } = await loadFixture( + deployOneYearLockFixture + ); + + // Transactions are sent using the first signer by default + await time.increaseTo(unlockTime); + + await expect(lock.write.withdraw()).to.be.fulfilled; + }); + }); + + describe.skip("Events", function () { + it("Should emit an event on withdrawals", async function () { + const { lock, unlockTime, lockedAmount, publicClient } = + await loadFixture(deployOneYearLockFixture); + + await time.increaseTo(unlockTime); + + const hash = await lock.write.withdraw(); + await publicClient.waitForTransactionReceipt({ hash }); + + // get the withdrawal events in the latest block + const withdrawalEvents = await lock.getEvents.Withdrawal(); + expect(withdrawalEvents).to.have.lengthOf(1); + expect(withdrawalEvents[0].args.amount).to.equal(lockedAmount); + }); + }); + }); +}); \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 4b2d9423..e87e8169 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@adraffy/ens-normalize@1.10.0": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz#d2a39395c587e092d77cbbc80acf956a54f38bf7" + integrity sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q== + "@babel/code-frame@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" @@ -511,10 +516,27 @@ tweetnacl "^1.0.3" tweetnacl-util "^0.15.1" +"@noble/curves@1.2.0", "@noble/curves@~1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== + dependencies: + "@noble/hashes" "1.3.2" + "@noble/hashes@1.0.0", "@noble/hashes@~1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.0.0.tgz#d5e38bfbdaba174805a4e649f13be9a9ed3351ae" +"@noble/hashes@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + +"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.2": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" + integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== + "@noble/secp256k1@1.5.5", "@noble/secp256k1@~1.5.2": version "1.5.5" resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.5.5.tgz#315ab5745509d1a8c8e90d0bdf59823ccf9bcfc3" @@ -627,6 +649,21 @@ "@nomicfoundation/ethereumjs-rlp" "5.0.4" ethereum-cryptography "0.1.3" +"@nomicfoundation/hardhat-network-helpers@^1.0.10": + version "1.0.10" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.10.tgz#c61042ceb104fdd6c10017859fdef6529c1d6585" + integrity sha512-R35/BMBlx7tWN5V6d/8/19QCwEmIdbnA4ZrsuXgvs8i2qFx5i7h6mH5pBS4Pwi4WigLH+upl6faYusrNPuzMrQ== + dependencies: + ethereumjs-util "^7.1.4" + +"@nomicfoundation/hardhat-viem@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-viem/-/hardhat-viem-2.0.0.tgz#4f5de792028a5607984ea9fd1e17727a71e3cdb8" + integrity sha512-ilXQKTc1jWHqJ66fAN6TIyCRyormoChOn1yQTCGoBQ+G6QcVCu5FTaGL2r0KUOY4IkTohtphK+UXQrKcxQX5Yw== + dependencies: + abitype "^0.9.8" + lodash.memoize "^4.1.2" + "@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.1": version "0.1.1" resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.1.tgz#4c858096b1c17fe58a474fe81b46815f93645c15" @@ -760,6 +797,11 @@ version "1.0.0" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.0.0.tgz#109fb595021de285f05a7db6806f2f48296fcee7" +"@scure/base@~1.1.0", "@scure/base@~1.1.2": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.6.tgz#8ce5d304b436e4c84f896e0550c83e4d88cb917d" + integrity sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g== + "@scure/bip32@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.0.1.tgz#1409bdf9f07f0aec99006bb0d5827693418d3aa5" @@ -768,6 +810,15 @@ "@noble/secp256k1" "~1.5.2" "@scure/base" "~1.0.0" +"@scure/bip32@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.2.tgz#90e78c027d5e30f0b22c1f8d50ff12f3fb7559f8" + integrity sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA== + dependencies: + "@noble/curves" "~1.2.0" + "@noble/hashes" "~1.3.2" + "@scure/base" "~1.1.2" + "@scure/bip39@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.0.0.tgz#47504e58de9a56a4bbed95159d2d6829fa491bb0" @@ -775,6 +826,14 @@ "@noble/hashes" "~1.0.0" "@scure/base" "~1.0.0" +"@scure/bip39@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" + integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== + dependencies: + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + "@sentry/core@5.30.0": version "5.30.0" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" @@ -1082,6 +1141,16 @@ abbrev@1.0.x: version "1.0.9" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" +abitype@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.0.tgz#237176dace81d90d018bebf3a45cb42f2a2d9e97" + integrity sha512-NMeMah//6bJ56H5XRj8QCV4AwuW6hB6zqz2LnhhLdcWVQOsXki6/Pn3APeqxCma62nXIcmZWdu1DlHWS74umVQ== + +abitype@^0.9.8: + version "0.9.10" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.9.10.tgz#fa6fa30a6465da98736f98b6c601a02ed49f6eec" + integrity sha512-FIS7U4n7qwAT58KibwYig5iFG4K61rbhAqaQh/UWj8v1Y8mjX3F8TC9gd8cz9yT1TYel9f8nS5NO5kZp2RW0jQ== + abstract-leveldown@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz#5cb89f958a44f526779d740d1440e743e0c30a57" @@ -2211,6 +2280,13 @@ caseless@^0.12.0, caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" +chai-as-promised@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0" + integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== + dependencies: + check-error "^1.0.2" + chai@^4.2.0, chai@^4.3.4: version "4.3.6" resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c" @@ -4837,6 +4913,11 @@ isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" +isows@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.3.tgz#93c1cf0575daf56e7120bab5c8c448b0809d0d74" + integrity sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg== + isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -5277,6 +5358,11 @@ lodash.flattendeep@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" @@ -7918,6 +8004,20 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +viem@^2.9.9: + version "2.9.9" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.9.9.tgz#c89e6f402ae06601579a7e3069de76eb08c60adb" + integrity sha512-SUIHBL6M5IIlqDCMEQwAAvHzeglaM4FEqM6bCI+srLXtFYmrpV4tWhnpobQRNwh4f7HIksmKLLZ+cytv8FfnJQ== + dependencies: + "@adraffy/ens-normalize" "1.10.0" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@scure/bip32" "1.3.2" + "@scure/bip39" "1.2.1" + abitype "1.0.0" + isows "1.0.3" + ws "8.13.0" + web3-bzz@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.11.tgz#41bc19a77444bd5365744596d778b811880f707f" @@ -8751,6 +8851,11 @@ ws@7.4.6: version "7.4.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" +ws@8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== + ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"