diff --git a/packages/protocol/.prettierrc.json b/packages/protocol/.prettierrc.json index e75916e827..46ca7116dd 100644 --- a/packages/protocol/.prettierrc.json +++ b/packages/protocol/.prettierrc.json @@ -3,7 +3,8 @@ { "files": ["*.sol", "*.ts"], "options": { - "tabWidth": 4 + "tabWidth": 4, + "compiler": "^0.8.18" } } ], diff --git a/packages/protocol/.solhint.json b/packages/protocol/.solhint.json index 70b58695ca..ac099f7e5d 100644 --- a/packages/protocol/.solhint.json +++ b/packages/protocol/.solhint.json @@ -2,7 +2,7 @@ "extends": "solhint:recommended", "rules": { "avoid-low-level-calls": "off", - "compiler-version": ["error", "^0.8.0"], + "compiler-version": ["error", "^0.8.18"], "func-visibility": ["warn", { "ignoreConstructors": true }], "max-line-length": ["warn", 80], "no-empty-blocks": "off", diff --git a/packages/protocol/contracts/L1/TaikoData.sol b/packages/protocol/contracts/L1/TaikoData.sol index dd143e8ca1..63cc52ff3e 100644 --- a/packages/protocol/contracts/L1/TaikoData.sol +++ b/packages/protocol/contracts/L1/TaikoData.sol @@ -75,15 +75,12 @@ library TaikoData { // This struct takes 9 slots. struct State { - // block id => block hash (some blocks' hashes won't be persisted, - // only the latest one if verified in a batch) - mapping(uint256 => bytes32) l2Hashes; - // block id => ProposedBlock - mapping(uint256 => ProposedBlock) proposedBlocks; - // block id => parent hash => fork choice - mapping(uint256 => mapping(bytes32 => ForkChoice)) forkChoices; - // proposer => commitSlot => hash(commitHash, commitHeight) - mapping(address => mapping(uint256 => bytes32)) commits; + // some blocks' hashes won't be persisted, + // only the latest one if verified in a batch + mapping(uint256 blockId => bytes32 blockHash) l2Hashes; + mapping(uint256 blockId => ProposedBlock proposedBlock) proposedBlocks; + mapping(uint256 blockId => mapping(bytes32 parentHash => ForkChoice forkChoice)) forkChoices; + mapping(address proposerAddress => mapping(uint256 commitSlot => bytes32 commitHash)) commits; // Never or rarely changed uint64 genesisHeight; uint64 genesisTimestamp; diff --git a/packages/protocol/contracts/L1/TaikoL1.sol b/packages/protocol/contracts/L1/TaikoL1.sol index 55255e224a..d8220682b9 100644 --- a/packages/protocol/contracts/L1/TaikoL1.sol +++ b/packages/protocol/contracts/L1/TaikoL1.sol @@ -89,7 +89,7 @@ contract TaikoL1 is EssentialContract, IHeaderSync, TaikoEvents { }); LibVerifying.verifyBlocks({ state: state, - config: getConfig(), + config: config, resolver: AddressResolver(this), maxBlocks: config.maxVerificationsPerTx, checkHalt: false diff --git a/packages/protocol/contracts/L1/libs/LibProving.sol b/packages/protocol/contracts/L1/libs/LibProving.sol index 2ae919689f..77f5617e78 100644 --- a/packages/protocol/contracts/L1/libs/LibProving.sol +++ b/packages/protocol/contracts/L1/libs/LibProving.sol @@ -73,6 +73,7 @@ library LibProving { error L1_ANCHOR_RECEIPT_ADDR(); error L1_ANCHOR_RECEIPT_TOPICS(); error L1_ANCHOR_RECEIPT_DATA(); + error L1_HALTED(); function proveBlock( TaikoData.State storage state, @@ -81,7 +82,7 @@ library LibProving { uint256 blockId, bytes[] calldata inputs ) public { - assert(!LibUtils.isHalted(state)); + if (LibUtils.isHalted(state)) revert L1_HALTED(); // Check and decode inputs if (inputs.length != 3) revert L1_INPUT_SIZE(); diff --git a/packages/protocol/contracts/L2/TaikoL2.sol b/packages/protocol/contracts/L2/TaikoL2.sol index 56475d9414..4a184b86d6 100644 --- a/packages/protocol/contracts/L2/TaikoL2.sol +++ b/packages/protocol/contracts/L2/TaikoL2.sol @@ -28,12 +28,12 @@ contract TaikoL2 is AddressResolver, ReentrancyGuard, IHeaderSync { // Mapping from L2 block numbers to their block hashes. // All L2 block hashes will be saved in this mapping. - mapping(uint256 => bytes32) private _l2Hashes; + mapping(uint256 blockNumber => bytes32 blockHash) private _l2Hashes; // Mapping from L1 block numbers to their block hashes. // Note that only hashes of L1 blocks where at least one L2 // block has been proposed will be saved in this mapping. - mapping(uint256 => bytes32) private _l1Hashes; + mapping(uint256 blockNumber => bytes32 blockHash) private _l1Hashes; // A hash to check te integrity of public inputs. bytes32 private _publicInputHash; diff --git a/packages/protocol/contracts/bridge/EtherVault.sol b/packages/protocol/contracts/bridge/EtherVault.sol index d19ade2d59..275ce8d301 100644 --- a/packages/protocol/contracts/bridge/EtherVault.sol +++ b/packages/protocol/contracts/bridge/EtherVault.sol @@ -27,7 +27,7 @@ contract EtherVault is EssentialContract { * State Variables * *********************/ - mapping(address => bool) private _authorizedAddrs; + mapping(address addr => bool isAuthorized) private _authorizedAddrs; uint256[49] private __gap; /********************* diff --git a/packages/protocol/contracts/bridge/TokenVault.sol b/packages/protocol/contracts/bridge/TokenVault.sol index d0bfae9128..3b2adf9116 100644 --- a/packages/protocol/contracts/bridge/TokenVault.sol +++ b/packages/protocol/contracts/bridge/TokenVault.sol @@ -47,18 +47,20 @@ contract TokenVault is EssentialContract { *********************/ // Tracks if a token on the current chain is a canonical or bridged token. - mapping(address => bool) public isBridgedToken; + mapping(address tokenAddress => bool isBridged) public isBridgedToken; // Mappings from bridged tokens to their canonical tokens. - mapping(address => CanonicalERC20) public bridgedToCanonical; + mapping(address bridgedAddress => CanonicalERC20 canonicalErc20) + public bridgedToCanonical; // Mappings from canonical tokens to their bridged tokens. // Also storing chainId for tokens across other chains aside from Ethereum. - // chainId => canonical address => bridged address - mapping(uint256 => mapping(address => address)) public canonicalToBridged; + mapping(uint256 chainId => mapping(address canonicalAddress => address bridgedAddress)) + public canonicalToBridged; // Tracks the token and amount associated with a message hash. - mapping(bytes32 => MessageDeposit) public messageDeposits; + mapping(bytes32 msgHash => MessageDeposit messageDeposit) + public messageDeposits; uint256[47] private __gap; @@ -108,6 +110,21 @@ contract TokenVault is EssentialContract { uint256 amount ); + /********************* + * Custom Errors* + *********************/ + + error TOKENVAULT_INVALID_TO(); + error TOKENVAULT_INVALID_VALUE(); + error TOKENVAULT_INVALID_CALL_VALUE(); + error TOKENVAULT_INVALID_TOKEN(); + error TOKENVAULT_INVALID_AMOUNT(); + error TOKENVAULT_CANONICAL_TOKEN_NOT_FOUND(); + error TOKENVAULT_INVALID_OWNER(); + error TOKENVAULT_INVALID_SRC_CHAIN_ID(); + error TOKENVAULT_MESSAGE_NOT_FAILED(); + error TOKENVAULT_INVALID_SENDER(); + /********************* * External Functions* *********************/ @@ -134,12 +151,11 @@ contract TokenVault is EssentialContract { address refundAddress, string memory memo ) external payable nonReentrant { - require( - to != address(0) && - to != resolve(destChainId, "token_vault", false), - "V:to" - ); - require(msg.value > processingFee, "V:msgValue"); + if ( + to == address(0) || to == resolve(destChainId, "token_vault", false) + ) revert TOKENVAULT_INVALID_TO(); + + if (msg.value <= processingFee) revert TOKENVAULT_INVALID_VALUE(); IBridge.Message memory message; message.destChainId = destChainId; @@ -152,7 +168,7 @@ contract TokenVault is EssentialContract { message.memo = memo; // prevent future PRs from changing the callValue when it must be zero - require(message.callValue == 0, "V:callValue"); + if (message.callValue != 0) revert TOKENVAULT_INVALID_CALL_VALUE(); bytes32 msgHash = IBridge(resolve("bridge", false)).sendMessage{ value: msg.value @@ -191,13 +207,13 @@ contract TokenVault is EssentialContract { address refundAddress, string memory memo ) external payable nonReentrant { - require( - to != address(0) && - to != resolve(destChainId, "token_vault", false), - "V:to" - ); - require(token != address(0), "V:token"); - require(amount > 0, "V:amount"); + if ( + to == address(0) || to == resolve(destChainId, "token_vault", false) + ) revert TOKENVAULT_INVALID_TO(); + + if (token == address(0)) revert TOKENVAULT_INVALID_TOKEN(); + + if (amount == 0) revert TOKENVAULT_INVALID_AMOUNT(); CanonicalERC20 memory canonicalToken; uint256 _amount; @@ -206,7 +222,8 @@ contract TokenVault is EssentialContract { if (isBridgedToken[token]) { BridgedERC20(token).bridgeBurnFrom(msg.sender, amount); canonicalToken = bridgedToCanonical[token]; - require(canonicalToken.addr != address(0), "V:canonicalToken"); + if (canonicalToken.addr == address(0)) + revert TOKENVAULT_CANONICAL_TOKEN_NOT_FOUND(); _amount = amount; } else { // is a canonical token, meaning, it lives on this chain @@ -271,20 +288,19 @@ contract TokenVault is EssentialContract { IBridge.Message calldata message, bytes calldata proof ) external nonReentrant { - require(message.owner != address(0), "B:owner"); - require(message.srcChainId == block.chainid, "B:srcChainId"); + if (message.owner == address(0)) revert TOKENVAULT_INVALID_OWNER(); + if (message.srcChainId != block.chainid) + revert TOKENVAULT_INVALID_SRC_CHAIN_ID(); IBridge bridge = IBridge(resolve("bridge", false)); bytes32 msgHash = bridge.hashMessage(message); address token = messageDeposits[msgHash].token; uint256 amount = messageDeposits[msgHash].amount; - require(token != address(0), "B:ERC20Released"); - require( - bridge.isMessageFailed(msgHash, message.destChainId, proof), - "V:notFailed" - ); + if (token == address(0)) revert TOKENVAULT_INVALID_TOKEN(); + if (!bridge.isMessageFailed(msgHash, message.destChainId, proof)) + revert TOKENVAULT_MESSAGE_NOT_FAILED(); messageDeposits[msgHash] = MessageDeposit(address(0), 0); if (amount > 0) { @@ -321,10 +337,8 @@ contract TokenVault is EssentialContract { uint256 amount ) external nonReentrant onlyFromNamed("bridge") { IBridge.Context memory ctx = IBridge(msg.sender).context(); - require( - ctx.sender == resolve(ctx.srcChainId, "token_vault", false), - "V:sender" - ); + if (ctx.sender != resolve(ctx.srcChainId, "token_vault", false)) + revert TOKENVAULT_INVALID_SENDER(); address token; if (canonicalToken.chainId == block.chainid) { @@ -367,12 +381,11 @@ contract TokenVault is EssentialContract { function _deployBridgedToken( CanonicalERC20 calldata canonicalToken ) private returns (address bridgedToken) { - bytes32 salt = keccak256( - abi.encodePacked(canonicalToken.chainId, canonicalToken.addr) - ); bridgedToken = Create2Upgradeable.deploy( 0, // amount of Ether to send - salt, + keccak256( + abi.encodePacked(canonicalToken.chainId, canonicalToken.addr) + ), type(BridgedERC20).creationCode ); diff --git a/packages/protocol/contracts/bridge/libs/LibBridgeData.sol b/packages/protocol/contracts/bridge/libs/LibBridgeData.sol index c3500e0371..ff7160de6b 100644 --- a/packages/protocol/contracts/bridge/libs/LibBridgeData.sol +++ b/packages/protocol/contracts/bridge/libs/LibBridgeData.sol @@ -20,7 +20,7 @@ library LibBridgeData { struct State { uint256 nextMessageId; IBridge.Context ctx; // 3 slots - mapping(bytes32 => bool) etherReleased; + mapping(bytes32 msgHash => bool released) etherReleased; uint256[45] __gap; } diff --git a/packages/protocol/contracts/test/libs/TestLibProving.sol b/packages/protocol/contracts/test/libs/TestLibProving.sol index 4c09f8e2ed..ff5c2d8aae 100644 --- a/packages/protocol/contracts/test/libs/TestLibProving.sol +++ b/packages/protocol/contracts/test/libs/TestLibProving.sol @@ -79,6 +79,7 @@ library TestLibProving { error L1_ANCHOR_RECEIPT_ADDR(); error L1_ANCHOR_RECEIPT_TOPICS(); error L1_ANCHOR_RECEIPT_DATA(); + error L1_HALTED(); function proveBlock( TaikoData.State storage state, @@ -87,7 +88,7 @@ library TestLibProving { uint256 blockId, bytes[] calldata inputs ) public { - assert(!LibUtils.isHalted(state)); + if (LibUtils.isHalted(state)) revert L1_HALTED(); // Check and decode inputs if (inputs.length != 3) revert L1_INPUT_SIZE(); diff --git a/packages/protocol/contracts/thirdparty/AddressManager.sol b/packages/protocol/contracts/thirdparty/AddressManager.sol index 084b75802c..115bdb4d18 100644 --- a/packages/protocol/contracts/thirdparty/AddressManager.sol +++ b/packages/protocol/contracts/thirdparty/AddressManager.sol @@ -42,7 +42,7 @@ contract AddressManager is OwnableUpgradeable { * Variables * *************/ - mapping(bytes32 => address) private addresses; + mapping(bytes32 nameHash => address addr) private addresses; /********** * Events * diff --git a/packages/protocol/contracts/thirdparty/ERC20Upgradeable.sol b/packages/protocol/contracts/thirdparty/ERC20Upgradeable.sol index 4a70cfdafc..a758f08c5e 100644 --- a/packages/protocol/contracts/thirdparty/ERC20Upgradeable.sol +++ b/packages/protocol/contracts/thirdparty/ERC20Upgradeable.sol @@ -66,9 +66,10 @@ contract ERC20Upgradeable is IERC20Upgradeable, IERC20MetadataUpgradeable { - mapping(address => uint256) private _balances; + mapping(address owner => uint256 balance) private _balances; - mapping(address => mapping(address => uint256)) private _allowances; + mapping(address owner => mapping(address spender => uint256 allowance)) + private _allowances; uint256 private _totalSupply; diff --git a/packages/protocol/hardhat.config.ts b/packages/protocol/hardhat.config.ts index 5ab36dbf53..6316a26cd5 100644 --- a/packages/protocol/hardhat.config.ts +++ b/packages/protocol/hardhat.config.ts @@ -4,6 +4,7 @@ import "@openzeppelin/hardhat-upgrades"; import "@typechain/hardhat"; import "hardhat-abi-exporter"; import "hardhat-gas-reporter"; +import "hardhat-contract-sizer"; import { HardhatUserConfig } from "hardhat/config"; import "solidity-coverage"; import "solidity-docgen"; @@ -133,7 +134,7 @@ const config: HardhatUserConfig = { }, }, }, - version: "0.8.9", + version: "0.8.18", }, }; diff --git a/packages/protocol/package.json b/packages/protocol/package.json index 7d7bacb984..1fa5b717e7 100644 --- a/packages/protocol/package.json +++ b/packages/protocol/package.json @@ -8,7 +8,7 @@ "export:abi": "pnpm hardhat clear-abi && pnpm hardhat export-abi", "export:docs": "pnpm hardhat docgen && pnpm prettier --write ../website/pages/docs/reference/contract-documentation/**/*.md", "clean": "rm -rf abis cache && pnpm hardhat clean", - "lint:sol": "pnpm prettier '**/*.sol' --write && pnpm solhint 'contracts/**/*.sol' --fix", + "lint:sol": "pnpm prettier '**/*.sol' --write", "eslint": "pnpm exec eslint --ignore-path .eslintignore --ext .js,.ts .", "eslint:fix": "pnpm exec eslint --ignore-path .eslintignore --ext .js,.ts . --fix", "test": "pnpm hardhat test --grep '^[^integration]'", @@ -18,9 +18,10 @@ "test:genesis": "./test/genesis/generate_genesis.test.sh", "test:integration": "TEST_TYPE=integration ./test/test_integration.sh", "test:tokenomics": "TEST_TYPE=tokenomics ./test/test_integration.sh", - "test:all": "pnpm run test && pnpm run test:integration && pnpm run test:tokenomics", + "test:all": "pnpm run test && pnpm run test:integration && pnpm run test:tokenomics && pnpm run test:genesis", "deploy:hardhat": "./scripts/download_solc.sh && LOG_LEVEL=debug pnpm hardhat deploy_L1 --network hardhat --dao-vault 0xdf08f82de32b8d460adbe8d72043e3a7e25a3b39 --team-vault 0xdf08f82de32b8d460adbe8d72043e3a7e25a3b39 --l2-genesis-block-hash 0xee1950562d42f0da28bd4550d88886bc90894c77c9c9eaefef775d4c8223f259 --bridge-funder-private-key ddbf12f72c946bb1e6de5eaf580c51db51828ba198d9b0dba9c7d48ec748dc04 --bridge-fund 0xff --oracle-prover 0xdf08f82de32b8d460adbe8d72043e3a7e25a3b39 --confirmations 1", - "lint-staged": "lint-staged --allow-empty" + "lint-staged": "lint-staged --allow-empty", + "sizer": "pnpm hardhat size-contracts" }, "lint-staged": { "*.sol": "pnpm lint:sol", @@ -66,15 +67,16 @@ "glob": "^8.1.0", "hardhat": "^2.8.3", "hardhat-abi-exporter": "^2.10.0", + "hardhat-contract-sizer": "^2.8.0", "hardhat-docgen": "^1.3.0", "hardhat-gas-reporter": "^1.0.7", "lint-staged": "^12.3.4", "merkle-patricia-tree": "^4.2.4", "prettier": "^2.5.1", - "prettier-plugin-solidity": "^1.0.0-beta.19", + "prettier-plugin-solidity": "^1.1.2", "rlp": "^3.0.0", - "solhint": "^3.3.7", - "solidity-coverage": "^0.8.2", + "solhint": "^3.3.8", + "solidity-coverage": "github:taikoxyz/solidity-coverage", "solidity-docgen": "^0.6.0-beta.34", "ts-node": "^10.5.0", "typechain": "^5.2.0", diff --git a/packages/protocol/scripts/download_solc.sh b/packages/protocol/scripts/download_solc.sh index 2a8f4ce95d..9c5413ac91 100755 --- a/packages/protocol/scripts/download_solc.sh +++ b/packages/protocol/scripts/download_solc.sh @@ -8,7 +8,7 @@ if [ -f "solc" ]; then exit 0 fi -VERSION=v0.8.9 +VERSION=v0.8.18 if [ "$(uname)" = 'Darwin' ]; then SOLC_FILE_NAME=solc-macos diff --git a/packages/protocol/test/L1/TaikoL1.integration.test.ts b/packages/protocol/test/L1/TaikoL1.integration.test.ts index dba6889585..581d970b99 100644 --- a/packages/protocol/test/L1/TaikoL1.integration.test.ts +++ b/packages/protocol/test/L1/TaikoL1.integration.test.ts @@ -15,14 +15,25 @@ import halt from "../utils/halt"; import { onNewL2Block } from "../utils/onNewL2Block"; import { buildProposeBlockInputs } from "../utils/propose"; import Proposer from "../utils/proposer"; -import { proveBlock } from "../utils/prove"; +import { buildProveBlockInputs, proveBlock } from "../utils/prove"; import Prover from "../utils/prover"; -import { sendTinyEtherToZeroAddress } from "../utils/seed"; -import { commitProposeProveAndVerify } from "../utils/verify"; +import { + createAndSeedWallets, + seedTko, + sendTinyEtherToZeroAddress, +} from "../utils/seed"; +import { + commitProposeProveAndVerify, + sleepUntilBlockIsVerifiable, + verifyBlocks, +} from "../utils/verify"; import { txShouldRevertWithCustomError, readShouldRevertWithCustomError, } from "../utils/errors"; +import { getBlockHeader } from "../utils/rpc"; +import Evidence from "../utils/evidence"; +import { encodeEvidence } from "../utils/encoding"; describe("integration:TaikoL1", function () { let taikoL1: TaikoL1; @@ -52,6 +63,7 @@ describe("integration:TaikoL1", function () { interval, chan, config, + tkoTokenL1, } = await initIntegrationFixture(false, false)); proposer = new Proposer( taikoL1.connect(proposerSigner), @@ -174,6 +186,60 @@ describe("integration:TaikoL1", function () { expect(forkChoice.blockHash).to.be.eq(block.hash); expect(forkChoice.provers[0]).to.be.eq(await l1Signer.getAddress()); }); + + it("returns empty after a block is verified", async function () { + const provers = (await createAndSeedWallets(2, l1Signer)).map( + (p: ethersLib.Wallet) => new Prover(taikoL1, l2Provider, p) + ); + + await seedTko(provers, tkoTokenL1.connect(l1Signer)); + + l2Provider.on("block", blockListener(chan, genesisHeight)); + + /* eslint-disable-next-line */ + for await (const blockNumber of chan) { + if ( + blockNumber > + genesisHeight + config.maxNumBlocks.toNumber() - 1 + ) { + break; + } + + const block = await l2Provider.getBlock(blockNumber); + + // commit and propose block, so our provers can prove it. + const { proposedEvent } = await proposer.commitThenProposeBlock( + block + ); + + await provers[0].prove( + proposedEvent.args.id.toNumber(), + blockNumber, + proposedEvent.args.meta as any as BlockMetadata + ); + + let forkChoice = await taikoL1.getForkChoice( + proposedEvent.args.id.toNumber(), + block.parentHash + ); + expect(forkChoice).not.to.be.undefined; + expect(forkChoice.provers.length).to.be.eq(1); + + await sleepUntilBlockIsVerifiable( + taikoL1, + proposedEvent.args.id.toNumber(), + 0 + ); + const verifiedEvent = await verifyBlocks(taikoL1, 1); + expect(verifiedEvent).not.to.be.undefined; + + forkChoice = await taikoL1.getForkChoice( + proposedEvent.args.id.toNumber(), + block.parentHash + ); + expect(forkChoice.provers.length).to.be.eq(0); + } + }); }); describe("commitBlock() -> proposeBlock() integration", async function () { @@ -397,4 +463,263 @@ describe("integration:TaikoL1", function () { ); }); }); + + describe("proveBlock", function () { + it("can not be called if chain is halted", async function () { + await halt(taikoL1.connect(l1Signer), true); + const txPromise = ( + await taikoL1.proveBlock(1, [], { gasLimit: 1000000 }) + ).wait(1); + await txShouldRevertWithCustomError( + txPromise, + l1Provider, + "L1_HALTED()" + ); + }); + + it("reverts when inputs is incorrect length", async function () { + for (let i = 1; i <= 2; i++) { + const txPromise = ( + await taikoL1.proveBlock( + 1, + new Array(i).fill(ethers.constants.HashZero), + { + gasLimit: 1000000, + } + ) + ).wait(1); + await txShouldRevertWithCustomError( + txPromise, + l1Provider, + "L1_INPUT_SIZE()" + ); + } + }); + + it("reverts when evidence meta id is not the same as the blockId", async function () { + l2Provider.on("block", blockListener(chan, genesisHeight)); + + const config = await taikoL1.getConfig(); + /* eslint-disable-next-line */ + for await (const blockNumber of chan) { + if ( + blockNumber > + genesisHeight + config.maxNumBlocks.toNumber() - 1 + ) { + break; + } + + const block = await l2Provider.getBlock(blockNumber); + + // commit and propose block, so our provers can prove it. + const { proposedEvent } = await proposer.commitThenProposeBlock( + block + ); + + const header = await getBlockHeader(l2Provider, blockNumber); + const inputs = buildProveBlockInputs( + proposedEvent.args.meta as any as BlockMetadata, + header.blockHeader, + await prover.getSigner().getAddress(), + "0x", + "0x", + config.zkProofsPerBlock.toNumber() + ); + + const txPromise = ( + await taikoL1.proveBlock( + proposedEvent.args.meta.id.toNumber() + 1, // id different than meta + inputs, + { + gasLimit: 2000000, + } + ) + ).wait(1); + + await txShouldRevertWithCustomError( + txPromise, + l1Provider, + "L1_ID()" + ); + } + }); + it("reverts when evidence proofs length is less than 2 + zkProofsPerBlock set in the config", async function () { + l2Provider.on("block", blockListener(chan, genesisHeight)); + + const config = await taikoL1.getConfig(); + /* eslint-disable-next-line */ + for await (const blockNumber of chan) { + if ( + blockNumber > + genesisHeight + config.maxNumBlocks.toNumber() - 1 + ) { + break; + } + + const block = await l2Provider.getBlock(blockNumber); + + // commit and propose block, so our provers can prove it. + const { proposedEvent } = await proposer.commitThenProposeBlock( + block + ); + + const header = await getBlockHeader(l2Provider, blockNumber); + const inputs = []; + const evidence: Evidence = { + meta: proposedEvent.args.meta as any as BlockMetadata, + header: header.blockHeader, + prover: await prover.getSigner().getAddress(), + proofs: [], // keep proofs array empty to fail check + circuits: [], + }; + + for (let i = 0; i < config.zkProofsPerBlock.toNumber(); i++) { + evidence.circuits.push(1); + } + + inputs[0] = encodeEvidence(evidence); + inputs[1] = "0x"; + inputs[2] = "0x"; + + const txPromise = ( + await taikoL1.proveBlock( + proposedEvent.args.meta.id.toNumber(), // id different than meta + inputs, + { + gasLimit: 2000000, + } + ) + ).wait(1); + + await txShouldRevertWithCustomError( + txPromise, + l1Provider, + "L1_PROOF_LENGTH()" + ); + } + }); + it("reverts when evidence circuits length is less than zkProofsPerBlock set in the config", async function () { + l2Provider.on("block", blockListener(chan, genesisHeight)); + + const config = await taikoL1.getConfig(); + /* eslint-disable-next-line */ + for await (const blockNumber of chan) { + if ( + blockNumber > + genesisHeight + config.maxNumBlocks.toNumber() - 1 + ) { + break; + } + + const block = await l2Provider.getBlock(blockNumber); + + // commit and propose block, so our provers can prove it. + const { proposedEvent } = await proposer.commitThenProposeBlock( + block + ); + + const header = await getBlockHeader(l2Provider, blockNumber); + const inputs = []; + const evidence: Evidence = { + meta: proposedEvent.args.meta as any as BlockMetadata, + header: header.blockHeader, + prover: await prover.getSigner().getAddress(), + proofs: [], + circuits: [], // keep circuits array empty to fail check + }; + + for ( + let i = 0; + i < config.zkProofsPerBlock.toNumber() + 2; + i++ + ) { + evidence.proofs.push("0xff"); + } + + inputs[0] = encodeEvidence(evidence); + inputs[1] = "0x"; + inputs[2] = "0x"; + + const txPromise = ( + await taikoL1.proveBlock( + proposedEvent.args.meta.id.toNumber(), // id different than meta + inputs, + { + gasLimit: 2000000, + } + ) + ).wait(1); + + await txShouldRevertWithCustomError( + txPromise, + l1Provider, + "L1_CIRCUIT_LENGTH()" + ); + } + }); + + it("reverts when prover is the zero address", async function () { + l2Provider.on("block", blockListener(chan, genesisHeight)); + + const config = await taikoL1.getConfig(); + /* eslint-disable-next-line */ + for await (const blockNumber of chan) { + if ( + blockNumber > + genesisHeight + config.maxNumBlocks.toNumber() - 1 + ) { + break; + } + + const block = await l2Provider.getBlock(blockNumber); + + // commit and propose block, so our provers can prove it. + const { proposedEvent } = await proposer.commitThenProposeBlock( + block + ); + + const header = await getBlockHeader(l2Provider, blockNumber); + const inputs = []; + const evidence: Evidence = { + meta: proposedEvent.args.meta as any as BlockMetadata, + header: header.blockHeader, + prover: ethers.constants.AddressZero, + proofs: [], + circuits: [], + }; + + for (let i = 0; i < config.zkProofsPerBlock.toNumber(); i++) { + evidence.circuits.push(1); + } + + for ( + let i = 0; + i < config.zkProofsPerBlock.toNumber() + 2; + i++ + ) { + evidence.proofs.push("0xff"); + } + + inputs[0] = encodeEvidence(evidence); + inputs[1] = "0x"; + inputs[2] = "0x"; + + const txPromise = ( + await taikoL1.proveBlock( + proposedEvent.args.meta.id.toNumber(), // id different than meta + inputs, + { + gasLimit: 2000000, + } + ) + ).wait(1); + + await txShouldRevertWithCustomError( + txPromise, + l1Provider, + "L1_PROVER()" + ); + } + }); + }); }); diff --git a/packages/protocol/test/tokenVault/TokenVault.test.ts b/packages/protocol/test/tokenVault/TokenVault.test.ts index 746c247ae7..7de260f6f0 100644 --- a/packages/protocol/test/tokenVault/TokenVault.test.ts +++ b/packages/protocol/test/tokenVault/TokenVault.test.ts @@ -132,7 +132,7 @@ describe("TokenVault", function () { owner.address, "" ) - ).to.be.revertedWith("V:msgValue"); + ).to.be.revertedWith("TOKENVAULT_INVALID_VALUE()"); }); it("throws when msg.value - processing fee is 0", async () => { @@ -148,7 +148,7 @@ describe("TokenVault", function () { value: defaultProcessingFee, } ) - ).to.be.revertedWith("V:msgValue"); + ).to.be.revertedWith("TOKENVAULT_INVALID_VALUE()"); }); it("throws when msg.value is < processingFee", async () => { @@ -164,7 +164,7 @@ describe("TokenVault", function () { value: defaultProcessingFee - 1, } ) - ).to.be.revertedWith("V:msgValue"); + ).to.be.revertedWith("TOKENVAULT_INVALID_VALUE()"); }); it("throws when to is 0", async () => { @@ -180,7 +180,7 @@ describe("TokenVault", function () { value: defaultProcessingFee - 1, } ) - ).to.be.revertedWith("V:to"); + ).to.be.revertedWith("TOKENVAULT_INVALID_TO()"); }); it("succeeds with processingFee", async () => { @@ -258,7 +258,7 @@ describe("TokenVault", function () { value: 1, } ) - ).to.be.revertedWith("V:to"); + ).to.be.revertedWith("TOKENVAULT_INVALID_TO()"); }); it("should throw if to == destChainId.token_vault", async function () { @@ -276,7 +276,7 @@ describe("TokenVault", function () { value: 1, } ) - ).to.be.revertedWith("V:to"); + ).to.be.revertedWith("TOKENVAULT_INVALID_TO()"); }); it("should throw if token == address(0)", async function () { @@ -294,7 +294,7 @@ describe("TokenVault", function () { value: 1, } ) - ).to.be.revertedWith("V:token"); + ).to.be.revertedWith("TOKENVAULT_INVALID_TOKEN()"); }); it("should throw if amount <= 0", async function () { @@ -312,7 +312,7 @@ describe("TokenVault", function () { value: 1, } ) - ).to.be.revertedWith("V:amount"); + ).to.be.revertedWith("TOKENVAULT_INVALID_AMOUNT()"); }); it("should throw if isBridgedToken, and canonicalToken.addr == address(0)", async function () { @@ -335,7 +335,7 @@ describe("TokenVault", function () { value: 1, } ) - ).to.be.revertedWith("V:canonicalToken"); + ).to.be.revertedWith("TOKENVAULT_CANONICAL_TOKEN_NOT_FOUND()"); }); it("should pass and emit ERC20Sent Event", async function () { diff --git a/packages/protocol/test/tokenomics/proofReward.test.ts b/packages/protocol/test/tokenomics/proofReward.test.ts index 0b349e659a..4a34c34d9e 100644 --- a/packages/protocol/test/tokenomics/proofReward.test.ts +++ b/packages/protocol/test/tokenomics/proofReward.test.ts @@ -7,9 +7,14 @@ import { pickRandomElement } from "../utils/array"; import blockListener from "../utils/blockListener"; import Proposer from "../utils/proposer"; import Prover from "../utils/prover"; -import { createAndSeedWallets } from "../utils/seed"; -import { commitProposeProveAndVerify } from "../utils/verify"; +import { createAndSeedWallets, seedTko } from "../utils/seed"; +import { + commitProposeProveAndVerify, + sleepUntilBlockIsVerifiable, + verifyBlocks, +} from "../utils/verify"; import { initIntegrationFixture } from "../utils/fixture"; +import { BlockMetadata } from "../utils/block_metadata"; describe("tokenomics: proofReward", function () { let taikoL1: TaikoL1; @@ -93,14 +98,8 @@ describe("tokenomics: proofReward", function () { they receive the proofReward. the proposer should receive a refund on his deposit because he holds a tkoBalance > 0 at time of verification.`, async function () { // prover needs TKO or their reward will be cut down to 1 wei. - await ( - await tkoTokenL1 - .connect(l1Signer) - .mintAnyone( - await proverSigner.getAddress(), - ethers.utils.parseEther("100") - ) - ).wait(1); + + await seedTko([prover], tkoTokenL1.connect(l1Signer)); l2Provider.on("block", blockListener(chan, genesisHeight)); @@ -157,26 +156,9 @@ describe("tokenomics: proofReward", function () { (p: ethers.Wallet) => new Prover(taikoL1, l2Provider, p) ); - for (const prover of provers) { - await ( - await tkoTokenL1 - .connect(l1Signer) - .mintAnyone( - await prover.getSigner().getAddress(), - ethers.utils.parseEther("10000") - ) - ).wait(1); - } - for (const proposer of proposers) { - await ( - await tkoTokenL1 - .connect(l1Signer) - .mintAnyone( - await proposer.getSigner().getAddress(), - ethers.utils.parseEther("10000") - ) - ).wait(1); - } + await seedTko(provers, tkoTokenL1.connect(l1Signer)); + + await seedTko(proposers, tkoTokenL1.connect(l1Signer)); // prover needs TKO or their reward will be cut down to 1 wei. await ( @@ -192,7 +174,10 @@ describe("tokenomics: proofReward", function () { /* eslint-disable-next-line */ for await (const blockNumber of chan) { - if (blockNumber > genesisHeight + config.maxNumBlocks.toNumber()) { + if ( + blockNumber > + genesisHeight + (config.maxNumBlocks.toNumber() - 1) + ) { break; } const prover = pickRandomElement(provers); @@ -229,4 +214,76 @@ describe("tokenomics: proofReward", function () { ); } }); + + it(`asserts that with N provers, where N is config.maxProofsPerForkChoice all provers who submit proofs are paid with decreasing weight from the first prover to the Nth`, async function () { + const provers = ( + await createAndSeedWallets( + config.maxProofsPerForkChoice.toNumber(), + l1Signer + ) + ).map((p: ethers.Wallet) => new Prover(taikoL1, l2Provider, p)); + + await seedTko(provers, tkoTokenL1.connect(l1Signer)); + + l2Provider.on("block", blockListener(chan, genesisHeight)); + + /* eslint-disable-next-line */ + for await (const blockNumber of chan) { + if ( + blockNumber > + genesisHeight + (config.maxNumBlocks.toNumber() - 1) + ) { + break; + } + + const block = await l2Provider.getBlock(blockNumber); + + // commit and propose block, so our provers can prove it. + const { proposedEvent } = await proposer.commitThenProposeBlock( + block + ); + + // submit a proof for each prover + for (const prover of provers) { + await prover.prove( + proposedEvent.args.id.toNumber(), + blockNumber, + proposedEvent.args.meta as any as BlockMetadata + ); + } + + const forkChoice = await taikoL1.getForkChoice( + proposedEvent.args.id.toNumber(), + block.parentHash + ); + expect(forkChoice).not.to.be.undefined; + expect(forkChoice.provers.length).to.be.eq( + config.maxProofsPerForkChoice.toNumber() + ); + + await sleepUntilBlockIsVerifiable( + taikoL1, + proposedEvent.args.id.toNumber(), + 0 + ); + await verifyBlocks(taikoL1, 1); + + // all provers had same initial TKO balance. + // each prover in order should have less balance than the previous. + for (let i = 0; i < forkChoice.provers.length; i++) { + if (i !== 0) { + const proverBalance = await tkoTokenL1.balanceOf( + forkChoice.provers[i] + ); + const previousProverBalance = await tkoTokenL1.balanceOf( + forkChoice.provers[i - 1] + ); + + expect(previousProverBalance.gt(proverBalance)).to.be.eq( + true + ); + } + } + } + }); }); diff --git a/packages/protocol/test/utils/commit.ts b/packages/protocol/test/utils/commit.ts index e569e7d429..2c435e43bd 100644 --- a/packages/protocol/test/utils/commit.ts +++ b/packages/protocol/test/utils/commit.ts @@ -66,9 +66,9 @@ const commitAndProposeLatestBlock = async ( commit.txListHash, commitReceipt.blockNumber as number, block.gasLimit, - commitSlot, - { gasLimit: 500000 } + commitSlot ); + const proposedEvent: BlockProposedEvent = ( proposeReceipt.events as any[] ).find((e) => e.event === "BlockProposed"); diff --git a/packages/protocol/test/utils/errors.ts b/packages/protocol/test/utils/errors.ts index 3c9af52553..0640d7252f 100644 --- a/packages/protocol/test/utils/errors.ts +++ b/packages/protocol/test/utils/errors.ts @@ -4,26 +4,31 @@ import { expect } from "chai"; async function txShouldRevertWithCustomError( txPromise: Promise, provider: ethers.providers.JsonRpcProvider, - customError: String + customError: string ) { try { await txPromise; expect.fail("Expected promise to throw but it didn't"); } catch (tx) { // console.log(tx) - const _tx = await provider.getTransaction(tx.transactionHash); - // console.log(_tx) - const code = await provider.call(_tx, _tx.blockNumber); + const _tx = await provider.getTransaction( + (tx as { transactionHash: string }).transactionHash + ); + const code = await provider.call( + _tx as ethers.providers.TransactionRequest, + _tx.blockNumber + ); + const expectedCode = utils .keccak256(utils.toUtf8Bytes(customError)) .substring(0, 10); if (code !== expectedCode) { expect.fail( - "Error code mismatch: actual=", - code, - "expected=", - expectedCode + `Error code mismatch: actual= + ${code} + expected= + ${expectedCode}` ); } } @@ -31,19 +36,20 @@ async function txShouldRevertWithCustomError( async function readShouldRevertWithCustomError( txPromise: Promise, - customError: String + customError: string ) { try { await txPromise; expect.fail("Expected promise to throw but it didn't"); } catch (result) { - if (result.errorSignature !== customError) { + const r = result as { errorSignature: string }; + if (r.errorSignature !== customError) { expect.fail( - "Error code mismatch: actual=", - result.errorSignature, - "expected=", - customError + `Error code mismatch: actual= + ${r.errorSignature} + "expected=" + ${customError}` ); } } diff --git a/packages/protocol/test/utils/onNewL2Block.ts b/packages/protocol/test/utils/onNewL2Block.ts index e1691da027..4fae746d31 100644 --- a/packages/protocol/test/utils/onNewL2Block.ts +++ b/packages/protocol/test/utils/onNewL2Block.ts @@ -22,11 +22,7 @@ async function onNewL2Block( newProofReward: BigNumber; }> { const block = await l2Provider.getBlock(blockNumber); - const receipt = await proposer.commitThenProposeBlock(block); - const proposedEvent: BlockProposedEvent = (receipt.events as any[]).find( - (e) => e.event === "BlockProposed" - ); - + const { proposedEvent } = await proposer.commitThenProposeBlock(block); const { id, meta } = proposedEvent.args; const { enableTokenomics } = await taikoL1.getConfig(); diff --git a/packages/protocol/test/utils/proposer.ts b/packages/protocol/test/utils/proposer.ts index fc74286dd3..34a69dd666 100644 --- a/packages/protocol/test/utils/proposer.ts +++ b/packages/protocol/test/utils/proposer.ts @@ -1,5 +1,6 @@ import { ethers } from "ethers"; import { TaikoL1 } from "../../typechain"; +import { BlockProposedEvent } from "../../typechain/LibProposing"; import { commitBlock } from "./commit"; import { proposeBlock } from "./propose"; import sleep from "./sleep"; @@ -58,9 +59,13 @@ class Proposer { commitSlot ); + const proposedEvent: BlockProposedEvent = ( + receipt.events as any[] + ).find((e) => e.event === "BlockProposed"); + this.proposingMutex = false; - return receipt; + return { receipt, proposedEvent }; } finally { this.proposingMutex = false; } diff --git a/packages/protocol/test/utils/prover.ts b/packages/protocol/test/utils/prover.ts index 1c9960d173..df1bed6b2d 100644 --- a/packages/protocol/test/utils/prover.ts +++ b/packages/protocol/test/utils/prover.ts @@ -26,7 +26,6 @@ class Prover { } async prove( - proverAddress: string, blockId: number, blockNumber: number, meta: BlockMetadata @@ -41,7 +40,7 @@ class Prover { blockProvenEvent = await proveBlock( this.taikoL1, this.l2Provider, - proverAddress, + await this.getSigner().getAddress(), blockId, blockNumber, meta diff --git a/packages/protocol/test/utils/seed.ts b/packages/protocol/test/utils/seed.ts index ba4431c5fb..88f073387b 100644 --- a/packages/protocol/test/utils/seed.ts +++ b/packages/protocol/test/utils/seed.ts @@ -1,4 +1,5 @@ import { BigNumber, ethers } from "ethers"; +import { TestTkoToken } from "../../typechain"; const createAndSeedWallets = async ( len: number, @@ -30,4 +31,19 @@ const sendTinyEtherToZeroAddress = async (signer: any) => { await tx.wait(1); }; -export { createAndSeedWallets, sendTinyEtherToZeroAddress }; +const seedTko = async ( + wallets: { getSigner: () => ethers.Wallet }[], + tkoToken: TestTkoToken +) => { + for (const wallet of wallets) { + // prover needs TKO or their reward will be cut down to 1 wei. + await ( + await tkoToken.mintAnyone( + await wallet.getSigner().getAddress(), + ethers.utils.parseEther("100") + ) + ).wait(1); + } +}; + +export { createAndSeedWallets, sendTinyEtherToZeroAddress, seedTko }; diff --git a/packages/protocol/test/utils/verify.ts b/packages/protocol/test/utils/verify.ts index 4e67c2390a..ef16ac0d37 100644 --- a/packages/protocol/test/utils/verify.ts +++ b/packages/protocol/test/utils/verify.ts @@ -116,7 +116,6 @@ async function commitProposeProveAndVerify( console.log("proving", blockNumber); const provedEvent = await prover.prove( - await prover.getSigner().getAddress(), proposedEvent.args.id.toNumber(), blockNumber, proposedEvent.args.meta as any as BlockMetadata @@ -173,6 +172,7 @@ async function commitProposeProveAndVerify( } export { + verifyBlocks, verifyBlockAndAssert, sleepUntilBlockIsVerifiable, commitProposeProveAndVerify, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 67825e0489..255abd625e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -151,15 +151,16 @@ importers: glob: ^8.1.0 hardhat: ^2.8.3 hardhat-abi-exporter: ^2.10.0 + hardhat-contract-sizer: ^2.8.0 hardhat-docgen: ^1.3.0 hardhat-gas-reporter: ^1.0.7 lint-staged: ^12.3.4 merkle-patricia-tree: ^4.2.4 prettier: ^2.5.1 - prettier-plugin-solidity: ^1.0.0-beta.19 + prettier-plugin-solidity: ^1.1.2 rlp: ^3.0.0 - solhint: ^3.3.7 - solidity-coverage: ^0.8.2 + solhint: ^3.3.8 + solidity-coverage: github:taikoxyz/solidity-coverage solidity-docgen: ^0.6.0-beta.34 ts-node: ^10.5.0 typechain: ^5.2.0 @@ -199,15 +200,16 @@ importers: glob: 8.1.0 hardhat: 2.12.2_2dtigtkb225m7ii7q45utxqwgi hardhat-abi-exporter: 2.10.1_hardhat@2.12.2 + hardhat-contract-sizer: 2.8.0_hardhat@2.12.2 hardhat-docgen: 1.3.0_lfwxduevmqdtswpjkbv2koayie hardhat-gas-reporter: 1.0.9_hardhat@2.12.2 lint-staged: 12.5.0 merkle-patricia-tree: 4.2.4 prettier: 2.8.0 - prettier-plugin-solidity: 1.0.0_prettier@2.8.0 + prettier-plugin-solidity: 1.1.2_prettier@2.8.0 rlp: 3.0.0 - solhint: 3.3.7 - solidity-coverage: 0.8.2_hardhat@2.12.2 + solhint: 3.3.8 + solidity-coverage: github.com/taikoxyz/solidity-coverage/ceb49fd1f6041e4fcd26079dfb0d3b0f58c812e5_hardhat@2.12.2 solidity-docgen: 0.6.0-beta.34_hardhat@2.12.2 ts-node: 10.9.1_vw4thnff6td543szquzqpxymti typechain: 5.2.0_typescript@4.9.3 @@ -1577,6 +1579,13 @@ packages: - utf-8-validate dev: false + /@colors/colors/1.5.0: + resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} + engines: {node: '>=0.1.90'} + requiresBuild: true + dev: true + optional: true + /@cspotcode/source-map-support/0.8.1: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} @@ -2053,13 +2062,13 @@ packages: resolution: {integrity: sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==} dependencies: '@formatjs/intl-localematcher': 0.2.25 - tslib: 2.4.1 + tslib: 2.5.0 dev: false /@formatjs/fast-memoize/1.2.1: resolution: {integrity: sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg==} dependencies: - tslib: 2.4.1 + tslib: 2.5.0 dev: false /@formatjs/icu-messageformat-parser/2.1.0: @@ -2067,20 +2076,20 @@ packages: dependencies: '@formatjs/ecma402-abstract': 1.11.4 '@formatjs/icu-skeleton-parser': 1.3.6 - tslib: 2.4.1 + tslib: 2.5.0 dev: false /@formatjs/icu-skeleton-parser/1.3.6: resolution: {integrity: sha512-I96mOxvml/YLrwU2Txnd4klA7V8fRhb6JG/4hm3VMNmeJo1F03IpV2L3wWt7EweqNLES59SZ4d6hVOPCSf80Bg==} dependencies: '@formatjs/ecma402-abstract': 1.11.4 - tslib: 2.4.1 + tslib: 2.5.0 dev: false /@formatjs/intl-localematcher/0.2.25: resolution: {integrity: sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==} dependencies: - tslib: 2.4.1 + tslib: 2.5.0 dev: false /@gar/promisify/1.1.3: @@ -2173,7 +2182,7 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.5.1 - '@types/node': 18.11.18 + '@types/node': 18.13.0 chalk: 4.1.2 jest-message-util: 27.5.1 jest-util: 27.5.1 @@ -2194,7 +2203,7 @@ packages: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 18.11.18 + '@types/node': 18.13.0 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.8.1 @@ -2231,7 +2240,7 @@ packages: dependencies: '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 18.11.18 + '@types/node': 18.13.0 jest-mock: 27.5.1 dev: true @@ -2241,7 +2250,7 @@ packages: dependencies: '@jest/types': 27.5.1 '@sinonjs/fake-timers': 8.1.0 - '@types/node': 18.11.18 + '@types/node': 18.13.0 jest-message-util: 27.5.1 jest-mock: 27.5.1 jest-util: 27.5.1 @@ -2270,7 +2279,7 @@ packages: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 18.11.18 + '@types/node': 18.13.0 chalk: 4.1.2 collect-v8-coverage: 1.0.1 exit: 0.1.2 @@ -2354,7 +2363,7 @@ packages: dependencies: '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.1 - '@types/node': 18.11.18 + '@types/node': 18.13.0 '@types/yargs': 16.0.4 chalk: 4.1.2 dev: true @@ -3357,6 +3366,12 @@ packages: antlr4ts: 0.5.0-alpha.4 dev: true + /@solidity-parser/parser/0.15.0: + resolution: {integrity: sha512-5UFJJTzWi1hgFk6aGCZ5rxG2DJkCJOzJ74qg7UkWSNCDSigW+CJLoYUb5bLiKrtI34Nr9rpFSUNHfkqtlL+N/w==} + dependencies: + antlr4ts: 0.5.0-alpha.4 + dev: true + /@sveltejs/vite-plugin-svelte/1.3.1_svelte@3.53.1+vite@3.2.4: resolution: {integrity: sha512-2Uu2sDdIR+XQWF7QWOVSF2jR9EU6Ciw1yWfYnfLYj8HIgnNxkh/8g22Fw2pBUI8QNyW/KxtqJUWBI+8ypamSrQ==} engines: {node: ^14.18.0 || >= 16} @@ -3525,12 +3540,12 @@ packages: /@types/bn.js/4.11.6: resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.13.0 /@types/bn.js/5.1.1: resolution: {integrity: sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.13.0 dev: true /@types/cacheable-request/6.0.3: @@ -3538,7 +3553,7 @@ packages: dependencies: '@types/http-cache-semantics': 4.0.1 '@types/keyv': 3.1.4 - '@types/node': 18.11.18 + '@types/node': 18.13.0 '@types/responselike': 1.0.0 dev: true optional: true @@ -3550,13 +3565,13 @@ packages: /@types/concat-stream/1.6.1: resolution: {integrity: sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.13.0 dev: true /@types/connect/3.4.35: resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.13.0 dev: false /@types/debug/4.1.7: @@ -3603,14 +3618,14 @@ packages: /@types/form-data/0.0.33: resolution: {integrity: sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.13.0 dev: true /@types/glob/7.2.0: resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} dependencies: '@types/minimatch': 5.1.2 - '@types/node': 18.11.18 + '@types/node': 18.13.0 dev: true /@types/glob/8.0.1: @@ -3623,7 +3638,7 @@ packages: /@types/graceful-fs/4.1.5: resolution: {integrity: sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.13.0 dev: true /@types/hast/2.3.4: @@ -3683,7 +3698,7 @@ packages: /@types/keyv/3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.13.0 dev: true optional: true @@ -3696,7 +3711,7 @@ packages: dependencies: '@types/abstract-leveldown': 7.2.0 '@types/level-errors': 3.0.0 - '@types/node': 18.11.18 + '@types/node': 18.13.0 dev: true /@types/lru-cache/5.1.1: @@ -3728,7 +3743,7 @@ packages: /@types/mkdirp/0.5.2: resolution: {integrity: sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.13.0 dev: true /@types/mocha/9.1.1: @@ -3742,7 +3757,7 @@ packages: /@types/node-fetch/2.6.2: resolution: {integrity: sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.13.0 form-data: 3.0.1 dev: true @@ -3755,10 +3770,10 @@ packages: /@types/node/18.11.18: resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==} + dev: true /@types/node/18.13.0: resolution: {integrity: sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==} - dev: true /@types/node/8.10.66: resolution: {integrity: sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==} @@ -3775,7 +3790,7 @@ packages: /@types/pbkdf2/3.1.0: resolution: {integrity: sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.13.0 /@types/prettier/2.7.1: resolution: {integrity: sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==} @@ -3802,13 +3817,13 @@ packages: /@types/resolve/0.0.8: resolution: {integrity: sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.13.0 dev: true /@types/responselike/1.0.0: resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.13.0 dev: true optional: true @@ -3821,7 +3836,7 @@ packages: /@types/sass/1.43.1: resolution: {integrity: sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.13.0 dev: true /@types/scheduler/0.16.2: @@ -3830,7 +3845,7 @@ packages: /@types/secp256k1/4.0.3: resolution: {integrity: sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.13.0 /@types/semver/7.3.13: resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==} @@ -3875,7 +3890,7 @@ packages: /@types/ws/7.4.7: resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.13.0 dev: false /@types/yargs-parser/21.0.0: @@ -4794,10 +4809,9 @@ packages: resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} engines: {node: '>=0.4.0'} hasBin: true - dev: false - /address/1.2.1: - resolution: {integrity: sha512-B+6bi5D34+fDYENiH5qOlA0cV2rAGKuWZ9LeyUUehbXy8e0VS9e498yO0Jeeh+iM+6KbfudHTFjXw2MmJD4QRA==} + /address/1.2.2: + resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} engines: {node: '>= 10.0.0'} dev: true @@ -5183,7 +5197,7 @@ packages: /async-mutex/0.2.6: resolution: {integrity: sha512-Hs4R+4SPgamu6rSGW8C7cV9gaWUKEHykfzCCvIRuaVv636Ju10ZdeUbvb4TBEW0INuq2DHZqXbK4Nd3yG4RaRw==} dependencies: - tslib: 2.4.1 + tslib: 2.5.0 dev: false /async/1.5.2: @@ -6449,7 +6463,7 @@ packages: resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} dependencies: pascal-case: 3.1.2 - tslib: 2.4.1 + tslib: 2.5.0 dev: true /camelcase-css/2.0.1: @@ -6763,6 +6777,15 @@ packages: colors: 1.4.0 dev: true + /cli-table3/0.6.3: + resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==} + engines: {node: 10.* || >= 12.*} + dependencies: + string-width: 4.2.3 + optionalDependencies: + '@colors/colors': 1.5.0 + dev: true + /cli-truncate/2.1.0: resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} engines: {node: '>=8'} @@ -7789,7 +7812,7 @@ packages: resolution: {integrity: sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==} hasBin: true dependencies: - address: 1.2.1 + address: 1.2.2 debug: 4.3.4 transitivePeerDependencies: - supports-color @@ -7844,7 +7867,7 @@ packages: /difflib/0.2.4: resolution: {integrity: sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==} dependencies: - heap: 0.2.7 + heap: 0.2.6 dev: true /dijkstrajs/1.0.2: @@ -7924,7 +7947,7 @@ packages: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} dependencies: no-case: 3.0.4 - tslib: 2.4.1 + tslib: 2.5.0 dev: true /dotenv/10.0.0: @@ -7998,10 +8021,6 @@ packages: engines: {node: '>=10'} dev: true - /emoji-regex/10.2.1: - resolution: {integrity: sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==} - dev: true - /emoji-regex/7.0.3: resolution: {integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==} @@ -8962,7 +8981,7 @@ packages: /eth-json-rpc-middleware/1.6.0: resolution: {integrity: sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q==} dependencies: - async: 2.6.2 + async: 2.6.4 eth-query: 2.1.2 eth-tx-summary: 3.2.4 ethereumjs-block: 1.7.1 @@ -9062,7 +9081,7 @@ packages: /eth-tx-summary/3.2.4: resolution: {integrity: sha512-NtlDnaVZah146Rm8HMRUNMgIwG/ED4jiqk0TME9zFheMl1jOp6jL1m0NKGjJwehXQ6ZKCPr16MTr+qspKpEXNg==} dependencies: - async: 2.6.2 + async: 2.6.4 clone: 2.1.2 concat-stream: 1.6.2 end-of-stream: 1.4.4 @@ -9179,7 +9198,7 @@ packages: resolution: {integrity: sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==} deprecated: 'New package name format for new versions: @ethereumjs/block. Please update.' dependencies: - async: 2.6.2 + async: 2.6.4 ethereum-common: 0.2.0 ethereumjs-tx: 1.3.7 ethereumjs-util: 5.2.1 @@ -9281,7 +9300,7 @@ packages: resolution: {integrity: sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw==} deprecated: 'New package name format for new versions: @ethereumjs/vm. Please update.' dependencies: - async: 2.6.2 + async: 2.6.4 async-eventemitter: 0.2.4 ethereumjs-account: 2.0.5 ethereumjs-block: 2.2.2 @@ -9298,7 +9317,7 @@ packages: resolution: {integrity: sha512-X6qqZbsY33p5FTuZqCnQ4+lo957iUJMM6Mpa6bL4UW0dxM6WmDSHuI4j/zOp1E2TDKImBGCJA9QPfc08PaNubA==} deprecated: 'New package name format for new versions: @ethereumjs/vm. Please update.' dependencies: - async: 2.6.2 + async: 2.6.4 async-eventemitter: 0.2.4 core-js-pure: 3.26.1 ethereumjs-account: 3.0.0 @@ -10485,6 +10504,17 @@ packages: hardhat: 2.12.2_2dtigtkb225m7ii7q45utxqwgi dev: true + /hardhat-contract-sizer/2.8.0_hardhat@2.12.2: + resolution: {integrity: sha512-jXt2Si3uIDx5z99J+gvKa0yvIw156pE4dpH9X/PvTQv652BUd+qGj7WT93PXnHXGh5qhQLkjDYeZMYNOThfjFg==} + peerDependencies: + hardhat: ^2.0.0 + dependencies: + chalk: 4.1.2 + cli-table3: 0.6.3 + hardhat: 2.12.2_2dtigtkb225m7ii7q45utxqwgi + strip-ansi: 6.0.1 + dev: true + /hardhat-docgen/1.3.0_lfwxduevmqdtswpjkbv2koayie: resolution: {integrity: sha512-paaiOHjJFLCLz2/qM1TQ7ZEG+Vy+LBvJL+SW4A64ZhBnVnyoZ/zv9DvEuawaWhqP5P7AOM6r22reVz4ecWgW7A==} engines: {node: '>=14.14.0'} @@ -10845,10 +10875,6 @@ packages: resolution: {integrity: sha512-MzzWcnfB1e4EG2vHi3dXHoBupmuXNZzx6pY6HldVS55JKKBoq3xOyzfSaZRkJp37HIhEYC78knabHff3zc4dQQ==} dev: true - /heap/0.2.7: - resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} - dev: true - /hmac-drbg/1.0.1: resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} dependencies: @@ -11738,7 +11764,7 @@ packages: '@jest/environment': 27.5.1 '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 18.11.18 + '@types/node': 18.13.0 chalk: 4.1.2 co: 4.6.0 dedent: 0.7.0 @@ -11863,7 +11889,7 @@ packages: '@jest/environment': 27.5.1 '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 18.11.18 + '@types/node': 18.13.0 jest-mock: 27.5.1 jest-util: 27.5.1 jsdom: 16.7.0 @@ -11881,7 +11907,7 @@ packages: '@jest/environment': 27.5.1 '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 18.11.18 + '@types/node': 18.13.0 jest-mock: 27.5.1 jest-util: 27.5.1 dev: true @@ -11897,7 +11923,7 @@ packages: dependencies: '@jest/types': 27.5.1 '@types/graceful-fs': 4.1.5 - '@types/node': 18.11.18 + '@types/node': 18.13.0 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.10 @@ -11919,7 +11945,7 @@ packages: '@jest/source-map': 27.5.1 '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 18.11.18 + '@types/node': 18.13.0 chalk: 4.1.2 co: 4.6.0 expect: 27.5.1 @@ -11974,7 +12000,7 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.5.1 - '@types/node': 18.11.18 + '@types/node': 18.13.0 dev: true /jest-pnp-resolver/1.2.3_jest-resolve@27.5.1: @@ -12030,7 +12056,7 @@ packages: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 18.11.18 + '@types/node': 18.13.0 chalk: 4.1.2 emittery: 0.8.1 graceful-fs: 4.2.10 @@ -12087,7 +12113,7 @@ packages: resolution: {integrity: sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.13.0 graceful-fs: 4.2.10 dev: true @@ -12126,7 +12152,7 @@ packages: engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} dependencies: '@jest/types': 27.5.1 - '@types/node': 18.11.18 + '@types/node': 18.13.0 chalk: 4.1.2 ci-info: 3.6.2 graceful-fs: 4.2.10 @@ -12151,7 +12177,7 @@ packages: dependencies: '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 18.11.18 + '@types/node': 18.13.0 ansi-escapes: 4.3.2 chalk: 4.1.2 jest-util: 27.5.1 @@ -12162,7 +12188,7 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 18.11.18 + '@types/node': 18.13.0 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true @@ -12241,7 +12267,7 @@ packages: optional: true dependencies: abab: 2.0.6 - acorn: 8.8.1 + acorn: 8.8.2 acorn-globals: 6.0.0 cssom: 0.4.4 cssstyle: 2.3.0 @@ -12309,7 +12335,7 @@ packages: /json-rpc-engine/3.8.0: resolution: {integrity: sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA==} dependencies: - async: 2.6.2 + async: 2.6.4 babel-preset-env: 1.7.0 babelify: 7.3.0 json-rpc-error: 2.0.0 @@ -13055,7 +13081,7 @@ packages: /lower-case/2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} dependencies: - tslib: 2.4.1 + tslib: 2.5.0 dev: true /lowercase-keys/1.0.1: @@ -14535,7 +14561,7 @@ packages: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} dependencies: lower-case: 2.0.2 - tslib: 2.4.1 + tslib: 2.5.0 dev: true /node-abi/3.32.0: @@ -15044,7 +15070,7 @@ packages: resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} dependencies: dot-case: 3.0.4 - tslib: 2.4.1 + tslib: 2.5.0 dev: true /parent-module/1.0.1: @@ -15139,7 +15165,7 @@ packages: resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} dependencies: no-case: 3.0.4 - tslib: 2.4.1 + tslib: 2.5.0 dev: true /pascalcase/0.1.1: @@ -15649,19 +15675,16 @@ packages: fast-diff: 1.2.0 dev: true - /prettier-plugin-solidity/1.0.0_prettier@2.8.0: - resolution: {integrity: sha512-gRJCeZ7imbWtNYN2SudjJoPmka5r6jcd2cSTV6FC3pVCtY6LFZbeQQjpKufUEp88hXBAAnkOTOh7TA5xwj9M3A==} + /prettier-plugin-solidity/1.1.2_prettier@2.8.0: + resolution: {integrity: sha512-KC5oNbFJfyBaFiO0kl56J6AXnDmr9tUlBV1iqo864x4KQrKYKaBZvW9jhT2oC0NHoNp7/GoMJNxqL8pp8k7C/g==} engines: {node: '>=12'} peerDependencies: - prettier: ^2.3.0 + prettier: '>=2.3.0 || >=3.0.0-alpha.0' dependencies: - '@solidity-parser/parser': 0.14.5 - emoji-regex: 10.2.1 - escape-string-regexp: 4.0.0 + '@solidity-parser/parser': 0.15.0 prettier: 2.8.0 semver: 7.3.8 solidity-comments-extractor: 0.0.7 - string-width: 4.2.3 dev: true /prettier/1.19.1: @@ -17204,8 +17227,8 @@ packages: - debug dev: false - /solhint/3.3.7: - resolution: {integrity: sha512-NjjjVmXI3ehKkb3aNtRJWw55SUVJ8HMKKodwe0HnejA+k0d2kmhw7jvpa+MCTbcEgt8IWSwx0Hu6aCo/iYOZzQ==} + /solhint/3.3.8: + resolution: {integrity: sha512-TkYyJ6uUJCaiqRKuhHhFuoAoyco9Ia+RDKhl3usjG/rkaNk8/LdLRla2Xln7MVdBTaPKNAU8ezTRSit50Yy4qw==} hasBin: true dependencies: '@solidity-parser/parser': 0.14.5 @@ -17236,37 +17259,6 @@ packages: resolution: {integrity: sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==} dev: true - /solidity-coverage/0.8.2_hardhat@2.12.2: - resolution: {integrity: sha512-cv2bWb7lOXPE9/SSleDO6czkFiMHgP4NXPj+iW9W7iEKLBk7Cj0AGBiNmGX3V1totl9wjPrT0gHmABZKZt65rQ==} - hasBin: true - peerDependencies: - hardhat: ^2.11.0 - dependencies: - '@ethersproject/abi': 5.7.0 - '@solidity-parser/parser': 0.14.5 - chalk: 2.4.2 - death: 1.1.0 - detect-port: 1.5.1 - difflib: 0.2.4 - fs-extra: 8.1.0 - ghost-testrpc: 0.0.2 - global-modules: 2.0.0 - globby: 10.0.2 - hardhat: 2.12.2_2dtigtkb225m7ii7q45utxqwgi - jsonschema: 1.4.1 - lodash: 4.17.21 - mocha: 7.1.2 - node-emoji: 1.11.0 - pify: 4.0.1 - recursive-readdir: 2.2.3 - sc-istanbul: 0.4.6 - semver: 7.3.8 - shelljs: 0.8.5 - web3-utils: 1.8.1 - transitivePeerDependencies: - - supports-color - dev: true - /solidity-docgen/0.6.0-beta.34_hardhat@2.12.2: resolution: {integrity: sha512-igdGrkg8gT1jn+B2NwzjEtSf+7NTrSi/jz88zO7MZWgETmcWbXaxgAsQP4BQeC4YFeH0Pie1NsLP7+9qDgvFtA==} peerDependencies: @@ -18172,7 +18164,7 @@ packages: hasBin: true dependencies: '@jridgewell/source-map': 0.3.2 - acorn: 8.8.1 + acorn: 8.8.2 commander: 2.20.3 source-map-support: 0.5.21 dev: true @@ -18544,7 +18536,6 @@ packages: /tslib/2.5.0: resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} - dev: false /tsort/0.0.1: resolution: {integrity: sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==} @@ -19578,7 +19569,7 @@ packages: /web3-provider-engine/14.2.1: resolution: {integrity: sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw==} dependencies: - async: 2.6.2 + async: 2.6.4 backoff: 2.5.0 clone: 2.1.2 cross-fetch: 2.2.6 @@ -20281,3 +20272,37 @@ packages: dependencies: bn.js: 4.12.0 ethereumjs-util: 6.2.1 + + github.com/taikoxyz/solidity-coverage/ceb49fd1f6041e4fcd26079dfb0d3b0f58c812e5_hardhat@2.12.2: + resolution: {tarball: https://codeload.github.com/taikoxyz/solidity-coverage/tar.gz/ceb49fd1f6041e4fcd26079dfb0d3b0f58c812e5} + id: github.com/taikoxyz/solidity-coverage/ceb49fd1f6041e4fcd26079dfb0d3b0f58c812e5 + name: solidity-coverage + version: 0.8.1 + hasBin: true + peerDependencies: + hardhat: ^2.11.0 + dependencies: + '@ethersproject/abi': 5.7.0 + '@solidity-parser/parser': 0.15.0 + chalk: 2.4.2 + death: 1.1.0 + detect-port: 1.5.1 + difflib: 0.2.4 + fs-extra: 8.1.0 + ghost-testrpc: 0.0.2 + global-modules: 2.0.0 + globby: 10.0.2 + hardhat: 2.12.2_2dtigtkb225m7ii7q45utxqwgi + jsonschema: 1.4.1 + lodash: 4.17.21 + mocha: 7.1.2 + node-emoji: 1.11.0 + pify: 4.0.1 + recursive-readdir: 2.2.3 + sc-istanbul: 0.4.6 + semver: 7.3.8 + shelljs: 0.8.5 + web3-utils: 1.8.1 + transitivePeerDependencies: + - supports-color + dev: true