From f79723be4073c60b25c92906c8a626d22c2b133a Mon Sep 17 00:00:00 2001 From: Andres Martin Aiello <50411235+andresaiello@users.noreply.github.com> Date: Fri, 2 Feb 2024 13:22:18 -0300 Subject: [PATCH] feat: implement feature to disable invitation (#148) * feat: implement feature to disable invitation * audit recommendation * add expiration * typo * update addresses * add pk --- package.json | 2 +- .../zeta-app-contracts/data/addresses.json | 6 +- packages/zeta-app-contracts/hardhat.config.ts | 5 +- .../contracts/disperse/Disperse.sol | 9 +- .../zeta-points/InvitationManager.sol | 46 ++++-- .../zevm-app-contracts/data/addresses.json | 10 +- packages/zevm-app-contracts/hardhat.config.ts | 2 +- .../zevm-app-contracts/test/Disperse.spec.ts | 16 ++- .../test/zeta-points/InvitationManager.ts | 62 ++++++-- .../test/zeta-points/test.helpers.ts | 8 +- yarn.lock | 132 +++++++++++++----- 11 files changed, 214 insertions(+), 84 deletions(-) diff --git a/package.json b/package.json index e7a00b32..569e7040 100644 --- a/package.json +++ b/package.json @@ -29,8 +29,8 @@ }, "devDependencies": { "@changesets/cli": "^2.23.1", + "@nomicfoundation/hardhat-verify": "2.0.3", "@nomiclabs/hardhat-ethers": "^2.0.5", - "@nomiclabs/hardhat-etherscan": "3.0.3", "@nomiclabs/hardhat-waffle": "^2.0.3", "@typechain/ethers-v5": "^10.0.0", "@typechain/hardhat": "^6.0.0", diff --git a/packages/zeta-app-contracts/data/addresses.json b/packages/zeta-app-contracts/data/addresses.json index 27c51e4a..eba55858 100644 --- a/packages/zeta-app-contracts/data/addresses.json +++ b/packages/zeta-app-contracts/data/addresses.json @@ -8,7 +8,7 @@ }, "bsc_mainnet": { "multiChainSwap": "", - "multiChainValue": "", + "multiChainValue": "0x33e5fCFfe910B99DB46c259804fCA1317EA0Aa89", "zetaTokenConsumerUniV2": "", "zetaTokenConsumerUniV3": "" }, @@ -26,7 +26,7 @@ }, "eth_mainnet": { "multiChainSwap": "", - "multiChainValue": "", + "multiChainValue": "0x910966E1C0Bc9FD74f499723c19Ff9799fE258a5", "zetaTokenConsumerUniV2": "", "zetaTokenConsumerUniV3": "" }, @@ -44,7 +44,7 @@ }, "zeta_testnet": { "multiChainSwap": "", - "multiChainValue": "0x82aC45D07dEe4DBDe050e838beF345347DEd99a8", + "multiChainValue": "0x36Cfb6dCd6926dFb749dc8E4b28efc73f3e6FAe3", "zetaTokenConsumerUniV2": "", "zetaTokenConsumerUniV3": "" } diff --git a/packages/zeta-app-contracts/hardhat.config.ts b/packages/zeta-app-contracts/hardhat.config.ts index 8d3851c6..fe201701 100644 --- a/packages/zeta-app-contracts/hardhat.config.ts +++ b/packages/zeta-app-contracts/hardhat.config.ts @@ -1,4 +1,4 @@ -import "@nomiclabs/hardhat-etherscan"; +import "@nomicfoundation/hardhat-verify"; import "@nomiclabs/hardhat-waffle"; import "@typechain/hardhat"; import "hardhat-gas-reporter"; @@ -11,11 +11,14 @@ import type { HardhatUserConfig } from "hardhat/types"; dotenv.config(); +const PRIVATE_KEYS = process.env.PRIVATE_KEY !== undefined ? [`0x${process.env.PRIVATE_KEY}`] : []; + const config: HardhatUserConfig = { //@ts-ignore etherscan: { apiKey: { // BSC + bsc: process.env.BSCSCAN_API_KEY || "", bscTestnet: process.env.BSCSCAN_API_KEY || "", // ETH goerli: process.env.ETHERSCAN_API_KEY || "", diff --git a/packages/zevm-app-contracts/contracts/disperse/Disperse.sol b/packages/zevm-app-contracts/contracts/disperse/Disperse.sol index 21efac64..943ce30c 100644 --- a/packages/zevm-app-contracts/contracts/disperse/Disperse.sol +++ b/packages/zevm-app-contracts/contracts/disperse/Disperse.sol @@ -2,8 +2,11 @@ pragma solidity 0.8.7; import "@openzeppelin/contracts/interfaces/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; contract Disperse { + using SafeERC20 for IERC20; + bool private locked; event FundsDispersed(address indexed token, address indexed from, address indexed recipient, uint256 value); @@ -38,9 +41,9 @@ contract Disperse { ) external noReentrancy { uint256 total = 0; for (uint256 i = 0; i < recipients.length; i++) total += values[i]; - require(token.transferFrom(msg.sender, address(this), total)); + token.safeTransferFrom(msg.sender, address(this), total); for (uint256 i = 0; i < recipients.length; i++) { - require(token.transfer(recipients[i], values[i])); + token.safeTransfer(recipients[i], values[i]); emit FundsDispersed(address(token), msg.sender, recipients[i], values[i]); } } @@ -51,7 +54,7 @@ contract Disperse { uint256[] calldata values ) external noReentrancy { for (uint256 i = 0; i < recipients.length; i++) { - require(token.transferFrom(msg.sender, recipients[i], values[i])); + token.safeTransferFrom(msg.sender, recipients[i], values[i]); emit FundsDispersed(address(token), msg.sender, recipients[i], values[i]); } } diff --git a/packages/zevm-app-contracts/contracts/zeta-points/InvitationManager.sol b/packages/zevm-app-contracts/contracts/zeta-points/InvitationManager.sol index 50f43173..aad0d270 100644 --- a/packages/zevm-app-contracts/contracts/zeta-points/InvitationManager.sol +++ b/packages/zevm-app-contracts/contracts/zeta-points/InvitationManager.sol @@ -8,6 +8,10 @@ contract InvitationManager { bytes32 r; bytes32 s; } + + // Indicate if invitation is still available. The default value is true. + mapping(address => bool) public invitationEnabled; + // Records the timestamp when a particular user gets verified. mapping(address => uint256) public userVerificationTimestamps; @@ -24,23 +28,37 @@ contract InvitationManager { mapping(address => mapping(uint256 => uint256)) public totalInvitesByInviterByDay; error UserAlreadyVerified(); + error UserNotVerified(); error UnrecognizedInvitation(); error IndexOutOfBounds(); error CanNotInviteYourself(); - event UserVerified(address indexed userAddress, uint256 verifiedAt); - event InvitationAccepted(address indexed inviter, address indexed invitee, uint256 index, uint256 acceptedAt); + event UserVerified(address indexed userAddress, uint256 verifiedAt, uint256 unix_timestamp); + event InvitationAccepted( + address indexed inviter, + address indexed invitee, + uint256 index, + uint256 expiration, + uint256 acceptedAt, + uint256 unix_timestamp + ); function _markAsVerified(address user) internal { // Check if the user is already verified if (userVerificationTimestamps[user] > 0) revert UserAlreadyVerified(); userVerificationTimestamps[user] = block.timestamp; - emit UserVerified(user, block.timestamp); + emit UserVerified(user, block.timestamp, block.timestamp); } function markAsVerified() external { _markAsVerified(msg.sender); + invitationEnabled[msg.sender] = true; + } + + function updateInvitationStatus(bool value) external { + if (userVerificationTimestamps[msg.sender] == 0) revert UserNotVerified(); + invitationEnabled[msg.sender] = value; } function hasBeenVerified(address userAddress) external view returns (bool) { @@ -51,18 +69,21 @@ contract InvitationManager { return userVerificationTimestamps[userAddress]; } - function _verifySignature(address inviter, Signature calldata signature) private pure { - bytes32 payloadHash = keccak256(abi.encode(inviter)); + function _verifySignature(address inviter, uint256 expiration, Signature calldata signature) private pure { + bytes32 payloadHash = keccak256(abi.encode(inviter, expiration)); bytes32 messageHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", payloadHash)); address messageSigner = ecrecover(messageHash, signature.v, signature.r, signature.s); if (inviter != messageSigner) revert UnrecognizedInvitation(); } - function confirmAndAcceptInvitation(address inviter, Signature calldata signature) external { + function confirmAndAcceptInvitation(address inviter, uint256 expiration, Signature calldata signature) external { if (inviter == msg.sender) revert CanNotInviteYourself(); - if (userVerificationTimestamps[inviter] == 0) revert UnrecognizedInvitation(); - _verifySignature(inviter, signature); + if (!invitationEnabled[inviter]) revert UnrecognizedInvitation(); + + _verifySignature(inviter, expiration, signature); + + if (expiration < block.timestamp) revert UnrecognizedInvitation(); acceptedInvitationsTimestamp[inviter][msg.sender] = block.timestamp; _markAsVerified(msg.sender); @@ -75,7 +96,14 @@ contract InvitationManager { totalInvitesByDay[dayStartTimestamp]++; totalInvitesByInviterByDay[inviter][dayStartTimestamp]++; - emit InvitationAccepted(inviter, msg.sender, inviteeLists[inviter].length - 1, block.timestamp); + emit InvitationAccepted( + inviter, + msg.sender, + inviteeLists[inviter].length - 1, + expiration, + block.timestamp, + block.timestamp + ); } function getInviteeCount(address inviter) external view returns (uint256) { diff --git a/packages/zevm-app-contracts/data/addresses.json b/packages/zevm-app-contracts/data/addresses.json index e040ed8f..bd53a842 100644 --- a/packages/zevm-app-contracts/data/addresses.json +++ b/packages/zevm-app-contracts/data/addresses.json @@ -1,11 +1,11 @@ { "zevm": { "zeta_testnet": { - "disperse": "0xf394dc01879E39f19eDA533EFD10C82eEee5B2b1", - "rewardDistributorFactory": "0x667e4C493d40015256BDC89E3ba750B2F90359E1", - "zetaSwap": "0x44D1F1f9289DBA1Cf5824bd667184cEBE020aA1c", - "zetaSwapBtcInbound": "0x008b393933D5CA2457Df570CA5D628380FFf6da4", - "invitationManager": "0xF4cF881A3d23936e3710ef2Cbbe93f71C4389918" + "disperse": "0x23ce409Ea60c3d75827d04D9db3d52F3af62e44d", + "rewardDistributorFactory": "0xB9dc665610CF5109cE23aBBdaAc315B41FA094c1", + "zetaSwap": "0xA8168Dc495Ed61E70f5c1941e2860050AB902cEF", + "zetaSwapBtcInbound": "0x358E2cfC0E16444Ba7D3164Bbeeb6bEA7472c559", + "invitationManager": "0x3649C03C472B698213926543456E9c21081e529d" } } } \ No newline at end of file diff --git a/packages/zevm-app-contracts/hardhat.config.ts b/packages/zevm-app-contracts/hardhat.config.ts index d495af66..3ac46d5e 100644 --- a/packages/zevm-app-contracts/hardhat.config.ts +++ b/packages/zevm-app-contracts/hardhat.config.ts @@ -1,4 +1,4 @@ -import "@nomiclabs/hardhat-etherscan"; +import "@nomicfoundation/hardhat-verify"; import "@nomiclabs/hardhat-waffle"; import "@typechain/hardhat"; import "hardhat-gas-reporter"; diff --git a/packages/zevm-app-contracts/test/Disperse.spec.ts b/packages/zevm-app-contracts/test/Disperse.spec.ts index 20b7ca2c..3002619b 100644 --- a/packages/zevm-app-contracts/test/Disperse.spec.ts +++ b/packages/zevm-app-contracts/test/Disperse.spec.ts @@ -1,6 +1,7 @@ import { parseUnits } from "@ethersproject/units"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { expect } from "chai"; +import { parseEther } from "ethers/lib/utils"; import { ethers, network } from "hardhat"; import { Disperse, Disperse__factory, MockZRC20, MockZRC20__factory } from "../typechain-types"; @@ -23,18 +24,23 @@ describe("Disperse tests", () => { describe("Disperse", () => { it("Should disperse ETH", async () => { - const amount = parseUnits("10"); + const count = 500; + const amount = parseEther("0.01"); const balance0 = await ethers.provider.getBalance(accounts[0].address); const balance1 = await ethers.provider.getBalance(accounts[1].address); - await disperseContract.disperseEther([accounts[0].address, accounts[1].address], [amount, amount.mul(2)], { - value: amount.mul(3), + + const bigArrayAddress = new Array(count).fill(accounts[0].address); + const bigArrayAmount = new Array(count).fill(amount); + + await disperseContract.disperseEther(bigArrayAddress, bigArrayAmount, { + value: amount.mul(count), }); const balance0After = await ethers.provider.getBalance(accounts[0].address); const balance1After = await ethers.provider.getBalance(accounts[1].address); - expect(balance0After.sub(balance0)).to.be.eq(amount); - expect(balance1After.sub(balance1)).to.be.eq(amount.mul(2)); + expect(balance0After.sub(balance0)).to.be.eq(amount.mul(count)); + expect(balance1After.sub(balance1)).to.be.eq(0); }); it("Should disperse ETH with surplus", async () => { diff --git a/packages/zevm-app-contracts/test/zeta-points/InvitationManager.ts b/packages/zevm-app-contracts/test/zeta-points/InvitationManager.ts index 2c9d5279..0eb30a06 100644 --- a/packages/zevm-app-contracts/test/zeta-points/InvitationManager.ts +++ b/packages/zevm-app-contracts/test/zeta-points/InvitationManager.ts @@ -21,6 +21,13 @@ describe("InvitationManager Contract test", () => { await invitationManager.markAsVerified(); }); + const getTomorrowTimestamp = async () => { + const block = await ethers.provider.getBlock("latest"); + const now = block.timestamp; + const tomorrow = now + 24 * 60 * 60; + return tomorrow; + }; + describe("True", () => { it("Should be true", async () => { expect(true).to.equal(true); @@ -29,12 +36,16 @@ describe("InvitationManager Contract test", () => { describe("Invitations test", () => { it("Should verify an invitation and store it", async () => { - const sig = await getInvitationSig(inviter); + const expirationDate = await getTomorrowTimestamp(); + + const sig = await getInvitationSig(inviter, expirationDate); const hasBeenVerifiedBefore = await invitationManager.hasBeenVerified(invitee.address); await expect(hasBeenVerifiedBefore).to.be.eq(false); - const tx = await invitationManager.connect(invitee).confirmAndAcceptInvitation(inviter.address, sig); + const tx = await invitationManager + .connect(invitee) + .confirmAndAcceptInvitation(inviter.address, expirationDate, sig); const rec = await tx.wait(); const block = await ethers.provider.getBlock(rec.blockNumber); @@ -50,30 +61,47 @@ describe("InvitationManager Contract test", () => { }); it("Should revert if invitation is invalid", async () => { - const sig = await getInvitationSig(inviter); - const tx = invitationManager.connect(invitee).confirmAndAcceptInvitation(addrs[0].address, sig); + const expirationDate = await getTomorrowTimestamp(); + const sig = await getInvitationSig(inviter, expirationDate); + const tx = invitationManager.connect(invitee).confirmAndAcceptInvitation(addrs[0].address, expirationDate, sig); + await expect(tx).to.be.revertedWith("UnrecognizedInvitation"); + }); + + it("Should revert if invitation is expired", async () => { + const expirationDate = await getTomorrowTimestamp(); + const yesterdayTimestamp = expirationDate - 24 * 60 * 60; + const sig = await getInvitationSig(inviter, expirationDate); + const tx = invitationManager + .connect(invitee) + .confirmAndAcceptInvitation(inviter.address, yesterdayTimestamp, sig); await expect(tx).to.be.revertedWith("UnrecognizedInvitation"); }); it("Should revert if inviter has not been verified", async () => { - const sig = await getInvitationSig(addrs[0]); - const tx = invitationManager.connect(invitee).confirmAndAcceptInvitation(addrs[0].address, sig); + const expirationDate = await getTomorrowTimestamp(); + const sig = await getInvitationSig(addrs[0], expirationDate); + const tx = invitationManager.connect(invitee).confirmAndAcceptInvitation(addrs[0].address, expirationDate, sig); await expect(tx).to.be.revertedWith("UnrecognizedInvitation"); }); it("Should revert if invitation is already accepted", async () => { - const sig = await getInvitationSig(inviter); - await invitationManager.connect(invitee).confirmAndAcceptInvitation(inviter.address, sig); - const tx = invitationManager.connect(invitee).confirmAndAcceptInvitation(inviter.address, sig); + const expirationDate = await getTomorrowTimestamp(); + const sig = await getInvitationSig(inviter, expirationDate); + await invitationManager.connect(invitee).confirmAndAcceptInvitation(inviter.address, expirationDate, sig); + const tx = invitationManager.connect(invitee).confirmAndAcceptInvitation(inviter.address, expirationDate, sig); await expect(tx).to.be.revertedWith("UserAlreadyVerified"); }); it("Should count only for today if I just accepted", async () => { - const sig = await getInvitationSig(inviter); - const tx = await invitationManager.connect(invitee).confirmAndAcceptInvitation(inviter.address, sig); + const expirationDate = await getTomorrowTimestamp(); + const sig = await getInvitationSig(inviter, expirationDate); + const tx = await invitationManager + .connect(invitee) + .confirmAndAcceptInvitation(inviter.address, expirationDate, sig); const rec = await tx.wait(); const block = await ethers.provider.getBlock(rec.blockNumber); + const now = block.timestamp; const invitation = await invitationManager.acceptedInvitationsTimestamp(inviter.address, invitee.address); await expect(invitation).to.be.eq(block.timestamp); @@ -81,7 +109,6 @@ describe("InvitationManager Contract test", () => { const invitationCount = await invitationManager.getInviteeCount(inviter.address); await expect(invitationCount).to.be.eq(1); - const now = block.timestamp; const todayTimestamp = Math.floor(now / 86400) * 86400; const invitationCountToday = await invitationManager.getTotalInvitesOnDay(todayTimestamp); await expect(invitationCountToday).to.be.eq(1); @@ -104,12 +131,15 @@ describe("InvitationManager Contract test", () => { }); it("Should emit the right event when invitation is accepted", async () => { - const sig = await getInvitationSig(inviter); + const expirationDate = await getTomorrowTimestamp(); + const sig = await getInvitationSig(inviter, expirationDate); const hasBeenVerifiedBefore = await invitationManager.hasBeenVerified(invitee.address); await expect(hasBeenVerifiedBefore).to.be.eq(false); - const tx = await invitationManager.connect(invitee).confirmAndAcceptInvitation(inviter.address, sig); + const tx = await invitationManager + .connect(invitee) + .confirmAndAcceptInvitation(inviter.address, expirationDate, sig); const rec = await tx.wait(); const event = rec.events?.find((e) => e.event === "InvitationAccepted"); const block = await ethers.provider.getBlock(rec.blockNumber); @@ -121,7 +151,9 @@ describe("InvitationManager Contract test", () => { const inviteeByIndex = await invitationManager.getInviteeAtIndex(inviter.address, event?.args?.index); expect(inviteeByIndex).to.be.eq(invitee.address); - const tx2 = await invitationManager.connect(addrs[0]).confirmAndAcceptInvitation(inviter.address, sig); + const tx2 = await invitationManager + .connect(addrs[0]) + .confirmAndAcceptInvitation(inviter.address, expirationDate, sig); const rec2 = await tx2.wait(); const event2 = rec2.events?.find((e) => e.event === "InvitationAccepted"); const block2 = await ethers.provider.getBlock(rec2.blockNumber); diff --git a/packages/zevm-app-contracts/test/zeta-points/test.helpers.ts b/packages/zevm-app-contracts/test/zeta-points/test.helpers.ts index cb758210..f60e9a5f 100644 --- a/packages/zevm-app-contracts/test/zeta-points/test.helpers.ts +++ b/packages/zevm-app-contracts/test/zeta-points/test.helpers.ts @@ -1,12 +1,12 @@ import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { ethers } from "hardhat"; -export const getInvitationSig = async (signer: SignerWithAddress) => { - let payload = ethers.utils.defaultAbiCoder.encode(["address"], [signer.address]); +export const getInvitationSig = async (signer: SignerWithAddress, expirationDate: number) => { + const payload = ethers.utils.defaultAbiCoder.encode(["address", "uint256"], [signer.address, expirationDate]); - let payloadHash = ethers.utils.keccak256(payload); + const payloadHash = ethers.utils.keccak256(payload); // This adds the message prefix - let signature = await signer.signMessage(ethers.utils.arrayify(payloadHash)); + const signature = await signer.signMessage(ethers.utils.arrayify(payloadHash)); return ethers.utils.splitSignature(signature); }; diff --git a/yarn.lock b/yarn.lock index d0be129f..9f6ae3ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1773,6 +1773,25 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/hardhat-verify@npm:2.0.3": + version: 2.0.3 + resolution: "@nomicfoundation/hardhat-verify@npm:2.0.3" + dependencies: + "@ethersproject/abi": ^5.1.2 + "@ethersproject/address": ^5.0.2 + cbor: ^8.1.0 + chalk: ^2.4.2 + debug: ^4.1.1 + lodash.clonedeep: ^4.5.0 + semver: ^6.3.0 + table: ^6.8.0 + undici: ^5.14.0 + peerDependencies: + hardhat: ^2.0.4 + checksum: 5cc3513d3385eb45c19081e79b1b2a67b13376f0d2c5dc2da07ee41886f82110b0af5b46e7fae6204db8a9d4dcda7e568a630a254bd5567779068bc29c22c86f + languageName: node + linkType: hard + "@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.1": version: 0.1.1 resolution: "@nomicfoundation/solidity-analyzer-darwin-arm64@npm:0.1.1" @@ -1892,23 +1911,6 @@ __metadata: languageName: node linkType: hard -"@nomiclabs/hardhat-etherscan@npm:3.0.3": - version: 3.0.3 - resolution: "@nomiclabs/hardhat-etherscan@npm:3.0.3" - dependencies: - "@ethersproject/abi": ^5.1.2 - "@ethersproject/address": ^5.0.2 - cbor: ^5.0.2 - debug: ^4.1.1 - fs-extra: ^7.0.1 - semver: ^6.3.0 - undici: ^4.14.1 - peerDependencies: - hardhat: ^2.0.4 - checksum: 6ce0856ad989c4cff5c90f7673d80fb7778ac1941db2bdf0998afca31c2439ed2e840fbad123a6f5958768243179af33a56f7b45919a598c8361b9a7cfdbaea6 - languageName: node - linkType: hard - "@nomiclabs/hardhat-waffle@npm:^2.0.3": version: 2.0.6 resolution: "@nomiclabs/hardhat-waffle@npm:2.0.6" @@ -3008,6 +3010,18 @@ __metadata: languageName: node linkType: hard +"ajv@npm:^8.0.1": + version: 8.12.0 + resolution: "ajv@npm:8.12.0" + dependencies: + fast-deep-equal: ^3.1.1 + json-schema-traverse: ^1.0.0 + require-from-string: ^2.0.2 + uri-js: ^4.2.2 + checksum: 4dc13714e316e67537c8b31bc063f99a1d9d9a497eb4bbd55191ac0dcd5e4985bbb71570352ad6f1e76684fb6d790928f96ba3b2d4fd6e10024be9612fe3f001 + languageName: node + linkType: hard + "amdefine@npm:>=0.0.4": version: 1.0.1 resolution: "amdefine@npm:1.0.1" @@ -3285,6 +3299,13 @@ __metadata: languageName: node linkType: hard +"astral-regex@npm:^2.0.0": + version: 2.0.0 + resolution: "astral-regex@npm:2.0.0" + checksum: 876231688c66400473ba505731df37ea436e574dd524520294cc3bbc54ea40334865e01fa0d074d74d036ee874ee7e62f486ea38bc421ee8e6a871c06f011766 + languageName: node + linkType: hard + "async-eventemitter@npm:^0.2.4": version: 0.2.4 resolution: "async-eventemitter@npm:0.2.4" @@ -3418,7 +3439,7 @@ __metadata: languageName: node linkType: hard -"bignumber.js@npm:^9.0.0, bignumber.js@npm:^9.0.1": +"bignumber.js@npm:^9.0.0": version: 9.1.2 resolution: "bignumber.js@npm:9.1.2" checksum: 582c03af77ec9cb0ebd682a373ee6c66475db94a4325f92299621d544aa4bd45cb45fd60001610e94aef8ae98a0905fa538241d9638d4422d57abbeeac6fadaf @@ -3893,13 +3914,12 @@ __metadata: languageName: node linkType: hard -"cbor@npm:^5.0.2": - version: 5.2.0 - resolution: "cbor@npm:5.2.0" +"cbor@npm:^8.1.0": + version: 8.1.0 + resolution: "cbor@npm:8.1.0" dependencies: - bignumber.js: ^9.0.1 - nofilter: ^1.0.4 - checksum: b3c39dae64370f361526dbec88f51d0f1b47027224cdd21dbd64c228f0fe7eaa945932d349ec5324068a6c6dcdbb1e3b46242852524fd53c526d14cb60514bdc + nofilter: ^3.1.0 + checksum: a90338435dc7b45cc01461af979e3bb6ddd4f2a08584c437586039cd5f2235014c06e49d664295debbfb3514d87b2f06728092ab6aa6175e2e85e9cd7dc0c1fd languageName: node linkType: hard @@ -7686,6 +7706,13 @@ __metadata: languageName: node linkType: hard +"json-schema-traverse@npm:^1.0.0": + version: 1.0.0 + resolution: "json-schema-traverse@npm:1.0.0" + checksum: 02f2f466cdb0362558b2f1fd5e15cce82ef55d60cd7f8fa828cf35ba74330f8d767fcae5c5c2adb7851fa811766c694b9405810879bc4e1ddd78a7c0e03658ad + languageName: node + linkType: hard + "json-schema@npm:0.4.0, json-schema@npm:^0.4.0": version: 0.4.0 resolution: "json-schema@npm:0.4.0" @@ -8084,6 +8111,13 @@ __metadata: languageName: node linkType: hard +"lodash.clonedeep@npm:^4.5.0": + version: 4.5.0 + resolution: "lodash.clonedeep@npm:4.5.0" + checksum: 92c46f094b064e876a23c97f57f81fbffd5d760bf2d8a1c61d85db6d1e488c66b0384c943abee4f6af7debf5ad4e4282e74ff83177c9e63d8ff081a4837c3489 + languageName: node + linkType: hard + "lodash.isequal@npm:^4.5.0": version: 4.5.0 resolution: "lodash.isequal@npm:4.5.0" @@ -8112,6 +8146,13 @@ __metadata: languageName: node linkType: hard +"lodash.truncate@npm:^4.4.2": + version: 4.4.2 + resolution: "lodash.truncate@npm:4.4.2" + checksum: b463d8a382cfb5f0e71c504dcb6f807a7bd379ff1ea216669aa42c52fc28c54e404bfbd96791aa09e6df0de2c1d7b8f1b7f4b1a61f324d38fe98bc535aeee4f5 + languageName: node + linkType: hard + "lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.21": version: 4.17.21 resolution: "lodash@npm:4.17.21" @@ -8956,10 +8997,10 @@ __metadata: languageName: node linkType: hard -"nofilter@npm:^1.0.4": - version: 1.0.4 - resolution: "nofilter@npm:1.0.4" - checksum: 54d864f745de5c3312994e880cf2d4f55e34830d6adc8275dce3731507ca380d21040336e4a277a4901551c07f04c452fbeffd57fad1dc8f68a2943eaf894a04 +"nofilter@npm:^3.1.0": + version: 3.1.0 + resolution: "nofilter@npm:3.1.0" + checksum: 58aa85a5b4b35cbb6e42de8a8591c5e338061edc9f3e7286f2c335e9e9b9b8fa7c335ae45daa8a1f3433164dc0b9a3d187fa96f9516e04a17a1f9ce722becc4f languageName: node linkType: hard @@ -9953,7 +9994,7 @@ __metadata: languageName: node linkType: hard -"require-from-string@npm:^2.0.0": +"require-from-string@npm:^2.0.0, require-from-string@npm:^2.0.2": version: 2.0.2 resolution: "require-from-string@npm:2.0.2" checksum: a03ef6895445f33a4015300c426699bc66b2b044ba7b670aa238610381b56d3f07c686251740d575e22f4c87531ba662d06937508f0f3c0f1ddc04db3130560b @@ -10574,6 +10615,17 @@ __metadata: languageName: node linkType: hard +"slice-ansi@npm:^4.0.0": + version: 4.0.0 + resolution: "slice-ansi@npm:4.0.0" + dependencies: + ansi-styles: ^4.0.0 + astral-regex: ^2.0.0 + is-fullwidth-code-point: ^3.0.0 + checksum: 4a82d7f085b0e1b070e004941ada3c40d3818563ac44766cca4ceadd2080427d337554f9f99a13aaeb3b4a94d9964d9466c807b3d7b7541d1ec37ee32d308756 + languageName: node + linkType: hard + "smart-buffer@npm:^4.2.0": version: 4.2.0 resolution: "smart-buffer@npm:4.2.0" @@ -11083,6 +11135,19 @@ __metadata: languageName: node linkType: hard +"table@npm:^6.8.0": + version: 6.8.1 + resolution: "table@npm:6.8.1" + dependencies: + ajv: ^8.0.1 + lodash.truncate: ^4.4.2 + slice-ansi: ^4.0.0 + string-width: ^4.2.3 + strip-ansi: ^6.0.1 + checksum: 08249c7046125d9d0a944a6e96cfe9ec66908d6b8a9db125531be6eb05fa0de047fd5542e9d43b4f987057f00a093b276b8d3e19af162a9c40db2681058fd306 + languageName: node + linkType: hard + "tar@npm:^4.0.2": version: 4.4.19 resolution: "tar@npm:4.4.19" @@ -11647,13 +11712,6 @@ __metadata: languageName: node linkType: hard -"undici@npm:^4.14.1": - version: 4.16.0 - resolution: "undici@npm:4.16.0" - checksum: 5e88c2b3381085e25ed1d1a308610ac7ee985f478ac705af7a8e03213536e10f73ef8dd8d85e6ed38948d1883fa0ae935e04357c317b0f5d3d3c0211d0c8c393 - languageName: node - linkType: hard - "undici@npm:^5.14.0": version: 5.28.2 resolution: "undici@npm:5.28.2" @@ -12880,8 +12938,8 @@ __metadata: resolution: "zetachain@workspace:." dependencies: "@changesets/cli": ^2.23.1 + "@nomicfoundation/hardhat-verify": 2.0.3 "@nomiclabs/hardhat-ethers": ^2.0.5 - "@nomiclabs/hardhat-etherscan": 3.0.3 "@nomiclabs/hardhat-waffle": ^2.0.3 "@typechain/ethers-v5": ^10.0.0 "@typechain/hardhat": ^6.0.0