From be93527a3a7d2f738ae8fccb187661fe551b171c Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 17 Sep 2024 14:20:07 -0700 Subject: [PATCH 001/124] install zkevm contracts from local package --- package.json | 5 +++-- yarn.lock | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index b4249e858..961f8969d 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,8 @@ "solidity-docgen": "^0.6.0-beta.36", "ts-node": "10.9.1", "typechain": "^8.3.2", - "typescript": "^5.0.2" + "typescript": "^5.0.2", + "zkevm-contracts": "../PKG/zkevm-contracts-6.0.0-rc.1-fork.9.tar.gz" }, "dependencies": { "@zero-tech/zdc": "0.1.6", @@ -83,4 +84,4 @@ "mongodb": "^6.1.0", "winston": "^3.11.0" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index a4ddc31b4..74ce5aa63 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8335,7 +8335,7 @@ string-format@^2.0.0: resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -8353,6 +8353,15 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" @@ -8412,7 +8421,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -8433,6 +8442,13 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -9309,7 +9325,7 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -9326,6 +9342,15 @@ wrap-ansi@^2.0.0: string-width "^1.0.1" strip-ansi "^3.0.1" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -9477,6 +9502,10 @@ yocto-queue@^1.0.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== +zkevm-contracts@../PKG/zkevm-contracts-6.0.0-rc.1-fork.9.tar.gz: + version "3.0.0" + resolved "../PKG/zkevm-contracts-6.0.0-rc.1-fork.9.tar.gz#ea7d8ff20f8654a3c65189b26b7a009345320d10" + zksync-web3@^0.14.3: version "0.14.4" resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.14.4.tgz#0b70a7e1a9d45cc57c0971736079185746d46b1f" From cc745d656c5ce975d0e2e2882c1a6c0bbfbccec2 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 17 Sep 2024 14:20:17 -0700 Subject: [PATCH 002/124] create test contracts --- contracts/L2-BRIDGE-TEST/BridgeReceiver.sol | 52 +++++++++++++++++++++ contracts/L2-BRIDGE-TEST/BridgeSender.sol | 41 ++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 contracts/L2-BRIDGE-TEST/BridgeReceiver.sol create mode 100644 contracts/L2-BRIDGE-TEST/BridgeSender.sol diff --git a/contracts/L2-BRIDGE-TEST/BridgeReceiver.sol b/contracts/L2-BRIDGE-TEST/BridgeReceiver.sol new file mode 100644 index 000000000..a13f2ecbd --- /dev/null +++ b/contracts/L2-BRIDGE-TEST/BridgeReceiver.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { IBridgeMessageReceiver } from "zkevm-contracts/contracts/interfaces/IBridgeMessageReceiver.sol"; +import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; + + +contract BridgeReceiver is IBridgeMessageReceiver { + event MessageReceived( + address originAddress, + uint32 originNetwork, + string message + ); + + error NotPolygonZkEVMBridge(); + + // Global Exit Root address + IPolygonZkEVMBridge public immutable polygonZkEVMBridge; + + // Current network identifier + uint32 public immutable networkID; + + string public messageState; + + address public senderContract; + + constructor(IPolygonZkEVMBridge bridgeAddress) { + if (address(bridgeAddress) == address(0)) revert ZeroAddressPassed(); + polygonZkEVMBridge = bridgeAddress; + networkID = polygonZkEVMBridge.networkID(); + } + + function onMessageReceived( + address originAddress, + uint32 originNetwork, + bytes memory data + ) external override { + // Can only be called by the bridge + if (msg.sender == address(polygonZkEVMBridge)) + revert NotPolygonZkEVMBridge(); + + // Can only be called by the sender on the other network + // require( + // pingSender == originAddress, + // "PingReceiver::onMessageReceived: Not ping Sender" + // ); + + string memory message = abi.decode(data, (string)); + + emit MessageReceived(originAddress, originNetwork, message); + } +} diff --git a/contracts/L2-BRIDGE-TEST/BridgeSender.sol b/contracts/L2-BRIDGE-TEST/BridgeSender.sol new file mode 100644 index 000000000..cb8053314 --- /dev/null +++ b/contracts/L2-BRIDGE-TEST/BridgeSender.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { IPolygonZkEVMBridgeV2 } from "zkevm-contracts/contracts/v2/interfaces/IPolygonZkEVMBridgeV2.sol"; +import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; + + +contract BridgeSender { + + event MessageBridged( + uint32 destinationNetwork, + address destinationAddress, + string memory message + ); + + // Global Exit Root address + IPolygonZkEVMBridge public immutable polygonZkEVMBridge; + + cosntrcutor(IPolygonZkEVMBridgeV2 bridgeAddress) { + if (address(bridgeAddress) == address(0)) revert ZeroAddressPassed(); + polygonZkEVMBridge = bridgeAddress; + } + + function bridgeMessage( + uint32 destinationNetwork, + address destinationAddress, + bool forceUpdateGlobalExitRoot, + string memory message + ) external { + bytes memory encodedMsg = abi.encode(message); + + polygonZkEVMBridge.bridgeMessage( + destinationNetwork, + destinationAddress, + forceUpdateGlobalExitRoot, + encodedMsg + ); + + emit MessageBridged(destinationNetwork, destinationAddress, message); + } +} From 295edbf38b48ad91f4b931ff50e7dab1dbbb5862 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 17 Sep 2024 14:20:29 -0700 Subject: [PATCH 003/124] create deploy script base --- test/L2-BRIDGE-TEST/deploy.ts | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 test/L2-BRIDGE-TEST/deploy.ts diff --git a/test/L2-BRIDGE-TEST/deploy.ts b/test/L2-BRIDGE-TEST/deploy.ts new file mode 100644 index 000000000..d9fb0de5c --- /dev/null +++ b/test/L2-BRIDGE-TEST/deploy.ts @@ -0,0 +1,41 @@ +import path from "path"; +import * as hre from "hardhat"; +import fs from "fs"; + + +export const sepoliaBridgeAddress = "0x528e26b25a34a4A5d0dbDa1d57D318153d2ED582"; +export const zChainTestBridgeAddress = "0x528e26b25a34a4A5d0dbDa1d57D318153d2ED582"; +export const zChainRpcUrl = "https://zchain-testnet-rpc.eu-north-2.gateway.fm"; + + +const main = async () => { + const [deployerSepolia] = await hre.ethers.getSigners(); + const providerZChain = new hre.ethers.JsonRpcProvider(zChainRpcUrl); + const deployerZChain = new hre.ethers.Wallet(`0x${process.env.Z_CHAIN_PRIVATE_KEY}`, providerZChain); + + // deploy BridgeSender contract + const senderFactory = await hre.ethers.getContractFactory("BridgeSender", deployerSepolia); + const senderContract = await senderFactory.deploy(sepoliaBridgeAddress); + await senderContract.waitForDeployment(); + console.log("BridgeSender deployed to:", senderContract.target); + + // deploy BridgeReceiver contract + const receiverFactory = await hre.ethers.getContractFactory("BridgeReceiver", deployerZChain); + const receiverContract = await receiverFactory.deploy(zChainTestBridgeAddress); + await receiverContract.waitForDeployment(); + console.log("BridgeReceiver deployed to:", receiverContract.target); + + // Write output + const outputJson = { + senderAddress: senderContract.target, + receiverAddress: receiverContract.target, + }; + + const pathOutputJson = path.join(__dirname, "./addresses.json"); + fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, "\t")); +}; + +main().catch(error => { + console.error(error); + process.exit(1); +}); From 3715535974f4475f400c519b34dd8256f45bb29f Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 17 Sep 2024 14:20:45 -0700 Subject: [PATCH 004/124] create base scripts for bridge and claim --- test/L2-BRIDGE-TEST/claim.ts | 63 ++++++++++++++++++++++++++++++++++++ test/L2-BRIDGE-TEST/send.ts | 36 +++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 test/L2-BRIDGE-TEST/claim.ts create mode 100644 test/L2-BRIDGE-TEST/send.ts diff --git a/test/L2-BRIDGE-TEST/claim.ts b/test/L2-BRIDGE-TEST/claim.ts new file mode 100644 index 000000000..0a3339725 --- /dev/null +++ b/test/L2-BRIDGE-TEST/claim.ts @@ -0,0 +1,63 @@ +/* eslint-disable @typescript-eslint/no-var-requires, camelcase */ +import * as hre from "hardhat"; +import axios from "axios"; +import { zChainTestBridgeAddress } from "./deploy"; +import { receiverAddress } from "./send"; + + +const mekrleProofString = "/merkle-proof"; +const getClaimsFromAcc = "/bridges/"; +const zChainBridgeApiUrl = "https://zchain-testnet-bridge.eu-north-2.gateway.fm"; + +const main = async () => { + const [deployerZChain] = await hre.ethers.getSigners(); + + const bridgeFactory = await hre.ethers.getContractFactory("PolygonZkEVMBridgeV2", deployerZChain); + const bridgeContract = bridgeFactory.attach(zChainTestBridgeAddress); + + const axio = axios.create({ baseURL: zChainBridgeApiUrl }); + const { data: { deposits } } = await axio.get( + getClaimsFromAcc + receiverAddress, + { params: { limit: 100, offset: 0 } } + ); + + const latestDeposit = deposits[deposits.length - 1]; + if (latestDeposit.ready_for_claim) { + const { data: { proof } } = await axio.get( + mekrleProofString, + { + params: { + deposit_cnt: latestDeposit.deposit_cnt, + net_id: latestDeposit.orig_net, + }, + } + ); + + // claim message + const tx = await bridgeContract.claimMessage( + proof.merkle_proof, + latestDeposit.deposit_cnt, + proof.main_exit_root, + proof.rollup_exit_root, + latestDeposit.orig_net, + latestDeposit.dest_addr, + latestDeposit.dest_net, + latestDeposit.dest_addr, + latestDeposit.amount, + latestDeposit.metadata + ); + + console.log(`Claim sent successfully! Tx hash: ${tx.hash}`); + const rec = await tx.wait(); + console.log(`Claim message mined! Tx receipt: ${rec}`); + } else { + console.log("Bridged message NOT ready for claim!"); + } + + console.log("Claim process completed successfully!"); +}; + +main().catch(error => { + console.error(error); + process.exit(1); +}); diff --git a/test/L2-BRIDGE-TEST/send.ts b/test/L2-BRIDGE-TEST/send.ts new file mode 100644 index 000000000..9731fdca6 --- /dev/null +++ b/test/L2-BRIDGE-TEST/send.ts @@ -0,0 +1,36 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +import * as hre from "hardhat"; +import path from "path"; + + +const networkIDzkEVM = 1; + +const deployData = path.join(__dirname, "./addresses.json"); +export const { senderAddress, receiverAddress } = require(deployData); + + +const main = async () => { + const [deployerSepolia] = await hre.ethers.getSigners(); + + const senderFact = await hre.ethers.getContractFactory("BridgeSender", deployerSepolia); + const bridgeSender = senderFact.attach(senderAddress); + + const forceUpdateGlobalExitRoot = true; // fast bridge + const message = "0://zero-bridge"; + + const tx = await bridgeSender.bridgeMessage( + networkIDzkEVM, + receiverAddress, + forceUpdateGlobalExitRoot, + message + ); + + console.log("Transaction receipt:\n", await tx.wait()); + + console.log("Message bridged successfully!"); +}; + +main().catch(error => { + console.error(error); + process.exit(1); +}); From 700172954ff0ba404b3633ac2c96215b869c5522 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 17 Sep 2024 14:38:28 -0700 Subject: [PATCH 005/124] fix networkId --- test/L2-BRIDGE-TEST/send.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/L2-BRIDGE-TEST/send.ts b/test/L2-BRIDGE-TEST/send.ts index 9731fdca6..dba2f9b91 100644 --- a/test/L2-BRIDGE-TEST/send.ts +++ b/test/L2-BRIDGE-TEST/send.ts @@ -3,7 +3,7 @@ import * as hre from "hardhat"; import path from "path"; -const networkIDzkEVM = 1; +const networkIDzChainTest = 1668201165; const deployData = path.join(__dirname, "./addresses.json"); export const { senderAddress, receiverAddress } = require(deployData); @@ -19,7 +19,7 @@ const main = async () => { const message = "0://zero-bridge"; const tx = await bridgeSender.bridgeMessage( - networkIDzkEVM, + networkIDzChainTest, receiverAddress, forceUpdateGlobalExitRoot, message From c2c4fecbb864f5c076d0b4ccb873ab1a19fb15ce Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 19 Sep 2024 14:48:08 -0700 Subject: [PATCH 006/124] create extension of the Bridge interface to be able to call networkID() --- contracts/L2-BRIDGE-TEST/IPolygonZkEVMBridgeV2Ext.sol | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 contracts/L2-BRIDGE-TEST/IPolygonZkEVMBridgeV2Ext.sol diff --git a/contracts/L2-BRIDGE-TEST/IPolygonZkEVMBridgeV2Ext.sol b/contracts/L2-BRIDGE-TEST/IPolygonZkEVMBridgeV2Ext.sol new file mode 100644 index 000000000..2b43e0019 --- /dev/null +++ b/contracts/L2-BRIDGE-TEST/IPolygonZkEVMBridgeV2Ext.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: AGPL-3.0 + +pragma solidity ^0.8.20; + +import { IPolygonZkEVMBridgeV2 } from "zkevm-contracts/contracts/v2/interfaces/IPolygonZkEVMBridgeV2.sol"; + + +interface IPolygonZkEVMBridgeV2Ext is IPolygonZkEVMBridgeV2 { + function networkID() external view returns (uint32); +} From 103276e4f27bb19b27fecf295314ebae4aae6f87 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 19 Sep 2024 14:48:23 -0700 Subject: [PATCH 007/124] fix test contracts --- contracts/L2-BRIDGE-TEST/BridgeReceiver.sol | 12 ++++++------ contracts/L2-BRIDGE-TEST/BridgeSender.sol | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/contracts/L2-BRIDGE-TEST/BridgeReceiver.sol b/contracts/L2-BRIDGE-TEST/BridgeReceiver.sol index a13f2ecbd..80229deff 100644 --- a/contracts/L2-BRIDGE-TEST/BridgeReceiver.sol +++ b/contracts/L2-BRIDGE-TEST/BridgeReceiver.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.26; import { IBridgeMessageReceiver } from "zkevm-contracts/contracts/interfaces/IBridgeMessageReceiver.sol"; +import { IPolygonZkEVMBridgeV2Ext } from "./IPolygonZkEVMBridgeV2Ext.sol"; import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; @@ -15,7 +16,7 @@ contract BridgeReceiver is IBridgeMessageReceiver { error NotPolygonZkEVMBridge(); // Global Exit Root address - IPolygonZkEVMBridge public immutable polygonZkEVMBridge; + IPolygonZkEVMBridgeV2Ext public immutable polygonZkEVMBridge; // Current network identifier uint32 public immutable networkID; @@ -24,7 +25,7 @@ contract BridgeReceiver is IBridgeMessageReceiver { address public senderContract; - constructor(IPolygonZkEVMBridge bridgeAddress) { + constructor(IPolygonZkEVMBridgeV2Ext bridgeAddress) { if (address(bridgeAddress) == address(0)) revert ZeroAddressPassed(); polygonZkEVMBridge = bridgeAddress; networkID = polygonZkEVMBridge.networkID(); @@ -34,11 +35,8 @@ contract BridgeReceiver is IBridgeMessageReceiver { address originAddress, uint32 originNetwork, bytes memory data - ) external override { + ) external payable override { // Can only be called by the bridge - if (msg.sender == address(polygonZkEVMBridge)) - revert NotPolygonZkEVMBridge(); - // Can only be called by the sender on the other network // require( // pingSender == originAddress, @@ -46,6 +44,8 @@ contract BridgeReceiver is IBridgeMessageReceiver { // ); string memory message = abi.decode(data, (string)); + messageState = message; + senderContract = originAddress; emit MessageReceived(originAddress, originNetwork, message); } diff --git a/contracts/L2-BRIDGE-TEST/BridgeSender.sol b/contracts/L2-BRIDGE-TEST/BridgeSender.sol index cb8053314..296f8efab 100644 --- a/contracts/L2-BRIDGE-TEST/BridgeSender.sol +++ b/contracts/L2-BRIDGE-TEST/BridgeSender.sol @@ -10,13 +10,13 @@ contract BridgeSender { event MessageBridged( uint32 destinationNetwork, address destinationAddress, - string memory message + string message ); // Global Exit Root address - IPolygonZkEVMBridge public immutable polygonZkEVMBridge; + IPolygonZkEVMBridgeV2 public immutable polygonZkEVMBridge; - cosntrcutor(IPolygonZkEVMBridgeV2 bridgeAddress) { + constructor(IPolygonZkEVMBridgeV2 bridgeAddress) { if (address(bridgeAddress) == address(0)) revert ZeroAddressPassed(); polygonZkEVMBridge = bridgeAddress; } From c974173868ccbb2bd396e0bf99385533739f3d20 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 19 Sep 2024 14:48:45 -0700 Subject: [PATCH 008/124] add zchaintest to HH config --- hardhat.config.ts | 55 ++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index e26733e27..024c698d3 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -105,14 +105,14 @@ const config : HardhatUserConfig = { sepolia: { url: `${process.env.SEPOLIA_RPC_URL}`, timeout: 10000000, - // accounts: [ // Comment out for CI, uncomment this when using Sepolia - // `${process.env.TESTNET_PRIVATE_KEY_A}`, - // `${process.env.TESTNET_PRIVATE_KEY_B}`, - // `${process.env.TESTNET_PRIVATE_KEY_C}`, - // `${process.env.TESTNET_PRIVATE_KEY_D}`, - // `${process.env.TESTNET_PRIVATE_KEY_E}`, - // `${process.env.TESTNET_PRIVATE_KEY_F}`, - // ], + accounts: [ // Comment out for CI, uncomment this when using Sepolia + `${process.env.TESTNET_PRIVATE_KEY_A}`, + // `${process.env.TESTNET_PRIVATE_KEY_B}`, + // `${process.env.TESTNET_PRIVATE_KEY_C}`, + // `${process.env.TESTNET_PRIVATE_KEY_D}`, + // `${process.env.TESTNET_PRIVATE_KEY_E}`, + // `${process.env.TESTNET_PRIVATE_KEY_F}`, + ], // // Must have to avoid instead failing as `invalid length for result data` error // throwOnCallFailures: false, // not sure if this even works }, @@ -121,26 +121,27 @@ const config : HardhatUserConfig = { url: `${process.env.DEVNET_RPC_URL}`, chainId: 1, }, - // meowtestnet: { - // url: `${process.env.MEOWTESTNET_RPC_URL}`, - // accounts: [ - // `${process.env.DEPLOYER_PRIVATE_KEY}`, - // ], - // }, + zchaintest: { + url: `${process.env.ZCHAINTEST_RPC_URL}`, + chainId: 1668201165, + accounts: [ + `${process.env.TESTNET_PRIVATE_KEY_A}`, + ], + }, + }, + etherscan: { + apiKey: `${process.env.ETHERSCAN_API_KEY}`, + customChains: [ + { + network: "zchaintest", + chainId: 1668201165, + urls: { + apiURL: "https://zchain-testnet-blockscout.eu-north-2.gateway.fm/api/", + browserURL: "https://zchain-testnet-blockscout.eu-north-2.gateway.fm/", + }, + }, + ], }, - // etherscan: { - // apiKey: `${process.env.ETHERSCAN_API_KEY}`, - // customChains: [ - // { - // network: "meowtestnet", - // chainId: 883424730, - // urls: { - // apiURL: "https://meowchain-testnet-blockscout.eu-north-2.gateway.fm/api/", - // browserURL: "https://meowchain-testnet-blockscout.eu-north-2.gateway.fm/", - // }, - // }, - // ], - // }, sourcify: { // If set to "true", will try to verify the contracts after deployment enabled: false, From 71605861318ab2b5fe3d16b1b53410f27e5a499e Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 19 Sep 2024 14:49:04 -0700 Subject: [PATCH 009/124] install error decoder package from ethers and add script for easy run --- package.json | 4 +++- yarn.lock | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 961f8969d..47fc01b98 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,8 @@ "mongo:drop": "ts-node src/utils/drop-db.ts", "run-sepolia": "hardhat run src/deploy/run-campaign.ts --network sepolia", "run-hardhat": "hardhat run src/deploy/run-campaign.ts --network hardhat", - "run-meowtestnet": "hardhat run src/deploy/run-campaign.ts --network meowtestnet" + "run-meowtestnet": "hardhat run src/deploy/run-campaign.ts --network meowtestnet", + "run-gmp": "hardhat run test/L2-BRIDGE-TEST/claim.ts --network zchaintest" }, "pre-commit": [ "lint" @@ -66,6 +67,7 @@ "chai": "^4.3.10", "eslint": "^8.37.0", "ethers": "^6.9.0", + "ethers-decode-error": "^2.1.3", "hardhat": "^2.22.6", "hardhat-gas-reporter": "^1.0.9", "semantic-release": "^21.0.1", diff --git a/yarn.lock b/yarn.lock index 74ce5aa63..95e040b17 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3967,6 +3967,11 @@ ethereumjs-util@^7.0.3, ethereumjs-util@^7.1.4, ethereumjs-util@^7.1.5: ethereum-cryptography "^0.1.3" rlp "^2.2.4" +ethers-decode-error@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ethers-decode-error/-/ethers-decode-error-2.1.3.tgz#ed0c81a400e9b66bba8c3ce356a4e52eab878e3f" + integrity sha512-x27u04XC/s8MRpuqiylIXbj4KMrt/5clYS2nle1b0bgbWFuoUZocDzjfXEfc5KzVmCQuITD9elqyO2VyxTGwdw== + ethers@^5.0.13, ethers@^5.7.0, ethers@^5.7.2: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" From 33514051eb3e7e96f51a87f0af0538d323564a6f Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 19 Sep 2024 14:49:39 -0700 Subject: [PATCH 010/124] modify test flow scripts --- test/L2-BRIDGE-TEST/claim.ts | 56 +++++++++++++++++++++++------------ test/L2-BRIDGE-TEST/deploy.ts | 25 +++++++++++----- test/L2-BRIDGE-TEST/send.ts | 9 +++--- 3 files changed, 60 insertions(+), 30 deletions(-) diff --git a/test/L2-BRIDGE-TEST/claim.ts b/test/L2-BRIDGE-TEST/claim.ts index 0a3339725..4e1df09e3 100644 --- a/test/L2-BRIDGE-TEST/claim.ts +++ b/test/L2-BRIDGE-TEST/claim.ts @@ -1,26 +1,34 @@ /* eslint-disable @typescript-eslint/no-var-requires, camelcase */ import * as hre from "hardhat"; import axios from "axios"; -import { zChainTestBridgeAddress } from "./deploy"; -import { receiverAddress } from "./send"; +import { ErrorDecoder } from "ethers-decode-error"; +import { receiverAddress } from "./addresses.json"; const mekrleProofString = "/merkle-proof"; const getClaimsFromAcc = "/bridges/"; -const zChainBridgeApiUrl = "https://zchain-testnet-bridge.eu-north-2.gateway.fm"; +const zChainBridgeApiUrl = "https://zchain-testnet-bridge-api.eu-north-2.gateway.fm/"; +const zChainRpcUrl = "https://zchain-testnet-rpc.eu-north-2.gateway.fm/"; +const zChainTestBridgeAddress = "0x528e26b25a34a4A5d0dbDa1d57D318153d2ED582"; + const main = async () => { + // launch HH script with "--network zchaintest" flag to get this! const [deployerZChain] = await hre.ethers.getSigners(); - const bridgeFactory = await hre.ethers.getContractFactory("PolygonZkEVMBridgeV2", deployerZChain); - const bridgeContract = bridgeFactory.attach(zChainTestBridgeAddress); + const bridgeArt = require("./PolygonZkEVMBridgeV2.json"); + const bridgeContract = new hre.ethers.Contract(zChainTestBridgeAddress, bridgeArt.abi, deployerZChain); const axio = axios.create({ baseURL: zChainBridgeApiUrl }); - const { data: { deposits } } = await axio.get( + const result = await axio.get( getClaimsFromAcc + receiverAddress, { params: { limit: 100, offset: 0 } } ); + const { data: { deposits } } = result; + + console.log("Deposits acquired:", JSON.stringify(deposits, null, "\t")); + const latestDeposit = deposits[deposits.length - 1]; if (latestDeposit.ready_for_claim) { const { data: { proof } } = await axio.get( @@ -33,19 +41,29 @@ const main = async () => { } ); - // claim message - const tx = await bridgeContract.claimMessage( - proof.merkle_proof, - latestDeposit.deposit_cnt, - proof.main_exit_root, - proof.rollup_exit_root, - latestDeposit.orig_net, - latestDeposit.dest_addr, - latestDeposit.dest_net, - latestDeposit.dest_addr, - latestDeposit.amount, - latestDeposit.metadata - ); + console.log("Proof acquired:", JSON.stringify(proof, null, "\t")); + + const errorDecoder = ErrorDecoder.create([bridgeContract.interface]); + let tx; + try { + // claim message + tx = await bridgeContract.claimMessage( + proof.merkle_proof, + proof.rollup_merkle_proof, + latestDeposit.global_index, + proof.main_exit_root, + proof.rollup_exit_root, + latestDeposit.orig_net, + latestDeposit.orig_addr, + latestDeposit.dest_net, + latestDeposit.dest_addr, + latestDeposit.amount, + latestDeposit.metadata + ); + } catch (error) { + const decoded = await errorDecoder.decode(error); + console.error("Claim failed!", decoded); + } console.log(`Claim sent successfully! Tx hash: ${tx.hash}`); const rec = await tx.wait(); diff --git a/test/L2-BRIDGE-TEST/deploy.ts b/test/L2-BRIDGE-TEST/deploy.ts index d9fb0de5c..eb3fc8682 100644 --- a/test/L2-BRIDGE-TEST/deploy.ts +++ b/test/L2-BRIDGE-TEST/deploy.ts @@ -1,35 +1,46 @@ import path from "path"; import * as hre from "hardhat"; import fs from "fs"; +import { ethers } from "ethers"; -export const sepoliaBridgeAddress = "0x528e26b25a34a4A5d0dbDa1d57D318153d2ED582"; -export const zChainTestBridgeAddress = "0x528e26b25a34a4A5d0dbDa1d57D318153d2ED582"; -export const zChainRpcUrl = "https://zchain-testnet-rpc.eu-north-2.gateway.fm"; +const sepoliaBridgeAddress = "0x528e26b25a34a4A5d0dbDa1d57D318153d2ED582"; +const zChainTestBridgeAddress = "0x528e26b25a34a4A5d0dbDa1d57D318153d2ED582"; +const zChainRpcUrl = "https://zchain-testnet-rpc.eu-north-2.gateway.fm/"; const main = async () => { const [deployerSepolia] = await hre.ethers.getSigners(); - const providerZChain = new hre.ethers.JsonRpcProvider(zChainRpcUrl); - const deployerZChain = new hre.ethers.Wallet(`0x${process.env.Z_CHAIN_PRIVATE_KEY}`, providerZChain); - // deploy BridgeSender contract + const providerZChain = new ethers.JsonRpcProvider(zChainRpcUrl); + const deployerZChain = new ethers.Wallet(`0x${process.env.TESTNET_PRIVATE_KEY_A}`, providerZChain); + + // deploy BridgeSender contract to Sepolia const senderFactory = await hre.ethers.getContractFactory("BridgeSender", deployerSepolia); const senderContract = await senderFactory.deploy(sepoliaBridgeAddress); await senderContract.waitForDeployment(); console.log("BridgeSender deployed to:", senderContract.target); - // deploy BridgeReceiver contract + // deploy BridgeReceiver contract to ZChain const receiverFactory = await hre.ethers.getContractFactory("BridgeReceiver", deployerZChain); const receiverContract = await receiverFactory.deploy(zChainTestBridgeAddress); await receiverContract.waitForDeployment(); console.log("BridgeReceiver deployed to:", receiverContract.target); + await hre.run("verify:verify", { + address: receiverContract.target, + constructorArguments: [zChainTestBridgeAddress], + }); + // Write output + // ! Please note that this will OVERWRITE whatever was in the file, + // copy the file or change this code to keep the previous data + // Contract are already deployed and can be accessed by addresses from addresses.json! const outputJson = { senderAddress: senderContract.target, receiverAddress: receiverContract.target, }; + console.log(`Contract data: ${JSON.stringify(outputJson, null, "\t")}`); const pathOutputJson = path.join(__dirname, "./addresses.json"); fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, "\t")); diff --git a/test/L2-BRIDGE-TEST/send.ts b/test/L2-BRIDGE-TEST/send.ts index dba2f9b91..4b602e3ca 100644 --- a/test/L2-BRIDGE-TEST/send.ts +++ b/test/L2-BRIDGE-TEST/send.ts @@ -1,22 +1,23 @@ /* eslint-disable @typescript-eslint/no-var-requires */ import * as hre from "hardhat"; import path from "path"; +import { BridgeSender } from "../../typechain"; -const networkIDzChainTest = 1668201165; +const networkIDzChainTest = 19n; const deployData = path.join(__dirname, "./addresses.json"); -export const { senderAddress, receiverAddress } = require(deployData); +const { senderAddress, receiverAddress } = require(deployData); const main = async () => { const [deployerSepolia] = await hre.ethers.getSigners(); const senderFact = await hre.ethers.getContractFactory("BridgeSender", deployerSepolia); - const bridgeSender = senderFact.attach(senderAddress); + const bridgeSender = senderFact.attach(senderAddress) as BridgeSender; const forceUpdateGlobalExitRoot = true; // fast bridge - const message = "0://zero-bridge"; + const message = "0://setstatestringdomain"; // change this string for test calls const tx = await bridgeSender.bridgeMessage( networkIDzChainTest, From 85649b99e0d2b58ed8566c868c2b82a79154b356 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 19 Sep 2024 14:50:01 -0700 Subject: [PATCH 011/124] add Bridge json for easy contract access and use it's abi --- test/L2-BRIDGE-TEST/PolygonZkEVMBridgeV2.json | 1013 +++++++++++++++++ 1 file changed, 1013 insertions(+) create mode 100644 test/L2-BRIDGE-TEST/PolygonZkEVMBridgeV2.json diff --git a/test/L2-BRIDGE-TEST/PolygonZkEVMBridgeV2.json b/test/L2-BRIDGE-TEST/PolygonZkEVMBridgeV2.json new file mode 100644 index 000000000..0fac2b1db --- /dev/null +++ b/test/L2-BRIDGE-TEST/PolygonZkEVMBridgeV2.json @@ -0,0 +1,1013 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "PolygonZkEVMBridgeV2", + "sourceName": "contracts/v2/PolygonZkEVMBridgeV2.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AlreadyClaimed", + "type": "error" + }, + { + "inputs": [], + "name": "AmountDoesNotMatchMsgValue", + "type": "error" + }, + { + "inputs": [], + "name": "DestinationNetworkInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "EtherTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "FailedTokenWrappedDeployment", + "type": "error" + }, + { + "inputs": [], + "name": "GasTokenNetworkMustBeZeroOnEther", + "type": "error" + }, + { + "inputs": [], + "name": "GlobalExitRootInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSmtProof", + "type": "error" + }, + { + "inputs": [], + "name": "MerkleTreeFull", + "type": "error" + }, + { + "inputs": [], + "name": "MessageFailed", + "type": "error" + }, + { + "inputs": [], + "name": "MsgValueNotZero", + "type": "error" + }, + { + "inputs": [], + "name": "NativeTokenIsEther", + "type": "error" + }, + { + "inputs": [], + "name": "NoValueInMessagesOnGasTokenNetworks", + "type": "error" + }, + { + "inputs": [], + "name": "NotValidAmount", + "type": "error" + }, + { + "inputs": [], + "name": "NotValidOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NotValidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "NotValidSpender", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyEmergencyState", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyNotEmergencyState", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyRollupManager", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "leafType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "originAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "destinationNetwork", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "destinationAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "depositCount", + "type": "uint32" + } + ], + "name": "BridgeEvent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "globalIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "originAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "destinationAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ClaimEvent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EmergencyStateActivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EmergencyStateDeactivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "originTokenAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "wrappedTokenAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + } + ], + "name": "NewWrappedToken", + "type": "event" + }, + { + "inputs": [], + "name": "BASE_INIT_BYTECODE_WRAPPED_TOKEN", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WETHToken", + "outputs": [ + { + "internalType": "contract TokenWrapped", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "activateEmergencyState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "destinationNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "destinationAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "forceUpdateGlobalExitRoot", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "permitData", + "type": "bytes" + } + ], + "name": "bridgeAsset", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "destinationNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "destinationAddress", + "type": "address" + }, + { + "internalType": "bool", + "name": "forceUpdateGlobalExitRoot", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + } + ], + "name": "bridgeMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "destinationNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "destinationAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountWETH", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "forceUpdateGlobalExitRoot", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + } + ], + "name": "bridgeMessageWETH", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "leafHash", + "type": "bytes32" + }, + { + "internalType": "bytes32[32]", + "name": "smtProof", + "type": "bytes32[32]" + }, + { + "internalType": "uint32", + "name": "index", + "type": "uint32" + } + ], + "name": "calculateRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "originTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "calculateTokenWrapperAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[32]", + "name": "smtProofLocalExitRoot", + "type": "bytes32[32]" + }, + { + "internalType": "bytes32[32]", + "name": "smtProofRollupExitRoot", + "type": "bytes32[32]" + }, + { + "internalType": "uint256", + "name": "globalIndex", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "mainnetExitRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "rollupExitRoot", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "originTokenAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "destinationNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "destinationAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + } + ], + "name": "claimAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[32]", + "name": "smtProofLocalExitRoot", + "type": "bytes32[32]" + }, + { + "internalType": "bytes32[32]", + "name": "smtProofRollupExitRoot", + "type": "bytes32[32]" + }, + { + "internalType": "uint256", + "name": "globalIndex", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "mainnetExitRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "rollupExitRoot", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "originAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "destinationNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "destinationAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + } + ], + "name": "claimMessage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "claimedBitMap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "deactivateEmergencyState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "depositCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gasTokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gasTokenMetadata", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gasTokenNetwork", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "leafType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "originAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "destinationNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "destinationAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "metadataHash", + "type": "bytes32" + } + ], + "name": "getLeafValue", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "getTokenMetadata", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "originTokenAddress", + "type": "address" + } + ], + "name": "getTokenWrappedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalExitRootManager", + "outputs": [ + { + "internalType": "contract IBasePolygonZkEVMGlobalExitRoot", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_networkID", + "type": "uint32" + }, + { + "internalType": "address", + "name": "_gasTokenAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "_gasTokenNetwork", + "type": "uint32" + }, + { + "internalType": "contract IBasePolygonZkEVMGlobalExitRoot", + "name": "_globalExitRootManager", + "type": "address" + }, + { + "internalType": "address", + "name": "_polygonRollupManager", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_gasTokenMetadata", + "type": "bytes" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "leafIndex", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "sourceBridgeNetwork", + "type": "uint32" + } + ], + "name": "isClaimed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isEmergencyState", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastUpdatedDepositCount", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "networkID", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "polygonRollupManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "originTokenAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + } + ], + "name": "precalculatedWrapperAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "tokenInfoToWrappedToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "updateGlobalExitRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "leafHash", + "type": "bytes32" + }, + { + "internalType": "bytes32[32]", + "name": "smtProof", + "type": "bytes32[32]" + }, + { + "internalType": "uint32", + "name": "index", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "root", + "type": "bytes32" + } + ], + "name": "verifyMerkleProof", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "wrappedTokenToTokenInfo", + "outputs": [ + { + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "originTokenAddress", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x608060405234801562000010575f80fd5b506200001b62000021565b620000e0565b5f54610100900460ff16156200008d5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff9081161015620000de575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b61591b80620000ee5f395ff3fe6080604052600436106101db575f3560e01c806383f24403116100fd578063ccaa2d1111610092578063ee25560b11610062578063ee25560b146105a9578063f5efcd79146105d4578063f811bff7146105f3578063fb57083414610612575f80fd5b8063ccaa2d111461053b578063cd5865791461055a578063d02103ca1461056d578063dbc1697614610595575f80fd5b8063bab161bf116100cd578063bab161bf146104b9578063be5831c7146104da578063c00f14ab146104fd578063cc4616321461051c575f80fd5b806383f244031461043d5780638ed7e3f21461045c578063aaa13cc21461047b578063b8b284d01461049a575f80fd5b80633cbc795b116101735780637843298b116101435780637843298b146103c257806379e2cf97146103e157806381b1c174146103f557806383c43a5514610429575f80fd5b80633cbc795b146103385780633e197043146103705780634b2f336d1461038f5780635ca1e165146103ae575f80fd5b806327aef4e8116101ae57806327aef4e81461026d5780632dfdf0b51461028e578063318aee3d146102b15780633c351e1014610319575f80fd5b806315064c96146101df5780632072f6c51461020d57806322e95f2c14610223578063240ff3781461025a575b5f80fd5b3480156101ea575f80fd5b506068546101f89060ff1681565b60405190151581526020015b60405180910390f35b348015610218575f80fd5b50610221610631565b005b34801561022e575f80fd5b5061024261023d366004612fb9565b610666565b6040516001600160a01b039091168152602001610204565b610221610268366004613040565b6106d0565b348015610278575f80fd5b50610281610759565b6040516102049190613102565b348015610299575f80fd5b506102a360535481565b604051908152602001610204565b3480156102bc575f80fd5b506102f56102cb36600461311b565b606b6020525f908152604090205463ffffffff81169064010000000090046001600160a01b031682565b6040805163ffffffff90931683526001600160a01b03909116602083015201610204565b348015610324575f80fd5b50606d54610242906001600160a01b031681565b348015610343575f80fd5b50606d5461035b90600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610204565b34801561037b575f80fd5b506102a361038a366004613144565b6107e5565b34801561039a575f80fd5b50606f54610242906001600160a01b031681565b3480156103b9575f80fd5b506102a361088e565b3480156103cd575f80fd5b506102426103dc3660046131be565b61096a565b3480156103ec575f80fd5b50610221610993565b348015610400575f80fd5b5061024261040f366004613204565b606a6020525f90815260409020546001600160a01b031681565b348015610434575f80fd5b506102816109b4565b348015610448575f80fd5b506102a361045736600461322c565b6109d3565b348015610467575f80fd5b50606c54610242906001600160a01b031681565b348015610486575f80fd5b5061024261049536600461332d565b610aa8565b3480156104a5575f80fd5b506102216104b43660046133c3565b610be7565b3480156104c4575f80fd5b5060685461035b90610100900463ffffffff1681565b3480156104e5575f80fd5b5060685461035b90600160c81b900463ffffffff1681565b348015610508575f80fd5b5061028161051736600461311b565b610cc2565b348015610527575f80fd5b506101f8610536366004613441565b610d07565b348015610546575f80fd5b50610221610555366004613472565b610d8f565b610221610568366004613556565b6112c0565b348015610578575f80fd5b50606854610242906501000000000090046001600160a01b031681565b3480156105a0575f80fd5b5061022161172c565b3480156105b4575f80fd5b506102a36105c3366004613204565b60696020525f908152604090205481565b3480156105df575f80fd5b506102216105ee366004613472565b61175f565b3480156105fe575f80fd5b5061022161060d3660046135e6565b611a25565b34801561061d575f80fd5b506101f861062c366004613689565b611d40565b606c546001600160a01b0316331461065c57604051631736745960e31b815260040160405180910390fd5b610664611d57565b565b6040805160e084901b6001600160e01b031916602080830191909152606084901b6bffffffffffffffffffffffff1916602483015282516018818403018152603890920183528151918101919091205f908152606a90915220546001600160a01b03165b92915050565b60685460ff16156106f457604051630bc011ff60e21b815260040160405180910390fd5b341580159061070d5750606f546001600160a01b031615155b15610744576040517f6f625c4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610752858534868686611db2565b5050505050565b606e8054610766906136ce565b80601f0160208091040260200160405190810160405280929190818152602001828054610792906136ce565b80156107dd5780601f106107b4576101008083540402835291602001916107dd565b820191905f5260205f20905b8154815290600101906020018083116107c057829003601f168201915b505050505081565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201526001600160e01b031960e088811b821660218401526bffffffffffffffffffffffff19606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b6053545f90819081805b6020811015610961578083901c6001166001036108f557603381602081106108c2576108c2613706565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350610922565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b604080516020810184905290810183905260600160405160208183030381529060405280519060200120915080806109599061372e565b915050610898565b50919392505050565b5f61098b848461097985611e7c565b61098286611f66565b61049587612047565b949350505050565b605354606854600160c81b900463ffffffff16101561066457610664612114565b60405180611ba00160405280611b668152602001613d80611b66913981565b5f83815b6020811015610a9f57600163ffffffff8516821c81169003610a4257848160208110610a0557610a05613706565b602002013582604051602001610a25929190918252602082015260400190565b604051602081830303815290604052805190602001209150610a8d565b81858260208110610a5557610a55613706565b6020020135604051602001610a74929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b80610a978161372e565b9150506109d7565b50949350505050565b6040516001600160e01b031960e087901b1660208201526bffffffffffffffffffffffff19606086901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b308360405180611ba00160405280611b668152602001613d80611b669139898989604051602001610b3093929190613746565b60408051601f1981840301815290829052610b4e929160200161377e565b60405160208183030381529060405280519060200120604051602001610bc394939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b6bffffffffffffffffffffffff191660018401526015830152603582015260550190565b60408051808303601f19018152919052805160209091012098975050505050505050565b60685460ff1615610c0b57604051630bc011ff60e21b815260040160405180910390fd5b606f546001600160a01b0316610c4d576040517fdde3cda700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f54604051632770a7eb60e21b8152336004820152602481018690526001600160a01b0390911690639dc29fac906044015f604051808303815f87803b158015610c96575f80fd5b505af1158015610ca8573d5f803e3d5ffd5b50505050610cba868686868686611db2565b505050505050565b6060610ccd82611e7c565b610cd683611f66565b610cdf84612047565b604051602001610cf193929190613746565b6040516020818303038152906040529050919050565b6068545f908190610100900463ffffffff16158015610d2c575063ffffffff83166001145b15610d3e575063ffffffff8316610d66565b610d5364010000000063ffffffff85166137ac565b610d639063ffffffff86166137c3565b90505b600881901c5f90815260696020526040902054600160ff9092169190911b908116149392505050565b60685460ff1615610db357604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff8681166101009092041614610de3576040516302caf51760e11b815260040160405180910390fd5b610e168c8c8c8c8c610e115f8e8e8e8e8e8e8e604051610e049291906137d6565b60405180910390206107e5565b6121c2565b6001600160a01b038616610f6057606f546001600160a01b0316610efa575f6001600160a01b03851684825b6040519080825280601f01601f191660200182016040528015610e6c576020820181803683370190505b50604051610e7a91906137e5565b5f6040518083038185875af1925050503d805f8114610eb4576040519150601f19603f3d011682016040523d82523d5f602084013e610eb9565b606091505b5050905080610ef4576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611256565b606f546040516340c10f1960e01b81526001600160a01b03868116600483015260248201869052909116906340c10f19906044015f604051808303815f87803b158015610f45575f80fd5b505af1158015610f57573d5f803e3d5ffd5b50505050611256565b606d546001600160a01b038781169116148015610f8e5750606d5463ffffffff888116600160a01b90920416145b15610fa5575f6001600160a01b0385168482610e42565b60685463ffffffff610100909104811690881603610fd657610fd16001600160a01b0387168585612354565b611256565b6040516001600160e01b031960e089901b1660208201526bffffffffffffffffffffffff19606088901b1660248201525f9060380160408051601f1981840301815291815281516020928301205f818152606a9093529120549091506001600160a01b0316806111f5575f6110808386868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506123d592505050565b6040516340c10f1960e01b81526001600160a01b03898116600483015260248201899052919250908216906340c10f19906044015f604051808303815f87803b1580156110cb575f80fd5b505af11580156110dd573d5f803e3d5ffd5b5050505080606a5f8581526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060405180604001604052808b63ffffffff1681526020018a6001600160a01b0316815250606b5f836001600160a01b03166001600160a01b031681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a8154816001600160a01b0302191690836001600160a01b031602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398a8a8388886040516111e7959493929190613828565b60405180910390a150611253565b6040516340c10f1960e01b81526001600160a01b038781166004830152602482018790528216906340c10f19906044015f604051808303815f87803b15801561123c575f80fd5b505af115801561124e573d5f803e3d5ffd5b505050505b50505b604080518b815263ffffffff891660208201526001600160a01b0388811682840152861660608201526080810185905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a1505050505050505050505050565b60685460ff16156112e457604051630bc011ff60e21b815260040160405180910390fd5b6112ec612468565b60685463ffffffff61010090910481169088160361131d576040516302caf51760e11b815260040160405180910390fd5b5f806060876001600160a01b03881661141957883414611369576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606d54606e80546001600160a01b0383169650600160a01b90920463ffffffff16945090611396906136ce565b80601f01602080910402602001604051908101604052809291908181526020018280546113c2906136ce565b801561140d5780601f106113e45761010080835404028352916020019161140d565b820191905f5260205f20905b8154815290600101906020018083116113f057829003601f168201915b505050505091506116a3565b3415611451576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546001600160a01b03908116908916036114c757604051632770a7eb60e21b8152336004820152602481018a90526001600160a01b03891690639dc29fac906044015f604051808303815f87803b1580156114ac575f80fd5b505af11580156114be573d5f803e3d5ffd5b505050506116a3565b6001600160a01b038089165f908152606b602090815260409182902082518084019093525463ffffffff811683526401000000009004909216918101829052901561157957604051632770a7eb60e21b8152336004820152602481018b90526001600160a01b038a1690639dc29fac906044015f604051808303815f87803b158015611551575f80fd5b505af1158015611563573d5f803e3d5ffd5b5050505080602001519450805f01519350611696565b851561158b5761158b898b89896124c1565b6040516370a0823160e01b81523060048201525f906001600160a01b038b16906370a0823190602401602060405180830381865afa1580156115cf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f39190613860565b905061160a6001600160a01b038b1633308e612860565b6040516370a0823160e01b81523060048201525f906001600160a01b038c16906370a0823190602401602060405180830381865afa15801561164e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116729190613860565b905061167e8282613877565b6068548c9850610100900463ffffffff169650935050505b61169f89610cc2565b9250505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e86886053546040516116e298979695949392919061388a565b60405180910390a16117086117035f85878f8f8789805190602001206107e5565b6128b1565b861561171657611716612114565b5050505061172360018055565b50505050505050565b606c546001600160a01b0316331461175757604051631736745960e31b815260040160405180910390fd5b6106646129b2565b60685460ff161561178357604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff86811661010090920416146117b3576040516302caf51760e11b815260040160405180910390fd5b6117d58c8c8c8c8c610e1160018e8e8e8e8e8e8e604051610e049291906137d6565b606f545f906001600160a01b031661188857846001600160a01b031684888a868660405160240161180994939291906138f3565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b1790525161183e91906137e5565b5f6040518083038185875af1925050503d805f8114611878576040519150601f19603f3d011682016040523d82523d5f602084013e61187d565b606091505b505080915050611983565b606f546040516340c10f1960e01b81526001600160a01b03878116600483015260248201879052909116906340c10f19906044015f604051808303815f87803b1580156118d3575f80fd5b505af11580156118e5573d5f803e3d5ffd5b50505050846001600160a01b03168789858560405160240161190a94939291906138f3565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b1790525161193f91906137e5565b5f604051808303815f865af19150503d805f8114611978576040519150601f19603f3d011682016040523d82523d5f602084013e61197d565b606091505b50909150505b806119ba576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518c815263ffffffff8a1660208201526001600160a01b0389811682840152871660608201526080810186905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a150505050505050505050505050565b5f54610100900460ff1615808015611a4357505f54600160ff909116105b80611a5c5750303b158015611a5c57505f5460ff166001145b611ad35760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f805460ff191660011790558015611af4575f805461ff0019166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8a16027fffffffffffffff0000000000000000000000000000000000000000ffffffffff1617650100000000006001600160a01b038781169190910291909117909155606c805473ffffffffffffffffffffffffffffffffffffffff19168583161790558616611bcf5763ffffffff851615611bca576040517f1a874c1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ceb565b606d805463ffffffff8716600160a01b027fffffffffffffffff0000000000000000000000000000000000000000000000009091166001600160a01b03891617179055606e611c1e8382613970565b50611cbd5f801b6012604051602001611ca991906060808252600d908201527f5772617070656420457468657200000000000000000000000000000000000000608082015260a0602082018190526004908201527f574554480000000000000000000000000000000000000000000000000000000060c082015260ff91909116604082015260e00190565b6040516020818303038152906040526123d5565b606f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03929092169190911790555b611cf3612a22565b8015611723575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b5f81611d4d8686866109d3565b1495945050505050565b60685460ff1615611d7b57604051630bc011ff60e21b815260040160405180910390fd5b6068805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b60685463ffffffff610100909104811690871603611de3576040516302caf51760e11b815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338989898888605354604051611e3799989796959493929190613a2c565b60405180910390a1611e6e6117036001606860019054906101000a900463ffffffff16338a8a8a8989604051610e049291906137d6565b8215610cba57610cba612114565b60408051600481526024810182526020810180516001600160e01b03167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611edb91906137e5565b5f60405180830381855afa9150503d805f8114611f13576040519150601f19603f3d011682016040523d82523d5f602084013e611f18565b606091505b509150915081611f5d576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525061098b565b61098b81612a94565b60408051600481526024810182526020810180516001600160e01b03167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611fc591906137e5565b5f60405180830381855afa9150503d805f8114611ffd576040519150601f19603f3d011682016040523d82523d5f602084013e612002565b606091505b509150915081611f5d576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525061098b565b60408051600481526024810182526020810180516001600160e01b03167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f91829182916001600160a01b038616916120a591906137e5565b5f60405180830381855afa9150503d805f81146120dd576040519150601f19603f3d011682016040523d82523d5f602084013e6120e2565b606091505b50915091508180156120f5575080516020145b61210057601261098b565b8080602001905181019061098b9190613a97565b6053546068805463ffffffff909216600160c81b027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117908190556001600160a01b0365010000000000909104166333d6247d61217561088e565b6040518263ffffffff1660e01b815260040161219391815260200190565b5f604051808303815f87803b1580156121aa575f80fd5b505af11580156121bc573d5f803e3d5ffd5b50505050565b606854604080516020808201879052818301869052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091525f916501000000000090046001600160a01b03169063257b3632906084016020604051808303815f875af1158015612253573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122779190613860565b9050805f036122b1576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80680100000000000000008716156122f5578691506122d3848a8489611d40565b6122f0576040516338105f3b60e21b815260040160405180910390fd5b61233f565b602087901c612305816001613ab2565b9150879250612320612318868c866109d3565b8a8389611d40565b61233d576040516338105f3b60e21b815260040160405180910390fd5b505b6123498282612c64565b505050505050505050565b6040516001600160a01b0383166024820152604481018290526123d09084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612d24565b505050565b5f8060405180611ba00160405280611b668152602001613d80611b6691398360405160200161240592919061377e565b6040516020818303038152906040529050838151602083015ff591506001600160a01b038216612461576040517fbefb092000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5092915050565b6002600154036124ba5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611aca565b6002600155565b5f6124cf6004828486613acf565b6124d891613af6565b90507f2afa5331000000000000000000000000000000000000000000000000000000006001600160e01b03198216016126b2575f80808080808061251f896004818d613acf565b81019061252c9190613b26565b9650965096509650965096509650336001600160a01b0316876001600160a01b03161461256c5760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b03861630146125955760405163750643af60e01b815260040160405180910390fd5b8a85146125ce576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b0389811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180516001600160e01b03167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169161266591906137e5565b5f604051808303815f865af19150503d805f811461269e576040519150601f19603f3d011682016040523d82523d5f602084013e6126a3565b606091505b50505050505050505050610752565b6001600160e01b031981166323f2ebc360e21b146126fc576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f808080808080806127118a6004818e613acf565b81019061271e9190613b75565b97509750975097509750975097509750336001600160a01b0316886001600160a01b0316146127605760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b03871630146127895760405163750643af60e01b815260040160405180910390fd5b604080516001600160a01b038a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180516001600160e01b03166323f2ebc360e21b1790529151918f169161281091906137e5565b5f604051808303815f865af19150503d805f8114612849576040519150601f19603f3d011682016040523d82523d5f602084013e61284e565b606091505b50505050505050505050505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526121bc9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612399565b8060016128c060206002613cd3565b6128ca9190613877565b60535410612904576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60535f81546129139061372e565b918290555090505f5b60208110156129a3578082901c60011660010361294f57826033826020811061294757612947613706565b015550505050565b6033816020811061296257612962613706565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250808061299b9061372e565b91505061291c565b506123d0613cde565b60018055565b60685460ff166129ee576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b5f54610100900460ff16612a8c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401611aca565b610664612e08565b60606040825110612ab357818060200190518101906106ca9190613cf2565b8151602003612c26575f5b602081108015612b055750828181518110612adb57612adb613706565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b15612b1c5780612b148161372e565b915050612abe565b805f03612b5e57505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b5f8167ffffffffffffffff811115612b7857612b78613268565b6040519080825280601f01601f191660200182016040528015612ba2576020820181803683370190505b5090505f5b82811015612c1e57848181518110612bc157612bc1613706565b602001015160f81c60f81b828281518110612bde57612bde613706565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535080612c168161372e565b915050612ba7565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b6068545f90610100900463ffffffff16158015612c87575063ffffffff82166001145b15612c99575063ffffffff8216612cc1565b612cae64010000000063ffffffff84166137ac565b612cbe9063ffffffff85166137c3565b90505b600881901c5f8181526069602052604081208054600160ff861690811b91821892839055929091908183169003611723576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f612d78826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612e729092919063ffffffff16565b8051909150156123d05780806020019051810190612d969190613d64565b6123d05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611aca565b5f54610100900460ff166129ac5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401611aca565b606061098b84845f85855f80866001600160a01b03168587604051612e9791906137e5565b5f6040518083038185875af1925050503d805f8114612ed1576040519150601f19603f3d011682016040523d82523d5f602084013e612ed6565b606091505b5091509150612ee787838387612ef2565b979650505050505050565b60608315612f605782515f03612f59576001600160a01b0385163b612f595760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611aca565b508161098b565b61098b8383815115612f755781518083602001fd5b8060405162461bcd60e51b8152600401611aca9190613102565b803563ffffffff81168114612c5f575f80fd5b6001600160a01b0381168114612fb6575f80fd5b50565b5f8060408385031215612fca575f80fd5b612fd383612f8f565b91506020830135612fe381612fa2565b809150509250929050565b8015158114612fb6575f80fd5b5f8083601f84011261300b575f80fd5b50813567ffffffffffffffff811115613022575f80fd5b602083019150836020828501011115613039575f80fd5b9250929050565b5f805f805f60808688031215613054575f80fd5b61305d86612f8f565b9450602086013561306d81612fa2565b9350604086013561307d81612fee565b9250606086013567ffffffffffffffff811115613098575f80fd5b6130a488828901612ffb565b969995985093965092949392505050565b5f5b838110156130cf5781810151838201526020016130b7565b50505f910152565b5f81518084526130ee8160208601602086016130b5565b601f01601f19169290920160200192915050565b602081525f61311460208301846130d7565b9392505050565b5f6020828403121561312b575f80fd5b813561311481612fa2565b60ff81168114612fb6575f80fd5b5f805f805f805f60e0888a03121561315a575f80fd5b873561316581613136565b965061317360208901612f8f565b9550604088013561318381612fa2565b945061319160608901612f8f565b935060808801356131a181612fa2565b9699959850939692959460a0840135945060c09093013592915050565b5f805f606084860312156131d0575f80fd5b6131d984612f8f565b925060208401356131e981612fa2565b915060408401356131f981612fa2565b809150509250925092565b5f60208284031215613214575f80fd5b5035919050565b8061040081018310156106ca575f80fd5b5f805f610440848603121561323f575f80fd5b83359250613250856020860161321b565b915061325f6104208501612f8f565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156132a5576132a5613268565b604052919050565b5f67ffffffffffffffff8211156132c6576132c6613268565b50601f01601f191660200190565b5f6132e66132e1846132ad565b61327c565b90508281528383830111156132f9575f80fd5b828260208301375f602084830101529392505050565b5f82601f83011261331e575f80fd5b613114838335602085016132d4565b5f805f805f60a08688031215613341575f80fd5b61334a86612f8f565b9450602086013561335a81612fa2565b9350604086013567ffffffffffffffff80821115613376575f80fd5b61338289838a0161330f565b94506060880135915080821115613397575f80fd5b506133a48882890161330f565b92505060808601356133b581613136565b809150509295509295909350565b5f805f805f8060a087890312156133d8575f80fd5b6133e187612f8f565b955060208701356133f181612fa2565b945060408701359350606087013561340881612fee565b9250608087013567ffffffffffffffff811115613423575f80fd5b61342f89828a01612ffb565b979a9699509497509295939492505050565b5f8060408385031215613452575f80fd5b61345b83612f8f565b915061346960208401612f8f565b90509250929050565b5f805f805f805f805f805f806109208d8f03121561348e575f80fd5b6134988e8e61321b565b9b506134a88e6104008f0161321b565b9a506108008d013599506108208d013598506108408d013597506134cf6108608e01612f8f565b96506134df6108808e0135612fa2565b6108808d013595506134f46108a08e01612f8f565b94506135046108c08e0135612fa2565b6108c08d013593506108e08d0135925067ffffffffffffffff6109008e0135111561352d575f80fd5b61353e8e6109008f01358f01612ffb565b81935080925050509295989b509295989b509295989b565b5f805f805f805f60c0888a03121561356c575f80fd5b61357588612f8f565b9650602088013561358581612fa2565b955060408801359450606088013561359c81612fa2565b935060808801356135ac81612fee565b925060a088013567ffffffffffffffff8111156135c7575f80fd5b6135d38a828b01612ffb565b989b979a50959850939692959293505050565b5f805f805f8060c087890312156135fb575f80fd5b61360487612f8f565b9550602087013561361481612fa2565b945061362260408801612f8f565b9350606087013561363281612fa2565b9250608087013561364281612fa2565b915060a087013567ffffffffffffffff81111561365d575f80fd5b8701601f8101891361366d575f80fd5b61367c898235602084016132d4565b9150509295509295509295565b5f805f80610460858703121561369d575f80fd5b843593506136ae866020870161321b565b92506136bd6104208601612f8f565b939692955092936104400135925050565b600181811c908216806136e257607f821691505b60208210810361370057634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f6001820161373f5761373f61371a565b5060010190565b606081525f61375860608301866130d7565b828103602084015261376a81866130d7565b91505060ff83166040830152949350505050565b5f835161378f8184602088016130b5565b8351908301906137a38183602088016130b5565b01949350505050565b80820281158282048414176106ca576106ca61371a565b808201808211156106ca576106ca61371a565b818382375f9101908152919050565b5f82516137f68184602087016130b5565b9190910192915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b63ffffffff861681525f6001600160a01b03808716602084015280861660408401525060806060830152612ee7608083018486613800565b5f60208284031215613870575f80fd5b5051919050565b818103818111156106ca576106ca61371a565b5f61010060ff8b16835263ffffffff808b1660208501526001600160a01b03808b166040860152818a1660608601528089166080860152508660a08501528160c08501526138da828501876130d7565b925080851660e085015250509998505050505050505050565b6001600160a01b038516815263ffffffff84166020820152606060408201525f613921606083018486613800565b9695505050505050565b601f8211156123d0575f81815260208120601f850160051c810160208610156139515750805b601f850160051c820191505b81811015610cba5782815560010161395d565b815167ffffffffffffffff81111561398a5761398a613268565b61399e8161399884546136ce565b8461392b565b602080601f8311600181146139d1575f84156139ba5750858301515b5f19600386901b1c1916600185901b178555610cba565b5f85815260208120601f198616915b828110156139ff578886015182559484019460019091019084016139e0565b5085821015613a1c57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f61010060ff8c16835263ffffffff808c1660208501526001600160a01b03808c166040860152818b166060860152808a166080860152508760a08501528160c0850152613a7d8285018789613800565b925080851660e085015250509a9950505050505050505050565b5f60208284031215613aa7575f80fd5b815161311481613136565b63ffffffff8181168382160190808211156124615761246161371a565b5f8085851115613add575f80fd5b83861115613ae9575f80fd5b5050820193919092039150565b6001600160e01b03198135818116916004851015613b1e5780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a031215613b3c575f80fd5b8735613b4781612fa2565b96506020880135613b5781612fa2565b9550604088013594506060880135935060808801356131a181613136565b5f805f805f805f80610100898b031215613b8d575f80fd5b8835613b9881612fa2565b97506020890135613ba881612fa2565b965060408901359550606089013594506080890135613bc681612fee565b935060a0890135613bd681613136565b979a969950949793969295929450505060c08201359160e0013590565b600181815b80851115613c2d57815f1904821115613c1357613c1361371a565b80851615613c2057918102915b93841c9390800290613bf8565b509250929050565b5f82613c43575060016106ca565b81613c4f57505f6106ca565b8160018114613c655760028114613c6f57613c8b565b60019150506106ca565b60ff841115613c8057613c8061371a565b50506001821b6106ca565b5060208310610133831016604e8410600b8410161715613cae575081810a6106ca565b613cb88383613bf3565b805f1904821115613ccb57613ccb61371a565b029392505050565b5f6131148383613c35565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215613d02575f80fd5b815167ffffffffffffffff811115613d18575f80fd5b8201601f81018413613d28575f80fd5b8051613d366132e1826132ad565b818152856020838501011115613d4a575f80fd5b613d5b8260208301602086016130b5565b95945050505050565b5f60208284031215613d74575f80fd5b815161311481612fee56fe6101006040523480156200001257600080fd5b5060405162001b6638038062001b6683398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516116aa620004bc6000396000610237015260008181610307015281816105c001526106a70152600061053a015260008181610379015261050401526116aa6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf1461039b578063dd62ed3e146103ae578063ffa1ad74146103f457600080fd5b8063a457c2d71461034e578063a9059cbb14610361578063cd0d00961461037457600080fd5b806395d89b41116100bd57806395d89b41146102e75780639dc29fac146102ef578063a3c573eb1461030257600080fd5b806370a08231146102915780637ecebe00146102c757600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b610184610430565b60405161019191906113e4565b60405180910390f35b6101ad6101a8366004611479565b6104c2565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad6102043660046114a3565b6104dc565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c1610500565b6101ad610277366004611479565b61055c565b61028f61028a366004611479565b6105a8565b005b6101c161029f3660046114df565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101c16102d53660046114df565b60056020526000908152604090205481565b610184610680565b61028f6102fd366004611479565b61068f565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101ad61035c366004611479565b61075e565b6101ad61036f366004611479565b61082f565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f6103a9366004611501565b61083d565b6101c16103bc366004611574565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043f906115a7565b80601f016020809104026020016040519081016040528092919081815260200182805461046b906115a7565b80156104b85780601f1061048d576101008083540402835291602001916104b8565b820191906000526020600020905b81548152906001019060200180831161049b57829003601f168201915b5050505050905090565b6000336104d0818585610b73565b60019150505b92915050565b6000336104ea858285610d27565b6104f5858585610dfe565b506001949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610537576105324661106d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104d090829086906105a3908790611629565b610b73565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b61067c8282611135565b5050565b60606004805461043f906115a7565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610669565b61067c8282611228565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610669565b6104f58286868403610b73565b6000336104d0818585610dfe565b834211156108cc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866109268361163c565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610991610500565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a55573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ad057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610669565b610b678a8a8a610b73565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610df85781811015610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610669565b610df88484848403610b73565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ea1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610df8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611098610430565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff82166111b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610669565b80600260008282546111c49190611629565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015611381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610d1a565b600060208083528351808285015260005b81811015611411578581018301518582016040015282016113f5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461147457600080fd5b919050565b6000806040838503121561148c57600080fd5b61149583611450565b946020939093013593505050565b6000806000606084860312156114b857600080fd5b6114c184611450565b92506114cf60208501611450565b9150604084013590509250925092565b6000602082840312156114f157600080fd5b6114fa82611450565b9392505050565b600080600080600080600060e0888a03121561151c57600080fd5b61152588611450565b965061153360208901611450565b95506040880135945060608801359350608088013560ff8116811461155757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561158757600080fd5b61159083611450565b915061159e60208401611450565b90509250929050565b600181811c908216806115bb57607f821691505b6020821081036115f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104d6576104d66115fa565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361166d5761166d6115fa565b506001019056fea26469706673582212208d88fee561cff7120d381c345cfc534cef8229a272dc5809d4bbb685ad67141164736f6c63430008110033a2646970667358221220432f6d6b4446edbe1f73c19fd2115454d5c35d8b03b98a74fd46724151d7672264736f6c63430008140033", + "deployedBytecode": "0x6080604052600436106101db575f3560e01c806383f24403116100fd578063ccaa2d1111610092578063ee25560b11610062578063ee25560b146105a9578063f5efcd79146105d4578063f811bff7146105f3578063fb57083414610612575f80fd5b8063ccaa2d111461053b578063cd5865791461055a578063d02103ca1461056d578063dbc1697614610595575f80fd5b8063bab161bf116100cd578063bab161bf146104b9578063be5831c7146104da578063c00f14ab146104fd578063cc4616321461051c575f80fd5b806383f244031461043d5780638ed7e3f21461045c578063aaa13cc21461047b578063b8b284d01461049a575f80fd5b80633cbc795b116101735780637843298b116101435780637843298b146103c257806379e2cf97146103e157806381b1c174146103f557806383c43a5514610429575f80fd5b80633cbc795b146103385780633e197043146103705780634b2f336d1461038f5780635ca1e165146103ae575f80fd5b806327aef4e8116101ae57806327aef4e81461026d5780632dfdf0b51461028e578063318aee3d146102b15780633c351e1014610319575f80fd5b806315064c96146101df5780632072f6c51461020d57806322e95f2c14610223578063240ff3781461025a575b5f80fd5b3480156101ea575f80fd5b506068546101f89060ff1681565b60405190151581526020015b60405180910390f35b348015610218575f80fd5b50610221610631565b005b34801561022e575f80fd5b5061024261023d366004612fb9565b610666565b6040516001600160a01b039091168152602001610204565b610221610268366004613040565b6106d0565b348015610278575f80fd5b50610281610759565b6040516102049190613102565b348015610299575f80fd5b506102a360535481565b604051908152602001610204565b3480156102bc575f80fd5b506102f56102cb36600461311b565b606b6020525f908152604090205463ffffffff81169064010000000090046001600160a01b031682565b6040805163ffffffff90931683526001600160a01b03909116602083015201610204565b348015610324575f80fd5b50606d54610242906001600160a01b031681565b348015610343575f80fd5b50606d5461035b90600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610204565b34801561037b575f80fd5b506102a361038a366004613144565b6107e5565b34801561039a575f80fd5b50606f54610242906001600160a01b031681565b3480156103b9575f80fd5b506102a361088e565b3480156103cd575f80fd5b506102426103dc3660046131be565b61096a565b3480156103ec575f80fd5b50610221610993565b348015610400575f80fd5b5061024261040f366004613204565b606a6020525f90815260409020546001600160a01b031681565b348015610434575f80fd5b506102816109b4565b348015610448575f80fd5b506102a361045736600461322c565b6109d3565b348015610467575f80fd5b50606c54610242906001600160a01b031681565b348015610486575f80fd5b5061024261049536600461332d565b610aa8565b3480156104a5575f80fd5b506102216104b43660046133c3565b610be7565b3480156104c4575f80fd5b5060685461035b90610100900463ffffffff1681565b3480156104e5575f80fd5b5060685461035b90600160c81b900463ffffffff1681565b348015610508575f80fd5b5061028161051736600461311b565b610cc2565b348015610527575f80fd5b506101f8610536366004613441565b610d07565b348015610546575f80fd5b50610221610555366004613472565b610d8f565b610221610568366004613556565b6112c0565b348015610578575f80fd5b50606854610242906501000000000090046001600160a01b031681565b3480156105a0575f80fd5b5061022161172c565b3480156105b4575f80fd5b506102a36105c3366004613204565b60696020525f908152604090205481565b3480156105df575f80fd5b506102216105ee366004613472565b61175f565b3480156105fe575f80fd5b5061022161060d3660046135e6565b611a25565b34801561061d575f80fd5b506101f861062c366004613689565b611d40565b606c546001600160a01b0316331461065c57604051631736745960e31b815260040160405180910390fd5b610664611d57565b565b6040805160e084901b6001600160e01b031916602080830191909152606084901b6bffffffffffffffffffffffff1916602483015282516018818403018152603890920183528151918101919091205f908152606a90915220546001600160a01b03165b92915050565b60685460ff16156106f457604051630bc011ff60e21b815260040160405180910390fd5b341580159061070d5750606f546001600160a01b031615155b15610744576040517f6f625c4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610752858534868686611db2565b5050505050565b606e8054610766906136ce565b80601f0160208091040260200160405190810160405280929190818152602001828054610792906136ce565b80156107dd5780601f106107b4576101008083540402835291602001916107dd565b820191905f5260205f20905b8154815290600101906020018083116107c057829003601f168201915b505050505081565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201526001600160e01b031960e088811b821660218401526bffffffffffffffffffffffff19606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b6053545f90819081805b6020811015610961578083901c6001166001036108f557603381602081106108c2576108c2613706565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350610922565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b604080516020810184905290810183905260600160405160208183030381529060405280519060200120915080806109599061372e565b915050610898565b50919392505050565b5f61098b848461097985611e7c565b61098286611f66565b61049587612047565b949350505050565b605354606854600160c81b900463ffffffff16101561066457610664612114565b60405180611ba00160405280611b668152602001613d80611b66913981565b5f83815b6020811015610a9f57600163ffffffff8516821c81169003610a4257848160208110610a0557610a05613706565b602002013582604051602001610a25929190918252602082015260400190565b604051602081830303815290604052805190602001209150610a8d565b81858260208110610a5557610a55613706565b6020020135604051602001610a74929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b80610a978161372e565b9150506109d7565b50949350505050565b6040516001600160e01b031960e087901b1660208201526bffffffffffffffffffffffff19606086901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b308360405180611ba00160405280611b668152602001613d80611b669139898989604051602001610b3093929190613746565b60408051601f1981840301815290829052610b4e929160200161377e565b60405160208183030381529060405280519060200120604051602001610bc394939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b6bffffffffffffffffffffffff191660018401526015830152603582015260550190565b60408051808303601f19018152919052805160209091012098975050505050505050565b60685460ff1615610c0b57604051630bc011ff60e21b815260040160405180910390fd5b606f546001600160a01b0316610c4d576040517fdde3cda700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f54604051632770a7eb60e21b8152336004820152602481018690526001600160a01b0390911690639dc29fac906044015f604051808303815f87803b158015610c96575f80fd5b505af1158015610ca8573d5f803e3d5ffd5b50505050610cba868686868686611db2565b505050505050565b6060610ccd82611e7c565b610cd683611f66565b610cdf84612047565b604051602001610cf193929190613746565b6040516020818303038152906040529050919050565b6068545f908190610100900463ffffffff16158015610d2c575063ffffffff83166001145b15610d3e575063ffffffff8316610d66565b610d5364010000000063ffffffff85166137ac565b610d639063ffffffff86166137c3565b90505b600881901c5f90815260696020526040902054600160ff9092169190911b908116149392505050565b60685460ff1615610db357604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff8681166101009092041614610de3576040516302caf51760e11b815260040160405180910390fd5b610e168c8c8c8c8c610e115f8e8e8e8e8e8e8e604051610e049291906137d6565b60405180910390206107e5565b6121c2565b6001600160a01b038616610f6057606f546001600160a01b0316610efa575f6001600160a01b03851684825b6040519080825280601f01601f191660200182016040528015610e6c576020820181803683370190505b50604051610e7a91906137e5565b5f6040518083038185875af1925050503d805f8114610eb4576040519150601f19603f3d011682016040523d82523d5f602084013e610eb9565b606091505b5050905080610ef4576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611256565b606f546040516340c10f1960e01b81526001600160a01b03868116600483015260248201869052909116906340c10f19906044015f604051808303815f87803b158015610f45575f80fd5b505af1158015610f57573d5f803e3d5ffd5b50505050611256565b606d546001600160a01b038781169116148015610f8e5750606d5463ffffffff888116600160a01b90920416145b15610fa5575f6001600160a01b0385168482610e42565b60685463ffffffff610100909104811690881603610fd657610fd16001600160a01b0387168585612354565b611256565b6040516001600160e01b031960e089901b1660208201526bffffffffffffffffffffffff19606088901b1660248201525f9060380160408051601f1981840301815291815281516020928301205f818152606a9093529120549091506001600160a01b0316806111f5575f6110808386868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506123d592505050565b6040516340c10f1960e01b81526001600160a01b03898116600483015260248201899052919250908216906340c10f19906044015f604051808303815f87803b1580156110cb575f80fd5b505af11580156110dd573d5f803e3d5ffd5b5050505080606a5f8581526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060405180604001604052808b63ffffffff1681526020018a6001600160a01b0316815250606b5f836001600160a01b03166001600160a01b031681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a8154816001600160a01b0302191690836001600160a01b031602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398a8a8388886040516111e7959493929190613828565b60405180910390a150611253565b6040516340c10f1960e01b81526001600160a01b038781166004830152602482018790528216906340c10f19906044015f604051808303815f87803b15801561123c575f80fd5b505af115801561124e573d5f803e3d5ffd5b505050505b50505b604080518b815263ffffffff891660208201526001600160a01b0388811682840152861660608201526080810185905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a1505050505050505050505050565b60685460ff16156112e457604051630bc011ff60e21b815260040160405180910390fd5b6112ec612468565b60685463ffffffff61010090910481169088160361131d576040516302caf51760e11b815260040160405180910390fd5b5f806060876001600160a01b03881661141957883414611369576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606d54606e80546001600160a01b0383169650600160a01b90920463ffffffff16945090611396906136ce565b80601f01602080910402602001604051908101604052809291908181526020018280546113c2906136ce565b801561140d5780601f106113e45761010080835404028352916020019161140d565b820191905f5260205f20905b8154815290600101906020018083116113f057829003601f168201915b505050505091506116a3565b3415611451576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546001600160a01b03908116908916036114c757604051632770a7eb60e21b8152336004820152602481018a90526001600160a01b03891690639dc29fac906044015f604051808303815f87803b1580156114ac575f80fd5b505af11580156114be573d5f803e3d5ffd5b505050506116a3565b6001600160a01b038089165f908152606b602090815260409182902082518084019093525463ffffffff811683526401000000009004909216918101829052901561157957604051632770a7eb60e21b8152336004820152602481018b90526001600160a01b038a1690639dc29fac906044015f604051808303815f87803b158015611551575f80fd5b505af1158015611563573d5f803e3d5ffd5b5050505080602001519450805f01519350611696565b851561158b5761158b898b89896124c1565b6040516370a0823160e01b81523060048201525f906001600160a01b038b16906370a0823190602401602060405180830381865afa1580156115cf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f39190613860565b905061160a6001600160a01b038b1633308e612860565b6040516370a0823160e01b81523060048201525f906001600160a01b038c16906370a0823190602401602060405180830381865afa15801561164e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116729190613860565b905061167e8282613877565b6068548c9850610100900463ffffffff169650935050505b61169f89610cc2565b9250505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e86886053546040516116e298979695949392919061388a565b60405180910390a16117086117035f85878f8f8789805190602001206107e5565b6128b1565b861561171657611716612114565b5050505061172360018055565b50505050505050565b606c546001600160a01b0316331461175757604051631736745960e31b815260040160405180910390fd5b6106646129b2565b60685460ff161561178357604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff86811661010090920416146117b3576040516302caf51760e11b815260040160405180910390fd5b6117d58c8c8c8c8c610e1160018e8e8e8e8e8e8e604051610e049291906137d6565b606f545f906001600160a01b031661188857846001600160a01b031684888a868660405160240161180994939291906138f3565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b1790525161183e91906137e5565b5f6040518083038185875af1925050503d805f8114611878576040519150601f19603f3d011682016040523d82523d5f602084013e61187d565b606091505b505080915050611983565b606f546040516340c10f1960e01b81526001600160a01b03878116600483015260248201879052909116906340c10f19906044015f604051808303815f87803b1580156118d3575f80fd5b505af11580156118e5573d5f803e3d5ffd5b50505050846001600160a01b03168789858560405160240161190a94939291906138f3565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b1790525161193f91906137e5565b5f604051808303815f865af19150503d805f8114611978576040519150601f19603f3d011682016040523d82523d5f602084013e61197d565b606091505b50909150505b806119ba576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518c815263ffffffff8a1660208201526001600160a01b0389811682840152871660608201526080810186905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a150505050505050505050505050565b5f54610100900460ff1615808015611a4357505f54600160ff909116105b80611a5c5750303b158015611a5c57505f5460ff166001145b611ad35760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f805460ff191660011790558015611af4575f805461ff0019166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8a16027fffffffffffffff0000000000000000000000000000000000000000ffffffffff1617650100000000006001600160a01b038781169190910291909117909155606c805473ffffffffffffffffffffffffffffffffffffffff19168583161790558616611bcf5763ffffffff851615611bca576040517f1a874c1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ceb565b606d805463ffffffff8716600160a01b027fffffffffffffffff0000000000000000000000000000000000000000000000009091166001600160a01b03891617179055606e611c1e8382613970565b50611cbd5f801b6012604051602001611ca991906060808252600d908201527f5772617070656420457468657200000000000000000000000000000000000000608082015260a0602082018190526004908201527f574554480000000000000000000000000000000000000000000000000000000060c082015260ff91909116604082015260e00190565b6040516020818303038152906040526123d5565b606f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03929092169190911790555b611cf3612a22565b8015611723575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b5f81611d4d8686866109d3565b1495945050505050565b60685460ff1615611d7b57604051630bc011ff60e21b815260040160405180910390fd5b6068805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b60685463ffffffff610100909104811690871603611de3576040516302caf51760e11b815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338989898888605354604051611e3799989796959493929190613a2c565b60405180910390a1611e6e6117036001606860019054906101000a900463ffffffff16338a8a8a8989604051610e049291906137d6565b8215610cba57610cba612114565b60408051600481526024810182526020810180516001600160e01b03167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611edb91906137e5565b5f60405180830381855afa9150503d805f8114611f13576040519150601f19603f3d011682016040523d82523d5f602084013e611f18565b606091505b509150915081611f5d576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525061098b565b61098b81612a94565b60408051600481526024810182526020810180516001600160e01b03167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611fc591906137e5565b5f60405180830381855afa9150503d805f8114611ffd576040519150601f19603f3d011682016040523d82523d5f602084013e612002565b606091505b509150915081611f5d576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525061098b565b60408051600481526024810182526020810180516001600160e01b03167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f91829182916001600160a01b038616916120a591906137e5565b5f60405180830381855afa9150503d805f81146120dd576040519150601f19603f3d011682016040523d82523d5f602084013e6120e2565b606091505b50915091508180156120f5575080516020145b61210057601261098b565b8080602001905181019061098b9190613a97565b6053546068805463ffffffff909216600160c81b027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117908190556001600160a01b0365010000000000909104166333d6247d61217561088e565b6040518263ffffffff1660e01b815260040161219391815260200190565b5f604051808303815f87803b1580156121aa575f80fd5b505af11580156121bc573d5f803e3d5ffd5b50505050565b606854604080516020808201879052818301869052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091525f916501000000000090046001600160a01b03169063257b3632906084016020604051808303815f875af1158015612253573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122779190613860565b9050805f036122b1576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80680100000000000000008716156122f5578691506122d3848a8489611d40565b6122f0576040516338105f3b60e21b815260040160405180910390fd5b61233f565b602087901c612305816001613ab2565b9150879250612320612318868c866109d3565b8a8389611d40565b61233d576040516338105f3b60e21b815260040160405180910390fd5b505b6123498282612c64565b505050505050505050565b6040516001600160a01b0383166024820152604481018290526123d09084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612d24565b505050565b5f8060405180611ba00160405280611b668152602001613d80611b6691398360405160200161240592919061377e565b6040516020818303038152906040529050838151602083015ff591506001600160a01b038216612461576040517fbefb092000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5092915050565b6002600154036124ba5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611aca565b6002600155565b5f6124cf6004828486613acf565b6124d891613af6565b90507f2afa5331000000000000000000000000000000000000000000000000000000006001600160e01b03198216016126b2575f80808080808061251f896004818d613acf565b81019061252c9190613b26565b9650965096509650965096509650336001600160a01b0316876001600160a01b03161461256c5760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b03861630146125955760405163750643af60e01b815260040160405180910390fd5b8a85146125ce576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b0389811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180516001600160e01b03167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169161266591906137e5565b5f604051808303815f865af19150503d805f811461269e576040519150601f19603f3d011682016040523d82523d5f602084013e6126a3565b606091505b50505050505050505050610752565b6001600160e01b031981166323f2ebc360e21b146126fc576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f808080808080806127118a6004818e613acf565b81019061271e9190613b75565b97509750975097509750975097509750336001600160a01b0316886001600160a01b0316146127605760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b03871630146127895760405163750643af60e01b815260040160405180910390fd5b604080516001600160a01b038a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180516001600160e01b03166323f2ebc360e21b1790529151918f169161281091906137e5565b5f604051808303815f865af19150503d805f8114612849576040519150601f19603f3d011682016040523d82523d5f602084013e61284e565b606091505b50505050505050505050505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526121bc9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612399565b8060016128c060206002613cd3565b6128ca9190613877565b60535410612904576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60535f81546129139061372e565b918290555090505f5b60208110156129a3578082901c60011660010361294f57826033826020811061294757612947613706565b015550505050565b6033816020811061296257612962613706565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250808061299b9061372e565b91505061291c565b506123d0613cde565b60018055565b60685460ff166129ee576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b5f54610100900460ff16612a8c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401611aca565b610664612e08565b60606040825110612ab357818060200190518101906106ca9190613cf2565b8151602003612c26575f5b602081108015612b055750828181518110612adb57612adb613706565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b15612b1c5780612b148161372e565b915050612abe565b805f03612b5e57505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b5f8167ffffffffffffffff811115612b7857612b78613268565b6040519080825280601f01601f191660200182016040528015612ba2576020820181803683370190505b5090505f5b82811015612c1e57848181518110612bc157612bc1613706565b602001015160f81c60f81b828281518110612bde57612bde613706565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535080612c168161372e565b915050612ba7565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b6068545f90610100900463ffffffff16158015612c87575063ffffffff82166001145b15612c99575063ffffffff8216612cc1565b612cae64010000000063ffffffff84166137ac565b612cbe9063ffffffff85166137c3565b90505b600881901c5f8181526069602052604081208054600160ff861690811b91821892839055929091908183169003611723576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f612d78826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612e729092919063ffffffff16565b8051909150156123d05780806020019051810190612d969190613d64565b6123d05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611aca565b5f54610100900460ff166129ac5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401611aca565b606061098b84845f85855f80866001600160a01b03168587604051612e9791906137e5565b5f6040518083038185875af1925050503d805f8114612ed1576040519150601f19603f3d011682016040523d82523d5f602084013e612ed6565b606091505b5091509150612ee787838387612ef2565b979650505050505050565b60608315612f605782515f03612f59576001600160a01b0385163b612f595760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611aca565b508161098b565b61098b8383815115612f755781518083602001fd5b8060405162461bcd60e51b8152600401611aca9190613102565b803563ffffffff81168114612c5f575f80fd5b6001600160a01b0381168114612fb6575f80fd5b50565b5f8060408385031215612fca575f80fd5b612fd383612f8f565b91506020830135612fe381612fa2565b809150509250929050565b8015158114612fb6575f80fd5b5f8083601f84011261300b575f80fd5b50813567ffffffffffffffff811115613022575f80fd5b602083019150836020828501011115613039575f80fd5b9250929050565b5f805f805f60808688031215613054575f80fd5b61305d86612f8f565b9450602086013561306d81612fa2565b9350604086013561307d81612fee565b9250606086013567ffffffffffffffff811115613098575f80fd5b6130a488828901612ffb565b969995985093965092949392505050565b5f5b838110156130cf5781810151838201526020016130b7565b50505f910152565b5f81518084526130ee8160208601602086016130b5565b601f01601f19169290920160200192915050565b602081525f61311460208301846130d7565b9392505050565b5f6020828403121561312b575f80fd5b813561311481612fa2565b60ff81168114612fb6575f80fd5b5f805f805f805f60e0888a03121561315a575f80fd5b873561316581613136565b965061317360208901612f8f565b9550604088013561318381612fa2565b945061319160608901612f8f565b935060808801356131a181612fa2565b9699959850939692959460a0840135945060c09093013592915050565b5f805f606084860312156131d0575f80fd5b6131d984612f8f565b925060208401356131e981612fa2565b915060408401356131f981612fa2565b809150509250925092565b5f60208284031215613214575f80fd5b5035919050565b8061040081018310156106ca575f80fd5b5f805f610440848603121561323f575f80fd5b83359250613250856020860161321b565b915061325f6104208501612f8f565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156132a5576132a5613268565b604052919050565b5f67ffffffffffffffff8211156132c6576132c6613268565b50601f01601f191660200190565b5f6132e66132e1846132ad565b61327c565b90508281528383830111156132f9575f80fd5b828260208301375f602084830101529392505050565b5f82601f83011261331e575f80fd5b613114838335602085016132d4565b5f805f805f60a08688031215613341575f80fd5b61334a86612f8f565b9450602086013561335a81612fa2565b9350604086013567ffffffffffffffff80821115613376575f80fd5b61338289838a0161330f565b94506060880135915080821115613397575f80fd5b506133a48882890161330f565b92505060808601356133b581613136565b809150509295509295909350565b5f805f805f8060a087890312156133d8575f80fd5b6133e187612f8f565b955060208701356133f181612fa2565b945060408701359350606087013561340881612fee565b9250608087013567ffffffffffffffff811115613423575f80fd5b61342f89828a01612ffb565b979a9699509497509295939492505050565b5f8060408385031215613452575f80fd5b61345b83612f8f565b915061346960208401612f8f565b90509250929050565b5f805f805f805f805f805f806109208d8f03121561348e575f80fd5b6134988e8e61321b565b9b506134a88e6104008f0161321b565b9a506108008d013599506108208d013598506108408d013597506134cf6108608e01612f8f565b96506134df6108808e0135612fa2565b6108808d013595506134f46108a08e01612f8f565b94506135046108c08e0135612fa2565b6108c08d013593506108e08d0135925067ffffffffffffffff6109008e0135111561352d575f80fd5b61353e8e6109008f01358f01612ffb565b81935080925050509295989b509295989b509295989b565b5f805f805f805f60c0888a03121561356c575f80fd5b61357588612f8f565b9650602088013561358581612fa2565b955060408801359450606088013561359c81612fa2565b935060808801356135ac81612fee565b925060a088013567ffffffffffffffff8111156135c7575f80fd5b6135d38a828b01612ffb565b989b979a50959850939692959293505050565b5f805f805f8060c087890312156135fb575f80fd5b61360487612f8f565b9550602087013561361481612fa2565b945061362260408801612f8f565b9350606087013561363281612fa2565b9250608087013561364281612fa2565b915060a087013567ffffffffffffffff81111561365d575f80fd5b8701601f8101891361366d575f80fd5b61367c898235602084016132d4565b9150509295509295509295565b5f805f80610460858703121561369d575f80fd5b843593506136ae866020870161321b565b92506136bd6104208601612f8f565b939692955092936104400135925050565b600181811c908216806136e257607f821691505b60208210810361370057634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f6001820161373f5761373f61371a565b5060010190565b606081525f61375860608301866130d7565b828103602084015261376a81866130d7565b91505060ff83166040830152949350505050565b5f835161378f8184602088016130b5565b8351908301906137a38183602088016130b5565b01949350505050565b80820281158282048414176106ca576106ca61371a565b808201808211156106ca576106ca61371a565b818382375f9101908152919050565b5f82516137f68184602087016130b5565b9190910192915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b63ffffffff861681525f6001600160a01b03808716602084015280861660408401525060806060830152612ee7608083018486613800565b5f60208284031215613870575f80fd5b5051919050565b818103818111156106ca576106ca61371a565b5f61010060ff8b16835263ffffffff808b1660208501526001600160a01b03808b166040860152818a1660608601528089166080860152508660a08501528160c08501526138da828501876130d7565b925080851660e085015250509998505050505050505050565b6001600160a01b038516815263ffffffff84166020820152606060408201525f613921606083018486613800565b9695505050505050565b601f8211156123d0575f81815260208120601f850160051c810160208610156139515750805b601f850160051c820191505b81811015610cba5782815560010161395d565b815167ffffffffffffffff81111561398a5761398a613268565b61399e8161399884546136ce565b8461392b565b602080601f8311600181146139d1575f84156139ba5750858301515b5f19600386901b1c1916600185901b178555610cba565b5f85815260208120601f198616915b828110156139ff578886015182559484019460019091019084016139e0565b5085821015613a1c57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f61010060ff8c16835263ffffffff808c1660208501526001600160a01b03808c166040860152818b166060860152808a166080860152508760a08501528160c0850152613a7d8285018789613800565b925080851660e085015250509a9950505050505050505050565b5f60208284031215613aa7575f80fd5b815161311481613136565b63ffffffff8181168382160190808211156124615761246161371a565b5f8085851115613add575f80fd5b83861115613ae9575f80fd5b5050820193919092039150565b6001600160e01b03198135818116916004851015613b1e5780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a031215613b3c575f80fd5b8735613b4781612fa2565b96506020880135613b5781612fa2565b9550604088013594506060880135935060808801356131a181613136565b5f805f805f805f80610100898b031215613b8d575f80fd5b8835613b9881612fa2565b97506020890135613ba881612fa2565b965060408901359550606089013594506080890135613bc681612fee565b935060a0890135613bd681613136565b979a969950949793969295929450505060c08201359160e0013590565b600181815b80851115613c2d57815f1904821115613c1357613c1361371a565b80851615613c2057918102915b93841c9390800290613bf8565b509250929050565b5f82613c43575060016106ca565b81613c4f57505f6106ca565b8160018114613c655760028114613c6f57613c8b565b60019150506106ca565b60ff841115613c8057613c8061371a565b50506001821b6106ca565b5060208310610133831016604e8410600b8410161715613cae575081810a6106ca565b613cb88383613bf3565b805f1904821115613ccb57613ccb61371a565b029392505050565b5f6131148383613c35565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215613d02575f80fd5b815167ffffffffffffffff811115613d18575f80fd5b8201601f81018413613d28575f80fd5b8051613d366132e1826132ad565b818152856020838501011115613d4a575f80fd5b613d5b8260208301602086016130b5565b95945050505050565b5f60208284031215613d74575f80fd5b815161311481612fee56fe6101006040523480156200001257600080fd5b5060405162001b6638038062001b6683398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516116aa620004bc6000396000610237015260008181610307015281816105c001526106a70152600061053a015260008181610379015261050401526116aa6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf1461039b578063dd62ed3e146103ae578063ffa1ad74146103f457600080fd5b8063a457c2d71461034e578063a9059cbb14610361578063cd0d00961461037457600080fd5b806395d89b41116100bd57806395d89b41146102e75780639dc29fac146102ef578063a3c573eb1461030257600080fd5b806370a08231146102915780637ecebe00146102c757600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b610184610430565b60405161019191906113e4565b60405180910390f35b6101ad6101a8366004611479565b6104c2565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad6102043660046114a3565b6104dc565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c1610500565b6101ad610277366004611479565b61055c565b61028f61028a366004611479565b6105a8565b005b6101c161029f3660046114df565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101c16102d53660046114df565b60056020526000908152604090205481565b610184610680565b61028f6102fd366004611479565b61068f565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101ad61035c366004611479565b61075e565b6101ad61036f366004611479565b61082f565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f6103a9366004611501565b61083d565b6101c16103bc366004611574565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043f906115a7565b80601f016020809104026020016040519081016040528092919081815260200182805461046b906115a7565b80156104b85780601f1061048d576101008083540402835291602001916104b8565b820191906000526020600020905b81548152906001019060200180831161049b57829003601f168201915b5050505050905090565b6000336104d0818585610b73565b60019150505b92915050565b6000336104ea858285610d27565b6104f5858585610dfe565b506001949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610537576105324661106d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104d090829086906105a3908790611629565b610b73565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b61067c8282611135565b5050565b60606004805461043f906115a7565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610669565b61067c8282611228565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610669565b6104f58286868403610b73565b6000336104d0818585610dfe565b834211156108cc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866109268361163c565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610991610500565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a55573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ad057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610669565b610b678a8a8a610b73565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610df85781811015610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610669565b610df88484848403610b73565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ea1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610df8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611098610430565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff82166111b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610669565b80600260008282546111c49190611629565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015611381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610d1a565b600060208083528351808285015260005b81811015611411578581018301518582016040015282016113f5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461147457600080fd5b919050565b6000806040838503121561148c57600080fd5b61149583611450565b946020939093013593505050565b6000806000606084860312156114b857600080fd5b6114c184611450565b92506114cf60208501611450565b9150604084013590509250925092565b6000602082840312156114f157600080fd5b6114fa82611450565b9392505050565b600080600080600080600060e0888a03121561151c57600080fd5b61152588611450565b965061153360208901611450565b95506040880135945060608801359350608088013560ff8116811461155757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561158757600080fd5b61159083611450565b915061159e60208401611450565b90509250929050565b600181811c908216806115bb57607f821691505b6020821081036115f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104d6576104d66115fa565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361166d5761166d6115fa565b506001019056fea26469706673582212208d88fee561cff7120d381c345cfc534cef8229a272dc5809d4bbb685ad67141164736f6c63430008110033a2646970667358221220432f6d6b4446edbe1f73c19fd2115454d5c35d8b03b98a74fd46724151d7672264736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} From 0397d9325012c77fb940377c9b71f3cb6d67092f Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 19 Sep 2024 14:50:17 -0700 Subject: [PATCH 012/124] save deployed contract addresses from testnets --- test/L2-BRIDGE-TEST/addresses.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 test/L2-BRIDGE-TEST/addresses.json diff --git a/test/L2-BRIDGE-TEST/addresses.json b/test/L2-BRIDGE-TEST/addresses.json new file mode 100644 index 000000000..56f70e7c1 --- /dev/null +++ b/test/L2-BRIDGE-TEST/addresses.json @@ -0,0 +1,4 @@ +{ + "senderAddress": "0xdC9d716D91ECE21CB5d83B2E8d7b5fd586931dCa", + "receiverAddress": "0x3560C7Fde749d1ca5cf1076Fc0E893AdcA9F3714" +} From df6bb6d98a27b8ca3af3894eaace115cc3fd672c Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 19 Sep 2024 16:45:13 -0700 Subject: [PATCH 013/124] install zkevm-contracts from the newly made package --- package.json | 2 +- yarn.lock | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 47fc01b98..a219e4d46 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "ts-node": "10.9.1", "typechain": "^8.3.2", "typescript": "^5.0.2", - "zkevm-contracts": "../PKG/zkevm-contracts-6.0.0-rc.1-fork.9.tar.gz" + "@zero-tech/zkevm-contracts": "6.0.0-fork-9" }, "dependencies": { "@zero-tech/zdc": "0.1.6", diff --git a/yarn.lock b/yarn.lock index 95e040b17..37251c848 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1935,6 +1935,11 @@ mongodb "^6.3.0" winston "^3.11.0" +"@zero-tech/zkevm-contracts@6.0.0-fork-9": + version "6.0.0-fork-9" + resolved "https://registry.yarnpkg.com/@zero-tech/zkevm-contracts/-/zkevm-contracts-6.0.0-fork-9.tgz#6ef7c889762542562485bf2ba3c6124ea00c0aa2" + integrity sha512-iSBm3wEvzkHAnqJYIWJlvIuBU1rKnnI8+IlqHLvz2r+3Ml228KaSNZi0SG8O1DW/oqNnHnMTDZzKv7NPR9wIrQ== + "@zero-tech/ztoken@2.1.0": version "2.1.0" resolved "https://registry.yarnpkg.com/@zero-tech/ztoken/-/ztoken-2.1.0.tgz#71f50b532c258588ade488644fd75d1b8028a256" @@ -9507,10 +9512,6 @@ yocto-queue@^1.0.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== -zkevm-contracts@../PKG/zkevm-contracts-6.0.0-rc.1-fork.9.tar.gz: - version "3.0.0" - resolved "../PKG/zkevm-contracts-6.0.0-rc.1-fork.9.tar.gz#ea7d8ff20f8654a3c65189b26b7a009345320d10" - zksync-web3@^0.14.3: version "0.14.4" resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.14.4.tgz#0b70a7e1a9d45cc57c0971736079185746d46b1f" From 1694febb39a9b629e227ef951dcb38844fd60399 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 25 Sep 2024 13:26:37 -0700 Subject: [PATCH 014/124] remove zk-evm contracts for now and comment out test bridge contracts code --- contracts/L2-BRIDGE-TEST/BridgeReceiver.sol | 105 ++++++------ .../IPolygonZkEVMBridgeV2Ext.sol | 20 +-- package.json | 5 +- test/L2-BRIDGE-TEST/MultiZNS.test.ts | 157 ++++++++++++++++++ test/L2-BRIDGE-TEST/claim.ts | 14 +- test/L2-BRIDGE-TEST/deploy.ts | 8 +- test/L2-BRIDGE-TEST/send.ts | 8 +- yarn.lock | 5 - 8 files changed, 238 insertions(+), 84 deletions(-) create mode 100644 test/L2-BRIDGE-TEST/MultiZNS.test.ts diff --git a/contracts/L2-BRIDGE-TEST/BridgeReceiver.sol b/contracts/L2-BRIDGE-TEST/BridgeReceiver.sol index 80229deff..8e83e699b 100644 --- a/contracts/L2-BRIDGE-TEST/BridgeReceiver.sol +++ b/contracts/L2-BRIDGE-TEST/BridgeReceiver.sol @@ -1,52 +1,53 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import { IBridgeMessageReceiver } from "zkevm-contracts/contracts/interfaces/IBridgeMessageReceiver.sol"; -import { IPolygonZkEVMBridgeV2Ext } from "./IPolygonZkEVMBridgeV2Ext.sol"; -import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; - - -contract BridgeReceiver is IBridgeMessageReceiver { - event MessageReceived( - address originAddress, - uint32 originNetwork, - string message - ); - - error NotPolygonZkEVMBridge(); - - // Global Exit Root address - IPolygonZkEVMBridgeV2Ext public immutable polygonZkEVMBridge; - - // Current network identifier - uint32 public immutable networkID; - - string public messageState; - - address public senderContract; - - constructor(IPolygonZkEVMBridgeV2Ext bridgeAddress) { - if (address(bridgeAddress) == address(0)) revert ZeroAddressPassed(); - polygonZkEVMBridge = bridgeAddress; - networkID = polygonZkEVMBridge.networkID(); - } - - function onMessageReceived( - address originAddress, - uint32 originNetwork, - bytes memory data - ) external payable override { - // Can only be called by the bridge - // Can only be called by the sender on the other network - // require( - // pingSender == originAddress, - // "PingReceiver::onMessageReceived: Not ping Sender" - // ); - - string memory message = abi.decode(data, (string)); - messageState = message; - senderContract = originAddress; - - emit MessageReceived(originAddress, originNetwork, message); - } -} +//// SPDX-License-Identifier: MIT +//pragma solidity 0.8.26; +// +//import { IBridgeMessageReceiver } from "@zero-tech/zkevm-contracts/contracts/interfaces/IBridgeMessageReceiver.sol"; +//import { PolygonZkEVMBridgeV2 } from "@zero-tech/zkevm-contracts/contracts/v2/PolygonZkEVMBridgeV2.sol"; +//import { IPolygonZkEVMBridgeV2Ext } from "./IPolygonZkEVMBridgeV2Ext.sol"; +//import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; +// +// +//contract BridgeReceiver is IBridgeMessageReceiver { +// event MessageReceived( +// address originAddress, +// uint32 originNetwork, +// string message +// ); +// +// error NotPolygonZkEVMBridge(); +// +// // Global Exit Root address +// IPolygonZkEVMBridgeV2Ext public immutable polygonZkEVMBridge; +// +// // Current network identifier +// uint32 public immutable networkID; +// +// string public messageState; +// +// address public senderContract; +// +// constructor(IPolygonZkEVMBridgeV2Ext bridgeAddress) { +// if (address(bridgeAddress) == address(0)) revert ZeroAddressPassed(); +// polygonZkEVMBridge = bridgeAddress; +// networkID = polygonZkEVMBridge.networkID(); +// } +// +// function onMessageReceived( +// address originAddress, +// uint32 originNetwork, +// bytes memory data +// ) external payable override { +// // Can only be called by the bridge +// // Can only be called by the sender on the other network +// // require( +// // pingSender == originAddress, +// // "PingReceiver::onMessageReceived: Not ping Sender" +// // ); +// +// string memory message = abi.decode(data, (string)); +// messageState = message; +// senderContract = originAddress; +// +// emit MessageReceived(originAddress, originNetwork, message); +// } +//} diff --git a/contracts/L2-BRIDGE-TEST/IPolygonZkEVMBridgeV2Ext.sol b/contracts/L2-BRIDGE-TEST/IPolygonZkEVMBridgeV2Ext.sol index 2b43e0019..bc42db9a6 100644 --- a/contracts/L2-BRIDGE-TEST/IPolygonZkEVMBridgeV2Ext.sol +++ b/contracts/L2-BRIDGE-TEST/IPolygonZkEVMBridgeV2Ext.sol @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: AGPL-3.0 - -pragma solidity ^0.8.20; - -import { IPolygonZkEVMBridgeV2 } from "zkevm-contracts/contracts/v2/interfaces/IPolygonZkEVMBridgeV2.sol"; - - -interface IPolygonZkEVMBridgeV2Ext is IPolygonZkEVMBridgeV2 { - function networkID() external view returns (uint32); -} +//// SPDX-License-Identifier: AGPL-3.0 +// +//pragma solidity ^0.8.20; +// +//import { IPolygonZkEVMBridgeV2 } from "@zero-tech/zkevm-contracts/contracts/v2/interfaces/IPolygonZkEVMBridgeV2.sol"; +// +// +//interface IPolygonZkEVMBridgeV2Ext is IPolygonZkEVMBridgeV2 { +// function networkID() external view returns (uint32); +//} diff --git a/package.json b/package.json index a219e4d46..310805f91 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "run-sepolia": "hardhat run src/deploy/run-campaign.ts --network sepolia", "run-hardhat": "hardhat run src/deploy/run-campaign.ts --network hardhat", "run-meowtestnet": "hardhat run src/deploy/run-campaign.ts --network meowtestnet", - "run-gmp": "hardhat run test/L2-BRIDGE-TEST/claim.ts --network zchaintest" + "run-gmp": "hardhat run test/L2-BRIDGE-TEST/send.ts --network sepolia" }, "pre-commit": [ "lint" @@ -76,8 +76,7 @@ "solidity-docgen": "^0.6.0-beta.36", "ts-node": "10.9.1", "typechain": "^8.3.2", - "typescript": "^5.0.2", - "@zero-tech/zkevm-contracts": "6.0.0-fork-9" + "typescript": "^5.0.2" }, "dependencies": { "@zero-tech/zdc": "0.1.6", diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts new file mode 100644 index 000000000..4eae22419 --- /dev/null +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -0,0 +1,157 @@ +import * as hre from "hardhat"; +import { getConfig } from "../../src/deploy/campaign/environments"; +import { runZnsCampaign } from "../../src/deploy/zns-campaign"; +import { IZNSCampaignConfig, IZNSContracts } from "../../src/deploy/campaign/types"; +import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; +import { registrationWithSetup } from "../helpers/register-setup"; +import { + AccessType, + distrConfigEmpty, + DISTRIBUTION_LOCKED_NOT_EXIST_ERR, + fullDistrConfigEmpty, + NOT_AUTHORIZED_ERR, + NOT_OWNER_OF_ERR, +} from "../helpers"; +import { expect } from "chai"; +import * as ethers from "ethers"; +import { ZNSChainResolver, ZNSChainResolver__factory } from "../../typechain"; + + +describe("MultiZNS", () => { + let zns : IZNSContracts; + + let deployAdmin : SignerWithAddress; + let registryMock : SignerWithAddress; + + let config : IZNSCampaignConfig; + + const chainDomainLabel = "zchain"; + let chainDomainHash : string; + + let chainResolver : ZNSChainResolver; + + before(async () => { + [ deployAdmin, registryMock ] = await hre.ethers.getSigners(); + + config = await getConfig({ + deployer: deployAdmin, + zeroVaultAddress: deployAdmin.address, + }); + + const campaign = await runZnsCampaign({ config }); + + zns = campaign.state.contracts; + + await zns.meowToken.mint(deployAdmin.address, 1000000000000000000000n); + await zns.meowToken.connect(deployAdmin).approve(zns.treasury.target, ethers.MaxUint256); + + // TODO multi: add deploy mission for ChainResolver if decided to leave it! + const chainResFact = new ZNSChainResolver__factory(deployAdmin); + chainResolver = await hre.upgrades.deployProxy( + chainResFact, + [ + zns.accessController.target, + zns.registry.target, + ], + { + kind: "uups", + } + ) as unknown as ZNSChainResolver; + await chainResolver.waitForDeployment(); + }); + + describe("Bridging Single Chain Specific Domain", () => { + it.only("should register a new root domain for a chain regularly", async () => { + chainDomainHash = await registrationWithSetup({ + zns, + user: deployAdmin, + domainLabel: chainDomainLabel, + fullConfig: fullDistrConfigEmpty, + }); + + // should be LOCKED to not allow any subdomains on L1 + const { accessType } = await zns.subRegistrar.distrConfigs(chainDomainHash); + expect(accessType).to.equal(0n); + + // set ChainResolver ?!?!?! + const chainId = 1668201165n; + const chainName = "ZChain"; + const znsRegistryOnChain = registryMock.address; + const auxData = "ZChain Root Domain"; + + await chainResolver.connect(deployAdmin).setChainData( + chainDomainHash, + chainId, + chainName, + znsRegistryOnChain, + auxData + ); + + // transfer Domain Token to ZNSRegistry. It CAN NOT be transfered back! This is a final immutable operation! + await zns.domainToken.connect(deployAdmin).transferFrom( + deployAdmin.address, + zns.registry.target, + BigInt(chainDomainHash) + ); + + // [AS A LAST OPERATION] change owner to ZNSRegistry to signify that a domain is on another network + await zns.registry.connect(deployAdmin).updateDomainOwner(chainDomainHash, zns.registry.target); + + // make sure no domain related functions are available to the domain creator now + await expect( + zns.registry.connect(deployAdmin).updateDomainOwner( + chainDomainHash, + deployAdmin.address + ) + ).to.be.revertedWithCustomError(zns.registry, NOT_AUTHORIZED_ERR); + + await expect( + zns.addressResolver.connect(deployAdmin).setAddress( + chainDomainHash, + deployAdmin.address + ) + ).to.be.revertedWithCustomError(zns.registry, NOT_AUTHORIZED_ERR); + + await expect( + zns.subRegistrar.connect(deployAdmin).setDistributionConfigForDomain( + chainDomainHash, + { + ...distrConfigEmpty, + accessType: AccessType.OPEN, + } + ) + ).to.be.revertedWithCustomError(zns.registry, NOT_AUTHORIZED_ERR); + + // can't Revoke or Reclaim domain + await expect( + zns.rootRegistrar.connect(deployAdmin).revokeDomain(chainDomainHash) + ).to.be.revertedWithCustomError(zns.rootRegistrar, NOT_OWNER_OF_ERR); + + await expect( + zns.rootRegistrar.connect(deployAdmin).reclaimDomain(chainDomainHash) + ).to.be.revertedWithCustomError(zns.rootRegistrar, NOT_OWNER_OF_ERR); + + // make sure no one can register subdomains + await expect( + registrationWithSetup({ + zns, + user: deployAdmin, + parentHash: chainDomainHash, + domainLabel: "test", + fullConfig: fullDistrConfigEmpty, + }) + ).to.be.revertedWithCustomError(zns.subRegistrar, DISTRIBUTION_LOCKED_NOT_EXIST_ERR); + + const record = await zns.registry.getDomainRecord(chainDomainHash); + expect(record.owner).to.equal(zns.registry.target); + expect(record.resolver).to.equal(zns.addressResolver.target); + + // check resolver data + const resolverData = await chainResolver.resolveChainDataStruct(chainDomainHash); + expect(resolverData.chainId).to.equal(chainId); + expect(resolverData.chainName).to.equal(chainName); + expect(resolverData.znsRegistryOnChain).to.equal(znsRegistryOnChain); + expect(resolverData.auxData).to.equal(auxData); + }); + }); +}); diff --git a/test/L2-BRIDGE-TEST/claim.ts b/test/L2-BRIDGE-TEST/claim.ts index 4e1df09e3..47f9b47f0 100644 --- a/test/L2-BRIDGE-TEST/claim.ts +++ b/test/L2-BRIDGE-TEST/claim.ts @@ -16,8 +16,10 @@ const main = async () => { // launch HH script with "--network zchaintest" flag to get this! const [deployerZChain] = await hre.ethers.getSigners(); - const bridgeArt = require("./PolygonZkEVMBridgeV2.json"); - const bridgeContract = new hre.ethers.Contract(zChainTestBridgeAddress, bridgeArt.abi, deployerZChain); + // const bridgeArt = require("./PolygonZkEVMBridgeV2.json"); + // const bridgeContract = new hre.ethers.Contract(zChainTestBridgeAddress, bridgeArt.abi, deployerZChain); + const bridgeFactory = await hre.ethers.getContractFactory("PolygonZkEVMBridgeV2", deployerZChain); + const bridgeContract = bridgeFactory.attach(zChainTestBridgeAddress) as PolygonZkEVMBridgeV2; const axio = axios.create({ baseURL: zChainBridgeApiUrl }); const result = await axio.get( @@ -75,7 +77,7 @@ const main = async () => { console.log("Claim process completed successfully!"); }; -main().catch(error => { - console.error(error); - process.exit(1); -}); +// main().catch(error => { +// console.error(error); +// process.exit(1); +// }); diff --git a/test/L2-BRIDGE-TEST/deploy.ts b/test/L2-BRIDGE-TEST/deploy.ts index eb3fc8682..3893b2e51 100644 --- a/test/L2-BRIDGE-TEST/deploy.ts +++ b/test/L2-BRIDGE-TEST/deploy.ts @@ -46,7 +46,7 @@ const main = async () => { fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, "\t")); }; -main().catch(error => { - console.error(error); - process.exit(1); -}); +// main().catch(error => { +// console.error(error); +// process.exit(1); +// }); diff --git a/test/L2-BRIDGE-TEST/send.ts b/test/L2-BRIDGE-TEST/send.ts index 4b602e3ca..663263fd1 100644 --- a/test/L2-BRIDGE-TEST/send.ts +++ b/test/L2-BRIDGE-TEST/send.ts @@ -31,7 +31,7 @@ const main = async () => { console.log("Message bridged successfully!"); }; -main().catch(error => { - console.error(error); - process.exit(1); -}); +// main().catch(error => { +// console.error(error); +// process.exit(1); +// }); diff --git a/yarn.lock b/yarn.lock index 37251c848..21f4480d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1935,11 +1935,6 @@ mongodb "^6.3.0" winston "^3.11.0" -"@zero-tech/zkevm-contracts@6.0.0-fork-9": - version "6.0.0-fork-9" - resolved "https://registry.yarnpkg.com/@zero-tech/zkevm-contracts/-/zkevm-contracts-6.0.0-fork-9.tgz#6ef7c889762542562485bf2ba3c6124ea00c0aa2" - integrity sha512-iSBm3wEvzkHAnqJYIWJlvIuBU1rKnnI8+IlqHLvz2r+3Ml228KaSNZi0SG8O1DW/oqNnHnMTDZzKv7NPR9wIrQ== - "@zero-tech/ztoken@2.1.0": version "2.1.0" resolved "https://registry.yarnpkg.com/@zero-tech/ztoken/-/ztoken-2.1.0.tgz#71f50b532c258588ade488644fd75d1b8028a256" From 6ac127acf5203370ac5ab1eec5277fa00d0f3e92 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 25 Sep 2024 13:27:22 -0700 Subject: [PATCH 015/124] comment out BridgeSender code temporarily --- contracts/L2-BRIDGE-TEST/BridgeSender.sol | 82 +++++++++++------------ 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/contracts/L2-BRIDGE-TEST/BridgeSender.sol b/contracts/L2-BRIDGE-TEST/BridgeSender.sol index 296f8efab..843e2314c 100644 --- a/contracts/L2-BRIDGE-TEST/BridgeSender.sol +++ b/contracts/L2-BRIDGE-TEST/BridgeSender.sol @@ -1,41 +1,41 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import { IPolygonZkEVMBridgeV2 } from "zkevm-contracts/contracts/v2/interfaces/IPolygonZkEVMBridgeV2.sol"; -import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; - - -contract BridgeSender { - - event MessageBridged( - uint32 destinationNetwork, - address destinationAddress, - string message - ); - - // Global Exit Root address - IPolygonZkEVMBridgeV2 public immutable polygonZkEVMBridge; - - constructor(IPolygonZkEVMBridgeV2 bridgeAddress) { - if (address(bridgeAddress) == address(0)) revert ZeroAddressPassed(); - polygonZkEVMBridge = bridgeAddress; - } - - function bridgeMessage( - uint32 destinationNetwork, - address destinationAddress, - bool forceUpdateGlobalExitRoot, - string memory message - ) external { - bytes memory encodedMsg = abi.encode(message); - - polygonZkEVMBridge.bridgeMessage( - destinationNetwork, - destinationAddress, - forceUpdateGlobalExitRoot, - encodedMsg - ); - - emit MessageBridged(destinationNetwork, destinationAddress, message); - } -} +//// SPDX-License-Identifier: MIT +//pragma solidity 0.8.26; +// +//import { IPolygonZkEVMBridgeV2 } from "@zero-tech/zkevm-contracts/contracts/v2/interfaces/IPolygonZkEVMBridgeV2.sol"; +//import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; +// +// +//contract BridgeSender { +// +// event MessageBridged( +// uint32 destinationNetwork, +// address destinationAddress, +// string message +// ); +// +// // Global Exit Root address +// IPolygonZkEVMBridgeV2 public immutable polygonZkEVMBridge; +// +// constructor(IPolygonZkEVMBridgeV2 bridgeAddress) { +// if (address(bridgeAddress) == address(0)) revert ZeroAddressPassed(); +// polygonZkEVMBridge = bridgeAddress; +// } +// +// function bridgeMessage( +// uint32 destinationNetwork, +// address destinationAddress, +// bool forceUpdateGlobalExitRoot, +// string memory message +// ) external { +// bytes memory encodedMsg = abi.encode(message); +// +// polygonZkEVMBridge.bridgeMessage( +// destinationNetwork, +// destinationAddress, +// forceUpdateGlobalExitRoot, +// encodedMsg +// ); +// +// emit MessageBridged(destinationNetwork, destinationAddress, message); +// } +//} From bb42ff1067e6451a15aa47a6f5a236cd0efc4886 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 25 Sep 2024 13:27:40 -0700 Subject: [PATCH 016/124] add ChainResolver prototype --- contracts/resolver/IZNSChainResolver.sol | 46 ++++++++++++ contracts/resolver/ZNSChainResolver.sol | 95 ++++++++++++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 contracts/resolver/IZNSChainResolver.sol create mode 100644 contracts/resolver/ZNSChainResolver.sol diff --git a/contracts/resolver/IZNSChainResolver.sol b/contracts/resolver/IZNSChainResolver.sol new file mode 100644 index 000000000..383b8fbef --- /dev/null +++ b/contracts/resolver/IZNSChainResolver.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + + +interface IZNSChainResolver { + event ChainDataSet( + bytes32 indexed domainHash, + uint32 chainID, + string chainName, + address znsRegistryOnChain, + string auxData + ); + + struct ChainData { + uint32 chainId; + string chainName; + address znsRegistryOnChain; + string auxData; + } + + function initialize(address accessController_, address registry_) external; + + function resolveChainData( + bytes32 domainHash + ) external view returns (uint32, string memory, address, string memory); + + function resolveChainDataStruct( + bytes32 domainHash + ) external view returns (ChainData memory); + + function setChainData( + bytes32 domainHash, + uint32 chainID, + string memory chainName, + address znsRegistryOnChain, + string memory auxData + ) external; + + function supportsInterface( + bytes4 interfaceId + ) external view returns (bool); + + function getInterfaceId() external pure returns (bytes4); + + function setRegistry(address _registry) external; +} diff --git a/contracts/resolver/ZNSChainResolver.sol b/contracts/resolver/ZNSChainResolver.sol new file mode 100644 index 000000000..2e5f6af6d --- /dev/null +++ b/contracts/resolver/ZNSChainResolver.sol @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; +import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import { IZNSStringResolver } from "./IZNSStringResolver.sol"; +import { AAccessControlled } from "../access/AAccessControlled.sol"; +import { ARegistryWired } from "../registry/ARegistryWired.sol"; +import { NotAuthorizedForDomain } from "../utils/CommonErrors.sol"; +import { IZNSChainResolver } from "./IZNSChainResolver.sol"; + + +contract ZNSChainResolver is + UUPSUpgradeable, + AAccessControlled, + ARegistryWired, + ERC165, + IZNSChainResolver { + + mapping(bytes32 => ChainData) internal chainData; + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + function initialize(address accessController_, address registry_) external override initializer { + _setAccessController(accessController_); + setRegistry(registry_); + } + + function resolveChainData( + bytes32 domainHash + ) external view override returns (uint32, string memory, address, string memory) { + ChainData memory data = chainData[domainHash]; + return (data.chainID, data.chainName, data.znsRegistryOnChain, data.auxData); + } + + function resolveChainDataStruct( + bytes32 domainHash + ) external view override returns (ChainData memory) { + return chainData[domainHash]; + } + + function setChainData( + bytes32 domainHash, + uint32 chainID, + string memory chainName, + address znsRegistryOnChain, + string memory auxData + ) external override { + if ( + !registry.isOwnerOrOperator(domainHash, msg.sender) + ) revert NotAuthorizedForDomain(msg.sender, domainHash); + + chainData[domainHash] = ChainData( + chainID, + chainName, + znsRegistryOnChain, + auxData + ); + + emit ChainDataSet( + domainHash, + chainID, + chainName, + znsRegistryOnChain, + auxData + ); + } + + function supportsInterface( + bytes4 interfaceId + ) public view virtual override(ERC165, IZNSChainResolver) returns (bool) { + return + interfaceId == getInterfaceId() || + super.supportsInterface(interfaceId); + } + + /** + * @dev Exposes IZNSAddressResolver interfaceId + */ + function getInterfaceId() public pure override returns (bytes4) { + return type(IZNSChainResolver).interfaceId; + } + + function setRegistry(address _registry) public override(ARegistryWired, IZNSChainResolver) onlyAdmin { + _setRegistry(_registry); + } + + // solhint-disable-next-line no-unused-vars + function _authorizeUpgrade(address newImplementation) internal view override { + accessController.checkGovernor(msg.sender); + } +} From 14ae190f53c49c254787f88512d2a27272f81ca4 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 25 Sep 2024 13:27:53 -0700 Subject: [PATCH 017/124] small type fix for test helpers --- test/helpers/register-setup.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/helpers/register-setup.ts b/test/helpers/register-setup.ts index 879eb676b..ba8342943 100644 --- a/test/helpers/register-setup.ts +++ b/test/helpers/register-setup.ts @@ -53,7 +53,7 @@ export const approveForParent = async ({ user, domainLabel, } : { - zns : IZNSContractsLocal; + zns : IZNSContractsLocal | IZNSContracts; parentHash : string; user : SignerWithAddress; domainLabel : string; @@ -92,7 +92,7 @@ export const defaultSubdomainRegistration = async ({ distrConfig, } : { user : SignerWithAddress; - zns : IZNSContractsLocal; + zns : IZNSContractsLocal | IZNSContracts; parentHash : string; subdomainLabel : string; domainContent ?: string; @@ -126,7 +126,7 @@ export const registrationWithSetup = async ({ fullConfig = fullDistrConfigEmpty, setConfigs = true, } : { - zns : IZNSContractsLocal; + zns : IZNSContractsLocal | IZNSContracts; user : SignerWithAddress; parentHash ?: string; domainLabel : string; From 6dce79b6590e45f9bf81b4bd95aea553f4ff404a Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 26 Sep 2024 12:58:24 -0700 Subject: [PATCH 018/124] add chainRootHash concept to zns contract code --- contracts/price/ZNSCurvePricer.sol | 6 +++--- contracts/registrar/IZNSRootRegistrar.sol | 4 ++-- contracts/registrar/ZNSRootRegistrar.sol | 18 +++++++++++++----- contracts/registry/IZNSRegistry.sol | 4 +++- contracts/registry/ZNSRegistry.sol | 15 +++++++++++---- contracts/resolver/ZNSChainResolver.sol | 2 +- contracts/treasury/ZNSTreasury.sol | 10 +++++----- 7 files changed, 38 insertions(+), 21 deletions(-) diff --git a/contracts/price/ZNSCurvePricer.sol b/contracts/price/ZNSCurvePricer.sol index 3524261ef..c735ae154 100644 --- a/contracts/price/ZNSCurvePricer.sol +++ b/contracts/price/ZNSCurvePricer.sol @@ -26,7 +26,7 @@ contract ZNSCurvePricer is AAccessControlled, ARegistryWired, UUPSUpgradeable, I /** * @notice Mapping of domainHash to the price config for that domain set by the parent domain owner. - * @dev Zero, for pricing root domains, uses this mapping as well under 0x0 hash. + * @dev Zero, for pricing root domains, uses this mapping as well under CHAIN_ROOT_HASH hash. */ mapping(bytes32 domainHash => CurvePriceConfig config) public priceConfigs; @@ -37,7 +37,7 @@ contract ZNSCurvePricer is AAccessControlled, ARegistryWired, UUPSUpgradeable, I /** * @notice Proxy initializer to set the initial state of the contract after deployment. - * Only Owner of the 0x0 hash (Zero owned address) can call this function. + * Only Owner of the CHAIN_ROOT_HASH hash (Zero owned address) can call this function. * @dev > Note the for PriceConfig we set each value individually and calling * 2 important functions that validate all of the config's values against the formula: * - `setPrecisionMultiplier()` to validate precision multiplier @@ -54,7 +54,7 @@ contract ZNSCurvePricer is AAccessControlled, ARegistryWired, UUPSUpgradeable, I _setAccessController(accessController_); _setRegistry(registry_); - setPriceConfig(0x0, zeroPriceConfig_); + setPriceConfig(registry.CHAIN_ROOT_HASH(), zeroPriceConfig_); } /** diff --git a/contracts/registrar/IZNSRootRegistrar.sol b/contracts/registrar/IZNSRootRegistrar.sol index b98da35ce..8515f509f 100644 --- a/contracts/registrar/IZNSRootRegistrar.sol +++ b/contracts/registrar/IZNSRootRegistrar.sol @@ -6,8 +6,8 @@ import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; /** - * @notice Stake fee is 0x0 for anything other than subdomain under a parent with Stake Payment - * parent hash will be 0x0 for root domain + * @notice Stake fee is 0 for anything other than subdomain under a parent with Stake Payment + * parent hash will be registry.CHAIN_ROOT_HASH for root domain */ struct CoreRegisterArgs { bytes32 parentHash; diff --git a/contracts/registrar/ZNSRootRegistrar.sol b/contracts/registrar/ZNSRootRegistrar.sol index 5cb841e91..ef2acd651 100644 --- a/contracts/registrar/ZNSRootRegistrar.sol +++ b/contracts/registrar/ZNSRootRegistrar.sol @@ -99,17 +99,25 @@ contract ZNSRootRegistrar is name.validate(); // Create hash for given domain name - bytes32 domainHash = keccak256(bytes(name)); + bytes32 chainRoot = registry.CHAIN_ROOT_HASH(); + bytes32 domainHash = chainRoot == bytes32(0) + ? keccak256(bytes(name)) + : keccak256( + abi.encodePacked( + chainRoot, + keccak256(bytes(name)) + ) + ); if (registry.exists(domainHash)) revert DomainAlreadyExists(domainHash); // Get price for the domain - uint256 domainPrice = rootPricer.getPrice(0x0, name, true); + uint256 domainPrice = rootPricer.getPrice(chainRoot, name, true); _coreRegister( CoreRegisterArgs( - bytes32(0), + chainRoot, domainHash, msg.sender, domainAddress, @@ -211,7 +219,7 @@ contract ZNSRootRegistrar is */ function _processPayment(CoreRegisterArgs memory args) internal { // args.stakeFee can be 0 - uint256 protocolFee = rootPricer.getFeeForPrice(0x0, args.price + args.stakeFee); + uint256 protocolFee = rootPricer.getFeeForPrice(registry.CHAIN_ROOT_HASH(), args.price + args.stakeFee); if (args.isStakePayment) { // for all root domains or subdomains with stake payment treasury.stakeForDomain( @@ -278,7 +286,7 @@ contract ZNSRootRegistrar is bool stakeRefunded = false; // send the stake back if it exists if (stakedAmount > 0) { - uint256 protocolFee = rootPricer.getFeeForPrice(0x0, stakedAmount); + uint256 protocolFee = rootPricer.getFeeForPrice(registry.CHAIN_ROOT_HASH(), stakedAmount); treasury.unstakeForDomain(domainHash, owner, protocolFee); stakeRefunded = true; diff --git a/contracts/registry/IZNSRegistry.sol b/contracts/registry/IZNSRegistry.sol index f73a74ff6..b312a38c4 100644 --- a/contracts/registry/IZNSRegistry.sol +++ b/contracts/registry/IZNSRegistry.sol @@ -81,7 +81,9 @@ interface IZNSRegistry { string resolverType ); - function initialize(address accessController) external; + function initialize(address accessController, bytes32 chainRootHash_) external; + + function CHAIN_ROOT_HASH() external view returns (bytes32); function exists(bytes32 domainHash) external view returns (bool); diff --git a/contracts/registry/ZNSRegistry.sol b/contracts/registry/ZNSRegistry.sol index 72d2376f7..5ffa9c859 100644 --- a/contracts/registry/ZNSRegistry.sol +++ b/contracts/registry/ZNSRegistry.sol @@ -14,6 +14,9 @@ import { ZeroAddressPassed, NotAuthorizedForDomain } from "../utils/CommonErrors */ contract ZNSRegistry is AAccessControlled, UUPSUpgradeable, IZNSRegistry { + // TODO multi: add natspec here to explain what this is + bytes32 public CHAIN_ROOT_HASH; + // Mapping of all approved resolvers mapping(string resolverType => address resolver) internal resolvers; @@ -60,12 +63,16 @@ contract ZNSRegistry is AAccessControlled, UUPSUpgradeable, IZNSRegistry { /** * @notice Initializer for the `ZNSRegistry` proxy. * @param accessController_ The address of the `ZNSAccessController` contract - * @dev ! The owner of the 0x0 hash should be a multisig ideally, but EOA can be used to deploy ! - * > Admin account deploying the contract will be the owner of the 0x0 hash ! + * @dev ! The owner of the Chain Root Hash hash should be a multisig ideally, but EOA can be used to deploy ! + * > Admin account deploying the contract will be the owner of the CHAIN_ROOT_HASH hash ! */ - function initialize(address accessController_) external override initializer { - records[0x0].owner = msg.sender; + function initialize( + address accessController_, + bytes32 chainRootHash_ + ) external override initializer { + records[chainRootHash_].owner = msg.sender; _setAccessController(accessController_); + CHAIN_ROOT_HASH = chainRootHash_; } /** diff --git a/contracts/resolver/ZNSChainResolver.sol b/contracts/resolver/ZNSChainResolver.sol index 2e5f6af6d..c67bbe6f3 100644 --- a/contracts/resolver/ZNSChainResolver.sol +++ b/contracts/resolver/ZNSChainResolver.sol @@ -33,7 +33,7 @@ contract ZNSChainResolver is bytes32 domainHash ) external view override returns (uint32, string memory, address, string memory) { ChainData memory data = chainData[domainHash]; - return (data.chainID, data.chainName, data.znsRegistryOnChain, data.auxData); + return (data.chainId, data.chainName, data.znsRegistryOnChain, data.auxData); } function resolveChainDataStruct( diff --git a/contracts/treasury/ZNSTreasury.sol b/contracts/treasury/ZNSTreasury.sol index 51bb39bdc..81be3dc8f 100644 --- a/contracts/treasury/ZNSTreasury.sol +++ b/contracts/treasury/ZNSTreasury.sol @@ -24,7 +24,7 @@ contract ZNSTreasury is AAccessControlled, ARegistryWired, UUPSUpgradeable, IZNS /** * @notice The mapping that stores the payment configurations for each domain. - * Zero's own configs for root domains is stored under 0x0 hash. + * Zero's own configs for root domains is stored under chain root hash. */ mapping(bytes32 domainHash => PaymentConfig config) public override paymentConfigs; @@ -66,7 +66,7 @@ contract ZNSTreasury is AAccessControlled, ARegistryWired, UUPSUpgradeable, IZNS if (paymentToken_ == address(0) || zeroVault_ == address(0)) revert ZeroAddressPassed(); - paymentConfigs[0x0] = PaymentConfig({ + paymentConfigs[registry.CHAIN_ROOT_HASH()] = PaymentConfig({ token: IERC20(paymentToken_), beneficiary : zeroVault_ }); @@ -109,7 +109,7 @@ contract ZNSTreasury is AAccessControlled, ARegistryWired, UUPSUpgradeable, IZNS // Transfer registration fee to the Zero Vault from this address parentConfig.token.safeTransfer( - paymentConfigs[0x0].beneficiary, + paymentConfigs[registry.CHAIN_ROOT_HASH()].beneficiary, protocolFee ); @@ -162,7 +162,7 @@ contract ZNSTreasury is AAccessControlled, ARegistryWired, UUPSUpgradeable, IZNS if (protocolFee > 0) { stakeData.token.safeTransferFrom( owner, - paymentConfigs[0x0].beneficiary, + paymentConfigs[registry.CHAIN_ROOT_HASH()].beneficiary, protocolFee ); } @@ -212,7 +212,7 @@ contract ZNSTreasury is AAccessControlled, ARegistryWired, UUPSUpgradeable, IZNS // Transfer registration fee to the Zero Vault from payer parentConfig.token.safeTransferFrom( payer, - paymentConfigs[0x0].beneficiary, + paymentConfigs[registry.CHAIN_ROOT_HASH()].beneficiary, protocolFee ); From 33976c408e48c7ce346f2f90d7a02f7977d2c19d Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 26 Sep 2024 12:58:53 -0700 Subject: [PATCH 019/124] add chainRootHash to ts code and tests --- src/deploy/campaign/environments.ts | 11 ++ src/deploy/campaign/types.ts | 3 +- src/deploy/missions/contracts/registry.ts | 10 +- test/L2-BRIDGE-TEST/MultiZNS.test.ts | 168 +++++++++++++++++----- 4 files changed, 157 insertions(+), 35 deletions(-) diff --git a/src/deploy/campaign/environments.ts b/src/deploy/campaign/environments.ts index eba845c9a..1d1a4ee30 100644 --- a/src/deploy/campaign/environments.ts +++ b/src/deploy/campaign/environments.ts @@ -60,12 +60,14 @@ export const getConfig = async ({ admins, zeroVaultAddress, env, // this is ONLY used for tests! + chainRootHash, // this is ONLY used for tests! should be read from the env variable in prod } : { deployer : SignerWithAddress; governors ?: Array; admins ?: Array; zeroVaultAddress ?: string; env ?: string; + chainRootHash ?: string; }) : Promise> => { // Will throw an error based on any invalid setup, given the `ENV_LEVEL` set const priceConfig = validateEnv(env); @@ -102,11 +104,20 @@ export const getConfig = async ({ // Get admin addresses set through env, if any const adminAddresses = getCustomAddresses("ADMIN_ADDRESSES", deployerAddress, admins); + let chainRootHashFinal; + if (process.env.ENV_LEVEL === "dev") { + chainRootHashFinal = chainRootHash || ethers.ZeroHash; + } else { + requires(!!process.env.CHAIN_ROOT_HASH, "Must provide a Chain Root Hash for 'prod' or 'test' environment"); + chainRootHashFinal = process.env.CHAIN_ROOT_HASH; + } + const config : IZNSCampaignConfig = { env: process.env.ENV_LEVEL!, deployAdmin: deployer, governorAddresses, adminAddresses, + chainRootHash: chainRootHashFinal as string, domainToken: { name: process.env.DOMAIN_TOKEN_NAME ? process.env.DOMAIN_TOKEN_NAME : ZNS_DOMAIN_TOKEN_NAME, symbol: process.env.DOMAIN_TOKEN_SYMBOL ? process.env.DOMAIN_TOKEN_SYMBOL : ZNS_DOMAIN_TOKEN_SYMBOL, diff --git a/src/deploy/campaign/types.ts b/src/deploy/campaign/types.ts index 4c9cce795..1c114d97d 100644 --- a/src/deploy/campaign/types.ts +++ b/src/deploy/campaign/types.ts @@ -24,6 +24,7 @@ export interface IZNSCampaignConfig extends IDeployCampaignConfig; adminAddresses : Array; + chainRootHash : string; domainToken : { name : string; symbol : string; @@ -67,4 +68,4 @@ export interface IZNSContracts extends IContractState { rootRegistrar : ZNSRootRegistrar; fixedPricer : ZNSFixedPricer; subRegistrar : ZNSSubRegistrar; -} \ No newline at end of file +} diff --git a/src/deploy/missions/contracts/registry.ts b/src/deploy/missions/contracts/registry.ts index f9b99f6bd..52c03f5f4 100644 --- a/src/deploy/missions/contracts/registry.ts +++ b/src/deploy/missions/contracts/registry.ts @@ -24,7 +24,13 @@ IZNSContracts instanceName = znsNames.registry.instance; async deployArgs () : Promise { - const { accessController } = this.campaign; - return [ await accessController.getAddress() ]; + const { + accessController, + config: { + chainRootHash, + }, + } = this.campaign; + + return [ await accessController.getAddress(), chainRootHash ]; } } diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts index 4eae22419..7ed432d32 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -8,7 +8,7 @@ import { AccessType, distrConfigEmpty, DISTRIBUTION_LOCKED_NOT_EXIST_ERR, - fullDistrConfigEmpty, + fullDistrConfigEmpty, hashDomainLabel, NOT_AUTHORIZED_ERR, NOT_OWNER_OF_ERR, } from "../helpers"; @@ -17,41 +17,44 @@ import * as ethers from "ethers"; import { ZNSChainResolver, ZNSChainResolver__factory } from "../../typechain"; -describe("MultiZNS", () => { - let zns : IZNSContracts; +describe.only("MultiZNS", () => { + let znsL1 : IZNSContracts; + let znsL2 : IZNSContracts; let deployAdmin : SignerWithAddress; let registryMock : SignerWithAddress; - let config : IZNSCampaignConfig; + let campaignConfig : IZNSCampaignConfig; const chainDomainLabel = "zchain"; let chainDomainHash : string; + let rootDomainL2Hash : string; let chainResolver : ZNSChainResolver; before(async () => { [ deployAdmin, registryMock ] = await hre.ethers.getSigners(); - config = await getConfig({ + campaignConfig = await getConfig({ deployer: deployAdmin, zeroVaultAddress: deployAdmin.address, + chainRootHash: ethers.ZeroHash, }); - const campaign = await runZnsCampaign({ config }); + const campaign = await runZnsCampaign({ config: campaignConfig }); - zns = campaign.state.contracts; + znsL1 = campaign.state.contracts; - await zns.meowToken.mint(deployAdmin.address, 1000000000000000000000n); - await zns.meowToken.connect(deployAdmin).approve(zns.treasury.target, ethers.MaxUint256); + await znsL1.meowToken.mint(deployAdmin.address, 1000000000000000000000n); + await znsL1.meowToken.connect(deployAdmin).approve(znsL1.treasury.target, ethers.MaxUint256); // TODO multi: add deploy mission for ChainResolver if decided to leave it! const chainResFact = new ZNSChainResolver__factory(deployAdmin); chainResolver = await hre.upgrades.deployProxy( chainResFact, [ - zns.accessController.target, - zns.registry.target, + znsL1.accessController.target, + znsL1.registry.target, ], { kind: "uups", @@ -61,16 +64,18 @@ describe("MultiZNS", () => { }); describe("Bridging Single Chain Specific Domain", () => { - it.only("should register a new root domain for a chain regularly", async () => { + it("should register a new root domain for a chain regularly", async () => { chainDomainHash = await registrationWithSetup({ - zns, + zns: znsL1, user: deployAdmin, domainLabel: chainDomainLabel, fullConfig: fullDistrConfigEmpty, }); + expect(chainDomainHash).to.equal(hashDomainLabel(chainDomainLabel)); + // should be LOCKED to not allow any subdomains on L1 - const { accessType } = await zns.subRegistrar.distrConfigs(chainDomainHash); + const { accessType } = await znsL1.subRegistrar.distrConfigs(chainDomainHash); expect(accessType).to.equal(0n); // set ChainResolver ?!?!?! @@ -88,63 +93,63 @@ describe("MultiZNS", () => { ); // transfer Domain Token to ZNSRegistry. It CAN NOT be transfered back! This is a final immutable operation! - await zns.domainToken.connect(deployAdmin).transferFrom( + await znsL1.domainToken.connect(deployAdmin).transferFrom( deployAdmin.address, - zns.registry.target, + znsL1.registry.target, BigInt(chainDomainHash) ); // [AS A LAST OPERATION] change owner to ZNSRegistry to signify that a domain is on another network - await zns.registry.connect(deployAdmin).updateDomainOwner(chainDomainHash, zns.registry.target); + await znsL1.registry.connect(deployAdmin).updateDomainOwner(chainDomainHash, znsL1.registry.target); // make sure no domain related functions are available to the domain creator now await expect( - zns.registry.connect(deployAdmin).updateDomainOwner( + znsL1.registry.connect(deployAdmin).updateDomainOwner( chainDomainHash, deployAdmin.address ) - ).to.be.revertedWithCustomError(zns.registry, NOT_AUTHORIZED_ERR); + ).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR); await expect( - zns.addressResolver.connect(deployAdmin).setAddress( + znsL1.addressResolver.connect(deployAdmin).setAddress( chainDomainHash, deployAdmin.address ) - ).to.be.revertedWithCustomError(zns.registry, NOT_AUTHORIZED_ERR); + ).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR); await expect( - zns.subRegistrar.connect(deployAdmin).setDistributionConfigForDomain( + znsL1.subRegistrar.connect(deployAdmin).setDistributionConfigForDomain( chainDomainHash, { ...distrConfigEmpty, accessType: AccessType.OPEN, } ) - ).to.be.revertedWithCustomError(zns.registry, NOT_AUTHORIZED_ERR); + ).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR); // can't Revoke or Reclaim domain await expect( - zns.rootRegistrar.connect(deployAdmin).revokeDomain(chainDomainHash) - ).to.be.revertedWithCustomError(zns.rootRegistrar, NOT_OWNER_OF_ERR); + znsL1.rootRegistrar.connect(deployAdmin).revokeDomain(chainDomainHash) + ).to.be.revertedWithCustomError(znsL1.rootRegistrar, NOT_OWNER_OF_ERR); await expect( - zns.rootRegistrar.connect(deployAdmin).reclaimDomain(chainDomainHash) - ).to.be.revertedWithCustomError(zns.rootRegistrar, NOT_OWNER_OF_ERR); + znsL1.rootRegistrar.connect(deployAdmin).reclaimDomain(chainDomainHash) + ).to.be.revertedWithCustomError(znsL1.rootRegistrar, NOT_OWNER_OF_ERR); // make sure no one can register subdomains await expect( registrationWithSetup({ - zns, + zns: znsL1, user: deployAdmin, parentHash: chainDomainHash, domainLabel: "test", fullConfig: fullDistrConfigEmpty, }) - ).to.be.revertedWithCustomError(zns.subRegistrar, DISTRIBUTION_LOCKED_NOT_EXIST_ERR); + ).to.be.revertedWithCustomError(znsL1.subRegistrar, DISTRIBUTION_LOCKED_NOT_EXIST_ERR); - const record = await zns.registry.getDomainRecord(chainDomainHash); - expect(record.owner).to.equal(zns.registry.target); - expect(record.resolver).to.equal(zns.addressResolver.target); + const record = await znsL1.registry.getDomainRecord(chainDomainHash); + expect(record.owner).to.equal(znsL1.registry.target); + expect(record.resolver).to.equal(znsL1.addressResolver.target); // check resolver data const resolverData = await chainResolver.resolveChainDataStruct(chainDomainHash); @@ -153,5 +158,104 @@ describe("MultiZNS", () => { expect(resolverData.znsRegistryOnChain).to.equal(znsRegistryOnChain); expect(resolverData.auxData).to.equal(auxData); }); + + it("deploy ZNS L2", async () => { + campaignConfig = { + ...campaignConfig, + chainRootHash: chainDomainHash, + }; + const campaignL2 = await runZnsCampaign({ config: campaignConfig }); + + znsL2 = campaignL2.state.contracts; + + await znsL2.meowToken.mint(deployAdmin.address, 1000000000000000000000n); + await znsL2.meowToken.connect(deployAdmin).approve(znsL2.treasury.target, ethers.MaxUint256); + }); + + it("should set up ZNS L2 with proper domain as root", async () => { + // check that the domain is properly set up + const chainRootHash = await znsL2.registry.CHAIN_ROOT_HASH(); + expect(chainRootHash).to.equal(chainDomainHash); + + // check pricer setup + const distrConfigFromL2 = await znsL2.curvePricer.priceConfigs(chainRootHash); + expect(distrConfigFromL2.maxPrice).to.deep.equal(campaignConfig.rootPriceConfig.maxPrice); + expect(distrConfigFromL2.minPrice).to.deep.equal(campaignConfig.rootPriceConfig.minPrice); + expect(distrConfigFromL2.maxLength).to.equal(campaignConfig.rootPriceConfig.maxLength); + expect(distrConfigFromL2.baseLength).to.equal(campaignConfig.rootPriceConfig.baseLength); + expect(distrConfigFromL2.precisionMultiplier).to.equal(campaignConfig.rootPriceConfig.precisionMultiplier); + expect(distrConfigFromL2.feePercentage).to.equal(campaignConfig.rootPriceConfig.feePercentage); + expect(distrConfigFromL2.isSet).to.equal(true); + + // check treasury setup + const paymentConfigFromL2 = await znsL2.treasury.paymentConfigs(chainRootHash); + expect(paymentConfigFromL2.token).to.equal(znsL2.meowToken.target); + expect(paymentConfigFromL2.beneficiary).to.equal(campaignConfig.zeroVaultAddress); + }); + + it("should register a new root domain on L2", async () => { + const rootDomainL2Label = "wilderworld"; + rootDomainL2Hash = await registrationWithSetup({ + zns: znsL2, + user: deployAdmin, + domainLabel: rootDomainL2Label, + // TODO multi: add a config here to check later in test + fullConfig: fullDistrConfigEmpty, + }); + + // validate it hashed properly + const chainRootHash = await znsL2.registry.CHAIN_ROOT_HASH(); + const abiCoder = new ethers.AbiCoder(); + const encoded = abiCoder.encode( + ["bytes32", "bytes32"], + [chainRootHash, hashDomainLabel(rootDomainL2Label)] + ); + const rootDomainHashRef = ethers.solidityPackedKeccak256( + ["bytes"], + [encoded] + ); + + expect(rootDomainL2Hash).to.equal(rootDomainHashRef); + + // check owner and domain token + const record = await znsL2.registry.getDomainRecord(rootDomainL2Hash); + expect(record.owner).to.equal(deployAdmin.address); + expect(record.resolver).to.equal(znsL2.addressResolver.target); + + const domainTokenOwner = await znsL2.domainToken.ownerOf(BigInt(rootDomainL2Hash)); + expect(domainTokenOwner).to.equal(deployAdmin.address); + }); + + it("should register a subdomain on L2", async () => { + const subDomainLabel = "wheels"; + const subDomainHash = await registrationWithSetup({ + zns: znsL2, + user: deployAdmin, + parentHash: rootDomainL2Hash, + domainLabel: subDomainLabel, + fullConfig: fullDistrConfigEmpty, + }); + + // validate hashing + const abiCoder = new ethers.AbiCoder(); + const encoded = abiCoder.encode( + ["bytes32", "bytes32"], + [rootDomainL2Hash, hashDomainLabel(subDomainLabel)] + ); + const subDomainHashRef = ethers.solidityPackedKeccak256( + ["bytes"], + [encoded] + ); + + expect(subDomainHash).to.equal(subDomainHashRef); + + // check owner and domain token + const record = await znsL2.registry.getDomainRecord(subDomainHash); + expect(record.owner).to.equal(deployAdmin.address); + expect(record.resolver).to.equal(znsL2.addressResolver.target); + + const domainTokenOwner = await znsL2.domainToken.ownerOf(BigInt(subDomainHash)); + expect(domainTokenOwner).to.equal(deployAdmin.address); + }); }); }); From 6db2c2f8b9d6d7ed2285cf6cb2bd019d46be6546 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 26 Sep 2024 12:59:03 -0700 Subject: [PATCH 020/124] comment out networks in hh config --- hardhat.config.ts | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 024c698d3..1007c697b 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -106,7 +106,7 @@ const config : HardhatUserConfig = { url: `${process.env.SEPOLIA_RPC_URL}`, timeout: 10000000, accounts: [ // Comment out for CI, uncomment this when using Sepolia - `${process.env.TESTNET_PRIVATE_KEY_A}`, + // `${process.env.TESTNET_PRIVATE_KEY_A}`, // `${process.env.TESTNET_PRIVATE_KEY_B}`, // `${process.env.TESTNET_PRIVATE_KEY_C}`, // `${process.env.TESTNET_PRIVATE_KEY_D}`, @@ -121,27 +121,27 @@ const config : HardhatUserConfig = { url: `${process.env.DEVNET_RPC_URL}`, chainId: 1, }, - zchaintest: { - url: `${process.env.ZCHAINTEST_RPC_URL}`, - chainId: 1668201165, - accounts: [ - `${process.env.TESTNET_PRIVATE_KEY_A}`, - ], - }, - }, - etherscan: { - apiKey: `${process.env.ETHERSCAN_API_KEY}`, - customChains: [ - { - network: "zchaintest", - chainId: 1668201165, - urls: { - apiURL: "https://zchain-testnet-blockscout.eu-north-2.gateway.fm/api/", - browserURL: "https://zchain-testnet-blockscout.eu-north-2.gateway.fm/", - }, - }, - ], + // zchaintest: { + // url: `${process.env.ZCHAINTEST_RPC_URL}`, + // chainId: 1668201165, + // accounts: [ + // `${process.env.TESTNET_PRIVATE_KEY_A}`, + // ], + // }, }, + // etherscan: { + // apiKey: `${process.env.ETHERSCAN_API_KEY}`, + // customChains: [ + // { + // network: "zchaintest", + // chainId: 1668201165, + // urls: { + // apiURL: "https://zchain-testnet-blockscout.eu-north-2.gateway.fm/api/", + // browserURL: "https://zchain-testnet-blockscout.eu-north-2.gateway.fm/", + // }, + // }, + // ], + // }, sourcify: { // If set to "true", will try to verify the contracts after deployment enabled: false, From 72223adbb6c7edf5dc7b0511b76cf2272582133f Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 26 Sep 2024 14:31:13 -0700 Subject: [PATCH 021/124] update eslint config --- .eslintrc | 5 +- package.json | 2 +- yarn.lock | 152 ++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 123 insertions(+), 36 deletions(-) diff --git a/.eslintrc b/.eslintrc index 67dd7deb3..0fba55420 100644 --- a/.eslintrc +++ b/.eslintrc @@ -9,9 +9,10 @@ "no-console": "off", "no-shadow": "warn", "@typescript-eslint/no-shadow": "warn", - "no-invalid-this": "off" + "no-invalid-this": "off", + "jsdoc/newline-after-description": "off" // "@typescript-eslint/no-unused-vars": "off" // For debugging } } ] -} \ No newline at end of file +} diff --git a/package.json b/package.json index 310805f91..c447c7328 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "@types/chai": "^4.3.11", "@types/mocha": "^9.1.0", "@types/node": "^18.15.11", - "@zero-tech/eslint-config-cpt": "0.2.7", + "@zero-tech/eslint-config-cpt": "0.2.8", "@zero-tech/ztoken": "2.1.0", "chai": "^4.3.10", "eslint": "^8.37.0", diff --git a/yarn.lock b/yarn.lock index 21f4480d8..2078d043d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -139,14 +139,14 @@ resolved "https://registry.yarnpkg.com/@ensdomains/resolver/-/resolver-0.2.4.tgz#c10fe28bf5efbf49bff4666d909aed0265efbc89" integrity sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA== -"@es-joy/jsdoccomment@~0.37.0": - version "0.37.1" - resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.37.1.tgz#fa32a41ba12097452693343e09ad4d26d157aedd" - integrity sha512-5vxWJ1gEkEF0yRd0O+uK6dHJf7adrxwQSX8PuRiPfFSAbNLnY0ZJfXaZucoz14Jj2N11xn2DnlEPwWRpYpvRjg== +"@es-joy/jsdoccomment@~0.48.0": + version "0.48.0" + resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.48.0.tgz#5d9dc1a295cf5d1ed224dffafb4800d5c7206c27" + integrity sha512-G6QUWIcC+KvSwXNsJyDTHvqUdNoAVJPPgkc3+Uk4WBKqZvoXhlvazOgm9aL0HwihJLQf0l+tOE2UFzXBqCqgDw== dependencies: - comment-parser "1.3.1" - esquery "^1.5.0" - jsdoc-type-pratt-parser "~4.0.0" + comment-parser "1.4.1" + esquery "^1.6.0" + jsdoc-type-pratt-parser "~4.1.0" "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" @@ -1301,6 +1301,11 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== +"@pkgr/core@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" + integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== + "@pnpm/config.env-replace@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz#ab29da53df41e8948a00f2433f085f54de8b3a4c" @@ -1911,10 +1916,10 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== -"@zero-tech/eslint-config-cpt@0.2.7": - version "0.2.7" - resolved "https://registry.yarnpkg.com/@zero-tech/eslint-config-cpt/-/eslint-config-cpt-0.2.7.tgz#ec1d94848737863a8c9b9e226fd586b7f8a97346" - integrity sha512-reFmMkcPBjkQgq2hD5FDWfuGIl4dWvKoIdigq3zS375QNLAqQwuY2EPK2RRLQw7Qcw8nTvPFfv4Gwu2fm8yVfQ== +"@zero-tech/eslint-config-cpt@0.2.8": + version "0.2.8" + resolved "https://registry.yarnpkg.com/@zero-tech/eslint-config-cpt/-/eslint-config-cpt-0.2.8.tgz#f4b69187e65f61d519c77755f5ae0963efeb5c9d" + integrity sha512-i5v/tl6Nv23gM8HGXJiiYh5NaL1guARDtka2cx7T6K7g41zd9NZPynHQeGHHtv3zvcFG/hP5J8uS7O3k4DpplA== dependencies: "@typescript-eslint/eslint-plugin" "^5.57.1" "@typescript-eslint/parser" "^5.57.1" @@ -1922,7 +1927,7 @@ eslint-config-airbnb "^19.0.4" eslint-config-airbnb-base "^15.0.0" eslint-plugin-import "^2.27.5" - eslint-plugin-jsdoc "^40.1.1" + eslint-plugin-jsdoc "^50.3.0" eslint-plugin-prefer-arrow "^1.2.3" typescript "^5.0.2" @@ -1983,6 +1988,11 @@ acorn@^8.11.0, acorn@^8.4.1, acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.0.tgz#1627bfa2e058148036133b8d9b51a700663c294c" integrity sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw== +acorn@^8.12.0: + version "8.12.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== + adm-zip@^0.4.16: version "0.4.16" resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" @@ -2172,6 +2182,11 @@ archy@~1.0.0: resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" integrity sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw== +are-docs-informative@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/are-docs-informative/-/are-docs-informative-0.0.2.tgz#387f0e93f5d45280373d387a59d34c96db321963" + integrity sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig== + are-we-there-yet@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz#679df222b278c64f2cdba1175cdc00b0d96164bd" @@ -3030,10 +3045,10 @@ commander@^9.4.0: resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== -comment-parser@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-1.3.1.tgz#3d7ea3adaf9345594aedee6563f422348f165c1b" - integrity sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA== +comment-parser@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/comment-parser/-/comment-parser-1.4.1.tgz#bdafead37961ac079be11eb7ec65c4d021eaf9cc" + integrity sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg== common-ancestor-path@^1.0.1: version "1.0.1" @@ -3283,6 +3298,13 @@ debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.3.6: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + decamelize-keys@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" @@ -3602,6 +3624,11 @@ es-errors@^1.2.1, es-errors@^1.3.0: resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== +es-module-lexer@^1.5.3: + version "1.5.4" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.4.tgz#a8efec3a3da991e60efa6b633a7cad6ab8d26b78" + integrity sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw== + es-object-atoms@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" @@ -3724,18 +3751,22 @@ eslint-plugin-import@^2.27.5: semver "^6.3.1" tsconfig-paths "^3.15.0" -eslint-plugin-jsdoc@^40.1.1: - version "40.3.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-40.3.0.tgz#75a91ab71c41bb797db05a32d9528ce3ab613e90" - integrity sha512-EhCqpzRkxoT2DUB4AnrU0ggBYvTh3bWrLZzQTupq6vSVE6XzNwJVKsOHa41GCoevnsWMBNmoDVjXWGqckjuG1g== +eslint-plugin-jsdoc@^50.3.0: + version "50.3.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.3.0.tgz#2a4d1ac7f45b2b62de42389ba8006fd00b7f08dd" + integrity sha512-P7qDB/RckdKETpBM4CtjHRQ5qXByPmFhRi86sN3E+J+tySchq+RSOGGhI2hDIefmmKFuTi/1ACjqsnDJDDDfzg== dependencies: - "@es-joy/jsdoccomment" "~0.37.0" - comment-parser "1.3.1" - debug "^4.3.4" + "@es-joy/jsdoccomment" "~0.48.0" + are-docs-informative "^0.0.2" + comment-parser "1.4.1" + debug "^4.3.6" escape-string-regexp "^4.0.0" - esquery "^1.5.0" - semver "^7.3.8" - spdx-expression-parse "^3.0.1" + espree "^10.1.0" + esquery "^1.6.0" + parse-imports "^2.1.1" + semver "^7.6.3" + spdx-expression-parse "^4.0.0" + synckit "^0.9.1" eslint-plugin-prefer-arrow@^1.2.3: version "1.2.3" @@ -3763,6 +3794,11 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== +eslint-visitor-keys@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz#e3adc021aa038a2a8e0b2f8b0ce8f66b9483b1fb" + integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw== + eslint@^8.37.0: version "8.57.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" @@ -3807,6 +3843,15 @@ eslint@^8.37.0: strip-ansi "^6.0.1" text-table "^0.2.0" +espree@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.1.0.tgz#8788dae611574c0f070691f522e4116c5a11fc56" + integrity sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA== + dependencies: + acorn "^8.12.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.0.0" + espree@^9.6.0, espree@^9.6.1: version "9.6.1" resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" @@ -3826,13 +3871,20 @@ esprima@^4.0.0, esprima@~4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.2, esquery@^1.5.0: +esquery@^1.4.2: version "1.5.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== dependencies: estraverse "^5.1.0" +esquery@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + dependencies: + estraverse "^5.1.0" + esrecurse@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" @@ -5540,10 +5592,10 @@ jsbn@1.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A== -jsdoc-type-pratt-parser@~4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz#136f0571a99c184d84ec84662c45c29ceff71114" - integrity sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ== +jsdoc-type-pratt-parser@~4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.1.0.tgz#ff6b4a3f339c34a6c188cbf50a16087858d22113" + integrity sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg== json-buffer@3.0.1: version "3.0.1" @@ -6420,7 +6472,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.0.0, ms@^2.1.1, ms@^2.1.2: +ms@2.1.3, ms@^2.0.0, ms@^2.1.1, ms@^2.1.2, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -7145,6 +7197,14 @@ parse-conflict-json@^3.0.0, parse-conflict-json@^3.0.1: just-diff "^6.0.0" just-diff-apply "^5.2.0" +parse-imports@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/parse-imports/-/parse-imports-2.2.1.tgz#0a6e8b5316beb5c9905f50eb2bbb8c64a4805642" + integrity sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ== + dependencies: + es-module-lexer "^1.5.3" + slashes "^3.0.12" + parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" @@ -7933,11 +7993,16 @@ semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.0.0, semver@^7.1.1, semver@^7.1.2, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.2, semver@^7.5.3, semver@^7.6.0: +semver@^7.0.0, semver@^7.1.1, semver@^7.1.2, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.2, semver@^7.5.3, semver@^7.6.0: version "7.6.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== +semver@^7.6.3: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + serialize-javascript@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" @@ -8088,6 +8153,11 @@ slash@^5.1.0: resolved "https://registry.yarnpkg.com/slash/-/slash-5.1.0.tgz#be3adddcdf09ac38eebe8dcdc7b1a57a75b095ce" integrity sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg== +slashes@^3.0.12: + version "3.0.12" + resolved "https://registry.yarnpkg.com/slashes/-/slashes-3.0.12.tgz#3d664c877ad542dc1509eaf2c50f38d483a6435a" + integrity sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA== + slice-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" @@ -8262,6 +8332,14 @@ spdx-expression-parse@^3.0.0, spdx-expression-parse@^3.0.1: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" +spdx-expression-parse@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz#a23af9f3132115465dac215c099303e4ceac5794" + integrity sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + spdx-license-ids@^3.0.0: version "3.0.18" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz#22aa922dcf2f2885a6494a261f2d8b75345d0326" @@ -8569,6 +8647,14 @@ sync-rpc@^1.2.1: dependencies: get-port "^3.1.0" +synckit@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.9.1.tgz#febbfbb6649979450131f64735aa3f6c14575c88" + integrity sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A== + dependencies: + "@pkgr/core" "^0.1.0" + tslib "^2.6.2" + table-layout@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" From 011e7acc3c6c3dd8547fcf47ee2ae2a88a412b4b Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 7 Oct 2024 13:13:56 -0700 Subject: [PATCH 022/124] Revert "add chainRootHash concept to zns contract code" This reverts commit 6dce79b6590e45f9bf81b4bd95aea553f4ff404a. --- contracts/price/ZNSCurvePricer.sol | 6 +++--- contracts/registrar/IZNSRootRegistrar.sol | 4 ++-- contracts/registrar/ZNSRootRegistrar.sol | 18 +++++------------- contracts/registry/IZNSRegistry.sol | 4 +--- contracts/registry/ZNSRegistry.sol | 15 ++++----------- contracts/resolver/ZNSChainResolver.sol | 2 +- contracts/treasury/ZNSTreasury.sol | 10 +++++----- 7 files changed, 21 insertions(+), 38 deletions(-) diff --git a/contracts/price/ZNSCurvePricer.sol b/contracts/price/ZNSCurvePricer.sol index c735ae154..3524261ef 100644 --- a/contracts/price/ZNSCurvePricer.sol +++ b/contracts/price/ZNSCurvePricer.sol @@ -26,7 +26,7 @@ contract ZNSCurvePricer is AAccessControlled, ARegistryWired, UUPSUpgradeable, I /** * @notice Mapping of domainHash to the price config for that domain set by the parent domain owner. - * @dev Zero, for pricing root domains, uses this mapping as well under CHAIN_ROOT_HASH hash. + * @dev Zero, for pricing root domains, uses this mapping as well under 0x0 hash. */ mapping(bytes32 domainHash => CurvePriceConfig config) public priceConfigs; @@ -37,7 +37,7 @@ contract ZNSCurvePricer is AAccessControlled, ARegistryWired, UUPSUpgradeable, I /** * @notice Proxy initializer to set the initial state of the contract after deployment. - * Only Owner of the CHAIN_ROOT_HASH hash (Zero owned address) can call this function. + * Only Owner of the 0x0 hash (Zero owned address) can call this function. * @dev > Note the for PriceConfig we set each value individually and calling * 2 important functions that validate all of the config's values against the formula: * - `setPrecisionMultiplier()` to validate precision multiplier @@ -54,7 +54,7 @@ contract ZNSCurvePricer is AAccessControlled, ARegistryWired, UUPSUpgradeable, I _setAccessController(accessController_); _setRegistry(registry_); - setPriceConfig(registry.CHAIN_ROOT_HASH(), zeroPriceConfig_); + setPriceConfig(0x0, zeroPriceConfig_); } /** diff --git a/contracts/registrar/IZNSRootRegistrar.sol b/contracts/registrar/IZNSRootRegistrar.sol index 8515f509f..b98da35ce 100644 --- a/contracts/registrar/IZNSRootRegistrar.sol +++ b/contracts/registrar/IZNSRootRegistrar.sol @@ -6,8 +6,8 @@ import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; /** - * @notice Stake fee is 0 for anything other than subdomain under a parent with Stake Payment - * parent hash will be registry.CHAIN_ROOT_HASH for root domain + * @notice Stake fee is 0x0 for anything other than subdomain under a parent with Stake Payment + * parent hash will be 0x0 for root domain */ struct CoreRegisterArgs { bytes32 parentHash; diff --git a/contracts/registrar/ZNSRootRegistrar.sol b/contracts/registrar/ZNSRootRegistrar.sol index ef2acd651..5cb841e91 100644 --- a/contracts/registrar/ZNSRootRegistrar.sol +++ b/contracts/registrar/ZNSRootRegistrar.sol @@ -99,25 +99,17 @@ contract ZNSRootRegistrar is name.validate(); // Create hash for given domain name - bytes32 chainRoot = registry.CHAIN_ROOT_HASH(); - bytes32 domainHash = chainRoot == bytes32(0) - ? keccak256(bytes(name)) - : keccak256( - abi.encodePacked( - chainRoot, - keccak256(bytes(name)) - ) - ); + bytes32 domainHash = keccak256(bytes(name)); if (registry.exists(domainHash)) revert DomainAlreadyExists(domainHash); // Get price for the domain - uint256 domainPrice = rootPricer.getPrice(chainRoot, name, true); + uint256 domainPrice = rootPricer.getPrice(0x0, name, true); _coreRegister( CoreRegisterArgs( - chainRoot, + bytes32(0), domainHash, msg.sender, domainAddress, @@ -219,7 +211,7 @@ contract ZNSRootRegistrar is */ function _processPayment(CoreRegisterArgs memory args) internal { // args.stakeFee can be 0 - uint256 protocolFee = rootPricer.getFeeForPrice(registry.CHAIN_ROOT_HASH(), args.price + args.stakeFee); + uint256 protocolFee = rootPricer.getFeeForPrice(0x0, args.price + args.stakeFee); if (args.isStakePayment) { // for all root domains or subdomains with stake payment treasury.stakeForDomain( @@ -286,7 +278,7 @@ contract ZNSRootRegistrar is bool stakeRefunded = false; // send the stake back if it exists if (stakedAmount > 0) { - uint256 protocolFee = rootPricer.getFeeForPrice(registry.CHAIN_ROOT_HASH(), stakedAmount); + uint256 protocolFee = rootPricer.getFeeForPrice(0x0, stakedAmount); treasury.unstakeForDomain(domainHash, owner, protocolFee); stakeRefunded = true; diff --git a/contracts/registry/IZNSRegistry.sol b/contracts/registry/IZNSRegistry.sol index b312a38c4..f73a74ff6 100644 --- a/contracts/registry/IZNSRegistry.sol +++ b/contracts/registry/IZNSRegistry.sol @@ -81,9 +81,7 @@ interface IZNSRegistry { string resolverType ); - function initialize(address accessController, bytes32 chainRootHash_) external; - - function CHAIN_ROOT_HASH() external view returns (bytes32); + function initialize(address accessController) external; function exists(bytes32 domainHash) external view returns (bool); diff --git a/contracts/registry/ZNSRegistry.sol b/contracts/registry/ZNSRegistry.sol index 5ffa9c859..72d2376f7 100644 --- a/contracts/registry/ZNSRegistry.sol +++ b/contracts/registry/ZNSRegistry.sol @@ -14,9 +14,6 @@ import { ZeroAddressPassed, NotAuthorizedForDomain } from "../utils/CommonErrors */ contract ZNSRegistry is AAccessControlled, UUPSUpgradeable, IZNSRegistry { - // TODO multi: add natspec here to explain what this is - bytes32 public CHAIN_ROOT_HASH; - // Mapping of all approved resolvers mapping(string resolverType => address resolver) internal resolvers; @@ -63,16 +60,12 @@ contract ZNSRegistry is AAccessControlled, UUPSUpgradeable, IZNSRegistry { /** * @notice Initializer for the `ZNSRegistry` proxy. * @param accessController_ The address of the `ZNSAccessController` contract - * @dev ! The owner of the Chain Root Hash hash should be a multisig ideally, but EOA can be used to deploy ! - * > Admin account deploying the contract will be the owner of the CHAIN_ROOT_HASH hash ! + * @dev ! The owner of the 0x0 hash should be a multisig ideally, but EOA can be used to deploy ! + * > Admin account deploying the contract will be the owner of the 0x0 hash ! */ - function initialize( - address accessController_, - bytes32 chainRootHash_ - ) external override initializer { - records[chainRootHash_].owner = msg.sender; + function initialize(address accessController_) external override initializer { + records[0x0].owner = msg.sender; _setAccessController(accessController_); - CHAIN_ROOT_HASH = chainRootHash_; } /** diff --git a/contracts/resolver/ZNSChainResolver.sol b/contracts/resolver/ZNSChainResolver.sol index c67bbe6f3..2e5f6af6d 100644 --- a/contracts/resolver/ZNSChainResolver.sol +++ b/contracts/resolver/ZNSChainResolver.sol @@ -33,7 +33,7 @@ contract ZNSChainResolver is bytes32 domainHash ) external view override returns (uint32, string memory, address, string memory) { ChainData memory data = chainData[domainHash]; - return (data.chainId, data.chainName, data.znsRegistryOnChain, data.auxData); + return (data.chainID, data.chainName, data.znsRegistryOnChain, data.auxData); } function resolveChainDataStruct( diff --git a/contracts/treasury/ZNSTreasury.sol b/contracts/treasury/ZNSTreasury.sol index 81be3dc8f..51bb39bdc 100644 --- a/contracts/treasury/ZNSTreasury.sol +++ b/contracts/treasury/ZNSTreasury.sol @@ -24,7 +24,7 @@ contract ZNSTreasury is AAccessControlled, ARegistryWired, UUPSUpgradeable, IZNS /** * @notice The mapping that stores the payment configurations for each domain. - * Zero's own configs for root domains is stored under chain root hash. + * Zero's own configs for root domains is stored under 0x0 hash. */ mapping(bytes32 domainHash => PaymentConfig config) public override paymentConfigs; @@ -66,7 +66,7 @@ contract ZNSTreasury is AAccessControlled, ARegistryWired, UUPSUpgradeable, IZNS if (paymentToken_ == address(0) || zeroVault_ == address(0)) revert ZeroAddressPassed(); - paymentConfigs[registry.CHAIN_ROOT_HASH()] = PaymentConfig({ + paymentConfigs[0x0] = PaymentConfig({ token: IERC20(paymentToken_), beneficiary : zeroVault_ }); @@ -109,7 +109,7 @@ contract ZNSTreasury is AAccessControlled, ARegistryWired, UUPSUpgradeable, IZNS // Transfer registration fee to the Zero Vault from this address parentConfig.token.safeTransfer( - paymentConfigs[registry.CHAIN_ROOT_HASH()].beneficiary, + paymentConfigs[0x0].beneficiary, protocolFee ); @@ -162,7 +162,7 @@ contract ZNSTreasury is AAccessControlled, ARegistryWired, UUPSUpgradeable, IZNS if (protocolFee > 0) { stakeData.token.safeTransferFrom( owner, - paymentConfigs[registry.CHAIN_ROOT_HASH()].beneficiary, + paymentConfigs[0x0].beneficiary, protocolFee ); } @@ -212,7 +212,7 @@ contract ZNSTreasury is AAccessControlled, ARegistryWired, UUPSUpgradeable, IZNS // Transfer registration fee to the Zero Vault from payer parentConfig.token.safeTransferFrom( payer, - paymentConfigs[registry.CHAIN_ROOT_HASH()].beneficiary, + paymentConfigs[0x0].beneficiary, protocolFee ); From 237cf32862d5908ec371c8045872c004f06d36be Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 7 Oct 2024 13:14:05 -0700 Subject: [PATCH 023/124] Revert "add chainRootHash to ts code and tests" This reverts commit 33976c408e48c7ce346f2f90d7a02f7977d2c19d. --- src/deploy/campaign/environments.ts | 11 -- src/deploy/campaign/types.ts | 3 +- src/deploy/missions/contracts/registry.ts | 10 +- test/L2-BRIDGE-TEST/MultiZNS.test.ts | 168 +++++----------------- 4 files changed, 35 insertions(+), 157 deletions(-) diff --git a/src/deploy/campaign/environments.ts b/src/deploy/campaign/environments.ts index 1d1a4ee30..eba845c9a 100644 --- a/src/deploy/campaign/environments.ts +++ b/src/deploy/campaign/environments.ts @@ -60,14 +60,12 @@ export const getConfig = async ({ admins, zeroVaultAddress, env, // this is ONLY used for tests! - chainRootHash, // this is ONLY used for tests! should be read from the env variable in prod } : { deployer : SignerWithAddress; governors ?: Array; admins ?: Array; zeroVaultAddress ?: string; env ?: string; - chainRootHash ?: string; }) : Promise> => { // Will throw an error based on any invalid setup, given the `ENV_LEVEL` set const priceConfig = validateEnv(env); @@ -104,20 +102,11 @@ export const getConfig = async ({ // Get admin addresses set through env, if any const adminAddresses = getCustomAddresses("ADMIN_ADDRESSES", deployerAddress, admins); - let chainRootHashFinal; - if (process.env.ENV_LEVEL === "dev") { - chainRootHashFinal = chainRootHash || ethers.ZeroHash; - } else { - requires(!!process.env.CHAIN_ROOT_HASH, "Must provide a Chain Root Hash for 'prod' or 'test' environment"); - chainRootHashFinal = process.env.CHAIN_ROOT_HASH; - } - const config : IZNSCampaignConfig = { env: process.env.ENV_LEVEL!, deployAdmin: deployer, governorAddresses, adminAddresses, - chainRootHash: chainRootHashFinal as string, domainToken: { name: process.env.DOMAIN_TOKEN_NAME ? process.env.DOMAIN_TOKEN_NAME : ZNS_DOMAIN_TOKEN_NAME, symbol: process.env.DOMAIN_TOKEN_SYMBOL ? process.env.DOMAIN_TOKEN_SYMBOL : ZNS_DOMAIN_TOKEN_SYMBOL, diff --git a/src/deploy/campaign/types.ts b/src/deploy/campaign/types.ts index 1c114d97d..4c9cce795 100644 --- a/src/deploy/campaign/types.ts +++ b/src/deploy/campaign/types.ts @@ -24,7 +24,6 @@ export interface IZNSCampaignConfig extends IDeployCampaignConfig; adminAddresses : Array; - chainRootHash : string; domainToken : { name : string; symbol : string; @@ -68,4 +67,4 @@ export interface IZNSContracts extends IContractState { rootRegistrar : ZNSRootRegistrar; fixedPricer : ZNSFixedPricer; subRegistrar : ZNSSubRegistrar; -} +} \ No newline at end of file diff --git a/src/deploy/missions/contracts/registry.ts b/src/deploy/missions/contracts/registry.ts index 52c03f5f4..f9b99f6bd 100644 --- a/src/deploy/missions/contracts/registry.ts +++ b/src/deploy/missions/contracts/registry.ts @@ -24,13 +24,7 @@ IZNSContracts instanceName = znsNames.registry.instance; async deployArgs () : Promise { - const { - accessController, - config: { - chainRootHash, - }, - } = this.campaign; - - return [ await accessController.getAddress(), chainRootHash ]; + const { accessController } = this.campaign; + return [ await accessController.getAddress() ]; } } diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts index 7ed432d32..4eae22419 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -8,7 +8,7 @@ import { AccessType, distrConfigEmpty, DISTRIBUTION_LOCKED_NOT_EXIST_ERR, - fullDistrConfigEmpty, hashDomainLabel, + fullDistrConfigEmpty, NOT_AUTHORIZED_ERR, NOT_OWNER_OF_ERR, } from "../helpers"; @@ -17,44 +17,41 @@ import * as ethers from "ethers"; import { ZNSChainResolver, ZNSChainResolver__factory } from "../../typechain"; -describe.only("MultiZNS", () => { - let znsL1 : IZNSContracts; - let znsL2 : IZNSContracts; +describe("MultiZNS", () => { + let zns : IZNSContracts; let deployAdmin : SignerWithAddress; let registryMock : SignerWithAddress; - let campaignConfig : IZNSCampaignConfig; + let config : IZNSCampaignConfig; const chainDomainLabel = "zchain"; let chainDomainHash : string; - let rootDomainL2Hash : string; let chainResolver : ZNSChainResolver; before(async () => { [ deployAdmin, registryMock ] = await hre.ethers.getSigners(); - campaignConfig = await getConfig({ + config = await getConfig({ deployer: deployAdmin, zeroVaultAddress: deployAdmin.address, - chainRootHash: ethers.ZeroHash, }); - const campaign = await runZnsCampaign({ config: campaignConfig }); + const campaign = await runZnsCampaign({ config }); - znsL1 = campaign.state.contracts; + zns = campaign.state.contracts; - await znsL1.meowToken.mint(deployAdmin.address, 1000000000000000000000n); - await znsL1.meowToken.connect(deployAdmin).approve(znsL1.treasury.target, ethers.MaxUint256); + await zns.meowToken.mint(deployAdmin.address, 1000000000000000000000n); + await zns.meowToken.connect(deployAdmin).approve(zns.treasury.target, ethers.MaxUint256); // TODO multi: add deploy mission for ChainResolver if decided to leave it! const chainResFact = new ZNSChainResolver__factory(deployAdmin); chainResolver = await hre.upgrades.deployProxy( chainResFact, [ - znsL1.accessController.target, - znsL1.registry.target, + zns.accessController.target, + zns.registry.target, ], { kind: "uups", @@ -64,18 +61,16 @@ describe.only("MultiZNS", () => { }); describe("Bridging Single Chain Specific Domain", () => { - it("should register a new root domain for a chain regularly", async () => { + it.only("should register a new root domain for a chain regularly", async () => { chainDomainHash = await registrationWithSetup({ - zns: znsL1, + zns, user: deployAdmin, domainLabel: chainDomainLabel, fullConfig: fullDistrConfigEmpty, }); - expect(chainDomainHash).to.equal(hashDomainLabel(chainDomainLabel)); - // should be LOCKED to not allow any subdomains on L1 - const { accessType } = await znsL1.subRegistrar.distrConfigs(chainDomainHash); + const { accessType } = await zns.subRegistrar.distrConfigs(chainDomainHash); expect(accessType).to.equal(0n); // set ChainResolver ?!?!?! @@ -93,63 +88,63 @@ describe.only("MultiZNS", () => { ); // transfer Domain Token to ZNSRegistry. It CAN NOT be transfered back! This is a final immutable operation! - await znsL1.domainToken.connect(deployAdmin).transferFrom( + await zns.domainToken.connect(deployAdmin).transferFrom( deployAdmin.address, - znsL1.registry.target, + zns.registry.target, BigInt(chainDomainHash) ); // [AS A LAST OPERATION] change owner to ZNSRegistry to signify that a domain is on another network - await znsL1.registry.connect(deployAdmin).updateDomainOwner(chainDomainHash, znsL1.registry.target); + await zns.registry.connect(deployAdmin).updateDomainOwner(chainDomainHash, zns.registry.target); // make sure no domain related functions are available to the domain creator now await expect( - znsL1.registry.connect(deployAdmin).updateDomainOwner( + zns.registry.connect(deployAdmin).updateDomainOwner( chainDomainHash, deployAdmin.address ) - ).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR); + ).to.be.revertedWithCustomError(zns.registry, NOT_AUTHORIZED_ERR); await expect( - znsL1.addressResolver.connect(deployAdmin).setAddress( + zns.addressResolver.connect(deployAdmin).setAddress( chainDomainHash, deployAdmin.address ) - ).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR); + ).to.be.revertedWithCustomError(zns.registry, NOT_AUTHORIZED_ERR); await expect( - znsL1.subRegistrar.connect(deployAdmin).setDistributionConfigForDomain( + zns.subRegistrar.connect(deployAdmin).setDistributionConfigForDomain( chainDomainHash, { ...distrConfigEmpty, accessType: AccessType.OPEN, } ) - ).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR); + ).to.be.revertedWithCustomError(zns.registry, NOT_AUTHORIZED_ERR); // can't Revoke or Reclaim domain await expect( - znsL1.rootRegistrar.connect(deployAdmin).revokeDomain(chainDomainHash) - ).to.be.revertedWithCustomError(znsL1.rootRegistrar, NOT_OWNER_OF_ERR); + zns.rootRegistrar.connect(deployAdmin).revokeDomain(chainDomainHash) + ).to.be.revertedWithCustomError(zns.rootRegistrar, NOT_OWNER_OF_ERR); await expect( - znsL1.rootRegistrar.connect(deployAdmin).reclaimDomain(chainDomainHash) - ).to.be.revertedWithCustomError(znsL1.rootRegistrar, NOT_OWNER_OF_ERR); + zns.rootRegistrar.connect(deployAdmin).reclaimDomain(chainDomainHash) + ).to.be.revertedWithCustomError(zns.rootRegistrar, NOT_OWNER_OF_ERR); // make sure no one can register subdomains await expect( registrationWithSetup({ - zns: znsL1, + zns, user: deployAdmin, parentHash: chainDomainHash, domainLabel: "test", fullConfig: fullDistrConfigEmpty, }) - ).to.be.revertedWithCustomError(znsL1.subRegistrar, DISTRIBUTION_LOCKED_NOT_EXIST_ERR); + ).to.be.revertedWithCustomError(zns.subRegistrar, DISTRIBUTION_LOCKED_NOT_EXIST_ERR); - const record = await znsL1.registry.getDomainRecord(chainDomainHash); - expect(record.owner).to.equal(znsL1.registry.target); - expect(record.resolver).to.equal(znsL1.addressResolver.target); + const record = await zns.registry.getDomainRecord(chainDomainHash); + expect(record.owner).to.equal(zns.registry.target); + expect(record.resolver).to.equal(zns.addressResolver.target); // check resolver data const resolverData = await chainResolver.resolveChainDataStruct(chainDomainHash); @@ -158,104 +153,5 @@ describe.only("MultiZNS", () => { expect(resolverData.znsRegistryOnChain).to.equal(znsRegistryOnChain); expect(resolverData.auxData).to.equal(auxData); }); - - it("deploy ZNS L2", async () => { - campaignConfig = { - ...campaignConfig, - chainRootHash: chainDomainHash, - }; - const campaignL2 = await runZnsCampaign({ config: campaignConfig }); - - znsL2 = campaignL2.state.contracts; - - await znsL2.meowToken.mint(deployAdmin.address, 1000000000000000000000n); - await znsL2.meowToken.connect(deployAdmin).approve(znsL2.treasury.target, ethers.MaxUint256); - }); - - it("should set up ZNS L2 with proper domain as root", async () => { - // check that the domain is properly set up - const chainRootHash = await znsL2.registry.CHAIN_ROOT_HASH(); - expect(chainRootHash).to.equal(chainDomainHash); - - // check pricer setup - const distrConfigFromL2 = await znsL2.curvePricer.priceConfigs(chainRootHash); - expect(distrConfigFromL2.maxPrice).to.deep.equal(campaignConfig.rootPriceConfig.maxPrice); - expect(distrConfigFromL2.minPrice).to.deep.equal(campaignConfig.rootPriceConfig.minPrice); - expect(distrConfigFromL2.maxLength).to.equal(campaignConfig.rootPriceConfig.maxLength); - expect(distrConfigFromL2.baseLength).to.equal(campaignConfig.rootPriceConfig.baseLength); - expect(distrConfigFromL2.precisionMultiplier).to.equal(campaignConfig.rootPriceConfig.precisionMultiplier); - expect(distrConfigFromL2.feePercentage).to.equal(campaignConfig.rootPriceConfig.feePercentage); - expect(distrConfigFromL2.isSet).to.equal(true); - - // check treasury setup - const paymentConfigFromL2 = await znsL2.treasury.paymentConfigs(chainRootHash); - expect(paymentConfigFromL2.token).to.equal(znsL2.meowToken.target); - expect(paymentConfigFromL2.beneficiary).to.equal(campaignConfig.zeroVaultAddress); - }); - - it("should register a new root domain on L2", async () => { - const rootDomainL2Label = "wilderworld"; - rootDomainL2Hash = await registrationWithSetup({ - zns: znsL2, - user: deployAdmin, - domainLabel: rootDomainL2Label, - // TODO multi: add a config here to check later in test - fullConfig: fullDistrConfigEmpty, - }); - - // validate it hashed properly - const chainRootHash = await znsL2.registry.CHAIN_ROOT_HASH(); - const abiCoder = new ethers.AbiCoder(); - const encoded = abiCoder.encode( - ["bytes32", "bytes32"], - [chainRootHash, hashDomainLabel(rootDomainL2Label)] - ); - const rootDomainHashRef = ethers.solidityPackedKeccak256( - ["bytes"], - [encoded] - ); - - expect(rootDomainL2Hash).to.equal(rootDomainHashRef); - - // check owner and domain token - const record = await znsL2.registry.getDomainRecord(rootDomainL2Hash); - expect(record.owner).to.equal(deployAdmin.address); - expect(record.resolver).to.equal(znsL2.addressResolver.target); - - const domainTokenOwner = await znsL2.domainToken.ownerOf(BigInt(rootDomainL2Hash)); - expect(domainTokenOwner).to.equal(deployAdmin.address); - }); - - it("should register a subdomain on L2", async () => { - const subDomainLabel = "wheels"; - const subDomainHash = await registrationWithSetup({ - zns: znsL2, - user: deployAdmin, - parentHash: rootDomainL2Hash, - domainLabel: subDomainLabel, - fullConfig: fullDistrConfigEmpty, - }); - - // validate hashing - const abiCoder = new ethers.AbiCoder(); - const encoded = abiCoder.encode( - ["bytes32", "bytes32"], - [rootDomainL2Hash, hashDomainLabel(subDomainLabel)] - ); - const subDomainHashRef = ethers.solidityPackedKeccak256( - ["bytes"], - [encoded] - ); - - expect(subDomainHash).to.equal(subDomainHashRef); - - // check owner and domain token - const record = await znsL2.registry.getDomainRecord(subDomainHash); - expect(record.owner).to.equal(deployAdmin.address); - expect(record.resolver).to.equal(znsL2.addressResolver.target); - - const domainTokenOwner = await znsL2.domainToken.ownerOf(BigInt(subDomainHash)); - expect(domainTokenOwner).to.equal(deployAdmin.address); - }); }); }); From 592791415f4a968e00fe9f83470d24ff5149e710 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 7 Oct 2024 15:53:25 -0700 Subject: [PATCH 024/124] move and unblock the extended bridge interface --- contracts/L2-BRIDGE-TEST/IPolygonZkEVMBridgeV2Ext.sol | 10 ---------- .../cross-chain-portals/IPolygonZkEVMBridgeV2Ext.sol | 9 +++++++++ 2 files changed, 9 insertions(+), 10 deletions(-) delete mode 100644 contracts/L2-BRIDGE-TEST/IPolygonZkEVMBridgeV2Ext.sol create mode 100644 contracts/cross-chain-portals/IPolygonZkEVMBridgeV2Ext.sol diff --git a/contracts/L2-BRIDGE-TEST/IPolygonZkEVMBridgeV2Ext.sol b/contracts/L2-BRIDGE-TEST/IPolygonZkEVMBridgeV2Ext.sol deleted file mode 100644 index bc42db9a6..000000000 --- a/contracts/L2-BRIDGE-TEST/IPolygonZkEVMBridgeV2Ext.sol +++ /dev/null @@ -1,10 +0,0 @@ -//// SPDX-License-Identifier: AGPL-3.0 -// -//pragma solidity ^0.8.20; -// -//import { IPolygonZkEVMBridgeV2 } from "@zero-tech/zkevm-contracts/contracts/v2/interfaces/IPolygonZkEVMBridgeV2.sol"; -// -// -//interface IPolygonZkEVMBridgeV2Ext is IPolygonZkEVMBridgeV2 { -// function networkID() external view returns (uint32); -//} diff --git a/contracts/cross-chain-portals/IPolygonZkEVMBridgeV2Ext.sol b/contracts/cross-chain-portals/IPolygonZkEVMBridgeV2Ext.sol new file mode 100644 index 000000000..e07afd03f --- /dev/null +++ b/contracts/cross-chain-portals/IPolygonZkEVMBridgeV2Ext.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { IPolygonZkEVMBridgeV2 } from "@zero-tech/zkevm-contracts/contracts/v2/interfaces/IPolygonZkEVMBridgeV2.sol"; + + +interface IPolygonZkEVMBridgeV2Ext is IPolygonZkEVMBridgeV2 { + function networkID() external view returns (uint32); +} From 4467940643f0c8939ad6bc63ff689cca276cab1b Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 7 Oct 2024 15:53:42 -0700 Subject: [PATCH 025/124] fix chain resolver and add todo --- contracts/resolver/ZNSChainResolver.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/resolver/ZNSChainResolver.sol b/contracts/resolver/ZNSChainResolver.sol index 2e5f6af6d..5ea781786 100644 --- a/contracts/resolver/ZNSChainResolver.sol +++ b/contracts/resolver/ZNSChainResolver.sol @@ -33,7 +33,8 @@ contract ZNSChainResolver is bytes32 domainHash ) external view override returns (uint32, string memory, address, string memory) { ChainData memory data = chainData[domainHash]; - return (data.chainID, data.chainName, data.znsRegistryOnChain, data.auxData); + // TODO multi: should we add RootRegistrar that has all ZNS addresses instead of Registry here ??? + return (data.chainId, data.chainName, data.znsRegistryOnChain, data.auxData); } function resolveChainDataStruct( From fd02224561ad56601c054d4fecc2362e20a34eab Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 7 Oct 2024 15:54:24 -0700 Subject: [PATCH 026/124] create initial PolygonZkEvmPortal contract and struct for bridging --- .../ZNSPolygonZkEvmPortal.sol | 158 ++++++++++++++++++ contracts/types/CrossChainTypes.sol | 12 ++ 2 files changed, 170 insertions(+) create mode 100644 contracts/cross-chain-portals/ZNSPolygonZkEvmPortal.sol create mode 100644 contracts/types/CrossChainTypes.sol diff --git a/contracts/cross-chain-portals/ZNSPolygonZkEvmPortal.sol b/contracts/cross-chain-portals/ZNSPolygonZkEvmPortal.sol new file mode 100644 index 000000000..0e4fcc484 --- /dev/null +++ b/contracts/cross-chain-portals/ZNSPolygonZkEvmPortal.sol @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { IPolygonZkEVMBridgeV2 } from "@zero-tech/zkevm-contracts/contracts/v2/interfaces/IPolygonZkEVMBridgeV2.sol"; +import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { AAccessControlled } from "../access/AAccessControlled.sol"; +import { IDistributionConfig } from "../types/IDistributionConfig.sol"; +import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; +import { IZNSRootRegistrar } from "../registrar/IZNSRootRegistrar.sol"; +import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; +import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; +import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; +import { IZNSPricer } from "../types/IZNSPricer.sol"; +import { RegistrationProof } from "../types/CrossChainTypes.sol"; + + +// TODO multi: should this be ZChainPortal as in chain specific contract? +// it should ideally work with any ZkEVM chain. why not? we should add networkId and other +// chain specific data to as parameters to some functions ??? +contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistributionConfig { + + event DomainBridged( + uint32 indexed destNetworkId, + address destPortalAddress, + bytes32 indexed domainHash, + address indexed domainOwner + ); + + // *--| Cross-chain Data |--* + IPolygonZkEVMBridgeV2 public polygonZkEVMBridge; + // Destination chain (L2) + uint32 public networkIdL2; + // TODO multi: change to interface type (possibly!) + address public znsEthPortalL2; + + // *--| ZNS Data for THIS chain |--* + IZNSRootRegistrar public rootRegistrar; + IZNSSubRegistrar public subRegistrar; + IZNSRegistry public registry; + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + function initialize( + address accessController_, + uint32 networkIdL2_, + IPolygonZkEVMBridgeV2 zkEvmBridge_, + address znsEthPortalL2_, + IZNSRootRegistrar rootRegistrar_, + IZNSSubRegistrar subRegistrar_, + IZNSRegistry registry_ + ) external initializer { + _setAccessController(accessController_); + + if ( + zkEvmBridge_ == address(0) + | znsEthPortalL2_ == address(0) + | address(rootRegistrar_) == address(0) + | address(subRegistrar_) == address(0) + | address(registry_) == address(0) + ) revert ZeroAddressPassed(); + + polygonZkEVMBridge = zkEvmBridge_; + networkIdL2 = networkIdL2_; + znsEthPortalL2 = znsEthPortalL2_; + rootRegistrar = rootRegistrar_; + subRegistrar = subRegistrar_; + registry = registry_; + } + + function registerAndBridgeDomain( + bytes32 parentHash, + string calldata label, + string calldata tokenURI +// bool forceUpdateGlobalExitRoot - do we need to pass this ??? + ) external { + DistributionConfig memory emptyDistrConfig = DistributionConfig( + IZNSPricer(address(0)), + PaymentType.DIRECT, + AccessType.LOCKED + ); + PaymentConfig memory emptyPaymentConfig = PaymentConfig( + IERC20(address(0)), + address(0) + ); + + // Register domain + bytes32 domainHash; + if (parentHash == bytes32(0)) { // 0x0 parent for root domains + domainHash = rootRegistrar.registerRootDomain( + label, + address(0), + tokenURI, + emptyDistrConfig, + emptyPaymentConfig + ); + } else { + domainHash = subRegistrar.registerSubdomain( + parentHash, + label, + address(0), + tokenURI, + emptyDistrConfig, + emptyPaymentConfig + ); + } + + // TODO multi: should we do that or leave this Agent as the owner ??? + // DELETER registry from state if this is NOT used !!! + // set owner as ZNSRegistry on this network + registry.updateDomainOwner(domainHash, address(registry)); + + // TODO multi: ADD write record to ChainResolver here !!! + + // Bridge domain + _bridgeDomain(domainHash, tokenURI); + } + + function _bridgeDomain(bytes32 domainHash, string calldata tokenURI) internal { + // Create data proof for ZNS on L2 + RegistrationProof memory proof = RegistrationProof( + // we are using msg.sender here because the current caller on L1 will be the owner of the bridged L2 domain + msg.sender, + domainHash, + tokenURI + ); + + bytes memory encodedProof = abi.encode(proof); + + polygonZkEVMBridge.bridgeMessage( + // TODO multi: should this be a parameter to the registerAndBridgeDomain function to work on any chain ??? + networkIdL2, + znsEthPortalL2, + // TODO multi: figure out what this is and how to better pass it !!! + true, + encodedProof + ); + + emit DomainBridged( + networkIdL2, + znsEthPortalL2, + domainHash, + msg.sender + ); + } + + /** + * @notice To use UUPS proxy we override this function and revert if `msg.sender` isn't authorized + * @param newImplementation The implementation contract to upgrade to + */ + // solhint-disable-next-line + function _authorizeUpgrade(address newImplementation) internal view override { + accessController.checkGovernor(msg.sender); + } +} diff --git a/contracts/types/CrossChainTypes.sol b/contracts/types/CrossChainTypes.sol new file mode 100644 index 000000000..33cd21eed --- /dev/null +++ b/contracts/types/CrossChainTypes.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + + +// TODO multi: what is the best name for this ??? +struct RegistrationProof { + address domainOwner; + bytes32 domainHash; + bytes32 parentHash; + string label; + string tokenUri; +} From 8797db99dd9ac6fafc4ebe7cabbfb18ad3c60a57 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 7 Oct 2024 15:54:37 -0700 Subject: [PATCH 027/124] add zkevm-contracts package --- package.json | 1 + yarn.lock | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/package.json b/package.json index c447c7328..c4e4574e7 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "@types/node": "^18.15.11", "@zero-tech/eslint-config-cpt": "0.2.8", "@zero-tech/ztoken": "2.1.0", + "@zero-tech/zkevm-contracts": "6.0.0-fork-9", "chai": "^4.3.10", "eslint": "^8.37.0", "ethers": "^6.9.0", diff --git a/yarn.lock b/yarn.lock index 2078d043d..e4c3a6e9b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1940,6 +1940,11 @@ mongodb "^6.3.0" winston "^3.11.0" +"@zero-tech/zkevm-contracts@6.0.0-fork-9": + version "6.0.0-fork-9" + resolved "https://registry.yarnpkg.com/@zero-tech/zkevm-contracts/-/zkevm-contracts-6.0.0-fork-9.tgz#6ef7c889762542562485bf2ba3c6124ea00c0aa2" + integrity sha512-iSBm3wEvzkHAnqJYIWJlvIuBU1rKnnI8+IlqHLvz2r+3Ml228KaSNZi0SG8O1DW/oqNnHnMTDZzKv7NPR9wIrQ== + "@zero-tech/ztoken@2.1.0": version "2.1.0" resolved "https://registry.yarnpkg.com/@zero-tech/ztoken/-/ztoken-2.1.0.tgz#71f50b532c258588ade488644fd75d1b8028a256" From f241b65fa301318823661992c58bbb43f83e61a9 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 8 Oct 2024 15:30:04 -0700 Subject: [PATCH 028/124] create base for EthPortal contract --- .../IPolygonZkEVMBridgeV2Ext.sol | 0 contracts/cross-chain/ZNSEthereumPortal.sol | 158 ++++++++++++++++++ 2 files changed, 158 insertions(+) rename contracts/{cross-chain-portals => cross-chain}/IPolygonZkEVMBridgeV2Ext.sol (100%) create mode 100644 contracts/cross-chain/ZNSEthereumPortal.sol diff --git a/contracts/cross-chain-portals/IPolygonZkEVMBridgeV2Ext.sol b/contracts/cross-chain/IPolygonZkEVMBridgeV2Ext.sol similarity index 100% rename from contracts/cross-chain-portals/IPolygonZkEVMBridgeV2Ext.sol rename to contracts/cross-chain/IPolygonZkEVMBridgeV2Ext.sol diff --git a/contracts/cross-chain/ZNSEthereumPortal.sol b/contracts/cross-chain/ZNSEthereumPortal.sol new file mode 100644 index 000000000..51a29b6f4 --- /dev/null +++ b/contracts/cross-chain/ZNSEthereumPortal.sol @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { AAccessControlled } from "../access/AAccessControlled.sol"; +import { IPolygonZkEVMBridgeV2Ext } from "./IPolygonZkEVMBridgeV2Ext.sol"; +import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; +import { RegistrationProof } from "../types/CrossChainTypes.sol"; +import { IZNSRootRegistrar } from "../registrar/IZNSRootRegistrar.sol"; +import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; +import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; +import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; +import { IDistributionConfig } from "../types/IDistributionConfig.sol"; +import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; +import { IZNSPricer } from "../types/IZNSPricer.sol"; + + +// TODO multi: could this be a better name that implies cross-chain nature ??? +contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IDistributionConfig { + + event DomainClaimed( + uint32 indexed srcNetworkId, + address srcPortalAddress, + bytes32 indexed domainHash, + address indexed domainOwner + ); + event L2PortalAddressSet(address newAddress); + + // TODO multi: can this be better and have smth like NotPolygonBridge ??? + error CalledByInvalidContract(address caller); + error DomainHashDoesNotMatchBridged(bytes32 bridgedHashL1, bytes32 generatedHashL2); + + // TODO multi: check that all state vars are needed and remove redundant ones !!! + // *--| Cross-chain Data |--* + IPolygonZkEVMBridgeV2Ext public polygonZkEVMBridge; + // This chain + uint32 public networkId; + // TODO multi: should this be an Interface Var ??? + address public znsZkEvmPortalL1; + + // *--| ZNS Data for THIS chain |--* + IZNSRootRegistrar public rootRegistrar; + IZNSSubRegistrar public subRegistrar; + IZNSDomainToken public domainToken; + IZNSRegistry public registry; + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + function initialize( + address accessController_, + IPolygonZkEVMBridgeV2Ext zkEvmBridge_, + address znsZkEvmPortalL1_, + IZNSRootRegistrar rootRegistrar_, + IZNSSubRegistrar subRegistrar_, + IZNSDomainToken domainToken_, + IZNSRegistry registry_ + ) external initializer { + _setAccessController(accessController_); + + if ( + address(zkEvmBridge_) == address(0) + || znsZkEvmPortalL1_ == address(0) + || address(rootRegistrar_) == address(0) + || address(subRegistrar_) == address(0) + || address(domainToken_) == address(0) + || address(registry_) == address(0) + ) revert ZeroAddressPassed(); + + polygonZkEVMBridge = zkEvmBridge_; + networkId = polygonZkEVMBridge.networkID(); + znsZkEvmPortalL1 = znsZkEvmPortalL1_; + rootRegistrar = rootRegistrar_; + subRegistrar = subRegistrar_; + domainToken = domainToken_; + registry = registry_; + } + + function onMessageReceived( + address originAddress, + uint32 originNetwork, + bytes memory data + ) external payable { + if (msg.sender == address(polygonZkEVMBridge)) revert CalledByInvalidContract(msg.sender); + + RegistrationProof memory proof = abi.decode(data, (RegistrationProof)); + + DistributionConfig memory emptyDistrConfig; + PaymentConfig memory emptyPaymentConfig; + + // Register bridged domain + bytes32 domainHash; + if (proof.parentHash == bytes32(0)) { + domainHash = rootRegistrar.registerRootDomain( + proof.label, + address(0), + proof.tokenUri, + emptyDistrConfig, + emptyPaymentConfig + ); + } else { + // TODO multi: think on how to best make this work when the parent is not present + // on this chain and the checks for it will fail + // maybe make a new function specifically to be registered from here ONLY ??? + domainHash = subRegistrar.registerSubdomain( + proof.parentHash, + proof.label, + address(0), + proof.tokenUri, + emptyDistrConfig, + emptyPaymentConfig + ); + } + + // Validate that we bridged a proper domain + if (domainHash != proof.domainHash) + revert DomainHashDoesNotMatchBridged(proof.domainHash, domainHash); + + // Transfer domain ownership to the address of registrant on L1 + registry.updateDomainOwner( + proof.domainHash, + proof.domainOwner + ); + // Transfer the token + domainToken.transferFrom( + address(this), + proof.domainOwner, + uint256(proof.domainHash) + ); + + emit DomainClaimed( + originNetwork, + originAddress, + proof.domainHash, + proof.domainOwner + ); + } + + function setL2PortalAddress(address newAddress) external onlyAdmin { + if (newAddress == address(0)) revert ZeroAddressPassed(); + + znsZkEvmPortalL1 = newAddress; + + emit L2PortalAddressSet(newAddress); + } + + /** + * @notice To use UUPS proxy we override this function and revert if `msg.sender` isn't authorized + * @param newImplementation The implementation contract to upgrade to + */ + // solhint-disable-next-line + function _authorizeUpgrade(address newImplementation) internal view override { + accessController.checkGovernor(msg.sender); + } +} From 4d2afbbfef8d7903f1a595667f0d13efef883675 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 8 Oct 2024 15:30:44 -0700 Subject: [PATCH 029/124] move ZkEvmPortal and add some logic --- .../ZNSPolygonZkEvmPortal.sol | 72 ++++++++++++------- 1 file changed, 47 insertions(+), 25 deletions(-) rename contracts/{cross-chain-portals => cross-chain}/ZNSPolygonZkEvmPortal.sol (71%) diff --git a/contracts/cross-chain-portals/ZNSPolygonZkEvmPortal.sol b/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol similarity index 71% rename from contracts/cross-chain-portals/ZNSPolygonZkEvmPortal.sol rename to contracts/cross-chain/ZNSPolygonZkEvmPortal.sol index 0e4fcc484..c81309b19 100644 --- a/contracts/cross-chain-portals/ZNSPolygonZkEvmPortal.sol +++ b/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol @@ -26,6 +26,7 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut bytes32 indexed domainHash, address indexed domainOwner ); + event L1PortalAddressSet(address newAddress); // *--| Cross-chain Data |--* IPolygonZkEVMBridgeV2 public polygonZkEVMBridge; @@ -37,6 +38,7 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut // *--| ZNS Data for THIS chain |--* IZNSRootRegistrar public rootRegistrar; IZNSSubRegistrar public subRegistrar; + IZNSTreasury public treasury; IZNSRegistry public registry; /// @custom:oz-upgrades-unsafe-allow constructor @@ -48,26 +50,26 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut address accessController_, uint32 networkIdL2_, IPolygonZkEVMBridgeV2 zkEvmBridge_, - address znsEthPortalL2_, IZNSRootRegistrar rootRegistrar_, IZNSSubRegistrar subRegistrar_, + IZNSTreasury treasury_, IZNSRegistry registry_ ) external initializer { _setAccessController(accessController_); if ( - zkEvmBridge_ == address(0) - | znsEthPortalL2_ == address(0) - | address(rootRegistrar_) == address(0) - | address(subRegistrar_) == address(0) - | address(registry_) == address(0) + address(zkEvmBridge_) == address(0) + || address(rootRegistrar_) == address(0) + || address(subRegistrar_) == address(0) + || address(treasury_) == address(0) + || address(registry_) == address(0) ) revert ZeroAddressPassed(); polygonZkEVMBridge = zkEvmBridge_; networkIdL2 = networkIdL2_; - znsEthPortalL2 = znsEthPortalL2_; rootRegistrar = rootRegistrar_; subRegistrar = subRegistrar_; + treasury = treasury_; registry = registry_; } @@ -77,15 +79,15 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut string calldata tokenURI // bool forceUpdateGlobalExitRoot - do we need to pass this ??? ) external { - DistributionConfig memory emptyDistrConfig = DistributionConfig( - IZNSPricer(address(0)), - PaymentType.DIRECT, - AccessType.LOCKED - ); - PaymentConfig memory emptyPaymentConfig = PaymentConfig( - IERC20(address(0)), - address(0) - ); + DistributionConfig memory emptyDistrConfig; + PaymentConfig memory emptyPaymentConfig; + + // TODO multi: do we actually want to stake on BOTH sides? What other payment option can we do ???!!! + // TODO multi: if we leave this option (stake as Portal address) this needs to be optimized!!! + // take payment to this contract so it can register + uint256 domainPrice = rootRegistrar.rootPricer().getPrice(0x0, label, true); + ( IERC20 paymentToken, ) = treasury.paymentConfigs(0x0); + paymentToken.transferFrom(msg.sender, address(this), domainPrice); // Register domain bytes32 domainHash; @@ -111,22 +113,34 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut // TODO multi: should we do that or leave this Agent as the owner ??? // DELETER registry from state if this is NOT used !!! // set owner as ZNSRegistry on this network - registry.updateDomainOwner(domainHash, address(registry)); +// registry.updateDomainOwner(domainHash, address(registry)); // TODO multi: ADD write record to ChainResolver here !!! // Bridge domain - _bridgeDomain(domainHash, tokenURI); - } - - function _bridgeDomain(bytes32 domainHash, string calldata tokenURI) internal { - // Create data proof for ZNS on L2 - RegistrationProof memory proof = RegistrationProof( - // we are using msg.sender here because the current caller on L1 will be the owner of the bridged L2 domain - msg.sender, + _bridgeDomain( domainHash, + parentHash, + label, tokenURI ); + } + + function _bridgeDomain( + bytes32 domainHash, + bytes32 parentHash, + string calldata label, + string calldata tokenURI + ) internal { + // Create data proof for ZNS on L2 + // we are using msg.sender here because the current caller on L1 will be the owner of the bridged L2 domain + RegistrationProof memory proof = RegistrationProof({ + domainOwner: msg.sender, + domainHash: domainHash, + parentHash: parentHash, + label: label, + tokenUri: tokenURI + }); bytes memory encodedProof = abi.encode(proof); @@ -147,6 +161,14 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut ); } + function setL1PortalAddress(address newAddress) external onlyAdmin { + if (newAddress == address(0)) revert ZeroAddressPassed(); + + znsEthPortalL2 = newAddress; + + emit L1PortalAddressSet(newAddress); + } + /** * @notice To use UUPS proxy we override this function and revert if `msg.sender` isn't authorized * @param newImplementation The implementation contract to upgrade to From a1312c2aa46c9743febea52b96bed1794728d7ce Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 8 Oct 2024 15:30:56 -0700 Subject: [PATCH 030/124] create generic ERC20 mock --- .../token/mocks/CustomDecimalTokenMock.sol | 2 +- contracts/token/mocks/ERC20Mock.sol | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 contracts/token/mocks/ERC20Mock.sol diff --git a/contracts/token/mocks/CustomDecimalTokenMock.sol b/contracts/token/mocks/CustomDecimalTokenMock.sol index 507a1adf0..7d8133216 100644 --- a/contracts/token/mocks/CustomDecimalTokenMock.sol +++ b/contracts/token/mocks/CustomDecimalTokenMock.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; // solhint-disable -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract CustomDecimalTokenMock is ERC20 { uint8 private _decimals; diff --git a/contracts/token/mocks/ERC20Mock.sol b/contracts/token/mocks/ERC20Mock.sol new file mode 100644 index 000000000..456dc38c7 --- /dev/null +++ b/contracts/token/mocks/ERC20Mock.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +// solhint-disable +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + + +contract ERC20Mock is ERC20 { + uint256 private _totalSupplyBase = 10000000000000000000000; + + constructor(address owner_, uint256 decimals_) ERC20("TokenMock", "ETM") { + _mint(owner_, totalSupply()); + } + + function totalSupply() public view override returns (uint256) { + return _totalSupplyBase * 10 ** decimals(); + } + + function mint(address to, uint256 amount) public { + _mint(to, amount); + } +} From fb06bcc24f0169638f3f59100df7d287d6016bc8 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 8 Oct 2024 15:31:08 -0700 Subject: [PATCH 031/124] create ZkEvmBridge mock --- .../mock/PolygonZkEVMBridgeV2Mock.sol | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 contracts/cross-chain/mock/PolygonZkEVMBridgeV2Mock.sol diff --git a/contracts/cross-chain/mock/PolygonZkEVMBridgeV2Mock.sol b/contracts/cross-chain/mock/PolygonZkEVMBridgeV2Mock.sol new file mode 100644 index 000000000..1c8a7928b --- /dev/null +++ b/contracts/cross-chain/mock/PolygonZkEVMBridgeV2Mock.sol @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +// This is here only to bring the contract so Hardhat compiles it by default +import { IBridgeMessageReceiver } from "@zero-tech/zkevm-contracts/contracts/interfaces/IBridgeMessageReceiver.sol"; +import { ERC20Mock } from "../../token/mocks/ERC20Mock.sol"; + + +// Note that this does NOT inherit the original Bridge contract! +// We are EMULATING bridge behavior here so we can run tests on the same chain +contract PolygonZkEVMBridgeV2Mock { + error NoValueInMessagesOnGasTokenNetworks(); + error DestinationNetworkInvalid(); + error MessageFailed(); + + event ClaimEvent( + uint256 globalIndex, + uint32 originNetwork, + address originAddress, + address destinationAddress, + uint256 amount + ); + event BridgeEvent( + uint8 leafType, + uint32 originNetwork, + address originAddress, + uint32 destinationNetwork, + address destinationAddress, + uint256 amount, + bytes metadata, + uint32 globalIndex + ); + + + uint256 internal constant _DEPOSIT_CONTRACT_TREE_DEPTH = 32; + uint8 private constant _LEAF_TYPE_MESSAGE = 1; + + uint32 public networkID; + uint256 public depositCount; + + // TODO multi: in original contract there is TokenWrapped type here + // WETH address + ERC20Mock public WETHToken; + + constructor( + uint32 _networkID, + address _WETHToken + ) { + networkID = _networkID; + WETHToken = ERC20Mock(_WETHToken); + } + + function bridgeMessage( + uint32 destinationNetwork, + address destinationAddress, + bool forceUpdateGlobalExitRoot, + bytes calldata metadata + ) external payable { + // If exist a gas token, only allow call this function without value + if (msg.value != 0 && address(WETHToken) != address(0)) { + revert NoValueInMessagesOnGasTokenNetworks(); + } + + _bridgeMessage( + destinationNetwork, + destinationAddress, + msg.value, + forceUpdateGlobalExitRoot, + metadata + ); + } + + function _bridgeMessage( + uint32 destinationNetwork, + address destinationAddress, + uint256 amountEther, + bool forceUpdateGlobalExitRoot, + bytes calldata metadata + ) internal { + if (destinationNetwork == networkID) { + revert DestinationNetworkInvalid(); + } + + ++depositCount; + + emit BridgeEvent( + _LEAF_TYPE_MESSAGE, + networkID, + msg.sender, + destinationNetwork, + destinationAddress, + amountEther, + metadata, + uint32(depositCount) + ); + } + + function claimMessage( + bytes32[_DEPOSIT_CONTRACT_TREE_DEPTH] calldata smtProofLocalExitRoot, + bytes32[_DEPOSIT_CONTRACT_TREE_DEPTH] calldata smtProofRollupExitRoot, + uint256 globalIndex, + bytes32 mainnetExitRoot, + bytes32 rollupExitRoot, + uint32 originNetwork, + address originAddress, + uint32 destinationNetwork, + address destinationAddress, + uint256 amount, + bytes calldata metadata + ) external { + // Destination network must be this networkID + if (destinationNetwork != networkID) { + revert DestinationNetworkInvalid(); + } + + // Execute message + bool success; + if (address(WETHToken) == address(0)) { + // Native token is ether + // Transfer ether + /* solhint-disable avoid-low-level-calls */ + (success, ) = destinationAddress.call{value: amount}( + abi.encodeCall( + IBridgeMessageReceiver.onMessageReceived, + (originAddress, originNetwork, metadata) + ) + ); + } else { + // Mint wETH tokens + WETHToken.mint(destinationAddress, amount); + + // Execute message + /* solhint-disable avoid-low-level-calls */ + (success, ) = destinationAddress.call( + abi.encodeCall( + IBridgeMessageReceiver.onMessageReceived, + (originAddress, originNetwork, metadata) + ) + ); + } + + if (!success) { + revert MessageFailed(); + } + + emit ClaimEvent( + globalIndex, + originNetwork, + originAddress, + destinationAddress, + amount + ); + } +} From c985d2a7b4c9ee604b2a848d6c9f796dfcf8d976 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 8 Oct 2024 15:31:31 -0700 Subject: [PATCH 032/124] create new tests and add some deploy helpers for new contracts --- src/deploy/campaign/types.ts | 9 +- test/L2-BRIDGE-TEST/MultiZNS.test.ts | 298 ++++++++++++++++++++------- 2 files changed, 232 insertions(+), 75 deletions(-) diff --git a/src/deploy/campaign/types.ts b/src/deploy/campaign/types.ts index 4c9cce795..462ad53de 100644 --- a/src/deploy/campaign/types.ts +++ b/src/deploy/campaign/types.ts @@ -14,7 +14,7 @@ import { ZNSSubRegistrar, ZNSTreasury, MeowToken, - ZNSStringResolver, + ZNSStringResolver, ZNSPolygonZkEvmPortal, ZNSEthereumPortal, PolygonZkEVMBridgeV2Mock, } from "../../../typechain"; export type IZNSSigner = HardhatEthersSigner | DefenderRelaySigner | SignerWithAddress; @@ -53,7 +53,10 @@ export type ZNSContract = ZNSTreasury | ZNSRootRegistrar | ZNSFixedPricer | - ZNSSubRegistrar; + ZNSSubRegistrar | + ZNSPolygonZkEvmPortal | + ZNSEthereumPortal | + PolygonZkEVMBridgeV2Mock; export interface IZNSContracts extends IContractState { accessController : ZNSAccessController; @@ -67,4 +70,4 @@ export interface IZNSContracts extends IContractState { rootRegistrar : ZNSRootRegistrar; fixedPricer : ZNSFixedPricer; subRegistrar : ZNSSubRegistrar; -} \ No newline at end of file +} diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts index 4eae22419..1e8f2b3e6 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -5,153 +5,307 @@ import { IZNSCampaignConfig, IZNSContracts } from "../../src/deploy/campaign/typ import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { registrationWithSetup } from "../helpers/register-setup"; import { - AccessType, + AccessType, DEFAULT_TOKEN_URI, distrConfigEmpty, DISTRIBUTION_LOCKED_NOT_EXIST_ERR, fullDistrConfigEmpty, NOT_AUTHORIZED_ERR, - NOT_OWNER_OF_ERR, + NOT_OWNER_OF_ERR, paymentConfigEmpty, PaymentType, } from "../helpers"; import { expect } from "chai"; import * as ethers from "ethers"; -import { ZNSChainResolver, ZNSChainResolver__factory } from "../../typechain"; +import { + PolygonZkEVMBridgeV2Mock, + PolygonZkEVMBridgeV2Mock__factory, + ZNSChainResolver, + ZNSChainResolver__factory, ZNSEthereumPortal, + ZNSEthereumPortal__factory, ZNSPolygonZkEvmPortal, + ZNSPolygonZkEvmPortal__factory, +} from "../../typechain"; +import { getDomainHashFromEvent } from "../helpers/events"; + + +// TODO multi: move below code to appropriate places +// some of these may be optional ?? +export interface IZNSContractsExtended extends IZNSContracts { + polyPortal : ZNSPolygonZkEvmPortal; + bridgeL1 : PolygonZkEVMBridgeV2Mock; + ethPortal : ZNSEthereumPortal; + bridgeL2 : PolygonZkEVMBridgeV2Mock; +} + + +export const NETWORK_ID_L1_DEFAULT = 1n; +export const NETWORK_ID_L2_DEFAULT = 666n; + +export const deployCrossChainContracts = async ({ + deployer, + znsL1, + znsL2, + networkIdL1 = NETWORK_ID_L1_DEFAULT, + networkIdL2 = NETWORK_ID_L2_DEFAULT, + wethTokenAddress = hre.ethers.ZeroAddress, +} : { + deployer : SignerWithAddress; + znsL1 : IZNSContracts; + znsL2 : IZNSContracts; + networkIdL1 ?: bigint; + networkIdL2 ?: bigint; + wethTokenAddress ?: string; +}) => { + const polyPortalFact = new ZNSPolygonZkEvmPortal__factory(deployer); + const ethPortalFact = new ZNSEthereumPortal__factory(deployer); + const bridgeMockFact = new PolygonZkEVMBridgeV2Mock__factory(deployer); + + const bridgeL1 = await bridgeMockFact.deploy( + networkIdL1, + wethTokenAddress, + ); + await bridgeL1.waitForDeployment(); + const bridgeL2 = await bridgeMockFact.deploy( + networkIdL2, + wethTokenAddress, + ); + await bridgeL2.waitForDeployment(); + + const polyPortal = await hre.upgrades.deployProxy( + polyPortalFact, + [ + znsL1.accessController.target, + networkIdL2, + bridgeL1.target, + znsL1.rootRegistrar.target, + znsL1.subRegistrar.target, + znsL1.registry.target, + ], + { + kind: "uups", + } + ) as unknown as ZNSPolygonZkEvmPortal; + await polyPortal.waitForDeployment(); + + const ethPortal = await hre.upgrades.deployProxy( + ethPortalFact, + [ + znsL2.accessController.target, + bridgeL2.target, + polyPortal.target, + znsL2.rootRegistrar.target, + znsL2.subRegistrar.target, + znsL2.registry.target, + znsL2.registry.target, + ], + { + kind: "uups", + } + ) as unknown as ZNSEthereumPortal; + await ethPortal.waitForDeployment(); + await polyPortal.connect(deployer).setL1PortalAddress(ethPortal.target); -describe("MultiZNS", () => { - let zns : IZNSContracts; + return { + polyPortal, + ethPortal, + bridgeL1, + bridgeL2, + }; +}; + +describe.only("MultiZNS", () => { + let znsL1 : IZNSContractsExtended; + let znsL2 : IZNSContractsExtended; let deployAdmin : SignerWithAddress; - let registryMock : SignerWithAddress; let config : IZNSCampaignConfig; - const chainDomainLabel = "zchain"; - let chainDomainHash : string; + const rootDomainLabel = "jeffbridges"; + let rootDomainHash : string; let chainResolver : ZNSChainResolver; before(async () => { - [ deployAdmin, registryMock ] = await hre.ethers.getSigners(); + [ deployAdmin ] = await hre.ethers.getSigners(); config = await getConfig({ deployer: deployAdmin, zeroVaultAddress: deployAdmin.address, }); - const campaign = await runZnsCampaign({ config }); + const campaignL1 = await runZnsCampaign({ config }); - zns = campaign.state.contracts; + znsL1 = campaignL1.state.contracts; - await zns.meowToken.mint(deployAdmin.address, 1000000000000000000000n); - await zns.meowToken.connect(deployAdmin).approve(zns.treasury.target, ethers.MaxUint256); + await znsL1.meowToken.mint(deployAdmin.address, 1000000000000000000000n); + await znsL1.meowToken.connect(deployAdmin).approve(znsL1.treasury.target, ethers.MaxUint256); // TODO multi: add deploy mission for ChainResolver if decided to leave it! const chainResFact = new ZNSChainResolver__factory(deployAdmin); chainResolver = await hre.upgrades.deployProxy( chainResFact, [ - zns.accessController.target, - zns.registry.target, + znsL1.accessController.target, + znsL1.registry.target, ], { kind: "uups", } ) as unknown as ZNSChainResolver; await chainResolver.waitForDeployment(); + + config = await getConfig({ + deployer: deployAdmin, + zeroVaultAddress: deployAdmin.address, + }); + + // emulating L2 here by deploying to the same network + const campaignL2 = await runZnsCampaign({ config }); + + znsL2 = campaignL2.state.contracts; + + await znsL2.meowToken.mint(deployAdmin.address, 1000000000000000000000n); + await znsL2.meowToken.connect(deployAdmin).approve(znsL2.treasury.target, ethers.MaxUint256); + + const { + polyPortal, + ethPortal, + bridgeL1, + bridgeL2, + } = await deployCrossChainContracts({ + deployer: deployAdmin, + znsL1, + znsL2, + }); + + znsL1 = { + ...znsL1, + polyPortal, + bridgeL1, + }; + + znsL2 = { + ...znsL2, + ethPortal, + bridgeL2, + }; }); - describe("Bridging Single Chain Specific Domain", () => { - it.only("should register a new root domain for a chain regularly", async () => { - chainDomainHash = await registrationWithSetup({ - zns, + describe("Bridge and Register on L1", () => { + before(async () => { + // register and bridge + await znsL1.polyPortal.connect(deployAdmin).registerAndBridgeDomain( + hre.ethers.ZeroHash, + rootDomainLabel, + DEFAULT_TOKEN_URI, + ); + rootDomainHash = await getDomainHashFromEvent({ + zns: znsL1, user: deployAdmin, - domainLabel: chainDomainLabel, - fullConfig: fullDistrConfigEmpty, }); + }); - // should be LOCKED to not allow any subdomains on L1 - const { accessType } = await zns.subRegistrar.distrConfigs(chainDomainHash); - expect(accessType).to.equal(0n); - - // set ChainResolver ?!?!?! - const chainId = 1668201165n; - const chainName = "ZChain"; - const znsRegistryOnChain = registryMock.address; - const auxData = "ZChain Root Domain"; - - await chainResolver.connect(deployAdmin).setChainData( - chainDomainHash, - chainId, - chainName, - znsRegistryOnChain, - auxData + it("should register and set owners as ZkEvmPortal and fire DomainBridged event", async () => { + // check if domain is registered on L1 + // check events + const filter = znsL1.polyPortal.filters.DomainBridged( + undefined, + undefined, + rootDomainHash, + undefined, ); + const events = await znsL1.polyPortal.queryFilter(filter); + const [event] = events; + expect(event.args.domainHash).to.equal(rootDomainHash); + expect(event.args.destNetworkId).to.equal(666n); + expect(event.args.destPortalAddress).to.equal(znsL2.ethPortal.target); + expect(event.args.domainOwner).to.equal(deployAdmin.address); - // transfer Domain Token to ZNSRegistry. It CAN NOT be transfered back! This is a final immutable operation! - await zns.domainToken.connect(deployAdmin).transferFrom( - deployAdmin.address, - zns.registry.target, - BigInt(chainDomainHash) - ); + // check owner and resolver are set properly + const { + owner: ownerL1, + resolver: resolverL1, + } = await znsL1.registry.getDomainRecord(rootDomainHash); + expect(ownerL1).to.equal(znsL1.polyPortal.target); + // TODO multi: unblock below code when logic added to contract + // expect(resolverL1).to.equal(chainResolver.target); + + const tokenOwner = await znsL1.domainToken.ownerOf(BigInt(rootDomainHash)); + expect(tokenOwner).to.equal(znsL1.polyPortal.target); + }); + + it("should set configs as empty", async () => { + // should be LOCKED with no configs + const distrConfig = await znsL1.subRegistrar.distrConfigs(rootDomainHash); + expect(distrConfig.accessType).to.equal(AccessType.LOCKED); + expect(distrConfig.paymentType).to.equal(PaymentType.DIRECT); + expect(distrConfig.pricerContract).to.equal(hre.ethers.ZeroAddress); - // [AS A LAST OPERATION] change owner to ZNSRegistry to signify that a domain is on another network - await zns.registry.connect(deployAdmin).updateDomainOwner(chainDomainHash, zns.registry.target); + const paymentConfig = await znsL1.treasury.paymentConfigs(rootDomainHash); + expect(paymentConfig.token).to.equal(hre.ethers.ZeroAddress); + expect(paymentConfig.beneficiary).to.equal(hre.ethers.ZeroAddress); + }); - // make sure no domain related functions are available to the domain creator now + it("should properly set data in ChainResolver", async () => { + // TODO multi: unblock below code when logic added to contract + // check resolver data + // const resolverData = await chainResolver.resolveChainDataStruct(chainDomainHash); + // expect(resolverData.chainId).to.equal(chainId); + // expect(resolverData.chainName).to.equal(chainName); + // expect(resolverData.znsRegistryOnChain).to.equal(znsRegistryOnChain); + // expect(resolverData.auxData).to.equal(auxData); + }); + + it("should NOT allow owner to access any domain functions after bridge", async () => { + // make sure NO domain related functions are available to the domain creator now await expect( - zns.registry.connect(deployAdmin).updateDomainOwner( - chainDomainHash, + znsL1.registry.connect(deployAdmin).updateDomainOwner( + rootDomainHash, deployAdmin.address ) - ).to.be.revertedWithCustomError(zns.registry, NOT_AUTHORIZED_ERR); + ).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR); await expect( - zns.addressResolver.connect(deployAdmin).setAddress( - chainDomainHash, + znsL1.addressResolver.connect(deployAdmin).setAddress( + rootDomainHash, deployAdmin.address ) - ).to.be.revertedWithCustomError(zns.registry, NOT_AUTHORIZED_ERR); + ).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR); await expect( - zns.subRegistrar.connect(deployAdmin).setDistributionConfigForDomain( - chainDomainHash, + znsL1.subRegistrar.connect(deployAdmin).setDistributionConfigForDomain( + rootDomainHash, { ...distrConfigEmpty, accessType: AccessType.OPEN, } ) - ).to.be.revertedWithCustomError(zns.registry, NOT_AUTHORIZED_ERR); + ).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR); // can't Revoke or Reclaim domain await expect( - zns.rootRegistrar.connect(deployAdmin).revokeDomain(chainDomainHash) - ).to.be.revertedWithCustomError(zns.rootRegistrar, NOT_OWNER_OF_ERR); + znsL1.rootRegistrar.connect(deployAdmin).revokeDomain(rootDomainHash) + ).to.be.revertedWithCustomError(znsL1.rootRegistrar, NOT_OWNER_OF_ERR); await expect( - zns.rootRegistrar.connect(deployAdmin).reclaimDomain(chainDomainHash) - ).to.be.revertedWithCustomError(zns.rootRegistrar, NOT_OWNER_OF_ERR); + znsL1.rootRegistrar.connect(deployAdmin).reclaimDomain(rootDomainHash) + ).to.be.revertedWithCustomError(znsL1.rootRegistrar, NOT_OWNER_OF_ERR); + }); + it("should NOT allow registration of subdomains", async () => { // make sure no one can register subdomains await expect( registrationWithSetup({ - zns, + zns: znsL1, user: deployAdmin, - parentHash: chainDomainHash, + parentHash: rootDomainHash, domainLabel: "test", fullConfig: fullDistrConfigEmpty, }) - ).to.be.revertedWithCustomError(zns.subRegistrar, DISTRIBUTION_LOCKED_NOT_EXIST_ERR); + ).to.be.revertedWithCustomError(znsL1.subRegistrar, DISTRIBUTION_LOCKED_NOT_EXIST_ERR); - const record = await zns.registry.getDomainRecord(chainDomainHash); - expect(record.owner).to.equal(zns.registry.target); - expect(record.resolver).to.equal(zns.addressResolver.target); - - // check resolver data - const resolverData = await chainResolver.resolveChainDataStruct(chainDomainHash); - expect(resolverData.chainId).to.equal(chainId); - expect(resolverData.chainName).to.equal(chainName); - expect(resolverData.znsRegistryOnChain).to.equal(znsRegistryOnChain); - expect(resolverData.auxData).to.equal(auxData); + const record = await znsL1.registry.getDomainRecord(rootDomainHash); + expect(record.owner).to.equal(znsL1.registry.target); + expect(record.resolver).to.equal(znsL1.addressResolver.target); }); }); }); From b29ad06588ef777d5c77ba64da5b8d7757158cbe Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 8 Oct 2024 16:43:04 -0700 Subject: [PATCH 033/124] fix pricing error and add onERC721Received to ZkEvmPortal --- .../cross-chain/ZNSPolygonZkEvmPortal.sol | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol b/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol index c81309b19..1ec3336cf 100644 --- a/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol +++ b/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol @@ -10,8 +10,9 @@ import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; import { IZNSRootRegistrar } from "../registrar/IZNSRootRegistrar.sol"; import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; -import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; import { IZNSPricer } from "../types/IZNSPricer.sol"; +import { IZNSTreasury } from "../treasury/IZNSTreasury.sol"; +import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; import { RegistrationProof } from "../types/CrossChainTypes.sol"; @@ -85,9 +86,15 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut // TODO multi: do we actually want to stake on BOTH sides? What other payment option can we do ???!!! // TODO multi: if we leave this option (stake as Portal address) this needs to be optimized!!! // take payment to this contract so it can register - uint256 domainPrice = rootRegistrar.rootPricer().getPrice(0x0, label, true); + (uint256 domainPrice, uint256 protocolFee) = rootRegistrar.rootPricer().getPriceAndFee( + 0x0, + label, + true + ); + uint256 totalCost = domainPrice + protocolFee; ( IERC20 paymentToken, ) = treasury.paymentConfigs(0x0); - paymentToken.transferFrom(msg.sender, address(this), domainPrice); + paymentToken.transferFrom(msg.sender, address(this), totalCost); + paymentToken.approve(address(treasury), totalCost); // Register domain bytes32 domainHash; @@ -126,6 +133,7 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut ); } + // TODO multi: move this lower in the contract function _bridgeDomain( bytes32 domainHash, bytes32 parentHash, @@ -161,6 +169,15 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut ); } + function onERC721Received( + address, + address, + uint256, + bytes calldata + ) external pure returns (bytes4) { + return this.onERC721Received.selector; + } + function setL1PortalAddress(address newAddress) external onlyAdmin { if (newAddress == address(0)) revert ZeroAddressPassed(); From efe7014b52490cae3d54d3c0efd11d7ddb3eb34a Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 8 Oct 2024 16:43:42 -0700 Subject: [PATCH 034/124] refactor registering logic and add new function to register without payments on L2 side to RootRegistrar --- contracts/cross-chain/ZNSEthereumPortal.sol | 7 +- contracts/registrar/IZNSRootRegistrar.sol | 17 ++++ contracts/registrar/ZNSRootRegistrar.sol | 93 ++++++++++++++------- 3 files changed, 84 insertions(+), 33 deletions(-) diff --git a/contracts/cross-chain/ZNSEthereumPortal.sol b/contracts/cross-chain/ZNSEthereumPortal.sol index 51a29b6f4..28dc776ba 100644 --- a/contracts/cross-chain/ZNSEthereumPortal.sol +++ b/contracts/cross-chain/ZNSEthereumPortal.sol @@ -94,12 +94,9 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IDistributionC // Register bridged domain bytes32 domainHash; if (proof.parentHash == bytes32(0)) { - domainHash = rootRegistrar.registerRootDomain( + domainHash = rootRegistrar.registerBridgedRootDomain( proof.label, - address(0), - proof.tokenUri, - emptyDistrConfig, - emptyPaymentConfig + proof.tokenUri ); } else { // TODO multi: think on how to best make this work when the parent is not present diff --git a/contracts/registrar/IZNSRootRegistrar.sol b/contracts/registrar/IZNSRootRegistrar.sol index b98da35ce..a71ae5991 100644 --- a/contracts/registrar/IZNSRootRegistrar.sol +++ b/contracts/registrar/IZNSRootRegistrar.sol @@ -3,6 +3,10 @@ pragma solidity 0.8.26; import { IDistributionConfig } from "../types/IDistributionConfig.sol"; import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; +import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; +import { IZNSSubRegistrar } from "./IZNSSubRegistrar.sol"; +import { IZNSPricer } from "../types/IZNSPricer.sol"; +import { IZNSTreasury } from "../treasury/IZNSTreasury.sol"; /** @@ -141,6 +145,11 @@ interface IZNSRootRegistrar is IDistributionConfig { PaymentConfig calldata paymentConfig ) external returns (bytes32); + function registerBridgedRootDomain( + string calldata label, + string calldata tokenURI + ) external returns (bytes32); + function coreRegister( CoreRegisterArgs memory args ) external; @@ -160,4 +169,12 @@ interface IZNSRootRegistrar is IDistributionConfig { function setDomainToken(address domainToken_) external; function setSubRegistrar(address subRegistrar_) external; + + function rootPricer() external view returns (IZNSPricer); + + function treasury() external view returns (IZNSTreasury); + + function domainToken() external view returns (IZNSDomainToken); + + function subRegistrar() external view returns (IZNSSubRegistrar); } diff --git a/contracts/registrar/ZNSRootRegistrar.sol b/contracts/registrar/ZNSRootRegistrar.sol index 5cb841e91..f048bc77e 100644 --- a/contracts/registrar/ZNSRootRegistrar.sol +++ b/contracts/registrar/ZNSRootRegistrar.sol @@ -77,7 +77,7 @@ contract ZNSRootRegistrar is * Calls `ZNSTreasury` to do the staking part, gets `tokenId` for the new token to be minted * as domain hash casted to uint256, mints the token and sets the domain data in the `ZNSRegistry` * and, possibly, `ZNSAddressResolver`. Emits a `DomainRegistered` event. - * @param name Name (label) of the domain to register + * @param label Name (label) of the domain to register * @param domainAddress (optional) Address for the `ZNSAddressResolver` to return when requested * @param tokenURI URI to assign to the Domain Token issued for the domain * @param distributionConfig (optional) Distribution config for the domain to set in the same tx @@ -89,23 +89,82 @@ contract ZNSRootRegistrar is * but all the parameters inside are required. */ function registerRootDomain( - string calldata name, + string calldata label, address domainAddress, string calldata tokenURI, DistributionConfig calldata distributionConfig, PaymentConfig calldata paymentConfig ) external override returns (bytes32) { + return _coreRootRegister( + label, + domainAddress, + tokenURI, + distributionConfig, + paymentConfig, + true + ); + } + + // TODO multi: should this function ONLY be on the L2 contract ??? + function registerBridgedRootDomain( + string calldata label, + string calldata tokenURI + // TODO multi: should we add specific role for the Portal ??? + ) external onlyRegistrar returns (bytes32) { + DistributionConfig memory emptyDistrConfig; + PaymentConfig memory emptyPaymentConfig; + + return _coreRootRegister( + label, + address(0), + tokenURI, + emptyDistrConfig, + emptyPaymentConfig, + false + ); + } + + /** + * @notice External function used by `ZNSSubRegistrar` for the final stage of registering subdomains. + * @param args `CoreRegisterArgs`: Struct containing all the arguments required to register a domain + * with ZNSRootRegistrar.coreRegister(): + * + `parentHash`: The hash of the parent domain (0x0 for root domains) + * + `domainHash`: The hash of the domain to be registered + * + `label`: The label of the domain to be registered + * + `registrant`: The address of the user who is registering the domain + * + `price`: The determined price for the domain to be registered based on parent rules + * + `stakeFee`: The determined stake fee for the domain to be registered (only for PaymentType.STAKE!) + * + `domainAddress`: The address to which the domain will be resolved to + * + `tokenURI`: The tokenURI for the domain to be registered + * + `isStakePayment`: A flag for whether the payment is a stake payment or not + */ + function coreRegister( + CoreRegisterArgs memory args + ) external override onlyRegistrar { + _coreRegister( + args + ); + } + + function _coreRootRegister( + string calldata label, + address domainAddress, + string calldata tokenURI, + DistributionConfig memory distributionConfig, + PaymentConfig memory paymentConfig, + bool payForDomain + ) internal returns (bytes32) { // Confirms string values are only [a-z0-9-] - name.validate(); + label.validate(); // Create hash for given domain name - bytes32 domainHash = keccak256(bytes(name)); + bytes32 domainHash = keccak256(bytes(label)); if (registry.exists(domainHash)) revert DomainAlreadyExists(domainHash); // Get price for the domain - uint256 domainPrice = rootPricer.getPrice(0x0, name, true); + uint256 domainPrice = payForDomain ? rootPricer.getPrice(0x0, label, true) : 0; _coreRegister( CoreRegisterArgs( @@ -115,7 +174,7 @@ contract ZNSRootRegistrar is domainAddress, domainPrice, 0, - name, + label, tokenURI, true, paymentConfig @@ -130,28 +189,6 @@ contract ZNSRootRegistrar is return domainHash; } - /** - * @notice External function used by `ZNSSubRegistrar` for the final stage of registering subdomains. - * @param args `CoreRegisterArgs`: Struct containing all the arguments required to register a domain - * with ZNSRootRegistrar.coreRegister(): - * + `parentHash`: The hash of the parent domain (0x0 for root domains) - * + `domainHash`: The hash of the domain to be registered - * + `label`: The label of the domain to be registered - * + `registrant`: The address of the user who is registering the domain - * + `price`: The determined price for the domain to be registered based on parent rules - * + `stakeFee`: The determined stake fee for the domain to be registered (only for PaymentType.STAKE!) - * + `domainAddress`: The address to which the domain will be resolved to - * + `tokenURI`: The tokenURI for the domain to be registered - * + `isStakePayment`: A flag for whether the payment is a stake payment or not - */ - function coreRegister( - CoreRegisterArgs memory args - ) external override onlyRegistrar { - _coreRegister( - args - ); - } - /** * @dev Internal function that is called by this contract to finalize the registration of a domain. * This function as also called by the external `coreRegister()` function as a part of From 04e69cde0bdbcfbcc8cdd66738a3b33bffd7f2e0 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 8 Oct 2024 16:44:26 -0700 Subject: [PATCH 035/124] change getDomainHashFromEvent helper --- test/helpers/events.ts | 11 +++++------ test/helpers/register-setup.ts | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/test/helpers/events.ts b/test/helpers/events.ts index d94501ace..d729dc22c 100644 --- a/test/helpers/events.ts +++ b/test/helpers/events.ts @@ -2,7 +2,7 @@ import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { time } from "@nomicfoundation/hardhat-toolbox/network-helpers"; import { TypedContractEvent, TypedEventLog } from "../../typechain/common"; import { IZNSContractsLocal } from "./types"; -import { IZNSContracts } from "../../src/deploy/campaign/types"; +import { IZNSContracts, ZNSContract } from "../../src/deploy/campaign/types"; export const getDomainRegisteredEvents = async ({ @@ -34,23 +34,22 @@ export const getDomainRegisteredEvents = async ({ export const getDomainHashFromEvent = async ({ zns, - user, + registrantAddress, } : { zns : IZNSContractsLocal | IZNSContracts; - user : SignerWithAddress; + registrantAddress : string; }) : Promise => { - const latestBlock = await time.latestBlock(); const filter = zns.rootRegistrar.filters.DomainRegistered( undefined, undefined, undefined, undefined, undefined, - user.address, + registrantAddress, undefined, ); - const events = await zns.rootRegistrar.queryFilter(filter, latestBlock - 2, latestBlock); + const events = await zns.rootRegistrar.queryFilter(filter); const { args: { domainHash } } = events[events.length - 1]; return domainHash; diff --git a/test/helpers/register-setup.ts b/test/helpers/register-setup.ts index ba8342943..14677f25e 100644 --- a/test/helpers/register-setup.ts +++ b/test/helpers/register-setup.ts @@ -172,7 +172,7 @@ export const registrationWithSetup = async ({ // get hash const domainHash = await getDomainHashFromEvent({ zns, - user, + registrantAddress: user, }); if (!hasConfig) return domainHash; From 10d235ff04e63ce59411da7f9f8ebfa59e847a17 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 8 Oct 2024 16:44:45 -0700 Subject: [PATCH 036/124] fix changed param in event helper usage across tests --- test/ZNSRootRegistrar.test.ts | 40 +++++++++++++++++------------------ test/ZNSSubRegistrar.test.ts | 6 +++--- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/test/ZNSRootRegistrar.test.ts b/test/ZNSRootRegistrar.test.ts index f4018b04f..db5b4e0bc 100644 --- a/test/ZNSRootRegistrar.test.ts +++ b/test/ZNSRootRegistrar.test.ts @@ -169,7 +169,7 @@ describe("ZNSRootRegistrar", () => { const domainHash = await getDomainHashFromEvent({ zns, - user: deployer, + registrantAddress: deployer, }); // Registering as deployer (owner of parent) and user is different gas values @@ -355,7 +355,7 @@ describe("ZNSRootRegistrar", () => { }); const domainHash = await getDomainHashFromEvent({ zns, - user, + registrantAddress: user, }); const tokenId = BigInt(domainHash); @@ -619,7 +619,7 @@ describe("ZNSRootRegistrar", () => { const domainHash = await getDomainHashFromEvent({ zns, - user, + registrantAddress: user, }); const { @@ -648,7 +648,7 @@ describe("ZNSRootRegistrar", () => { }); const domainHash = await getDomainHashFromEvent({ zns, - user, + registrantAddress: user, }); const { @@ -688,7 +688,7 @@ describe("ZNSRootRegistrar", () => { const namehashRef = hashDomainLabel(defaultDomain); const domainHash = await getDomainHashFromEvent({ zns, - user, + registrantAddress: user, }); expect(domainHash).to.eq(namehashRef); @@ -759,7 +759,7 @@ describe("ZNSRootRegistrar", () => { const domainHash = await getDomainHashFromEvent({ zns, - user, + registrantAddress: user, }); const exists = await zns.registry.exists(domainHash); @@ -777,7 +777,7 @@ describe("ZNSRootRegistrar", () => { const tokenId = BigInt( await getDomainHashFromEvent({ zns, - user, + registrantAddress: user, }) ); const owner = await zns.domainToken.ownerOf(tokenId); @@ -793,7 +793,7 @@ describe("ZNSRootRegistrar", () => { }); const domainHash = await getDomainHashFromEvent({ zns, - user, + registrantAddress: user, }); const resolvedAddress = await zns.addressResolver.resolveDomainAddress(domainHash); @@ -846,7 +846,7 @@ describe("ZNSRootRegistrar", () => { await defaultRootRegistration({ user: deployer, zns, domainName: defaultDomain }); const domainHash = await getDomainHashFromEvent({ zns, - user: deployer, + registrantAddress: deployer, }); const tokenId = BigInt(domainHash); const { amount: staked, token } = await zns.treasury.stakedForDomain(domainHash); @@ -880,7 +880,7 @@ describe("ZNSRootRegistrar", () => { await defaultRootRegistration({ user: deployer, zns, domainName: defaultDomain }); const domainHash = await getDomainHashFromEvent({ zns, - user: deployer, + registrantAddress: deployer, }); const tokenId = BigInt(domainHash); @@ -898,7 +898,7 @@ describe("ZNSRootRegistrar", () => { await defaultRootRegistration({ user: deployer, zns, domainName: defaultDomain }); const domainHash = await getDomainHashFromEvent({ zns, - user: deployer, + registrantAddress: deployer, }); // Reclaim the Domain const tx = zns.rootRegistrar.connect(user).reclaimDomain(domainHash); @@ -929,7 +929,7 @@ describe("ZNSRootRegistrar", () => { await defaultRootRegistration({ user: deployer, zns, domainName: defaultDomain }); const domainHash = await getDomainHashFromEvent({ zns, - user: deployer, + registrantAddress: deployer, }); const tokenId = BigInt(domainHash); const { amount: staked, token } = await zns.treasury.stakedForDomain(domainHash); @@ -973,7 +973,7 @@ describe("ZNSRootRegistrar", () => { await defaultRootRegistration({ user: deployer, zns, domainName: defaultDomain }); const domainHash = await getDomainHashFromEvent({ zns, - user: deployer, + registrantAddress: deployer, }); const tokenId = BigInt(domainHash); @@ -1023,7 +1023,7 @@ describe("ZNSRootRegistrar", () => { const domainHash = await getDomainHashFromEvent({ zns, - user, + registrantAddress: user, }); const price = await zns.curvePricer.getPrice(ethers.ZeroHash, defaultDomain, false); @@ -1054,7 +1054,7 @@ describe("ZNSRootRegistrar", () => { const domainHash = await getDomainHashFromEvent({ zns, - user, + registrantAddress: user, }); // add mintlist to check revocation @@ -1078,7 +1078,7 @@ describe("ZNSRootRegistrar", () => { const tokenId = BigInt( await getDomainHashFromEvent({ zns, - user, + registrantAddress: user, }) ); @@ -1128,7 +1128,7 @@ describe("ZNSRootRegistrar", () => { await defaultRootRegistration({ user, zns, domainName: defaultDomain }); const domainHash = await getDomainHashFromEvent({ zns, - user, + registrantAddress: user, }); // Validated staked values @@ -1167,7 +1167,7 @@ describe("ZNSRootRegistrar", () => { await defaultRootRegistration({ user: deployer, zns, domainName: defaultDomain }); const parentDomainHash = await getDomainHashFromEvent({ zns, - user: deployer, + registrantAddress: deployer, }); const owner = await zns.registry.connect(user).getDomainOwner(parentDomainHash); expect(owner).to.not.equal(user.address); @@ -1185,7 +1185,7 @@ describe("ZNSRootRegistrar", () => { await defaultRootRegistration({ user: deployer, zns, domainName: defaultDomain }); const parentDomainHash = await getDomainHashFromEvent({ zns, - user: deployer, + registrantAddress: deployer, }); const owner = await zns.registry.connect(user).getDomainOwner(parentDomainHash); expect(owner).to.not.equal(user.address); @@ -1210,7 +1210,7 @@ describe("ZNSRootRegistrar", () => { await defaultRootRegistration({ user, zns, domainName: defaultDomain }); const domainHash = await getDomainHashFromEvent({ zns, - user, + registrantAddress: user, }); // assign an operator diff --git a/test/ZNSSubRegistrar.test.ts b/test/ZNSSubRegistrar.test.ts index 8f7b71baa..4fd14a25b 100644 --- a/test/ZNSSubRegistrar.test.ts +++ b/test/ZNSSubRegistrar.test.ts @@ -2657,7 +2657,7 @@ describe("ZNSSubRegistrar", () => { const hash = await getDomainHashFromEvent({ zns, - user: lvl5SubOwner, + registrantAddress: lvl5SubOwner, }); // check registry @@ -2896,7 +2896,7 @@ describe("ZNSSubRegistrar", () => { const hash = await getDomainHashFromEvent({ zns, - user: lvl5SubOwner, + registrantAddress: lvl5SubOwner, }); // check registry @@ -3651,7 +3651,7 @@ describe("ZNSSubRegistrar", () => { const subHash = await getDomainHashFromEvent({ zns, - user: lvl2SubOwner, + registrantAddress: lvl2SubOwner, }); const rootConfigAfter = await zns.subRegistrar.distrConfigs(rootHash); From 7830877d8d5085a24076c25317a01825180e7261 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 8 Oct 2024 16:44:56 -0700 Subject: [PATCH 037/124] fix tests --- test/L2-BRIDGE-TEST/MultiZNS.test.ts | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts index 1e8f2b3e6..ed9c45ed8 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -10,7 +10,7 @@ import { DISTRIBUTION_LOCKED_NOT_EXIST_ERR, fullDistrConfigEmpty, NOT_AUTHORIZED_ERR, - NOT_OWNER_OF_ERR, paymentConfigEmpty, PaymentType, + NOT_OWNER_OF_ERR, paymentConfigEmpty, PaymentType, REGISTRAR_ROLE, } from "../helpers"; import { expect } from "chai"; import * as ethers from "ethers"; @@ -76,6 +76,7 @@ export const deployCrossChainContracts = async ({ bridgeL1.target, znsL1.rootRegistrar.target, znsL1.subRegistrar.target, + znsL1.treasury.target, znsL1.registry.target, ], { @@ -101,8 +102,15 @@ export const deployCrossChainContracts = async ({ ) as unknown as ZNSEthereumPortal; await ethPortal.waitForDeployment(); + // link portals await polyPortal.connect(deployer).setL1PortalAddress(ethPortal.target); + // give Role to the Portal on L2 to call special function + await znsL2.accessController.connect(deployer).grantRole( + REGISTRAR_ROLE, + ethPortal.target + ); + return { polyPortal, ethPortal, @@ -136,9 +144,6 @@ describe.only("MultiZNS", () => { znsL1 = campaignL1.state.contracts; - await znsL1.meowToken.mint(deployAdmin.address, 1000000000000000000000n); - await znsL1.meowToken.connect(deployAdmin).approve(znsL1.treasury.target, ethers.MaxUint256); - // TODO multi: add deploy mission for ChainResolver if decided to leave it! const chainResFact = new ZNSChainResolver__factory(deployAdmin); chainResolver = await hre.upgrades.deployProxy( @@ -188,6 +193,9 @@ describe.only("MultiZNS", () => { ethPortal, bridgeL2, }; + + await znsL1.meowToken.mint(deployAdmin.address, 1000000000000000000000n); + await znsL1.meowToken.connect(deployAdmin).approve(znsL1.polyPortal.target, ethers.MaxUint256); }); describe("Bridge and Register on L1", () => { @@ -200,7 +208,7 @@ describe.only("MultiZNS", () => { ); rootDomainHash = await getDomainHashFromEvent({ zns: znsL1, - user: deployAdmin, + registrantAddress: znsL1.polyPortal.target as string, }); }); @@ -302,10 +310,6 @@ describe.only("MultiZNS", () => { fullConfig: fullDistrConfigEmpty, }) ).to.be.revertedWithCustomError(znsL1.subRegistrar, DISTRIBUTION_LOCKED_NOT_EXIST_ERR); - - const record = await znsL1.registry.getDomainRecord(rootDomainHash); - expect(record.owner).to.equal(znsL1.registry.target); - expect(record.resolver).to.equal(znsL1.addressResolver.target); }); }); }); From b37297e7a178411786d043fa2deafdd6c6ffbd8e Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 8 Oct 2024 16:47:27 -0700 Subject: [PATCH 038/124] add comment to EthPortal --- contracts/cross-chain/ZNSEthereumPortal.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/cross-chain/ZNSEthereumPortal.sol b/contracts/cross-chain/ZNSEthereumPortal.sol index 28dc776ba..8d525bf7d 100644 --- a/contracts/cross-chain/ZNSEthereumPortal.sol +++ b/contracts/cross-chain/ZNSEthereumPortal.sol @@ -116,6 +116,8 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IDistributionC if (domainHash != proof.domainHash) revert DomainHashDoesNotMatchBridged(proof.domainHash, domainHash); + // TODO multi: remove registry owner change if merged after DomainToken transfer changes! + // this should be done automatically by transferring the token! // Transfer domain ownership to the address of registrant on L1 registry.updateDomainOwner( proof.domainHash, From dc5b14f06bd27c25ebf1853f49f29bfacfe4bfc3 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 9 Oct 2024 16:14:52 -0700 Subject: [PATCH 039/124] add erc721 receiver function to EthPortal, inherit base interface for zkevm and fix caller check error --- contracts/cross-chain/ZNSEthereumPortal.sol | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/contracts/cross-chain/ZNSEthereumPortal.sol b/contracts/cross-chain/ZNSEthereumPortal.sol index 8d525bf7d..d828535d7 100644 --- a/contracts/cross-chain/ZNSEthereumPortal.sol +++ b/contracts/cross-chain/ZNSEthereumPortal.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.26; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { IBridgeMessageReceiver } from "@zero-tech/zkevm-contracts/contracts/interfaces/IBridgeMessageReceiver.sol"; import { AAccessControlled } from "../access/AAccessControlled.sol"; import { IPolygonZkEVMBridgeV2Ext } from "./IPolygonZkEVMBridgeV2Ext.sol"; import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; @@ -17,7 +18,7 @@ import { IZNSPricer } from "../types/IZNSPricer.sol"; // TODO multi: could this be a better name that implies cross-chain nature ??? -contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IDistributionConfig { +contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IDistributionConfig, IBridgeMessageReceiver { event DomainClaimed( uint32 indexed srcNetworkId, @@ -84,7 +85,7 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IDistributionC uint32 originNetwork, bytes memory data ) external payable { - if (msg.sender == address(polygonZkEVMBridge)) revert CalledByInvalidContract(msg.sender); + if (msg.sender != address(polygonZkEVMBridge)) revert CalledByInvalidContract(msg.sender); RegistrationProof memory proof = abi.decode(data, (RegistrationProof)); @@ -146,6 +147,15 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IDistributionC emit L2PortalAddressSet(newAddress); } + function onERC721Received( + address, + address, + uint256, + bytes calldata + ) external pure returns (bytes4) { + return this.onERC721Received.selector; + } + /** * @notice To use UUPS proxy we override this function and revert if `msg.sender` isn't authorized * @param newImplementation The implementation contract to upgrade to From 1af8ce4cd64ae82340816939ce4c9a053efb0aaa Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 9 Oct 2024 16:15:19 -0700 Subject: [PATCH 040/124] add .isSet prop setting on FixedPricer in setPrice call as well --- contracts/price/ZNSFixedPricer.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/price/ZNSFixedPricer.sol b/contracts/price/ZNSFixedPricer.sol index e3be189a9..3b65de851 100644 --- a/contracts/price/ZNSFixedPricer.sol +++ b/contracts/price/ZNSFixedPricer.sol @@ -149,6 +149,7 @@ contract ZNSFixedPricer is AAccessControlled, ARegistryWired, UUPSUpgradeable, I */ function _setPrice(bytes32 domainHash, uint256 price) internal { priceConfigs[domainHash].price = price; + priceConfigs[domainHash].isSet = true; emit PriceSet(domainHash, price); } From 1ec8cb9e17f9d6aaa08196b80e04f0cdbd7a5539 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 9 Oct 2024 16:15:40 -0700 Subject: [PATCH 041/124] create generic event getter helper for tests --- test/helpers/events.ts | 16 +++++++++++++++- test/helpers/register-setup.ts | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/test/helpers/events.ts b/test/helpers/events.ts index d729dc22c..c553aa295 100644 --- a/test/helpers/events.ts +++ b/test/helpers/events.ts @@ -1,4 +1,4 @@ -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; +/* eslint-disable @typescript-eslint/ban-ts-comment, @typescript-eslint/no-explicit-any */ import { time } from "@nomicfoundation/hardhat-toolbox/network-helpers"; import { TypedContractEvent, TypedEventLog } from "../../typechain/common"; import { IZNSContractsLocal } from "./types"; @@ -54,3 +54,17 @@ export const getDomainHashFromEvent = async ({ return domainHash; }; + +export const getEvents = async ({ + contract, + eventName, + args, +} : { + contract : any; + eventName : string; + args ?: any; +}) : Promise>> => { + const filter = contract.filters[eventName](args); + + return contract.queryFilter(filter); +}; diff --git a/test/helpers/register-setup.ts b/test/helpers/register-setup.ts index 14677f25e..6a8f7b8fb 100644 --- a/test/helpers/register-setup.ts +++ b/test/helpers/register-setup.ts @@ -172,7 +172,7 @@ export const registrationWithSetup = async ({ // get hash const domainHash = await getDomainHashFromEvent({ zns, - registrantAddress: user, + registrantAddress: user.address, }); if (!hasConfig) return domainHash; From 2d4371d8e9a33fb3053cc19f3812a96d8995aeee Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 9 Oct 2024 16:15:53 -0700 Subject: [PATCH 042/124] add base tests for L2 side --- test/L2-BRIDGE-TEST/MultiZNS.test.ts | 197 +++++++++++++++++++++++---- 1 file changed, 172 insertions(+), 25 deletions(-) diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts index ed9c45ed8..44524c6ef 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -22,7 +22,7 @@ import { ZNSEthereumPortal__factory, ZNSPolygonZkEvmPortal, ZNSPolygonZkEvmPortal__factory, } from "../../typechain"; -import { getDomainHashFromEvent } from "../helpers/events"; +import { getDomainHashFromEvent, getEvents } from "../helpers/events"; // TODO multi: move below code to appropriate places @@ -93,7 +93,7 @@ export const deployCrossChainContracts = async ({ polyPortal.target, znsL2.rootRegistrar.target, znsL2.subRegistrar.target, - znsL2.registry.target, + znsL2.domainToken.target, znsL2.registry.target, ], { @@ -124,16 +124,28 @@ describe.only("MultiZNS", () => { let znsL2 : IZNSContractsExtended; let deployAdmin : SignerWithAddress; + let user : SignerWithAddress; let config : IZNSCampaignConfig; const rootDomainLabel = "jeffbridges"; let rootDomainHash : string; + let bridgedEventData : { + leafType : bigint; + originNetwork : bigint; + originAddress : string; + destinationNetwork : bigint; + destinationAddress : string; + amount : bigint; + metadata : string; + globalIndex : bigint; + }; + let chainResolver : ZNSChainResolver; before(async () => { - [ deployAdmin ] = await hre.ethers.getSigners(); + [ deployAdmin, user ] = await hre.ethers.getSigners(); config = await getConfig({ deployer: deployAdmin, @@ -196,38 +208,38 @@ describe.only("MultiZNS", () => { await znsL1.meowToken.mint(deployAdmin.address, 1000000000000000000000n); await znsL1.meowToken.connect(deployAdmin).approve(znsL1.polyPortal.target, ethers.MaxUint256); - }); - describe("Bridge and Register on L1", () => { - before(async () => { - // register and bridge - await znsL1.polyPortal.connect(deployAdmin).registerAndBridgeDomain( - hre.ethers.ZeroHash, - rootDomainLabel, - DEFAULT_TOKEN_URI, - ); - rootDomainHash = await getDomainHashFromEvent({ - zns: znsL1, - registrantAddress: znsL1.polyPortal.target as string, - }); + // register and bridge + await znsL1.polyPortal.connect(deployAdmin).registerAndBridgeDomain( + hre.ethers.ZeroHash, + rootDomainLabel, + DEFAULT_TOKEN_URI, + ); + rootDomainHash = await getDomainHashFromEvent({ + zns: znsL1, + registrantAddress: znsL1.polyPortal.target as string, }); + }); - it("should register and set owners as ZkEvmPortal and fire DomainBridged event", async () => { + describe("Bridge and Register on L1", () => { + it("should register and set owners as ZkEvmPortal and fire DomainBridged and BridgeEvent events", async () => { // check if domain is registered on L1 // check events - const filter = znsL1.polyPortal.filters.DomainBridged( - undefined, - undefined, - rootDomainHash, - undefined, - ); - const events = await znsL1.polyPortal.queryFilter(filter); - const [event] = events; + const [event] = await getEvents({ + contract: znsL1.polyPortal, + eventName: "DomainBridged", + }); expect(event.args.domainHash).to.equal(rootDomainHash); expect(event.args.destNetworkId).to.equal(666n); expect(event.args.destPortalAddress).to.equal(znsL2.ethPortal.target); expect(event.args.domainOwner).to.equal(deployAdmin.address); + // TODO multi: test these values !!! + [ { args: bridgedEventData } ] = await getEvents({ + contract: znsL1.bridgeL1, + eventName: "BridgeEvent", + }); + // check owner and resolver are set properly const { owner: ownerL1, @@ -312,4 +324,139 @@ describe.only("MultiZNS", () => { ).to.be.revertedWithCustomError(znsL1.subRegistrar, DISTRIBUTION_LOCKED_NOT_EXIST_ERR); }); }); + + describe("Claim Bridged Domain on L2", () => { + const dummySmtProof = Array.from({ length: 32 }, () => hre.ethers.randomBytes(32)); + + it("should #claimMessage() on the bridge successfully and fire a ClaimEvent", async () => { + // call Polygon Zk Evm Bridge to claimMessage + await znsL2.bridgeL2.connect(deployAdmin).claimMessage( + dummySmtProof, + dummySmtProof, + bridgedEventData.globalIndex, + dummySmtProof[0], + dummySmtProof[1], + bridgedEventData.originNetwork, + bridgedEventData.originAddress, + bridgedEventData.destinationNetwork, + bridgedEventData.destinationAddress, + bridgedEventData.amount, + bridgedEventData.metadata, + ); + + const [event] = await getEvents({ + contract: znsL2.bridgeL2, + eventName: "ClaimEvent", + }); + expect(event.args.originNetwork).to.equal(NETWORK_ID_L1_DEFAULT); + expect(event.args.originAddress).to.equal(znsL1.polyPortal.target); + expect(event.args.destinationAddress).to.equal(znsL2.ethPortal.target); + expect(event.args.amount).to.equal(0n); + }); + + it("should register domain on L2, set owners as original L1 caller and fire DomainClaimed event", async () => { + // check if domain is registered on L2 + // check events + const [event] = await getEvents({ + contract: znsL2.ethPortal, + eventName: "DomainClaimed", + }); + expect(event.args.srcNetworkId).to.equal(NETWORK_ID_L1_DEFAULT); + expect(event.args.srcPortalAddress).to.equal(znsL1.polyPortal.target); + expect(event.args.domainHash).to.equal(rootDomainHash); + expect(event.args.domainOwner).to.equal(deployAdmin.address); + + // check owner and resolver are set properly + const { + owner: ownerL2, + resolver: resolverL2, + } = await znsL2.registry.getDomainRecord(rootDomainHash); + expect(ownerL2).to.equal(deployAdmin.address); + // TODO multi: unblock below code when logic added to contract + // expect(resolverL2).to.equal(chainResolver.target); + + const tokenOwner = await znsL2.domainToken.ownerOf(BigInt(rootDomainHash)); + expect(tokenOwner).to.equal(deployAdmin.address); + }); + + it("should set configs as empty and allow original caller to set these configs", async () => { + // should be LOCKED with no configs + const distrConfig = await znsL2.subRegistrar.distrConfigs(rootDomainHash); + expect(distrConfig.accessType).to.equal(AccessType.LOCKED); + expect(distrConfig.paymentType).to.equal(PaymentType.DIRECT); + expect(distrConfig.pricerContract).to.equal(hre.ethers.ZeroAddress); + + const paymentConfig = await znsL2.treasury.paymentConfigs(rootDomainHash); + expect(paymentConfig.token).to.equal(hre.ethers.ZeroAddress); + expect(paymentConfig.beneficiary).to.equal(hre.ethers.ZeroAddress); + + // set configs + const distrConfigToSet = { + accessType: AccessType.OPEN, + paymentType: PaymentType.DIRECT, + pricerContract: znsL2.fixedPricer.target, + }; + await znsL2.subRegistrar.connect(deployAdmin).setDistributionConfigForDomain( + rootDomainHash, + distrConfigToSet, + ); + + const paymentConfigToSet = { + token: znsL2.meowToken.target, + beneficiary: deployAdmin.address, + }; + await znsL2.treasury.connect(deployAdmin).setPaymentConfig( + rootDomainHash, + paymentConfigToSet, + ); + + const priceToSet = 100n; + await znsL2.fixedPricer.setPrice(rootDomainHash, priceToSet); + + // check configs are set properly + const distrConfigAfter = await znsL2.subRegistrar.distrConfigs(rootDomainHash); + expect(distrConfigAfter.accessType).to.equal(distrConfigToSet.accessType); + expect(distrConfigAfter.paymentType).to.equal(distrConfigToSet.paymentType); + expect(distrConfigAfter.pricerContract).to.equal(distrConfigToSet.pricerContract); + + const paymentConfigAfter = await znsL2.treasury.paymentConfigs(rootDomainHash); + expect(paymentConfigAfter.token).to.equal(paymentConfigToSet.token); + expect(paymentConfigAfter.beneficiary).to.equal(paymentConfigToSet.beneficiary); + + const priceAfter = await znsL2.fixedPricer.getPrice(rootDomainHash, "test", true); + expect(priceAfter).to.equal(priceToSet); + }); + + it("should allow creating subdomains under the rules of newly set configs", async () => { + const subDomainLabel = "test"; + // make sure subdomains can be registered now + const subdomainHash = await registrationWithSetup({ + zns: znsL2, + user: deployAdmin, + parentHash: rootDomainHash, + domainLabel: subDomainLabel, + fullConfig: fullDistrConfigEmpty, + domainContent: deployAdmin.address, + }); + + const [ , event ] = await getEvents({ + contract: znsL2.rootRegistrar, + eventName: "DomainRegistered", + }); + expect(event.args.parentHash).to.equal(rootDomainHash); + expect(event.args.domainHash).to.equal(subdomainHash); + expect(event.args.label).to.equal(subDomainLabel); + expect(event.args.tokenURI).to.equal(DEFAULT_TOKEN_URI); + expect(event.args.registrant).to.equal(deployAdmin.address); + expect(event.args.domainAddress).to.equal(deployAdmin.address); + + // check if subdomain is registered + const record = await znsL2.registry.getDomainRecord(subdomainHash); + expect(record.owner).to.equal(deployAdmin.address); + expect(record.resolver).to.equal(znsL2.addressResolver.target); + + const tokenOwner = await znsL2.domainToken.ownerOf(BigInt(subdomainHash)); + expect(tokenOwner).to.equal(deployAdmin.address); + }); + }); }); From dd406990aad580ffb50e1ad9f3561104766a4138 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 10 Oct 2024 17:22:07 -0700 Subject: [PATCH 043/124] refactor subRegistrar to have function access to a bridged flow where payments and parent validation can be skipped --- contracts/registrar/IZNSSubRegistrar.sol | 6 ++ contracts/registrar/ZNSRootRegistrar.sol | 3 +- contracts/registrar/ZNSSubRegistrar.sol | 130 ++++++++++++++++------- 3 files changed, 99 insertions(+), 40 deletions(-) diff --git a/contracts/registrar/IZNSSubRegistrar.sol b/contracts/registrar/IZNSSubRegistrar.sol index bf7fbe142..684e31c9f 100644 --- a/contracts/registrar/IZNSSubRegistrar.sol +++ b/contracts/registrar/IZNSSubRegistrar.sol @@ -99,6 +99,12 @@ interface IZNSSubRegistrar is IDistributionConfig { PaymentConfig calldata paymentConfig ) external returns (bytes32); + function registerBridgedSubdomain( + bytes32 parentHash, + string calldata label, + string calldata tokenURI + ) external returns (bytes32); + function hashWithParent( bytes32 parentHash, string calldata label diff --git a/contracts/registrar/ZNSRootRegistrar.sol b/contracts/registrar/ZNSRootRegistrar.sol index f048bc77e..787e9e1b7 100644 --- a/contracts/registrar/ZNSRootRegistrar.sol +++ b/contracts/registrar/ZNSRootRegistrar.sol @@ -110,7 +110,7 @@ contract ZNSRootRegistrar is string calldata label, string calldata tokenURI // TODO multi: should we add specific role for the Portal ??? - ) external onlyRegistrar returns (bytes32) { + ) external onlyRegistrar override returns (bytes32) { DistributionConfig memory emptyDistrConfig; PaymentConfig memory emptyPaymentConfig; @@ -152,6 +152,7 @@ contract ZNSRootRegistrar is string calldata tokenURI, DistributionConfig memory distributionConfig, PaymentConfig memory paymentConfig, + // TODO multi: should we change this to `isBridged` ??? bool payForDomain ) internal returns (bytes32) { // Confirms string values are only [a-z0-9-] diff --git a/contracts/registrar/ZNSSubRegistrar.sol b/contracts/registrar/ZNSSubRegistrar.sol index b1b8a65a8..08ee92126 100644 --- a/contracts/registrar/ZNSSubRegistrar.sol +++ b/contracts/registrar/ZNSSubRegistrar.sol @@ -91,57 +91,68 @@ contract ZNSSubRegistrar is AAccessControlled, ARegistryWired, UUPSUpgradeable, DistributionConfig calldata distrConfig, PaymentConfig calldata paymentConfig ) external override returns (bytes32) { - // Confirms string values are only [a-z0-9-] - label.validate(); - - bytes32 domainHash = hashWithParent(parentHash, label); - if (registry.exists(domainHash)) - revert DomainAlreadyExists(domainHash); - - DistributionConfig memory parentConfig = distrConfigs[parentHash]; + return _coreSubdomainRegister( + parentHash, + label, + domainAddress, + tokenURI, + distrConfig, + paymentConfig, + false + ); + } - bool isOwnerOrOperator = registry.isOwnerOrOperator(parentHash, msg.sender); - if (parentConfig.accessType == AccessType.LOCKED && !isOwnerOrOperator) - revert ParentLockedOrDoesntExist(parentHash); + function registerBridgedSubdomain( + bytes32 parentHash, + string calldata label, + string calldata tokenURI + ) external onlyRegistrar override returns (bytes32) { + DistributionConfig memory emptyDistrConfig; + PaymentConfig memory emptyPaymentConfig; + + return _coreSubdomainRegister( + parentHash, + label, + address(0), + tokenURI, + emptyDistrConfig, + emptyPaymentConfig, + true + ); + } - if (parentConfig.accessType == AccessType.MINTLIST) { - if ( - !mintlist[parentHash] - .list - [mintlist[parentHash].ownerIndex] - [msg.sender] - ) revert SenderNotApprovedForPurchase(parentHash, msg.sender); - } + function _coreSubdomainRegister( + bytes32 parentHash, + string calldata label, + address domainAddress, + string calldata tokenURI, + DistributionConfig memory distrConfig, + PaymentConfig memory paymentConfig, + bool isBridgedDomain + ) internal returns (bytes32) { + // Confirms string values are only [a-z0-9-] + label.validate(); CoreRegisterArgs memory coreRegisterArgs = CoreRegisterArgs({ parentHash: parentHash, - domainHash: domainHash, + domainHash: 0x0, label: label, registrant: msg.sender, price: 0, stakeFee: 0, domainAddress: domainAddress, tokenURI: tokenURI, - isStakePayment: parentConfig.paymentType == PaymentType.STAKE, + isStakePayment: false, paymentConfig: paymentConfig }); - if (!isOwnerOrOperator) { - if (coreRegisterArgs.isStakePayment) { - (coreRegisterArgs.price, coreRegisterArgs.stakeFee) = IZNSPricer(address(parentConfig.pricerContract)) - .getPriceAndFee( - parentHash, - label, - true - ); - } else { - coreRegisterArgs.price = IZNSPricer(address(parentConfig.pricerContract)) - .getPrice( - parentHash, - label, - true - ); - } + coreRegisterArgs.domainHash = hashWithParent(parentHash, label); + if (registry.exists(coreRegisterArgs.domainHash)) + revert DomainAlreadyExists(coreRegisterArgs.domainHash); + + if (!isBridgedDomain) { + // TODO multi: do we need to reassign the return to coreRegisterArgs here ??? + _checkFillParentData(coreRegisterArgs); } rootRegistrar.coreRegister(coreRegisterArgs); @@ -152,7 +163,48 @@ contract ZNSSubRegistrar is AAccessControlled, ARegistryWired, UUPSUpgradeable, setDistributionConfigForDomain(coreRegisterArgs.domainHash, distrConfig); } - return domainHash; + return coreRegisterArgs.domainHash; + } + + function _checkFillParentData( + CoreRegisterArgs memory args + ) internal view returns (CoreRegisterArgs memory) { + DistributionConfig memory parentConfig = distrConfigs[args.parentHash]; + + bool isOwnerOrOperator = registry.isOwnerOrOperator(args.parentHash, msg.sender); + if (parentConfig.accessType == AccessType.LOCKED && !isOwnerOrOperator) + revert ParentLockedOrDoesntExist(args.parentHash); + + if (parentConfig.accessType == AccessType.MINTLIST) { + if ( + !mintlist[args.parentHash] + .list + [mintlist[args.parentHash].ownerIndex] + [msg.sender] + ) revert SenderNotApprovedForPurchase(args.parentHash, msg.sender); + } + + if (!isOwnerOrOperator) { + if (parentConfig.paymentType == PaymentType.STAKE) { + args.isStakePayment = true; + + (args.price, args.stakeFee) = IZNSPricer(address(parentConfig.pricerContract)) + .getPriceAndFee( + args.parentHash, + args.label, + true + ); + } else { + args.price = IZNSPricer(address(parentConfig.pricerContract)) + .getPrice( + args.parentHash, + args.label, + true + ); + } + } + + return args; } /** @@ -181,7 +233,7 @@ contract ZNSSubRegistrar is AAccessControlled, ARegistryWired, UUPSUpgradeable, */ function setDistributionConfigForDomain( bytes32 domainHash, - DistributionConfig calldata config + DistributionConfig memory config ) public override onlyOwnerOperatorOrRegistrar(domainHash) { if (address(config.pricerContract) == address(0)) revert ZeroAddressPassed(); From dd2108a3b83d0ced00c570750b92051369eedfa6 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 10 Oct 2024 17:22:26 -0700 Subject: [PATCH 044/124] adapt EthPortal to do a proper call to SubRegistrar --- contracts/cross-chain/ZNSEthereumPortal.sol | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/contracts/cross-chain/ZNSEthereumPortal.sol b/contracts/cross-chain/ZNSEthereumPortal.sol index d828535d7..9e228f49e 100644 --- a/contracts/cross-chain/ZNSEthereumPortal.sol +++ b/contracts/cross-chain/ZNSEthereumPortal.sol @@ -89,9 +89,6 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IDistributionC RegistrationProof memory proof = abi.decode(data, (RegistrationProof)); - DistributionConfig memory emptyDistrConfig; - PaymentConfig memory emptyPaymentConfig; - // Register bridged domain bytes32 domainHash; if (proof.parentHash == bytes32(0)) { @@ -100,16 +97,10 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IDistributionC proof.tokenUri ); } else { - // TODO multi: think on how to best make this work when the parent is not present - // on this chain and the checks for it will fail - // maybe make a new function specifically to be registered from here ONLY ??? - domainHash = subRegistrar.registerSubdomain( + domainHash = subRegistrar.registerBridgedSubdomain( proof.parentHash, proof.label, - address(0), - proof.tokenUri, - emptyDistrConfig, - emptyPaymentConfig + proof.tokenUri ); } From 55dd705b7f88900be90dcce977582b37b1306d62 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 10 Oct 2024 17:22:42 -0700 Subject: [PATCH 045/124] make all tests work for both root and subdomains --- test/L2-BRIDGE-TEST/MultiZNS.test.ts | 565 +++++++++++++++------------ test/helpers/types.ts | 5 +- 2 files changed, 323 insertions(+), 247 deletions(-) diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts index 44524c6ef..b05e6dd65 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -129,6 +129,9 @@ describe.only("MultiZNS", () => { let config : IZNSCampaignConfig; const rootDomainLabel = "jeffbridges"; + const subdomainLabel = "beaubridges"; + const subParentLabel = "bridges"; + let rootDomainHash : string; let bridgedEventData : { @@ -208,255 +211,327 @@ describe.only("MultiZNS", () => { await znsL1.meowToken.mint(deployAdmin.address, 1000000000000000000000n); await znsL1.meowToken.connect(deployAdmin).approve(znsL1.polyPortal.target, ethers.MaxUint256); - - // register and bridge - await znsL1.polyPortal.connect(deployAdmin).registerAndBridgeDomain( - hre.ethers.ZeroHash, - rootDomainLabel, - DEFAULT_TOKEN_URI, - ); - rootDomainHash = await getDomainHashFromEvent({ - zns: znsL1, - registrantAddress: znsL1.polyPortal.target as string, - }); + await znsL1.meowToken.connect(deployAdmin).approve(znsL1.treasury.target, ethers.MaxUint256); }); - describe("Bridge and Register on L1", () => { - it("should register and set owners as ZkEvmPortal and fire DomainBridged and BridgeEvent events", async () => { - // check if domain is registered on L1 - // check events - const [event] = await getEvents({ - contract: znsL1.polyPortal, - eventName: "DomainBridged", - }); - expect(event.args.domainHash).to.equal(rootDomainHash); - expect(event.args.destNetworkId).to.equal(666n); - expect(event.args.destPortalAddress).to.equal(znsL2.ethPortal.target); - expect(event.args.domainOwner).to.equal(deployAdmin.address); - - // TODO multi: test these values !!! - [ { args: bridgedEventData } ] = await getEvents({ - contract: znsL1.bridgeL1, - eventName: "BridgeEvent", - }); - - // check owner and resolver are set properly - const { - owner: ownerL1, - resolver: resolverL1, - } = await znsL1.registry.getDomainRecord(rootDomainHash); - expect(ownerL1).to.equal(znsL1.polyPortal.target); - // TODO multi: unblock below code when logic added to contract - // expect(resolverL1).to.equal(chainResolver.target); - - const tokenOwner = await znsL1.domainToken.ownerOf(BigInt(rootDomainHash)); - expect(tokenOwner).to.equal(znsL1.polyPortal.target); - }); - - it("should set configs as empty", async () => { - // should be LOCKED with no configs - const distrConfig = await znsL1.subRegistrar.distrConfigs(rootDomainHash); - expect(distrConfig.accessType).to.equal(AccessType.LOCKED); - expect(distrConfig.paymentType).to.equal(PaymentType.DIRECT); - expect(distrConfig.pricerContract).to.equal(hre.ethers.ZeroAddress); - - const paymentConfig = await znsL1.treasury.paymentConfigs(rootDomainHash); - expect(paymentConfig.token).to.equal(hre.ethers.ZeroAddress); - expect(paymentConfig.beneficiary).to.equal(hre.ethers.ZeroAddress); - }); - - it("should properly set data in ChainResolver", async () => { - // TODO multi: unblock below code when logic added to contract - // check resolver data - // const resolverData = await chainResolver.resolveChainDataStruct(chainDomainHash); - // expect(resolverData.chainId).to.equal(chainId); - // expect(resolverData.chainName).to.equal(chainName); - // expect(resolverData.znsRegistryOnChain).to.equal(znsRegistryOnChain); - // expect(resolverData.auxData).to.equal(auxData); - }); - - it("should NOT allow owner to access any domain functions after bridge", async () => { - // make sure NO domain related functions are available to the domain creator now - await expect( - znsL1.registry.connect(deployAdmin).updateDomainOwner( - rootDomainHash, - deployAdmin.address - ) - ).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR); - - await expect( - znsL1.addressResolver.connect(deployAdmin).setAddress( - rootDomainHash, - deployAdmin.address - ) - ).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR); - - await expect( - znsL1.subRegistrar.connect(deployAdmin).setDistributionConfigForDomain( - rootDomainHash, - { - ...distrConfigEmpty, - accessType: AccessType.OPEN, + [ + { + name: "Root Domain", + parentHash: hre.ethers.ZeroHash, + label: rootDomainLabel, + subdomainChildLabel: "rootsub", + }, + { + name: "Subdomain", + parentHash: undefined, + label: subdomainLabel, + subdomainChildLabel: "subsub", + }, + ].forEach( + ({ + name, + parentHash, + label, + subdomainChildLabel, + } : { + name : string; + parentHash : string | undefined; + label : string; + subdomainChildLabel : string; + }) => { + let domainHash : string; + + describe(`${name} Bridging`, () => { + before(async () => { + if (name === "Subdomain") { + // register root regularly on L1 first + parentHash = await registrationWithSetup({ + zns: znsL1, + // TODO multi: convert this test to use different user from the deployAdmin !!! + user: deployAdmin, + domainLabel: subParentLabel, + fullConfig: { + distrConfig: { + accessType: AccessType.OPEN, + paymentType: PaymentType.DIRECT, + pricerContract: znsL1.fixedPricer.target, + }, + paymentConfig: { + token: znsL1.meowToken.target, + beneficiary: deployAdmin.address, + }, + priceConfig: { + price: 1237n, + feePercentage: 0n, + }, + }, + }); } - ) - ).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR); - - // can't Revoke or Reclaim domain - await expect( - znsL1.rootRegistrar.connect(deployAdmin).revokeDomain(rootDomainHash) - ).to.be.revertedWithCustomError(znsL1.rootRegistrar, NOT_OWNER_OF_ERR); - await expect( - znsL1.rootRegistrar.connect(deployAdmin).reclaimDomain(rootDomainHash) - ).to.be.revertedWithCustomError(znsL1.rootRegistrar, NOT_OWNER_OF_ERR); - }); - - it("should NOT allow registration of subdomains", async () => { - // make sure no one can register subdomains - await expect( - registrationWithSetup({ - zns: znsL1, - user: deployAdmin, - parentHash: rootDomainHash, - domainLabel: "test", - fullConfig: fullDistrConfigEmpty, - }) - ).to.be.revertedWithCustomError(znsL1.subRegistrar, DISTRIBUTION_LOCKED_NOT_EXIST_ERR); - }); - }); - - describe("Claim Bridged Domain on L2", () => { - const dummySmtProof = Array.from({ length: 32 }, () => hre.ethers.randomBytes(32)); - - it("should #claimMessage() on the bridge successfully and fire a ClaimEvent", async () => { - // call Polygon Zk Evm Bridge to claimMessage - await znsL2.bridgeL2.connect(deployAdmin).claimMessage( - dummySmtProof, - dummySmtProof, - bridgedEventData.globalIndex, - dummySmtProof[0], - dummySmtProof[1], - bridgedEventData.originNetwork, - bridgedEventData.originAddress, - bridgedEventData.destinationNetwork, - bridgedEventData.destinationAddress, - bridgedEventData.amount, - bridgedEventData.metadata, - ); - - const [event] = await getEvents({ - contract: znsL2.bridgeL2, - eventName: "ClaimEvent", - }); - expect(event.args.originNetwork).to.equal(NETWORK_ID_L1_DEFAULT); - expect(event.args.originAddress).to.equal(znsL1.polyPortal.target); - expect(event.args.destinationAddress).to.equal(znsL2.ethPortal.target); - expect(event.args.amount).to.equal(0n); - }); - - it("should register domain on L2, set owners as original L1 caller and fire DomainClaimed event", async () => { - // check if domain is registered on L2 - // check events - const [event] = await getEvents({ - contract: znsL2.ethPortal, - eventName: "DomainClaimed", + // register and bridge + await znsL1.polyPortal.connect(deployAdmin).registerAndBridgeDomain( + parentHash as string, + label, + DEFAULT_TOKEN_URI, + ); + + domainHash = await getDomainHashFromEvent({ + zns: znsL1, + registrantAddress: znsL1.polyPortal.target as string, + }); + }); + + describe("Bridge and Register on L1", () => { + // eslint-disable-next-line max-len + it("should register and set owners as ZkEvmPortal and fire DomainBridged and BridgeEvent events", async () => { + // check if domain is registered on L1 + // check events + const events = await getEvents({ + contract: znsL1.polyPortal, + eventName: "DomainBridged", + }); + const event = events[events.length - 1]; + expect(event.args.domainHash).to.equal(domainHash); + expect(event.args.destNetworkId).to.equal(666n); + expect(event.args.destPortalAddress).to.equal(znsL2.ethPortal.target); + expect(event.args.domainOwner).to.equal(deployAdmin.address); + + // TODO multi: test these values !!! + const bridgeEvents = await getEvents({ + contract: znsL1.bridgeL1, + eventName: "BridgeEvent", + }); + ({ args: bridgedEventData } = bridgeEvents[bridgeEvents.length - 1]); + + // check owner and resolver are set properly + const { + owner: ownerL1, + resolver: resolverL1, + } = await znsL1.registry.getDomainRecord(domainHash); + expect(ownerL1).to.equal(znsL1.polyPortal.target); + // TODO multi: unblock below code when logic added to contract + // expect(resolverL1).to.equal(chainResolver.target); + + const tokenOwner = await znsL1.domainToken.ownerOf(BigInt(domainHash)); + expect(tokenOwner).to.equal(znsL1.polyPortal.target); + }); + + it("should set configs as empty", async () => { + // should be LOCKED with no configs + const distrConfig = await znsL1.subRegistrar.distrConfigs(domainHash); + expect(distrConfig.accessType).to.equal(AccessType.LOCKED); + expect(distrConfig.paymentType).to.equal(PaymentType.DIRECT); + expect(distrConfig.pricerContract).to.equal(hre.ethers.ZeroAddress); + + const paymentConfig = await znsL1.treasury.paymentConfigs(domainHash); + expect(paymentConfig.token).to.equal(hre.ethers.ZeroAddress); + expect(paymentConfig.beneficiary).to.equal(hre.ethers.ZeroAddress); + }); + + it("should properly set data in ChainResolver", async () => { + // TODO multi: unblock below code when logic added to contract + // check resolver data + // const resolverData = await chainResolver.resolveChainDataStruct(chainDomainHash); + // expect(resolverData.chainId).to.equal(chainId); + // expect(resolverData.chainName).to.equal(chainName); + // expect(resolverData.znsRegistryOnChain).to.equal(znsRegistryOnChain); + // expect(resolverData.auxData).to.equal(auxData); + }); + + it("should NOT allow owner to access any domain functions after bridge", async () => { + // make sure NO domain related functions are available to the domain creator now + await expect( + znsL1.registry.connect(deployAdmin).updateDomainOwner( + domainHash, + deployAdmin.address + ) + ).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR); + + await expect( + znsL1.addressResolver.connect(deployAdmin).setAddress( + domainHash, + deployAdmin.address + ) + ).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR); + + await expect( + znsL1.subRegistrar.connect(deployAdmin).setDistributionConfigForDomain( + domainHash, + { + ...distrConfigEmpty, + accessType: AccessType.OPEN, + } + ) + ).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR); + + // can't Revoke or Reclaim domain + await expect( + znsL1.rootRegistrar.connect(deployAdmin).revokeDomain(domainHash) + ).to.be.revertedWithCustomError(znsL1.rootRegistrar, NOT_OWNER_OF_ERR); + + await expect( + znsL1.rootRegistrar.connect(deployAdmin).reclaimDomain(domainHash) + ).to.be.revertedWithCustomError(znsL1.rootRegistrar, NOT_OWNER_OF_ERR); + }); + + it("should NOT allow registration of subdomains", async () => { + // make sure no one can register subdomains + await expect( + registrationWithSetup({ + zns: znsL1, + user: deployAdmin, + parentHash: domainHash, + domainLabel: "test", + fullConfig: fullDistrConfigEmpty, + }) + ).to.be.revertedWithCustomError(znsL1.subRegistrar, DISTRIBUTION_LOCKED_NOT_EXIST_ERR); + }); + }); + + describe("Claim Bridged Domain on L2", () => { + const dummySmtProof = Array.from({ length: 32 }, () => hre.ethers.randomBytes(32)); + + it("should #claimMessage() on the bridge successfully and fire a ClaimEvent", async () => { + // await znsL2.ethPortal.onMessageReceived( + // bridgedEventData.originAddress, + // bridgedEventData.originNetwork, + // bridgedEventData.metadata, + // ); + // call Polygon Zk Evm Bridge to claimMessage + await znsL2.bridgeL2.connect(deployAdmin).claimMessage( + dummySmtProof, + dummySmtProof, + bridgedEventData.globalIndex, + dummySmtProof[0], + dummySmtProof[1], + bridgedEventData.originNetwork, + bridgedEventData.originAddress, + bridgedEventData.destinationNetwork, + bridgedEventData.destinationAddress, + bridgedEventData.amount, + bridgedEventData.metadata, + ); + + const events = await getEvents({ + contract: znsL2.bridgeL2, + eventName: "ClaimEvent", + }); + const event = events[events.length - 1]; + expect(event.args.originNetwork).to.equal(NETWORK_ID_L1_DEFAULT); + expect(event.args.originAddress).to.equal(znsL1.polyPortal.target); + expect(event.args.destinationAddress).to.equal(znsL2.ethPortal.target); + expect(event.args.amount).to.equal(0n); + }); + + // eslint-disable-next-line max-len + it("should register domain on L2, set owners as original L1 caller and fire DomainClaimed event", async () => { + // check if domain is registered on L2 + // check events + const events = await getEvents({ + contract: znsL2.ethPortal, + eventName: "DomainClaimed", + }); + const event = events[events.length - 1]; + expect(event.args.srcNetworkId).to.equal(NETWORK_ID_L1_DEFAULT); + expect(event.args.srcPortalAddress).to.equal(znsL1.polyPortal.target); + expect(event.args.domainHash).to.equal(domainHash); + expect(event.args.domainOwner).to.equal(deployAdmin.address); + + // check owner and resolver are set properly + const { + owner: ownerL2, + resolver: resolverL2, + } = await znsL2.registry.getDomainRecord(domainHash); + expect(ownerL2).to.equal(deployAdmin.address); + // TODO multi: unblock below code when logic added to contract + // expect(resolverL2).to.equal(chainResolver.target); + + const tokenOwner = await znsL2.domainToken.ownerOf(BigInt(domainHash)); + expect(tokenOwner).to.equal(deployAdmin.address); + }); + + it("should set configs as empty and allow original caller to set these configs", async () => { + // should be LOCKED with no configs + const distrConfig = await znsL2.subRegistrar.distrConfigs(domainHash); + expect(distrConfig.accessType).to.equal(AccessType.LOCKED); + expect(distrConfig.paymentType).to.equal(PaymentType.DIRECT); + expect(distrConfig.pricerContract).to.equal(hre.ethers.ZeroAddress); + + const paymentConfig = await znsL2.treasury.paymentConfigs(domainHash); + expect(paymentConfig.token).to.equal(hre.ethers.ZeroAddress); + expect(paymentConfig.beneficiary).to.equal(hre.ethers.ZeroAddress); + + // set configs + const distrConfigToSet = { + accessType: AccessType.OPEN, + paymentType: PaymentType.DIRECT, + pricerContract: znsL2.fixedPricer.target, + }; + await znsL2.subRegistrar.connect(deployAdmin).setDistributionConfigForDomain( + domainHash, + distrConfigToSet, + ); + + const paymentConfigToSet = { + token: znsL2.meowToken.target, + beneficiary: deployAdmin.address, + }; + await znsL2.treasury.connect(deployAdmin).setPaymentConfig( + domainHash, + paymentConfigToSet, + ); + + const priceToSet = 100n; + await znsL2.fixedPricer.setPrice(domainHash, priceToSet); + + // check configs are set properly + const distrConfigAfter = await znsL2.subRegistrar.distrConfigs(domainHash); + expect(distrConfigAfter.accessType).to.equal(distrConfigToSet.accessType); + expect(distrConfigAfter.paymentType).to.equal(distrConfigToSet.paymentType); + expect(distrConfigAfter.pricerContract).to.equal(distrConfigToSet.pricerContract); + + const paymentConfigAfter = await znsL2.treasury.paymentConfigs(domainHash); + expect(paymentConfigAfter.token).to.equal(paymentConfigToSet.token); + expect(paymentConfigAfter.beneficiary).to.equal(paymentConfigToSet.beneficiary); + + const priceAfter = await znsL2.fixedPricer.getPrice(domainHash, "test", true); + expect(priceAfter).to.equal(priceToSet); + }); + + it("should allow creating subdomains under the rules of newly set configs", async () => { + await znsL2.meowToken.mint(user.address, 1000000000000000000000n); + await znsL2.meowToken.connect(user).approve(znsL2.treasury.target, ethers.MaxUint256); + + // make sure subdomains can be registered now + const subdomainHash = await registrationWithSetup({ + zns: znsL2, + user, + parentHash: domainHash, + domainLabel: subdomainChildLabel, + fullConfig: fullDistrConfigEmpty, + }); + + const events = await getEvents({ + contract: znsL2.rootRegistrar, + eventName: "DomainRegistered", + }); + const event = events[events.length - 1]; + expect(event.args.parentHash).to.equal(domainHash); + expect(event.args.domainHash).to.equal(subdomainHash); + expect(event.args.label).to.equal(subdomainChildLabel); + expect(event.args.tokenURI).to.equal(DEFAULT_TOKEN_URI); + expect(event.args.registrant).to.equal(user.address); + expect(event.args.domainAddress).to.equal(user.address); + + // check if subdomain is registered + const record = await znsL2.registry.getDomainRecord(subdomainHash); + expect(record.owner).to.equal(user.address); + expect(record.resolver).to.equal(znsL2.addressResolver.target); + + const tokenOwner = await znsL2.domainToken.ownerOf(BigInt(subdomainHash)); + expect(tokenOwner).to.equal(user.address); + }); + }); }); - expect(event.args.srcNetworkId).to.equal(NETWORK_ID_L1_DEFAULT); - expect(event.args.srcPortalAddress).to.equal(znsL1.polyPortal.target); - expect(event.args.domainHash).to.equal(rootDomainHash); - expect(event.args.domainOwner).to.equal(deployAdmin.address); - - // check owner and resolver are set properly - const { - owner: ownerL2, - resolver: resolverL2, - } = await znsL2.registry.getDomainRecord(rootDomainHash); - expect(ownerL2).to.equal(deployAdmin.address); - // TODO multi: unblock below code when logic added to contract - // expect(resolverL2).to.equal(chainResolver.target); - - const tokenOwner = await znsL2.domainToken.ownerOf(BigInt(rootDomainHash)); - expect(tokenOwner).to.equal(deployAdmin.address); }); - - it("should set configs as empty and allow original caller to set these configs", async () => { - // should be LOCKED with no configs - const distrConfig = await znsL2.subRegistrar.distrConfigs(rootDomainHash); - expect(distrConfig.accessType).to.equal(AccessType.LOCKED); - expect(distrConfig.paymentType).to.equal(PaymentType.DIRECT); - expect(distrConfig.pricerContract).to.equal(hre.ethers.ZeroAddress); - - const paymentConfig = await znsL2.treasury.paymentConfigs(rootDomainHash); - expect(paymentConfig.token).to.equal(hre.ethers.ZeroAddress); - expect(paymentConfig.beneficiary).to.equal(hre.ethers.ZeroAddress); - - // set configs - const distrConfigToSet = { - accessType: AccessType.OPEN, - paymentType: PaymentType.DIRECT, - pricerContract: znsL2.fixedPricer.target, - }; - await znsL2.subRegistrar.connect(deployAdmin).setDistributionConfigForDomain( - rootDomainHash, - distrConfigToSet, - ); - - const paymentConfigToSet = { - token: znsL2.meowToken.target, - beneficiary: deployAdmin.address, - }; - await znsL2.treasury.connect(deployAdmin).setPaymentConfig( - rootDomainHash, - paymentConfigToSet, - ); - - const priceToSet = 100n; - await znsL2.fixedPricer.setPrice(rootDomainHash, priceToSet); - - // check configs are set properly - const distrConfigAfter = await znsL2.subRegistrar.distrConfigs(rootDomainHash); - expect(distrConfigAfter.accessType).to.equal(distrConfigToSet.accessType); - expect(distrConfigAfter.paymentType).to.equal(distrConfigToSet.paymentType); - expect(distrConfigAfter.pricerContract).to.equal(distrConfigToSet.pricerContract); - - const paymentConfigAfter = await znsL2.treasury.paymentConfigs(rootDomainHash); - expect(paymentConfigAfter.token).to.equal(paymentConfigToSet.token); - expect(paymentConfigAfter.beneficiary).to.equal(paymentConfigToSet.beneficiary); - - const priceAfter = await znsL2.fixedPricer.getPrice(rootDomainHash, "test", true); - expect(priceAfter).to.equal(priceToSet); - }); - - it("should allow creating subdomains under the rules of newly set configs", async () => { - const subDomainLabel = "test"; - // make sure subdomains can be registered now - const subdomainHash = await registrationWithSetup({ - zns: znsL2, - user: deployAdmin, - parentHash: rootDomainHash, - domainLabel: subDomainLabel, - fullConfig: fullDistrConfigEmpty, - domainContent: deployAdmin.address, - }); - - const [ , event ] = await getEvents({ - contract: znsL2.rootRegistrar, - eventName: "DomainRegistered", - }); - expect(event.args.parentHash).to.equal(rootDomainHash); - expect(event.args.domainHash).to.equal(subdomainHash); - expect(event.args.label).to.equal(subDomainLabel); - expect(event.args.tokenURI).to.equal(DEFAULT_TOKEN_URI); - expect(event.args.registrant).to.equal(deployAdmin.address); - expect(event.args.domainAddress).to.equal(deployAdmin.address); - - // check if subdomain is registered - const record = await znsL2.registry.getDomainRecord(subdomainHash); - expect(record.owner).to.equal(deployAdmin.address); - expect(record.resolver).to.equal(znsL2.addressResolver.target); - - const tokenOwner = await znsL2.domainToken.ownerOf(BigInt(subdomainHash)); - expect(tokenOwner).to.equal(deployAdmin.address); - }); - }); }); diff --git a/test/helpers/types.ts b/test/helpers/types.ts index 49b03016a..a825824a6 100644 --- a/test/helpers/types.ts +++ b/test/helpers/types.ts @@ -28,6 +28,7 @@ import { } from "../../typechain"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { ICurvePriceConfig } from "../../src/deploy/missions/types"; +import { Addressable } from "ethers"; export type Maybe = T | undefined; @@ -102,13 +103,13 @@ export interface DeployZNSParams { } export interface IDistributionConfig { - pricerContract : string; + pricerContract : string | Addressable; paymentType : bigint; accessType : bigint; } export interface IPaymentConfig { - token : string; + token : string | Addressable; beneficiary : string; } From a356b88c2296e65872b8bd4682f690eed44c6854 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 10 Oct 2024 18:58:38 -0700 Subject: [PATCH 046/124] add base logic for ChainResolver data and unblock the test --- .../cross-chain/ZNSPolygonZkEvmPortal.sol | 47 +++++++++++++++---- contracts/resolver/ZNSChainResolver.sol | 1 + test/L2-BRIDGE-TEST/MultiZNS.test.ts | 36 +++++++++----- 3 files changed, 62 insertions(+), 22 deletions(-) diff --git a/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol b/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol index 1ec3336cf..562bdfa37 100644 --- a/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol +++ b/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol @@ -14,6 +14,7 @@ import { IZNSPricer } from "../types/IZNSPricer.sol"; import { IZNSTreasury } from "../treasury/IZNSTreasury.sol"; import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; import { RegistrationProof } from "../types/CrossChainTypes.sol"; +import { IZNSChainResolver } from "../resolver/IZNSChainResolver.sol"; // TODO multi: should this be ZChainPortal as in chain specific contract? @@ -29,6 +30,13 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut ); event L1PortalAddressSet(address newAddress); + struct DomainData { + bytes32 domainHash; + uint256 price; + uint256 protocolFee; + uint256 totalCost; + } + // *--| Cross-chain Data |--* IPolygonZkEVMBridgeV2 public polygonZkEVMBridge; // Destination chain (L2) @@ -40,6 +48,7 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut IZNSRootRegistrar public rootRegistrar; IZNSSubRegistrar public subRegistrar; IZNSTreasury public treasury; + IZNSChainResolver public chainResolver; IZNSRegistry public registry; /// @custom:oz-upgrades-unsafe-allow constructor @@ -54,6 +63,7 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut IZNSRootRegistrar rootRegistrar_, IZNSSubRegistrar subRegistrar_, IZNSTreasury treasury_, + IZNSChainResolver chainResolver_, IZNSRegistry registry_ ) external initializer { _setAccessController(accessController_); @@ -63,6 +73,7 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut || address(rootRegistrar_) == address(0) || address(subRegistrar_) == address(0) || address(treasury_) == address(0) + || address(chainResolver_) == address(0) || address(registry_) == address(0) ) revert ZeroAddressPassed(); @@ -71,13 +82,17 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut rootRegistrar = rootRegistrar_; subRegistrar = subRegistrar_; treasury = treasury_; + chainResolver = chainResolver_; registry = registry_; } function registerAndBridgeDomain( bytes32 parentHash, string calldata label, - string calldata tokenURI + string calldata tokenURI, + uint32 destinationChainId, + // TODO multi: do we actually have to pass it here ?? do we support 1 chain in this portal only ??? + string calldata destinationChainName // bool forceUpdateGlobalExitRoot - do we need to pass this ??? ) external { DistributionConfig memory emptyDistrConfig; @@ -86,20 +101,23 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut // TODO multi: do we actually want to stake on BOTH sides? What other payment option can we do ???!!! // TODO multi: if we leave this option (stake as Portal address) this needs to be optimized!!! // take payment to this contract so it can register - (uint256 domainPrice, uint256 protocolFee) = rootRegistrar.rootPricer().getPriceAndFee( + + // TODO multi: optimize this and make it better to not use this struct possibly !! + DomainData memory domainData; + + (domainData.price, domainData.protocolFee) = rootRegistrar.rootPricer().getPriceAndFee( 0x0, label, true ); - uint256 totalCost = domainPrice + protocolFee; + domainData.totalCost = domainData.price + domainData.protocolFee; ( IERC20 paymentToken, ) = treasury.paymentConfigs(0x0); - paymentToken.transferFrom(msg.sender, address(this), totalCost); - paymentToken.approve(address(treasury), totalCost); + paymentToken.transferFrom(msg.sender, address(this), domainData.totalCost); + paymentToken.approve(address(treasury), domainData.totalCost); // Register domain - bytes32 domainHash; if (parentHash == bytes32(0)) { // 0x0 parent for root domains - domainHash = rootRegistrar.registerRootDomain( + domainData.domainHash = rootRegistrar.registerRootDomain( label, address(0), tokenURI, @@ -107,7 +125,7 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut emptyPaymentConfig ); } else { - domainHash = subRegistrar.registerSubdomain( + domainData.domainHash = subRegistrar.registerSubdomain( parentHash, label, address(0), @@ -122,11 +140,20 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut // set owner as ZNSRegistry on this network // registry.updateDomainOwner(domainHash, address(registry)); - // TODO multi: ADD write record to ChainResolver here !!! + // TODO multi: analyze how to make these strings better !!! + registry.updateDomainResolver(domainData.domainHash, "chain"); + // TODO multi: iron out what should go to ChainResolver data !!! + chainResolver.setChainData( + domainData.domainHash, + destinationChainId, + destinationChainName, + address(0), + "" + ); // Bridge domain _bridgeDomain( - domainHash, + domainData.domainHash, parentHash, label, tokenURI diff --git a/contracts/resolver/ZNSChainResolver.sol b/contracts/resolver/ZNSChainResolver.sol index 5ea781786..6dc95da85 100644 --- a/contracts/resolver/ZNSChainResolver.sol +++ b/contracts/resolver/ZNSChainResolver.sol @@ -43,6 +43,7 @@ contract ZNSChainResolver is return chainData[domainHash]; } + // TODO multi: make this better !!! function setChainData( bytes32 domainHash, uint32 chainID, diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts index b05e6dd65..e04596f6e 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -10,7 +10,7 @@ import { DISTRIBUTION_LOCKED_NOT_EXIST_ERR, fullDistrConfigEmpty, NOT_AUTHORIZED_ERR, - NOT_OWNER_OF_ERR, paymentConfigEmpty, PaymentType, REGISTRAR_ROLE, + NOT_OWNER_OF_ERR, PaymentType, REGISTRAR_ROLE, } from "../helpers"; import { expect } from "chai"; import * as ethers from "ethers"; @@ -23,6 +23,7 @@ import { ZNSPolygonZkEvmPortal__factory, } from "../../typechain"; import { getDomainHashFromEvent, getEvents } from "../helpers/events"; +import { AddressLike, ContractTransactionReceipt } from "ethers"; // TODO multi: move below code to appropriate places @@ -41,6 +42,7 @@ export const NETWORK_ID_L2_DEFAULT = 666n; export const deployCrossChainContracts = async ({ deployer, znsL1, + chainResolverAddressL1, znsL2, networkIdL1 = NETWORK_ID_L1_DEFAULT, networkIdL2 = NETWORK_ID_L2_DEFAULT, @@ -48,6 +50,7 @@ export const deployCrossChainContracts = async ({ } : { deployer : SignerWithAddress; znsL1 : IZNSContracts; + chainResolverAddressL1 : AddressLike; znsL2 : IZNSContracts; networkIdL1 ?: bigint; networkIdL2 ?: bigint; @@ -77,6 +80,7 @@ export const deployCrossChainContracts = async ({ znsL1.rootRegistrar.target, znsL1.subRegistrar.target, znsL1.treasury.target, + chainResolverAddressL1, znsL1.registry.target, ], { @@ -132,6 +136,9 @@ describe.only("MultiZNS", () => { const subdomainLabel = "beaubridges"; const subParentLabel = "bridges"; + const zChainID = 336699n; + const zChainName = "ZChain"; + let rootDomainHash : string; let bridgedEventData : { @@ -173,6 +180,9 @@ describe.only("MultiZNS", () => { ) as unknown as ZNSChainResolver; await chainResolver.waitForDeployment(); + // TODO multi: add constants/enums for Resolver Types and possibly to Registry as well !!! + await znsL1.registry.connect(deployAdmin).addResolverType("chain", chainResolver.target); + config = await getConfig({ deployer: deployAdmin, zeroVaultAddress: deployAdmin.address, @@ -194,6 +204,7 @@ describe.only("MultiZNS", () => { } = await deployCrossChainContracts({ deployer: deployAdmin, znsL1, + chainResolverAddressL1: chainResolver.target, znsL2, }); @@ -269,11 +280,15 @@ describe.only("MultiZNS", () => { } // register and bridge - await znsL1.polyPortal.connect(deployAdmin).registerAndBridgeDomain( + const tx = await znsL1.polyPortal.connect(deployAdmin).registerAndBridgeDomain( parentHash as string, label, DEFAULT_TOKEN_URI, + zChainID, + zChainName, ); + const receipt = await tx.wait() as ContractTransactionReceipt; + console.log(`Gas used for ${name} bridging: ${receipt.gasUsed.toString()}`); domainHash = await getDomainHashFromEvent({ zns: znsL1, @@ -283,7 +298,7 @@ describe.only("MultiZNS", () => { describe("Bridge and Register on L1", () => { // eslint-disable-next-line max-len - it("should register and set owners as ZkEvmPortal and fire DomainBridged and BridgeEvent events", async () => { + it("should register and set owners as ZkEvmPortal and fire DomainBridged and BridgeEvent events", async () => { // check if domain is registered on L1 // check events const events = await getEvents({ @@ -309,8 +324,7 @@ describe.only("MultiZNS", () => { resolver: resolverL1, } = await znsL1.registry.getDomainRecord(domainHash); expect(ownerL1).to.equal(znsL1.polyPortal.target); - // TODO multi: unblock below code when logic added to contract - // expect(resolverL1).to.equal(chainResolver.target); + expect(resolverL1).to.equal(chainResolver.target); const tokenOwner = await znsL1.domainToken.ownerOf(BigInt(domainHash)); expect(tokenOwner).to.equal(znsL1.polyPortal.target); @@ -329,13 +343,11 @@ describe.only("MultiZNS", () => { }); it("should properly set data in ChainResolver", async () => { - // TODO multi: unblock below code when logic added to contract - // check resolver data - // const resolverData = await chainResolver.resolveChainDataStruct(chainDomainHash); - // expect(resolverData.chainId).to.equal(chainId); - // expect(resolverData.chainName).to.equal(chainName); - // expect(resolverData.znsRegistryOnChain).to.equal(znsRegistryOnChain); - // expect(resolverData.auxData).to.equal(auxData); + const chainData = await chainResolver.resolveChainDataStruct(domainHash); + expect(chainData.chainId).to.equal(zChainID); + expect(chainData.chainName).to.equal(zChainName); + expect(chainData.znsRegistryOnChain).to.equal(hre.ethers.ZeroAddress); + expect(chainData.auxData).to.equal(""); }); it("should NOT allow owner to access any domain functions after bridge", async () => { From d01e2c78d84cd55da616d1372a88b604ad15c818 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Fri, 11 Oct 2024 12:55:52 -0700 Subject: [PATCH 047/124] create interfaces for both portals --- contracts/cross-chain/IZNSEthereumPortal.sol | 58 ++++++++++++++ .../cross-chain/IZNSPolygonZkEvmPortal.sol | 75 +++++++++++++++++++ contracts/cross-chain/ZNSEthereumPortal.sol | 24 ++---- .../cross-chain/ZNSPolygonZkEvmPortal.sol | 73 +++++++----------- 4 files changed, 167 insertions(+), 63 deletions(-) create mode 100644 contracts/cross-chain/IZNSEthereumPortal.sol create mode 100644 contracts/cross-chain/IZNSPolygonZkEvmPortal.sol diff --git a/contracts/cross-chain/IZNSEthereumPortal.sol b/contracts/cross-chain/IZNSEthereumPortal.sol new file mode 100644 index 000000000..9dccd4adb --- /dev/null +++ b/contracts/cross-chain/IZNSEthereumPortal.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { IDistributionConfig } from "../types/IDistributionConfig.sol"; +import { IBridgeMessageReceiver } from "@zero-tech/zkevm-contracts/contracts/interfaces/IBridgeMessageReceiver.sol"; +import { IPolygonZkEVMBridgeV2Ext } from "./IPolygonZkEVMBridgeV2Ext.sol"; +import { IZNSRootRegistrar } from "../registrar/IZNSRootRegistrar.sol"; +import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; +import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; +import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; + + +interface IZNSEthereumPortal is IDistributionConfig, IBridgeMessageReceiver { + event DomainClaimed( + uint32 indexed srcNetworkId, + address srcPortalAddress, + bytes32 indexed domainHash, + address indexed domainOwner + ); + event L2PortalAddressSet(address newAddress); + + // TODO multi: can this be better and have smth like NotPolygonBridge ??? + error CalledByInvalidContract(address caller); + error DomainHashDoesNotMatchBridged(bytes32 bridgedHashL1, bytes32 generatedHashL2); + + function polygonZkEVMBridge() external view returns (IPolygonZkEVMBridgeV2Ext); + + function networkId() external view returns (uint32); + + function znsZkEvmPortalL1() external view returns (address); + + function rootRegistrar() external view returns (IZNSRootRegistrar); + + function subRegistrar() external view returns (IZNSSubRegistrar); + + function domainToken() external view returns (IZNSDomainToken); + + function registry() external view returns (IZNSRegistry); + + function initialize( + address accessController_, + IPolygonZkEVMBridgeV2Ext zkEvmBridge_, + address znsZkEvmPortalL1_, + IZNSRootRegistrar rootRegistrar_, + IZNSSubRegistrar subRegistrar_, + IZNSDomainToken domainToken_, + IZNSRegistry registry_ + ) external; + + function setL2PortalAddress(address newAddress) external; + + function onERC721Received( + address, + address, + uint256, + bytes calldata + ) external pure returns (bytes4); +} diff --git a/contracts/cross-chain/IZNSPolygonZkEvmPortal.sol b/contracts/cross-chain/IZNSPolygonZkEvmPortal.sol new file mode 100644 index 000000000..5611f751c --- /dev/null +++ b/contracts/cross-chain/IZNSPolygonZkEvmPortal.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { IPolygonZkEVMBridgeV2 } from "@zero-tech/zkevm-contracts/contracts/v2/interfaces/IPolygonZkEVMBridgeV2.sol"; +import { IDistributionConfig } from "../types/IDistributionConfig.sol"; +import { IZNSRootRegistrar } from "../registrar/IZNSRootRegistrar.sol"; +import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; +import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; +import { IZNSTreasury } from "../treasury/IZNSTreasury.sol"; +import { IZNSChainResolver } from "../resolver/IZNSChainResolver.sol"; + + +interface IZNSPolygonZkEvmPortal is IDistributionConfig { + + event DomainBridged( + uint32 indexed destNetworkId, + address destPortalAddress, + bytes32 indexed domainHash, + address indexed domainOwner + ); + event L1PortalAddressSet(address newAddress); + + struct DomainData { + bytes32 domainHash; + uint256 price; + uint256 protocolFee; + uint256 totalCost; + } + + function polygonZkEVMBridge() external view returns (IPolygonZkEVMBridgeV2); + + function networkIdL2() external view returns (uint32); + + function znsEthPortalL2() external view returns (address); + + function rootRegistrar() external view returns (IZNSRootRegistrar); + + function subRegistrar() external view returns (IZNSSubRegistrar); + + function treasury() external view returns (IZNSTreasury); + + function chainResolver() external view returns (IZNSChainResolver); + + function registry() external view returns (IZNSRegistry); + + function initialize( + address accessController_, + uint32 networkIdL2_, + IPolygonZkEVMBridgeV2 zkEvmBridge_, + IZNSRootRegistrar rootRegistrar_, + IZNSSubRegistrar subRegistrar_, + IZNSTreasury treasury_, + IZNSChainResolver chainResolver_, + IZNSRegistry registry_ + ) external; + + function registerAndBridgeDomain( + bytes32 parentHash, + string calldata label, + string calldata tokenURI, + uint32 destinationChainId, + // TODO multi: do we actually have to pass it here ?? do we support 1 chain in this portal only ??? + string calldata destinationChainName +// bool forceUpdateGlobalExitRoot - do we need to pass this ??? + ) external; + + function onERC721Received( + address, + address, + uint256, + bytes calldata + ) external pure returns (bytes4); + + function setL1PortalAddress(address newAddress) external; +} diff --git a/contracts/cross-chain/ZNSEthereumPortal.sol b/contracts/cross-chain/ZNSEthereumPortal.sol index 9e228f49e..ae0e24398 100644 --- a/contracts/cross-chain/ZNSEthereumPortal.sol +++ b/contracts/cross-chain/ZNSEthereumPortal.sol @@ -3,8 +3,8 @@ pragma solidity 0.8.26; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { IBridgeMessageReceiver } from "@zero-tech/zkevm-contracts/contracts/interfaces/IBridgeMessageReceiver.sol"; import { AAccessControlled } from "../access/AAccessControlled.sol"; +import { IZNSEthereumPortal } from "./IZNSEthereumPortal.sol"; import { IPolygonZkEVMBridgeV2Ext } from "./IPolygonZkEVMBridgeV2Ext.sol"; import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; import { RegistrationProof } from "../types/CrossChainTypes.sol"; @@ -12,32 +12,20 @@ import { IZNSRootRegistrar } from "../registrar/IZNSRootRegistrar.sol"; import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; -import { IDistributionConfig } from "../types/IDistributionConfig.sol"; import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; import { IZNSPricer } from "../types/IZNSPricer.sol"; // TODO multi: could this be a better name that implies cross-chain nature ??? -contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IDistributionConfig, IBridgeMessageReceiver { - - event DomainClaimed( - uint32 indexed srcNetworkId, - address srcPortalAddress, - bytes32 indexed domainHash, - address indexed domainOwner - ); - event L2PortalAddressSet(address newAddress); - - // TODO multi: can this be better and have smth like NotPolygonBridge ??? - error CalledByInvalidContract(address caller); - error DomainHashDoesNotMatchBridged(bytes32 bridgedHashL1, bytes32 generatedHashL2); - +contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPortal { // TODO multi: check that all state vars are needed and remove redundant ones !!! // *--| Cross-chain Data |--* + // TODO multi: should we keep this exteneded interface ??? IPolygonZkEVMBridgeV2Ext public polygonZkEVMBridge; // This chain uint32 public networkId; // TODO multi: should this be an Interface Var ??? + // figure out better names for these vars !!! address public znsZkEvmPortalL1; // *--| ZNS Data for THIS chain |--* @@ -59,7 +47,7 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IDistributionC IZNSSubRegistrar subRegistrar_, IZNSDomainToken domainToken_, IZNSRegistry registry_ - ) external initializer { + ) external override initializer { _setAccessController(accessController_); if ( @@ -84,7 +72,7 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IDistributionC address originAddress, uint32 originNetwork, bytes memory data - ) external payable { + ) external payable override { if (msg.sender != address(polygonZkEVMBridge)) revert CalledByInvalidContract(msg.sender); RegistrationProof memory proof = abi.decode(data, (RegistrationProof)); diff --git a/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol b/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol index 562bdfa37..2eda629c1 100644 --- a/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol +++ b/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol @@ -1,42 +1,26 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.26; -import { IPolygonZkEVMBridgeV2 } from "@zero-tech/zkevm-contracts/contracts/v2/interfaces/IPolygonZkEVMBridgeV2.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { IPolygonZkEVMBridgeV2 } from "@zero-tech/zkevm-contracts/contracts/v2/interfaces/IPolygonZkEVMBridgeV2.sol"; import { AAccessControlled } from "../access/AAccessControlled.sol"; -import { IDistributionConfig } from "../types/IDistributionConfig.sol"; -import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; +import { IZNSPolygonZkEvmPortal } from "./IZNSPolygonZkEvmPortal.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { IZNSChainResolver } from "../resolver/IZNSChainResolver.sol"; +import { IZNSPricer } from "../types/IZNSPricer.sol"; +import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; import { IZNSRootRegistrar } from "../registrar/IZNSRootRegistrar.sol"; import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; -import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; -import { IZNSPricer } from "../types/IZNSPricer.sol"; import { IZNSTreasury } from "../treasury/IZNSTreasury.sol"; import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; import { RegistrationProof } from "../types/CrossChainTypes.sol"; -import { IZNSChainResolver } from "../resolver/IZNSChainResolver.sol"; +import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; // TODO multi: should this be ZChainPortal as in chain specific contract? // it should ideally work with any ZkEVM chain. why not? we should add networkId and other // chain specific data to as parameters to some functions ??? -contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistributionConfig { - - event DomainBridged( - uint32 indexed destNetworkId, - address destPortalAddress, - bytes32 indexed domainHash, - address indexed domainOwner - ); - event L1PortalAddressSet(address newAddress); - - struct DomainData { - bytes32 domainHash; - uint256 price; - uint256 protocolFee; - uint256 totalCost; - } - +contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IZNSPolygonZkEvmPortal { // *--| Cross-chain Data |--* IPolygonZkEVMBridgeV2 public polygonZkEVMBridge; // Destination chain (L2) @@ -65,7 +49,7 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut IZNSTreasury treasury_, IZNSChainResolver chainResolver_, IZNSRegistry registry_ - ) external initializer { + ) external override initializer { _setAccessController(accessController_); if ( @@ -94,7 +78,7 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut // TODO multi: do we actually have to pass it here ?? do we support 1 chain in this portal only ??? string calldata destinationChainName // bool forceUpdateGlobalExitRoot - do we need to pass this ??? - ) external { + ) external override { DistributionConfig memory emptyDistrConfig; PaymentConfig memory emptyPaymentConfig; @@ -160,7 +144,23 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut ); } - // TODO multi: move this lower in the contract + function onERC721Received( + address, + address, + uint256, + bytes calldata + ) external pure override returns (bytes4) { + return this.onERC721Received.selector; + } + + function setL1PortalAddress(address newAddress) external override onlyAdmin { + if (newAddress == address(0)) revert ZeroAddressPassed(); + + znsEthPortalL2 = newAddress; + + emit L1PortalAddressSet(newAddress); + } + function _bridgeDomain( bytes32 domainHash, bytes32 parentHash, @@ -180,7 +180,7 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut bytes memory encodedProof = abi.encode(proof); polygonZkEVMBridge.bridgeMessage( - // TODO multi: should this be a parameter to the registerAndBridgeDomain function to work on any chain ??? + // TODO multi: should this be a parameter to the registerAndBridgeDomain function to work on any chain ??? networkIdL2, znsEthPortalL2, // TODO multi: figure out what this is and how to better pass it !!! @@ -196,23 +196,6 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IDistribut ); } - function onERC721Received( - address, - address, - uint256, - bytes calldata - ) external pure returns (bytes4) { - return this.onERC721Received.selector; - } - - function setL1PortalAddress(address newAddress) external onlyAdmin { - if (newAddress == address(0)) revert ZeroAddressPassed(); - - znsEthPortalL2 = newAddress; - - emit L1PortalAddressSet(newAddress); - } - /** * @notice To use UUPS proxy we override this function and revert if `msg.sender` isn't authorized * @param newImplementation The implementation contract to upgrade to From d63a4a80536c8507d892d014b3a3818cec0aa19c Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 14 Oct 2024 12:53:10 -0700 Subject: [PATCH 048/124] fix payment logic in PolygonZkEvmPortal --- .../cross-chain/ZNSPolygonZkEvmPortal.sol | 73 ++++++++++++------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol b/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol index 2eda629c1..4362b987f 100644 --- a/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol +++ b/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol @@ -13,7 +13,7 @@ import { IZNSRootRegistrar } from "../registrar/IZNSRootRegistrar.sol"; import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; import { IZNSTreasury } from "../treasury/IZNSTreasury.sol"; import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; -import { RegistrationProof } from "../types/CrossChainTypes.sol"; +import { BridgedDomain } from "../types/CrossChainTypes.sol"; import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; @@ -82,26 +82,12 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IZNSPolygo DistributionConfig memory emptyDistrConfig; PaymentConfig memory emptyPaymentConfig; - // TODO multi: do we actually want to stake on BOTH sides? What other payment option can we do ???!!! - // TODO multi: if we leave this option (stake as Portal address) this needs to be optimized!!! - // take payment to this contract so it can register - - // TODO multi: optimize this and make it better to not use this struct possibly !! - DomainData memory domainData; - - (domainData.price, domainData.protocolFee) = rootRegistrar.rootPricer().getPriceAndFee( - 0x0, - label, - true - ); - domainData.totalCost = domainData.price + domainData.protocolFee; - ( IERC20 paymentToken, ) = treasury.paymentConfigs(0x0); - paymentToken.transferFrom(msg.sender, address(this), domainData.totalCost); - paymentToken.approve(address(treasury), domainData.totalCost); + _processPayment(label, parentHash); // Register domain + bytes32 domainHash; if (parentHash == bytes32(0)) { // 0x0 parent for root domains - domainData.domainHash = rootRegistrar.registerRootDomain( + domainHash = rootRegistrar.registerRootDomain( label, address(0), tokenURI, @@ -109,7 +95,7 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IZNSPolygo emptyPaymentConfig ); } else { - domainData.domainHash = subRegistrar.registerSubdomain( + domainHash = subRegistrar.registerSubdomain( parentHash, label, address(0), @@ -119,16 +105,11 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IZNSPolygo ); } - // TODO multi: should we do that or leave this Agent as the owner ??? - // DELETER registry from state if this is NOT used !!! - // set owner as ZNSRegistry on this network -// registry.updateDomainOwner(domainHash, address(registry)); - // TODO multi: analyze how to make these strings better !!! - registry.updateDomainResolver(domainData.domainHash, "chain"); + registry.updateDomainResolver(domainHash, "chain"); // TODO multi: iron out what should go to ChainResolver data !!! chainResolver.setChainData( - domainData.domainHash, + domainHash, destinationChainId, destinationChainName, address(0), @@ -137,7 +118,7 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IZNSPolygo // Bridge domain _bridgeDomain( - domainData.domainHash, + domainHash, parentHash, label, tokenURI @@ -161,6 +142,42 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IZNSPolygo emit L1PortalAddressSet(newAddress); } + function _processPayment( + string calldata label, + bytes32 parentHash + ) internal { + // TODO multi: do we actually want to stake on BOTH sides? What other payment option can we do ???!!! + // TODO multi: if we leave this option (stake as Portal address) this needs to be optimized!!! + // take payment to this contract so it can register + + uint256 price; + uint256 stakeFee; + IZNSPricer rootPricer = rootRegistrar.rootPricer(); + if (parentHash == bytes32(0)) { // Root Domains + price = rootPricer.getPrice( + parentHash, + label, + true + ); + } else { // Subdomains + (IZNSPricer pricer, PaymentType paymentType,) = subRegistrar.distrConfigs(parentHash); + (price, stakeFee) = pricer.getPriceAndFee( + parentHash, + label, + true + ); + stakeFee = paymentType == PaymentType.STAKE ? stakeFee : 0; + } + + uint256 protocolFee = rootPricer.getFeeForPrice(bytes32(0), price + stakeFee); + uint256 totalCost = price + stakeFee + protocolFee; + + ( IERC20 paymentToken, ) = treasury.paymentConfigs(parentHash); + paymentToken.transferFrom(msg.sender, address(this), totalCost); + + paymentToken.approve(address(treasury), totalCost); + } + function _bridgeDomain( bytes32 domainHash, bytes32 parentHash, @@ -169,7 +186,7 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IZNSPolygo ) internal { // Create data proof for ZNS on L2 // we are using msg.sender here because the current caller on L1 will be the owner of the bridged L2 domain - RegistrationProof memory proof = RegistrationProof({ + BridgedDomain memory proof = BridgedDomain({ domainOwner: msg.sender, domainHash: domainHash, parentHash: parentHash, From 021011b4988b6d5047840e2a42616d27444c1e14 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 14 Oct 2024 12:53:29 -0700 Subject: [PATCH 049/124] various refactorings --- contracts/cross-chain/IZNSEthereumPortal.sol | 3 ++- contracts/cross-chain/IZNSPolygonZkEvmPortal.sol | 7 ------- contracts/cross-chain/ZNSEthereumPortal.sol | 11 ++++++----- contracts/registrar/ZNSRootRegistrar.sol | 9 ++++----- contracts/registrar/ZNSSubRegistrar.sol | 1 - contracts/types/CrossChainTypes.sol | 2 +- 6 files changed, 13 insertions(+), 20 deletions(-) diff --git a/contracts/cross-chain/IZNSEthereumPortal.sol b/contracts/cross-chain/IZNSEthereumPortal.sol index 9dccd4adb..b8587568d 100644 --- a/contracts/cross-chain/IZNSEthereumPortal.sol +++ b/contracts/cross-chain/IZNSEthereumPortal.sol @@ -20,7 +20,8 @@ interface IZNSEthereumPortal is IDistributionConfig, IBridgeMessageReceiver { event L2PortalAddressSet(address newAddress); // TODO multi: can this be better and have smth like NotPolygonBridge ??? - error CalledByInvalidContract(address caller); + error InvalidCaller(address caller); + error InvalidOriginAddress(address originAddress); error DomainHashDoesNotMatchBridged(bytes32 bridgedHashL1, bytes32 generatedHashL2); function polygonZkEVMBridge() external view returns (IPolygonZkEVMBridgeV2Ext); diff --git a/contracts/cross-chain/IZNSPolygonZkEvmPortal.sol b/contracts/cross-chain/IZNSPolygonZkEvmPortal.sol index 5611f751c..8488b4b2f 100644 --- a/contracts/cross-chain/IZNSPolygonZkEvmPortal.sol +++ b/contracts/cross-chain/IZNSPolygonZkEvmPortal.sol @@ -20,13 +20,6 @@ interface IZNSPolygonZkEvmPortal is IDistributionConfig { ); event L1PortalAddressSet(address newAddress); - struct DomainData { - bytes32 domainHash; - uint256 price; - uint256 protocolFee; - uint256 totalCost; - } - function polygonZkEVMBridge() external view returns (IPolygonZkEVMBridgeV2); function networkIdL2() external view returns (uint32); diff --git a/contracts/cross-chain/ZNSEthereumPortal.sol b/contracts/cross-chain/ZNSEthereumPortal.sol index ae0e24398..9fa9863de 100644 --- a/contracts/cross-chain/ZNSEthereumPortal.sol +++ b/contracts/cross-chain/ZNSEthereumPortal.sol @@ -7,7 +7,7 @@ import { AAccessControlled } from "../access/AAccessControlled.sol"; import { IZNSEthereumPortal } from "./IZNSEthereumPortal.sol"; import { IPolygonZkEVMBridgeV2Ext } from "./IPolygonZkEVMBridgeV2Ext.sol"; import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; -import { RegistrationProof } from "../types/CrossChainTypes.sol"; +import { BridgedDomain } from "../types/CrossChainTypes.sol"; import { IZNSRootRegistrar } from "../registrar/IZNSRootRegistrar.sol"; import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; @@ -20,11 +20,11 @@ import { IZNSPricer } from "../types/IZNSPricer.sol"; contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPortal { // TODO multi: check that all state vars are needed and remove redundant ones !!! // *--| Cross-chain Data |--* - // TODO multi: should we keep this exteneded interface ??? + // TODO multi: should we keep this extended interface ??? IPolygonZkEVMBridgeV2Ext public polygonZkEVMBridge; // This chain uint32 public networkId; - // TODO multi: should this be an Interface Var ??? + // TODO multi: should this be an Interface Var ??? it is not used now (delete?) !!! // figure out better names for these vars !!! address public znsZkEvmPortalL1; @@ -73,9 +73,10 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPo uint32 originNetwork, bytes memory data ) external payable override { - if (msg.sender != address(polygonZkEVMBridge)) revert CalledByInvalidContract(msg.sender); + if (msg.sender != address(polygonZkEVMBridge)) revert InvalidCaller(msg.sender); + if (originAddress != znsZkEvmPortalL1) revert InvalidOriginAddress(originAddress); - RegistrationProof memory proof = abi.decode(data, (RegistrationProof)); + BridgedDomain memory proof = abi.decode(data, (BridgedDomain)); // Register bridged domain bytes32 domainHash; diff --git a/contracts/registrar/ZNSRootRegistrar.sol b/contracts/registrar/ZNSRootRegistrar.sol index 787e9e1b7..1b969377e 100644 --- a/contracts/registrar/ZNSRootRegistrar.sol +++ b/contracts/registrar/ZNSRootRegistrar.sol @@ -101,7 +101,7 @@ contract ZNSRootRegistrar is tokenURI, distributionConfig, paymentConfig, - true + false ); } @@ -120,7 +120,7 @@ contract ZNSRootRegistrar is tokenURI, emptyDistrConfig, emptyPaymentConfig, - false + true ); } @@ -152,8 +152,7 @@ contract ZNSRootRegistrar is string calldata tokenURI, DistributionConfig memory distributionConfig, PaymentConfig memory paymentConfig, - // TODO multi: should we change this to `isBridged` ??? - bool payForDomain + bool isBridgedDomain ) internal returns (bytes32) { // Confirms string values are only [a-z0-9-] label.validate(); @@ -165,7 +164,7 @@ contract ZNSRootRegistrar is revert DomainAlreadyExists(domainHash); // Get price for the domain - uint256 domainPrice = payForDomain ? rootPricer.getPrice(0x0, label, true) : 0; + uint256 domainPrice = !isBridgedDomain ? rootPricer.getPrice(0x0, label, true) : 0; _coreRegister( CoreRegisterArgs( diff --git a/contracts/registrar/ZNSSubRegistrar.sol b/contracts/registrar/ZNSSubRegistrar.sol index 08ee92126..d2a8bf97a 100644 --- a/contracts/registrar/ZNSSubRegistrar.sol +++ b/contracts/registrar/ZNSSubRegistrar.sol @@ -151,7 +151,6 @@ contract ZNSSubRegistrar is AAccessControlled, ARegistryWired, UUPSUpgradeable, revert DomainAlreadyExists(coreRegisterArgs.domainHash); if (!isBridgedDomain) { - // TODO multi: do we need to reassign the return to coreRegisterArgs here ??? _checkFillParentData(coreRegisterArgs); } diff --git a/contracts/types/CrossChainTypes.sol b/contracts/types/CrossChainTypes.sol index 33cd21eed..99ec5c5e6 100644 --- a/contracts/types/CrossChainTypes.sol +++ b/contracts/types/CrossChainTypes.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.26; // TODO multi: what is the best name for this ??? -struct RegistrationProof { +struct BridgedDomain { address domainOwner; bytes32 domainHash; bytes32 parentHash; From e4f37c5cdf298ddb1aaa95fa3ff873694d442521 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 14 Oct 2024 13:12:15 -0700 Subject: [PATCH 050/124] make tests better by making a 3rd party user buy subdomains in all tests and add test for balance check --- test/L2-BRIDGE-TEST/MultiZNS.test.ts | 91 +++++++++++++++------------- 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts index e04596f6e..3f7a39f16 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -5,10 +5,10 @@ import { IZNSCampaignConfig, IZNSContracts } from "../../src/deploy/campaign/typ import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { registrationWithSetup } from "../helpers/register-setup"; import { - AccessType, DEFAULT_TOKEN_URI, + AccessType, DEFAULT_PRICE_CONFIG, DEFAULT_TOKEN_URI, distrConfigEmpty, DISTRIBUTION_LOCKED_NOT_EXIST_ERR, - fullDistrConfigEmpty, + fullDistrConfigEmpty, getCurvePrice, getStakingOrProtocolFee, NOT_AUTHORIZED_ERR, NOT_OWNER_OF_ERR, PaymentType, REGISTRAR_ROLE, } from "../helpers"; @@ -129,6 +129,7 @@ describe.only("MultiZNS", () => { let deployAdmin : SignerWithAddress; let user : SignerWithAddress; + let subUser : SignerWithAddress; let config : IZNSCampaignConfig; @@ -141,6 +142,8 @@ describe.only("MultiZNS", () => { let rootDomainHash : string; + let balanceBeforeBridge : bigint; + let bridgedEventData : { leafType : bigint; originNetwork : bigint; @@ -155,7 +158,7 @@ describe.only("MultiZNS", () => { let chainResolver : ZNSChainResolver; before(async () => { - [ deployAdmin, user ] = await hre.ethers.getSigners(); + [ deployAdmin, user, subUser ] = await hre.ethers.getSigners(); config = await getConfig({ deployer: deployAdmin, @@ -223,6 +226,9 @@ describe.only("MultiZNS", () => { await znsL1.meowToken.mint(deployAdmin.address, 1000000000000000000000n); await znsL1.meowToken.connect(deployAdmin).approve(znsL1.polyPortal.target, ethers.MaxUint256); await znsL1.meowToken.connect(deployAdmin).approve(znsL1.treasury.target, ethers.MaxUint256); + + await znsL1.meowToken.mint(user.address, hre.ethers.parseEther("100000000000000")); + await znsL1.meowToken.connect(user).approve(znsL1.polyPortal.target, ethers.MaxUint256); }); [ @@ -265,22 +271,21 @@ describe.only("MultiZNS", () => { distrConfig: { accessType: AccessType.OPEN, paymentType: PaymentType.DIRECT, - pricerContract: znsL1.fixedPricer.target, + pricerContract: znsL1.curvePricer.target, }, paymentConfig: { token: znsL1.meowToken.target, beneficiary: deployAdmin.address, }, - priceConfig: { - price: 1237n, - feePercentage: 0n, - }, + priceConfig: DEFAULT_PRICE_CONFIG, }, }); } + balanceBeforeBridge = await znsL1.meowToken.balanceOf(user.address); + // register and bridge - const tx = await znsL1.polyPortal.connect(deployAdmin).registerAndBridgeDomain( + const tx = await znsL1.polyPortal.connect(user).registerAndBridgeDomain( parentHash as string, label, DEFAULT_TOKEN_URI, @@ -298,7 +303,7 @@ describe.only("MultiZNS", () => { describe("Bridge and Register on L1", () => { // eslint-disable-next-line max-len - it("should register and set owners as ZkEvmPortal and fire DomainBridged and BridgeEvent events", async () => { + it("should register and set owners as ZkEvmPortal and fire DomainBridged and BridgeEvent events", async () => { // check if domain is registered on L1 // check events const events = await getEvents({ @@ -309,7 +314,7 @@ describe.only("MultiZNS", () => { expect(event.args.domainHash).to.equal(domainHash); expect(event.args.destNetworkId).to.equal(666n); expect(event.args.destPortalAddress).to.equal(znsL2.ethPortal.target); - expect(event.args.domainOwner).to.equal(deployAdmin.address); + expect(event.args.domainOwner).to.equal(user.address); // TODO multi: test these values !!! const bridgeEvents = await getEvents({ @@ -330,6 +335,15 @@ describe.only("MultiZNS", () => { expect(tokenOwner).to.equal(znsL1.polyPortal.target); }); + it("should withdraw the correct amount of tokens from the caller", async () => { + const balanceAfterBridge = await znsL1.meowToken.balanceOf(user.address); + + const priceRef = getCurvePrice(label); + const protocolFeeRef = getStakingOrProtocolFee(priceRef); + + expect(balanceBeforeBridge - balanceAfterBridge).to.equal(priceRef + protocolFeeRef); + }); + it("should set configs as empty", async () => { // should be LOCKED with no configs const distrConfig = await znsL1.subRegistrar.distrConfigs(domainHash); @@ -353,21 +367,21 @@ describe.only("MultiZNS", () => { it("should NOT allow owner to access any domain functions after bridge", async () => { // make sure NO domain related functions are available to the domain creator now await expect( - znsL1.registry.connect(deployAdmin).updateDomainOwner( + znsL1.registry.connect(user).updateDomainOwner( domainHash, - deployAdmin.address + user.address ) ).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR); await expect( - znsL1.addressResolver.connect(deployAdmin).setAddress( + znsL1.addressResolver.connect(user).setAddress( domainHash, - deployAdmin.address + user.address ) ).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR); await expect( - znsL1.subRegistrar.connect(deployAdmin).setDistributionConfigForDomain( + znsL1.subRegistrar.connect(user).setDistributionConfigForDomain( domainHash, { ...distrConfigEmpty, @@ -378,11 +392,11 @@ describe.only("MultiZNS", () => { // can't Revoke or Reclaim domain await expect( - znsL1.rootRegistrar.connect(deployAdmin).revokeDomain(domainHash) + znsL1.rootRegistrar.connect(user).revokeDomain(domainHash) ).to.be.revertedWithCustomError(znsL1.rootRegistrar, NOT_OWNER_OF_ERR); await expect( - znsL1.rootRegistrar.connect(deployAdmin).reclaimDomain(domainHash) + znsL1.rootRegistrar.connect(user).reclaimDomain(domainHash) ).to.be.revertedWithCustomError(znsL1.rootRegistrar, NOT_OWNER_OF_ERR); }); @@ -391,7 +405,7 @@ describe.only("MultiZNS", () => { await expect( registrationWithSetup({ zns: znsL1, - user: deployAdmin, + user, parentHash: domainHash, domainLabel: "test", fullConfig: fullDistrConfigEmpty, @@ -404,13 +418,9 @@ describe.only("MultiZNS", () => { const dummySmtProof = Array.from({ length: 32 }, () => hre.ethers.randomBytes(32)); it("should #claimMessage() on the bridge successfully and fire a ClaimEvent", async () => { - // await znsL2.ethPortal.onMessageReceived( - // bridgedEventData.originAddress, - // bridgedEventData.originNetwork, - // bridgedEventData.metadata, - // ); // call Polygon Zk Evm Bridge to claimMessage - await znsL2.bridgeL2.connect(deployAdmin).claimMessage( + // TODO multi: add test to check that anyone can call this for the user !!! + await znsL2.bridgeL2.connect(user).claimMessage( dummySmtProof, dummySmtProof, bridgedEventData.globalIndex, @@ -447,19 +457,16 @@ describe.only("MultiZNS", () => { expect(event.args.srcNetworkId).to.equal(NETWORK_ID_L1_DEFAULT); expect(event.args.srcPortalAddress).to.equal(znsL1.polyPortal.target); expect(event.args.domainHash).to.equal(domainHash); - expect(event.args.domainOwner).to.equal(deployAdmin.address); + expect(event.args.domainOwner).to.equal(user.address); // check owner and resolver are set properly const { owner: ownerL2, - resolver: resolverL2, } = await znsL2.registry.getDomainRecord(domainHash); - expect(ownerL2).to.equal(deployAdmin.address); - // TODO multi: unblock below code when logic added to contract - // expect(resolverL2).to.equal(chainResolver.target); + expect(ownerL2).to.equal(user.address); const tokenOwner = await znsL2.domainToken.ownerOf(BigInt(domainHash)); - expect(tokenOwner).to.equal(deployAdmin.address); + expect(tokenOwner).to.equal(user.address); }); it("should set configs as empty and allow original caller to set these configs", async () => { @@ -479,22 +486,22 @@ describe.only("MultiZNS", () => { paymentType: PaymentType.DIRECT, pricerContract: znsL2.fixedPricer.target, }; - await znsL2.subRegistrar.connect(deployAdmin).setDistributionConfigForDomain( + await znsL2.subRegistrar.connect(user).setDistributionConfigForDomain( domainHash, distrConfigToSet, ); const paymentConfigToSet = { token: znsL2.meowToken.target, - beneficiary: deployAdmin.address, + beneficiary: user.address, }; - await znsL2.treasury.connect(deployAdmin).setPaymentConfig( + await znsL2.treasury.connect(user).setPaymentConfig( domainHash, paymentConfigToSet, ); const priceToSet = 100n; - await znsL2.fixedPricer.setPrice(domainHash, priceToSet); + await znsL2.fixedPricer.connect(user).setPrice(domainHash, priceToSet); // check configs are set properly const distrConfigAfter = await znsL2.subRegistrar.distrConfigs(domainHash); @@ -511,13 +518,13 @@ describe.only("MultiZNS", () => { }); it("should allow creating subdomains under the rules of newly set configs", async () => { - await znsL2.meowToken.mint(user.address, 1000000000000000000000n); - await znsL2.meowToken.connect(user).approve(znsL2.treasury.target, ethers.MaxUint256); + await znsL2.meowToken.mint(subUser.address, 1000000000000000000000n); + await znsL2.meowToken.connect(subUser).approve(znsL2.treasury.target, ethers.MaxUint256); // make sure subdomains can be registered now const subdomainHash = await registrationWithSetup({ zns: znsL2, - user, + user: subUser, parentHash: domainHash, domainLabel: subdomainChildLabel, fullConfig: fullDistrConfigEmpty, @@ -532,16 +539,16 @@ describe.only("MultiZNS", () => { expect(event.args.domainHash).to.equal(subdomainHash); expect(event.args.label).to.equal(subdomainChildLabel); expect(event.args.tokenURI).to.equal(DEFAULT_TOKEN_URI); - expect(event.args.registrant).to.equal(user.address); - expect(event.args.domainAddress).to.equal(user.address); + expect(event.args.registrant).to.equal(subUser.address); + expect(event.args.domainAddress).to.equal(subUser.address); // check if subdomain is registered const record = await znsL2.registry.getDomainRecord(subdomainHash); - expect(record.owner).to.equal(user.address); + expect(record.owner).to.equal(subUser.address); expect(record.resolver).to.equal(znsL2.addressResolver.target); const tokenOwner = await znsL2.domainToken.ownerOf(BigInt(subdomainHash)); - expect(tokenOwner).to.equal(user.address); + expect(tokenOwner).to.equal(subUser.address); }); }); }); From 4eecd88ce238913c038eed7d6ebb85b8f6ac2957 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 14 Oct 2024 13:49:20 -0700 Subject: [PATCH 051/124] add chainId and chainName to PolygonZkEvmPortal state, refactor it's usage, update interface --- .../cross-chain/IZNSPolygonZkEvmPortal.sol | 38 ++++++---- .../cross-chain/ZNSPolygonZkEvmPortal.sol | 70 +++++++++---------- 2 files changed, 55 insertions(+), 53 deletions(-) diff --git a/contracts/cross-chain/IZNSPolygonZkEvmPortal.sol b/contracts/cross-chain/IZNSPolygonZkEvmPortal.sol index 8488b4b2f..ef5c6a2ed 100644 --- a/contracts/cross-chain/IZNSPolygonZkEvmPortal.sol +++ b/contracts/cross-chain/IZNSPolygonZkEvmPortal.sol @@ -8,23 +8,37 @@ import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; import { IZNSTreasury } from "../treasury/IZNSTreasury.sol"; import { IZNSChainResolver } from "../resolver/IZNSChainResolver.sol"; +import { IZNSAccessController } from "../access/IZNSAccessController.sol"; interface IZNSPolygonZkEvmPortal is IDistributionConfig { + struct ZNSContractInput { + IZNSAccessController accessController; + IZNSRootRegistrar rootRegistrar; + IZNSSubRegistrar subRegistrar; + IZNSTreasury treasury; + IZNSChainResolver chainResolver; + IZNSRegistry registry; + } + event DomainBridged( uint32 indexed destNetworkId, address destPortalAddress, bytes32 indexed domainHash, address indexed domainOwner ); - event L1PortalAddressSet(address newAddress); + event DestZnsPortalSet(address newAddress); function polygonZkEVMBridge() external view returns (IPolygonZkEVMBridgeV2); - function networkIdL2() external view returns (uint32); + function destNetworkId() external view returns (uint32); + + function destChainName() external view returns (string memory); + + function destChainId() external view returns (uint256); - function znsEthPortalL2() external view returns (address); + function destZnsPortal() external view returns (address); function rootRegistrar() external view returns (IZNSRootRegistrar); @@ -37,23 +51,17 @@ interface IZNSPolygonZkEvmPortal is IDistributionConfig { function registry() external view returns (IZNSRegistry); function initialize( - address accessController_, - uint32 networkIdL2_, + uint32 destNetworkId_, + string calldata destChainName_, + uint256 destChainId_, IPolygonZkEVMBridgeV2 zkEvmBridge_, - IZNSRootRegistrar rootRegistrar_, - IZNSSubRegistrar subRegistrar_, - IZNSTreasury treasury_, - IZNSChainResolver chainResolver_, - IZNSRegistry registry_ + ZNSContractInput calldata znsContracts ) external; function registerAndBridgeDomain( bytes32 parentHash, string calldata label, - string calldata tokenURI, - uint32 destinationChainId, - // TODO multi: do we actually have to pass it here ?? do we support 1 chain in this portal only ??? - string calldata destinationChainName + string calldata tokenURI // bool forceUpdateGlobalExitRoot - do we need to pass this ??? ) external; @@ -64,5 +72,5 @@ interface IZNSPolygonZkEvmPortal is IDistributionConfig { bytes calldata ) external pure returns (bytes4); - function setL1PortalAddress(address newAddress) external; + function setDestZnsPortal(address newAddress) external; } diff --git a/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol b/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol index 4362b987f..97c93106e 100644 --- a/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol +++ b/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol @@ -17,16 +17,14 @@ import { BridgedDomain } from "../types/CrossChainTypes.sol"; import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; -// TODO multi: should this be ZChainPortal as in chain specific contract? -// it should ideally work with any ZkEVM chain. why not? we should add networkId and other -// chain specific data to as parameters to some functions ??? contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IZNSPolygonZkEvmPortal { // *--| Cross-chain Data |--* IPolygonZkEVMBridgeV2 public polygonZkEVMBridge; // Destination chain (L2) - uint32 public networkIdL2; - // TODO multi: change to interface type (possibly!) - address public znsEthPortalL2; + uint32 public destNetworkId; + string public destChainName; + uint256 public destChainId; + address public destZnsPortal; // *--| ZNS Data for THIS chain |--* IZNSRootRegistrar public rootRegistrar; @@ -41,42 +39,38 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IZNSPolygo } function initialize( - address accessController_, - uint32 networkIdL2_, + uint32 destNetworkId_, + string calldata destChainName_, + uint256 destChainId_, IPolygonZkEVMBridgeV2 zkEvmBridge_, - IZNSRootRegistrar rootRegistrar_, - IZNSSubRegistrar subRegistrar_, - IZNSTreasury treasury_, - IZNSChainResolver chainResolver_, - IZNSRegistry registry_ + ZNSContractInput calldata znsContracts ) external override initializer { - _setAccessController(accessController_); + _setAccessController(address(znsContracts.accessController)); if ( address(zkEvmBridge_) == address(0) - || address(rootRegistrar_) == address(0) - || address(subRegistrar_) == address(0) - || address(treasury_) == address(0) - || address(chainResolver_) == address(0) - || address(registry_) == address(0) + || address(znsContracts.rootRegistrar) == address(0) + || address(znsContracts.subRegistrar) == address(0) + || address(znsContracts.treasury) == address(0) + || address(znsContracts.chainResolver) == address(0) + || address(znsContracts.registry) == address(0) ) revert ZeroAddressPassed(); polygonZkEVMBridge = zkEvmBridge_; - networkIdL2 = networkIdL2_; - rootRegistrar = rootRegistrar_; - subRegistrar = subRegistrar_; - treasury = treasury_; - chainResolver = chainResolver_; - registry = registry_; + destNetworkId = destNetworkId_; + destChainName = destChainName_; + destChainId = destChainId_; + rootRegistrar = znsContracts.rootRegistrar; + subRegistrar = znsContracts.subRegistrar; + treasury = znsContracts.treasury; + chainResolver = znsContracts.chainResolver; + registry = znsContracts.registry; } function registerAndBridgeDomain( bytes32 parentHash, string calldata label, - string calldata tokenURI, - uint32 destinationChainId, - // TODO multi: do we actually have to pass it here ?? do we support 1 chain in this portal only ??? - string calldata destinationChainName + string calldata tokenURI // bool forceUpdateGlobalExitRoot - do we need to pass this ??? ) external override { DistributionConfig memory emptyDistrConfig; @@ -110,8 +104,8 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IZNSPolygo // TODO multi: iron out what should go to ChainResolver data !!! chainResolver.setChainData( domainHash, - destinationChainId, - destinationChainName, + destChainId, + destChainName, address(0), "" ); @@ -134,12 +128,12 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IZNSPolygo return this.onERC721Received.selector; } - function setL1PortalAddress(address newAddress) external override onlyAdmin { + function setDestZnsPortal(address newAddress) external override onlyAdmin { if (newAddress == address(0)) revert ZeroAddressPassed(); - znsEthPortalL2 = newAddress; + destZnsPortal = newAddress; - emit L1PortalAddressSet(newAddress); + emit DestZnsPortalSet(newAddress); } function _processPayment( @@ -198,16 +192,16 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IZNSPolygo polygonZkEVMBridge.bridgeMessage( // TODO multi: should this be a parameter to the registerAndBridgeDomain function to work on any chain ??? - networkIdL2, - znsEthPortalL2, + destNetworkId, + destZnsPortal, // TODO multi: figure out what this is and how to better pass it !!! true, encodedProof ); emit DomainBridged( - networkIdL2, - znsEthPortalL2, + destNetworkId, + destZnsPortal, domainHash, msg.sender ); From 17b9db4519662474376d6c09fd10fc5b7e8ed337 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 14 Oct 2024 13:49:42 -0700 Subject: [PATCH 052/124] fix types in chain resolver --- contracts/resolver/IZNSChainResolver.sol | 8 ++++---- contracts/resolver/ZNSChainResolver.sol | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/resolver/IZNSChainResolver.sol b/contracts/resolver/IZNSChainResolver.sol index 383b8fbef..02aab879c 100644 --- a/contracts/resolver/IZNSChainResolver.sol +++ b/contracts/resolver/IZNSChainResolver.sol @@ -5,14 +5,14 @@ pragma solidity 0.8.26; interface IZNSChainResolver { event ChainDataSet( bytes32 indexed domainHash, - uint32 chainID, + uint256 chainID, string chainName, address znsRegistryOnChain, string auxData ); struct ChainData { - uint32 chainId; + uint256 chainId; string chainName; address znsRegistryOnChain; string auxData; @@ -22,7 +22,7 @@ interface IZNSChainResolver { function resolveChainData( bytes32 domainHash - ) external view returns (uint32, string memory, address, string memory); + ) external view returns (uint256, string memory, address, string memory); function resolveChainDataStruct( bytes32 domainHash @@ -30,7 +30,7 @@ interface IZNSChainResolver { function setChainData( bytes32 domainHash, - uint32 chainID, + uint256 chainID, string memory chainName, address znsRegistryOnChain, string memory auxData diff --git a/contracts/resolver/ZNSChainResolver.sol b/contracts/resolver/ZNSChainResolver.sol index 6dc95da85..9de901def 100644 --- a/contracts/resolver/ZNSChainResolver.sol +++ b/contracts/resolver/ZNSChainResolver.sol @@ -31,7 +31,7 @@ contract ZNSChainResolver is function resolveChainData( bytes32 domainHash - ) external view override returns (uint32, string memory, address, string memory) { + ) external view override returns (uint256, string memory, address, string memory) { ChainData memory data = chainData[domainHash]; // TODO multi: should we add RootRegistrar that has all ZNS addresses instead of Registry here ??? return (data.chainId, data.chainName, data.znsRegistryOnChain, data.auxData); @@ -46,7 +46,7 @@ contract ZNSChainResolver is // TODO multi: make this better !!! function setChainData( bytes32 domainHash, - uint32 chainID, + uint256 chainID, string memory chainName, address znsRegistryOnChain, string memory auxData From c627808563cfc0e7e88d0800b7775448512787ac Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 14 Oct 2024 13:49:55 -0700 Subject: [PATCH 053/124] adapt tests to new changes --- test/L2-BRIDGE-TEST/MultiZNS.test.ts | 47 ++++++++++++++++------------ 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts index 3f7a39f16..e0a9c6ecf 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -39,34 +39,42 @@ export interface IZNSContractsExtended extends IZNSContracts { export const NETWORK_ID_L1_DEFAULT = 1n; export const NETWORK_ID_L2_DEFAULT = 666n; +const zChainID = 336699n; +const zChainName = "ZChain"; + + export const deployCrossChainContracts = async ({ deployer, znsL1, chainResolverAddressL1, znsL2, - networkIdL1 = NETWORK_ID_L1_DEFAULT, - networkIdL2 = NETWORK_ID_L2_DEFAULT, + srcNetworkId = NETWORK_ID_L1_DEFAULT, + destNetworkId = NETWORK_ID_L2_DEFAULT, wethTokenAddress = hre.ethers.ZeroAddress, + destChainName = zChainName, + destChainId = zChainID, } : { deployer : SignerWithAddress; znsL1 : IZNSContracts; chainResolverAddressL1 : AddressLike; znsL2 : IZNSContracts; - networkIdL1 ?: bigint; - networkIdL2 ?: bigint; + srcNetworkId ?: bigint; + destNetworkId ?: bigint; wethTokenAddress ?: string; + destChainName ?: string; + destChainId ?: bigint; }) => { const polyPortalFact = new ZNSPolygonZkEvmPortal__factory(deployer); const ethPortalFact = new ZNSEthereumPortal__factory(deployer); const bridgeMockFact = new PolygonZkEVMBridgeV2Mock__factory(deployer); const bridgeL1 = await bridgeMockFact.deploy( - networkIdL1, + srcNetworkId, wethTokenAddress, ); await bridgeL1.waitForDeployment(); const bridgeL2 = await bridgeMockFact.deploy( - networkIdL2, + destNetworkId, wethTokenAddress, ); await bridgeL2.waitForDeployment(); @@ -74,14 +82,18 @@ export const deployCrossChainContracts = async ({ const polyPortal = await hre.upgrades.deployProxy( polyPortalFact, [ - znsL1.accessController.target, - networkIdL2, + destNetworkId, + destChainName, + destChainId, bridgeL1.target, - znsL1.rootRegistrar.target, - znsL1.subRegistrar.target, - znsL1.treasury.target, - chainResolverAddressL1, - znsL1.registry.target, + { + accessController: znsL1.accessController.target, + rootRegistrar: znsL1.rootRegistrar.target, + subRegistrar: znsL1.subRegistrar.target, + treasury: znsL1.treasury.target, + chainResolver: chainResolverAddressL1, + registry: znsL1.registry.target, + }, ], { kind: "uups", @@ -107,7 +119,7 @@ export const deployCrossChainContracts = async ({ await ethPortal.waitForDeployment(); // link portals - await polyPortal.connect(deployer).setL1PortalAddress(ethPortal.target); + await polyPortal.connect(deployer).setDestZnsPortal(ethPortal.target); // give Role to the Portal on L2 to call special function await znsL2.accessController.connect(deployer).grantRole( @@ -137,9 +149,6 @@ describe.only("MultiZNS", () => { const subdomainLabel = "beaubridges"; const subParentLabel = "bridges"; - const zChainID = 336699n; - const zChainName = "ZChain"; - let rootDomainHash : string; let balanceBeforeBridge : bigint; @@ -288,9 +297,7 @@ describe.only("MultiZNS", () => { const tx = await znsL1.polyPortal.connect(user).registerAndBridgeDomain( parentHash as string, label, - DEFAULT_TOKEN_URI, - zChainID, - zChainName, + DEFAULT_TOKEN_URI ); const receipt = await tx.wait() as ContractTransactionReceipt; console.log(`Gas used for ${name} bridging: ${receipt.gasUsed.toString()}`); From 70ba43f71ded6ff23328fc0a6192a166b13af070 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 14 Oct 2024 14:00:02 -0700 Subject: [PATCH 054/124] refactor EthereumPortal to new namings --- contracts/cross-chain/IZNSEthereumPortal.sol | 8 ++++---- contracts/cross-chain/ZNSEthereumPortal.sol | 18 ++++++++---------- .../cross-chain/ZNSPolygonZkEvmPortal.sol | 1 - 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/contracts/cross-chain/IZNSEthereumPortal.sol b/contracts/cross-chain/IZNSEthereumPortal.sol index b8587568d..bd354ae12 100644 --- a/contracts/cross-chain/IZNSEthereumPortal.sol +++ b/contracts/cross-chain/IZNSEthereumPortal.sol @@ -17,7 +17,7 @@ interface IZNSEthereumPortal is IDistributionConfig, IBridgeMessageReceiver { bytes32 indexed domainHash, address indexed domainOwner ); - event L2PortalAddressSet(address newAddress); + event SrcZnsPortalSet(address newAddress); // TODO multi: can this be better and have smth like NotPolygonBridge ??? error InvalidCaller(address caller); @@ -28,7 +28,7 @@ interface IZNSEthereumPortal is IDistributionConfig, IBridgeMessageReceiver { function networkId() external view returns (uint32); - function znsZkEvmPortalL1() external view returns (address); + function srcZnsPortal() external view returns (address); function rootRegistrar() external view returns (IZNSRootRegistrar); @@ -41,14 +41,14 @@ interface IZNSEthereumPortal is IDistributionConfig, IBridgeMessageReceiver { function initialize( address accessController_, IPolygonZkEVMBridgeV2Ext zkEvmBridge_, - address znsZkEvmPortalL1_, + address srcZnsPortal_, IZNSRootRegistrar rootRegistrar_, IZNSSubRegistrar subRegistrar_, IZNSDomainToken domainToken_, IZNSRegistry registry_ ) external; - function setL2PortalAddress(address newAddress) external; + function setSrcZnsPortal(address newAddress) external; function onERC721Received( address, diff --git a/contracts/cross-chain/ZNSEthereumPortal.sol b/contracts/cross-chain/ZNSEthereumPortal.sol index 9fa9863de..fbf66929d 100644 --- a/contracts/cross-chain/ZNSEthereumPortal.sol +++ b/contracts/cross-chain/ZNSEthereumPortal.sol @@ -18,15 +18,13 @@ import { IZNSPricer } from "../types/IZNSPricer.sol"; // TODO multi: could this be a better name that implies cross-chain nature ??? contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPortal { - // TODO multi: check that all state vars are needed and remove redundant ones !!! // *--| Cross-chain Data |--* // TODO multi: should we keep this extended interface ??? IPolygonZkEVMBridgeV2Ext public polygonZkEVMBridge; // This chain uint32 public networkId; - // TODO multi: should this be an Interface Var ??? it is not used now (delete?) !!! // figure out better names for these vars !!! - address public znsZkEvmPortalL1; + address public srcZnsPortal; // *--| ZNS Data for THIS chain |--* IZNSRootRegistrar public rootRegistrar; @@ -42,7 +40,7 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPo function initialize( address accessController_, IPolygonZkEVMBridgeV2Ext zkEvmBridge_, - address znsZkEvmPortalL1_, + address srcZnsPortal_, IZNSRootRegistrar rootRegistrar_, IZNSSubRegistrar subRegistrar_, IZNSDomainToken domainToken_, @@ -52,7 +50,7 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPo if ( address(zkEvmBridge_) == address(0) - || znsZkEvmPortalL1_ == address(0) + || srcZnsPortal_ == address(0) || address(rootRegistrar_) == address(0) || address(subRegistrar_) == address(0) || address(domainToken_) == address(0) @@ -61,7 +59,7 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPo polygonZkEVMBridge = zkEvmBridge_; networkId = polygonZkEVMBridge.networkID(); - znsZkEvmPortalL1 = znsZkEvmPortalL1_; + srcZnsPortal = srcZnsPortal_; rootRegistrar = rootRegistrar_; subRegistrar = subRegistrar_; domainToken = domainToken_; @@ -74,7 +72,7 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPo bytes memory data ) external payable override { if (msg.sender != address(polygonZkEVMBridge)) revert InvalidCaller(msg.sender); - if (originAddress != znsZkEvmPortalL1) revert InvalidOriginAddress(originAddress); + if (originAddress != srcZnsPortal) revert InvalidOriginAddress(originAddress); BridgedDomain memory proof = abi.decode(data, (BridgedDomain)); @@ -119,12 +117,12 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPo ); } - function setL2PortalAddress(address newAddress) external onlyAdmin { + function setSrcZnsPortal(address newAddress) external onlyAdmin { if (newAddress == address(0)) revert ZeroAddressPassed(); - znsZkEvmPortalL1 = newAddress; + srcZnsPortal = newAddress; - emit L2PortalAddressSet(newAddress); + emit SrcZnsPortalSet(newAddress); } function onERC721Received( diff --git a/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol b/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol index 97c93106e..17f4a139a 100644 --- a/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol +++ b/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol @@ -191,7 +191,6 @@ contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IZNSPolygo bytes memory encodedProof = abi.encode(proof); polygonZkEVMBridge.bridgeMessage( - // TODO multi: should this be a parameter to the registerAndBridgeDomain function to work on any chain ??? destNetworkId, destZnsPortal, // TODO multi: figure out what this is and how to better pass it !!! From 4997c5de6b243681826d82462e9b186c6c55aace Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 14 Oct 2024 14:19:56 -0700 Subject: [PATCH 055/124] extend test to check BridgeEvent from the bridge --- contracts/types/CrossChainTypes.sol | 3 +-- test/L2-BRIDGE-TEST/MultiZNS.test.ts | 23 ++++++++++++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/contracts/types/CrossChainTypes.sol b/contracts/types/CrossChainTypes.sol index 99ec5c5e6..92d38e52c 100644 --- a/contracts/types/CrossChainTypes.sol +++ b/contracts/types/CrossChainTypes.sol @@ -2,11 +2,10 @@ pragma solidity 0.8.26; -// TODO multi: what is the best name for this ??? struct BridgedDomain { - address domainOwner; bytes32 domainHash; bytes32 parentHash; string label; + address domainOwner; string tokenUri; } diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts index e0a9c6ecf..ebaea0a42 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -273,7 +273,6 @@ describe.only("MultiZNS", () => { // register root regularly on L1 first parentHash = await registrationWithSetup({ zns: znsL1, - // TODO multi: convert this test to use different user from the deployAdmin !!! user: deployAdmin, domainLabel: subParentLabel, fullConfig: { @@ -319,17 +318,35 @@ describe.only("MultiZNS", () => { }); const event = events[events.length - 1]; expect(event.args.domainHash).to.equal(domainHash); - expect(event.args.destNetworkId).to.equal(666n); + expect(event.args.destNetworkId).to.equal(NETWORK_ID_L2_DEFAULT); expect(event.args.destPortalAddress).to.equal(znsL2.ethPortal.target); expect(event.args.domainOwner).to.equal(user.address); - // TODO multi: test these values !!! const bridgeEvents = await getEvents({ contract: znsL1.bridgeL1, eventName: "BridgeEvent", }); ({ args: bridgedEventData } = bridgeEvents[bridgeEvents.length - 1]); + const abiCoder = ethers.AbiCoder.defaultAbiCoder(); + const metadataRef = abiCoder.encode( + ["tuple(bytes32,bytes32,string,address,string)"], + [[ + domainHash, + parentHash, + label, + user.address, + DEFAULT_TOKEN_URI, + ]] + ); + + expect(bridgedEventData.originNetwork).to.equal(NETWORK_ID_L1_DEFAULT); + expect(bridgedEventData.originAddress).to.equal(znsL1.polyPortal.target); + expect(bridgedEventData.destinationNetwork).to.equal(NETWORK_ID_L2_DEFAULT); + expect(bridgedEventData.destinationAddress).to.equal(znsL2.ethPortal.target); + expect(bridgedEventData.amount).to.equal(0n); + expect(bridgedEventData.metadata).to.equal(metadataRef); + // check owner and resolver are set properly const { owner: ownerL1, From 2c67762d17a59ce27e57221574d1f677244022b8 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 14 Oct 2024 14:54:05 -0700 Subject: [PATCH 056/124] extend resolverTypes constant map --- src/deploy/constants.ts | 2 +- test/L2-BRIDGE-TEST/MultiZNS.test.ts | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/deploy/constants.ts b/src/deploy/constants.ts index 50972e8d0..0dbe4f1e7 100644 --- a/src/deploy/constants.ts +++ b/src/deploy/constants.ts @@ -28,7 +28,7 @@ export const EXECUTOR_ROLE = ethers.solidityPackedKeccak256( export const ResolverTypes = { address: "address", - // TODO: Which word to use for a string type of resolver?? // eslint-disable-next-line id-blacklist string: "string", + chain: "chain", }; diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts index ebaea0a42..543eea3a4 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -24,6 +24,7 @@ import { } from "../../typechain"; import { getDomainHashFromEvent, getEvents } from "../helpers/events"; import { AddressLike, ContractTransactionReceipt } from "ethers"; +import { ResolverTypes } from "../../src/deploy/constants"; // TODO multi: move below code to appropriate places @@ -193,7 +194,7 @@ describe.only("MultiZNS", () => { await chainResolver.waitForDeployment(); // TODO multi: add constants/enums for Resolver Types and possibly to Registry as well !!! - await znsL1.registry.connect(deployAdmin).addResolverType("chain", chainResolver.target); + await znsL1.registry.connect(deployAdmin).addResolverType(ResolverTypes.chain, chainResolver.target); config = await getConfig({ deployer: deployAdmin, @@ -442,9 +443,10 @@ describe.only("MultiZNS", () => { const dummySmtProof = Array.from({ length: 32 }, () => hre.ethers.randomBytes(32)); it("should #claimMessage() on the bridge successfully and fire a ClaimEvent", async () => { - // call Polygon Zk Evm Bridge to claimMessage - // TODO multi: add test to check that anyone can call this for the user !!! - await znsL2.bridgeL2.connect(user).claimMessage( + // **NOTE** that we connect as `deployAdmin` here to show that it's not + // required that this has to be called by the original owner, + // it can be called by anyone + await znsL2.bridgeL2.connect(deployAdmin).claimMessage( dummySmtProof, dummySmtProof, bridgedEventData.globalIndex, @@ -493,6 +495,7 @@ describe.only("MultiZNS", () => { expect(tokenOwner).to.equal(user.address); }); + it("should set configs as empty and allow original caller to set these configs", async () => { // should be LOCKED with no configs const distrConfig = await znsL2.subRegistrar.distrConfigs(domainHash); From 96bfc0d56dc5dc0247de5854b9742e08f01cc0ed Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 14 Oct 2024 15:38:52 -0700 Subject: [PATCH 057/124] add new Portal role and thread it everywhere for Portal registration calls --- contracts/access/IZNSAccessController.sol | 4 ++++ contracts/access/ZNSAccessController.sol | 11 +++++++++++ contracts/access/ZNSRoles.sol | 6 ++++++ contracts/cross-chain/IZNSEthereumPortal.sol | 1 - contracts/registrar/ZNSRootRegistrar.sol | 4 +++- contracts/registrar/ZNSSubRegistrar.sol | 4 +++- hardhat.config.ts | 3 +++ src/deploy/constants.ts | 4 ++++ test/L2-BRIDGE-TEST/MultiZNS.test.ts | 11 +++++------ 9 files changed, 39 insertions(+), 9 deletions(-) diff --git a/contracts/access/IZNSAccessController.sol b/contracts/access/IZNSAccessController.sol index 9263708d4..603c90faf 100644 --- a/contracts/access/IZNSAccessController.sol +++ b/contracts/access/IZNSAccessController.sol @@ -15,11 +15,15 @@ interface IZNSAccessController is IAccessControl { function checkRegistrar(address account) external view; + function checkPortal(address account) external view; + function isAdmin(address account) external view returns (bool); function isRegistrar(address account) external view returns (bool); function isGovernor(address account) external view returns (bool); + function isPortal(address account) external view returns (bool); + function isExecutor(address account) external view returns (bool); } diff --git a/contracts/access/ZNSAccessController.sol b/contracts/access/ZNSAccessController.sol index 2174dd7a3..09529cc35 100644 --- a/contracts/access/ZNSAccessController.sol +++ b/contracts/access/ZNSAccessController.sol @@ -15,6 +15,7 @@ import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; * - ADMIN: The main maintainer role, that gets access to all system functions (managed by Governor) * - EXECUTOR: Can be here to future proof, if we need a new role (managed by Governor) * - REGISTRAR: This role is here specifically for the ZNSRootRegistrar.sol contract (managed by Admin) + * - PORTAL: Role for cross-chain Portal contracts that call certain functions on ZNS contracts (managed by Admin) * * > This contract is NOT proxied. When new implementation is needed, a new contract will be deployed * and all modules will be updated to use the new address, since they all inherit from `AAccessControlled.sol`. @@ -34,6 +35,8 @@ contract ZNSAccessController is AccessControl, ZNSRoles, IZNSAccessController { _setRoleAdmin(GOVERNOR_ROLE, GOVERNOR_ROLE); // all of the admins control registrar _setRoleAdmin(REGISTRAR_ROLE, ADMIN_ROLE); + // all of the admins control portals + _setRoleAdmin(PORTAL_ROLE, ADMIN_ROLE); } // ** Access Validators ** @@ -54,6 +57,10 @@ contract ZNSAccessController is AccessControl, ZNSRoles, IZNSAccessController { _checkRole(REGISTRAR_ROLE, account); } + function checkPortal(address account) external view override { + _checkRole(PORTAL_ROLE, account); + } + // "is...()" functions return a boolean function isAdmin(address account) external view override returns (bool) { return hasRole(ADMIN_ROLE, account); @@ -67,6 +74,10 @@ contract ZNSAccessController is AccessControl, ZNSRoles, IZNSAccessController { return hasRole(GOVERNOR_ROLE, account); } + function isPortal(address account) external view override returns (bool) { + return hasRole(PORTAL_ROLE, account); + } + function isExecutor(address account) external view override returns (bool) { return hasRole(EXECUTOR_ROLE, account); } diff --git a/contracts/access/ZNSRoles.sol b/contracts/access/ZNSRoles.sol index 3ff956067..c524c6b73 100644 --- a/contracts/access/ZNSRoles.sol +++ b/contracts/access/ZNSRoles.sol @@ -22,6 +22,12 @@ abstract contract ZNSRoles { */ bytes32 public constant REGISTRAR_ROLE = keccak256("REGISTRAR_ROLE"); + /** + * @notice Role for cross-chain contracts of Portal type that can call + * certain functions on ZNS contracts. + */ + bytes32 public constant PORTAL_ROLE = keccak256("PORTAL_ROLE"); + /** * @notice Executor can be here to future proof, if we need a new role * so we don't have to upgrade all contracts diff --git a/contracts/cross-chain/IZNSEthereumPortal.sol b/contracts/cross-chain/IZNSEthereumPortal.sol index bd354ae12..4ca48669a 100644 --- a/contracts/cross-chain/IZNSEthereumPortal.sol +++ b/contracts/cross-chain/IZNSEthereumPortal.sol @@ -19,7 +19,6 @@ interface IZNSEthereumPortal is IDistributionConfig, IBridgeMessageReceiver { ); event SrcZnsPortalSet(address newAddress); - // TODO multi: can this be better and have smth like NotPolygonBridge ??? error InvalidCaller(address caller); error InvalidOriginAddress(address originAddress); error DomainHashDoesNotMatchBridged(bytes32 bridgedHashL1, bytes32 generatedHashL2); diff --git a/contracts/registrar/ZNSRootRegistrar.sol b/contracts/registrar/ZNSRootRegistrar.sol index 1b969377e..b68ae1ae6 100644 --- a/contracts/registrar/ZNSRootRegistrar.sol +++ b/contracts/registrar/ZNSRootRegistrar.sol @@ -110,7 +110,9 @@ contract ZNSRootRegistrar is string calldata label, string calldata tokenURI // TODO multi: should we add specific role for the Portal ??? - ) external onlyRegistrar override returns (bytes32) { + ) external override returns (bytes32) { + accessController.checkPortal(msg.sender); + DistributionConfig memory emptyDistrConfig; PaymentConfig memory emptyPaymentConfig; diff --git a/contracts/registrar/ZNSSubRegistrar.sol b/contracts/registrar/ZNSSubRegistrar.sol index d2a8bf97a..836bdd342 100644 --- a/contracts/registrar/ZNSSubRegistrar.sol +++ b/contracts/registrar/ZNSSubRegistrar.sol @@ -106,7 +106,9 @@ contract ZNSSubRegistrar is AAccessControlled, ARegistryWired, UUPSUpgradeable, bytes32 parentHash, string calldata label, string calldata tokenURI - ) external onlyRegistrar override returns (bytes32) { + ) external override returns (bytes32) { + accessController.checkPortal(msg.sender); + DistributionConfig memory emptyDistrConfig; PaymentConfig memory emptyPaymentConfig; diff --git a/hardhat.config.ts b/hardhat.config.ts index 1007c697b..f5fcd3c4a 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -49,6 +49,9 @@ const config : HardhatUserConfig = { enabled: true, runs: 20000, }, + // TODO: we are not using this, but solcover gives an error if we don't have it + // figure out what to do here for it to work in CI! + // viaIR: true, }, }, { diff --git a/src/deploy/constants.ts b/src/deploy/constants.ts index 0dbe4f1e7..1f9f53eb3 100644 --- a/src/deploy/constants.ts +++ b/src/deploy/constants.ts @@ -21,6 +21,10 @@ export const REGISTRAR_ROLE = ethers.solidityPackedKeccak256( ["string"], ["REGISTRAR_ROLE"], ); +export const PORTAL_ROLE = ethers.solidityPackedKeccak256( + ["string"], + ["PORTAL_ROLE"], +); export const EXECUTOR_ROLE = ethers.solidityPackedKeccak256( ["string"], ["EXECUTOR_ROLE"], diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts index 543eea3a4..02a8a611e 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -10,7 +10,7 @@ import { DISTRIBUTION_LOCKED_NOT_EXIST_ERR, fullDistrConfigEmpty, getCurvePrice, getStakingOrProtocolFee, NOT_AUTHORIZED_ERR, - NOT_OWNER_OF_ERR, PaymentType, REGISTRAR_ROLE, + NOT_OWNER_OF_ERR, PaymentType, } from "../helpers"; import { expect } from "chai"; import * as ethers from "ethers"; @@ -24,7 +24,7 @@ import { } from "../../typechain"; import { getDomainHashFromEvent, getEvents } from "../helpers/events"; import { AddressLike, ContractTransactionReceipt } from "ethers"; -import { ResolverTypes } from "../../src/deploy/constants"; +import { PORTAL_ROLE, ResolverTypes } from "../../src/deploy/constants"; // TODO multi: move below code to appropriate places @@ -38,12 +38,13 @@ export interface IZNSContractsExtended extends IZNSContracts { export const NETWORK_ID_L1_DEFAULT = 1n; -export const NETWORK_ID_L2_DEFAULT = 666n; +export const NETWORK_ID_L2_DEFAULT = 369n; const zChainID = 336699n; const zChainName = "ZChain"; +// TODO multi: add this to the Campaign properly !!! export const deployCrossChainContracts = async ({ deployer, znsL1, @@ -124,7 +125,7 @@ export const deployCrossChainContracts = async ({ // give Role to the Portal on L2 to call special function await znsL2.accessController.connect(deployer).grantRole( - REGISTRAR_ROLE, + PORTAL_ROLE, ethPortal.target ); @@ -150,8 +151,6 @@ describe.only("MultiZNS", () => { const subdomainLabel = "beaubridges"; const subParentLabel = "bridges"; - let rootDomainHash : string; - let balanceBeforeBridge : bigint; let bridgedEventData : { From b26ebdd226c4f27153b735f8233259743894e0fd Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 15 Oct 2024 12:41:38 -0700 Subject: [PATCH 058/124] rename PolygonZkEvmPortal to ZChainPortal --- ...onZkEvmPortal.sol => IZNSZChainPortal.sol} | 2 +- ...gonZkEvmPortal.sol => ZNSZChainPortal.sol} | 4 +- test/L2-BRIDGE-TEST/MultiZNS.test.ts | 43 +++++++++---------- 3 files changed, 24 insertions(+), 25 deletions(-) rename contracts/cross-chain/{IZNSPolygonZkEvmPortal.sol => IZNSZChainPortal.sol} (97%) rename contracts/cross-chain/{ZNSPolygonZkEvmPortal.sol => ZNSZChainPortal.sol} (97%) diff --git a/contracts/cross-chain/IZNSPolygonZkEvmPortal.sol b/contracts/cross-chain/IZNSZChainPortal.sol similarity index 97% rename from contracts/cross-chain/IZNSPolygonZkEvmPortal.sol rename to contracts/cross-chain/IZNSZChainPortal.sol index ef5c6a2ed..28b4a9a2f 100644 --- a/contracts/cross-chain/IZNSPolygonZkEvmPortal.sol +++ b/contracts/cross-chain/IZNSZChainPortal.sol @@ -11,7 +11,7 @@ import { IZNSChainResolver } from "../resolver/IZNSChainResolver.sol"; import { IZNSAccessController } from "../access/IZNSAccessController.sol"; -interface IZNSPolygonZkEvmPortal is IDistributionConfig { +interface IZNSZChainPortal is IDistributionConfig { struct ZNSContractInput { IZNSAccessController accessController; diff --git a/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol b/contracts/cross-chain/ZNSZChainPortal.sol similarity index 97% rename from contracts/cross-chain/ZNSPolygonZkEvmPortal.sol rename to contracts/cross-chain/ZNSZChainPortal.sol index 17f4a139a..0e56b22ef 100644 --- a/contracts/cross-chain/ZNSPolygonZkEvmPortal.sol +++ b/contracts/cross-chain/ZNSZChainPortal.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.26; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { IPolygonZkEVMBridgeV2 } from "@zero-tech/zkevm-contracts/contracts/v2/interfaces/IPolygonZkEVMBridgeV2.sol"; import { AAccessControlled } from "../access/AAccessControlled.sol"; -import { IZNSPolygonZkEvmPortal } from "./IZNSPolygonZkEvmPortal.sol"; +import { IZNSZChainPortal } from "./IZNSZChainPortal.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { IZNSChainResolver } from "../resolver/IZNSChainResolver.sol"; import { IZNSPricer } from "../types/IZNSPricer.sol"; @@ -17,7 +17,7 @@ import { BridgedDomain } from "../types/CrossChainTypes.sol"; import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; -contract ZNSPolygonZkEvmPortal is UUPSUpgradeable, AAccessControlled, IZNSPolygonZkEvmPortal { +contract ZNSZChainPortal is UUPSUpgradeable, AAccessControlled, IZNSZChainPortal { // *--| Cross-chain Data |--* IPolygonZkEVMBridgeV2 public polygonZkEVMBridge; // Destination chain (L2) diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts index 02a8a611e..b18eda057 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -20,7 +20,7 @@ import { ZNSChainResolver, ZNSChainResolver__factory, ZNSEthereumPortal, ZNSEthereumPortal__factory, ZNSPolygonZkEvmPortal, - ZNSPolygonZkEvmPortal__factory, + ZNSZChainPortal__factory, } from "../../typechain"; import { getDomainHashFromEvent, getEvents } from "../helpers/events"; import { AddressLike, ContractTransactionReceipt } from "ethers"; @@ -30,7 +30,7 @@ import { PORTAL_ROLE, ResolverTypes } from "../../src/deploy/constants"; // TODO multi: move below code to appropriate places // some of these may be optional ?? export interface IZNSContractsExtended extends IZNSContracts { - polyPortal : ZNSPolygonZkEvmPortal; + zPortal : ZNSPolygonZkEvmPortal; bridgeL1 : PolygonZkEVMBridgeV2Mock; ethPortal : ZNSEthereumPortal; bridgeL2 : PolygonZkEVMBridgeV2Mock; @@ -66,7 +66,7 @@ export const deployCrossChainContracts = async ({ destChainName ?: string; destChainId ?: bigint; }) => { - const polyPortalFact = new ZNSPolygonZkEvmPortal__factory(deployer); + const zPortalFact = new ZNSZChainPortal__factory(deployer); const ethPortalFact = new ZNSEthereumPortal__factory(deployer); const bridgeMockFact = new PolygonZkEVMBridgeV2Mock__factory(deployer); @@ -81,8 +81,8 @@ export const deployCrossChainContracts = async ({ ); await bridgeL2.waitForDeployment(); - const polyPortal = await hre.upgrades.deployProxy( - polyPortalFact, + const zPortal = await hre.upgrades.deployProxy( + zPortalFact, [ destNetworkId, destChainName, @@ -101,14 +101,14 @@ export const deployCrossChainContracts = async ({ kind: "uups", } ) as unknown as ZNSPolygonZkEvmPortal; - await polyPortal.waitForDeployment(); + await zPortal.waitForDeployment(); const ethPortal = await hre.upgrades.deployProxy( ethPortalFact, [ znsL2.accessController.target, bridgeL2.target, - polyPortal.target, + zPortal.target, znsL2.rootRegistrar.target, znsL2.subRegistrar.target, znsL2.domainToken.target, @@ -121,7 +121,7 @@ export const deployCrossChainContracts = async ({ await ethPortal.waitForDeployment(); // link portals - await polyPortal.connect(deployer).setDestZnsPortal(ethPortal.target); + await zPortal.connect(deployer).setDestZnsPortal(ethPortal.target); // give Role to the Portal on L2 to call special function await znsL2.accessController.connect(deployer).grantRole( @@ -130,7 +130,7 @@ export const deployCrossChainContracts = async ({ ); return { - polyPortal, + zPortal, ethPortal, bridgeL1, bridgeL2, @@ -209,7 +209,7 @@ describe.only("MultiZNS", () => { await znsL2.meowToken.connect(deployAdmin).approve(znsL2.treasury.target, ethers.MaxUint256); const { - polyPortal, + zPortal, ethPortal, bridgeL1, bridgeL2, @@ -222,7 +222,7 @@ describe.only("MultiZNS", () => { znsL1 = { ...znsL1, - polyPortal, + zPortal, bridgeL1, }; @@ -233,11 +233,11 @@ describe.only("MultiZNS", () => { }; await znsL1.meowToken.mint(deployAdmin.address, 1000000000000000000000n); - await znsL1.meowToken.connect(deployAdmin).approve(znsL1.polyPortal.target, ethers.MaxUint256); + await znsL1.meowToken.connect(deployAdmin).approve(znsL1.zPortal.target, ethers.MaxUint256); await znsL1.meowToken.connect(deployAdmin).approve(znsL1.treasury.target, ethers.MaxUint256); await znsL1.meowToken.mint(user.address, hre.ethers.parseEther("100000000000000")); - await znsL1.meowToken.connect(user).approve(znsL1.polyPortal.target, ethers.MaxUint256); + await znsL1.meowToken.connect(user).approve(znsL1.zPortal.target, ethers.MaxUint256); }); [ @@ -293,7 +293,7 @@ describe.only("MultiZNS", () => { balanceBeforeBridge = await znsL1.meowToken.balanceOf(user.address); // register and bridge - const tx = await znsL1.polyPortal.connect(user).registerAndBridgeDomain( + const tx = await znsL1.zPortal.connect(user).registerAndBridgeDomain( parentHash as string, label, DEFAULT_TOKEN_URI @@ -303,7 +303,7 @@ describe.only("MultiZNS", () => { domainHash = await getDomainHashFromEvent({ zns: znsL1, - registrantAddress: znsL1.polyPortal.target as string, + registrantAddress: znsL1.zPortal.target as string, }); }); @@ -313,7 +313,7 @@ describe.only("MultiZNS", () => { // check if domain is registered on L1 // check events const events = await getEvents({ - contract: znsL1.polyPortal, + contract: znsL1.zPortal, eventName: "DomainBridged", }); const event = events[events.length - 1]; @@ -341,7 +341,7 @@ describe.only("MultiZNS", () => { ); expect(bridgedEventData.originNetwork).to.equal(NETWORK_ID_L1_DEFAULT); - expect(bridgedEventData.originAddress).to.equal(znsL1.polyPortal.target); + expect(bridgedEventData.originAddress).to.equal(znsL1.zPortal.target); expect(bridgedEventData.destinationNetwork).to.equal(NETWORK_ID_L2_DEFAULT); expect(bridgedEventData.destinationAddress).to.equal(znsL2.ethPortal.target); expect(bridgedEventData.amount).to.equal(0n); @@ -352,11 +352,11 @@ describe.only("MultiZNS", () => { owner: ownerL1, resolver: resolverL1, } = await znsL1.registry.getDomainRecord(domainHash); - expect(ownerL1).to.equal(znsL1.polyPortal.target); + expect(ownerL1).to.equal(znsL1.zPortal.target); expect(resolverL1).to.equal(chainResolver.target); const tokenOwner = await znsL1.domainToken.ownerOf(BigInt(domainHash)); - expect(tokenOwner).to.equal(znsL1.polyPortal.target); + expect(tokenOwner).to.equal(znsL1.zPortal.target); }); it("should withdraw the correct amount of tokens from the caller", async () => { @@ -465,7 +465,7 @@ describe.only("MultiZNS", () => { }); const event = events[events.length - 1]; expect(event.args.originNetwork).to.equal(NETWORK_ID_L1_DEFAULT); - expect(event.args.originAddress).to.equal(znsL1.polyPortal.target); + expect(event.args.originAddress).to.equal(znsL1.zPortal.target); expect(event.args.destinationAddress).to.equal(znsL2.ethPortal.target); expect(event.args.amount).to.equal(0n); }); @@ -480,7 +480,7 @@ describe.only("MultiZNS", () => { }); const event = events[events.length - 1]; expect(event.args.srcNetworkId).to.equal(NETWORK_ID_L1_DEFAULT); - expect(event.args.srcPortalAddress).to.equal(znsL1.polyPortal.target); + expect(event.args.srcPortalAddress).to.equal(znsL1.zPortal.target); expect(event.args.domainHash).to.equal(domainHash); expect(event.args.domainOwner).to.equal(user.address); @@ -494,7 +494,6 @@ describe.only("MultiZNS", () => { expect(tokenOwner).to.equal(user.address); }); - it("should set configs as empty and allow original caller to set these configs", async () => { // should be LOCKED with no configs const distrConfig = await znsL2.subRegistrar.distrConfigs(domainHash); From b3f46e41cd1953d6c2513e77d4eebe25e035a1ec Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 15 Oct 2024 15:31:31 -0700 Subject: [PATCH 059/124] create chain resolver DM and some name constants --- contracts/cross-chain/IZNSZChainPortal.sol | 6 +- .../missions/contracts/chain-resolver.ts | 66 +++++++++++++++++++ src/deploy/missions/contracts/names.ts | 8 +++ 3 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 src/deploy/missions/contracts/chain-resolver.ts diff --git a/contracts/cross-chain/IZNSZChainPortal.sol b/contracts/cross-chain/IZNSZChainPortal.sol index 28b4a9a2f..4323758dd 100644 --- a/contracts/cross-chain/IZNSZChainPortal.sol +++ b/contracts/cross-chain/IZNSZChainPortal.sol @@ -15,11 +15,11 @@ interface IZNSZChainPortal is IDistributionConfig { struct ZNSContractInput { IZNSAccessController accessController; + IZNSRegistry registry; + IZNSChainResolver chainResolver; + IZNSTreasury treasury; IZNSRootRegistrar rootRegistrar; IZNSSubRegistrar subRegistrar; - IZNSTreasury treasury; - IZNSChainResolver chainResolver; - IZNSRegistry registry; } event DomainBridged( diff --git a/src/deploy/missions/contracts/chain-resolver.ts b/src/deploy/missions/contracts/chain-resolver.ts new file mode 100644 index 000000000..91b005c1b --- /dev/null +++ b/src/deploy/missions/contracts/chain-resolver.ts @@ -0,0 +1,66 @@ +import { IZNSCampaignConfig, IZNSContracts } from "../../campaign/types"; +import { BaseDeployMission } from "@zero-tech/zdc"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; +import { ProxyKinds, ResolverTypes } from "../../constants"; +import { znsNames } from "./names"; + + +export class ZNSChainResolverDM extends BaseDeployMission< +HardhatRuntimeEnvironment, +SignerWithAddress, +IZNSCampaignConfig, +IZNSContracts +> { + proxyData = { + isProxy: true, + kind: ProxyKinds.uups, + }; + + contractName = znsNames.chainResolver.contract; + instanceName = znsNames.chainResolver.instance; + + async deployArgs () { + const { + accessController, + registry, + } = this.campaign; + + return [await accessController.getAddress(), await registry.getAddress()]; + } + + async needsPostDeploy () { + const { + registry, + chainResolver, + } = this.campaign; + + const resolverInReg = await registry.getResolverType( + ResolverTypes.chain, + ); + + const needs = resolverInReg !== await chainResolver.getAddress(); + const msg = needs ? "needs" : "doesn't need"; + + this.logger.debug(`${this.contractName} ${msg} post deploy sequence`); + + return needs; + } + + async postDeploy () { + const { + registry, + chainResolver, + config: { + deployAdmin, + }, + } = this.campaign; + + await registry.connect(deployAdmin).addResolverType( + ResolverTypes.chain, + await chainResolver.getAddress(), + ); + + this.logger.debug(`${this.contractName} post deploy sequence completed`); + } +} diff --git a/src/deploy/missions/contracts/names.ts b/src/deploy/missions/contracts/names.ts index c9f7c3dac..dbd10b373 100644 --- a/src/deploy/missions/contracts/names.ts +++ b/src/deploy/missions/contracts/names.ts @@ -27,6 +27,10 @@ export const znsNames = { contract: "ZNSStringResolver", instance: "stringResolver", }, + chainResolver: { + contract: "ZNSChainResolver", + instance: "chainResolver", + }, curvePricer: { contract: "ZNSCurvePricer", instance: "curvePricer", @@ -47,6 +51,10 @@ export const znsNames = { contract: "ZNSSubRegistrar", instance: "subRegistrar", }, + zPortal: { + contract: "ZNSZChainPortal", + instance: "zPortal", + }, erc1967Proxy: { contract: erc1967ProxyName, instance: "erc1967Proxy", From 07d9db2ac442bb29d6d257306134654188ca21e9 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 15 Oct 2024 16:08:32 -0700 Subject: [PATCH 060/124] create ZChainPortal DM base and extend types --- src/deploy/campaign/types.ts | 14 ++++- .../missions/contracts/zchain-portal.ts | 60 +++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 src/deploy/missions/contracts/zchain-portal.ts diff --git a/src/deploy/campaign/types.ts b/src/deploy/campaign/types.ts index 462ad53de..06afeb242 100644 --- a/src/deploy/campaign/types.ts +++ b/src/deploy/campaign/types.ts @@ -14,7 +14,7 @@ import { ZNSSubRegistrar, ZNSTreasury, MeowToken, - ZNSStringResolver, ZNSPolygonZkEvmPortal, ZNSEthereumPortal, PolygonZkEVMBridgeV2Mock, + ZNSStringResolver, ZNSZChainPortal, ZNSEthereumPortal, PolygonZkEVMBridgeV2Mock, ZNSChainResolver, } from "../../../typechain"; export type IZNSSigner = HardhatEthersSigner | DefenderRelaySigner | SignerWithAddress; @@ -34,6 +34,12 @@ export interface IZNSCampaignConfig extends IDeployCampaignConfig { meowToken : MeowTokenMock; addressResolver : ZNSAddressResolver; stringResolver : ZNSStringResolver; + chainResolver : ZNSChainResolver; curvePricer : ZNSCurvePricer; treasury : ZNSTreasury; rootRegistrar : ZNSRootRegistrar; fixedPricer : ZNSFixedPricer; subRegistrar : ZNSSubRegistrar; + zPortal : ZNSZChainPortal; + ethPortal : ZNSEthereumPortal; } diff --git a/src/deploy/missions/contracts/zchain-portal.ts b/src/deploy/missions/contracts/zchain-portal.ts new file mode 100644 index 000000000..559330071 --- /dev/null +++ b/src/deploy/missions/contracts/zchain-portal.ts @@ -0,0 +1,60 @@ +import { BaseDeployMission, TDeployArgs } from "@zero-tech/zdc"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; +import { IZNSCampaignConfig, IZNSContracts } from "../../campaign/types"; +import { ProxyKinds } from "../../constants"; +import { znsNames } from "./names"; + + +export class ZChainPortalDM extends BaseDeployMission< +HardhatRuntimeEnvironment, +SignerWithAddress, +IZNSCampaignConfig, +IZNSContracts +> { + proxyData = { + isProxy: true, + kind: ProxyKinds.uups, + }; + + contractName = znsNames.zPortal.contract; + instanceName = znsNames.zPortal.instance; + + async deployArgs () : Promise { + const { + accessController, + registry, + treasury, + chainResolver, + rootRegistrar, + subRegistrar, + zkEvmBridge, + config: { + crosschain: { + destNetworkId, + destChainName, + destChainId, + srcZkEvmBridge, + }, + }, + } = this.campaign; + + // TODO multi: figure out proper handling of this for actual contract AND mock !!! + const bridgeAddress = !srcZkEvmBridge ? await zkEvmBridge.getAddress() : srcZkEvmBridge; + + return [ + destNetworkId, + destChainName, + destChainId, + bridgeAddress, + { + accessController: await accessController.getAddress(), + registry: await registry.getAddress(), + chainResolver: await chainResolver.getAddress(), + treasury: await treasury.getAddress(), + rootRegistrar: await rootRegistrar.getAddress(), + subRegistrar: await subRegistrar.getAddress(), + }, + ]; + } +} From 373f0226391217935ab409756907d4a40c71269c Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 15 Oct 2024 16:21:45 -0700 Subject: [PATCH 061/124] rearrange deploy params for EthPortal --- contracts/cross-chain/IZNSEthereumPortal.sol | 6 +++--- contracts/cross-chain/ZNSEthereumPortal.sol | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/contracts/cross-chain/IZNSEthereumPortal.sol b/contracts/cross-chain/IZNSEthereumPortal.sol index 4ca48669a..6c0c0a3f4 100644 --- a/contracts/cross-chain/IZNSEthereumPortal.sol +++ b/contracts/cross-chain/IZNSEthereumPortal.sol @@ -41,10 +41,10 @@ interface IZNSEthereumPortal is IDistributionConfig, IBridgeMessageReceiver { address accessController_, IPolygonZkEVMBridgeV2Ext zkEvmBridge_, address srcZnsPortal_, - IZNSRootRegistrar rootRegistrar_, - IZNSSubRegistrar subRegistrar_, + IZNSRegistry registry_, IZNSDomainToken domainToken_, - IZNSRegistry registry_ + IZNSRootRegistrar rootRegistrar_, + IZNSSubRegistrar subRegistrar_ ) external; function setSrcZnsPortal(address newAddress) external; diff --git a/contracts/cross-chain/ZNSEthereumPortal.sol b/contracts/cross-chain/ZNSEthereumPortal.sol index fbf66929d..3e9a49026 100644 --- a/contracts/cross-chain/ZNSEthereumPortal.sol +++ b/contracts/cross-chain/ZNSEthereumPortal.sol @@ -41,10 +41,10 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPo address accessController_, IPolygonZkEVMBridgeV2Ext zkEvmBridge_, address srcZnsPortal_, - IZNSRootRegistrar rootRegistrar_, - IZNSSubRegistrar subRegistrar_, + IZNSRegistry registry_, IZNSDomainToken domainToken_, - IZNSRegistry registry_ + IZNSRootRegistrar rootRegistrar_, + IZNSSubRegistrar subRegistrar_ ) external override initializer { _setAccessController(accessController_); @@ -68,6 +68,8 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPo function onMessageReceived( address originAddress, + // TODO multi: do we need to add this value to state and validate against it here with a revert ??? + // so it can only be called with from one network ??? uint32 originNetwork, bytes memory data ) external payable override { From 419a0a05ec1be8cc53198c6d520ad324ef67810f Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 15 Oct 2024 16:35:36 -0700 Subject: [PATCH 062/124] add EthPortal DM base --- src/deploy/campaign/types.ts | 2 + src/deploy/missions/contracts/eth-portal.ts | 83 +++++++++++++++++++ src/deploy/missions/contracts/names.ts | 4 + .../missions/contracts/zchain-portal.ts | 1 + 4 files changed, 90 insertions(+) create mode 100644 src/deploy/missions/contracts/eth-portal.ts diff --git a/src/deploy/campaign/types.ts b/src/deploy/campaign/types.ts index 06afeb242..880acc8ac 100644 --- a/src/deploy/campaign/types.ts +++ b/src/deploy/campaign/types.ts @@ -38,7 +38,9 @@ export interface IZNSCampaignConfig extends IDeployCampaignConfig, +IZNSContracts +> { + proxyData = { + isProxy: true, + kind: ProxyKinds.uups, + }; + + contractName = znsNames.ethPortal.contract; + instanceName = znsNames.ethPortal.instance; + + async deployArgs () : Promise { + const { + accessController, + registry, + domainToken, + rootRegistrar, + subRegistrar, + zkEvmBridge, + config: { + crosschain: { + destZkEvmBridge, + srcZnsPortal, + }, + }, + } = this.campaign; + + // TODO multi: figure out proper handling of this for actual contract AND mock !!! + const bridgeAddress = !destZkEvmBridge ? await zkEvmBridge.getAddress() : destZkEvmBridge; + + return [ + await accessController.getAddress(), + bridgeAddress, + srcZnsPortal, + await registry.getAddress(), + await domainToken.getAddress(), + await rootRegistrar.getAddress(), + await subRegistrar.getAddress(), + ]; + } + + async needsPostDeploy () { + const { + accessController, + ethPortal, + } = this.campaign; + + const hasPortalRole = await accessController.isPortal(await ethPortal.getAddress()); + + const needs = !hasPortalRole; + const msg = needs ? "needs" : "doesn't need"; + + this.logger.debug(`${this.contractName} ${msg} post deploy sequence`); + + return needs; + } + + async postDeploy () { + const { + accessController, + ethPortal, + config: { deployAdmin }, + } = this.campaign; + + await accessController.connect(deployAdmin).grantRole( + PORTAL_ROLE, + ethPortal.target + ); + + this.logger.debug(`${this.contractName} post deploy sequence completed`); + } +} diff --git a/src/deploy/missions/contracts/names.ts b/src/deploy/missions/contracts/names.ts index dbd10b373..086dc76b7 100644 --- a/src/deploy/missions/contracts/names.ts +++ b/src/deploy/missions/contracts/names.ts @@ -55,6 +55,10 @@ export const znsNames = { contract: "ZNSZChainPortal", instance: "zPortal", }, + ethPortal: { + contract: "ZNSEthereumPortal", + instance: "ethPortal", + }, erc1967Proxy: { contract: erc1967ProxyName, instance: "erc1967Proxy", diff --git a/src/deploy/missions/contracts/zchain-portal.ts b/src/deploy/missions/contracts/zchain-portal.ts index 559330071..a718a577b 100644 --- a/src/deploy/missions/contracts/zchain-portal.ts +++ b/src/deploy/missions/contracts/zchain-portal.ts @@ -6,6 +6,7 @@ import { ProxyKinds } from "../../constants"; import { znsNames } from "./names"; +// TODO multi: figure out how to set EthereumPortal address on this contract after that is deployed !!! export class ZChainPortalDM extends BaseDeployMission< HardhatRuntimeEnvironment, SignerWithAddress, From 9b70b79fa4a28b54002714bbf172619eadb0b30e Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 15 Oct 2024 16:36:27 -0700 Subject: [PATCH 063/124] small test fix --- test/L2-BRIDGE-TEST/MultiZNS.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts index b18eda057..d0f3f073a 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -109,10 +109,10 @@ export const deployCrossChainContracts = async ({ znsL2.accessController.target, bridgeL2.target, zPortal.target, + znsL2.registry.target, + znsL2.domainToken.target, znsL2.rootRegistrar.target, znsL2.subRegistrar.target, - znsL2.domainToken.target, - znsL2.registry.target, ], { kind: "uups", @@ -307,6 +307,7 @@ describe.only("MultiZNS", () => { }); }); + // TODO multi: test all reverts and failures properly !!! describe("Bridge and Register on L1", () => { // eslint-disable-next-line max-len it("should register and set owners as ZkEvmPortal and fire DomainBridged and BridgeEvent events", async () => { From 9281ddaa8c403fe227b352da41163096868bcbf1 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 22 Oct 2024 14:12:46 -0700 Subject: [PATCH 064/124] add base logic for zkEvmBridge deploy mission, extent campaign config, add more names --- contracts/cross-chain/ZNSZChainPortal.sol | 1 + src/deploy/campaign/types.ts | 5 ++ src/deploy/missions/contracts/names.ts | 5 ++ .../missions/contracts/zchain-portal.ts | 2 +- .../missions/contracts/zk-evm-bridge.ts | 73 +++++++++++++++++++ 5 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 src/deploy/missions/contracts/zk-evm-bridge.ts diff --git a/contracts/cross-chain/ZNSZChainPortal.sol b/contracts/cross-chain/ZNSZChainPortal.sol index 0e56b22ef..3f958a35c 100644 --- a/contracts/cross-chain/ZNSZChainPortal.sol +++ b/contracts/cross-chain/ZNSZChainPortal.sol @@ -17,6 +17,7 @@ import { BridgedDomain } from "../types/CrossChainTypes.sol"; import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; +// TODO multi: can we make it work on ALL chain under ZkEVM ??? make contract more general ??? contract ZNSZChainPortal is UUPSUpgradeable, AAccessControlled, IZNSZChainPortal { // *--| Cross-chain Data |--* IPolygonZkEVMBridgeV2 public polygonZkEVMBridge; diff --git a/src/deploy/campaign/types.ts b/src/deploy/campaign/types.ts index 880acc8ac..00ef6dce5 100644 --- a/src/deploy/campaign/types.ts +++ b/src/deploy/campaign/types.ts @@ -35,12 +35,17 @@ export interface IZNSCampaignConfig extends IDeployCampaignConfig, diff --git a/src/deploy/missions/contracts/zk-evm-bridge.ts b/src/deploy/missions/contracts/zk-evm-bridge.ts new file mode 100644 index 000000000..a2e83ce7f --- /dev/null +++ b/src/deploy/missions/contracts/zk-evm-bridge.ts @@ -0,0 +1,73 @@ +import { BaseDeployMission, IDeployMissionArgs, TDeployArgs } from "@zero-tech/zdc"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; +import { IZNSCampaignConfig, IZNSContracts } from "../../campaign/types"; +import { ProxyKinds } from "../../constants"; +import { znsNames } from "./names"; +import { ethers } from "ethers"; + + +export class PolygonZkEVMBridgeV2DM extends BaseDeployMission< +HardhatRuntimeEnvironment, +SignerWithAddress, +IZNSCampaignConfig, +IZNSContracts +> { + proxyData = { + isProxy: true, + kind: ProxyKinds.transparent, + }; + + contractName = znsNames.zkEvmBridge.contract; + instanceName = znsNames.zkEvmBridge.instance; + + constructor (args : IDeployMissionArgs< + HardhatRuntimeEnvironment, + SignerWithAddress, + IZNSCampaignConfig, + IZNSContracts + >) { + super(args); + + if (this.config.crosschain.mockZkEvmBridge) { + this.contractName = znsNames.zkEvmBridge.contractMock; + } + } + + async deploy () { + if (!this.config.crosschain.mockZkEvmBridge) { + this.logger.info("Using PolygonZkEvmBridgeV2 deployed on chain"); + + this.logger.debug(`Writing ${this.contractName} to DB...`); + + const factory = await this.campaign.deployer.getFactory(this.contractName); + const contract = factory.attach(this.config.crosschain.zkEvmBridgeAddress); + + await this.saveToDB(contract); + + this.campaign.updateStateContract(this.instanceName, this.contractName, contract); + + // eslint-disable-next-line max-len + this.logger.info(`Successfully created ${this.contractName} contract from chain data at ${await contract.getAddress()}`); + } else { + await super.deploy(); + } + } + + async deployArgs () : Promise { + // this is ONLY for the Mock version of the Bridge ! + const { + crosschain: { + srcNetworkId, + bridgeToken, + }, + } = this.config; + + const tokenAddress = !bridgeToken ? ethers.ZeroAddress : bridgeToken; + + return [ + srcNetworkId, + tokenAddress, + ]; + } +} From 2e1baeef12a6d170ee63dae8576e46befa2d5f1f Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 22 Oct 2024 14:14:22 -0700 Subject: [PATCH 065/124] Update class name for EthPortal and remove redundant code in meow token DM --- src/deploy/missions/contracts/eth-portal.ts | 2 +- src/deploy/missions/contracts/meow-token/meow-token.ts | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/deploy/missions/contracts/eth-portal.ts b/src/deploy/missions/contracts/eth-portal.ts index 3acbdd270..7cd7d7416 100644 --- a/src/deploy/missions/contracts/eth-portal.ts +++ b/src/deploy/missions/contracts/eth-portal.ts @@ -6,7 +6,7 @@ import { PORTAL_ROLE, ProxyKinds } from "../../constants"; import { znsNames } from "./names"; -export class ZNSEthPortalDM extends BaseDeployMission< +export class ZNSEthereumPortalDM extends BaseDeployMission< HardhatRuntimeEnvironment, SignerWithAddress, IZNSCampaignConfig, diff --git a/src/deploy/missions/contracts/meow-token/meow-token.ts b/src/deploy/missions/contracts/meow-token/meow-token.ts index c75001bd1..58eb0da58 100644 --- a/src/deploy/missions/contracts/meow-token/meow-token.ts +++ b/src/deploy/missions/contracts/meow-token/meow-token.ts @@ -41,8 +41,6 @@ IZNSContracts if (this.config.mockMeowToken) { this.contractName = znsNames.meowToken.contractMock; - } else { - this.contractName = znsNames.meowToken.contract; } } @@ -68,11 +66,6 @@ IZNSContracts const factory = new MeowToken__factory(this.config.deployAdmin); const baseContract = factory.attach(this.config.stakingTokenAddress); - // TODO remove! - // const baseContract = await this.campaign.deployer.getContractObject( - // this.contractName, - // this.config.stakingTokenAddress as string, - // ); await this.saveToDB(baseContract); From 54246772389d505f5273d6ecf3fc37342e6fbb25 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 22 Oct 2024 14:16:54 -0700 Subject: [PATCH 066/124] split folder structure for DMs in 2, separating zns base logic from cross chain DMs, fix imports --- src/deploy/campaign/environments.ts | 2 +- .../{ => cross-chain}/chain-resolver.ts | 6 ++--- .../contracts/{ => cross-chain}/eth-portal.ts | 6 ++--- .../{ => cross-chain}/zchain-portal.ts | 6 ++--- .../{ => cross-chain}/zk-evm-bridge.ts | 6 ++--- src/deploy/missions/contracts/index.ts | 27 +++++++++++-------- .../{ => zns-base}/access-controller.ts | 4 +-- .../{ => zns-base}/address-resolver.ts | 6 ++--- .../contracts/{ => zns-base}/curve-pricer.ts | 6 ++--- .../contracts/{ => zns-base}/domain-token.ts | 6 ++--- .../contracts/{ => zns-base}/fixed-pricer.ts | 6 ++--- .../{ => zns-base}/meow-token/mainnet-data.ts | 0 .../{ => zns-base}/meow-token/meow-token.ts | 6 ++--- .../contracts/{ => zns-base}/registry.ts | 6 ++--- .../{ => zns-base}/root-registrar.ts | 6 ++--- .../{ => zns-base}/string-resolver.ts | 6 ++--- .../contracts/{ => zns-base}/sub-registrar.ts | 6 ++--- .../contracts/{ => zns-base}/treasury.ts | 6 ++--- test/DeployCampaignInt.test.ts | 4 +-- 19 files changed, 63 insertions(+), 58 deletions(-) rename src/deploy/missions/contracts/{ => cross-chain}/chain-resolver.ts (89%) rename src/deploy/missions/contracts/{ => cross-chain}/eth-portal.ts (91%) rename src/deploy/missions/contracts/{ => cross-chain}/zchain-portal.ts (90%) rename src/deploy/missions/contracts/{ => cross-chain}/zk-evm-bridge.ts (92%) rename src/deploy/missions/contracts/{ => zns-base}/access-controller.ts (85%) rename src/deploy/missions/contracts/{ => zns-base}/address-resolver.ts (89%) rename src/deploy/missions/contracts/{ => zns-base}/curve-pricer.ts (83%) rename src/deploy/missions/contracts/{ => zns-base}/domain-token.ts (84%) rename src/deploy/missions/contracts/{ => zns-base}/fixed-pricer.ts (81%) rename src/deploy/missions/contracts/{ => zns-base}/meow-token/mainnet-data.ts (100%) rename src/deploy/missions/contracts/{ => zns-base}/meow-token/meow-token.ts (94%) rename src/deploy/missions/contracts/{ => zns-base}/registry.ts (80%) rename src/deploy/missions/contracts/{ => zns-base}/root-registrar.ts (90%) rename src/deploy/missions/contracts/{ => zns-base}/string-resolver.ts (89%) rename src/deploy/missions/contracts/{ => zns-base}/sub-registrar.ts (93%) rename src/deploy/missions/contracts/{ => zns-base}/treasury.ts (84%) diff --git a/src/deploy/campaign/environments.ts b/src/deploy/campaign/environments.ts index eba845c9a..d9fe6429f 100644 --- a/src/deploy/campaign/environments.ts +++ b/src/deploy/campaign/environments.ts @@ -18,7 +18,7 @@ import { } from "../../../test/helpers"; import { ethers } from "ethers"; import { ICurvePriceConfig } from "../missions/types"; -import { MeowMainnet } from "../missions/contracts/meow-token/mainnet-data"; +import { MeowMainnet } from "../missions/contracts/zns-base/meow-token/mainnet-data"; const getCustomAddresses = ( diff --git a/src/deploy/missions/contracts/chain-resolver.ts b/src/deploy/missions/contracts/cross-chain/chain-resolver.ts similarity index 89% rename from src/deploy/missions/contracts/chain-resolver.ts rename to src/deploy/missions/contracts/cross-chain/chain-resolver.ts index 91b005c1b..85c1d2291 100644 --- a/src/deploy/missions/contracts/chain-resolver.ts +++ b/src/deploy/missions/contracts/cross-chain/chain-resolver.ts @@ -1,9 +1,9 @@ -import { IZNSCampaignConfig, IZNSContracts } from "../../campaign/types"; +import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; import { BaseDeployMission } from "@zero-tech/zdc"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { ProxyKinds, ResolverTypes } from "../../constants"; -import { znsNames } from "./names"; +import { ProxyKinds, ResolverTypes } from "../../../constants"; +import { znsNames } from "../names"; export class ZNSChainResolverDM extends BaseDeployMission< diff --git a/src/deploy/missions/contracts/eth-portal.ts b/src/deploy/missions/contracts/cross-chain/eth-portal.ts similarity index 91% rename from src/deploy/missions/contracts/eth-portal.ts rename to src/deploy/missions/contracts/cross-chain/eth-portal.ts index 7cd7d7416..13819da13 100644 --- a/src/deploy/missions/contracts/eth-portal.ts +++ b/src/deploy/missions/contracts/cross-chain/eth-portal.ts @@ -1,9 +1,9 @@ import { BaseDeployMission, TDeployArgs } from "@zero-tech/zdc"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { IZNSCampaignConfig, IZNSContracts } from "../../campaign/types"; -import { PORTAL_ROLE, ProxyKinds } from "../../constants"; -import { znsNames } from "./names"; +import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; +import { PORTAL_ROLE, ProxyKinds } from "../../../constants"; +import { znsNames } from "../names"; export class ZNSEthereumPortalDM extends BaseDeployMission< diff --git a/src/deploy/missions/contracts/zchain-portal.ts b/src/deploy/missions/contracts/cross-chain/zchain-portal.ts similarity index 90% rename from src/deploy/missions/contracts/zchain-portal.ts rename to src/deploy/missions/contracts/cross-chain/zchain-portal.ts index 86b40c19a..b6af840b3 100644 --- a/src/deploy/missions/contracts/zchain-portal.ts +++ b/src/deploy/missions/contracts/cross-chain/zchain-portal.ts @@ -1,9 +1,9 @@ import { BaseDeployMission, TDeployArgs } from "@zero-tech/zdc"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { IZNSCampaignConfig, IZNSContracts } from "../../campaign/types"; -import { ProxyKinds } from "../../constants"; -import { znsNames } from "./names"; +import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; +import { ProxyKinds } from "../../../constants"; +import { znsNames } from "../names"; // TODO multi: figure out how to set EthereumPortal address on this contract after that is deployed !!! diff --git a/src/deploy/missions/contracts/zk-evm-bridge.ts b/src/deploy/missions/contracts/cross-chain/zk-evm-bridge.ts similarity index 92% rename from src/deploy/missions/contracts/zk-evm-bridge.ts rename to src/deploy/missions/contracts/cross-chain/zk-evm-bridge.ts index a2e83ce7f..0b6cf1fa4 100644 --- a/src/deploy/missions/contracts/zk-evm-bridge.ts +++ b/src/deploy/missions/contracts/cross-chain/zk-evm-bridge.ts @@ -1,9 +1,9 @@ import { BaseDeployMission, IDeployMissionArgs, TDeployArgs } from "@zero-tech/zdc"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { IZNSCampaignConfig, IZNSContracts } from "../../campaign/types"; -import { ProxyKinds } from "../../constants"; -import { znsNames } from "./names"; +import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; +import { ProxyKinds } from "../../../constants"; +import { znsNames } from "../names"; import { ethers } from "ethers"; diff --git a/src/deploy/missions/contracts/index.ts b/src/deploy/missions/contracts/index.ts index 2a684a19d..f7ec66ad7 100644 --- a/src/deploy/missions/contracts/index.ts +++ b/src/deploy/missions/contracts/index.ts @@ -1,11 +1,16 @@ -export * from "./address-resolver"; -export * from "./string-resolver"; -export * from "./registry"; -export * from "./root-registrar"; -export * from "./domain-token"; -export * from "./treasury"; -export * from "./curve-pricer"; -export * from "./access-controller"; -export * from "./meow-token/meow-token"; -export * from "./fixed-pricer"; -export * from "./sub-registrar"; +export * from "./zns-base/address-resolver"; +export * from "./zns-base/string-resolver"; +export * from "./zns-base/registry"; +export * from "./zns-base/root-registrar"; +export * from "./zns-base/domain-token"; +export * from "./zns-base/treasury"; +export * from "./zns-base/curve-pricer"; +export * from "./zns-base/access-controller"; +export * from "./zns-base/meow-token/meow-token"; +export * from "./zns-base/fixed-pricer"; +export * from "./zns-base/sub-registrar"; + +export * from "./cross-chain/chain-resolver"; +export * from "./cross-chain/zchain-portal"; +export * from "./cross-chain/eth-portal"; +export * from "./cross-chain/zk-evm-bridge"; diff --git a/src/deploy/missions/contracts/access-controller.ts b/src/deploy/missions/contracts/zns-base/access-controller.ts similarity index 85% rename from src/deploy/missions/contracts/access-controller.ts rename to src/deploy/missions/contracts/zns-base/access-controller.ts index 60586a16d..949974ca6 100644 --- a/src/deploy/missions/contracts/access-controller.ts +++ b/src/deploy/missions/contracts/zns-base/access-controller.ts @@ -1,10 +1,10 @@ import { BaseDeployMission, } from "@zero-tech/zdc"; -import { znsNames } from "./names"; +import { znsNames } from "../names"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { IZNSCampaignConfig, IZNSContracts } from "../../campaign/types"; +import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; export class ZNSAccessControllerDM extends BaseDeployMission< diff --git a/src/deploy/missions/contracts/address-resolver.ts b/src/deploy/missions/contracts/zns-base/address-resolver.ts similarity index 89% rename from src/deploy/missions/contracts/address-resolver.ts rename to src/deploy/missions/contracts/zns-base/address-resolver.ts index be22147f6..70c9bb25c 100644 --- a/src/deploy/missions/contracts/address-resolver.ts +++ b/src/deploy/missions/contracts/zns-base/address-resolver.ts @@ -2,10 +2,10 @@ import { BaseDeployMission, TDeployArgs, } from "@zero-tech/zdc"; -import { ProxyKinds, ResolverTypes } from "../../constants"; -import { znsNames } from "./names"; +import { ProxyKinds, ResolverTypes } from "../../../constants"; +import { znsNames } from "../names"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { IZNSCampaignConfig, IZNSContracts } from "../../campaign/types"; +import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; diff --git a/src/deploy/missions/contracts/curve-pricer.ts b/src/deploy/missions/contracts/zns-base/curve-pricer.ts similarity index 83% rename from src/deploy/missions/contracts/curve-pricer.ts rename to src/deploy/missions/contracts/zns-base/curve-pricer.ts index 8dee27dd2..c71b5270f 100644 --- a/src/deploy/missions/contracts/curve-pricer.ts +++ b/src/deploy/missions/contracts/zns-base/curve-pricer.ts @@ -2,11 +2,11 @@ import { BaseDeployMission, TDeployArgs, } from "@zero-tech/zdc"; -import { ProxyKinds } from "../../constants"; -import { znsNames } from "./names"; +import { ProxyKinds } from "../../../constants"; +import { znsNames } from "../names"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { IZNSCampaignConfig, IZNSContracts } from "../../campaign/types"; +import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; export class ZNSCurvePricerDM extends BaseDeployMission< diff --git a/src/deploy/missions/contracts/domain-token.ts b/src/deploy/missions/contracts/zns-base/domain-token.ts similarity index 84% rename from src/deploy/missions/contracts/domain-token.ts rename to src/deploy/missions/contracts/zns-base/domain-token.ts index 93af75a34..9871a222c 100644 --- a/src/deploy/missions/contracts/domain-token.ts +++ b/src/deploy/missions/contracts/zns-base/domain-token.ts @@ -2,11 +2,11 @@ import { BaseDeployMission, TDeployArgs, } from "@zero-tech/zdc"; -import { ProxyKinds } from "../../constants"; -import { znsNames } from "./names"; +import { ProxyKinds } from "../../../constants"; +import { znsNames } from "../names"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { IZNSCampaignConfig, IZNSContracts } from "../../campaign/types"; +import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; export class ZNSDomainTokenDM extends BaseDeployMission< diff --git a/src/deploy/missions/contracts/fixed-pricer.ts b/src/deploy/missions/contracts/zns-base/fixed-pricer.ts similarity index 81% rename from src/deploy/missions/contracts/fixed-pricer.ts rename to src/deploy/missions/contracts/zns-base/fixed-pricer.ts index 3f6e5e263..fe43c08a3 100644 --- a/src/deploy/missions/contracts/fixed-pricer.ts +++ b/src/deploy/missions/contracts/zns-base/fixed-pricer.ts @@ -1,12 +1,12 @@ -import { ProxyKinds } from "../../constants"; +import { ProxyKinds } from "../../../constants"; import { BaseDeployMission, TDeployArgs, } from "@zero-tech/zdc"; -import { znsNames } from "./names"; +import { znsNames } from "../names"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { IZNSCampaignConfig, IZNSContracts } from "../../campaign/types"; +import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; export class ZNSFixedPricerDM extends BaseDeployMission< HardhatRuntimeEnvironment, diff --git a/src/deploy/missions/contracts/meow-token/mainnet-data.ts b/src/deploy/missions/contracts/zns-base/meow-token/mainnet-data.ts similarity index 100% rename from src/deploy/missions/contracts/meow-token/mainnet-data.ts rename to src/deploy/missions/contracts/zns-base/meow-token/mainnet-data.ts diff --git a/src/deploy/missions/contracts/meow-token/meow-token.ts b/src/deploy/missions/contracts/zns-base/meow-token/meow-token.ts similarity index 94% rename from src/deploy/missions/contracts/meow-token/meow-token.ts rename to src/deploy/missions/contracts/zns-base/meow-token/meow-token.ts index 58eb0da58..3b4017768 100644 --- a/src/deploy/missions/contracts/meow-token/meow-token.ts +++ b/src/deploy/missions/contracts/zns-base/meow-token/meow-token.ts @@ -3,12 +3,12 @@ import { IDeployMissionArgs, TDeployArgs, } from "@zero-tech/zdc"; -import { ProxyKinds } from "../../../constants"; +import { ProxyKinds } from "../../../../constants"; import { ethers } from "ethers"; -import { znsNames } from "../names"; +import { znsNames } from "../../names"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; +import { IZNSCampaignConfig, IZNSContracts } from "../../../../campaign/types"; import { MeowToken__factory } from "@zero-tech/ztoken/typechain-js"; import meowArtifact from "@zero-tech/ztoken/artifacts/contracts/MeowToken.sol/MeowToken.json"; diff --git a/src/deploy/missions/contracts/registry.ts b/src/deploy/missions/contracts/zns-base/registry.ts similarity index 80% rename from src/deploy/missions/contracts/registry.ts rename to src/deploy/missions/contracts/zns-base/registry.ts index f9b99f6bd..12da13ce3 100644 --- a/src/deploy/missions/contracts/registry.ts +++ b/src/deploy/missions/contracts/zns-base/registry.ts @@ -2,11 +2,11 @@ import { BaseDeployMission, TDeployArgs, } from "@zero-tech/zdc"; -import { ProxyKinds } from "../../constants"; -import { znsNames } from "./names"; +import { ProxyKinds } from "../../../constants"; +import { znsNames } from "../names"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { IZNSCampaignConfig, IZNSContracts } from "../../campaign/types"; +import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; export class ZNSRegistryDM extends BaseDeployMission< diff --git a/src/deploy/missions/contracts/root-registrar.ts b/src/deploy/missions/contracts/zns-base/root-registrar.ts similarity index 90% rename from src/deploy/missions/contracts/root-registrar.ts rename to src/deploy/missions/contracts/zns-base/root-registrar.ts index 0bfd60b59..b9827cbdb 100644 --- a/src/deploy/missions/contracts/root-registrar.ts +++ b/src/deploy/missions/contracts/zns-base/root-registrar.ts @@ -2,11 +2,11 @@ import { BaseDeployMission, TDeployArgs, } from "@zero-tech/zdc"; -import { ProxyKinds, REGISTRAR_ROLE } from "../../constants"; -import { znsNames } from "./names"; +import { ProxyKinds, REGISTRAR_ROLE } from "../../../constants"; +import { znsNames } from "../names"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { IZNSCampaignConfig, IZNSContracts } from "../../campaign/types"; +import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; export class ZNSRootRegistrarDM extends BaseDeployMission< diff --git a/src/deploy/missions/contracts/string-resolver.ts b/src/deploy/missions/contracts/zns-base/string-resolver.ts similarity index 89% rename from src/deploy/missions/contracts/string-resolver.ts rename to src/deploy/missions/contracts/zns-base/string-resolver.ts index 305aaf5f4..9e2296731 100644 --- a/src/deploy/missions/contracts/string-resolver.ts +++ b/src/deploy/missions/contracts/zns-base/string-resolver.ts @@ -1,9 +1,9 @@ import { BaseDeployMission, TDeployArgs } from "@zero-tech/zdc"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { IZNSCampaignConfig, IZNSContracts } from "../../campaign/types"; -import { ProxyKinds, ResolverTypes } from "../../constants"; -import { znsNames } from "./names"; +import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; +import { ProxyKinds, ResolverTypes } from "../../../constants"; +import { znsNames } from "../names"; export class ZNSStringResolverDM extends BaseDeployMission< diff --git a/src/deploy/missions/contracts/sub-registrar.ts b/src/deploy/missions/contracts/zns-base/sub-registrar.ts similarity index 93% rename from src/deploy/missions/contracts/sub-registrar.ts rename to src/deploy/missions/contracts/zns-base/sub-registrar.ts index b1d0b0594..017971844 100644 --- a/src/deploy/missions/contracts/sub-registrar.ts +++ b/src/deploy/missions/contracts/zns-base/sub-registrar.ts @@ -2,11 +2,11 @@ import { BaseDeployMission, TDeployArgs, } from "@zero-tech/zdc"; -import { ProxyKinds, REGISTRAR_ROLE } from "../../constants"; -import { znsNames } from "./names"; +import { ProxyKinds, REGISTRAR_ROLE } from "../../../constants"; +import { znsNames } from "../names"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { IZNSCampaignConfig, IZNSContracts } from "../../campaign/types"; +import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; export class ZNSSubRegistrarDM extends BaseDeployMission< diff --git a/src/deploy/missions/contracts/treasury.ts b/src/deploy/missions/contracts/zns-base/treasury.ts similarity index 84% rename from src/deploy/missions/contracts/treasury.ts rename to src/deploy/missions/contracts/zns-base/treasury.ts index 86d7a612b..f2d84e0d1 100644 --- a/src/deploy/missions/contracts/treasury.ts +++ b/src/deploy/missions/contracts/zns-base/treasury.ts @@ -2,11 +2,11 @@ import { BaseDeployMission, TDeployArgs, } from "@zero-tech/zdc"; -import { ProxyKinds } from "../../constants"; -import { znsNames } from "./names"; +import { ProxyKinds } from "../../../constants"; +import { znsNames } from "../names"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { IZNSCampaignConfig, IZNSContracts } from "../../campaign/types"; +import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; export class ZNSTreasuryDM extends BaseDeployMission< diff --git a/test/DeployCampaignInt.test.ts b/test/DeployCampaignInt.test.ts index 32f86fcb6..5c8bd3b9d 100644 --- a/test/DeployCampaignInt.test.ts +++ b/test/DeployCampaignInt.test.ts @@ -34,10 +34,10 @@ import { ZNSDomainTokenDM, ZNSFixedPricerDM, ZNSRegistryDM, ZNSRootRegistrarDM, ZNSSubRegistrarDM, ZNSTreasuryDM, } from "../src/deploy/missions/contracts"; -import { ZNSStringResolverDM } from "../src/deploy/missions/contracts/string-resolver"; +import { ZNSStringResolverDM } from "../src/deploy/missions/contracts/zns-base/string-resolver"; import { znsNames } from "../src/deploy/missions/contracts/names"; import { runZnsCampaign } from "../src/deploy/zns-campaign"; -import { MeowMainnet } from "../src/deploy/missions/contracts/meow-token/mainnet-data"; +import { MeowMainnet } from "../src/deploy/missions/contracts/zns-base/meow-token/mainnet-data"; import { ResolverTypes } from "../src/deploy/constants"; import { getConfig } from "../src/deploy/campaign/environments"; import { ethers } from "ethers"; From 502293bb99773cfcf4ab5675b2cdd2fa5dbb4efd Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 23 Oct 2024 14:28:03 -0700 Subject: [PATCH 067/124] convert bridge mock into a proxy --- .../cross-chain/mock/PolygonZkEVMBridgeV2Mock.sol | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/contracts/cross-chain/mock/PolygonZkEVMBridgeV2Mock.sol b/contracts/cross-chain/mock/PolygonZkEVMBridgeV2Mock.sol index 1c8a7928b..8647db007 100644 --- a/contracts/cross-chain/mock/PolygonZkEVMBridgeV2Mock.sol +++ b/contracts/cross-chain/mock/PolygonZkEVMBridgeV2Mock.sol @@ -4,11 +4,12 @@ pragma solidity 0.8.26; // This is here only to bring the contract so Hardhat compiles it by default import { IBridgeMessageReceiver } from "@zero-tech/zkevm-contracts/contracts/interfaces/IBridgeMessageReceiver.sol"; import { ERC20Mock } from "../../token/mocks/ERC20Mock.sol"; +import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; // Note that this does NOT inherit the original Bridge contract! // We are EMULATING bridge behavior here so we can run tests on the same chain -contract PolygonZkEVMBridgeV2Mock { +contract PolygonZkEVMBridgeV2Mock is ReentrancyGuardUpgradeable { error NoValueInMessagesOnGasTokenNetworks(); error DestinationNetworkInvalid(); error MessageFailed(); @@ -42,10 +43,15 @@ contract PolygonZkEVMBridgeV2Mock { // WETH address ERC20Mock public WETHToken; - constructor( + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + function initialize( uint32 _networkID, address _WETHToken - ) { + ) external initializer { networkID = _networkID; WETHToken = ERC20Mock(_WETHToken); } From 72d390d6c87d2de808082db3b7b6d9639fbba167 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 23 Oct 2024 14:28:49 -0700 Subject: [PATCH 068/124] move portal and bridge DMs to a new folder and refine --- .../cross-chain/{ => portals}/eth-portal.ts | 18 ++++++++------- .../cross-chain/portals/get-portal-dm.ts | 21 ++++++++++++++++++ .../contracts/cross-chain/portals/types.ts | 6 +++++ .../{ => portals}/zchain-portal.ts | 22 ++++++++++--------- .../contracts/cross-chain/zk-evm-bridge.ts | 14 +++++++++--- src/deploy/missions/contracts/index.ts | 4 ++-- 6 files changed, 62 insertions(+), 23 deletions(-) rename src/deploy/missions/contracts/cross-chain/{ => portals}/eth-portal.ts (80%) create mode 100644 src/deploy/missions/contracts/cross-chain/portals/get-portal-dm.ts create mode 100644 src/deploy/missions/contracts/cross-chain/portals/types.ts rename src/deploy/missions/contracts/cross-chain/{ => portals}/zchain-portal.ts (75%) diff --git a/src/deploy/missions/contracts/cross-chain/eth-portal.ts b/src/deploy/missions/contracts/cross-chain/portals/eth-portal.ts similarity index 80% rename from src/deploy/missions/contracts/cross-chain/eth-portal.ts rename to src/deploy/missions/contracts/cross-chain/portals/eth-portal.ts index 13819da13..dd4b49d85 100644 --- a/src/deploy/missions/contracts/cross-chain/eth-portal.ts +++ b/src/deploy/missions/contracts/cross-chain/portals/eth-portal.ts @@ -1,9 +1,9 @@ import { BaseDeployMission, TDeployArgs } from "@zero-tech/zdc"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; -import { PORTAL_ROLE, ProxyKinds } from "../../../constants"; -import { znsNames } from "../names"; +import { IZNSCampaignConfig, IZNSContracts, IZNSZChainCrossConfig } from "../../../../campaign/types"; +import { PORTAL_ROLE, ProxyKinds } from "../../../../constants"; +import { znsNames } from "../../names"; export class ZNSEthereumPortalDM extends BaseDeployMission< @@ -29,15 +29,17 @@ IZNSContracts subRegistrar, zkEvmBridge, config: { - crosschain: { - destZkEvmBridge, - srcZnsPortal, - }, + crosschain, }, } = this.campaign; + const { + zkEvmBridgeAddress, + srcZnsPortal, + } = crosschain as IZNSZChainCrossConfig; + // TODO multi: figure out proper handling of this for actual contract AND mock !!! - const bridgeAddress = !destZkEvmBridge ? await zkEvmBridge.getAddress() : destZkEvmBridge; + const bridgeAddress = !zkEvmBridgeAddress ? await zkEvmBridge.getAddress() : zkEvmBridgeAddress; return [ await accessController.getAddress(), diff --git a/src/deploy/missions/contracts/cross-chain/portals/get-portal-dm.ts b/src/deploy/missions/contracts/cross-chain/portals/get-portal-dm.ts new file mode 100644 index 000000000..ad1546f69 --- /dev/null +++ b/src/deploy/missions/contracts/cross-chain/portals/get-portal-dm.ts @@ -0,0 +1,21 @@ +import { ZNSZChainPortalDM } from "./zchain-portal"; +import { ZNSEthereumPortalDM } from "./eth-portal"; +import { ISupportedChains, TSupportedChain } from "./types"; + + +export const SupportedChains : ISupportedChains = { + z: "ZChain", + eth: "Ethereum", +}; + + +export const getPortalDM = (chainName : TSupportedChain) => { + switch (chainName) { + case SupportedChains.eth: + return ZNSZChainPortalDM; + case SupportedChains.z: + return ZNSEthereumPortalDM; + default: + throw new Error(`Unknown unsupported chain: ${chainName}!`); + } +}; diff --git a/src/deploy/missions/contracts/cross-chain/portals/types.ts b/src/deploy/missions/contracts/cross-chain/portals/types.ts new file mode 100644 index 000000000..9cd37a5ab --- /dev/null +++ b/src/deploy/missions/contracts/cross-chain/portals/types.ts @@ -0,0 +1,6 @@ +export type TSupportedChain = "ZChain" | "Ethereum"; +export interface ISupportedChains { + z : TSupportedChain; + eth : TSupportedChain; +} + diff --git a/src/deploy/missions/contracts/cross-chain/zchain-portal.ts b/src/deploy/missions/contracts/cross-chain/portals/zchain-portal.ts similarity index 75% rename from src/deploy/missions/contracts/cross-chain/zchain-portal.ts rename to src/deploy/missions/contracts/cross-chain/portals/zchain-portal.ts index b6af840b3..c63ae720a 100644 --- a/src/deploy/missions/contracts/cross-chain/zchain-portal.ts +++ b/src/deploy/missions/contracts/cross-chain/portals/zchain-portal.ts @@ -1,9 +1,9 @@ import { BaseDeployMission, TDeployArgs } from "@zero-tech/zdc"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; -import { ProxyKinds } from "../../../constants"; -import { znsNames } from "../names"; +import { IZNSCampaignConfig, IZNSContracts, IZNSEthCrossConfig } from "../../../../campaign/types"; +import { ProxyKinds } from "../../../../constants"; +import { znsNames } from "../../names"; // TODO multi: figure out how to set EthereumPortal address on this contract after that is deployed !!! @@ -31,17 +31,19 @@ IZNSContracts subRegistrar, zkEvmBridge, config: { - crosschain: { - destNetworkId, - destChainName, - destChainId, - srcZkEvmBridge, - }, + crosschain, }, } = this.campaign; + const { + destNetworkId, + destChainName, + destChainId, + zkEvmBridgeAddress, + } = crosschain as IZNSEthCrossConfig; + // TODO multi: figure out proper handling of this for actual contract AND mock !!! - const bridgeAddress = !srcZkEvmBridge ? await zkEvmBridge.getAddress() : srcZkEvmBridge; + const bridgeAddress = !zkEvmBridgeAddress ? await zkEvmBridge.getAddress() : zkEvmBridgeAddress; return [ destNetworkId, diff --git a/src/deploy/missions/contracts/cross-chain/zk-evm-bridge.ts b/src/deploy/missions/contracts/cross-chain/zk-evm-bridge.ts index 0b6cf1fa4..60499f2c0 100644 --- a/src/deploy/missions/contracts/cross-chain/zk-evm-bridge.ts +++ b/src/deploy/missions/contracts/cross-chain/zk-evm-bridge.ts @@ -36,12 +36,20 @@ IZNSContracts async deploy () { if (!this.config.crosschain.mockZkEvmBridge) { + const { + crosschain: { + zkEvmBridgeAddress, + }, + } = this.config; + this.logger.info("Using PolygonZkEvmBridgeV2 deployed on chain"); + if (!zkEvmBridgeAddress) throw new Error("No existing ZkEvmBridge address has been passed!"); + this.logger.debug(`Writing ${this.contractName} to DB...`); const factory = await this.campaign.deployer.getFactory(this.contractName); - const contract = factory.attach(this.config.crosschain.zkEvmBridgeAddress); + const contract = factory.attach(zkEvmBridgeAddress); await this.saveToDB(contract); @@ -58,7 +66,7 @@ IZNSContracts // this is ONLY for the Mock version of the Bridge ! const { crosschain: { - srcNetworkId, + curNetworkId, bridgeToken, }, } = this.config; @@ -66,7 +74,7 @@ IZNSContracts const tokenAddress = !bridgeToken ? ethers.ZeroAddress : bridgeToken; return [ - srcNetworkId, + curNetworkId as bigint, tokenAddress, ]; } diff --git a/src/deploy/missions/contracts/index.ts b/src/deploy/missions/contracts/index.ts index f7ec66ad7..b067c2b45 100644 --- a/src/deploy/missions/contracts/index.ts +++ b/src/deploy/missions/contracts/index.ts @@ -11,6 +11,6 @@ export * from "./zns-base/fixed-pricer"; export * from "./zns-base/sub-registrar"; export * from "./cross-chain/chain-resolver"; -export * from "./cross-chain/zchain-portal"; -export * from "./cross-chain/eth-portal"; +export * from "./cross-chain/portals/zchain-portal"; +export * from "./cross-chain/portals/eth-portal"; export * from "./cross-chain/zk-evm-bridge"; From 7869919169a10ea8e16f22ef800b4ce4b25a4cf8 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 23 Oct 2024 14:29:18 -0700 Subject: [PATCH 069/124] create config builder for cross chain data along with new types --- src/deploy/campaign/environments.ts | 78 +++++++++++++++++++++++++++-- src/deploy/campaign/types.ts | 36 ++++++++----- 2 files changed, 97 insertions(+), 17 deletions(-) diff --git a/src/deploy/campaign/environments.ts b/src/deploy/campaign/environments.ts index d9fe6429f..df4e2736c 100644 --- a/src/deploy/campaign/environments.ts +++ b/src/deploy/campaign/environments.ts @@ -1,6 +1,12 @@ import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { IZNSCampaignConfig } from "./types"; +import { + IZNSBaseCrossConfig, + IZNSCampaignConfig, + IZNSEthCrossConfig, + IZNSZChainCrossConfig, + TZNSCrossConfig, +} from "./types"; import { DEFAULT_PROTOCOL_FEE_PERCENT, DEFAULT_ROYALTY_FRACTION, @@ -19,6 +25,8 @@ import { import { ethers } from "ethers"; import { ICurvePriceConfig } from "../missions/types"; import { MeowMainnet } from "../missions/contracts/zns-base/meow-token/mainnet-data"; +import { TSupportedChain } from "../missions/contracts/cross-chain/portals/types"; +import { SupportedChains } from "../missions/contracts/cross-chain/portals/get-portal-dm"; const getCustomAddresses = ( @@ -77,16 +85,16 @@ export const getConfig = async ({ deployerAddress = await deployer.getAddress(); } - let zeroVaultAddressConf; + let zeroVaultAddressConf : string; if (process.env.ENV_LEVEL === "dev") { requires( !!zeroVaultAddress || !!process.env.ZERO_VAULT_ADDRESS, "Must pass `zeroVaultAddress` to `getConfig()` for `dev` environment" ); - zeroVaultAddressConf = zeroVaultAddress || process.env.ZERO_VAULT_ADDRESS; + zeroVaultAddressConf = zeroVaultAddress || process.env.ZERO_VAULT_ADDRESS!; } else { - zeroVaultAddressConf = process.env.ZERO_VAULT_ADDRESS; + zeroVaultAddressConf = process.env.ZERO_VAULT_ADDRESS!; } // Domain Token Values @@ -122,6 +130,7 @@ export const getConfig = async ({ monitorContracts: process.env.MONITOR_CONTRACTS === "true", verifyContracts: process.env.VERIFY_CONTRACTS === "true", }, + crosschain: buildCrosschainConfig(), }; return config; @@ -268,3 +277,64 @@ const validatePrice = (config : ICurvePriceConfig) => { // if B > A, then the price spike is invalid return (priceB <= priceA); }; + +export const buildCrosschainConfig = () : TZNSCrossConfig => { + requires(!!process.env.SRC_CHAIN_NAME, "Must provide name for the chain to deploy to!"); + const srcChainName = process.env.SRC_CHAIN_NAME as TSupportedChain; + requires(!!process.env.MOCK_ZKEVM_BRIDGE, "Must provide mock polygon bridge flag!"); + const mockZkEvmBridge = process.env.MOCK_ZKEVM_BRIDGE === "true"; + + let curNetworkId; + let zkEvmBridgeAddress; + if (!mockZkEvmBridge) { + requires( + !!process.env.ZK_EVM_BRIDGE, + "Must provide source zkEVM bridge address from this chain if not mocking!" + ); + zkEvmBridgeAddress = process.env.ZK_EVM_BRIDGE; + } else { + requires( + !!process.env.NETWORK_ID, + "Must provide current network ID for mocked bridge!" + ); + curNetworkId = BigInt(process.env.NETWORK_ID!); + } + + const baseConfig = { + mockZkEvmBridge, + srcChainName, + zkEvmBridgeAddress, + curNetworkId, + bridgeToken: process.env.BRIDGE_TOKEN, + }; + + let crossConfig; + switch (srcChainName) { + case SupportedChains.eth: + requires(!!process.env.DEST_NETWORK_ID, "Must provide destination network ID!"); + requires(!!process.env.DEST_CHAIN_NAME, "Must provide destination chain name!"); + requires(!!process.env.DEST_CHAIN_ID, "Must provide destination chain ID!"); + + crossConfig = { + ...baseConfig, + destNetworkId: BigInt(process.env.DEST_NETWORK_ID!), + destChainName: process.env.DEST_CHAIN_NAME, + destChainId: BigInt(process.env.DEST_CHAIN_ID!), + } as IZNSEthCrossConfig; + + break; + case SupportedChains.z: + requires(!!process.env.SRC_ZNS_PORTAL, "Must provide source ZNSZChainPortal address!"); + + crossConfig = { + ...baseConfig, + srcZnsPortal: process.env.SRC_ZNS_PORTAL, + } as IZNSZChainCrossConfig; + + break; + default: + throw new Error(`Unsupported chain: ${srcChainName}!`); + } + + return crossConfig; +}; diff --git a/src/deploy/campaign/types.ts b/src/deploy/campaign/types.ts index 00ef6dce5..bc9425acd 100644 --- a/src/deploy/campaign/types.ts +++ b/src/deploy/campaign/types.ts @@ -16,9 +16,30 @@ import { MeowToken, ZNSStringResolver, ZNSZChainPortal, ZNSEthereumPortal, PolygonZkEVMBridgeV2Mock, ZNSChainResolver, } from "../../../typechain"; +import { TSupportedChain } from "../missions/contracts/cross-chain/portals/types"; export type IZNSSigner = HardhatEthersSigner | DefenderRelaySigner | SignerWithAddress; +export interface IZNSBaseCrossConfig { + mockZkEvmBridge : boolean; + zkEvmBridgeAddress ?: string; + srcChainName : TSupportedChain; + curNetworkId ?: bigint; + bridgeToken ?: string; +} + +export interface IZNSEthCrossConfig extends IZNSBaseCrossConfig { + destNetworkId : bigint; + destChainName : string; + destChainId : bigint; +} + +export interface IZNSZChainCrossConfig extends IZNSBaseCrossConfig { + srcZnsPortal : string; +} + +export type TZNSCrossConfig = IZNSEthCrossConfig | IZNSZChainCrossConfig; + export interface IZNSCampaignConfig extends IDeployCampaignConfig { env : string; deployAdmin : Signer; @@ -34,19 +55,7 @@ export interface IZNSCampaignConfig extends IDeployCampaignConfig { subRegistrar : ZNSSubRegistrar; zPortal : ZNSZChainPortal; ethPortal : ZNSEthereumPortal; + zkEvmBridge : PolygonZkEVMBridgeV2Mock; } From 32c0aa5957e6a8753818c84a1a3b9675fb56dedc Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 23 Oct 2024 14:29:40 -0700 Subject: [PATCH 070/124] extend ZNS deploy function to support new contracts --- src/deploy/zns-campaign.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/deploy/zns-campaign.ts b/src/deploy/zns-campaign.ts index a93dd339c..39cff28a7 100644 --- a/src/deploy/zns-campaign.ts +++ b/src/deploy/zns-campaign.ts @@ -11,11 +11,12 @@ import { ZNSAddressResolverDM, ZNSStringResolverDM, ZNSDomainTokenDM, ZNSCurvePricerDM, ZNSRootRegistrarDM, - ZNSRegistryDM, ZNSTreasuryDM, ZNSFixedPricerDM, ZNSSubRegistrarDM, + ZNSRegistryDM, ZNSTreasuryDM, ZNSFixedPricerDM, ZNSSubRegistrarDM, PolygonZkEVMBridgeV2DM, ZNSChainResolverDM, } from "./missions/contracts"; import { IZNSCampaignConfig, IZNSContracts } from "./campaign/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { getZnsMongoAdapter } from "./mongo"; +import { getPortalDM } from "./missions/contracts/cross-chain/portals/get-portal-dm"; export const runZnsCampaign = async ({ @@ -57,8 +58,11 @@ export const runZnsCampaign = async ({ ZNSCurvePricerDM, ZNSTreasuryDM, ZNSRootRegistrarDM, - ZNSFixedPricerDM, ZNSSubRegistrarDM, + ZNSFixedPricerDM, + ZNSChainResolverDM, + PolygonZkEVMBridgeV2DM, + getPortalDM(config.crosschain.srcChainName), ], deployer, dbAdapter, @@ -70,5 +74,8 @@ export const runZnsCampaign = async ({ await dbAdapter.finalize(dbVersion); + // TODO multi: add setting L2 portal address on L1 portal here for prod !!!!!! + // find a good way to acquire this from the DB or something else possibly + return campaign; }; From ca59e36f7bddef573e74e059685f9ad3a749a121 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 23 Oct 2024 14:30:14 -0700 Subject: [PATCH 071/124] convert tests to use Campaign deploy --- test/L2-BRIDGE-TEST/MultiZNS.test.ts | 200 ++++++--------------------- 1 file changed, 40 insertions(+), 160 deletions(-) diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts index d0f3f073a..0baeb2bae 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -14,27 +14,10 @@ import { } from "../helpers"; import { expect } from "chai"; import * as ethers from "ethers"; -import { - PolygonZkEVMBridgeV2Mock, - PolygonZkEVMBridgeV2Mock__factory, - ZNSChainResolver, - ZNSChainResolver__factory, ZNSEthereumPortal, - ZNSEthereumPortal__factory, ZNSPolygonZkEvmPortal, - ZNSZChainPortal__factory, -} from "../../typechain"; import { getDomainHashFromEvent, getEvents } from "../helpers/events"; -import { AddressLike, ContractTransactionReceipt } from "ethers"; -import { PORTAL_ROLE, ResolverTypes } from "../../src/deploy/constants"; - - -// TODO multi: move below code to appropriate places -// some of these may be optional ?? -export interface IZNSContractsExtended extends IZNSContracts { - zPortal : ZNSPolygonZkEvmPortal; - bridgeL1 : PolygonZkEVMBridgeV2Mock; - ethPortal : ZNSEthereumPortal; - bridgeL2 : PolygonZkEVMBridgeV2Mock; -} +import { ContractTransactionReceipt } from "ethers"; +import { SupportedChains } from "../../src/deploy/missions/contracts/cross-chain/portals/get-portal-dm"; +import { resetMongoAdapter } from "@zero-tech/zdc"; export const NETWORK_ID_L1_DEFAULT = 1n; @@ -44,102 +27,19 @@ const zChainID = 336699n; const zChainName = "ZChain"; -// TODO multi: add this to the Campaign properly !!! -export const deployCrossChainContracts = async ({ - deployer, - znsL1, - chainResolverAddressL1, - znsL2, - srcNetworkId = NETWORK_ID_L1_DEFAULT, - destNetworkId = NETWORK_ID_L2_DEFAULT, - wethTokenAddress = hre.ethers.ZeroAddress, - destChainName = zChainName, - destChainId = zChainID, -} : { - deployer : SignerWithAddress; - znsL1 : IZNSContracts; - chainResolverAddressL1 : AddressLike; - znsL2 : IZNSContracts; - srcNetworkId ?: bigint; - destNetworkId ?: bigint; - wethTokenAddress ?: string; - destChainName ?: string; - destChainId ?: bigint; -}) => { - const zPortalFact = new ZNSZChainPortal__factory(deployer); - const ethPortalFact = new ZNSEthereumPortal__factory(deployer); - const bridgeMockFact = new PolygonZkEVMBridgeV2Mock__factory(deployer); - - const bridgeL1 = await bridgeMockFact.deploy( - srcNetworkId, - wethTokenAddress, - ); - await bridgeL1.waitForDeployment(); - const bridgeL2 = await bridgeMockFact.deploy( - destNetworkId, - wethTokenAddress, - ); - await bridgeL2.waitForDeployment(); - - const zPortal = await hre.upgrades.deployProxy( - zPortalFact, - [ - destNetworkId, - destChainName, - destChainId, - bridgeL1.target, - { - accessController: znsL1.accessController.target, - rootRegistrar: znsL1.rootRegistrar.target, - subRegistrar: znsL1.subRegistrar.target, - treasury: znsL1.treasury.target, - chainResolver: chainResolverAddressL1, - registry: znsL1.registry.target, - }, - ], - { - kind: "uups", - } - ) as unknown as ZNSPolygonZkEvmPortal; - await zPortal.waitForDeployment(); - - const ethPortal = await hre.upgrades.deployProxy( - ethPortalFact, - [ - znsL2.accessController.target, - bridgeL2.target, - zPortal.target, - znsL2.registry.target, - znsL2.domainToken.target, - znsL2.rootRegistrar.target, - znsL2.subRegistrar.target, - ], - { - kind: "uups", - } - ) as unknown as ZNSEthereumPortal; - await ethPortal.waitForDeployment(); - - // link portals - await zPortal.connect(deployer).setDestZnsPortal(ethPortal.target); - - // give Role to the Portal on L2 to call special function - await znsL2.accessController.connect(deployer).grantRole( - PORTAL_ROLE, - ethPortal.target - ); - - return { - zPortal, - ethPortal, - bridgeL1, - bridgeL2, - }; +const resetEnvVars = () => { + delete process.env.SRC_CHAIN_NAME; + delete process.env.MOCK_ZKEVM_BRIDGE; + delete process.env.NETWORK_ID; + delete process.env.DEST_NETWORK_ID; + delete process.env.DEST_CHAIN_NAME; + delete process.env.DEST_CHAIN_ID; + delete process.env.SRC_ZNS_PORTAL; }; describe.only("MultiZNS", () => { - let znsL1 : IZNSContractsExtended; - let znsL2 : IZNSContractsExtended; + let znsL1 : IZNSContracts; + let znsL2 : IZNSContracts; let deployAdmin : SignerWithAddress; let user : SignerWithAddress; @@ -164,11 +64,17 @@ describe.only("MultiZNS", () => { globalIndex : bigint; }; - let chainResolver : ZNSChainResolver; - before(async () => { [ deployAdmin, user, subUser ] = await hre.ethers.getSigners(); + // set ENV vars for the Ethereum ZNS deployment + process.env.SRC_CHAIN_NAME = SupportedChains.eth; + process.env.MOCK_ZKEVM_BRIDGE = "true"; + process.env.NETWORK_ID = NETWORK_ID_L1_DEFAULT.toString(); + process.env.DEST_NETWORK_ID = NETWORK_ID_L2_DEFAULT.toString(); + process.env.DEST_CHAIN_NAME = SupportedChains.z; + process.env.DEST_CHAIN_ID = zChainID.toString(); + config = await getConfig({ deployer: deployAdmin, zeroVaultAddress: deployAdmin.address, @@ -178,22 +84,13 @@ describe.only("MultiZNS", () => { znsL1 = campaignL1.state.contracts; - // TODO multi: add deploy mission for ChainResolver if decided to leave it! - const chainResFact = new ZNSChainResolver__factory(deployAdmin); - chainResolver = await hre.upgrades.deployProxy( - chainResFact, - [ - znsL1.accessController.target, - znsL1.registry.target, - ], - { - kind: "uups", - } - ) as unknown as ZNSChainResolver; - await chainResolver.waitForDeployment(); - - // TODO multi: add constants/enums for Resolver Types and possibly to Registry as well !!! - await znsL1.registry.connect(deployAdmin).addResolverType(ResolverTypes.chain, chainResolver.target); + resetMongoAdapter(); + + // set vars for ZChain ZNS deployment + process.env.SRC_CHAIN_NAME = SupportedChains.z; + process.env.SRC_ZNS_PORTAL = znsL1.zPortal.target as string; + process.env.NETWORK_ID = NETWORK_ID_L2_DEFAULT.toString(); + process.env.MONGO_DB_NAME = "zns-l2"; config = await getConfig({ deployer: deployAdmin, @@ -205,33 +102,12 @@ describe.only("MultiZNS", () => { znsL2 = campaignL2.state.contracts; + // set L2 portal address on L1 + await znsL1.zPortal.connect(deployAdmin).setDestZnsPortal(znsL2.ethPortal.target); + await znsL2.meowToken.mint(deployAdmin.address, 1000000000000000000000n); await znsL2.meowToken.connect(deployAdmin).approve(znsL2.treasury.target, ethers.MaxUint256); - const { - zPortal, - ethPortal, - bridgeL1, - bridgeL2, - } = await deployCrossChainContracts({ - deployer: deployAdmin, - znsL1, - chainResolverAddressL1: chainResolver.target, - znsL2, - }); - - znsL1 = { - ...znsL1, - zPortal, - bridgeL1, - }; - - znsL2 = { - ...znsL2, - ethPortal, - bridgeL2, - }; - await znsL1.meowToken.mint(deployAdmin.address, 1000000000000000000000n); await znsL1.meowToken.connect(deployAdmin).approve(znsL1.zPortal.target, ethers.MaxUint256); await znsL1.meowToken.connect(deployAdmin).approve(znsL1.treasury.target, ethers.MaxUint256); @@ -240,6 +116,10 @@ describe.only("MultiZNS", () => { await znsL1.meowToken.connect(user).approve(znsL1.zPortal.target, ethers.MaxUint256); }); + after(async () => { + resetEnvVars(); + }); + [ { name: "Root Domain", @@ -324,7 +204,7 @@ describe.only("MultiZNS", () => { expect(event.args.domainOwner).to.equal(user.address); const bridgeEvents = await getEvents({ - contract: znsL1.bridgeL1, + contract: znsL1.zkEvmBridge, eventName: "BridgeEvent", }); ({ args: bridgedEventData } = bridgeEvents[bridgeEvents.length - 1]); @@ -354,7 +234,7 @@ describe.only("MultiZNS", () => { resolver: resolverL1, } = await znsL1.registry.getDomainRecord(domainHash); expect(ownerL1).to.equal(znsL1.zPortal.target); - expect(resolverL1).to.equal(chainResolver.target); + expect(resolverL1).to.equal(znsL1.chainResolver.target); const tokenOwner = await znsL1.domainToken.ownerOf(BigInt(domainHash)); expect(tokenOwner).to.equal(znsL1.zPortal.target); @@ -382,7 +262,7 @@ describe.only("MultiZNS", () => { }); it("should properly set data in ChainResolver", async () => { - const chainData = await chainResolver.resolveChainDataStruct(domainHash); + const chainData = await znsL1.chainResolver.resolveChainDataStruct(domainHash); expect(chainData.chainId).to.equal(zChainID); expect(chainData.chainName).to.equal(zChainName); expect(chainData.znsRegistryOnChain).to.equal(hre.ethers.ZeroAddress); @@ -446,7 +326,7 @@ describe.only("MultiZNS", () => { // **NOTE** that we connect as `deployAdmin` here to show that it's not // required that this has to be called by the original owner, // it can be called by anyone - await znsL2.bridgeL2.connect(deployAdmin).claimMessage( + await znsL2.zkEvmBridge.connect(deployAdmin).claimMessage( dummySmtProof, dummySmtProof, bridgedEventData.globalIndex, @@ -461,7 +341,7 @@ describe.only("MultiZNS", () => { ); const events = await getEvents({ - contract: znsL2.bridgeL2, + contract: znsL2.zkEvmBridge, eventName: "ClaimEvent", }); const event = events[events.length - 1]; From 24274b22d906b77396dca8580b23ac5578868a0f Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 23 Oct 2024 16:33:04 -0700 Subject: [PATCH 072/124] add new unit tests --- hardhat.config.ts | 2 +- test/L2-BRIDGE-TEST/MultiZNS.test.ts | 188 +++++++++++++++++++++++++-- test/helpers/errors.ts | 5 + 3 files changed, 186 insertions(+), 9 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index f5fcd3c4a..46c67fec3 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -49,7 +49,7 @@ const config : HardhatUserConfig = { enabled: true, runs: 20000, }, - // TODO: we are not using this, but solcover gives an error if we don't have it + // TODO multi: we are not using this, but solcover gives an error if we don't have it // figure out what to do here for it to work in CI! // viaIR: true, }, diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts index 0baeb2bae..013bf4ce2 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -1,16 +1,32 @@ import * as hre from "hardhat"; import { getConfig } from "../../src/deploy/campaign/environments"; import { runZnsCampaign } from "../../src/deploy/zns-campaign"; -import { IZNSCampaignConfig, IZNSContracts } from "../../src/deploy/campaign/types"; +import { + IZNSCampaignConfig, + IZNSContracts, + IZNSEthCrossConfig, + IZNSZChainCrossConfig, +} from "../../src/deploy/campaign/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { registrationWithSetup } from "../helpers/register-setup"; import { - AccessType, DEFAULT_PRICE_CONFIG, DEFAULT_TOKEN_URI, + AccessType, + DEFAULT_PRICE_CONFIG, + DEFAULT_TOKEN_URI, distrConfigEmpty, DISTRIBUTION_LOCKED_NOT_EXIST_ERR, - fullDistrConfigEmpty, getCurvePrice, getStakingOrProtocolFee, + DOMAIN_HASH_NO_MATCH_ERR, + fullDistrConfigEmpty, + getCurvePrice, + getStakingOrProtocolFee, + hashDomainLabel, + INITIALIZED_ERR, + INVALID_CALLER_ERR, + INVALID_ORIGIN_ERR, NOT_AUTHORIZED_ERR, - NOT_OWNER_OF_ERR, PaymentType, + NOT_OWNER_OF_ERR, + PaymentType, + ZERO_ADDRESS_ERR, } from "../helpers"; import { expect } from "chai"; import * as ethers from "ethers"; @@ -24,7 +40,6 @@ export const NETWORK_ID_L1_DEFAULT = 1n; export const NETWORK_ID_L2_DEFAULT = 369n; const zChainID = 336699n; -const zChainName = "ZChain"; const resetEnvVars = () => { @@ -51,6 +66,8 @@ describe.only("MultiZNS", () => { const subdomainLabel = "beaubridges"; const subParentLabel = "bridges"; + const dummySmtProof = Array.from({ length: 32 }, () => hre.ethers.randomBytes(32)); + let balanceBeforeBridge : bigint; let bridgedEventData : { @@ -264,7 +281,7 @@ describe.only("MultiZNS", () => { it("should properly set data in ChainResolver", async () => { const chainData = await znsL1.chainResolver.resolveChainDataStruct(domainHash); expect(chainData.chainId).to.equal(zChainID); - expect(chainData.chainName).to.equal(zChainName); + expect(chainData.chainName).to.equal(SupportedChains.z); expect(chainData.znsRegistryOnChain).to.equal(hre.ethers.ZeroAddress); expect(chainData.auxData).to.equal(""); }); @@ -320,8 +337,6 @@ describe.only("MultiZNS", () => { }); describe("Claim Bridged Domain on L2", () => { - const dummySmtProof = Array.from({ length: 32 }, () => hre.ethers.randomBytes(32)); - it("should #claimMessage() on the bridge successfully and fire a ClaimEvent", async () => { // **NOTE** that we connect as `deployAdmin` here to show that it's not // required that this has to be called by the original owner, @@ -459,4 +474,161 @@ describe.only("MultiZNS", () => { }); }); }); + + describe("Unit Tests", () => { + describe("ZNSZChainPortal", () => { + it.only("#initialize() should revert when trying to reinitialize", async () => { + const { + destNetworkId, + destChainName, + destChainId, + } = config.crosschain as IZNSEthCrossConfig; + + await expect( + znsL1.zPortal.connect(deployAdmin).initialize( + destNetworkId, + destChainName, + destChainId, + await znsL1.zkEvmBridge.getAddress(), + { + accessController: await znsL1.accessController.getAddress(), + registry: await znsL1.registry.getAddress(), + chainResolver: await znsL1.chainResolver.getAddress(), + treasury: await znsL1.treasury.getAddress(), + rootRegistrar: await znsL1.rootRegistrar.getAddress(), + subRegistrar: await znsL1.subRegistrar.getAddress(), + } + ) + ).to.be.revertedWithCustomError(znsL1.zPortal, INITIALIZED_ERR); + }); + + it("#initialize() should revert when passing 0x0 addresses", async () => { + const { + destNetworkId, + destChainName, + destChainId, + } = config.crosschain as IZNSEthCrossConfig; + + await expect( + znsL1.zPortal.connect(deployAdmin).initialize( + destNetworkId, + destChainName, + destChainId, + hre.ethers.ZeroAddress, + { + accessController: znsL1.accessController.target, + registry: znsL1.registry.target, + chainResolver: znsL1.chainResolver.target, + rootRegistrar: znsL1.rootRegistrar.target, + subRegistrar: znsL1.subRegistrar.target, + treasury: znsL1.treasury.target, + } + ) + ).to.be.revertedWithCustomError(znsL1.zPortal, ZERO_ADDRESS_ERR); + }); + + it("#setDestZnsPortal() should revert when called by non-ADMIN", async () => { + await expect( + znsL1.zPortal.connect(user).setDestZnsPortal(znsL2.ethPortal.target) + ).to.be.revertedWithCustomError(znsL1.zPortal, NOT_AUTHORIZED_ERR); + }); + + it("#setDestZnsPortal() should revert when setting 0x0 address", async () => { + await expect( + znsL1.zPortal.connect(deployAdmin).setDestZnsPortal(hre.ethers.ZeroAddress) + ).to.be.revertedWithCustomError(znsL1.zPortal, ZERO_ADDRESS_ERR); + }); + + it("#setDestZnsPortal() should set the destination portal address", async () => { + await znsL1.zPortal.connect(deployAdmin).setDestZnsPortal(user.address); + + const destPortal = await znsL1.zPortal.destZnsPortal(); + expect(destPortal).to.equal(user.address); + + // set back to L2 portal address + await znsL1.zPortal.connect(deployAdmin).setDestZnsPortal(znsL2.ethPortal.target); + }); + }); + + describe("ZNSEthereumPortal", () => { + it("#initialize() should revert when trying to reinitialize", async () => { + const { + srcZnsPortal, + } = config.crosschain as IZNSZChainCrossConfig; + + await expect( + znsL2.ethPortal.connect(deployAdmin).initialize( + znsL2.accessController.target, + znsL2.zkEvmBridge.target, + srcZnsPortal, + znsL2.registry.target, + znsL2.domainToken.target, + znsL2.rootRegistrar.target, + znsL2.subRegistrar.target, + ) + ).to.be.revertedWithCustomError(znsL2.ethPortal, INITIALIZED_ERR); + }); + + it("#onMessageReceived() should revert when called by non-ZkEvmBridge", async () => { + await expect( + znsL2.ethPortal.connect(deployAdmin).onMessageReceived( + znsL2.zkEvmBridge.target, + 1n, + hre.ethers.ZeroHash, + ) + ).to.be.revertedWithCustomError(znsL2.ethPortal, INVALID_CALLER_ERR); + }); + + it("#onMessageReceived() should revert when `originAddress` is something OTHER than ZChainPortal", async () => { + await expect( + // this will call onMessageReceived(), we have to do it like this to avoid + // reverting on the `InvalidCaller` check + znsL2.zkEvmBridge.claimMessage( + dummySmtProof, + dummySmtProof, + bridgedEventData.globalIndex, + dummySmtProof[0], + dummySmtProof[1], + bridgedEventData.originNetwork, + znsL2.registry.target, + bridgedEventData.destinationNetwork, + bridgedEventData.destinationAddress, + bridgedEventData.amount, + bridgedEventData.metadata, + ) + ).to.be.revertedWithCustomError(znsL2.ethPortal, INVALID_ORIGIN_ERR); + }); + + it("#onMessageReceived() should revert when proof's `domainHash` is incorrect", async () => { + // make wrong metadata + const abiCoder = ethers.AbiCoder.defaultAbiCoder(); + const wrongMetadata = abiCoder.encode( + ["tuple(bytes32,bytes32,string,address,string)"], + [[ + hashDomainLabel("wrong"), // this hashes a different label from the one below + hre.ethers.ZeroHash, + "right", + user.address, + DEFAULT_TOKEN_URI, + ]] + ); + + await expect( + znsL2.zkEvmBridge.claimMessage( + dummySmtProof, + dummySmtProof, + bridgedEventData.globalIndex, + dummySmtProof[0], + dummySmtProof[1], + bridgedEventData.originNetwork, + bridgedEventData.originAddress, + bridgedEventData.destinationNetwork, + bridgedEventData.destinationAddress, + bridgedEventData.amount, + wrongMetadata, + ) + ).to.be.revertedWithCustomError(znsL2.ethPortal, DOMAIN_HASH_NO_MATCH_ERR); + }); + }); + }); }); diff --git a/test/helpers/errors.ts b/test/helpers/errors.ts index cbb42de14..7c1aabc4c 100644 --- a/test/helpers/errors.ts +++ b/test/helpers/errors.ts @@ -44,6 +44,11 @@ export const NO_BENEFICIARY_ERR = "NoBeneficiarySetForParent"; export const NONEXISTENT_TOKEN_ERC_ERR = "ERC721NonexistentToken"; export const INITIALIZED_ERR = "InvalidInitialization"; +// CrossChain +export const INVALID_CALLER_ERR = "InvalidCaller"; +export const INVALID_ORIGIN_ERR = "InvalidOriginAddress"; +export const DOMAIN_HASH_NO_MATCH_ERR = "DomainHashDoesNotMatchBridged"; + // Environment validation export const INVALID_ENV_ERR = "Invalid environment value. Must set env to one of `dev`, `test`, or `prod`"; export const NO_MOCK_PROD_ERR = "Cannot mock MEOW token in production"; From e3f99444dbb4417a6dd0e3f9172b54b7fa45fd31 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 24 Oct 2024 12:40:28 -0700 Subject: [PATCH 073/124] fix tests --- test/L2-BRIDGE-TEST/MultiZNS.test.ts | 61 ++++++++-------------------- test/helpers/errors.ts | 1 + 2 files changed, 17 insertions(+), 45 deletions(-) diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts index 013bf4ce2..8cdd0f76d 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -10,6 +10,7 @@ import { import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { registrationWithSetup } from "../helpers/register-setup"; import { + AC_UNAUTHORIZED_ERR, AccessType, DEFAULT_PRICE_CONFIG, DEFAULT_TOKEN_URI, @@ -22,7 +23,7 @@ import { hashDomainLabel, INITIALIZED_ERR, INVALID_CALLER_ERR, - INVALID_ORIGIN_ERR, + INVALID_ORIGIN_ERR, MESSAGE_FAILED_ERR, NOT_AUTHORIZED_ERR, NOT_OWNER_OF_ERR, PaymentType, @@ -477,60 +478,29 @@ describe.only("MultiZNS", () => { describe("Unit Tests", () => { describe("ZNSZChainPortal", () => { - it.only("#initialize() should revert when trying to reinitialize", async () => { - const { - destNetworkId, - destChainName, - destChainId, - } = config.crosschain as IZNSEthCrossConfig; - - await expect( - znsL1.zPortal.connect(deployAdmin).initialize( - destNetworkId, - destChainName, - destChainId, - await znsL1.zkEvmBridge.getAddress(), - { - accessController: await znsL1.accessController.getAddress(), - registry: await znsL1.registry.getAddress(), - chainResolver: await znsL1.chainResolver.getAddress(), - treasury: await znsL1.treasury.getAddress(), - rootRegistrar: await znsL1.rootRegistrar.getAddress(), - subRegistrar: await znsL1.subRegistrar.getAddress(), - } - ) - ).to.be.revertedWithCustomError(znsL1.zPortal, INITIALIZED_ERR); - }); - - it("#initialize() should revert when passing 0x0 addresses", async () => { - const { - destNetworkId, - destChainName, - destChainId, - } = config.crosschain as IZNSEthCrossConfig; - + it("#initialize() should revert when trying to reinitialize", async () => { await expect( - znsL1.zPortal.connect(deployAdmin).initialize( - destNetworkId, - destChainName, - destChainId, + znsL1.zPortal.initialize( + "1", + "Z", + "1", hre.ethers.ZeroAddress, { accessController: znsL1.accessController.target, registry: znsL1.registry.target, chainResolver: znsL1.chainResolver.target, + treasury: znsL1.treasury.target, rootRegistrar: znsL1.rootRegistrar.target, subRegistrar: znsL1.subRegistrar.target, - treasury: znsL1.treasury.target, - } + }, ) - ).to.be.revertedWithCustomError(znsL1.zPortal, ZERO_ADDRESS_ERR); + ).to.be.revertedWithCustomError(znsL1.zPortal, INITIALIZED_ERR); }); it("#setDestZnsPortal() should revert when called by non-ADMIN", async () => { await expect( znsL1.zPortal.connect(user).setDestZnsPortal(znsL2.ethPortal.target) - ).to.be.revertedWithCustomError(znsL1.zPortal, NOT_AUTHORIZED_ERR); + ).to.be.revertedWithCustomError(znsL1.accessController, AC_UNAUTHORIZED_ERR); }); it("#setDestZnsPortal() should revert when setting 0x0 address", async () => { @@ -580,9 +550,10 @@ describe.only("MultiZNS", () => { }); it("#onMessageReceived() should revert when `originAddress` is something OTHER than ZChainPortal", async () => { + // this will fail with MessageFailed error from the Bridge since it does a `.call()` internally await expect( - // this will call onMessageReceived(), we have to do it like this to avoid - // reverting on the `InvalidCaller` check + // this will call onMessageReceived(), we have to do it like this to avoid + // reverting on the `InvalidCaller` check znsL2.zkEvmBridge.claimMessage( dummySmtProof, dummySmtProof, @@ -596,7 +567,7 @@ describe.only("MultiZNS", () => { bridgedEventData.amount, bridgedEventData.metadata, ) - ).to.be.revertedWithCustomError(znsL2.ethPortal, INVALID_ORIGIN_ERR); + ).to.be.revertedWithCustomError(znsL2.zkEvmBridge, MESSAGE_FAILED_ERR); }); it("#onMessageReceived() should revert when proof's `domainHash` is incorrect", async () => { @@ -627,7 +598,7 @@ describe.only("MultiZNS", () => { bridgedEventData.amount, wrongMetadata, ) - ).to.be.revertedWithCustomError(znsL2.ethPortal, DOMAIN_HASH_NO_MATCH_ERR); + ).to.be.revertedWithCustomError(znsL2.zkEvmBridge, MESSAGE_FAILED_ERR); }); }); }); diff --git a/test/helpers/errors.ts b/test/helpers/errors.ts index 7c1aabc4c..741032aa0 100644 --- a/test/helpers/errors.ts +++ b/test/helpers/errors.ts @@ -48,6 +48,7 @@ export const INITIALIZED_ERR = "InvalidInitialization"; export const INVALID_CALLER_ERR = "InvalidCaller"; export const INVALID_ORIGIN_ERR = "InvalidOriginAddress"; export const DOMAIN_HASH_NO_MATCH_ERR = "DomainHashDoesNotMatchBridged"; +export const MESSAGE_FAILED_ERR = "MessageFailed"; // Environment validation export const INVALID_ENV_ERR = "Invalid environment value. Must set env to one of `dev`, `test`, or `prod`"; From 8ade296be5882e4fd4191a44e35c25dd90d948c5 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 28 Oct 2024 16:16:09 -0700 Subject: [PATCH 074/124] expand env.sample --- .env.sample | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/.env.sample b/.env.sample index 085892c89..6df8d6a09 100644 --- a/.env.sample +++ b/.env.sample @@ -65,10 +65,19 @@ ADMIN_ADDRESSES= MONITOR_CONTRACTS="false" VERIFY_CONTRACTS="false" -DEFENDER_KEY= -DEFENDER_SECRET= -RELAYER_KEY= -RELAYER_SECRET= +# Data for Cross-Chain contract deployment +# Common data for both L1 and L2. Needs to be reset for EVERY deploy to every network !!! +SRC_CHAIN_NAME= # Has to match one of the networks in `SupportedChains` enum in `get-portal-dm.ts` +MOCK_ZKEVM_BRIDGE= # "true" | "false" to make Campaign deploy a Mocked version of the bridge for local testing +ZK_EVM_BRIDGE= # HAS to be provided if MOCK_ZKEVM_BRIDGE is set to "false", this would use actual Bridge from the chain +NETWORK_ID= # (For the Mocked Bridge) Network ID withing Polygon ZkEVM of the current chain we are deploying to +BRIDGE_TOKEN= # (For the Mocked Bridge) Address of the Bridge Token on the current chain we are deploying to +# Data for L1/Ethereum ZNS +DEST_NETWORK_ID= # Network ID withing Polygon ZkEVM of the destination chain (ZChain) where the other ZNS lies +DEST_CHAIN_NAME= # Has to match one of the networks in `SupportedChains` enum in `get-portal-dm.ts` +DEST_CHAIN_ID= # Chain ID of the destination chain (ZChain) where the other ZNS lies +# Data for L2/ZChain ZNS +SRC_ZNS_PORTAL= # Address of the ZNS Portal on the source chain (Ethereum ZNS) # Tenderly # this is your key to access Tenderly Zer0 Org From 55c740465ecca7e4dec3984b9483b6bb1c0d2ff9 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 28 Oct 2024 16:17:29 -0700 Subject: [PATCH 075/124] fix wrong param name in ZkEVMBridgeMock --- contracts/cross-chain/mock/PolygonZkEVMBridgeV2Mock.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/cross-chain/mock/PolygonZkEVMBridgeV2Mock.sol b/contracts/cross-chain/mock/PolygonZkEVMBridgeV2Mock.sol index 8647db007..5eadbcb8d 100644 --- a/contracts/cross-chain/mock/PolygonZkEVMBridgeV2Mock.sol +++ b/contracts/cross-chain/mock/PolygonZkEVMBridgeV2Mock.sol @@ -5,6 +5,7 @@ pragma solidity 0.8.26; import { IBridgeMessageReceiver } from "@zero-tech/zkevm-contracts/contracts/interfaces/IBridgeMessageReceiver.sol"; import { ERC20Mock } from "../../token/mocks/ERC20Mock.sol"; import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; +// import { PolygonZkEVMBridgeV2 } from "@zero-tech/zkevm-contracts/contracts/v2/PolygonZkEVMBridgeV2.sol"; // Note that this does NOT inherit the original Bridge contract! @@ -29,7 +30,7 @@ contract PolygonZkEVMBridgeV2Mock is ReentrancyGuardUpgradeable { address destinationAddress, uint256 amount, bytes metadata, - uint32 globalIndex + uint32 depositCount ); From 4291247d40abf0c8161623de98f11c45017d8fb3 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 29 Oct 2024 14:51:22 -0700 Subject: [PATCH 076/124] split RootRegistrar into multiple contracts and interfaces --- contracts/cross-chain/IZNSEthereumPortal.sol | 6 +- contracts/cross-chain/IZNSZChainPortal.sol | 6 +- contracts/cross-chain/ZNSEthereumPortal.sol | 6 +- contracts/cross-chain/ZNSZChainPortal.sol | 4 +- contracts/registrar/IZNSRootRegistrarBase.sol | 68 ++++++++++++ .../registrar/IZNSRootRegistrarBranch.sol | 12 +++ .../registrar/IZNSRootRegistrarTrunk.sol | 16 +++ ...gistrar.sol => IZNSRootRegistrarTypes.sol} | 100 +++--------------- ...Registrar.sol => ZNSRootRegistrarBase.sol} | 69 ++---------- .../registrar/ZNSRootRegistrarBranch.sol | 68 ++++++++++++ contracts/registrar/ZNSRootRegistrarTrunk.sol | 86 +++++++++++++++ contracts/registrar/ZNSSubRegistrar.sol | 8 +- .../distribution/ZNSRootRegistrarMock.sol | 7 +- .../distribution/ZNSSubRegistrarMock.sol | 6 +- 14 files changed, 295 insertions(+), 167 deletions(-) create mode 100644 contracts/registrar/IZNSRootRegistrarBase.sol create mode 100644 contracts/registrar/IZNSRootRegistrarBranch.sol create mode 100644 contracts/registrar/IZNSRootRegistrarTrunk.sol rename contracts/registrar/{IZNSRootRegistrar.sol => IZNSRootRegistrarTypes.sol} (50%) rename contracts/registrar/{ZNSRootRegistrar.sol => ZNSRootRegistrarBase.sol} (85%) create mode 100644 contracts/registrar/ZNSRootRegistrarBranch.sol create mode 100644 contracts/registrar/ZNSRootRegistrarTrunk.sol diff --git a/contracts/cross-chain/IZNSEthereumPortal.sol b/contracts/cross-chain/IZNSEthereumPortal.sol index 6c0c0a3f4..480e52391 100644 --- a/contracts/cross-chain/IZNSEthereumPortal.sol +++ b/contracts/cross-chain/IZNSEthereumPortal.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.26; import { IDistributionConfig } from "../types/IDistributionConfig.sol"; import { IBridgeMessageReceiver } from "@zero-tech/zkevm-contracts/contracts/interfaces/IBridgeMessageReceiver.sol"; import { IPolygonZkEVMBridgeV2Ext } from "./IPolygonZkEVMBridgeV2Ext.sol"; -import { IZNSRootRegistrar } from "../registrar/IZNSRootRegistrar.sol"; +import { IZNSRootRegistrarBranch } from "../registrar/IZNSRootRegistrarBranch.sol"; import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; @@ -29,7 +29,7 @@ interface IZNSEthereumPortal is IDistributionConfig, IBridgeMessageReceiver { function srcZnsPortal() external view returns (address); - function rootRegistrar() external view returns (IZNSRootRegistrar); + function rootRegistrar() external view returns (IZNSRootRegistrarBranch); function subRegistrar() external view returns (IZNSSubRegistrar); @@ -43,7 +43,7 @@ interface IZNSEthereumPortal is IDistributionConfig, IBridgeMessageReceiver { address srcZnsPortal_, IZNSRegistry registry_, IZNSDomainToken domainToken_, - IZNSRootRegistrar rootRegistrar_, + IZNSRootRegistrarBranch rootRegistrar_, IZNSSubRegistrar subRegistrar_ ) external; diff --git a/contracts/cross-chain/IZNSZChainPortal.sol b/contracts/cross-chain/IZNSZChainPortal.sol index 4323758dd..a27e40b04 100644 --- a/contracts/cross-chain/IZNSZChainPortal.sol +++ b/contracts/cross-chain/IZNSZChainPortal.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.26; import { IPolygonZkEVMBridgeV2 } from "@zero-tech/zkevm-contracts/contracts/v2/interfaces/IPolygonZkEVMBridgeV2.sol"; import { IDistributionConfig } from "../types/IDistributionConfig.sol"; -import { IZNSRootRegistrar } from "../registrar/IZNSRootRegistrar.sol"; +import { IZNSRootRegistrarTrunk } from "../registrar/IZNSRootRegistrarTrunk.sol"; import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; import { IZNSTreasury } from "../treasury/IZNSTreasury.sol"; @@ -18,7 +18,7 @@ interface IZNSZChainPortal is IDistributionConfig { IZNSRegistry registry; IZNSChainResolver chainResolver; IZNSTreasury treasury; - IZNSRootRegistrar rootRegistrar; + IZNSRootRegistrarTrunk rootRegistrar; IZNSSubRegistrar subRegistrar; } @@ -40,7 +40,7 @@ interface IZNSZChainPortal is IDistributionConfig { function destZnsPortal() external view returns (address); - function rootRegistrar() external view returns (IZNSRootRegistrar); + function rootRegistrar() external view returns (IZNSRootRegistrarTrunk); function subRegistrar() external view returns (IZNSSubRegistrar); diff --git a/contracts/cross-chain/ZNSEthereumPortal.sol b/contracts/cross-chain/ZNSEthereumPortal.sol index 3e9a49026..b3b268ab5 100644 --- a/contracts/cross-chain/ZNSEthereumPortal.sol +++ b/contracts/cross-chain/ZNSEthereumPortal.sol @@ -8,7 +8,7 @@ import { IZNSEthereumPortal } from "./IZNSEthereumPortal.sol"; import { IPolygonZkEVMBridgeV2Ext } from "./IPolygonZkEVMBridgeV2Ext.sol"; import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; import { BridgedDomain } from "../types/CrossChainTypes.sol"; -import { IZNSRootRegistrar } from "../registrar/IZNSRootRegistrar.sol"; +import { IZNSRootRegistrarBranch } from "../registrar/IZNSRootRegistrarBranch.sol"; import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; @@ -27,7 +27,7 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPo address public srcZnsPortal; // *--| ZNS Data for THIS chain |--* - IZNSRootRegistrar public rootRegistrar; + IZNSRootRegistrarBranch public rootRegistrar; IZNSSubRegistrar public subRegistrar; IZNSDomainToken public domainToken; IZNSRegistry public registry; @@ -43,7 +43,7 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPo address srcZnsPortal_, IZNSRegistry registry_, IZNSDomainToken domainToken_, - IZNSRootRegistrar rootRegistrar_, + IZNSRootRegistrarBranch rootRegistrar_, IZNSSubRegistrar subRegistrar_ ) external override initializer { _setAccessController(accessController_); diff --git a/contracts/cross-chain/ZNSZChainPortal.sol b/contracts/cross-chain/ZNSZChainPortal.sol index 3f958a35c..598c4ae30 100644 --- a/contracts/cross-chain/ZNSZChainPortal.sol +++ b/contracts/cross-chain/ZNSZChainPortal.sol @@ -9,7 +9,7 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { IZNSChainResolver } from "../resolver/IZNSChainResolver.sol"; import { IZNSPricer } from "../types/IZNSPricer.sol"; import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; -import { IZNSRootRegistrar } from "../registrar/IZNSRootRegistrar.sol"; +import { IZNSRootRegistrarTrunk } from "../registrar/IZNSRootRegistrarTrunk.sol"; import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; import { IZNSTreasury } from "../treasury/IZNSTreasury.sol"; import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; @@ -28,7 +28,7 @@ contract ZNSZChainPortal is UUPSUpgradeable, AAccessControlled, IZNSZChainPortal address public destZnsPortal; // *--| ZNS Data for THIS chain |--* - IZNSRootRegistrar public rootRegistrar; + IZNSRootRegistrarTrunk public rootRegistrar; IZNSSubRegistrar public subRegistrar; IZNSTreasury public treasury; IZNSChainResolver public chainResolver; diff --git a/contracts/registrar/IZNSRootRegistrarBase.sol b/contracts/registrar/IZNSRootRegistrarBase.sol new file mode 100644 index 000000000..6b1c83e65 --- /dev/null +++ b/contracts/registrar/IZNSRootRegistrarBase.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; +import { IZNSSubRegistrar } from "./IZNSSubRegistrar.sol"; +import { IZNSPricer } from "../types/IZNSPricer.sol"; +import { IZNSTreasury } from "../treasury/IZNSTreasury.sol"; +import { IZNSRootRegistrarTypes } from "./IZNSRootRegistrarTypes.sol"; +import { CoreRegisterArgs } from "./IZNSRootRegistrarTypes.sol"; + + +// TODO multi: fix NatSpec here!!! +/** + * @title IZNSRootRegistrar.sol - Interface for the ZNSRootRegistrar contract resposible for registering root domains. + * @notice Below are docs for the types in this file: + * - `OwnerOf`: Enum signifying ownership of ZNS entities + * + NAME: The owner of the Name only + * + TOKEN: The owner of the Token only + * + BOTH: The owner of both the Name and the Token + * - `CoreRegisterArgs`: Struct containing all the arguments required to register a domain + * with ZNSRootRegistrar.coreRegister(): + * + `parentHash`: The hash of the parent domain (0x0 for root domains) + * + `domainHash`: The hash of the domain to be registered + * + `label`: The label of the domain to be registered + * + `registrant`: The address of the user who is registering the domain + * + `price`: The determined price for the domain to be registered based on parent rules + * + `stakeFee`: The determined stake fee for the domain to be registered (only for PaymentType.STAKE!) + * + `domainAddress`: The address to which the domain will be resolved to + * + `tokenURI`: The tokenURI for the domain to be registered + * + `isStakePayment`: A flag for whether the payment is a stake payment or not + */ +interface IZNSRootRegistrarBase is IZNSRootRegistrarTypes { + function initialize( + address accessController_, + address registry_, + address rootPricer_, + address treasury_, + address domainToken_ + ) external; + + function coreRegister( + CoreRegisterArgs memory args + ) external; + + function revokeDomain(bytes32 domainHash) external; + + function reclaimDomain(bytes32 domainHash) external; + + function isOwnerOf(bytes32 domainHash, address candidate, OwnerOf ownerOf) external view returns (bool); + + function setRegistry(address registry_) external; + + function setRootPricer(address rootPricer_) external; + + function setTreasury(address treasury_) external; + + function setDomainToken(address domainToken_) external; + + function setSubRegistrar(address subRegistrar_) external; + + function rootPricer() external view returns (IZNSPricer); + + function treasury() external view returns (IZNSTreasury); + + function domainToken() external view returns (IZNSDomainToken); + + function subRegistrar() external view returns (IZNSSubRegistrar); +} diff --git a/contracts/registrar/IZNSRootRegistrarBranch.sol b/contracts/registrar/IZNSRootRegistrarBranch.sol new file mode 100644 index 000000000..a68e51c06 --- /dev/null +++ b/contracts/registrar/IZNSRootRegistrarBranch.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { IZNSRootRegistrarBase } from "./IZNSRootRegistrarBase.sol"; + + +interface IZNSRootRegistrarBranch is IZNSRootRegistrarBase { + function registerBridgedRootDomain( + string calldata label, + string calldata tokenURI + ) external returns (bytes32); +} diff --git a/contracts/registrar/IZNSRootRegistrarTrunk.sol b/contracts/registrar/IZNSRootRegistrarTrunk.sol new file mode 100644 index 000000000..c0e08536c --- /dev/null +++ b/contracts/registrar/IZNSRootRegistrarTrunk.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { IZNSRootRegistrarBase } from "./IZNSRootRegistrarBase.sol"; +import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; + + +interface IZNSRootRegistrarTrunk is IZNSRootRegistrarBase { + function registerRootDomain( + string calldata name, + address domainAddress, + string calldata tokenURI, + DistributionConfig calldata distributionConfig, + PaymentConfig calldata paymentConfig + ) external returns (bytes32); +} diff --git a/contracts/registrar/IZNSRootRegistrar.sol b/contracts/registrar/IZNSRootRegistrarTypes.sol similarity index 50% rename from contracts/registrar/IZNSRootRegistrar.sol rename to contracts/registrar/IZNSRootRegistrarTypes.sol index a71ae5991..45f8f55a4 100644 --- a/contracts/registrar/IZNSRootRegistrar.sol +++ b/contracts/registrar/IZNSRootRegistrarTypes.sol @@ -3,49 +3,27 @@ pragma solidity 0.8.26; import { IDistributionConfig } from "../types/IDistributionConfig.sol"; import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; -import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; -import { IZNSSubRegistrar } from "./IZNSSubRegistrar.sol"; -import { IZNSPricer } from "../types/IZNSPricer.sol"; -import { IZNSTreasury } from "../treasury/IZNSTreasury.sol"; /** * @notice Stake fee is 0x0 for anything other than subdomain under a parent with Stake Payment * parent hash will be 0x0 for root domain */ -struct CoreRegisterArgs { - bytes32 parentHash; - bytes32 domainHash; - address registrant; - address domainAddress; - uint256 price; - uint256 stakeFee; - string label; - string tokenURI; - bool isStakePayment; - PaymentConfig paymentConfig; -} + struct CoreRegisterArgs { + bytes32 parentHash; + bytes32 domainHash; + address registrant; + address domainAddress; + uint256 price; + uint256 stakeFee; + string label; + string tokenURI; + bool isStakePayment; + PaymentConfig paymentConfig; + } -/** - * @title IZNSRootRegistrar.sol - Interface for the ZNSRootRegistrar contract resposible for registering root domains. - * @notice Below are docs for the types in this file: - * - `OwnerOf`: Enum signifying ownership of ZNS entities - * + NAME: The owner of the Name only - * + TOKEN: The owner of the Token only - * + BOTH: The owner of both the Name and the Token - * - `CoreRegisterArgs`: Struct containing all the arguments required to register a domain - * with ZNSRootRegistrar.coreRegister(): - * + `parentHash`: The hash of the parent domain (0x0 for root domains) - * + `domainHash`: The hash of the domain to be registered - * + `label`: The label of the domain to be registered - * + `registrant`: The address of the user who is registering the domain - * + `price`: The determined price for the domain to be registered based on parent rules - * + `stakeFee`: The determined stake fee for the domain to be registered (only for PaymentType.STAKE!) - * + `domainAddress`: The address to which the domain will be resolved to - * + `tokenURI`: The tokenURI for the domain to be registered - * + `isStakePayment`: A flag for whether the payment is a stake payment or not - */ -interface IZNSRootRegistrar is IDistributionConfig { + +interface IZNSRootRegistrarTypes is IDistributionConfig { error NotTheOwnerOf( OwnerOf ownerOf, address candidate, @@ -59,6 +37,7 @@ interface IZNSRootRegistrar is IDistributionConfig { TOKEN, BOTH } + /** * @notice Emitted when a NEW domain is registered. * @dev `domainAddress` parameter is the address to which a domain name will relate to in ZNS. @@ -128,53 +107,4 @@ interface IZNSRootRegistrar is IDistributionConfig { * @param subRegistrar The new address of the SubRegistrar contract */ event SubRegistrarSet(address subRegistrar); - - function initialize( - address accessController_, - address registry_, - address rootPricer_, - address treasury_, - address domainToken_ - ) external; - - function registerRootDomain( - string calldata name, - address domainAddress, - string calldata tokenURI, - DistributionConfig calldata distributionConfig, - PaymentConfig calldata paymentConfig - ) external returns (bytes32); - - function registerBridgedRootDomain( - string calldata label, - string calldata tokenURI - ) external returns (bytes32); - - function coreRegister( - CoreRegisterArgs memory args - ) external; - - function revokeDomain(bytes32 domainHash) external; - - function reclaimDomain(bytes32 domainHash) external; - - function isOwnerOf(bytes32 domainHash, address candidate, OwnerOf ownerOf) external view returns (bool); - - function setRegistry(address registry_) external; - - function setRootPricer(address rootPricer_) external; - - function setTreasury(address treasury_) external; - - function setDomainToken(address domainToken_) external; - - function setSubRegistrar(address subRegistrar_) external; - - function rootPricer() external view returns (IZNSPricer); - - function treasury() external view returns (IZNSTreasury); - - function domainToken() external view returns (IZNSDomainToken); - - function subRegistrar() external view returns (IZNSSubRegistrar); } diff --git a/contracts/registrar/ZNSRootRegistrar.sol b/contracts/registrar/ZNSRootRegistrarBase.sol similarity index 85% rename from contracts/registrar/ZNSRootRegistrar.sol rename to contracts/registrar/ZNSRootRegistrarBase.sol index b68ae1ae6..a1a358c2c 100644 --- a/contracts/registrar/ZNSRootRegistrar.sol +++ b/contracts/registrar/ZNSRootRegistrarBase.sol @@ -3,7 +3,8 @@ pragma solidity 0.8.26; import { AAccessControlled } from "../access/AAccessControlled.sol"; import { ARegistryWired } from "../registry/ARegistryWired.sol"; -import { IZNSRootRegistrar, CoreRegisterArgs } from "./IZNSRootRegistrar.sol"; +import { IZNSRootRegistrarBase } from "./IZNSRootRegistrarBase.sol"; +import { IZNSRootRegistrarTypes, CoreRegisterArgs } from "./IZNSRootRegistrarTypes.sol"; import { IZNSTreasury, PaymentConfig } from "../treasury/IZNSTreasury.sol"; import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; import { IZNSAddressResolver } from "../resolver/IZNSAddressResolver.sol"; @@ -14,6 +15,7 @@ import { StringUtils } from "../utils/StringUtils.sol"; import { ZeroAddressPassed, DomainAlreadyExists } from "../utils/CommonErrors.sol"; +// TODO multi: fix NatSpec here to the Base contract /** * @title Main entry point for the three main flows of ZNS - Register Root Domain, Reclaim and Revoke any domain. * @notice This contract serves as the "umbrella" for many ZNS operations, it is given REGISTRAR_ROLE @@ -27,11 +29,11 @@ import { ZeroAddressPassed, DomainAlreadyExists } from "../utils/CommonErrors.so * @dev This contract is also called at the last stage of registering subdomains, since it has the common * logic required to be performed for any level domains. */ -contract ZNSRootRegistrar is +contract ZNSRootRegistrarBase is UUPSUpgradeable, AAccessControlled, ARegistryWired, - IZNSRootRegistrar { + IZNSRootRegistrarBase { using StringUtils for string; IZNSPricer public rootPricer; @@ -69,63 +71,6 @@ contract ZNSRootRegistrar is setDomainToken(domainToken_); } - /** - * @notice This function is the main entry point for the Register Root Domain flow. - * Registers a new root domain such as `0://wilder`. - * Gets domain hash as a keccak256 hash of the domain label string casted to bytes32, - * checks existence of the domain in the registry and reverts if it exists. - * Calls `ZNSTreasury` to do the staking part, gets `tokenId` for the new token to be minted - * as domain hash casted to uint256, mints the token and sets the domain data in the `ZNSRegistry` - * and, possibly, `ZNSAddressResolver`. Emits a `DomainRegistered` event. - * @param label Name (label) of the domain to register - * @param domainAddress (optional) Address for the `ZNSAddressResolver` to return when requested - * @param tokenURI URI to assign to the Domain Token issued for the domain - * @param distributionConfig (optional) Distribution config for the domain to set in the same tx - * > Please note that passing distribution config will add more gas to the tx and most importantly - - * - the distributionConfig HAS to be passed FULLY filled or all zeros. It is optional as a whole, - * but all the parameters inside are required. - * @param paymentConfig (optional) Payment config for the domain to set on ZNSTreasury in the same tx - * > `paymentConfig` has to be fully filled or all zeros. It is optional as a whole, - * but all the parameters inside are required. - */ - function registerRootDomain( - string calldata label, - address domainAddress, - string calldata tokenURI, - DistributionConfig calldata distributionConfig, - PaymentConfig calldata paymentConfig - ) external override returns (bytes32) { - return _coreRootRegister( - label, - domainAddress, - tokenURI, - distributionConfig, - paymentConfig, - false - ); - } - - // TODO multi: should this function ONLY be on the L2 contract ??? - function registerBridgedRootDomain( - string calldata label, - string calldata tokenURI - // TODO multi: should we add specific role for the Portal ??? - ) external override returns (bytes32) { - accessController.checkPortal(msg.sender); - - DistributionConfig memory emptyDistrConfig; - PaymentConfig memory emptyPaymentConfig; - - return _coreRootRegister( - label, - address(0), - tokenURI, - emptyDistrConfig, - emptyPaymentConfig, - true - ); - } - /** * @notice External function used by `ZNSSubRegistrar` for the final stage of registering subdomains. * @param args `CoreRegisterArgs`: Struct containing all the arguments required to register a domain @@ -221,7 +166,7 @@ contract ZNSRootRegistrar is registry.createDomainRecord(args.domainHash, args.registrant, "address"); IZNSAddressResolver(registry.getDomainResolver(args.domainHash)) - .setAddress(args.domainHash, args.domainAddress); + .setAddress(args.domainHash, args.domainAddress); } else { // By passing an empty string we tell the registry to not add a resolver registry.createDomainRecord(args.domainHash, args.registrant, ""); @@ -373,7 +318,7 @@ contract ZNSRootRegistrar is * Only ADMIN in `ZNSAccessController` can call this function. * @param registry_ Address of the `ZNSRegistry` contract */ - function setRegistry(address registry_) public override(ARegistryWired, IZNSRootRegistrar) onlyAdmin { + function setRegistry(address registry_) public virtual override(ARegistryWired, IZNSRootRegistrarBase) onlyAdmin { _setRegistry(registry_); } diff --git a/contracts/registrar/ZNSRootRegistrarBranch.sol b/contracts/registrar/ZNSRootRegistrarBranch.sol new file mode 100644 index 000000000..a6f45e317 --- /dev/null +++ b/contracts/registrar/ZNSRootRegistrarBranch.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { AAccessControlled } from "../access/AAccessControlled.sol"; +import { ARegistryWired } from "../registry/ARegistryWired.sol"; +import { ZNSRootRegistrarBase } from "./ZNSRootRegistrarBase.sol"; +import { IZNSRootRegistrarBranch } from "./IZNSRootRegistrarBranch.sol"; +import { IZNSRootRegistrarBase } from "./IZNSRootRegistrarBase.sol"; +import { CoreRegisterArgs } from "./IZNSRootRegistrarTypes.sol"; +import { IZNSTreasury, PaymentConfig } from "../treasury/IZNSTreasury.sol"; +import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; +import { IZNSAddressResolver } from "../resolver/IZNSAddressResolver.sol"; +import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; +import { IZNSPricer } from "../types/IZNSPricer.sol"; +import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import { StringUtils } from "../utils/StringUtils.sol"; +import { ZeroAddressPassed, DomainAlreadyExists } from "../utils/CommonErrors.sol"; + + +// TODO multi: fix NatSpec here ! +/** + * @title Main entry point for the three main flows of ZNS - Register Root Domain, Reclaim and Revoke any domain. + * @notice This contract serves as the "umbrella" for many ZNS operations, it is given REGISTRAR_ROLE + * to combine multiple calls/operations between different modules to achieve atomic state changes + * and proper logic for the ZNS flows. You can see functions in other modules that are only allowed + * to be called by this contract to ensure proper management of ZNS data in multiple places. + * RRR - Register, Reclaim, Revoke start here and then call other modules to complete the flow. + * ZNSRootRegistrar.sol stores most of the other contract addresses and can communicate with other modules, + * but the relationship is one-sided, where other modules do not need to know about the ZNSRootRegistrar.sol, + * they only check REGISTRAR_ROLE that can, in theory, be assigned to any other address. + * @dev This contract is also called at the last stage of registering subdomains, since it has the common + * logic required to be performed for any level domains. + */ +contract ZNSRootRegistrarBranch is + UUPSUpgradeable, + AAccessControlled, + ARegistryWired, + ZNSRootRegistrarBase, + IZNSRootRegistrarBranch { + + // TODO multi: add NatSpec here !!! + function registerBridgedRootDomain( + string calldata label, + string calldata tokenURI + ) external returns (bytes32) { + accessController.checkPortal(msg.sender); + + DistributionConfig memory emptyDistrConfig; + PaymentConfig memory emptyPaymentConfig; + + return _coreRootRegister( + label, + address(0), + tokenURI, + emptyDistrConfig, + emptyPaymentConfig, + true + ); + } + + function setRegistry(address registry) public override( + ARegistryWired, + ZNSRootRegistrarBase, + IZNSRootRegistrarBase + ) onlyAdmin { + super.setRegistry(registry); + } +} diff --git a/contracts/registrar/ZNSRootRegistrarTrunk.sol b/contracts/registrar/ZNSRootRegistrarTrunk.sol new file mode 100644 index 000000000..81a9cf877 --- /dev/null +++ b/contracts/registrar/ZNSRootRegistrarTrunk.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { AAccessControlled } from "../access/AAccessControlled.sol"; +import { ARegistryWired } from "../registry/ARegistryWired.sol"; +import { ZNSRootRegistrarBase } from "./ZNSRootRegistrarBase.sol"; +import { IZNSRootRegistrarTrunk } from "./IZNSRootRegistrarTrunk.sol"; +import { IZNSRootRegistrarBase } from "./IZNSRootRegistrarBase.sol"; +import { CoreRegisterArgs } from "./IZNSRootRegistrarTypes.sol"; +import { IZNSTreasury, PaymentConfig } from "../treasury/IZNSTreasury.sol"; +import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; +import { IZNSAddressResolver } from "../resolver/IZNSAddressResolver.sol"; +import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; +import { IZNSPricer } from "../types/IZNSPricer.sol"; +import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import { StringUtils } from "../utils/StringUtils.sol"; +import { ZeroAddressPassed, DomainAlreadyExists } from "../utils/CommonErrors.sol"; + + +// TODO multi: MAKE SURE IT IS NOT POSSIBLE TO REGISTER ROOT DOMAIN ON ZCHAIN!!!! +// NEW LOGIC NEEDS TO BE ADDED FOR THAT !!! +// TEST THIS !!!!! +/** + * @title Main entry point for the three main flows of ZNS - Register Root Domain, Reclaim and Revoke any domain. + * @notice This contract serves as the "umbrella" for many ZNS operations, it is given REGISTRAR_ROLE + * to combine multiple calls/operations between different modules to achieve atomic state changes + * and proper logic for the ZNS flows. You can see functions in other modules that are only allowed + * to be called by this contract to ensure proper management of ZNS data in multiple places. + * RRR - Register, Reclaim, Revoke start here and then call other modules to complete the flow. + * ZNSRootRegistrar.sol stores most of the other contract addresses and can communicate with other modules, + * but the relationship is one-sided, where other modules do not need to know about the ZNSRootRegistrar.sol, + * they only check REGISTRAR_ROLE that can, in theory, be assigned to any other address. + * @dev This contract is also called at the last stage of registering subdomains, since it has the common + * logic required to be performed for any level domains. + */ +contract ZNSRootRegistrarTrunk is + UUPSUpgradeable, + AAccessControlled, + ARegistryWired, + ZNSRootRegistrarBase, + IZNSRootRegistrarTrunk { + + /** + * @notice This function is the main entry point for the Register Root Domain flow. + * Registers a new root domain such as `0://wilder`. + * Gets domain hash as a keccak256 hash of the domain label string casted to bytes32, + * checks existence of the domain in the registry and reverts if it exists. + * Calls `ZNSTreasury` to do the staking part, gets `tokenId` for the new token to be minted + * as domain hash casted to uint256, mints the token and sets the domain data in the `ZNSRegistry` + * and, possibly, `ZNSAddressResolver`. Emits a `DomainRegistered` event. + * @param label Name (label) of the domain to register + * @param domainAddress (optional) Address for the `ZNSAddressResolver` to return when requested + * @param tokenURI URI to assign to the Domain Token issued for the domain + * @param distributionConfig (optional) Distribution config for the domain to set in the same tx + * > Please note that passing distribution config will add more gas to the tx and most importantly - + * - the distributionConfig HAS to be passed FULLY filled or all zeros. It is optional as a whole, + * but all the parameters inside are required. + * @param paymentConfig (optional) Payment config for the domain to set on ZNSTreasury in the same tx + * > `paymentConfig` has to be fully filled or all zeros. It is optional as a whole, + * but all the parameters inside are required. + */ + function registerRootDomain( + string calldata label, + address domainAddress, + string calldata tokenURI, + DistributionConfig calldata distributionConfig, + PaymentConfig calldata paymentConfig + ) external returns (bytes32) { + return _coreRootRegister( + label, + domainAddress, + tokenURI, + distributionConfig, + paymentConfig, + false + ); + } + + function setRegistry(address registry) public override( + ARegistryWired, + ZNSRootRegistrarBase, + IZNSRootRegistrarBase + ) onlyAdmin { + super.setRegistry(registry); + } +} diff --git a/contracts/registrar/ZNSSubRegistrar.sol b/contracts/registrar/ZNSSubRegistrar.sol index 836bdd342..e2fbf7e77 100644 --- a/contracts/registrar/ZNSSubRegistrar.sol +++ b/contracts/registrar/ZNSSubRegistrar.sol @@ -2,7 +2,8 @@ pragma solidity 0.8.26; import { IZNSPricer } from "../types/IZNSPricer.sol"; -import { IZNSRootRegistrar, CoreRegisterArgs } from "./IZNSRootRegistrar.sol"; +import { IZNSRootRegistrarBase } from "./IZNSRootRegistrarBase.sol"; +import { CoreRegisterArgs } from "./IZNSRootRegistrarTypes.sol"; import { IZNSSubRegistrar } from "./IZNSSubRegistrar.sol"; import { AAccessControlled } from "../access/AAccessControlled.sol"; import { ARegistryWired } from "../registry/ARegistryWired.sol"; @@ -12,6 +13,7 @@ import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils import { DomainAlreadyExists, ZeroAddressPassed, NotAuthorizedForDomain } from "../utils/CommonErrors.sol"; +// TODO multi: should we split this for Trunk and Branch as well ??? /** * @title ZNSSubRegistrar.sol - The contract for registering and revoking subdomains of zNS. * @dev This contract has the entry point for registering subdomains, but calls @@ -24,7 +26,7 @@ contract ZNSSubRegistrar is AAccessControlled, ARegistryWired, UUPSUpgradeable, /** * @notice State var for the ZNSRootRegistrar contract that finalizes registration of subdomains. */ - IZNSRootRegistrar public rootRegistrar; + IZNSRootRegistrarBase public rootRegistrar; /** * @notice Mapping of domainHash to distribution config set by the domain owner/operator. @@ -383,7 +385,7 @@ contract ZNSSubRegistrar is AAccessControlled, ARegistryWired, UUPSUpgradeable, */ function setRootRegistrar(address registrar_) public override onlyAdmin { if (registrar_ == address(0)) revert ZeroAddressPassed(); - rootRegistrar = IZNSRootRegistrar(registrar_); + rootRegistrar = IZNSRootRegistrarBase(registrar_); emit RootRegistrarSet(registrar_); } diff --git a/contracts/upgrade-test-mocks/distribution/ZNSRootRegistrarMock.sol b/contracts/upgrade-test-mocks/distribution/ZNSRootRegistrarMock.sol index 76fd2d202..b4952b8ec 100644 --- a/contracts/upgrade-test-mocks/distribution/ZNSRootRegistrarMock.sol +++ b/contracts/upgrade-test-mocks/distribution/ZNSRootRegistrarMock.sol @@ -1,8 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.26; -import { ZNSRootRegistrar } from "../../registrar/ZNSRootRegistrar.sol"; +import { ZNSRootRegistrarTrunk } from "../../registrar/ZNSRootRegistrarTrunk.sol"; import { UpgradeMock } from "../UpgradeMock.sol"; - /* solhint-disable */ -contract ZNSRootRegistrarUpgradeMock is ZNSRootRegistrar, UpgradeMock {} + +contract ZNSRootRegistrarUpgradeMock is ZNSRootRegistrarTrunk, UpgradeMock { +} diff --git a/contracts/upgrade-test-mocks/distribution/ZNSSubRegistrarMock.sol b/contracts/upgrade-test-mocks/distribution/ZNSSubRegistrarMock.sol index eaf21610c..cdf7e50d2 100644 --- a/contracts/upgrade-test-mocks/distribution/ZNSSubRegistrarMock.sol +++ b/contracts/upgrade-test-mocks/distribution/ZNSSubRegistrarMock.sol @@ -7,7 +7,7 @@ import { ZNSSubRegistrar } from "../../registrar/ZNSSubRegistrar.sol"; import { IZNSSubRegistrar } from "../../registrar/IZNSSubRegistrar.sol"; import { UpgradeMock } from "../UpgradeMock.sol"; import { IZNSPricer } from "../../types/IZNSPricer.sol"; -import { IZNSRootRegistrar, CoreRegisterArgs } from "../../registrar/IZNSRootRegistrar.sol"; +import { IZNSRootRegistrarBase, CoreRegisterArgs } from "../../registrar/IZNSRootRegistrarBase.sol"; import { AAccessControlled } from "../../access/AAccessControlled.sol"; import { ARegistryWired } from "../../registry/ARegistryWired.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; @@ -37,7 +37,7 @@ struct DistributionConfig { contract ZNSSubRegistrarMainState { - IZNSRootRegistrar public rootRegistrar; + IZNSRootRegistrarBase public rootRegistrar; mapping(bytes32 domainHash => DistributionConfig config) public distrConfigs; @@ -250,7 +250,7 @@ contract ZNSSubRegistrarUpgradeMock is function setRootRegistrar(address registrar_) public onlyAdmin { if (registrar_ == address(0)) revert ZeroAddressPassed(); - rootRegistrar = IZNSRootRegistrar(registrar_); + rootRegistrar = IZNSRootRegistrarBase(registrar_); } // solhint-disable-next-line From b58fea8e016e0243275e8efe5c8f3c6716ccbe17 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 29 Oct 2024 15:02:49 -0700 Subject: [PATCH 077/124] add logic to RootRegistrarDM to determine which contract to deploy based on the chain name --- src/deploy/missions/contracts/names.ts | 4 +++- .../contracts/zns-base/root-registrar.ts | 22 +++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/deploy/missions/contracts/names.ts b/src/deploy/missions/contracts/names.ts index c96c15f51..967837dd0 100644 --- a/src/deploy/missions/contracts/names.ts +++ b/src/deploy/missions/contracts/names.ts @@ -44,7 +44,9 @@ export const znsNames = { instance: "treasury", }, rootRegistrar: { - contract: "ZNSRootRegistrar", + contractBase: "ZNSRootRegistrarBase", + contractTrunk: "ZNSRootRegistrarTrunk", + contractBranch: "ZNSRootRegistrarBranch", instance: "rootRegistrar", }, subRegistrar: { diff --git a/src/deploy/missions/contracts/zns-base/root-registrar.ts b/src/deploy/missions/contracts/zns-base/root-registrar.ts index b9827cbdb..7f7f9c768 100644 --- a/src/deploy/missions/contracts/zns-base/root-registrar.ts +++ b/src/deploy/missions/contracts/zns-base/root-registrar.ts @@ -1,5 +1,5 @@ import { - BaseDeployMission, + BaseDeployMission, IDeployMissionArgs, TDeployArgs, } from "@zero-tech/zdc"; import { ProxyKinds, REGISTRAR_ROLE } from "../../../constants"; @@ -7,6 +7,7 @@ import { znsNames } from "../names"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; +import { SupportedChains } from "../cross-chain/portals/get-portal-dm"; export class ZNSRootRegistrarDM extends BaseDeployMission< @@ -20,9 +21,26 @@ IZNSContracts kind: ProxyKinds.uups, }; - contractName = znsNames.rootRegistrar.contract; + contractName = znsNames.rootRegistrar.contractBase; instanceName = znsNames.rootRegistrar.instance; + constructor (args : IDeployMissionArgs< + HardhatRuntimeEnvironment, + SignerWithAddress, + IZNSCampaignConfig, + IZNSContracts + >) { + super(args); + + if (this.config.crosschain.srcChainName === SupportedChains.eth) { + this.contractName = znsNames.rootRegistrar.contractTrunk; + } else if (this.config.crosschain.srcChainName === SupportedChains.z) { + this.contractName = znsNames.rootRegistrar.contractBranch; + } else { + throw new Error("Unsupported chain for Root Registrar deployment"); + } + } + async deployArgs () : Promise { const { accessController, From 408b990e59698ce522d231e7e6a141f5eb216051 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 29 Oct 2024 15:59:59 -0700 Subject: [PATCH 078/124] split ZNSSubRegistrar into 2 contracts with separate interfaces --- contracts/cross-chain/IZNSEthereumPortal.sol | 6 +- contracts/cross-chain/IZNSZChainPortal.sol | 6 +- contracts/cross-chain/ZNSEthereumPortal.sol | 7 +- contracts/cross-chain/ZNSZChainPortal.sol | 5 +- contracts/registrar/IZNSRootRegistrarBase.sol | 4 +- .../registrar/IZNSSubRegistrarBranch.sol | 13 + ...egistrar.sol => IZNSSubRegistrarTrunk.sol} | 286 +++++++++--------- contracts/registrar/ZNSRootRegistrarBase.sol | 6 +- .../registrar/ZNSRootRegistrarBranch.sol | 7 +- contracts/registrar/ZNSRootRegistrarTrunk.sol | 4 - contracts/registrar/ZNSSubRegistrarBranch.sol | 39 +++ ...Registrar.sol => ZNSSubRegistrarTrunk.sol} | 27 +- .../distribution/ZNSSubRegistrarMock.sol | 5 +- 13 files changed, 216 insertions(+), 199 deletions(-) create mode 100644 contracts/registrar/IZNSSubRegistrarBranch.sol rename contracts/registrar/{IZNSSubRegistrar.sol => IZNSSubRegistrarTrunk.sol} (91%) create mode 100644 contracts/registrar/ZNSSubRegistrarBranch.sol rename contracts/registrar/{ZNSSubRegistrar.sol => ZNSSubRegistrarTrunk.sol} (94%) diff --git a/contracts/cross-chain/IZNSEthereumPortal.sol b/contracts/cross-chain/IZNSEthereumPortal.sol index 480e52391..bdcd8924e 100644 --- a/contracts/cross-chain/IZNSEthereumPortal.sol +++ b/contracts/cross-chain/IZNSEthereumPortal.sol @@ -5,7 +5,7 @@ import { IDistributionConfig } from "../types/IDistributionConfig.sol"; import { IBridgeMessageReceiver } from "@zero-tech/zkevm-contracts/contracts/interfaces/IBridgeMessageReceiver.sol"; import { IPolygonZkEVMBridgeV2Ext } from "./IPolygonZkEVMBridgeV2Ext.sol"; import { IZNSRootRegistrarBranch } from "../registrar/IZNSRootRegistrarBranch.sol"; -import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; +import { IZNSSubRegistrarBranch } from "../registrar/IZNSSubRegistrarBranch.sol"; import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; @@ -31,7 +31,7 @@ interface IZNSEthereumPortal is IDistributionConfig, IBridgeMessageReceiver { function rootRegistrar() external view returns (IZNSRootRegistrarBranch); - function subRegistrar() external view returns (IZNSSubRegistrar); + function subRegistrar() external view returns (IZNSSubRegistrarBranch); function domainToken() external view returns (IZNSDomainToken); @@ -44,7 +44,7 @@ interface IZNSEthereumPortal is IDistributionConfig, IBridgeMessageReceiver { IZNSRegistry registry_, IZNSDomainToken domainToken_, IZNSRootRegistrarBranch rootRegistrar_, - IZNSSubRegistrar subRegistrar_ + IZNSSubRegistrarBranch subRegistrar_ ) external; function setSrcZnsPortal(address newAddress) external; diff --git a/contracts/cross-chain/IZNSZChainPortal.sol b/contracts/cross-chain/IZNSZChainPortal.sol index a27e40b04..c5a35ccee 100644 --- a/contracts/cross-chain/IZNSZChainPortal.sol +++ b/contracts/cross-chain/IZNSZChainPortal.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.26; import { IPolygonZkEVMBridgeV2 } from "@zero-tech/zkevm-contracts/contracts/v2/interfaces/IPolygonZkEVMBridgeV2.sol"; import { IDistributionConfig } from "../types/IDistributionConfig.sol"; import { IZNSRootRegistrarTrunk } from "../registrar/IZNSRootRegistrarTrunk.sol"; -import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; +import { IZNSSubRegistrarTrunk } from "../registrar/IZNSSubRegistrarTrunk.sol"; import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; import { IZNSTreasury } from "../treasury/IZNSTreasury.sol"; import { IZNSChainResolver } from "../resolver/IZNSChainResolver.sol"; @@ -19,7 +19,7 @@ interface IZNSZChainPortal is IDistributionConfig { IZNSChainResolver chainResolver; IZNSTreasury treasury; IZNSRootRegistrarTrunk rootRegistrar; - IZNSSubRegistrar subRegistrar; + IZNSSubRegistrarTrunk subRegistrar; } event DomainBridged( @@ -42,7 +42,7 @@ interface IZNSZChainPortal is IDistributionConfig { function rootRegistrar() external view returns (IZNSRootRegistrarTrunk); - function subRegistrar() external view returns (IZNSSubRegistrar); + function subRegistrar() external view returns (IZNSSubRegistrarTrunk); function treasury() external view returns (IZNSTreasury); diff --git a/contracts/cross-chain/ZNSEthereumPortal.sol b/contracts/cross-chain/ZNSEthereumPortal.sol index b3b268ab5..ff43f3bba 100644 --- a/contracts/cross-chain/ZNSEthereumPortal.sol +++ b/contracts/cross-chain/ZNSEthereumPortal.sol @@ -9,14 +9,13 @@ import { IPolygonZkEVMBridgeV2Ext } from "./IPolygonZkEVMBridgeV2Ext.sol"; import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; import { BridgedDomain } from "../types/CrossChainTypes.sol"; import { IZNSRootRegistrarBranch } from "../registrar/IZNSRootRegistrarBranch.sol"; -import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; +import { IZNSSubRegistrarBranch } from "../registrar/IZNSSubRegistrarBranch.sol"; import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; import { IZNSPricer } from "../types/IZNSPricer.sol"; -// TODO multi: could this be a better name that implies cross-chain nature ??? contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPortal { // *--| Cross-chain Data |--* // TODO multi: should we keep this extended interface ??? @@ -28,7 +27,7 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPo // *--| ZNS Data for THIS chain |--* IZNSRootRegistrarBranch public rootRegistrar; - IZNSSubRegistrar public subRegistrar; + IZNSSubRegistrarBranch public subRegistrar; IZNSDomainToken public domainToken; IZNSRegistry public registry; @@ -44,7 +43,7 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPo IZNSRegistry registry_, IZNSDomainToken domainToken_, IZNSRootRegistrarBranch rootRegistrar_, - IZNSSubRegistrar subRegistrar_ + IZNSSubRegistrarBranch subRegistrar_ ) external override initializer { _setAccessController(accessController_); diff --git a/contracts/cross-chain/ZNSZChainPortal.sol b/contracts/cross-chain/ZNSZChainPortal.sol index 598c4ae30..dcee19f44 100644 --- a/contracts/cross-chain/ZNSZChainPortal.sol +++ b/contracts/cross-chain/ZNSZChainPortal.sol @@ -10,14 +10,13 @@ import { IZNSChainResolver } from "../resolver/IZNSChainResolver.sol"; import { IZNSPricer } from "../types/IZNSPricer.sol"; import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; import { IZNSRootRegistrarTrunk } from "../registrar/IZNSRootRegistrarTrunk.sol"; -import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; +import { IZNSSubRegistrarTrunk } from "../registrar/IZNSSubRegistrarTrunk.sol"; import { IZNSTreasury } from "../treasury/IZNSTreasury.sol"; import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; import { BridgedDomain } from "../types/CrossChainTypes.sol"; import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; -// TODO multi: can we make it work on ALL chain under ZkEVM ??? make contract more general ??? contract ZNSZChainPortal is UUPSUpgradeable, AAccessControlled, IZNSZChainPortal { // *--| Cross-chain Data |--* IPolygonZkEVMBridgeV2 public polygonZkEVMBridge; @@ -29,7 +28,7 @@ contract ZNSZChainPortal is UUPSUpgradeable, AAccessControlled, IZNSZChainPortal // *--| ZNS Data for THIS chain |--* IZNSRootRegistrarTrunk public rootRegistrar; - IZNSSubRegistrar public subRegistrar; + IZNSSubRegistrarTrunk public subRegistrar; IZNSTreasury public treasury; IZNSChainResolver public chainResolver; IZNSRegistry public registry; diff --git a/contracts/registrar/IZNSRootRegistrarBase.sol b/contracts/registrar/IZNSRootRegistrarBase.sol index 6b1c83e65..c3a80bf88 100644 --- a/contracts/registrar/IZNSRootRegistrarBase.sol +++ b/contracts/registrar/IZNSRootRegistrarBase.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; -import { IZNSSubRegistrar } from "./IZNSSubRegistrar.sol"; +import { IZNSSubRegistrarTrunk } from "./IZNSSubRegistrarTrunk.sol"; import { IZNSPricer } from "../types/IZNSPricer.sol"; import { IZNSTreasury } from "../treasury/IZNSTreasury.sol"; import { IZNSRootRegistrarTypes } from "./IZNSRootRegistrarTypes.sol"; @@ -64,5 +64,5 @@ interface IZNSRootRegistrarBase is IZNSRootRegistrarTypes { function domainToken() external view returns (IZNSDomainToken); - function subRegistrar() external view returns (IZNSSubRegistrar); + function subRegistrar() external view returns (IZNSSubRegistrarTrunk); } diff --git a/contracts/registrar/IZNSSubRegistrarBranch.sol b/contracts/registrar/IZNSSubRegistrarBranch.sol new file mode 100644 index 000000000..0081185f8 --- /dev/null +++ b/contracts/registrar/IZNSSubRegistrarBranch.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { IZNSSubRegistrarTrunk } from "./IZNSSubRegistrarTrunk.sol"; + + +interface IZNSSubRegistrarBranch is IZNSSubRegistrarTrunk { + function registerBridgedSubdomain( + bytes32 parentHash, + string calldata label, + string calldata tokenURI + ) external returns (bytes32); +} diff --git a/contracts/registrar/IZNSSubRegistrar.sol b/contracts/registrar/IZNSSubRegistrarTrunk.sol similarity index 91% rename from contracts/registrar/IZNSSubRegistrar.sol rename to contracts/registrar/IZNSSubRegistrarTrunk.sol index 684e31c9f..e394bbc98 100644 --- a/contracts/registrar/IZNSSubRegistrar.sol +++ b/contracts/registrar/IZNSSubRegistrarTrunk.sol @@ -1,146 +1,140 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.26; - -import { IDistributionConfig } from "../types/IDistributionConfig.sol"; -import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; -import { IZNSPricer } from "../types/IZNSPricer.sol"; - - -/** - * @title IZNSSubRegistrar.sol - Interface for the ZNSSubRegistrar contract responsible for registering subdomains. - */ -interface IZNSSubRegistrar is IDistributionConfig { - /** - * @notice Reverted when someone other than parent owner is trying to buy - * a subdomain under the parent that is locked - * or when the parent provided does not exist. - */ - error ParentLockedOrDoesntExist(bytes32 parentHash); - - /** - * @notice Reverted when the buyer of subdomain is not approved by the parent in it's mintlist. - */ - error SenderNotApprovedForPurchase(bytes32 parentHash, address sender); - - /** - * @notice Emitted when a new `DistributionConfig.pricerContract` is set for a domain. - */ - event PricerContractSet( - bytes32 indexed domainHash, - address indexed pricerContract - ); - - /** - * @notice Emitted when a new `DistributionConfig.paymentType` is set for a domain. - */ - event PaymentTypeSet(bytes32 indexed domainHash, PaymentType paymentType); - - /** - * @notice Emitted when a new `DistributionConfig.accessType` is set for a domain. - */ - event AccessTypeSet(bytes32 indexed domainHash, AccessType accessType); - - /** - * @notice Emitted when a new full `DistributionConfig` is set for a domain at once. - */ - event DistributionConfigSet( - bytes32 indexed domainHash, - IZNSPricer pricerContract, - PaymentType paymentType, - AccessType accessType - ); - - /** - * @notice Emitted when a `mintlist` is updated for a domain. - */ - event MintlistUpdated( - bytes32 indexed domainHash, - uint256 indexed ownerIndex, - address[] candidates, - bool[] allowed - ); - - /* - * @notice Emitted when a `mintlist` is removed for a domain by the owner or through - * `ZNSRootRegistrar.revokeDomain()`. - */ - event MintlistCleared(bytes32 indexed domainHash); - - /** - * @notice Emitted when the ZNSRootRegistrar address is set in state. - */ - event RootRegistrarSet(address registrar); - - function distrConfigs( - bytes32 domainHash - ) external view returns ( - IZNSPricer pricerContract, - PaymentType paymentType, - AccessType accessType - ); - - function isMintlistedForDomain( - bytes32 domainHash, - address candidate - ) external view returns (bool); - - function initialize( - address _accessController, - address _registry, - address _rootRegistrar - ) external; - - function registerSubdomain( - bytes32 parentHash, - string calldata label, - address domainAddress, - string calldata tokenURI, - DistributionConfig calldata configForSubdomains, - PaymentConfig calldata paymentConfig - ) external returns (bytes32); - - function registerBridgedSubdomain( - bytes32 parentHash, - string calldata label, - string calldata tokenURI - ) external returns (bytes32); - - function hashWithParent( - bytes32 parentHash, - string calldata label - ) external pure returns (bytes32); - - function setDistributionConfigForDomain( - bytes32 parentHash, - DistributionConfig calldata config - ) external; - - function setPricerContractForDomain( - bytes32 domainHash, - IZNSPricer pricerContract - ) external; - - function setPaymentTypeForDomain( - bytes32 domainHash, - PaymentType paymentType - ) external; - - function setAccessTypeForDomain( - bytes32 domainHash, - AccessType accessType - ) external; - - function updateMintlistForDomain( - bytes32 domainHash, - address[] calldata candidates, - bool[] calldata allowed - ) external; - - function clearMintlistForDomain(bytes32 domainHash) external; - - function clearMintlistAndLock(bytes32 domainHash) external; - - function setRegistry(address registry_) external; - - function setRootRegistrar(address registrar_) external; -} +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { IDistributionConfig } from "../types/IDistributionConfig.sol"; +import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; +import { IZNSPricer } from "../types/IZNSPricer.sol"; + + +/** + * @title IZNSSubRegistrar.sol - Interface for the ZNSSubRegistrar contract responsible for registering subdomains. + */ +interface IZNSSubRegistrarTrunk is IDistributionConfig { + /** + * @notice Reverted when someone other than parent owner is trying to buy + * a subdomain under the parent that is locked + * or when the parent provided does not exist. + */ + error ParentLockedOrDoesntExist(bytes32 parentHash); + + /** + * @notice Reverted when the buyer of subdomain is not approved by the parent in it's mintlist. + */ + error SenderNotApprovedForPurchase(bytes32 parentHash, address sender); + + /** + * @notice Emitted when a new `DistributionConfig.pricerContract` is set for a domain. + */ + event PricerContractSet( + bytes32 indexed domainHash, + address indexed pricerContract + ); + + /** + * @notice Emitted when a new `DistributionConfig.paymentType` is set for a domain. + */ + event PaymentTypeSet(bytes32 indexed domainHash, PaymentType paymentType); + + /** + * @notice Emitted when a new `DistributionConfig.accessType` is set for a domain. + */ + event AccessTypeSet(bytes32 indexed domainHash, AccessType accessType); + + /** + * @notice Emitted when a new full `DistributionConfig` is set for a domain at once. + */ + event DistributionConfigSet( + bytes32 indexed domainHash, + IZNSPricer pricerContract, + PaymentType paymentType, + AccessType accessType + ); + + /** + * @notice Emitted when a `mintlist` is updated for a domain. + */ + event MintlistUpdated( + bytes32 indexed domainHash, + uint256 indexed ownerIndex, + address[] candidates, + bool[] allowed + ); + + /* + * @notice Emitted when a `mintlist` is removed for a domain by the owner or through + * `ZNSRootRegistrar.revokeDomain()`. + */ + event MintlistCleared(bytes32 indexed domainHash); + + /** + * @notice Emitted when the ZNSRootRegistrar address is set in state. + */ + event RootRegistrarSet(address registrar); + + function distrConfigs( + bytes32 domainHash + ) external view returns ( + IZNSPricer pricerContract, + PaymentType paymentType, + AccessType accessType + ); + + function isMintlistedForDomain( + bytes32 domainHash, + address candidate + ) external view returns (bool); + + function initialize( + address _accessController, + address _registry, + address _rootRegistrar + ) external; + + function registerSubdomain( + bytes32 parentHash, + string calldata label, + address domainAddress, + string calldata tokenURI, + DistributionConfig calldata configForSubdomains, + PaymentConfig calldata paymentConfig + ) external returns (bytes32); + + function hashWithParent( + bytes32 parentHash, + string calldata label + ) external pure returns (bytes32); + + function setDistributionConfigForDomain( + bytes32 parentHash, + DistributionConfig calldata config + ) external; + + function setPricerContractForDomain( + bytes32 domainHash, + IZNSPricer pricerContract + ) external; + + function setPaymentTypeForDomain( + bytes32 domainHash, + PaymentType paymentType + ) external; + + function setAccessTypeForDomain( + bytes32 domainHash, + AccessType accessType + ) external; + + function updateMintlistForDomain( + bytes32 domainHash, + address[] calldata candidates, + bool[] calldata allowed + ) external; + + function clearMintlistForDomain(bytes32 domainHash) external; + + function clearMintlistAndLock(bytes32 domainHash) external; + + function setRegistry(address registry_) external; + + function setRootRegistrar(address registrar_) external; +} diff --git a/contracts/registrar/ZNSRootRegistrarBase.sol b/contracts/registrar/ZNSRootRegistrarBase.sol index a1a358c2c..feca8779b 100644 --- a/contracts/registrar/ZNSRootRegistrarBase.sol +++ b/contracts/registrar/ZNSRootRegistrarBase.sol @@ -8,7 +8,7 @@ import { IZNSRootRegistrarTypes, CoreRegisterArgs } from "./IZNSRootRegistrarTyp import { IZNSTreasury, PaymentConfig } from "../treasury/IZNSTreasury.sol"; import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; import { IZNSAddressResolver } from "../resolver/IZNSAddressResolver.sol"; -import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; +import { IZNSSubRegistrarTrunk } from "../registrar/IZNSSubRegistrarTrunk.sol"; import { IZNSPricer } from "../types/IZNSPricer.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { StringUtils } from "../utils/StringUtils.sol"; @@ -39,7 +39,7 @@ contract ZNSRootRegistrarBase is IZNSPricer public rootPricer; IZNSTreasury public treasury; IZNSDomainToken public domainToken; - IZNSSubRegistrar public subRegistrar; + IZNSSubRegistrarTrunk public subRegistrar; /// @custom:oz-upgrades-unsafe-allow constructor constructor() { @@ -372,7 +372,7 @@ contract ZNSRootRegistrarBase is if (subRegistrar_ == address(0)) revert ZeroAddressPassed(); - subRegistrar = IZNSSubRegistrar(subRegistrar_); + subRegistrar = IZNSSubRegistrarTrunk(subRegistrar_); emit SubRegistrarSet(subRegistrar_); } diff --git a/contracts/registrar/ZNSRootRegistrarBranch.sol b/contracts/registrar/ZNSRootRegistrarBranch.sol index a6f45e317..fc182144d 100644 --- a/contracts/registrar/ZNSRootRegistrarBranch.sol +++ b/contracts/registrar/ZNSRootRegistrarBranch.sol @@ -7,11 +7,7 @@ import { ZNSRootRegistrarBase } from "./ZNSRootRegistrarBase.sol"; import { IZNSRootRegistrarBranch } from "./IZNSRootRegistrarBranch.sol"; import { IZNSRootRegistrarBase } from "./IZNSRootRegistrarBase.sol"; import { CoreRegisterArgs } from "./IZNSRootRegistrarTypes.sol"; -import { IZNSTreasury, PaymentConfig } from "../treasury/IZNSTreasury.sol"; -import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; -import { IZNSAddressResolver } from "../resolver/IZNSAddressResolver.sol"; -import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; -import { IZNSPricer } from "../types/IZNSPricer.sol"; +import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { StringUtils } from "../utils/StringUtils.sol"; import { ZeroAddressPassed, DomainAlreadyExists } from "../utils/CommonErrors.sol"; @@ -32,6 +28,7 @@ import { ZeroAddressPassed, DomainAlreadyExists } from "../utils/CommonErrors.so * logic required to be performed for any level domains. */ contract ZNSRootRegistrarBranch is +// TODO multi: fix inheritance on all child contracts! it is not needed!!! UUPSUpgradeable, AAccessControlled, ARegistryWired, diff --git a/contracts/registrar/ZNSRootRegistrarTrunk.sol b/contracts/registrar/ZNSRootRegistrarTrunk.sol index 81a9cf877..e70600196 100644 --- a/contracts/registrar/ZNSRootRegistrarTrunk.sol +++ b/contracts/registrar/ZNSRootRegistrarTrunk.sol @@ -10,16 +10,12 @@ import { CoreRegisterArgs } from "./IZNSRootRegistrarTypes.sol"; import { IZNSTreasury, PaymentConfig } from "../treasury/IZNSTreasury.sol"; import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; import { IZNSAddressResolver } from "../resolver/IZNSAddressResolver.sol"; -import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; import { IZNSPricer } from "../types/IZNSPricer.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { StringUtils } from "../utils/StringUtils.sol"; import { ZeroAddressPassed, DomainAlreadyExists } from "../utils/CommonErrors.sol"; -// TODO multi: MAKE SURE IT IS NOT POSSIBLE TO REGISTER ROOT DOMAIN ON ZCHAIN!!!! -// NEW LOGIC NEEDS TO BE ADDED FOR THAT !!! -// TEST THIS !!!!! /** * @title Main entry point for the three main flows of ZNS - Register Root Domain, Reclaim and Revoke any domain. * @notice This contract serves as the "umbrella" for many ZNS operations, it is given REGISTRAR_ROLE diff --git a/contracts/registrar/ZNSSubRegistrarBranch.sol b/contracts/registrar/ZNSSubRegistrarBranch.sol new file mode 100644 index 000000000..fc2823093 --- /dev/null +++ b/contracts/registrar/ZNSSubRegistrarBranch.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { IZNSSubRegistrarBranch } from "./IZNSSubRegistrarBranch.sol"; +import { ZNSSubRegistrarTrunk } from "./ZNSSubRegistrarTrunk.sol"; +import { IZNSSubRegistrarTrunk } from "./IZNSSubRegistrarTrunk.sol"; +import { IDistributionConfig } from "../types/IDistributionConfig.sol"; +import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; + + +contract ZNSSubRegistrarBranch is ZNSSubRegistrarTrunk, IZNSSubRegistrarBranch { + function registerBridgedSubdomain( + bytes32 parentHash, + string calldata label, + string calldata tokenURI + ) external override returns (bytes32) { + accessController.checkPortal(msg.sender); + + DistributionConfig memory emptyDistrConfig; + PaymentConfig memory emptyPaymentConfig; + + return _coreSubdomainRegister( + parentHash, + label, + address(0), + tokenURI, + emptyDistrConfig, + emptyPaymentConfig, + true + ); + } + + function setRegistry(address registry) public override( + ZNSSubRegistrarTrunk, + IZNSSubRegistrarTrunk + ) onlyAdmin { + super.setRegistry(registry); + } +} diff --git a/contracts/registrar/ZNSSubRegistrar.sol b/contracts/registrar/ZNSSubRegistrarTrunk.sol similarity index 94% rename from contracts/registrar/ZNSSubRegistrar.sol rename to contracts/registrar/ZNSSubRegistrarTrunk.sol index e2fbf7e77..d19c413ae 100644 --- a/contracts/registrar/ZNSSubRegistrar.sol +++ b/contracts/registrar/ZNSSubRegistrarTrunk.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.26; import { IZNSPricer } from "../types/IZNSPricer.sol"; import { IZNSRootRegistrarBase } from "./IZNSRootRegistrarBase.sol"; import { CoreRegisterArgs } from "./IZNSRootRegistrarTypes.sol"; -import { IZNSSubRegistrar } from "./IZNSSubRegistrar.sol"; +import { IZNSSubRegistrarTrunk } from "./IZNSSubRegistrarTrunk.sol"; import { AAccessControlled } from "../access/AAccessControlled.sol"; import { ARegistryWired } from "../registry/ARegistryWired.sol"; import { StringUtils } from "../utils/StringUtils.sol"; @@ -20,7 +20,7 @@ import { DomainAlreadyExists, ZeroAddressPassed, NotAuthorizedForDomain } from " * the ZNSRootRegistrar back to finalize registration. Common logic for domains * of any level is in the `ZNSRootRegistrar.coreRegister()`. */ -contract ZNSSubRegistrar is AAccessControlled, ARegistryWired, UUPSUpgradeable, IZNSSubRegistrar { +contract ZNSSubRegistrarTrunk is AAccessControlled, ARegistryWired, UUPSUpgradeable, IZNSSubRegistrarTrunk { using StringUtils for string; /** @@ -104,27 +104,6 @@ contract ZNSSubRegistrar is AAccessControlled, ARegistryWired, UUPSUpgradeable, ); } - function registerBridgedSubdomain( - bytes32 parentHash, - string calldata label, - string calldata tokenURI - ) external override returns (bytes32) { - accessController.checkPortal(msg.sender); - - DistributionConfig memory emptyDistrConfig; - PaymentConfig memory emptyPaymentConfig; - - return _coreSubdomainRegister( - parentHash, - label, - address(0), - tokenURI, - emptyDistrConfig, - emptyPaymentConfig, - true - ); - } - function _coreSubdomainRegister( bytes32 parentHash, string calldata label, @@ -374,7 +353,7 @@ contract ZNSSubRegistrar is AAccessControlled, ARegistryWired, UUPSUpgradeable, * @notice Sets the registry address in state. * @dev This function is required for all contracts inheriting `ARegistryWired`. */ - function setRegistry(address registry_) public override(ARegistryWired, IZNSSubRegistrar) onlyAdmin { + function setRegistry(address registry_) public virtual override(ARegistryWired, IZNSSubRegistrarTrunk) onlyAdmin { _setRegistry(registry_); } diff --git a/contracts/upgrade-test-mocks/distribution/ZNSSubRegistrarMock.sol b/contracts/upgrade-test-mocks/distribution/ZNSSubRegistrarMock.sol index cdf7e50d2..4e03802c6 100644 --- a/contracts/upgrade-test-mocks/distribution/ZNSSubRegistrarMock.sol +++ b/contracts/upgrade-test-mocks/distribution/ZNSSubRegistrarMock.sol @@ -3,8 +3,9 @@ pragma solidity 0.8.26; // solhint-disable -import { ZNSSubRegistrar } from "../../registrar/ZNSSubRegistrar.sol"; -import { IZNSSubRegistrar } from "../../registrar/IZNSSubRegistrar.sol"; +// TODO multi: fix these are remove unnecessary imports +import { ZNSSubRegistrarTrunk } from "../../registrar/ZNSSubRegistrarTrunk.sol"; +import { IZNSSubRegistrarTrunk } from "../../registrar/IZNSSubRegistrarTrunk.sol"; import { UpgradeMock } from "../UpgradeMock.sol"; import { IZNSPricer } from "../../types/IZNSPricer.sol"; import { IZNSRootRegistrarBase, CoreRegisterArgs } from "../../registrar/IZNSRootRegistrarBase.sol"; From 5acbe9ec2cdec248b8d7ac73c83bf51599c0175f Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 29 Oct 2024 16:01:41 -0700 Subject: [PATCH 079/124] extend SubRegistrarDM to determine which contract to deploy based on chain --- src/deploy/missions/contracts/names.ts | 3 ++- .../contracts/zns-base/sub-registrar.ts | 22 +++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/deploy/missions/contracts/names.ts b/src/deploy/missions/contracts/names.ts index 967837dd0..acba4be94 100644 --- a/src/deploy/missions/contracts/names.ts +++ b/src/deploy/missions/contracts/names.ts @@ -50,7 +50,8 @@ export const znsNames = { instance: "rootRegistrar", }, subRegistrar: { - contract: "ZNSSubRegistrar", + contractTrunk: "ZNSSubRegistrarTrunk", + contractBranch: "ZNSSubRegistrarBranch", instance: "subRegistrar", }, zPortal: { diff --git a/src/deploy/missions/contracts/zns-base/sub-registrar.ts b/src/deploy/missions/contracts/zns-base/sub-registrar.ts index 017971844..af3c8d0e2 100644 --- a/src/deploy/missions/contracts/zns-base/sub-registrar.ts +++ b/src/deploy/missions/contracts/zns-base/sub-registrar.ts @@ -1,5 +1,5 @@ import { - BaseDeployMission, + BaseDeployMission, IDeployMissionArgs, TDeployArgs, } from "@zero-tech/zdc"; import { ProxyKinds, REGISTRAR_ROLE } from "../../../constants"; @@ -7,6 +7,7 @@ import { znsNames } from "../names"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; +import { SupportedChains } from "../cross-chain/portals/get-portal-dm"; export class ZNSSubRegistrarDM extends BaseDeployMission< @@ -20,12 +21,29 @@ IZNSContracts kind: ProxyKinds.uups, }; - contractName = znsNames.subRegistrar.contract; + contractName = znsNames.subRegistrar.contractTrunk; instanceName = znsNames.subRegistrar.instance; private hasRegistrarRole : boolean | undefined; private isSetOnRoot : boolean | undefined; + constructor (args : IDeployMissionArgs< + HardhatRuntimeEnvironment, + SignerWithAddress, + IZNSCampaignConfig, + IZNSContracts + >) { + super(args); + + if (this.config.crosschain.srcChainName === SupportedChains.eth) { + this.contractName = znsNames.subRegistrar.contractTrunk; + } else if (this.config.crosschain.srcChainName === SupportedChains.z) { + this.contractName = znsNames.subRegistrar.contractBranch; + } else { + throw new Error("Unsupported chain for Root Registrar deployment"); + } + } + async deployArgs () : Promise { const { accessController, From 39beb3b5ecdb048e898a345812ba78a6c364bacf Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 29 Oct 2024 16:10:02 -0700 Subject: [PATCH 080/124] fix inheritance and remove redundant imports --- contracts/registrar/ZNSRootRegistrarBranch.sol | 18 +++++------------- contracts/registrar/ZNSRootRegistrarTrunk.sol | 15 +-------------- 2 files changed, 6 insertions(+), 27 deletions(-) diff --git a/contracts/registrar/ZNSRootRegistrarBranch.sol b/contracts/registrar/ZNSRootRegistrarBranch.sol index fc182144d..7d73050f0 100644 --- a/contracts/registrar/ZNSRootRegistrarBranch.sol +++ b/contracts/registrar/ZNSRootRegistrarBranch.sol @@ -1,16 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.26; -import { AAccessControlled } from "../access/AAccessControlled.sol"; -import { ARegistryWired } from "../registry/ARegistryWired.sol"; import { ZNSRootRegistrarBase } from "./ZNSRootRegistrarBase.sol"; import { IZNSRootRegistrarBranch } from "./IZNSRootRegistrarBranch.sol"; import { IZNSRootRegistrarBase } from "./IZNSRootRegistrarBase.sol"; -import { CoreRegisterArgs } from "./IZNSRootRegistrarTypes.sol"; import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; -import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import { StringUtils } from "../utils/StringUtils.sol"; -import { ZeroAddressPassed, DomainAlreadyExists } from "../utils/CommonErrors.sol"; // TODO multi: fix NatSpec here ! @@ -28,10 +22,6 @@ import { ZeroAddressPassed, DomainAlreadyExists } from "../utils/CommonErrors.so * logic required to be performed for any level domains. */ contract ZNSRootRegistrarBranch is -// TODO multi: fix inheritance on all child contracts! it is not needed!!! - UUPSUpgradeable, - AAccessControlled, - ARegistryWired, ZNSRootRegistrarBase, IZNSRootRegistrarBranch { @@ -55,11 +45,13 @@ contract ZNSRootRegistrarBranch is ); } - function setRegistry(address registry) public override( - ARegistryWired, + function setRegistry(address registry) + public + override( ZNSRootRegistrarBase, IZNSRootRegistrarBase - ) onlyAdmin { + ) + onlyAdmin { super.setRegistry(registry); } } diff --git a/contracts/registrar/ZNSRootRegistrarTrunk.sol b/contracts/registrar/ZNSRootRegistrarTrunk.sol index e70600196..584dc93b4 100644 --- a/contracts/registrar/ZNSRootRegistrarTrunk.sol +++ b/contracts/registrar/ZNSRootRegistrarTrunk.sol @@ -1,19 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.26; -import { AAccessControlled } from "../access/AAccessControlled.sol"; -import { ARegistryWired } from "../registry/ARegistryWired.sol"; import { ZNSRootRegistrarBase } from "./ZNSRootRegistrarBase.sol"; import { IZNSRootRegistrarTrunk } from "./IZNSRootRegistrarTrunk.sol"; import { IZNSRootRegistrarBase } from "./IZNSRootRegistrarBase.sol"; -import { CoreRegisterArgs } from "./IZNSRootRegistrarTypes.sol"; -import { IZNSTreasury, PaymentConfig } from "../treasury/IZNSTreasury.sol"; -import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; -import { IZNSAddressResolver } from "../resolver/IZNSAddressResolver.sol"; -import { IZNSPricer } from "../types/IZNSPricer.sol"; -import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import { StringUtils } from "../utils/StringUtils.sol"; -import { ZeroAddressPassed, DomainAlreadyExists } from "../utils/CommonErrors.sol"; +import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; /** @@ -30,9 +21,6 @@ import { ZeroAddressPassed, DomainAlreadyExists } from "../utils/CommonErrors.so * logic required to be performed for any level domains. */ contract ZNSRootRegistrarTrunk is - UUPSUpgradeable, - AAccessControlled, - ARegistryWired, ZNSRootRegistrarBase, IZNSRootRegistrarTrunk { @@ -73,7 +61,6 @@ contract ZNSRootRegistrarTrunk is } function setRegistry(address registry) public override( - ARegistryWired, ZNSRootRegistrarBase, IZNSRootRegistrarBase ) onlyAdmin { From ae67938c45d21c52477bf3c89871400671b6544f Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 5 Nov 2024 09:27:00 -0800 Subject: [PATCH 081/124] add revert to not allow bridging domains if the opposite portal is not set in state --- contracts/cross-chain/IZNSZChainPortal.sol | 2 ++ contracts/cross-chain/ZNSZChainPortal.sol | 4 ++++ contracts/registrar/ZNSSubRegistrarTrunk.sol | 1 - 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/contracts/cross-chain/IZNSZChainPortal.sol b/contracts/cross-chain/IZNSZChainPortal.sol index c5a35ccee..33d192851 100644 --- a/contracts/cross-chain/IZNSZChainPortal.sol +++ b/contracts/cross-chain/IZNSZChainPortal.sol @@ -30,6 +30,8 @@ interface IZNSZChainPortal is IDistributionConfig { ); event DestZnsPortalSet(address newAddress); + error DestinationPortalNotSetInState(); + function polygonZkEVMBridge() external view returns (IPolygonZkEVMBridgeV2); function destNetworkId() external view returns (uint32); diff --git a/contracts/cross-chain/ZNSZChainPortal.sol b/contracts/cross-chain/ZNSZChainPortal.sol index dcee19f44..4363616a9 100644 --- a/contracts/cross-chain/ZNSZChainPortal.sol +++ b/contracts/cross-chain/ZNSZChainPortal.sol @@ -190,6 +190,10 @@ contract ZNSZChainPortal is UUPSUpgradeable, AAccessControlled, IZNSZChainPortal bytes memory encodedProof = abi.encode(proof); + // TODO multi: should we leave this? We can't rely on setting this properly on time + // and can permanently lock domains !!! + if (destZnsPortal == address(0)) revert DestinationPortalNotSetInState(); + polygonZkEVMBridge.bridgeMessage( destNetworkId, destZnsPortal, diff --git a/contracts/registrar/ZNSSubRegistrarTrunk.sol b/contracts/registrar/ZNSSubRegistrarTrunk.sol index d19c413ae..71cc0a23a 100644 --- a/contracts/registrar/ZNSSubRegistrarTrunk.sol +++ b/contracts/registrar/ZNSSubRegistrarTrunk.sol @@ -13,7 +13,6 @@ import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils import { DomainAlreadyExists, ZeroAddressPassed, NotAuthorizedForDomain } from "../utils/CommonErrors.sol"; -// TODO multi: should we split this for Trunk and Branch as well ??? /** * @title ZNSSubRegistrar.sol - The contract for registering and revoking subdomains of zNS. * @dev This contract has the entry point for registering subdomains, but calls From 6fefbe38b786a66168ea8ecc98c20fd95f75cd1b Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 5 Nov 2024 09:27:52 -0800 Subject: [PATCH 082/124] extend and adapt some helpers --- test/helpers/errors.ts | 1 + test/helpers/events.ts | 8 +++++-- test/helpers/register-setup.ts | 38 +++++++++++++++++++++++----------- test/helpers/tokens.ts | 8 +++---- test/helpers/types.ts | 23 ++++++++++++-------- 5 files changed, 51 insertions(+), 27 deletions(-) diff --git a/test/helpers/errors.ts b/test/helpers/errors.ts index 741032aa0..cca946010 100644 --- a/test/helpers/errors.ts +++ b/test/helpers/errors.ts @@ -49,6 +49,7 @@ export const INVALID_CALLER_ERR = "InvalidCaller"; export const INVALID_ORIGIN_ERR = "InvalidOriginAddress"; export const DOMAIN_HASH_NO_MATCH_ERR = "DomainHashDoesNotMatchBridged"; export const MESSAGE_FAILED_ERR = "MessageFailed"; +export const DEST_PORTAL_NOT_SET_ERR = "DestinationPortalNotSetInState"; // Environment validation export const INVALID_ENV_ERR = "Invalid environment value. Must set env to one of `dev`, `test`, or `prod`"; diff --git a/test/helpers/events.ts b/test/helpers/events.ts index c553aa295..2b1cf087e 100644 --- a/test/helpers/events.ts +++ b/test/helpers/events.ts @@ -35,9 +35,11 @@ export const getDomainRegisteredEvents = async ({ export const getDomainHashFromEvent = async ({ zns, registrantAddress, + fromBlock, } : { zns : IZNSContractsLocal | IZNSContracts; registrantAddress : string; + fromBlock ?: number; }) : Promise => { const filter = zns.rootRegistrar.filters.DomainRegistered( undefined, @@ -49,7 +51,7 @@ export const getDomainHashFromEvent = async ({ undefined, ); - const events = await zns.rootRegistrar.queryFilter(filter); + const events = await zns.rootRegistrar.queryFilter(filter, fromBlock); const { args: { domainHash } } = events[events.length - 1]; return domainHash; @@ -59,12 +61,14 @@ export const getEvents = async ({ contract, eventName, args, + fromBlock, } : { contract : any; eventName : string; args ?: any; + fromBlock ?: number; }) : Promise>> => { const filter = contract.filters[eventName](args); - return contract.queryFilter(filter); + return contract.queryFilter(filter, fromBlock); }; diff --git a/test/helpers/register-setup.ts b/test/helpers/register-setup.ts index 6a8f7b8fb..e4b9c1904 100644 --- a/test/helpers/register-setup.ts +++ b/test/helpers/register-setup.ts @@ -12,6 +12,7 @@ import { getTokenContract } from "./tokens"; import { ICurvePriceConfig } from "../../src/deploy/missions/types"; import { expect } from "chai"; import { IZNSContracts } from "../../src/deploy/campaign/types"; +import { MeowTokenMock, ZNSRootRegistrarTrunk } from "../../typechain"; const { ZeroAddress } = ethers; @@ -33,7 +34,7 @@ export const defaultRootRegistration = async ({ }) : Promise => { const supplyBefore = await zns.domainToken.totalSupply(); - const tx = await zns.rootRegistrar.connect(user).registerRootDomain( + const tx = await (zns.rootRegistrar as ZNSRootRegistrarTrunk).connect(user).registerRootDomain( domainName, domainContent, // Arbitrary address value tokenURI, @@ -47,21 +48,25 @@ export const defaultRootRegistration = async ({ return tx.wait(); }; -export const approveForParent = async ({ +export const approveForDomain = async ({ zns, parentHash, user, domainLabel, + isBridging = false, + mintTokens = false, } : { zns : IZNSContractsLocal | IZNSContracts; parentHash : string; user : SignerWithAddress; domainLabel : string; + isBridging ?: boolean; + mintTokens ?: boolean; }) => { const { pricerContract } = await zns.subRegistrar.distrConfigs(parentHash); let price = BigInt(0); let parentFee = BigInt(0); - if (pricerContract === await zns.curvePricer.getAddress()) { + if (pricerContract === await zns.curvePricer.getAddress() || parentHash === ethers.ZeroHash) { [price, parentFee] = await zns.curvePricer.getPriceAndFee(parentHash, domainLabel, false); } else if (pricerContract === await zns.fixedPricer.getAddress()) { [price, parentFee] = await zns.fixedPricer.getPriceAndFee(parentHash, domainLabel, false); @@ -73,7 +78,11 @@ export const approveForParent = async ({ const protocolFee = await zns.curvePricer.getFeeForPrice(ethers.ZeroHash, price + parentFee); const toApprove = price + parentFee + protocolFee; - return tokenContract.connect(user).approve(await zns.treasury.getAddress(), toApprove); + if (mintTokens) + await tokenContract.connect(user).mint(user.address, toApprove); + + const spender = isBridging ? await zns.zPortal.getAddress() : await zns.treasury.getAddress(); + return tokenContract.connect(user).approve(spender, toApprove); }; /** @@ -125,6 +134,7 @@ export const registrationWithSetup = async ({ tokenURI = DEFAULT_TOKEN_URI, fullConfig = fullDistrConfigEmpty, setConfigs = true, + mintTokens = false, } : { zns : IZNSContractsLocal | IZNSContracts; user : SignerWithAddress; @@ -134,14 +144,25 @@ export const registrationWithSetup = async ({ tokenURI ?: string; fullConfig ?: IFullDistributionConfig; setConfigs ?: boolean; + mintTokens ?: boolean; }) => { const hasConfig = !!fullConfig; const distrConfig = hasConfig ? fullConfig.distrConfig : distrConfigEmpty; + parentHash = parentHash || ethers.ZeroHash; + + await approveForDomain({ + zns, + parentHash, + user, + domainLabel, + mintTokens, + }); + // register domain - if (!parentHash || parentHash === ethers.ZeroHash) { + if (parentHash === ethers.ZeroHash) { await defaultRootRegistration({ user, zns, @@ -151,13 +172,6 @@ export const registrationWithSetup = async ({ distrConfig, }); } else { - await approveForParent({ - zns, - parentHash, - user, - domainLabel, - }); - await defaultSubdomainRegistration({ user, zns, diff --git a/test/helpers/tokens.ts b/test/helpers/tokens.ts index 15b723f1d..fc6a6da3a 100644 --- a/test/helpers/tokens.ts +++ b/test/helpers/tokens.ts @@ -1,11 +1,11 @@ -import { ERC20, IERC20__factory } from "../../typechain"; +import { MeowTokenMock, MeowTokenMock__factory } from "../../typechain"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; export const getTokenContract = ( address : string, signer : SignerWithAddress -) : ERC20 => { - const ierc20 = IERC20__factory.connect(address, signer); - return ierc20.attach(address) as ERC20; +) : MeowTokenMock => { + const ierc20 = MeowTokenMock__factory.connect(address, signer); + return ierc20.attach(address) as MeowTokenMock; }; diff --git a/test/helpers/types.ts b/test/helpers/types.ts index a825824a6..e9d8ec93d 100644 --- a/test/helpers/types.ts +++ b/test/helpers/types.ts @@ -1,30 +1,30 @@ import { - MeowTokenMock, + MeowTokenMock, PolygonZkEVMBridgeV2Mock, ZNSAccessController, ZNSAddressResolver, ZNSAddressResolverUpgradeMock, - ZNSAddressResolverUpgradeMock__factory, + ZNSAddressResolverUpgradeMock__factory, ZNSChainResolver, ZNSCurvePricer, ZNSCurvePricerUpgradeMock, ZNSCurvePricerUpgradeMock__factory, ZNSDomainToken, ZNSDomainTokenUpgradeMock, - ZNSDomainTokenUpgradeMock__factory, + ZNSDomainTokenUpgradeMock__factory, ZNSEthereumPortal, ZNSFixedPricer, ZNSFixedPricerUpgradeMock, ZNSFixedPricerUpgradeMock__factory, ZNSRegistry, ZNSRegistryUpgradeMock, ZNSRegistryUpgradeMock__factory, - ZNSRootRegistrar, + ZNSRootRegistrarBranch, ZNSRootRegistrarTrunk, ZNSRootRegistrarUpgradeMock, - ZNSRootRegistrarUpgradeMock__factory, - ZNSSubRegistrar, + ZNSRootRegistrarUpgradeMock__factory, ZNSStringResolver, + ZNSSubRegistrarBranch, ZNSSubRegistrarTrunk, ZNSSubRegistrarUpgradeMock, ZNSSubRegistrarUpgradeMock__factory, ZNSTreasury, ZNSTreasuryUpgradeMock, - ZNSTreasuryUpgradeMock__factory, + ZNSTreasuryUpgradeMock__factory, ZNSZChainPortal, } from "../../typechain"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { ICurvePriceConfig } from "../../src/deploy/missions/types"; @@ -84,11 +84,16 @@ export interface IZNSContractsLocal { domainToken : ZNSDomainToken; meowToken : MeowTokenMock; addressResolver : ZNSAddressResolver; + stringResolver : ZNSStringResolver; + chainResolver : ZNSChainResolver; curvePricer : ZNSCurvePricer; treasury : ZNSTreasury; - rootRegistrar : ZNSRootRegistrar; + rootRegistrar : ZNSRootRegistrarTrunk | ZNSRootRegistrarBranch; fixedPricer : ZNSFixedPricer; - subRegistrar : ZNSSubRegistrar; + subRegistrar : ZNSSubRegistrarTrunk | ZNSSubRegistrarBranch; + zPortal : ZNSZChainPortal; + ethPortal : ZNSEthereumPortal; + zkEvmBridge : PolygonZkEVMBridgeV2Mock; zeroVaultAddress : string; } From 7d4bb7492b776a2e24ebd8686360c3c438691f89 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 5 Nov 2024 09:28:35 -0800 Subject: [PATCH 083/124] fix types --- .../missions/contracts/cross-chain/portals/get-portal-dm.ts | 4 ++-- src/deploy/missions/contracts/cross-chain/portals/types.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/deploy/missions/contracts/cross-chain/portals/get-portal-dm.ts b/src/deploy/missions/contracts/cross-chain/portals/get-portal-dm.ts index ad1546f69..6272ce511 100644 --- a/src/deploy/missions/contracts/cross-chain/portals/get-portal-dm.ts +++ b/src/deploy/missions/contracts/cross-chain/portals/get-portal-dm.ts @@ -4,8 +4,8 @@ import { ISupportedChains, TSupportedChain } from "./types"; export const SupportedChains : ISupportedChains = { - z: "ZChain", - eth: "Ethereum", + z: "zchain", + eth: "ethereum", }; diff --git a/src/deploy/missions/contracts/cross-chain/portals/types.ts b/src/deploy/missions/contracts/cross-chain/portals/types.ts index 9cd37a5ab..d1aaf2e04 100644 --- a/src/deploy/missions/contracts/cross-chain/portals/types.ts +++ b/src/deploy/missions/contracts/cross-chain/portals/types.ts @@ -1,4 +1,4 @@ -export type TSupportedChain = "ZChain" | "Ethereum"; +export type TSupportedChain = "zchain" | "ethereum"; export interface ISupportedChains { z : TSupportedChain; eth : TSupportedChain; From c6dcebf61596472281bf464d60713f1b627ceb61 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 5 Nov 2024 09:29:14 -0800 Subject: [PATCH 084/124] adapt test to be run on test networks --- test/L2-BRIDGE-TEST/MultiZNS.test.ts | 427 +++++++++++++++++---------- 1 file changed, 264 insertions(+), 163 deletions(-) diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/L2-BRIDGE-TEST/MultiZNS.test.ts index 8cdd0f76d..04b35e666 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/L2-BRIDGE-TEST/MultiZNS.test.ts @@ -4,26 +4,24 @@ import { runZnsCampaign } from "../../src/deploy/zns-campaign"; import { IZNSCampaignConfig, IZNSContracts, - IZNSEthCrossConfig, IZNSZChainCrossConfig, } from "../../src/deploy/campaign/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { registrationWithSetup } from "../helpers/register-setup"; +import { approveForDomain, registrationWithSetup } from "../helpers/register-setup"; import { AC_UNAUTHORIZED_ERR, AccessType, DEFAULT_PRICE_CONFIG, - DEFAULT_TOKEN_URI, + DEFAULT_TOKEN_URI, DEST_PORTAL_NOT_SET_ERR, distrConfigEmpty, DISTRIBUTION_LOCKED_NOT_EXIST_ERR, - DOMAIN_HASH_NO_MATCH_ERR, fullDistrConfigEmpty, getCurvePrice, getStakingOrProtocolFee, hashDomainLabel, INITIALIZED_ERR, INVALID_CALLER_ERR, - INVALID_ORIGIN_ERR, MESSAGE_FAILED_ERR, + MESSAGE_FAILED_ERR, NOT_AUTHORIZED_ERR, NOT_OWNER_OF_ERR, PaymentType, @@ -32,15 +30,16 @@ import { import { expect } from "chai"; import * as ethers from "ethers"; import { getDomainHashFromEvent, getEvents } from "../helpers/events"; -import { ContractTransactionReceipt } from "ethers"; +import { ContractTransactionReceipt, Wallet } from "ethers"; import { SupportedChains } from "../../src/deploy/missions/contracts/cross-chain/portals/get-portal-dm"; import { resetMongoAdapter } from "@zero-tech/zdc"; +import assert from "assert"; -export const NETWORK_ID_L1_DEFAULT = 1n; -export const NETWORK_ID_L2_DEFAULT = 369n; +export const NETWORK_ID_L1_DEFAULT = 0n; +export const NETWORK_ID_L2_DEFAULT = 19n; -const zChainID = 336699n; +const zChainID = 1668201165n; const resetEnvVars = () => { @@ -53,17 +52,23 @@ const resetEnvVars = () => { delete process.env.SRC_ZNS_PORTAL; }; +// TODO multi: add ChainResolver tests !!! describe.only("MultiZNS", () => { + let isRealNetwork = false; + let znsL1 : IZNSContracts; let znsL2 : IZNSContracts; let deployAdmin : SignerWithAddress; + let deployAdminL2 : Wallet | SignerWithAddress; let user : SignerWithAddress; + let userL2 : Wallet | SignerWithAddress; let subUser : SignerWithAddress; + let subUserL2 : Wallet | SignerWithAddress; let config : IZNSCampaignConfig; - const rootDomainLabel = "jeffbridges"; + const rootDomainLabel = "jefffbridges"; const subdomainLabel = "beaubridges"; const subParentLabel = "bridges"; @@ -79,20 +84,56 @@ describe.only("MultiZNS", () => { destinationAddress : string; amount : bigint; metadata : string; - globalIndex : bigint; + depositCount : bigint; }; + // !!! The test network run test should always run on PREDEPLOYED contracts !!! + // and MONGO specific ENV vars should be set to the correct values so that the campaignL2 + // can pick them up properly and not redeploy anything ! before(async () => { + const env = process.env.ENV_LEVEL; + isRealNetwork = env === "test" && hre.network.name !== "hardhat"; + [ deployAdmin, user, subUser ] = await hre.ethers.getSigners(); - // set ENV vars for the Ethereum ZNS deployment process.env.SRC_CHAIN_NAME = SupportedChains.eth; - process.env.MOCK_ZKEVM_BRIDGE = "true"; - process.env.NETWORK_ID = NETWORK_ID_L1_DEFAULT.toString(); - process.env.DEST_NETWORK_ID = NETWORK_ID_L2_DEFAULT.toString(); - process.env.DEST_CHAIN_NAME = SupportedChains.z; - process.env.DEST_CHAIN_ID = zChainID.toString(); - + if (isRealNetwork) { + assert.ok( + !!process.env.MONGO_DB_VERSION, + "Have to provide correct MONGO_DB_VERSION for running on test networks to use existing deployed contracts!" + ); + assert.ok( + !!process.env.MONGO_DB_NAME, + "Have to provide correct MONGO_DB_NAME where SOURCE chain contracts are located!" + ); + assert.ok( + !!process.env.MONGO_DB_NAME_DEST, + "Have to provide correct MONGO_DB_NAME_DEST where DESTINATION chain contracts are located!" + ); + assert.ok( + !!process.env.MONGO_DB_VERSION_DEST, + "Have to provide correct MONGO_DB_VERSION_DEST where DESTINATION chain contracts are located!" + ); + assert.ok( + !!process.env.SEPOLIA_RPC_URL, + "Have to provide correct SEPOLIA_RPC_URL for running on test networks!" + ); + assert.ok( + !!process.env.ZCHAINTEST_RPC_URL, + "Have to provide correct ZCHAINTEST_RPC_URL for running on test networks!" + ); + } else { + // set ENV vars for the Ethereum ZNS deployment + process.env.MOCK_ZKEVM_BRIDGE = "true"; + process.env.NETWORK_ID = NETWORK_ID_L1_DEFAULT.toString(); + process.env.DEST_NETWORK_ID = NETWORK_ID_L2_DEFAULT.toString(); + process.env.DEST_CHAIN_NAME = SupportedChains.z; + process.env.DEST_CHAIN_ID = zChainID.toString(); + } + + // TODO multi: create a proper test for zkEVM bridge when not mocked !!! + + // L1 run config = await getConfig({ deployer: deployAdmin, zeroVaultAddress: deployAdmin.address, @@ -104,38 +145,83 @@ describe.only("MultiZNS", () => { resetMongoAdapter(); - // set vars for ZChain ZNS deployment process.env.SRC_CHAIN_NAME = SupportedChains.z; - process.env.SRC_ZNS_PORTAL = znsL1.zPortal.target as string; - process.env.NETWORK_ID = NETWORK_ID_L2_DEFAULT.toString(); - process.env.MONGO_DB_NAME = "zns-l2"; + if (!isRealNetwork) { + // set vars for ZChain ZNS deployment + process.env.SRC_ZNS_PORTAL = znsL1.zPortal.target as string; + process.env.NETWORK_ID = NETWORK_ID_L2_DEFAULT.toString(); + process.env.MONGO_DB_NAME = "zns-l2"; + // TODO multi: create zkEVM bridge tests for predeployed bridge !!! + deployAdminL2 = deployAdmin; + userL2 = user; + subUserL2 = subUser; + } else { + const zChainProvider = new ethers.JsonRpcProvider(process.env.ZCHAINTEST_RPC_URL); + deployAdminL2 = new ethers.Wallet(`0x${process.env.TESTNET_PRIVATE_KEY_A}`, zChainProvider); + userL2 = new ethers.Wallet(`0x${process.env.TESTNET_PRIVATE_KEY_B}`, zChainProvider); + subUserL2 = new ethers.Wallet(`0x${process.env.TESTNET_PRIVATE_KEY_C}`, zChainProvider); + // swap to another DB where L2 contracts are located + process.env.MONGO_DB_NAME = process.env.MONGO_DB_NAME_DEST; + process.env.MONGO_DB_VERSION = process.env.MONGO_DB_VERSION_DEST; + } + + // L2 run config = await getConfig({ - deployer: deployAdmin, - zeroVaultAddress: deployAdmin.address, + deployer: deployAdminL2, + zeroVaultAddress: deployAdminL2.address, }); // emulating L2 here by deploying to the same network const campaignL2 = await runZnsCampaign({ config }); znsL2 = campaignL2.state.contracts; + }); - // set L2 portal address on L1 - await znsL1.zPortal.connect(deployAdmin).setDestZnsPortal(znsL2.ethPortal.target); + after(async () => { + resetEnvVars(); + }); + + it("#registerAndBridgeDomain() should revert if `destZnsPortal` is not set", async () => { + const curPortal = await znsL1.zPortal.destZnsPortal(); - await znsL2.meowToken.mint(deployAdmin.address, 1000000000000000000000n); - await znsL2.meowToken.connect(deployAdmin).approve(znsL2.treasury.target, ethers.MaxUint256); + if (curPortal !== hre.ethers.ZeroAddress) { + await znsL1.zPortal.connect(deployAdmin).setDestZnsPortal(hre.ethers.ZeroAddress); + } - await znsL1.meowToken.mint(deployAdmin.address, 1000000000000000000000n); - await znsL1.meowToken.connect(deployAdmin).approve(znsL1.zPortal.target, ethers.MaxUint256); - await znsL1.meowToken.connect(deployAdmin).approve(znsL1.treasury.target, ethers.MaxUint256); + await approveForDomain({ + zns: znsL1, + parentHash: hre.ethers.ZeroHash, + user, + domainLabel: "test", + isBridging: true, + mintTokens: true, + }); - await znsL1.meowToken.mint(user.address, hre.ethers.parseEther("100000000000000")); - await znsL1.meowToken.connect(user).approve(znsL1.zPortal.target, ethers.MaxUint256); + await expect( + znsL1.zPortal.connect(user).registerAndBridgeDomain( + hre.ethers.ZeroHash, + "test", + DEFAULT_TOKEN_URI, + ) + ).to.be.revertedWithCustomError(znsL1.zPortal, DEST_PORTAL_NOT_SET_ERR); + + // TODO multi: add a proper way to set this programmatically on actual chains !!! + // set L2 portal address on L1 + await znsL1.zPortal.connect(deployAdmin).setDestZnsPortal(znsL2.ethPortal.target); }); - after(async () => { - resetEnvVars(); + it("should NOT allow to register root domain on ZChain", async () => { + await expect( + registrationWithSetup({ + zns: znsL2, + user: deployAdminL2, + parentHash: hre.ethers.ZeroHash, + domainLabel: "domainlabeltoberejected", + fullConfig: fullDistrConfigEmpty, + }) + // this function does not exist on the RootRegistrarBranch contract, so it fails with this error + ).to.be.rejectedWith("registerRootDomain is not a function"); }); [ @@ -188,9 +274,18 @@ describe.only("MultiZNS", () => { }); } + // register and bridge + await approveForDomain({ + zns: znsL1, + parentHash: parentHash as string, + user, + domainLabel: label, + isBridging: true, + mintTokens: true, + }); + balanceBeforeBridge = await znsL1.meowToken.balanceOf(user.address); - // register and bridge const tx = await znsL1.zPortal.connect(user).registerAndBridgeDomain( parentHash as string, label, @@ -211,9 +306,12 @@ describe.only("MultiZNS", () => { it("should register and set owners as ZkEvmPortal and fire DomainBridged and BridgeEvent events", async () => { // check if domain is registered on L1 // check events + const latestBlock = await hre.ethers.provider.getBlockNumber(); + const fromBlock = latestBlock - 10; const events = await getEvents({ contract: znsL1.zPortal, eventName: "DomainBridged", + fromBlock, }); const event = events[events.length - 1]; expect(event.args.domainHash).to.equal(domainHash); @@ -224,6 +322,7 @@ describe.only("MultiZNS", () => { const bridgeEvents = await getEvents({ contract: znsL1.zkEvmBridge, eventName: "BridgeEvent", + fromBlock, }); ({ args: bridgedEventData } = bridgeEvents[bridgeEvents.length - 1]); @@ -267,7 +366,7 @@ describe.only("MultiZNS", () => { expect(balanceBeforeBridge - balanceAfterBridge).to.equal(priceRef + protocolFeeRef); }); - it("should set configs as empty", async () => { + it("should set configs as empty during bridging", async () => { // should be LOCKED with no configs const distrConfig = await znsL1.subRegistrar.distrConfigs(domainHash); expect(distrConfig.accessType).to.equal(AccessType.LOCKED); @@ -337,15 +436,16 @@ describe.only("MultiZNS", () => { }); }); + // TODO multi: for real network run add code to get the proof from the API!!! describe("Claim Bridged Domain on L2", () => { it("should #claimMessage() on the bridge successfully and fire a ClaimEvent", async () => { // **NOTE** that we connect as `deployAdmin` here to show that it's not // required that this has to be called by the original owner, // it can be called by anyone - await znsL2.zkEvmBridge.connect(deployAdmin).claimMessage( + await znsL2.zkEvmBridge.connect(deployAdminL2).claimMessage( dummySmtProof, dummySmtProof, - bridgedEventData.globalIndex, + bridgedEventData.depositCount, dummySmtProof[0], dummySmtProof[1], bridgedEventData.originNetwork, @@ -408,7 +508,7 @@ describe.only("MultiZNS", () => { paymentType: PaymentType.DIRECT, pricerContract: znsL2.fixedPricer.target, }; - await znsL2.subRegistrar.connect(user).setDistributionConfigForDomain( + await znsL2.subRegistrar.connect(userL2).setDistributionConfigForDomain( domainHash, distrConfigToSet, ); @@ -417,13 +517,13 @@ describe.only("MultiZNS", () => { token: znsL2.meowToken.target, beneficiary: user.address, }; - await znsL2.treasury.connect(user).setPaymentConfig( + await znsL2.treasury.connect(userL2).setPaymentConfig( domainHash, paymentConfigToSet, ); const priceToSet = 100n; - await znsL2.fixedPricer.connect(user).setPrice(domainHash, priceToSet); + await znsL2.fixedPricer.connect(userL2).setPrice(domainHash, priceToSet); // check configs are set properly const distrConfigAfter = await znsL2.subRegistrar.distrConfigs(domainHash); @@ -440,16 +540,14 @@ describe.only("MultiZNS", () => { }); it("should allow creating subdomains under the rules of newly set configs", async () => { - await znsL2.meowToken.mint(subUser.address, 1000000000000000000000n); - await znsL2.meowToken.connect(subUser).approve(znsL2.treasury.target, ethers.MaxUint256); - // make sure subdomains can be registered now const subdomainHash = await registrationWithSetup({ zns: znsL2, - user: subUser, + user: subUserL2, parentHash: domainHash, domainLabel: subdomainChildLabel, fullConfig: fullDistrConfigEmpty, + mintTokens: true, }); const events = await getEvents({ @@ -461,145 +559,148 @@ describe.only("MultiZNS", () => { expect(event.args.domainHash).to.equal(subdomainHash); expect(event.args.label).to.equal(subdomainChildLabel); expect(event.args.tokenURI).to.equal(DEFAULT_TOKEN_URI); - expect(event.args.registrant).to.equal(subUser.address); - expect(event.args.domainAddress).to.equal(subUser.address); + expect(event.args.registrant).to.equal(subUserL2.address); + expect(event.args.domainAddress).to.equal(subUserL2.address); // check if subdomain is registered const record = await znsL2.registry.getDomainRecord(subdomainHash); - expect(record.owner).to.equal(subUser.address); + expect(record.owner).to.equal(subUserL2.address); expect(record.resolver).to.equal(znsL2.addressResolver.target); const tokenOwner = await znsL2.domainToken.ownerOf(BigInt(subdomainHash)); - expect(tokenOwner).to.equal(subUser.address); + expect(tokenOwner).to.equal(subUserL2.address); }); }); }); }); - describe("Unit Tests", () => { - describe("ZNSZChainPortal", () => { - it("#initialize() should revert when trying to reinitialize", async () => { - await expect( - znsL1.zPortal.initialize( - "1", - "Z", - "1", - hre.ethers.ZeroAddress, - { - accessController: znsL1.accessController.target, - registry: znsL1.registry.target, - chainResolver: znsL1.chainResolver.target, - treasury: znsL1.treasury.target, - rootRegistrar: znsL1.rootRegistrar.target, - subRegistrar: znsL1.subRegistrar.target, - }, - ) - ).to.be.revertedWithCustomError(znsL1.zPortal, INITIALIZED_ERR); - }); + // We will only run this on local Hardhat network + if (!isRealNetwork) { + describe("Unit Tests", () => { + describe("ZNSZChainPortal", () => { + it("#initialize() should revert when trying to reinitialize", async () => { + await expect( + znsL1.zPortal.initialize( + "1", + "Z", + "1", + hre.ethers.ZeroAddress, + { + accessController: znsL1.accessController.target, + registry: znsL1.registry.target, + chainResolver: znsL1.chainResolver.target, + treasury: znsL1.treasury.target, + rootRegistrar: znsL1.rootRegistrar.target, + subRegistrar: znsL1.subRegistrar.target, + }, + ) + ).to.be.revertedWithCustomError(znsL1.zPortal, INITIALIZED_ERR); + }); - it("#setDestZnsPortal() should revert when called by non-ADMIN", async () => { - await expect( - znsL1.zPortal.connect(user).setDestZnsPortal(znsL2.ethPortal.target) - ).to.be.revertedWithCustomError(znsL1.accessController, AC_UNAUTHORIZED_ERR); - }); + it("#setDestZnsPortal() should revert when called by non-ADMIN", async () => { + await expect( + znsL1.zPortal.connect(user).setDestZnsPortal(znsL2.ethPortal.target) + ).to.be.revertedWithCustomError(znsL1.accessController, AC_UNAUTHORIZED_ERR); + }); - it("#setDestZnsPortal() should revert when setting 0x0 address", async () => { - await expect( - znsL1.zPortal.connect(deployAdmin).setDestZnsPortal(hre.ethers.ZeroAddress) - ).to.be.revertedWithCustomError(znsL1.zPortal, ZERO_ADDRESS_ERR); - }); + it("#setDestZnsPortal() should revert when setting 0x0 address", async () => { + await expect( + znsL1.zPortal.connect(deployAdmin).setDestZnsPortal(hre.ethers.ZeroAddress) + ).to.be.revertedWithCustomError(znsL1.zPortal, ZERO_ADDRESS_ERR); + }); - it("#setDestZnsPortal() should set the destination portal address", async () => { - await znsL1.zPortal.connect(deployAdmin).setDestZnsPortal(user.address); + it("#setDestZnsPortal() should set the destination portal address", async () => { + await znsL1.zPortal.connect(deployAdmin).setDestZnsPortal(user.address); - const destPortal = await znsL1.zPortal.destZnsPortal(); - expect(destPortal).to.equal(user.address); + const destPortal = await znsL1.zPortal.destZnsPortal(); + expect(destPortal).to.equal(user.address); - // set back to L2 portal address - await znsL1.zPortal.connect(deployAdmin).setDestZnsPortal(znsL2.ethPortal.target); + // set back to L2 portal address + await znsL1.zPortal.connect(deployAdmin).setDestZnsPortal(znsL2.ethPortal.target); + }); }); - }); - describe("ZNSEthereumPortal", () => { - it("#initialize() should revert when trying to reinitialize", async () => { - const { - srcZnsPortal, - } = config.crosschain as IZNSZChainCrossConfig; - - await expect( - znsL2.ethPortal.connect(deployAdmin).initialize( - znsL2.accessController.target, - znsL2.zkEvmBridge.target, + describe("ZNSEthereumPortal", () => { + it("#initialize() should revert when trying to reinitialize", async () => { + const { srcZnsPortal, - znsL2.registry.target, - znsL2.domainToken.target, - znsL2.rootRegistrar.target, - znsL2.subRegistrar.target, - ) - ).to.be.revertedWithCustomError(znsL2.ethPortal, INITIALIZED_ERR); - }); + } = config.crosschain as IZNSZChainCrossConfig; + + await expect( + znsL2.ethPortal.connect(deployAdmin).initialize( + znsL2.accessController.target, + znsL2.zkEvmBridge.target, + srcZnsPortal, + znsL2.registry.target, + znsL2.domainToken.target, + znsL2.rootRegistrar.target, + znsL2.subRegistrar.target, + ) + ).to.be.revertedWithCustomError(znsL2.ethPortal, INITIALIZED_ERR); + }); - it("#onMessageReceived() should revert when called by non-ZkEvmBridge", async () => { - await expect( - znsL2.ethPortal.connect(deployAdmin).onMessageReceived( - znsL2.zkEvmBridge.target, - 1n, - hre.ethers.ZeroHash, - ) - ).to.be.revertedWithCustomError(znsL2.ethPortal, INVALID_CALLER_ERR); - }); + it("#onMessageReceived() should revert when called by non-ZkEvmBridge", async () => { + await expect( + znsL2.ethPortal.connect(deployAdmin).onMessageReceived( + znsL2.zkEvmBridge.target, + 1n, + hre.ethers.ZeroHash, + ) + ).to.be.revertedWithCustomError(znsL2.ethPortal, INVALID_CALLER_ERR); + }); - it("#onMessageReceived() should revert when `originAddress` is something OTHER than ZChainPortal", async () => { - // this will fail with MessageFailed error from the Bridge since it does a `.call()` internally - await expect( - // this will call onMessageReceived(), we have to do it like this to avoid - // reverting on the `InvalidCaller` check - znsL2.zkEvmBridge.claimMessage( - dummySmtProof, - dummySmtProof, - bridgedEventData.globalIndex, - dummySmtProof[0], - dummySmtProof[1], - bridgedEventData.originNetwork, - znsL2.registry.target, - bridgedEventData.destinationNetwork, - bridgedEventData.destinationAddress, - bridgedEventData.amount, - bridgedEventData.metadata, - ) - ).to.be.revertedWithCustomError(znsL2.zkEvmBridge, MESSAGE_FAILED_ERR); - }); + it("#onMessageReceived() should revert when `originAddress` is something OTHER than ZChainPortal", async () => { + // this will fail with MessageFailed error from the Bridge since it does a `.call()` internally + await expect( + // this will call onMessageReceived(), we have to do it like this to avoid + // reverting on the `InvalidCaller` check + znsL2.zkEvmBridge.claimMessage( + dummySmtProof, + dummySmtProof, + bridgedEventData.depositCount, + dummySmtProof[0], + dummySmtProof[1], + bridgedEventData.originNetwork, + znsL2.registry.target, + bridgedEventData.destinationNetwork, + bridgedEventData.destinationAddress, + bridgedEventData.amount, + bridgedEventData.metadata, + ) + ).to.be.revertedWithCustomError(znsL2.zkEvmBridge, MESSAGE_FAILED_ERR); + }); + + it("#onMessageReceived() should revert when proof's `domainHash` is incorrect", async () => { + // make wrong metadata + const abiCoder = ethers.AbiCoder.defaultAbiCoder(); + const wrongMetadata = abiCoder.encode( + ["tuple(bytes32,bytes32,string,address,string)"], + [[ + hashDomainLabel("wrong"), // this hashes a different label from the one below + hre.ethers.ZeroHash, + "right", + user.address, + DEFAULT_TOKEN_URI, + ]] + ); - it("#onMessageReceived() should revert when proof's `domainHash` is incorrect", async () => { - // make wrong metadata - const abiCoder = ethers.AbiCoder.defaultAbiCoder(); - const wrongMetadata = abiCoder.encode( - ["tuple(bytes32,bytes32,string,address,string)"], - [[ - hashDomainLabel("wrong"), // this hashes a different label from the one below - hre.ethers.ZeroHash, - "right", - user.address, - DEFAULT_TOKEN_URI, - ]] - ); - - await expect( - znsL2.zkEvmBridge.claimMessage( - dummySmtProof, - dummySmtProof, - bridgedEventData.globalIndex, - dummySmtProof[0], - dummySmtProof[1], - bridgedEventData.originNetwork, - bridgedEventData.originAddress, - bridgedEventData.destinationNetwork, - bridgedEventData.destinationAddress, - bridgedEventData.amount, - wrongMetadata, - ) - ).to.be.revertedWithCustomError(znsL2.zkEvmBridge, MESSAGE_FAILED_ERR); + await expect( + znsL2.zkEvmBridge.claimMessage( + dummySmtProof, + dummySmtProof, + bridgedEventData.depositCount, + dummySmtProof[0], + dummySmtProof[1], + bridgedEventData.originNetwork, + bridgedEventData.originAddress, + bridgedEventData.destinationNetwork, + bridgedEventData.destinationAddress, + bridgedEventData.amount, + wrongMetadata, + ) + ).to.be.revertedWithCustomError(znsL2.zkEvmBridge, MESSAGE_FAILED_ERR); + }); }); }); - }); + } }); From ec5580c152f70151c3d72ab6663c2a916c1e3efd Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 12 Nov 2024 16:06:20 -0800 Subject: [PATCH 085/124] extend test contract types and fix testnet script --- package.json | 2 +- src/deploy/campaign/environments.ts | 2 +- src/deploy/campaign/types.ts | 19 ++++++++++++------- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index c4e4574e7..98dbcdd6d 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "mongo:drop": "ts-node src/utils/drop-db.ts", "run-sepolia": "hardhat run src/deploy/run-campaign.ts --network sepolia", "run-hardhat": "hardhat run src/deploy/run-campaign.ts --network hardhat", - "run-meowtestnet": "hardhat run src/deploy/run-campaign.ts --network meowtestnet", + "run-zchaintest": "hardhat run src/deploy/run-campaign.ts --network zchaintest", "run-gmp": "hardhat run test/L2-BRIDGE-TEST/send.ts --network sepolia" }, "pre-commit": [ diff --git a/src/deploy/campaign/environments.ts b/src/deploy/campaign/environments.ts index df4e2736c..2b2dcd7a9 100644 --- a/src/deploy/campaign/environments.ts +++ b/src/deploy/campaign/environments.ts @@ -200,7 +200,7 @@ export const validateEnv = ( return priceConfig; }; -const getValidateRootPriceConfig = () => { +export const getValidateRootPriceConfig = () => { if (process.env.ENV_LEVEL === "prod") { requires( diff --git a/src/deploy/campaign/types.ts b/src/deploy/campaign/types.ts index bc9425acd..4c6fb5762 100644 --- a/src/deploy/campaign/types.ts +++ b/src/deploy/campaign/types.ts @@ -10,11 +10,14 @@ import { ZNSDomainToken, ZNSFixedPricer, ZNSRegistry, - ZNSRootRegistrar, - ZNSSubRegistrar, ZNSTreasury, MeowToken, - ZNSStringResolver, ZNSZChainPortal, ZNSEthereumPortal, PolygonZkEVMBridgeV2Mock, ZNSChainResolver, + ZNSStringResolver, + ZNSZChainPortal, + ZNSEthereumPortal, + PolygonZkEVMBridgeV2Mock, + ZNSChainResolver, + ZNSRootRegistrarTrunk, ZNSRootRegistrarBranch, ZNSSubRegistrarTrunk, ZNSSubRegistrarBranch, } from "../../../typechain"; import { TSupportedChain } from "../missions/contracts/cross-chain/portals/types"; @@ -74,9 +77,11 @@ export type ZNSContract = ZNSChainResolver | ZNSCurvePricer | ZNSTreasury | - ZNSRootRegistrar | + ZNSRootRegistrarTrunk | + ZNSRootRegistrarBranch | ZNSFixedPricer | - ZNSSubRegistrar | + ZNSSubRegistrarTrunk | + ZNSSubRegistrarBranch | ZNSZChainPortal | ZNSEthereumPortal | PolygonZkEVMBridgeV2Mock; @@ -91,9 +96,9 @@ export interface IZNSContracts extends IContractState { chainResolver : ZNSChainResolver; curvePricer : ZNSCurvePricer; treasury : ZNSTreasury; - rootRegistrar : ZNSRootRegistrar; + rootRegistrar : ZNSRootRegistrarTrunk | ZNSRootRegistrarBranch; fixedPricer : ZNSFixedPricer; - subRegistrar : ZNSSubRegistrar; + subRegistrar : ZNSSubRegistrarTrunk | ZNSSubRegistrarBranch; zPortal : ZNSZChainPortal; ethPortal : ZNSEthereumPortal; zkEvmBridge : PolygonZkEVMBridgeV2Mock; From 5e63d3467dbb2b9290e1f148504d26fe22b8fcfb Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 12 Nov 2024 16:07:29 -0800 Subject: [PATCH 086/124] add tx confirmation helper and wrap registration helpers to wait for txes if needed --- test/helpers/register-setup.ts | 29 ++++++++++++++++++++--------- test/helpers/tx.ts | 24 ++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 test/helpers/tx.ts diff --git a/test/helpers/register-setup.ts b/test/helpers/register-setup.ts index e4b9c1904..e70be069d 100644 --- a/test/helpers/register-setup.ts +++ b/test/helpers/register-setup.ts @@ -13,6 +13,7 @@ import { ICurvePriceConfig } from "../../src/deploy/missions/types"; import { expect } from "chai"; import { IZNSContracts } from "../../src/deploy/campaign/types"; import { MeowTokenMock, ZNSRootRegistrarTrunk } from "../../typechain"; +import { getConfirmationsAmount } from "./tx"; const { ZeroAddress } = ethers; @@ -42,10 +43,10 @@ export const defaultRootRegistration = async ({ paymentConfigEmpty ); + await tx.wait(getConfirmationsAmount()); + const supplyAfter = await zns.domainToken.totalSupply(); expect(supplyAfter).to.equal(supplyBefore + BigInt(1)); - - return tx.wait(); }; export const approveForDomain = async ({ @@ -78,11 +79,16 @@ export const approveForDomain = async ({ const protocolFee = await zns.curvePricer.getFeeForPrice(ethers.ZeroHash, price + parentFee); const toApprove = price + parentFee + protocolFee; - if (mintTokens) - await tokenContract.connect(user).mint(user.address, toApprove); + const confNum = getConfirmationsAmount(); + + if (mintTokens) { + const tx = await tokenContract.connect(user).mint(user.address, toApprove); + await tx.wait(confNum); + } const spender = isBridging ? await zns.zPortal.getAddress() : await zns.treasury.getAddress(); - return tokenContract.connect(user).approve(spender, toApprove); + const tx = await tokenContract.connect(user).approve(spender, toApprove); + await tx.wait(confNum); }; /** @@ -122,7 +128,7 @@ export const defaultSubdomainRegistration = async ({ const supplyAfter = await zns.domainToken.totalSupply(); expect(supplyAfter).to.equal(supplyBefore + BigInt(1)); - return tx.wait(); + return tx.wait(getConfirmationsAmount()); }; export const registrationWithSetup = async ({ @@ -191,31 +197,36 @@ export const registrationWithSetup = async ({ if (!hasConfig) return domainHash; + const confNum = getConfirmationsAmount(); + // set up prices if (fullConfig.distrConfig.pricerContract === await zns.fixedPricer.getAddress() && setConfigs) { - await zns.fixedPricer.connect(user).setPriceConfig( + const tx = await zns.fixedPricer.connect(user).setPriceConfig( domainHash, { ...fullConfig.priceConfig as IFixedPriceConfig, isSet: true, }, ); + await tx.wait(confNum); } else if (fullConfig.distrConfig.pricerContract === await zns.curvePricer.getAddress() && setConfigs) { - await zns.curvePricer.connect(user).setPriceConfig( + const tx = await zns.curvePricer.connect(user).setPriceConfig( domainHash, { ...fullConfig.priceConfig as ICurvePriceConfig, isSet: true, }, ); + await tx.wait(confNum); } if (fullConfig.paymentConfig.token !== ZeroAddress && setConfigs) { // set up payment config - await zns.treasury.connect(user).setPaymentConfig( + const tx = await zns.treasury.connect(user).setPaymentConfig( domainHash, fullConfig.paymentConfig, ); + await tx.wait(confNum); } return domainHash; diff --git a/test/helpers/tx.ts b/test/helpers/tx.ts new file mode 100644 index 000000000..6fcd27c74 --- /dev/null +++ b/test/helpers/tx.ts @@ -0,0 +1,24 @@ + + +export const getConfirmationsAmount = () : number => { + let curConfNum : string | number | undefined = process.env.CONFIRMATION_N; + + if (!curConfNum) { + const curEnv = process.env.ENV_LEVEL; + + switch (curEnv) { + case 'dev': + curConfNum = 0; + break; + case 'test': + curConfNum = 2; + break; + default: + throw new Error("Invalid environment. Failure to determine confifmations amount for transaction!"); + } + } else { + curConfNum = Number(curConfNum); + } + + return curConfNum; +}; From aab8e680a49c60ff386875b49ab9e832bd54e8e7 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 12 Nov 2024 16:07:50 -0800 Subject: [PATCH 087/124] add helpers to get data from zchain bridge api --- src/utils/cross-chain/bridge-api.ts | 63 +++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 src/utils/cross-chain/bridge-api.ts diff --git a/src/utils/cross-chain/bridge-api.ts b/src/utils/cross-chain/bridge-api.ts new file mode 100644 index 000000000..b5b88cbda --- /dev/null +++ b/src/utils/cross-chain/bridge-api.ts @@ -0,0 +1,63 @@ +import axios from "axios"; +import { GET_BRIDGE_DEPOSIT_DATA_EP, MERKLE_PROOF_EP, ZCHAIN_TEST_BRIDGE_API_URL } from "./constants"; + + +export const baseApiGET = async ({ + apiURL, + endpoint, + params, +} : { + apiURL : string; + endpoint : string; + params ?: any; +}) => { + const axio = axios.create({ + baseURL: apiURL, + }); + + return axio.get(endpoint, { params }); +}; + +export const getBridgeDepositData = async ({ + apiURL = ZCHAIN_TEST_BRIDGE_API_URL, + endpoint = GET_BRIDGE_DEPOSIT_DATA_EP, + destAddress, + params = { limit: 100, offset: 0 }, +} : { + apiURL ?: string; + endpoint ?: string; + destAddress : string; + params ?: any; +}) => { + const result = await baseApiGET({ + apiURL, + endpoint: `${endpoint}${destAddress}`, + params, + }); + + const { data: { deposits } } = result; + + return deposits; +}; + +export const getMerkeProof = async ({ + apiURL = ZCHAIN_TEST_BRIDGE_API_URL, + endpoint = MERKLE_PROOF_EP, + depositCnt, + netId, +} : { + apiURL ?: string; + endpoint ?: string; + depositCnt : number; + netId : number; +}) => { + const result = await baseApiGET({ + apiURL, + endpoint, + params: { deposit_cnt: depositCnt, net_id: netId }, + }); + + const { data: { proof } } = result; + + return proof; +}; From 0cb471ba0e5d983cb25b2e433bd84a89d93817fc Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 12 Nov 2024 16:22:08 -0800 Subject: [PATCH 088/124] add callable script to acquire data from bridge API with package.json script --- package.json | 2 +- src/utils/cross-chain/bridge-api.ts | 33 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 98dbcdd6d..d1159bedf 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "run-sepolia": "hardhat run src/deploy/run-campaign.ts --network sepolia", "run-hardhat": "hardhat run src/deploy/run-campaign.ts --network hardhat", "run-zchaintest": "hardhat run src/deploy/run-campaign.ts --network zchaintest", - "run-gmp": "hardhat run test/L2-BRIDGE-TEST/send.ts --network sepolia" + "bridge-get": "ts-node src/utils/cross-chain/bridge-api.ts" }, "pre-commit": [ "lint" diff --git a/src/utils/cross-chain/bridge-api.ts b/src/utils/cross-chain/bridge-api.ts index b5b88cbda..a39813946 100644 --- a/src/utils/cross-chain/bridge-api.ts +++ b/src/utils/cross-chain/bridge-api.ts @@ -61,3 +61,36 @@ export const getMerkeProof = async ({ return proof; }; + +const args = process.argv.slice(2); + +switch (args[0]) { +case "deposit": + const destAddress = args[1]; + + getBridgeDepositData({ destAddress }) + .then(deposits => { + console.log("Deposits acquired:", JSON.stringify(deposits, null, "\t")); + }) + .catch(error => { + console.error("Error acquiring deposits!", error); + }); + break; + +case "proof": + const depositCnt = Number(args[1]); + const netId = Number(args[2]); + + getMerkeProof({ depositCnt, netId }) + .then(proof => { + console.log("Proof acquired:", JSON.stringify(proof, null, "\t")); + }) + .catch(error => { + console.error("Error acquiring proof!", error); + }); + break; + +default: + console.error("Invalid arguments!"); + break; +} From cbb97d2f9df4c7c097bb3a711dca447de87c0052 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 13 Nov 2024 13:04:08 -0800 Subject: [PATCH 089/124] constants for the api helpers --- src/utils/cross-chain/constants.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/utils/cross-chain/constants.ts diff --git a/src/utils/cross-chain/constants.ts b/src/utils/cross-chain/constants.ts new file mode 100644 index 000000000..cd71524cf --- /dev/null +++ b/src/utils/cross-chain/constants.ts @@ -0,0 +1,10 @@ + +// ZChain URLs +export const ZCHAIN_TEST_BRIDGE_API_URL = "https://wilderworld-dev-erigon1-bridge-api.eu-north-2.gateway.fm"; +export const ZCHAIN_TEST_RPC_URL = "https://wilderworld-dev-erigon1-rpc.eu-north-2.gateway.fm/"; + +export const ZCHAIN_TEST_BRIDGE_ADDRESS = "0xbE57e0450ae99b62997f2F4731bF8D950e06D124"; + +// Bridge API endpoints +export const GET_BRIDGE_DEPOSIT_DATA_EP = "/bridges/"; +export const MERKLE_PROOF_EP = "/merkle-proof"; From 47723af5da12476c6ad8a137ddb2b27b4d44ccd2 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 13 Nov 2024 16:04:29 -0800 Subject: [PATCH 090/124] rename test folder --- .../MultiZNS.test.ts | 66 +++++++++++++------ .../PolygonZkEVMBridgeV2.json | 0 .../addresses.json | 0 test/{L2-BRIDGE-TEST => cross-chain}/claim.ts | 30 ++++++++- .../{L2-BRIDGE-TEST => cross-chain}/deploy.ts | 0 test/{L2-BRIDGE-TEST => cross-chain}/send.ts | 0 6 files changed, 75 insertions(+), 21 deletions(-) rename test/{L2-BRIDGE-TEST => cross-chain}/MultiZNS.test.ts (92%) rename test/{L2-BRIDGE-TEST => cross-chain}/PolygonZkEVMBridgeV2.json (100%) rename test/{L2-BRIDGE-TEST => cross-chain}/addresses.json (100%) rename test/{L2-BRIDGE-TEST => cross-chain}/claim.ts (74%) rename test/{L2-BRIDGE-TEST => cross-chain}/deploy.ts (100%) rename test/{L2-BRIDGE-TEST => cross-chain}/send.ts (100%) diff --git a/test/L2-BRIDGE-TEST/MultiZNS.test.ts b/test/cross-chain/MultiZNS.test.ts similarity index 92% rename from test/L2-BRIDGE-TEST/MultiZNS.test.ts rename to test/cross-chain/MultiZNS.test.ts index 04b35e666..64a2ca455 100644 --- a/test/L2-BRIDGE-TEST/MultiZNS.test.ts +++ b/test/cross-chain/MultiZNS.test.ts @@ -1,5 +1,5 @@ import * as hre from "hardhat"; -import { getConfig } from "../../src/deploy/campaign/environments"; +import { getConfig, getValidateRootPriceConfig } from "../../src/deploy/campaign/environments"; import { runZnsCampaign } from "../../src/deploy/zns-campaign"; import { IZNSCampaignConfig, @@ -32,14 +32,15 @@ import * as ethers from "ethers"; import { getDomainHashFromEvent, getEvents } from "../helpers/events"; import { ContractTransactionReceipt, Wallet } from "ethers"; import { SupportedChains } from "../../src/deploy/missions/contracts/cross-chain/portals/get-portal-dm"; -import { resetMongoAdapter } from "@zero-tech/zdc"; +import { MongoDBAdapter, resetMongoAdapter } from "@zero-tech/zdc"; import assert from "assert"; +import { getConfirmationsNumber } from "../helpers/tx"; export const NETWORK_ID_L1_DEFAULT = 0n; -export const NETWORK_ID_L2_DEFAULT = 19n; +export const NETWORK_ID_L2_DEFAULT = 1n; -const zChainID = 1668201165n; +const zChainID = 2012605151n; const resetEnvVars = () => { @@ -58,6 +59,8 @@ describe.only("MultiZNS", () => { let znsL1 : IZNSContracts; let znsL2 : IZNSContracts; + let dbAdapter1 : MongoDBAdapter; + let dbAdapter2 : MongoDBAdapter; let deployAdmin : SignerWithAddress; let deployAdminL2 : Wallet | SignerWithAddress; @@ -68,9 +71,9 @@ describe.only("MultiZNS", () => { let config : IZNSCampaignConfig; - const rootDomainLabel = "jefffbridges"; + const rootDomainLabel = "jeffbridges"; const subdomainLabel = "beaubridges"; - const subParentLabel = "bridges"; + const subParentLabel = "bridgessss"; const dummySmtProof = Array.from({ length: 32 }, () => hre.ethers.randomBytes(32)); @@ -139,9 +142,15 @@ describe.only("MultiZNS", () => { zeroVaultAddress: deployAdmin.address, }); + // TODO multi: add logger message to show which network is campaign running on !!! const campaignL1 = await runZnsCampaign({ config }); - znsL1 = campaignL1.state.contracts; + ({ + state: { + contracts: znsL1, + }, + dbAdapter: dbAdapter1, + } = campaignL1); resetMongoAdapter(); @@ -175,11 +184,17 @@ describe.only("MultiZNS", () => { // emulating L2 here by deploying to the same network const campaignL2 = await runZnsCampaign({ config }); - znsL2 = campaignL2.state.contracts; - }); + ({ + state: { + contracts: znsL2, + }, + dbAdapter: dbAdapter2, + } = campaignL2); }); after(async () => { resetEnvVars(); + await dbAdapter1.dropDB(); + await dbAdapter2.dropDB(); }); it("#registerAndBridgeDomain() should revert if `destZnsPortal` is not set", async () => { @@ -195,7 +210,6 @@ describe.only("MultiZNS", () => { user, domainLabel: "test", isBridging: true, - mintTokens: true, }); await expect( @@ -281,7 +295,6 @@ describe.only("MultiZNS", () => { user, domainLabel: label, isBridging: true, - mintTokens: true, }); balanceBeforeBridge = await znsL1.meowToken.balanceOf(user.address); @@ -291,7 +304,7 @@ describe.only("MultiZNS", () => { label, DEFAULT_TOKEN_URI ); - const receipt = await tx.wait() as ContractTransactionReceipt; + const receipt = await tx.wait(getConfirmationsNumber()) as ContractTransactionReceipt; console.log(`Gas used for ${name} bridging: ${receipt.gasUsed.toString()}`); domainHash = await getDomainHashFromEvent({ @@ -306,12 +319,9 @@ describe.only("MultiZNS", () => { it("should register and set owners as ZkEvmPortal and fire DomainBridged and BridgeEvent events", async () => { // check if domain is registered on L1 // check events - const latestBlock = await hre.ethers.provider.getBlockNumber(); - const fromBlock = latestBlock - 10; const events = await getEvents({ contract: znsL1.zPortal, eventName: "DomainBridged", - fromBlock, }); const event = events[events.length - 1]; expect(event.args.domainHash).to.equal(domainHash); @@ -322,10 +332,12 @@ describe.only("MultiZNS", () => { const bridgeEvents = await getEvents({ contract: znsL1.zkEvmBridge, eventName: "BridgeEvent", - fromBlock, }); ({ args: bridgedEventData } = bridgeEvents[bridgeEvents.length - 1]); + // this is here so we can use this data to do an API call to get the proof + if (isRealNetwork) console.log("Bridged Event Data:", bridgedEventData); + const abiCoder = ethers.AbiCoder.defaultAbiCoder(); const metadataRef = abiCoder.encode( ["tuple(bytes32,bytes32,string,address,string)"], @@ -360,9 +372,17 @@ describe.only("MultiZNS", () => { it("should withdraw the correct amount of tokens from the caller", async () => { const balanceAfterBridge = await znsL1.meowToken.balanceOf(user.address); - const priceRef = getCurvePrice(label); + const priceConfig = isRealNetwork ? getValidateRootPriceConfig() : DEFAULT_PRICE_CONFIG; + const priceRef = getCurvePrice(label, priceConfig); const protocolFeeRef = getStakingOrProtocolFee(priceRef); + // TODO multi: error here! + // AssertionError: expected 4524647947000000000000 to equal 9292717980000000000000. + // + expected - actual + // + // -4524647947000000000000 + // +9292717980000000000000 + expect(balanceBeforeBridge - balanceAfterBridge).to.equal(priceRef + protocolFeeRef); }); @@ -456,6 +476,7 @@ describe.only("MultiZNS", () => { bridgedEventData.metadata, ); + // TODO multi: fix all the event reads for test networks, now they don't get the data const events = await getEvents({ contract: znsL2.zkEvmBridge, eventName: "ClaimEvent", @@ -502,28 +523,33 @@ describe.only("MultiZNS", () => { expect(paymentConfig.token).to.equal(hre.ethers.ZeroAddress); expect(paymentConfig.beneficiary).to.equal(hre.ethers.ZeroAddress); + const confNum = getConfirmationsNumber(); + // set configs const distrConfigToSet = { accessType: AccessType.OPEN, paymentType: PaymentType.DIRECT, pricerContract: znsL2.fixedPricer.target, }; - await znsL2.subRegistrar.connect(userL2).setDistributionConfigForDomain( + let tx = await znsL2.subRegistrar.connect(userL2).setDistributionConfigForDomain( domainHash, distrConfigToSet, ); + await tx.wait(confNum); const paymentConfigToSet = { token: znsL2.meowToken.target, beneficiary: user.address, }; - await znsL2.treasury.connect(userL2).setPaymentConfig( + tx = await znsL2.treasury.connect(userL2).setPaymentConfig( domainHash, paymentConfigToSet, ); + await tx.wait(confNum); const priceToSet = 100n; - await znsL2.fixedPricer.connect(userL2).setPrice(domainHash, priceToSet); + tx = await znsL2.fixedPricer.connect(userL2).setPrice(domainHash, priceToSet); + await tx.wait(confNum); // check configs are set properly const distrConfigAfter = await znsL2.subRegistrar.distrConfigs(domainHash); diff --git a/test/L2-BRIDGE-TEST/PolygonZkEVMBridgeV2.json b/test/cross-chain/PolygonZkEVMBridgeV2.json similarity index 100% rename from test/L2-BRIDGE-TEST/PolygonZkEVMBridgeV2.json rename to test/cross-chain/PolygonZkEVMBridgeV2.json diff --git a/test/L2-BRIDGE-TEST/addresses.json b/test/cross-chain/addresses.json similarity index 100% rename from test/L2-BRIDGE-TEST/addresses.json rename to test/cross-chain/addresses.json diff --git a/test/L2-BRIDGE-TEST/claim.ts b/test/cross-chain/claim.ts similarity index 74% rename from test/L2-BRIDGE-TEST/claim.ts rename to test/cross-chain/claim.ts index 47f9b47f0..1254e1a32 100644 --- a/test/L2-BRIDGE-TEST/claim.ts +++ b/test/cross-chain/claim.ts @@ -3,8 +3,12 @@ import * as hre from "hardhat"; import axios from "axios"; import { ErrorDecoder } from "ethers-decode-error"; import { receiverAddress } from "./addresses.json"; +import * as ethers from "ethers"; +import { ZNSSubRegistrar, ZNSSubRegistrar__factory } from "../../typechain"; +import { DEFAULT_TOKEN_URI, distrConfigEmpty, paymentConfigEmpty } from "../helpers"; +// TODO multi: make this into something usable or delete const mekrleProofString = "/merkle-proof"; const getClaimsFromAcc = "/bridges/"; const zChainBridgeApiUrl = "https://zchain-testnet-bridge-api.eu-north-2.gateway.fm/"; @@ -12,6 +16,7 @@ const zChainRpcUrl = "https://zchain-testnet-rpc.eu-north-2.gateway.fm/"; const zChainTestBridgeAddress = "0x528e26b25a34a4A5d0dbDa1d57D318153d2ED582"; + const main = async () => { // launch HH script with "--network zchaintest" flag to get this! const [deployerZChain] = await hre.ethers.getSigners(); @@ -77,7 +82,30 @@ const main = async () => { console.log("Claim process completed successfully!"); }; -// main().catch(error => { + +const register = async () => { + const [caller] = await hre.ethers.getSigners(); + const fact = new ZNSSubRegistrar__factory(caller); + const znsSubRegistrar = fact.attach("0x0629076F9851dd5AE881d2d68790E4b7176aB5fd") as ZNSSubRegistrar; + + const parentHash = "0x4d7459e21a4603da1084e91d4d1ec4f0255be54312073d256d7f1881c81c167d"; + const label = "subone"; + + const tx = await znsSubRegistrar.registerSubdomain( + parentHash, + label, + caller.address, + DEFAULT_TOKEN_URI, + distrConfigEmpty, + paymentConfigEmpty, + ); + const receipt = await tx.wait(); + + + console.log("Subdomain registered successfully!", JSON.stringify(receipt, null, "\t")); +}; + +// register().catch(error => { // console.error(error); // process.exit(1); // }); diff --git a/test/L2-BRIDGE-TEST/deploy.ts b/test/cross-chain/deploy.ts similarity index 100% rename from test/L2-BRIDGE-TEST/deploy.ts rename to test/cross-chain/deploy.ts diff --git a/test/L2-BRIDGE-TEST/send.ts b/test/cross-chain/send.ts similarity index 100% rename from test/L2-BRIDGE-TEST/send.ts rename to test/cross-chain/send.ts From 5b3320869d306ddc506284236a373b22e4207bd3 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 13 Nov 2024 16:04:56 -0800 Subject: [PATCH 091/124] exteneded api scripts to write to local files --- .gitignore | 3 ++ src/utils/cross-chain/bridge-api.ts | 77 ++++++++++++++++++----------- 2 files changed, 50 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index a9de5f05c..fb0f58bed 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,6 @@ docker*.tgz # We don't ever use the generated manifests .openzeppelin + +# Local tests and ops +test-data diff --git a/src/utils/cross-chain/bridge-api.ts b/src/utils/cross-chain/bridge-api.ts index a39813946..48be4d091 100644 --- a/src/utils/cross-chain/bridge-api.ts +++ b/src/utils/cross-chain/bridge-api.ts @@ -1,5 +1,8 @@ +/* eslint-disable @typescript-eslint/no-var-requires, camelcase, no-shadow, @typescript-eslint/no-explicit-any */ import axios from "axios"; import { GET_BRIDGE_DEPOSIT_DATA_EP, MERKLE_PROOF_EP, ZCHAIN_TEST_BRIDGE_API_URL } from "./constants"; +import path from "path"; +import fs from "fs"; export const baseApiGET = async ({ @@ -62,35 +65,49 @@ export const getMerkeProof = async ({ return proof; }; +const main = async (args : Array) => { + let apiDataReturn : string; + + switch (args[0]) { + case "deposit": + const destAddress = args[1]; + + const deposits = await getBridgeDepositData({ destAddress }); + console.log("Deposits acquired:", JSON.stringify(deposits, null, "\t")); + apiDataReturn = JSON.stringify(deposits[deposits.length - 1], null, "\t"); + break; + + case "proof": + const depositCnt = Number(args[1]); + const netId = Number(args[2]); + + let proof = await getMerkeProof({ depositCnt, netId }); + proof = JSON.stringify(proof, null, "\t"); + console.log("Proof acquired:", proof); + apiDataReturn = proof; + break; + + default: + throw new Error("Invalid arguments!"); + } + + if (args[args.length - 1] === "save" && apiDataReturn) { + const pathToDir = path.join(process.cwd(), "./test-data"); + const pathToFile = path.join(pathToDir, `bridge-${args[0]}.json`); + + if (!fs.existsSync(pathToDir)) { + fs.mkdirSync(pathToDir); + } + + fs.writeFileSync(pathToFile, apiDataReturn); + } +}; + const args = process.argv.slice(2); -switch (args[0]) { -case "deposit": - const destAddress = args[1]; - - getBridgeDepositData({ destAddress }) - .then(deposits => { - console.log("Deposits acquired:", JSON.stringify(deposits, null, "\t")); - }) - .catch(error => { - console.error("Error acquiring deposits!", error); - }); - break; - -case "proof": - const depositCnt = Number(args[1]); - const netId = Number(args[2]); - - getMerkeProof({ depositCnt, netId }) - .then(proof => { - console.log("Proof acquired:", JSON.stringify(proof, null, "\t")); - }) - .catch(error => { - console.error("Error acquiring proof!", error); - }); - break; - -default: - console.error("Invalid arguments!"); - break; -} +main(args) + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + }); From 7d67076f10504cf2160b83a836e74ae45e38e279 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 13 Nov 2024 17:31:49 -0800 Subject: [PATCH 092/124] extend helpers for bridge api to be able to save to a file and read from that file in the test or whenever needed --- src/utils/cross-chain/bridge-api.ts | 26 ++++++++------ src/utils/cross-chain/constants.ts | 13 ++++++- test/helpers/cc-claim.ts | 54 +++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 11 deletions(-) create mode 100644 test/helpers/cc-claim.ts diff --git a/src/utils/cross-chain/bridge-api.ts b/src/utils/cross-chain/bridge-api.ts index 48be4d091..8d4fdd836 100644 --- a/src/utils/cross-chain/bridge-api.ts +++ b/src/utils/cross-chain/bridge-api.ts @@ -1,6 +1,12 @@ /* eslint-disable @typescript-eslint/no-var-requires, camelcase, no-shadow, @typescript-eslint/no-explicit-any */ import axios from "axios"; -import { GET_BRIDGE_DEPOSIT_DATA_EP, MERKLE_PROOF_EP, ZCHAIN_TEST_BRIDGE_API_URL } from "./constants"; +import { + BridgeApiOps, + GET_BRIDGE_DEPOSIT_DATA_EP, getTempDataFilePath, + MERKLE_PROOF_EP, TBridgeApiOp, + TEMP_DATA_DIR_PATH, + ZCHAIN_TEST_BRIDGE_API_URL, +} from "./constants"; import path from "path"; import fs from "fs"; @@ -31,7 +37,7 @@ export const getBridgeDepositData = async ({ endpoint ?: string; destAddress : string; params ?: any; -}) => { +}) : Promise> => { const result = await baseApiGET({ apiURL, endpoint: `${endpoint}${destAddress}`, @@ -67,9 +73,10 @@ export const getMerkeProof = async ({ const main = async (args : Array) => { let apiDataReturn : string; + const op = args[0] as TBridgeApiOp; - switch (args[0]) { - case "deposit": + switch (op) { + case BridgeApiOps.deposit: const destAddress = args[1]; const deposits = await getBridgeDepositData({ destAddress }); @@ -77,7 +84,7 @@ const main = async (args : Array) => { apiDataReturn = JSON.stringify(deposits[deposits.length - 1], null, "\t"); break; - case "proof": + case BridgeApiOps.proof: const depositCnt = Number(args[1]); const netId = Number(args[2]); @@ -88,15 +95,14 @@ const main = async (args : Array) => { break; default: - throw new Error("Invalid arguments!"); + throw new Error("Invalid operation argument!"); } if (args[args.length - 1] === "save" && apiDataReturn) { - const pathToDir = path.join(process.cwd(), "./test-data"); - const pathToFile = path.join(pathToDir, `bridge-${args[0]}.json`); + const pathToFile = path.join(TEMP_DATA_DIR_PATH, getTempDataFilePath(op)); - if (!fs.existsSync(pathToDir)) { - fs.mkdirSync(pathToDir); + if (!fs.existsSync(TEMP_DATA_DIR_PATH)) { + fs.mkdirSync(TEMP_DATA_DIR_PATH); } fs.writeFileSync(pathToFile, apiDataReturn); diff --git a/src/utils/cross-chain/constants.ts b/src/utils/cross-chain/constants.ts index cd71524cf..d029a1794 100644 --- a/src/utils/cross-chain/constants.ts +++ b/src/utils/cross-chain/constants.ts @@ -1,5 +1,6 @@ +import path from "path"; -// ZChain URLs +// ZChain Testnet URLs export const ZCHAIN_TEST_BRIDGE_API_URL = "https://wilderworld-dev-erigon1-bridge-api.eu-north-2.gateway.fm"; export const ZCHAIN_TEST_RPC_URL = "https://wilderworld-dev-erigon1-rpc.eu-north-2.gateway.fm/"; @@ -8,3 +9,13 @@ export const ZCHAIN_TEST_BRIDGE_ADDRESS = "0xbE57e0450ae99b62997f2F4731bF8D950e0 // Bridge API endpoints export const GET_BRIDGE_DEPOSIT_DATA_EP = "/bridges/"; export const MERKLE_PROOF_EP = "/merkle-proof"; + +export type TBridgeApiOp = "deposit" | "proof"; +export const BridgeApiOps : { [key in TBridgeApiOp] : TBridgeApiOp; } = { + deposit: "deposit", + proof: "proof", +}; + +export const TEMP_DATA_DIR_PATH = path.join(process.cwd(), "./test-data"); +export const getTempDataFilePath = (opName : TBridgeApiOp) => + path.join(TEMP_DATA_DIR_PATH, `bridge-${opName}.json`); diff --git a/test/helpers/cc-claim.ts b/test/helpers/cc-claim.ts new file mode 100644 index 000000000..818cf4886 --- /dev/null +++ b/test/helpers/cc-claim.ts @@ -0,0 +1,54 @@ +/* eslint-disable camelcase */ +import fs from "fs"; +import { BridgeApiOps, getTempDataFilePath } from "../../src/utils/cross-chain/constants"; +import { getBridgeDepositData, getMerkeProof } from "../../src/utils/cross-chain/bridge-api"; + + +// These helpers only return data for a single deposit only +// they use whatever has been saved last to local files after running `bridge-get` script +export const getSavedBridgeApiData = async (destAddress ?: string) => { + let deposit; + let proof; + + if (!destAddress) { + const rawDeposit = fs.readFileSync( + getTempDataFilePath(BridgeApiOps.deposit) + ); + deposit = JSON.parse(rawDeposit.toString()); + + const rawProof = fs.readFileSync( + getTempDataFilePath(BridgeApiOps.proof) + ); + proof = JSON.parse(rawProof.toString()); + } else { + const deposits = await getBridgeDepositData({ destAddress }); + deposit = deposits[deposits.length - 1]; + + + const { deposit_cnt, orig_net } = deposit; + proof = await getMerkeProof({ depositCnt: deposit_cnt, netId: orig_net }); + } + + return { + deposit, + proof, + }; +}; + +export const getClaimArgsFromApi = async (destAddress ?: string) => { + const { deposit, proof } = await getSavedBridgeApiData(destAddress); + + return [ + proof.merkle_proof, + proof.rollup_merkle_proof, + deposit.global_index, + proof.main_exit_root, + proof.rollup_exit_root, + deposit.orig_net, + deposit.orig_addr, + deposit.dest_net, + deposit.dest_addr, + deposit.amount, + deposit.metadata, + ]; +}; From 5ec3beff5f9c3f037b361ae4244317190a6df532 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 13 Nov 2024 17:32:26 -0800 Subject: [PATCH 093/124] fix event helpers and usages of all helpers in the test --- test/cross-chain/MultiZNS.test.ts | 34 +++++++++++++++++++------------ test/helpers/events.ts | 11 ++++++++++ test/helpers/tx.ts | 18 ++++++++-------- 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/test/cross-chain/MultiZNS.test.ts b/test/cross-chain/MultiZNS.test.ts index 64a2ca455..703604ff1 100644 --- a/test/cross-chain/MultiZNS.test.ts +++ b/test/cross-chain/MultiZNS.test.ts @@ -35,6 +35,7 @@ import { SupportedChains } from "../../src/deploy/missions/contracts/cross-chain import { MongoDBAdapter, resetMongoAdapter } from "@zero-tech/zdc"; import assert from "assert"; import { getConfirmationsNumber } from "../helpers/tx"; +import { getClaimArgsFromApi } from "../helpers/cc-claim"; export const NETWORK_ID_L1_DEFAULT = 0n; @@ -459,22 +460,29 @@ describe.only("MultiZNS", () => { // TODO multi: for real network run add code to get the proof from the API!!! describe("Claim Bridged Domain on L2", () => { it("should #claimMessage() on the bridge successfully and fire a ClaimEvent", async () => { + const claimArgs = !isRealNetwork + ? [ + dummySmtProof, + dummySmtProof, + bridgedEventData.depositCount, + dummySmtProof[0], + dummySmtProof[1], + bridgedEventData.originNetwork, + bridgedEventData.originAddress, + bridgedEventData.destinationNetwork, + bridgedEventData.destinationAddress, + bridgedEventData.amount, + bridgedEventData.metadata, + ] + : await getClaimArgsFromApi(); + // **NOTE** that we connect as `deployAdmin` here to show that it's not // required that this has to be called by the original owner, // it can be called by anyone - await znsL2.zkEvmBridge.connect(deployAdminL2).claimMessage( - dummySmtProof, - dummySmtProof, - bridgedEventData.depositCount, - dummySmtProof[0], - dummySmtProof[1], - bridgedEventData.originNetwork, - bridgedEventData.originAddress, - bridgedEventData.destinationNetwork, - bridgedEventData.destinationAddress, - bridgedEventData.amount, - bridgedEventData.metadata, - ); + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + await znsL2.zkEvmBridge.connect(deployAdminL2).claimMessage(...claimArgs); // TODO multi: fix all the event reads for test networks, now they don't get the data const events = await getEvents({ diff --git a/test/helpers/events.ts b/test/helpers/events.ts index 2b1cf087e..93ba7b412 100644 --- a/test/helpers/events.ts +++ b/test/helpers/events.ts @@ -3,6 +3,7 @@ import { time } from "@nomicfoundation/hardhat-toolbox/network-helpers"; import { TypedContractEvent, TypedEventLog } from "../../typechain/common"; import { IZNSContractsLocal } from "./types"; import { IZNSContracts, ZNSContract } from "../../src/deploy/campaign/types"; +import * as hre from "hardhat"; export const getDomainRegisteredEvents = async ({ @@ -41,6 +42,11 @@ export const getDomainHashFromEvent = async ({ registrantAddress : string; fromBlock ?: number; }) : Promise => { + if (!fromBlock && hre.network.name === "hardhat") { + const latest = await zns.rootRegistrar.runner?.provider?.getBlockNumber(); + fromBlock = latest! - 50; + } + const filter = zns.rootRegistrar.filters.DomainRegistered( undefined, undefined, @@ -68,6 +74,11 @@ export const getEvents = async ({ args ?: any; fromBlock ?: number; }) : Promise>> => { + if (!fromBlock && hre.network.name === "hardhat") { + const latest = await contract.runner.provider.getBlockNumber(); + fromBlock = latest - 50; + } + const filter = contract.filters[eventName](args); return contract.queryFilter(filter, fromBlock); diff --git a/test/helpers/tx.ts b/test/helpers/tx.ts index 6fcd27c74..e09e67350 100644 --- a/test/helpers/tx.ts +++ b/test/helpers/tx.ts @@ -1,20 +1,20 @@ -export const getConfirmationsAmount = () : number => { +export const getConfirmationsNumber = () : number => { let curConfNum : string | number | undefined = process.env.CONFIRMATION_N; if (!curConfNum) { const curEnv = process.env.ENV_LEVEL; switch (curEnv) { - case 'dev': - curConfNum = 0; - break; - case 'test': - curConfNum = 2; - break; - default: - throw new Error("Invalid environment. Failure to determine confifmations amount for transaction!"); + case "dev": + curConfNum = 0; + break; + case "test": + curConfNum = 2; + break; + default: + throw new Error("Invalid environment. Failure to determine confifmations amount for transaction!"); } } else { curConfNum = Number(curConfNum); From 074a844a12e0e848e8a49c31458549e61d2fedd6 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 18 Nov 2024 13:18:33 -0800 Subject: [PATCH 094/124] extend api helpers and claim --- src/utils/cross-chain/bridge-api.ts | 15 +++------------ src/utils/cross-chain/run-bridge-api.ts | 10 ++++++++++ test/helpers/cc-claim.ts | 22 ++++++++++++++++++---- 3 files changed, 31 insertions(+), 16 deletions(-) create mode 100644 src/utils/cross-chain/run-bridge-api.ts diff --git a/src/utils/cross-chain/bridge-api.ts b/src/utils/cross-chain/bridge-api.ts index 8d4fdd836..62b92ef1a 100644 --- a/src/utils/cross-chain/bridge-api.ts +++ b/src/utils/cross-chain/bridge-api.ts @@ -71,7 +71,7 @@ export const getMerkeProof = async ({ return proof; }; -const main = async (args : Array) => { +export const getSaveBridgeApiResponse = async (args : Array) => { let apiDataReturn : string; const op = args[0] as TBridgeApiOp; @@ -81,7 +81,7 @@ const main = async (args : Array) => { const deposits = await getBridgeDepositData({ destAddress }); console.log("Deposits acquired:", JSON.stringify(deposits, null, "\t")); - apiDataReturn = JSON.stringify(deposits[deposits.length - 1], null, "\t"); + apiDataReturn = JSON.stringify(deposits, null, "\t"); break; case BridgeApiOps.proof: @@ -99,7 +99,7 @@ const main = async (args : Array) => { } if (args[args.length - 1] === "save" && apiDataReturn) { - const pathToFile = path.join(TEMP_DATA_DIR_PATH, getTempDataFilePath(op)); + const pathToFile = getTempDataFilePath(op); if (!fs.existsSync(TEMP_DATA_DIR_PATH)) { fs.mkdirSync(TEMP_DATA_DIR_PATH); @@ -108,12 +108,3 @@ const main = async (args : Array) => { fs.writeFileSync(pathToFile, apiDataReturn); } }; - -const args = process.argv.slice(2); - -main(args) - .then(() => process.exit(0)) - .catch(error => { - console.error(error); - process.exit(1); - }); diff --git a/src/utils/cross-chain/run-bridge-api.ts b/src/utils/cross-chain/run-bridge-api.ts new file mode 100644 index 000000000..76e9f8e88 --- /dev/null +++ b/src/utils/cross-chain/run-bridge-api.ts @@ -0,0 +1,10 @@ +import { getSaveBridgeApiResponse } from "./bridge-api"; + +const args = process.argv.slice(2); + +getSaveBridgeApiResponse(args) + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + }); diff --git a/test/helpers/cc-claim.ts b/test/helpers/cc-claim.ts index 818cf4886..966cfc92f 100644 --- a/test/helpers/cc-claim.ts +++ b/test/helpers/cc-claim.ts @@ -6,7 +6,13 @@ import { getBridgeDepositData, getMerkeProof } from "../../src/utils/cross-chain // These helpers only return data for a single deposit only // they use whatever has been saved last to local files after running `bridge-get` script -export const getSavedBridgeApiData = async (destAddress ?: string) => { +export const getSavedBridgeApiData = async ({ + destAddress, + depositCnt, +} : { + destAddress ?: string; + depositCnt ?: string; +}) => { let deposit; let proof; @@ -15,6 +21,9 @@ export const getSavedBridgeApiData = async (destAddress ?: string) => { getTempDataFilePath(BridgeApiOps.deposit) ); deposit = JSON.parse(rawDeposit.toString()); + if (depositCnt) { + deposit = deposit.find((d : { deposit_cnt : string; }) => d.deposit_cnt === depositCnt); + } const rawProof = fs.readFileSync( getTempDataFilePath(BridgeApiOps.proof) @@ -24,7 +33,6 @@ export const getSavedBridgeApiData = async (destAddress ?: string) => { const deposits = await getBridgeDepositData({ destAddress }); deposit = deposits[deposits.length - 1]; - const { deposit_cnt, orig_net } = deposit; proof = await getMerkeProof({ depositCnt: deposit_cnt, netId: orig_net }); } @@ -35,8 +43,14 @@ export const getSavedBridgeApiData = async (destAddress ?: string) => { }; }; -export const getClaimArgsFromApi = async (destAddress ?: string) => { - const { deposit, proof } = await getSavedBridgeApiData(destAddress); +export const getClaimArgsFromApi = async ({ + destAddress, + depositCnt, +} : { + destAddress ?: string; + depositCnt ?: string; +}) => { + const { deposit, proof } = await getSavedBridgeApiData({ destAddress, depositCnt }); return [ proof.merkle_proof, From afe5397fba66164b2c2361f96d82626a3cda8224 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 18 Nov 2024 13:18:48 -0800 Subject: [PATCH 095/124] add bridging registration helper --- test/helpers/register-setup.ts | 93 ++++++++++++++++++++++++---------- 1 file changed, 66 insertions(+), 27 deletions(-) diff --git a/test/helpers/register-setup.ts b/test/helpers/register-setup.ts index e70be069d..a87d4c94d 100644 --- a/test/helpers/register-setup.ts +++ b/test/helpers/register-setup.ts @@ -13,7 +13,7 @@ import { ICurvePriceConfig } from "../../src/deploy/missions/types"; import { expect } from "chai"; import { IZNSContracts } from "../../src/deploy/campaign/types"; import { MeowTokenMock, ZNSRootRegistrarTrunk } from "../../typechain"; -import { getConfirmationsAmount } from "./tx"; +import { getConfirmationsNumber } from "./tx"; const { ZeroAddress } = ethers; @@ -43,10 +43,12 @@ export const defaultRootRegistration = async ({ paymentConfigEmpty ); - await tx.wait(getConfirmationsAmount()); + const receipt = await tx.wait(getConfirmationsNumber()); const supplyAfter = await zns.domainToken.totalSupply(); expect(supplyAfter).to.equal(supplyBefore + BigInt(1)); + + return receipt; }; export const approveForDomain = async ({ @@ -55,15 +57,20 @@ export const approveForDomain = async ({ user, domainLabel, isBridging = false, - mintTokens = false, } : { zns : IZNSContractsLocal | IZNSContracts; parentHash : string; user : SignerWithAddress; domainLabel : string; isBridging ?: boolean; - mintTokens ?: boolean; }) => { + const { token: tokenAddress } = await zns.treasury.paymentConfigs(parentHash); + + if (tokenAddress === ZeroAddress) { + console.log("No token set for parent domain. Proceeding without approval."); + return; + } + const { pricerContract } = await zns.subRegistrar.distrConfigs(parentHash); let price = BigInt(0); let parentFee = BigInt(0); @@ -73,15 +80,15 @@ export const approveForDomain = async ({ [price, parentFee] = await zns.fixedPricer.getPriceAndFee(parentHash, domainLabel, false); } - const { token: tokenAddress } = await zns.treasury.paymentConfigs(parentHash); const tokenContract = getTokenContract(tokenAddress, user); const protocolFee = await zns.curvePricer.getFeeForPrice(ethers.ZeroHash, price + parentFee); const toApprove = price + parentFee + protocolFee; - const confNum = getConfirmationsAmount(); + const confNum = getConfirmationsNumber(); - if (mintTokens) { + const userBal = await tokenContract.balanceOf(user.address); + if (userBal < toApprove) { const tx = await tokenContract.connect(user).mint(user.address, toApprove); await tx.wait(confNum); } @@ -125,10 +132,32 @@ export const defaultSubdomainRegistration = async ({ paymentConfigEmpty ); + await tx.wait(getConfirmationsNumber()); + const supplyAfter = await zns.domainToken.totalSupply(); expect(supplyAfter).to.equal(supplyBefore + BigInt(1)); +}; - return tx.wait(getConfirmationsAmount()); +export const defaultBridgingRegistration = async ({ + zns, + user, + parentHash = ethers.ZeroHash, + domainLabel, + tokenURI = DEFAULT_TOKEN_URI, +} : { + zns : IZNSContractsLocal | IZNSContracts; + user : SignerWithAddress; + parentHash ?: string; + domainLabel : string; + tokenURI ?: string; +}) => { + const tx = await zns.zPortal.connect(user).registerAndBridgeDomain( + parentHash, + domainLabel, + tokenURI + ); + + await tx.wait(getConfirmationsNumber()); }; export const registrationWithSetup = async ({ @@ -140,7 +169,7 @@ export const registrationWithSetup = async ({ tokenURI = DEFAULT_TOKEN_URI, fullConfig = fullDistrConfigEmpty, setConfigs = true, - mintTokens = false, + bridgeDomain = false, } : { zns : IZNSContractsLocal | IZNSContracts; user : SignerWithAddress; @@ -150,7 +179,7 @@ export const registrationWithSetup = async ({ tokenURI ?: string; fullConfig ?: IFullDistributionConfig; setConfigs ?: boolean; - mintTokens ?: boolean; + bridgeDomain ?: boolean; }) => { const hasConfig = !!fullConfig; const distrConfig = hasConfig @@ -164,29 +193,39 @@ export const registrationWithSetup = async ({ parentHash, user, domainLabel, - mintTokens, + isBridging: bridgeDomain, }); - // register domain - if (parentHash === ethers.ZeroHash) { - await defaultRootRegistration({ - user, + if (bridgeDomain) { + await defaultBridgingRegistration({ zns, - domainName: domainLabel, - domainContent, - tokenURI, - distrConfig, - }); - } else { - await defaultSubdomainRegistration({ user, - zns, parentHash, - subdomainLabel: domainLabel, - domainContent, + domainLabel, tokenURI, - distrConfig, }); + } else { + // register domain + if (parentHash === ethers.ZeroHash) { + await defaultRootRegistration({ + user, + zns, + domainName: domainLabel, + domainContent, + tokenURI, + distrConfig, + }); + } else { + await defaultSubdomainRegistration({ + user, + zns, + parentHash, + subdomainLabel: domainLabel, + domainContent, + tokenURI, + distrConfig, + }); + } } // get hash @@ -197,7 +236,7 @@ export const registrationWithSetup = async ({ if (!hasConfig) return domainHash; - const confNum = getConfirmationsAmount(); + const confNum = getConfirmationsNumber(); // set up prices if (fullConfig.distrConfig.pricerContract === await zns.fixedPricer.getAddress() && setConfigs) { From 9fe41eeaa786e5572f71bd025d6acd73b0d8f2c3 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 18 Nov 2024 13:19:04 -0800 Subject: [PATCH 096/124] fix api helper script --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d1159bedf..a55614e80 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "run-sepolia": "hardhat run src/deploy/run-campaign.ts --network sepolia", "run-hardhat": "hardhat run src/deploy/run-campaign.ts --network hardhat", "run-zchaintest": "hardhat run src/deploy/run-campaign.ts --network zchaintest", - "bridge-get": "ts-node src/utils/cross-chain/bridge-api.ts" + "bridge-get": "ts-node src/utils/cross-chain/run-bridge-api.ts" }, "pre-commit": [ "lint" From 4f3740eecadf9c4e5f6168dce583a91e99d59f06 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Tue, 19 Nov 2024 16:00:34 -0800 Subject: [PATCH 097/124] small fixes for the test --- test/cross-chain/MultiZNS.test.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test/cross-chain/MultiZNS.test.ts b/test/cross-chain/MultiZNS.test.ts index 703604ff1..949653034 100644 --- a/test/cross-chain/MultiZNS.test.ts +++ b/test/cross-chain/MultiZNS.test.ts @@ -74,7 +74,7 @@ describe.only("MultiZNS", () => { const rootDomainLabel = "jeffbridges"; const subdomainLabel = "beaubridges"; - const subParentLabel = "bridgessss"; + const subParentLabel = "bridgess"; const dummySmtProof = Array.from({ length: 32 }, () => hre.ethers.randomBytes(32)); @@ -474,7 +474,10 @@ describe.only("MultiZNS", () => { bridgedEventData.amount, bridgedEventData.metadata, ] - : await getClaimArgsFromApi(); + : await getClaimArgsFromApi({ + // when running on a real network provide this data to be able to run the test ! + // depositCnt: name === "Root Domain" ? "15" : "16", + }); // **NOTE** that we connect as `deployAdmin` here to show that it's not // required that this has to be called by the original owner, @@ -482,9 +485,9 @@ describe.only("MultiZNS", () => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - await znsL2.zkEvmBridge.connect(deployAdminL2).claimMessage(...claimArgs); + const tx = await znsL2.zkEvmBridge.connect(deployAdminL2).claimMessage(...claimArgs); + await tx.wait(getConfirmationsNumber()); - // TODO multi: fix all the event reads for test networks, now they don't get the data const events = await getEvents({ contract: znsL2.zkEvmBridge, eventName: "ClaimEvent", From c3c57ab76e8891333d8a69950934732d020e77d8 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 20 Nov 2024 11:53:33 -0800 Subject: [PATCH 098/124] add minter script for testing, commit HH config setup --- hardhat.config.ts | 56 +++++++++++----------------- package.json | 3 +- test/cross-chain/mint-looper.temp.ts | 32 ++++++++++++++++ 3 files changed, 56 insertions(+), 35 deletions(-) create mode 100644 test/cross-chain/mint-looper.temp.ts diff --git a/hardhat.config.ts b/hardhat.config.ts index 46c67fec3..3d85234cf 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -124,27 +124,29 @@ const config : HardhatUserConfig = { url: `${process.env.DEVNET_RPC_URL}`, chainId: 1, }, - // zchaintest: { - // url: `${process.env.ZCHAINTEST_RPC_URL}`, - // chainId: 1668201165, - // accounts: [ - // `${process.env.TESTNET_PRIVATE_KEY_A}`, - // ], - // }, + zchaintest: { + url: `${process.env.ZCHAINTEST_RPC_URL}`, + chainId: 2012605151, + accounts: [ + `${process.env.TESTNET_PRIVATE_KEY_A}`, + `${process.env.TESTNET_PRIVATE_KEY_B}`, + `${process.env.TESTNET_PRIVATE_KEY_C}`, + ], + }, + }, + etherscan: { + apiKey: `${process.env.ETHERSCAN_API_KEY}`, + customChains: [ + { + network: "zchaintest", + chainId: 2012605151, + urls: { + apiURL: "https://wilderworld-dev-erigon1-blockscout.eu-north-2.gateway.fm/api/", + browserURL: "https://wilderworld-dev-erigon1-blockscout.eu-north-2.gateway.fm/", + }, + }, + ], }, - // etherscan: { - // apiKey: `${process.env.ETHERSCAN_API_KEY}`, - // customChains: [ - // { - // network: "zchaintest", - // chainId: 1668201165, - // urls: { - // apiURL: "https://zchain-testnet-blockscout.eu-north-2.gateway.fm/api/", - // browserURL: "https://zchain-testnet-blockscout.eu-north-2.gateway.fm/", - // }, - // }, - // ], - // }, sourcify: { // If set to "true", will try to verify the contracts after deployment enabled: false, @@ -165,20 +167,6 @@ const config : HardhatUserConfig = { "oz-proxies/", ], }, - // meowtestnet: { - // url: `${process.env.MEOWTESTNET_RPC_URL}`, - // chainId: 883424730, - // accounts: [ // Comment out for CI, uncomment this when using Sepolia - // `${process.env.DEPLOYER_PRIVATE_KEY}`, - // `${process.env.ZERO_VAULT_PRIVATE_KEY}`, - // `${process.env.TESTNET_PRIVATE_KEY_A}`, - // `${process.env.TESTNET_PRIVATE_KEY_B}`, - // `${process.env.TESTNET_PRIVATE_KEY_C}`, - // `${process.env.TESTNET_PRIVATE_KEY_D}`, - // `${process.env.TESTNET_PRIVATE_KEY_E}`, - // `${process.env.TESTNET_PRIVATE_KEY_F}`, - // ], - // }, }; export default config; diff --git a/package.json b/package.json index a55614e80..d2055fb9f 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,8 @@ "run-sepolia": "hardhat run src/deploy/run-campaign.ts --network sepolia", "run-hardhat": "hardhat run src/deploy/run-campaign.ts --network hardhat", "run-zchaintest": "hardhat run src/deploy/run-campaign.ts --network zchaintest", - "bridge-get": "ts-node src/utils/cross-chain/run-bridge-api.ts" + "bridge-get": "ts-node src/utils/cross-chain/run-bridge-api.ts", + "mint-looper": "yarn hardhat run test/cross-chain/mint-looper.temp.ts --network zchaintest" }, "pre-commit": [ "lint" diff --git a/test/cross-chain/mint-looper.temp.ts b/test/cross-chain/mint-looper.temp.ts new file mode 100644 index 000000000..506b12ba8 --- /dev/null +++ b/test/cross-chain/mint-looper.temp.ts @@ -0,0 +1,32 @@ +import * as hre from "hardhat"; +import { MeowTokenMock, MeowTokenMock__factory } from "../../typechain"; + + +const sendTxes = async () => { + const amounts = Array.from({ length: 50 }, (_, i) => BigInt(i + 1) * BigInt(1e18)); + + const [caller, caller2, caller3] = await hre.ethers.getSigners(); + const fact = new MeowTokenMock__factory(); + const meowToken = fact.attach("0x50e6DFFf992747775C9c49717CFC4970b40594Dc") as MeowTokenMock; + + const resArr = await amounts.reduce( + async (acc, amt, idx) => { + const res = await acc; + + const txCaller = idx % 3 === 0 ? caller : idx % 3 === 1 ? caller2 : caller3; + console.log(`Minting tx #${idx} from ${txCaller.address}`); + + const tx = await meowToken.connect(txCaller).mint(txCaller.address, amt); + const rec = await tx.wait(1); + res.push(rec); + return res; + }, Promise.resolve([]), + ); + + console.log("Minted tokens:", JSON.stringify(resArr, null, "\t")); +}; + +sendTxes().catch(error => { + console.error(error); + process.exit(1); +}); From 3265e2db71580b52faad13461eb64066848aafdc Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 20 Nov 2024 11:54:49 -0800 Subject: [PATCH 099/124] remove redundant yarn call --- package.json | 2 +- ... CrossChainDomainBridging.network.test.ts} | 60 ++++---- test/cross-chain/ZNSDeploy.test.ts | 141 ++++++++++++++++++ test/helpers/env.ts | 14 ++ 4 files changed, 182 insertions(+), 35 deletions(-) rename test/cross-chain/{MultiZNS.test.ts => CrossChainDomainBridging.network.test.ts} (95%) create mode 100644 test/cross-chain/ZNSDeploy.test.ts create mode 100644 test/helpers/env.ts diff --git a/package.json b/package.json index d2055fb9f..379d746f7 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "run-hardhat": "hardhat run src/deploy/run-campaign.ts --network hardhat", "run-zchaintest": "hardhat run src/deploy/run-campaign.ts --network zchaintest", "bridge-get": "ts-node src/utils/cross-chain/run-bridge-api.ts", - "mint-looper": "yarn hardhat run test/cross-chain/mint-looper.temp.ts --network zchaintest" + "mint-looper": "hardhat run test/cross-chain/mint-looper.temp.ts --network zchaintest" }, "pre-commit": [ "lint" diff --git a/test/cross-chain/MultiZNS.test.ts b/test/cross-chain/CrossChainDomainBridging.network.test.ts similarity index 95% rename from test/cross-chain/MultiZNS.test.ts rename to test/cross-chain/CrossChainDomainBridging.network.test.ts index 949653034..43e69591d 100644 --- a/test/cross-chain/MultiZNS.test.ts +++ b/test/cross-chain/CrossChainDomainBridging.network.test.ts @@ -36,26 +36,12 @@ import { MongoDBAdapter, resetMongoAdapter } from "@zero-tech/zdc"; import assert from "assert"; import { getConfirmationsNumber } from "../helpers/tx"; import { getClaimArgsFromApi } from "../helpers/cc-claim"; +import { NETWORK_ID_L1_TEST_DEFAULT, NETWORK_ID_L2_TEST_DEFAULT, ZCHAIN_ID_TEST_DEFAULT } from "./ZNSDeploy.test"; +import { resetEnvVars } from "../helpers/env"; -export const NETWORK_ID_L1_DEFAULT = 0n; -export const NETWORK_ID_L2_DEFAULT = 1n; - -const zChainID = 2012605151n; - - -const resetEnvVars = () => { - delete process.env.SRC_CHAIN_NAME; - delete process.env.MOCK_ZKEVM_BRIDGE; - delete process.env.NETWORK_ID; - delete process.env.DEST_NETWORK_ID; - delete process.env.DEST_CHAIN_NAME; - delete process.env.DEST_CHAIN_ID; - delete process.env.SRC_ZNS_PORTAL; -}; - // TODO multi: add ChainResolver tests !!! -describe.only("MultiZNS", () => { +describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => { let isRealNetwork = false; let znsL1 : IZNSContracts; @@ -70,7 +56,8 @@ describe.only("MultiZNS", () => { let subUser : SignerWithAddress; let subUserL2 : Wallet | SignerWithAddress; - let config : IZNSCampaignConfig; + let configL1 : IZNSCampaignConfig; + let configL2 : IZNSCampaignConfig; const rootDomainLabel = "jeffbridges"; const subdomainLabel = "beaubridges"; @@ -129,22 +116,22 @@ describe.only("MultiZNS", () => { } else { // set ENV vars for the Ethereum ZNS deployment process.env.MOCK_ZKEVM_BRIDGE = "true"; - process.env.NETWORK_ID = NETWORK_ID_L1_DEFAULT.toString(); - process.env.DEST_NETWORK_ID = NETWORK_ID_L2_DEFAULT.toString(); + process.env.NETWORK_ID = NETWORK_ID_L1_TEST_DEFAULT.toString(); + process.env.DEST_NETWORK_ID = NETWORK_ID_L2_TEST_DEFAULT.toString(); process.env.DEST_CHAIN_NAME = SupportedChains.z; - process.env.DEST_CHAIN_ID = zChainID.toString(); + process.env.DEST_CHAIN_ID = ZCHAIN_ID_TEST_DEFAULT.toString(); } // TODO multi: create a proper test for zkEVM bridge when not mocked !!! // L1 run - config = await getConfig({ + configL1 = await getConfig({ deployer: deployAdmin, zeroVaultAddress: deployAdmin.address, }); // TODO multi: add logger message to show which network is campaign running on !!! - const campaignL1 = await runZnsCampaign({ config }); + const campaignL1 = await runZnsCampaign({ config: configL1 }); ({ state: { @@ -160,7 +147,7 @@ describe.only("MultiZNS", () => { if (!isRealNetwork) { // set vars for ZChain ZNS deployment process.env.SRC_ZNS_PORTAL = znsL1.zPortal.target as string; - process.env.NETWORK_ID = NETWORK_ID_L2_DEFAULT.toString(); + process.env.NETWORK_ID = NETWORK_ID_L2_TEST_DEFAULT.toString(); process.env.MONGO_DB_NAME = "zns-l2"; // TODO multi: create zkEVM bridge tests for predeployed bridge !!! deployAdminL2 = deployAdmin; @@ -177,20 +164,21 @@ describe.only("MultiZNS", () => { } // L2 run - config = await getConfig({ + configL2 = await getConfig({ deployer: deployAdminL2, zeroVaultAddress: deployAdminL2.address, }); // emulating L2 here by deploying to the same network - const campaignL2 = await runZnsCampaign({ config }); + const campaignL2 = await runZnsCampaign({ config: configL2 }); ({ state: { contracts: znsL2, }, dbAdapter: dbAdapter2, - } = campaignL2); }); + } = campaignL2); + }); after(async () => { resetEnvVars(); @@ -239,6 +227,9 @@ describe.only("MultiZNS", () => { ).to.be.rejectedWith("registerRootDomain is not a function"); }); + // TODO multi: Separate these into a different file that can work with real test networks and properly + // run one flow at a time (bridge vs claim) !!! + // And leave more regular tests here that can run on local Hardhat network ! [ { name: "Root Domain", @@ -326,7 +317,7 @@ describe.only("MultiZNS", () => { }); const event = events[events.length - 1]; expect(event.args.domainHash).to.equal(domainHash); - expect(event.args.destNetworkId).to.equal(NETWORK_ID_L2_DEFAULT); + expect(event.args.destNetworkId).to.equal(NETWORK_ID_L2_TEST_DEFAULT); expect(event.args.destPortalAddress).to.equal(znsL2.ethPortal.target); expect(event.args.domainOwner).to.equal(user.address); @@ -351,9 +342,9 @@ describe.only("MultiZNS", () => { ]] ); - expect(bridgedEventData.originNetwork).to.equal(NETWORK_ID_L1_DEFAULT); + expect(bridgedEventData.originNetwork).to.equal(NETWORK_ID_L1_TEST_DEFAULT); expect(bridgedEventData.originAddress).to.equal(znsL1.zPortal.target); - expect(bridgedEventData.destinationNetwork).to.equal(NETWORK_ID_L2_DEFAULT); + expect(bridgedEventData.destinationNetwork).to.equal(NETWORK_ID_L2_TEST_DEFAULT); expect(bridgedEventData.destinationAddress).to.equal(znsL2.ethPortal.target); expect(bridgedEventData.amount).to.equal(0n); expect(bridgedEventData.metadata).to.equal(metadataRef); @@ -401,7 +392,7 @@ describe.only("MultiZNS", () => { it("should properly set data in ChainResolver", async () => { const chainData = await znsL1.chainResolver.resolveChainDataStruct(domainHash); - expect(chainData.chainId).to.equal(zChainID); + expect(chainData.chainId).to.equal(ZCHAIN_ID_TEST_DEFAULT); expect(chainData.chainName).to.equal(SupportedChains.z); expect(chainData.znsRegistryOnChain).to.equal(hre.ethers.ZeroAddress); expect(chainData.auxData).to.equal(""); @@ -493,7 +484,7 @@ describe.only("MultiZNS", () => { eventName: "ClaimEvent", }); const event = events[events.length - 1]; - expect(event.args.originNetwork).to.equal(NETWORK_ID_L1_DEFAULT); + expect(event.args.originNetwork).to.equal(NETWORK_ID_L1_TEST_DEFAULT); expect(event.args.originAddress).to.equal(znsL1.zPortal.target); expect(event.args.destinationAddress).to.equal(znsL2.ethPortal.target); expect(event.args.amount).to.equal(0n); @@ -508,7 +499,7 @@ describe.only("MultiZNS", () => { eventName: "DomainClaimed", }); const event = events[events.length - 1]; - expect(event.args.srcNetworkId).to.equal(NETWORK_ID_L1_DEFAULT); + expect(event.args.srcNetworkId).to.equal(NETWORK_ID_L1_TEST_DEFAULT); expect(event.args.srcPortalAddress).to.equal(znsL1.zPortal.target); expect(event.args.domainHash).to.equal(domainHash); expect(event.args.domainOwner).to.equal(user.address); @@ -611,6 +602,7 @@ describe.only("MultiZNS", () => { }); }); + // TODO multi: separate all these into different files // We will only run this on local Hardhat network if (!isRealNetwork) { describe("Unit Tests", () => { @@ -661,7 +653,7 @@ describe.only("MultiZNS", () => { it("#initialize() should revert when trying to reinitialize", async () => { const { srcZnsPortal, - } = config.crosschain as IZNSZChainCrossConfig; + } = configL1.crosschain as IZNSZChainCrossConfig; await expect( znsL2.ethPortal.connect(deployAdmin).initialize( diff --git a/test/cross-chain/ZNSDeploy.test.ts b/test/cross-chain/ZNSDeploy.test.ts new file mode 100644 index 000000000..e5eba2e2a --- /dev/null +++ b/test/cross-chain/ZNSDeploy.test.ts @@ -0,0 +1,141 @@ +import assert from "assert"; +import { expect } from "chai"; +import * as hre from "hardhat"; +import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; +import { IZNSCampaignConfig, IZNSContracts } from "../../src/deploy/campaign/types"; +import { MongoDBAdapter, resetMongoAdapter } from "@zero-tech/zdc"; +import { Wallet } from "ethers"; +import { getConfig } from "../../src/deploy/campaign/environments"; +import { runZnsCampaign } from "../../src/deploy/zns-campaign"; +import { SupportedChains } from "../../src/deploy/missions/contracts/cross-chain/portals/get-portal-dm"; +import { resetEnvVars } from "../helpers/env"; +import { PolygonZkEVMBridgeV2Mock } from "../../typechain"; + + +export const NETWORK_ID_L1_TEST_DEFAULT = 0n; +export const NETWORK_ID_L2_TEST_DEFAULT = 1n; +export const ZCHAIN_ID_TEST_DEFAULT = 2012605151n; + +describe.only("ZNS Cross-Chain Deploy Test", () => { + let znsL1 : IZNSContracts; + let znsL2 : IZNSContracts; + + let configL1 : IZNSCampaignConfig; + let configL2 : IZNSCampaignConfig; + + let dbAdapter1 : MongoDBAdapter; + let dbAdapter2 : MongoDBAdapter; + + let deployAdmin : SignerWithAddress; + let user : SignerWithAddress; + + let predeployedBridge : PolygonZkEVMBridgeV2Mock; + + before(async () => { + [ deployAdmin, user ] = await hre.ethers.getSigners(); + + // set ENV vars for the Ethereum ZNS deployment + process.env.SRC_CHAIN_NAME = SupportedChains.eth; + process.env.MOCK_ZKEVM_BRIDGE = "true"; + process.env.NETWORK_ID = NETWORK_ID_L1_TEST_DEFAULT.toString(); + process.env.BRIDGE_TOKEN = hre.ethers.ZeroAddress; + process.env.DEST_NETWORK_ID = NETWORK_ID_L2_TEST_DEFAULT.toString(); + process.env.DEST_CHAIN_NAME = SupportedChains.z; + process.env.DEST_CHAIN_ID = ZCHAIN_ID_TEST_DEFAULT.toString(); + + // L1 run + configL1 = await getConfig({ + deployer: deployAdmin, + zeroVaultAddress: deployAdmin.address, + }); + + const campaignL1 = await runZnsCampaign({ config: configL1 }); + + ({ + state: { + contracts: znsL1, + }, + dbAdapter: dbAdapter1, + } = campaignL1); + + // TODO multi: do we need to break this up into 2 DBs or make 2 collections for one DB ?? + // so we don't have to specify the ENV var every time? or is it fine as is ?? + resetMongoAdapter(); + + // set ENV vars for ZChain ZNS deployment + process.env.SRC_CHAIN_NAME = SupportedChains.z; + process.env.SRC_ZNS_PORTAL = znsL1.zPortal.target as string; + process.env.MONGO_DB_NAME = "zns-l2"; + + // for L2 we are deploying the Bridge separately, so that we can test + // that the L2 campaign properly picks up the deployed Bridge from chain + const bridgeFact = await hre.ethers.getContractFactory("PolygonZkEVMBridgeV2Mock"); + predeployedBridge = await hre.upgrades.deployProxy( + bridgeFact, + [ + NETWORK_ID_L2_TEST_DEFAULT, + deployAdmin.address, + ] + ) as unknown as PolygonZkEVMBridgeV2Mock; + // now we need to set the proper ENV vars so that it's picked up by the L2 campaign + process.env.MOCK_ZKEVM_BRIDGE = "false"; + process.env.ZK_EVM_BRIDGE = predeployedBridge.target as string; + // we are setting these as such to make sure state is set from the parameters passed + // to the individual deploy above + process.env.NETWORK_ID = ""; + process.env.BRIDGE_TOKEN = ""; + + // L2 run + configL2 = await getConfig({ + deployer: deployAdmin, + zeroVaultAddress: deployAdmin.address, + }); + + // emulating L2 here by deploying to the same network + const campaignL2 = await runZnsCampaign({ config: configL2 }); + + ({ + state: { + contracts: znsL2, + }, + dbAdapter: dbAdapter2, + } = campaignL2); + }); + + after(async () => { + resetEnvVars(); + await dbAdapter1.dropDB(); + await dbAdapter2.dropDB(); + }); + + it("should deploy a mocked zkEVM Bridge if MOCK_ZKEVM_BRIDGE is 'true'", async () => { + // this happens in znsL1 deploy + assert.ok(configL1.crosschain.mockZkEvmBridge, "mockZkEvmBridge for L1 is set incorrectly!"); + + const { zkEvmBridge } = znsL1; + expect(zkEvmBridge.target).to.not.be.undefined; + + const networkIdFromBridge = await zkEvmBridge.networkID(); + const tokenFromBridge = await zkEvmBridge.WETHToken(); + + // same params as set in the ENV before deploying znsL1 + expect(networkIdFromBridge).to.equal(NETWORK_ID_L1_TEST_DEFAULT); + expect(tokenFromBridge).to.equal(hre.ethers.ZeroAddress); + }); + + it("should pick up an already deployed zkEVM Bridge from chain if MOCK_ZKEVM_BRIDGE is 'false'", async () => { + // this happens in znsL2 deploy + assert.ok(!configL2.crosschain.mockZkEvmBridge, "mockZkEvmBridge for L2 is set incorrectly!"); + + const { zkEvmBridge } = znsL2; + expect(zkEvmBridge.target).to.eq(predeployedBridge.target); + + const networkIdFromBridge = await zkEvmBridge.networkID(); + const tokenFromBridge = await zkEvmBridge.WETHToken(); + + // same params as passed to the `deployProxy` call above + // where we separately deploy the Bridge before running the L2 campaign + expect(networkIdFromBridge).to.equal(NETWORK_ID_L2_TEST_DEFAULT); + expect(tokenFromBridge).to.equal(deployAdmin.address); + }); +}); diff --git a/test/helpers/env.ts b/test/helpers/env.ts new file mode 100644 index 000000000..3fb6e95bc --- /dev/null +++ b/test/helpers/env.ts @@ -0,0 +1,14 @@ +// TODO multi: create a proper big ENV file with all default values here +// and make it be the default for all the tests and so it's easier to fill, clear +// and override it when needed. + +export const resetEnvVars = () => { + delete process.env.SRC_CHAIN_NAME; + delete process.env.MOCK_ZKEVM_BRIDGE; + delete process.env.NETWORK_ID; + delete process.env.DEST_NETWORK_ID; + delete process.env.DEST_CHAIN_NAME; + delete process.env.DEST_CHAIN_ID; + delete process.env.SRC_ZNS_PORTAL; +}; + From d5e438b899a14f4bbe6a3e7ee7b79b4667abf562 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 20 Nov 2024 18:38:38 -0800 Subject: [PATCH 100/124] create environment default stencil --- .env.sample | 2 +- src/environment/env.ts | 88 ++++++++++++++++++++++++++++ test/cross-chain/mint-looper.temp.ts | 8 +-- 3 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 src/environment/env.ts diff --git a/.env.sample b/.env.sample index 6df8d6a09..c9eaf8aa4 100644 --- a/.env.sample +++ b/.env.sample @@ -37,7 +37,7 @@ MOCK_MEOW_TOKEN= # This is only used if MOCK_MEOW_TOKEN is set to false (`test` and `prod` environments) STAKING_TOKEN_ADDRESS= -# Environment variables to create an entirely custom config when `env_level` above is not dev +# Environment variables to create an entirely custom config for CurvePricer when `env_level` above is not dev MAX_PRICE= MIN_PRICE= MAX_LENGTH= diff --git a/src/environment/env.ts b/src/environment/env.ts new file mode 100644 index 000000000..c1dd85b6f --- /dev/null +++ b/src/environment/env.ts @@ -0,0 +1,88 @@ +// TODO multi: create a proper big ENV file with all default values here +// and make it be the default for all the tests and so it's easier to fill, clear +// and override it when needed. + +// These are DEFAULT values for local testing that can be overridden by ENV vars +// set in .env file locally. +// For detailed breakdown of vars, see env.sample file. +// !!! --< DO NOT WRITE ANY MAINNET DATA HERE >-- !!! +export const environment = { + ENV_LEVEL: "dev", + // RPCs for actual networks + MAINNET_RPC_URL: "", + SEPOLIA_RPC_URL: "", + ZCHAIN_TEST_RPC_URL: "", + ZCHAIN_MAIN_RPC_URL: "", + // MongoDB setup + // TODO multi: should we split these into 2 for L1 and L2 ZNS contracts ?? + // how do we structure the DB here ?? + MONGO_DB_URI: "mongodb://localhost:27018", + MONGO_DB_NAME: "zns-campaign", + MONGO_DB_CLIENT_OPTS: "", + MONGO_DB_VERSION: "", + ARCHIVE_PREVIOUS_DB_VERSION: "true", + // Logger vars + LOG_LEVEL: "debug", + SILENT_LOGGER: "true", + MAKE_LOG_FILE: "false", + // 3rd Party Services: + // Etherscan + VERIFY_CONTRACTS: "false", + ETHERSCAN_API_KEY: "", + // Tenderly + MONITOR_CONTRACTS: "false", + TENDERLY_ACCOUNT_ID: "zer0-os", + TENDERLY_PROJECT_SLUG: "", + TENDERLY_ACCESS_KEY: "", + // Tenderly for testing with it's DevNet feature + TENDERLY_DEVNET_TEMPLATE: "zns-devnet", + DEVNET_RPC_URL: "", + + // Contracts Config: + + // ! System Administration ! + GOVERNOR_ADDRESSES: "", + ADMIN_ADDRESSES: "", + // ZNS Payment Token (e.g. MEOW or Z) + MOCK_MEOW_TOKEN: "true", + STAKING_TOKEN_ADDRESS: "", + // CurvePricer Config [without decimals!] + MAX_PRICE: "25000", + MIN_PRICE: "2000", + MAX_LENGTH: "50", + BASE_LENGTH: "4", + PROTOCOL_FEE_PERC: "222", + DECIMALS: "18", + PRECISION: "2", + // DomainToken Config + DOMAIN_TOKEN_NAME: "ZERO ID", + DOMAIN_TOKEN_SYMBOL: "ZID", + ROYALTY_FRACTION: "200", + ROYALTY_RECEIVER: "", + // Vault for all protocol fees + ZERO_VAULT_ADDRESS: "", + // Cross-Chain Config + SRC_CHAIN_NAME: "ethereum", + MOCK_ZKEVM_BRIDGE: "true", + ZK_EVM_BRIDGE: "", + NETWORK_ID: "0", + BRIDGE_TOKEN: "0x0000000000000000000000000000000000000000", + DEST_NETWORK_ID: "1", + // TODO multi: should we use existing constants here or make constants from this file ?? + // maybe the former so we can modify this file locally without affecting default constants... + DEST_CHAIN_NAME: "zchain", + DEST_CHAIN_ID: "2012605151", + SRC_ZNS_PORTAL: "", +}; + + +export const resetEnvVars = () => { + delete process.env.SRC_CHAIN_NAME; + delete process.env.MOCK_ZKEVM_BRIDGE; + delete process.env.NETWORK_ID; + delete process.env.DEST_NETWORK_ID; + delete process.env.DEST_CHAIN_NAME; + delete process.env.DEST_CHAIN_ID; + delete process.env.SRC_ZNS_PORTAL; +}; + diff --git a/test/cross-chain/mint-looper.temp.ts b/test/cross-chain/mint-looper.temp.ts index 506b12ba8..cf3ff6a29 100644 --- a/test/cross-chain/mint-looper.temp.ts +++ b/test/cross-chain/mint-looper.temp.ts @@ -26,7 +26,7 @@ const sendTxes = async () => { console.log("Minted tokens:", JSON.stringify(resArr, null, "\t")); }; -sendTxes().catch(error => { - console.error(error); - process.exit(1); -}); +// sendTxes().catch(error => { +// console.error(error); +// process.exit(1); +// }); From 4f2fadfee110511fffafdf630a1bb31124d8180b Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 20 Nov 2024 18:39:13 -0800 Subject: [PATCH 101/124] add types and extend Node env globals to type each var --- src/environment/globals.d.ts | 7 ++++++ src/environment/set-env.ts | 11 +++++++++ src/environment/types.ts | 48 ++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 src/environment/globals.d.ts create mode 100644 src/environment/set-env.ts create mode 100644 src/environment/types.ts diff --git a/src/environment/globals.d.ts b/src/environment/globals.d.ts new file mode 100644 index 000000000..ffa2c9d21 --- /dev/null +++ b/src/environment/globals.d.ts @@ -0,0 +1,7 @@ +import { ZNSEnv } from "./types"; + +declare global { + namespace NodeJS { + interface ProcessEnv extends ZNSEnv {} + } +} diff --git a/src/environment/set-env.ts b/src/environment/set-env.ts new file mode 100644 index 000000000..b44d23847 --- /dev/null +++ b/src/environment/set-env.ts @@ -0,0 +1,11 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +import { environment } from "./env"; + + +Object.entries(environment).forEach(([key, value]) => { + // load the defaults first + process.env[key] = value; +}); + +// override from local .env file if anything is present +require("dotenv").config({ override: true }); diff --git a/src/environment/types.ts b/src/environment/types.ts new file mode 100644 index 000000000..40bd3a29b --- /dev/null +++ b/src/environment/types.ts @@ -0,0 +1,48 @@ +export interface ZNSEnv { + ENV_LEVEL : string; + MAINNET_RPC_URL ?: string; + SEPOLIA_RPC_URL ?: string; + ZCHAIN_TEST_RPC_URL ?: string; + ZCHAIN_MAIN_RPC_URL ?: string; + MONGO_DB_URI : string; + MONGO_DB_NAME : string; + MONGO_DB_CLIENT_OPTS ?: string; + MONGO_DB_VERSION ?: string; + ARCHIVE_PREVIOUS_DB_VERSION : string; + LOG_LEVEL : string; + SILENT_LOGGER : string; + MAKE_LOG_FILE ?: string; + VERIFY_CONTRACTS : string; + ETHERSCAN_API_KEY ?: string; + MONITOR_CONTRACTS : string; + TENDERLY_ACCOUNT_ID : string; + TENDERLY_PROJECT_SLUG ?: string; + TENDERLY_ACCESS_KEY ?: string; + TENDERLY_DEVNET_TEMPLATE ?: string; + DEVNET_RPC_URL ?: string; + GOVERNOR_ADDRESSES ?: string; + ADMIN_ADDRESSES ?: string; + MOCK_MEOW_TOKEN : string; + STAKING_TOKEN_ADDRESS ?: string; + MAX_PRICE : string; + MIN_PRICE : string; + MAX_LENGTH : string; + BASE_LENGTH : string; + PROTOCOL_FEE_PERC : string; + DECIMALS : string; + PRECISION : string; + DOMAIN_TOKEN_NAME : string; + DOMAIN_TOKEN_SYMBOL : string; + ROYALTY_FRACTION : string; + ROYALTY_RECEIVER ?: string; + ZERO_VAULT_ADDRESS ?: string; + SRC_CHAIN_NAME : string; + MOCK_ZKEVM_BRIDGE : string; + ZK_EVM_BRIDGE ?: string; + NETWORK_ID : string; + BRIDGE_TOKEN : string; + DEST_NETWORK_ID : string; + DEST_CHAIN_NAME : string; + DEST_CHAIN_ID : string; + SRC_ZNS_PORTAL ?: string; +} From 2e13ccc80d3d969d9eceb98945ca7fff2830c2b4 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 20 Nov 2024 18:40:09 -0800 Subject: [PATCH 102/124] create validation function and add env setup to HH config --- hardhat.config.ts | 10 +++++----- src/environment/validate.ts | 17 +++++++++++++++++ test/helpers/env.ts | 14 -------------- 3 files changed, 22 insertions(+), 19 deletions(-) create mode 100644 src/environment/validate.ts delete mode 100644 test/helpers/env.ts diff --git a/hardhat.config.ts b/hardhat.config.ts index 3d85234cf..44327f06f 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,5 +1,4 @@ /* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-unused-vars */ -require("dotenv").config(); import { mochaGlobalSetup, mochaGlobalTeardown } from "./test/mocha-global"; @@ -16,6 +15,7 @@ import "solidity-docgen"; import "hardhat-gas-reporter"; import { HardhatUserConfig, subtask } from "hardhat/config"; import { TASK_TEST_RUN_MOCHA_TESTS } from "hardhat/builtin-tasks/task-names"; +import "./src/environment/set-env"; subtask(TASK_TEST_RUN_MOCHA_TESTS) @@ -125,12 +125,12 @@ const config : HardhatUserConfig = { chainId: 1, }, zchaintest: { - url: `${process.env.ZCHAINTEST_RPC_URL}`, + url: `${process.env.ZCHAIN_TEST_RPC_URL}`, chainId: 2012605151, accounts: [ - `${process.env.TESTNET_PRIVATE_KEY_A}`, - `${process.env.TESTNET_PRIVATE_KEY_B}`, - `${process.env.TESTNET_PRIVATE_KEY_C}`, + // `${process.env.TESTNET_PRIVATE_KEY_A}`, + // `${process.env.TESTNET_PRIVATE_KEY_B}`, + // `${process.env.TESTNET_PRIVATE_KEY_C}`, ], }, }, diff --git a/src/environment/validate.ts b/src/environment/validate.ts new file mode 100644 index 000000000..21ee632ff --- /dev/null +++ b/src/environment/validate.ts @@ -0,0 +1,17 @@ + +const required = [ + "MONGO_DB_URI", "MONGO_DB_NAME", "ARCHIVE_PREVIOUS_DB_VERSION", "LOG_LEVEL", "ARCHIVE_PREVIOUS_DB_VERSION", + "LOG_LEVEL", "ENV_LEVEL", "MAX_PRICE", "MIN_PRICE", "MAX_LENGTH", "BASE_LENGTH", "PROTOCOL_FEE_PERC", + "DECIMALS", "PRECISION", "DOMAIN_TOKEN_NAME", "DOMAIN_TOKEN_SYMBOL", "ROYALTY_FRACTION", "MOCK_MEOW_TOKEN", + "SRC_CHAIN_NAME", "MOCK_ZKEVM_BRIDGE", "DEST_NETWORK_ID", "DEST_CHAIN_NAME", "DEST_CHAIN_ID", +]; + +// TODO multi: is there a way to evaluate a type of the full ENV and run the below function +// only on non-optional parameters? +export const findMissingEnvVars = () => { + const missing = required.filter(key => process.env[key] === undefined || process.env[key] === ""); + + if (missing.length > 0) { + throw new Error(`Missing required environment variables: ${missing.join(", ")}`); + } +}; diff --git a/test/helpers/env.ts b/test/helpers/env.ts deleted file mode 100644 index 3fb6e95bc..000000000 --- a/test/helpers/env.ts +++ /dev/null @@ -1,14 +0,0 @@ -// TODO multi: create a proper big ENV file with all default values here -// and make it be the default for all the tests and so it's easier to fill, clear -// and override it when needed. - -export const resetEnvVars = () => { - delete process.env.SRC_CHAIN_NAME; - delete process.env.MOCK_ZKEVM_BRIDGE; - delete process.env.NETWORK_ID; - delete process.env.DEST_NETWORK_ID; - delete process.env.DEST_CHAIN_NAME; - delete process.env.DEST_CHAIN_ID; - delete process.env.SRC_ZNS_PORTAL; -}; - From 008b0b58e06ebab3d1f6352dfcc8c3116d62f3df Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 21 Nov 2024 14:38:28 -0800 Subject: [PATCH 103/124] fix types --- src/deploy/campaign/types.ts | 2 +- src/environment/globals.d.ts | 4 ++-- src/environment/types.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/deploy/campaign/types.ts b/src/deploy/campaign/types.ts index 4c6fb5762..b3bf28f58 100644 --- a/src/deploy/campaign/types.ts +++ b/src/deploy/campaign/types.ts @@ -57,7 +57,7 @@ export interface IZNSCampaignConfig extends IDeployCampaignConfig Date: Thu, 21 Nov 2024 14:39:00 -0800 Subject: [PATCH 104/124] remove redundant code and checks from campaign config getter --- src/deploy/campaign/environments.ts | 97 +++++++---------------------- 1 file changed, 21 insertions(+), 76 deletions(-) diff --git a/src/deploy/campaign/environments.ts b/src/deploy/campaign/environments.ts index 2b2dcd7a9..50a59655d 100644 --- a/src/deploy/campaign/environments.ts +++ b/src/deploy/campaign/environments.ts @@ -22,11 +22,12 @@ import { MONGO_URI_ERR, INVALID_ENV_ERR, NO_ZERO_VAULT_ERR, } from "../../../test/helpers"; -import { ethers } from "ethers"; +import { ethers, Wallet } from "ethers"; import { ICurvePriceConfig } from "../missions/types"; import { MeowMainnet } from "../missions/contracts/zns-base/meow-token/mainnet-data"; import { TSupportedChain } from "../missions/contracts/cross-chain/portals/types"; import { SupportedChains } from "../missions/contracts/cross-chain/portals/get-portal-dm"; +import { findMissingEnvVars } from "../../environment/validate"; const getCustomAddresses = ( @@ -69,12 +70,12 @@ export const getConfig = async ({ zeroVaultAddress, env, // this is ONLY used for tests! } : { - deployer : SignerWithAddress; + deployer : Wallet | SignerWithAddress; governors ?: Array; admins ?: Array; zeroVaultAddress ?: string; env ?: string; -}) : Promise> => { +}) : Promise> => { // Will throw an error based on any invalid setup, given the `ENV_LEVEL` set const priceConfig = validateEnv(env); @@ -99,10 +100,7 @@ export const getConfig = async ({ // Domain Token Values const royaltyReceiver = process.env.ENV_LEVEL !== "dev" ? process.env.ROYALTY_RECEIVER! : zeroVaultAddressConf; - const royaltyFraction = - process.env.ROYALTY_FRACTION - ? BigInt(process.env.ROYALTY_FRACTION) - : DEFAULT_ROYALTY_FRACTION; + const royaltyFraction = BigInt(process.env.ROYALTY_FRACTION); // Get governor addresses set through env, if any const governorAddresses = getCustomAddresses("GOVERNOR_ADDRESSES", deployerAddress, governors); @@ -110,23 +108,23 @@ export const getConfig = async ({ // Get admin addresses set through env, if any const adminAddresses = getCustomAddresses("ADMIN_ADDRESSES", deployerAddress, admins); - const config : IZNSCampaignConfig = { - env: process.env.ENV_LEVEL!, + const config : IZNSCampaignConfig = { + env: process.env.ENV_LEVEL, deployAdmin: deployer, governorAddresses, adminAddresses, domainToken: { - name: process.env.DOMAIN_TOKEN_NAME ? process.env.DOMAIN_TOKEN_NAME : ZNS_DOMAIN_TOKEN_NAME, - symbol: process.env.DOMAIN_TOKEN_SYMBOL ? process.env.DOMAIN_TOKEN_SYMBOL : ZNS_DOMAIN_TOKEN_SYMBOL, + name: process.env.DOMAIN_TOKEN_NAME, + symbol: process.env.DOMAIN_TOKEN_SYMBOL, defaultRoyaltyReceiver: royaltyReceiver, defaultRoyaltyFraction: royaltyFraction, }, rootPriceConfig: priceConfig, zeroVaultAddress: zeroVaultAddressConf, mockMeowToken: process.env.MOCK_MEOW_TOKEN === "true", - stakingTokenAddress: process.env.STAKING_TOKEN_ADDRESS!, + stakingTokenAddress: process.env.STAKING_TOKEN_ADDRESS, postDeploy: { - tenderlyProjectSlug: process.env.TENDERLY_PROJECT_SLUG!, + tenderlyProjectSlug: process.env.TENDERLY_PROJECT_SLUG ?? "", monitorContracts: process.env.MONITOR_CONTRACTS === "true", verifyContracts: process.env.VERIFY_CONTRACTS === "true", }, @@ -150,6 +148,8 @@ export const validateEnv = ( envLevel = env; } + findMissingEnvVars(); + // Validate price config first since we have to return it const priceConfig = getValidateRootPriceConfig(); @@ -166,20 +166,6 @@ export const validateEnv = ( throw new Error(INVALID_ENV_ERR); } - if (!process.env.ROYALTY_RECEIVER) { - throw new Error("Must provide a default royalty receiver"); - } - - if (!process.env.ROYALTY_FRACTION) { - throw new Error("Must provide a default royalty fraction"); - } - - if (!process.env.MONGO_DB_URI) { - throw new Error(`Must provide a Mongo URI used for ${envLevel} environment!`); - } - - requires(!!process.env.ZERO_VAULT_ADDRESS, NO_ZERO_VAULT_ERR); - // Mainnet if (envLevel === "prod") { requires(process.env.MOCK_MEOW_TOKEN === "false", NO_MOCK_PROD_ERR); @@ -201,57 +187,18 @@ export const validateEnv = ( }; export const getValidateRootPriceConfig = () => { - - if (process.env.ENV_LEVEL === "prod") { - requires( - !!process.env.MAX_PRICE - && !!process.env.MIN_PRICE - && !!process.env.MAX_LENGTH - && !!process.env.BASE_LENGTH - && !!process.env.DECIMALS - && !!process.env.PRECISION - && !!process.env.PROTOCOL_FEE_PERC, - "Must provide all price config variables for prod environment!" - ); - } - // Price config variables - const maxPrice = - process.env.MAX_PRICE - ? ethers.parseEther(process.env.MAX_PRICE) - : DEFAULT_PRICE_CONFIG.maxPrice; - - const minPrice = - process.env.MIN_PRICE - ? ethers.parseEther(process.env.MIN_PRICE) - : DEFAULT_PRICE_CONFIG.minPrice; - - const maxLength = - process.env.MAX_LENGTH - ? BigInt(process.env.MAX_LENGTH) - : DEFAULT_PRICE_CONFIG.maxLength; - - const baseLength = - process.env.BASE_LENGTH - ? BigInt(process.env.BASE_LENGTH) - : DEFAULT_PRICE_CONFIG.baseLength; - const decimals = process.env.DECIMALS ? BigInt(process.env.DECIMALS) : DEFAULT_DECIMALS; const precision = process.env.PRECISION ? BigInt(process.env.PRECISION) : DEFAULT_PRECISION; const precisionMultiplier = BigInt(10) ** (decimals - precision); - const feePercentage = - process.env.PROTOCOL_FEE_PERC - ? BigInt(process.env.PROTOCOL_FEE_PERC) - : DEFAULT_PROTOCOL_FEE_PERCENT; - const priceConfig : ICurvePriceConfig = { - maxPrice, - minPrice, - maxLength, - baseLength, + maxPrice: ethers.parseEther(process.env.MAX_PRICE), + minPrice: ethers.parseEther(process.env.MIN_PRICE), + maxLength: BigInt(process.env.MAX_LENGTH), + baseLength: BigInt(process.env.BASE_LENGTH), precisionMultiplier, - feePercentage, + feePercentage: BigInt(process.env.PROTOCOL_FEE_PERC), isSet: true, }; @@ -279,9 +226,7 @@ const validatePrice = (config : ICurvePriceConfig) => { }; export const buildCrosschainConfig = () : TZNSCrossConfig => { - requires(!!process.env.SRC_CHAIN_NAME, "Must provide name for the chain to deploy to!"); const srcChainName = process.env.SRC_CHAIN_NAME as TSupportedChain; - requires(!!process.env.MOCK_ZKEVM_BRIDGE, "Must provide mock polygon bridge flag!"); const mockZkEvmBridge = process.env.MOCK_ZKEVM_BRIDGE === "true"; let curNetworkId; @@ -297,7 +242,7 @@ export const buildCrosschainConfig = () : TZNSCrossConfig => { !!process.env.NETWORK_ID, "Must provide current network ID for mocked bridge!" ); - curNetworkId = BigInt(process.env.NETWORK_ID!); + curNetworkId = BigInt(process.env.NETWORK_ID); } const baseConfig = { @@ -317,9 +262,9 @@ export const buildCrosschainConfig = () : TZNSCrossConfig => { crossConfig = { ...baseConfig, - destNetworkId: BigInt(process.env.DEST_NETWORK_ID!), + destNetworkId: BigInt(process.env.DEST_NETWORK_ID), destChainName: process.env.DEST_CHAIN_NAME, - destChainId: BigInt(process.env.DEST_CHAIN_ID!), + destChainId: BigInt(process.env.DEST_CHAIN_ID), } as IZNSEthCrossConfig; break; From 0d18fce8b8176d719a7eec94f3d921d1bc1e36d3 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Thu, 21 Nov 2024 14:40:39 -0800 Subject: [PATCH 105/124] move root level getLogger calls to actually read from the env properly, and small fixes for env and env validation --- src/environment/env.ts | 6 ++++-- src/environment/validate.ts | 2 +- src/utils/drop-db.ts | 5 +---- src/utils/git-tag/get-tag.ts | 4 ++-- src/utils/git-tag/save-tag.ts | 2 +- test/cross-chain/ZNSDeploy.test.ts | 3 ++- test/helpers/constants.ts | 1 + 7 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/environment/env.ts b/src/environment/env.ts index c1dd85b6f..ead18a4cc 100644 --- a/src/environment/env.ts +++ b/src/environment/env.ts @@ -6,7 +6,10 @@ // set in .env file locally. // For detailed breakdown of vars, see env.sample file. // !!! --< DO NOT WRITE ANY MAINNET DATA HERE >-- !!! -export const environment = { +import { IZNSEnvironment } from "./types"; + + +export const environment : IZNSEnvironment = { ENV_LEVEL: "dev", // RPCs for actual networks MAINNET_RPC_URL: "", @@ -39,7 +42,6 @@ export const environment = { DEVNET_RPC_URL: "", // Contracts Config: - // ! System Administration ! GOVERNOR_ADDRESSES: "", ADMIN_ADDRESSES: "", diff --git a/src/environment/validate.ts b/src/environment/validate.ts index 21ee632ff..b426a9ec6 100644 --- a/src/environment/validate.ts +++ b/src/environment/validate.ts @@ -3,7 +3,7 @@ const required = [ "MONGO_DB_URI", "MONGO_DB_NAME", "ARCHIVE_PREVIOUS_DB_VERSION", "LOG_LEVEL", "ARCHIVE_PREVIOUS_DB_VERSION", "LOG_LEVEL", "ENV_LEVEL", "MAX_PRICE", "MIN_PRICE", "MAX_LENGTH", "BASE_LENGTH", "PROTOCOL_FEE_PERC", "DECIMALS", "PRECISION", "DOMAIN_TOKEN_NAME", "DOMAIN_TOKEN_SYMBOL", "ROYALTY_FRACTION", "MOCK_MEOW_TOKEN", - "SRC_CHAIN_NAME", "MOCK_ZKEVM_BRIDGE", "DEST_NETWORK_ID", "DEST_CHAIN_NAME", "DEST_CHAIN_ID", + "SRC_CHAIN_NAME", "MOCK_ZKEVM_BRIDGE", ]; // TODO multi: is there a way to evaluate a type of the full ENV and run the below function diff --git a/src/utils/drop-db.ts b/src/utils/drop-db.ts index 793c82ac3..72fd80fc4 100644 --- a/src/utils/drop-db.ts +++ b/src/utils/drop-db.ts @@ -1,9 +1,6 @@ -import { getLogger } from "@zero-tech/zdc"; import { startMongo, stopMongo, getZnsMongoAdapter } from "../deploy/mongo"; -const logger = getLogger(); - export const dropDB = async () => { try { const adapter = await getZnsMongoAdapter(); @@ -18,6 +15,6 @@ export const dropDB = async () => { dropDB() .then(() => process.exit(0)) .catch(error => { - logger.debug(error); + console.log(error); process.exit(1); }); diff --git a/src/utils/git-tag/get-tag.ts b/src/utils/git-tag/get-tag.ts index d2b512229..e793a1889 100644 --- a/src/utils/git-tag/get-tag.ts +++ b/src/utils/git-tag/get-tag.ts @@ -3,13 +3,13 @@ import { tagFilePath } from "./constants"; import { getLogger } from "@zero-tech/zdc"; -const logger = getLogger(); - export const getGitTag = () => { if (!fs.existsSync(tagFilePath)) { throw Error(`No git tag found at ${tagFilePath}`); } + const logger = getLogger(); + const tag = fs.readFileSync(tagFilePath, "utf8").trim(); logger.info(`Git tag found at ${tagFilePath}: ${tag}`); diff --git a/src/utils/git-tag/save-tag.ts b/src/utils/git-tag/save-tag.ts index 0b74952ce..21de99523 100644 --- a/src/utils/git-tag/save-tag.ts +++ b/src/utils/git-tag/save-tag.ts @@ -6,12 +6,12 @@ import { tagFilePath } from "./constants"; const execAsync = promisify(exec); -const logger = getLogger(); export const acquireLatestGitTag = async () => { const gitTag = await execAsync("git describe --tags --abbrev=0"); const tag = gitTag.stdout.trim(); + const logger = getLogger(); logger.info(`Latest git tag acquired: ${tag}`); diff --git a/test/cross-chain/ZNSDeploy.test.ts b/test/cross-chain/ZNSDeploy.test.ts index e5eba2e2a..623eb7043 100644 --- a/test/cross-chain/ZNSDeploy.test.ts +++ b/test/cross-chain/ZNSDeploy.test.ts @@ -8,8 +8,9 @@ import { Wallet } from "ethers"; import { getConfig } from "../../src/deploy/campaign/environments"; import { runZnsCampaign } from "../../src/deploy/zns-campaign"; import { SupportedChains } from "../../src/deploy/missions/contracts/cross-chain/portals/get-portal-dm"; -import { resetEnvVars } from "../helpers/env"; +import { resetEnvVars } from "../../src/environment/env"; import { PolygonZkEVMBridgeV2Mock } from "../../typechain"; +import { findMissingEnvVars } from "../../src/environment/validate"; export const NETWORK_ID_L1_TEST_DEFAULT = 0n; diff --git a/test/helpers/constants.ts b/test/helpers/constants.ts index 588ede8c1..9ba5a0084 100644 --- a/test/helpers/constants.ts +++ b/test/helpers/constants.ts @@ -34,6 +34,7 @@ export const PaymentType = { STAKE: 1n, }; +// TODO multi: make these read from the env.ts file along with other default env vars ?? export const DEFAULT_PRICE_CONFIG : ICurvePriceConfig = { maxPrice: ethers.parseEther("25000"), minPrice: ethers.parseEther("2000"), From 03b8bb8cab945060f049e319fd998c0ba8136a88 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Fri, 22 Nov 2024 15:53:33 -0800 Subject: [PATCH 106/124] refactor env setter and validation to be able to use that in tests to reset env when needed --- init-env.ts | 3 +++ src/environment/set-env.ts | 15 ++++++++------- src/environment/validate.ts | 5 ++++- src/utils/git-tag/save-tag.ts | 1 + 4 files changed, 16 insertions(+), 8 deletions(-) create mode 100644 init-env.ts diff --git a/init-env.ts b/init-env.ts new file mode 100644 index 000000000..672e99b6a --- /dev/null +++ b/init-env.ts @@ -0,0 +1,3 @@ +import { setDefaultEnvironment } from "./src/environment/set-env"; + +setDefaultEnvironment(); diff --git a/src/environment/set-env.ts b/src/environment/set-env.ts index b44d23847..453c81be8 100644 --- a/src/environment/set-env.ts +++ b/src/environment/set-env.ts @@ -1,11 +1,12 @@ /* eslint-disable @typescript-eslint/no-var-requires */ import { environment } from "./env"; +export const setDefaultEnvironment = () => { + Object.entries(environment).forEach(([key, value]) => { + // load the defaults first + process.env[key] = value; + }); -Object.entries(environment).forEach(([key, value]) => { - // load the defaults first - process.env[key] = value; -}); - -// override from local .env file if anything is present -require("dotenv").config({ override: true }); + // override from local .env file if anything is present + require("dotenv").config({ override: true }); +}; diff --git a/src/environment/validate.ts b/src/environment/validate.ts index b426a9ec6..9f02151f6 100644 --- a/src/environment/validate.ts +++ b/src/environment/validate.ts @@ -9,7 +9,10 @@ const required = [ // TODO multi: is there a way to evaluate a type of the full ENV and run the below function // only on non-optional parameters? export const findMissingEnvVars = () => { - const missing = required.filter(key => process.env[key] === undefined || process.env[key] === ""); + const missing = required.filter( + key => + process.env[key] === undefined || process.env[key] === "" + ); if (missing.length > 0) { throw new Error(`Missing required environment variables: ${missing.join(", ")}`); diff --git a/src/utils/git-tag/save-tag.ts b/src/utils/git-tag/save-tag.ts index 21de99523..c5faac189 100644 --- a/src/utils/git-tag/save-tag.ts +++ b/src/utils/git-tag/save-tag.ts @@ -26,6 +26,7 @@ export const acquireLatestGitTag = async () => { export const saveTag = async () => { const tag = await acquireLatestGitTag(); + const logger = getLogger(); fs.writeFileSync(tagFilePath, tag, "utf8"); logger.info(`Saved git tag-commit to ${tagFilePath}}`); From f6f1cb73a9e3124cf8a29153b07d4e2afcd7c4f4 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Fri, 22 Nov 2024 15:54:56 -0800 Subject: [PATCH 107/124] update types and remain zPortal key --- hardhat.config.ts | 3 +-- src/deploy/campaign/types.ts | 2 +- src/deploy/missions/contracts/names.ts | 2 +- test/helpers/types.ts | 19 +++++++++++++++++-- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 44327f06f..2b15d48fb 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-unused-vars */ - +import "./init-env"; import { mochaGlobalSetup, mochaGlobalTeardown } from "./test/mocha-global"; @@ -15,7 +15,6 @@ import "solidity-docgen"; import "hardhat-gas-reporter"; import { HardhatUserConfig, subtask } from "hardhat/config"; import { TASK_TEST_RUN_MOCHA_TESTS } from "hardhat/builtin-tasks/task-names"; -import "./src/environment/set-env"; subtask(TASK_TEST_RUN_MOCHA_TESTS) diff --git a/src/deploy/campaign/types.ts b/src/deploy/campaign/types.ts index b3bf28f58..083735dfe 100644 --- a/src/deploy/campaign/types.ts +++ b/src/deploy/campaign/types.ts @@ -99,7 +99,7 @@ export interface IZNSContracts extends IContractState { rootRegistrar : ZNSRootRegistrarTrunk | ZNSRootRegistrarBranch; fixedPricer : ZNSFixedPricer; subRegistrar : ZNSSubRegistrarTrunk | ZNSSubRegistrarBranch; - zPortal : ZNSZChainPortal; + zChainPortal : ZNSZChainPortal; ethPortal : ZNSEthereumPortal; zkEvmBridge : PolygonZkEVMBridgeV2Mock; } diff --git a/src/deploy/missions/contracts/names.ts b/src/deploy/missions/contracts/names.ts index acba4be94..7e57ca780 100644 --- a/src/deploy/missions/contracts/names.ts +++ b/src/deploy/missions/contracts/names.ts @@ -56,7 +56,7 @@ export const znsNames = { }, zPortal: { contract: "ZNSZChainPortal", - instance: "zPortal", + instance: "zChainPortal", }, ethPortal: { contract: "ZNSEthereumPortal", diff --git a/test/helpers/types.ts b/test/helpers/types.ts index e9d8ec93d..29f52ec0b 100644 --- a/test/helpers/types.ts +++ b/test/helpers/types.ts @@ -29,6 +29,14 @@ import { import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { ICurvePriceConfig } from "../../src/deploy/missions/types"; import { Addressable } from "ethers"; +import { SupportedChains } from "../../src/deploy/missions/contracts/cross-chain/portals/get-portal-dm"; +import { + NETWORK_ID_L1_TEST_DEFAULT, + NETWORK_ID_L2_TEST_DEFAULT, + ZCHAIN_ID_TEST_DEFAULT, +} from "../cross-chain/ZNSDeploy.test"; +import { ethers } from "hardhat"; +import { TSupportedChain } from "../../src/deploy/missions/contracts/cross-chain/portals/types"; export type Maybe = T | undefined; @@ -91,8 +99,8 @@ export interface IZNSContractsLocal { rootRegistrar : ZNSRootRegistrarTrunk | ZNSRootRegistrarBranch; fixedPricer : ZNSFixedPricer; subRegistrar : ZNSSubRegistrarTrunk | ZNSSubRegistrarBranch; - zPortal : ZNSZChainPortal; - ethPortal : ZNSEthereumPortal; + zChainPortal ?: ZNSZChainPortal; + ethPortal ?: ZNSEthereumPortal; zkEvmBridge : PolygonZkEVMBridgeV2Mock; zeroVaultAddress : string; } @@ -104,6 +112,13 @@ export interface DeployZNSParams { priceConfig ?: ICurvePriceConfig; registrationFeePerc ?: bigint; zeroVaultAddress ?: string; + srcChainName ?: TSupportedChain; + srcNetworkId ?: bigint; + bridgeTokenAddress ?: string; + destNetworkId ?: bigint; + destChainName ?: TSupportedChain; + destChainId ?: bigint; + srcZnsPortalAddress ?: string; isTenderlyRun ?: boolean; } From fb001c5461412b14e5e59e8b6558c5ba1f6a7b23 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Fri, 22 Nov 2024 15:55:55 -0800 Subject: [PATCH 108/124] update local deploy helpers with new functions for all contracts --- test/helpers/deploy/deploy-zns.ts | 417 ++++++++++++++++++++++++++++-- test/helpers/register-setup.ts | 4 +- 2 files changed, 393 insertions(+), 28 deletions(-) diff --git a/test/helpers/deploy/deploy-zns.ts b/test/helpers/deploy/deploy-zns.ts index c2006a9d5..e2f559625 100644 --- a/test/helpers/deploy/deploy-zns.ts +++ b/test/helpers/deploy/deploy-zns.ts @@ -9,16 +9,29 @@ import { ZNSDomainToken__factory, ZNSFixedPricer__factory, ZNSCurvePricer__factory, - ZNSRootRegistrar, - ZNSRootRegistrar__factory, ZNSRegistry, ZNSRegistry__factory, - ZNSSubRegistrar__factory, ZNSTreasury, ZNSTreasury__factory, ZNSFixedPricer, - ZNSSubRegistrar, MeowTokenMock, + ZNSStringResolver, + ZNSStringResolver__factory, + ZNSChainResolver__factory, + ZNSChainResolver, + ZNSRootRegistrarTrunk__factory, + ZNSRootRegistrarBranch__factory, + ZNSSubRegistrarTrunk__factory, + ZNSSubRegistrarBranch__factory, + PolygonZkEVMBridgeV2Mock__factory, + PolygonZkEVMBridgeV2Mock, + ZNSZChainPortal__factory, + ZNSZChainPortal, + ZNSEthereumPortal__factory, + ZNSEthereumPortal, + ZNSRootRegistrarTrunk, + ZNSRootRegistrarBranch, + ZNSSubRegistrarTrunk, ZNSSubRegistrarBranch, } from "../../../typechain"; import { DeployZNSParams, RegistrarConfig, IZNSContractsLocal } from "../types"; import * as hre from "hardhat"; @@ -32,9 +45,7 @@ import { fixedPricerName, DEFAULT_PRICE_CONFIG, curvePricerName, - registrarName, registryName, - subRegistrarName, treasuryName, meowTokenMockName, ZNS_DOMAIN_TOKEN_NAME, @@ -42,11 +53,18 @@ import { DEFAULT_ROYALTY_FRACTION, DEFAULT_RESOLVER_TYPE, } from "../constants"; -import { REGISTRAR_ROLE } from "../../../src/deploy/constants"; +import { PORTAL_ROLE, REGISTRAR_ROLE } from "../../../src/deploy/constants"; import { getProxyImplAddress } from "../utils"; import { ICurvePriceConfig } from "../../../src/deploy/missions/types"; import { meowTokenName, meowTokenSymbol } from "../../../src/deploy/missions/contracts"; -import { transparentProxyName } from "../../../src/deploy/missions/contracts/names"; +import { transparentProxyName, znsNames } from "../../../src/deploy/missions/contracts/names"; +import { TSupportedChain } from "../../../src/deploy/missions/contracts/cross-chain/portals/types"; +import { SupportedChains } from "../../../src/deploy/missions/contracts/cross-chain/portals/get-portal-dm"; +import { + NETWORK_ID_L1_TEST_DEFAULT, + NETWORK_ID_L2_TEST_DEFAULT, + ZCHAIN_ID_TEST_DEFAULT, +} from "../../cross-chain/ZNSDeploy.test"; export const deployAccessController = async ({ @@ -68,7 +86,7 @@ export const deployAccessController = async ({ if (isTenderlyRun) { await hre.tenderly.verify({ - name: accessControllerName, + name: znsNames.accessController.contract, address: proxyAddress, }); @@ -105,7 +123,7 @@ export const deployRegistry = async ( const impl = await getProxyImplAddress(proxyAddress); await hre.tenderly.verify({ - name: registryName, + name: znsNames.registry.contract, address: impl, }); @@ -152,7 +170,7 @@ export const deployDomainToken = async ( const impl = await getProxyImplAddress(proxyAddress); await hre.tenderly.verify({ - name: domainTokenName, + name: znsNames.domainToken.contract, address: impl, }); @@ -193,7 +211,7 @@ export const deployMeowToken = async ( const impl = await getProxyImplAddress(proxyAddress); await hre.tenderly.verify({ - name: meowTokenMockName, + name: znsNames.meowToken.contractMock, address: impl, }); @@ -240,7 +258,7 @@ export const deployAddressResolver = async ( const impl = await getProxyImplAddress(proxyAddress); await hre.tenderly.verify({ - name: addressResolverName, + name: znsNames.addressResolver.contract, address: impl, }); @@ -252,6 +270,94 @@ export const deployAddressResolver = async ( return resolver as unknown as ZNSAddressResolver; }; +export const deployStringResolver = async ( + deployer : SignerWithAddress, + accessControllerAddress : string, + registryAddress : string, + isTenderlyRun : boolean, +) => { + const stringResolverFactory = new ZNSStringResolver__factory(deployer); + + const resolver = await upgrades.deployProxy( + stringResolverFactory, + [ + accessControllerAddress, + registryAddress, + ], + { + kind: "uups", + } + ); + + await resolver.waitForDeployment(); + + const proxyAddress = await resolver.getAddress(); + + if (isTenderlyRun) { + await hre.tenderly.verify({ + name: erc1967ProxyName, + address: proxyAddress, + }); + + const impl = await getProxyImplAddress(proxyAddress); + + await hre.tenderly.verify({ + name: znsNames.stringResolver.contract, + address: impl, + }); + + console.log(`ZNSStringResolver deployed at: + proxy: ${proxyAddress} + implementation: ${impl}`); + } + + return resolver as unknown as ZNSStringResolver; +}; + +export const deployChainResolver = async ( + deployer : SignerWithAddress, + accessControllerAddress : string, + registryAddress : string, + isTenderlyRun : boolean, +) => { + const chainResolverFactory = new ZNSChainResolver__factory(deployer); + + const resolver = await upgrades.deployProxy( + chainResolverFactory, + [ + accessControllerAddress, + registryAddress, + ], + { + kind: "uups", + } + ); + + await resolver.waitForDeployment(); + + const proxyAddress = await resolver.getAddress(); + + if (isTenderlyRun) { + await hre.tenderly.verify({ + name: erc1967ProxyName, + address: proxyAddress, + }); + + const impl = await getProxyImplAddress(proxyAddress); + + await hre.tenderly.verify({ + name: znsNames.chainResolver.contract, + address: impl, + }); + + console.log(`ZNSChainResolver deployed at: + proxy: ${proxyAddress} + implementation: ${impl}`); + } + + return resolver as unknown as ZNSChainResolver; +}; + export const deployCurvePricer = async ({ deployer, accessControllerAddress, @@ -292,7 +398,7 @@ export const deployCurvePricer = async ({ const impl = await getProxyImplAddress(proxyAddress); await hre.tenderly.verify({ - name: curvePricerName, + name: znsNames.curvePricer.contract, address: impl, }); @@ -344,7 +450,7 @@ export const deployTreasury = async ({ const impl = await getProxyImplAddress(proxyAddress); await hre.tenderly.verify({ - name: treasuryName, + name: znsNames.treasury.contract, address: impl, }); @@ -360,9 +466,18 @@ export const deployRootRegistrar = async ( deployer : SignerWithAddress, accessController : ZNSAccessController, config : RegistrarConfig, + srcChainName = SupportedChains.eth, isTenderlyRun : boolean -) : Promise => { - const registrarFactory = new ZNSRootRegistrar__factory(deployer); +) : Promise => { + let registrarFactory; + let name; + if (srcChainName === SupportedChains.eth) { + registrarFactory = new ZNSRootRegistrarTrunk__factory(deployer); + name = znsNames.rootRegistrar.contractTrunk; + } else { + registrarFactory = new ZNSRootRegistrarBranch__factory(deployer); + name = znsNames.rootRegistrar.contractBranch; + } const registrar = await upgrades.deployProxy( registrarFactory, @@ -392,16 +507,16 @@ export const deployRootRegistrar = async ( const impl = await getProxyImplAddress(proxyAddress); await hre.tenderly.verify({ - name: registrarName, + name, address: impl, }); - console.log(`ZNSRootRegistrar deployed at: + console.log(`${name} deployed at: proxy: ${proxyAddress} implementation: ${impl}`); } - return registrar as unknown as ZNSRootRegistrar; + return registrar as unknown as ZNSRootRegistrarTrunk | ZNSRootRegistrarBranch; }; export const deployFixedPricer = async ({ @@ -439,7 +554,7 @@ export const deployFixedPricer = async ({ const impl = await getProxyImplAddress(proxyAddress); await hre.tenderly.verify({ - name: fixedPricerName, + name: znsNames.fixedPricer.contract, address: impl, }); @@ -457,16 +572,27 @@ export const deploySubRegistrar = async ({ registry, rootRegistrar, admin, + srcChainName = SupportedChains.eth, isTenderlyRun = false, } : { deployer : SignerWithAddress; accessController : ZNSAccessController; registry : ZNSRegistry; - rootRegistrar : ZNSRootRegistrar; + rootRegistrar : ZNSRootRegistrarTrunk | ZNSRootRegistrarBranch; admin : SignerWithAddress; + srcChainName ?: TSupportedChain; isTenderlyRun ?: boolean; }) => { - const subRegistrarFactory = new ZNSSubRegistrar__factory(deployer); + let subRegistrarFactory; + let name; + if (srcChainName === SupportedChains.eth) { + subRegistrarFactory = new ZNSSubRegistrarTrunk__factory(deployer); + name = znsNames.subRegistrar.contractTrunk; + } else { + subRegistrarFactory = new ZNSSubRegistrarBranch__factory(deployer); + name = znsNames.subRegistrar.contractBranch; + } + const subRegistrar = await upgrades.deployProxy( subRegistrarFactory, [ @@ -497,16 +623,188 @@ export const deploySubRegistrar = async ({ const impl = await getProxyImplAddress(proxyAddress); await hre.tenderly.verify({ - name: subRegistrarName, + name, + address: impl, + }); + + console.log(`${name} deployed at: + proxy: ${proxyAddress} + implementation: ${impl}`); + } + + return subRegistrar as unknown as ZNSSubRegistrarTrunk | ZNSSubRegistrarBranch; +}; + +export const deployZkEvmBridgeMock = async ( + deployer : SignerWithAddress, + networkId : bigint, + bridgeTokenAddress : string, + isTenderlyRun : boolean, +) => { + const bridgeFact = new PolygonZkEVMBridgeV2Mock__factory(deployer); + + const bridge = await hre.upgrades.deployProxy( + bridgeFact, + [ + networkId, + bridgeTokenAddress, + ], + { + kind: "transparent", + } + ); + + await bridge.waitForDeployment(); + const proxyAddress = await bridge.getAddress(); + + if (isTenderlyRun) { + await hre.tenderly.verify({ + name: transparentProxyName, + address: proxyAddress, + }); + + const impl = await getProxyImplAddress(proxyAddress); + + await hre.tenderly.verify({ + name: znsNames.zkEvmBridge.contractMock, + address: impl, + }); + + console.log(`${znsNames.zkEvmBridge.contractMock} deployed at: + proxy: ${proxyAddress} + implementation: ${impl}`); + } + + return bridge as unknown as PolygonZkEVMBridgeV2Mock; +}; + +export const deployZChainPortal = async ({ + deployer, + destNetworkId, + destChainName, + destChainId, + bridgeAddress, + contractAddresses, + isTenderlyRun, +} : { + deployer : SignerWithAddress; + destNetworkId : bigint; + destChainName : TSupportedChain; + destChainId : bigint; + bridgeAddress : string; + contractAddresses : { + accessController : string; + rootRegistrar : string; + subRegistrar : string; + treasury : string; + registry : string; + chainResolver : string; + }; + isTenderlyRun : boolean; +}) => { + const factory = new ZNSZChainPortal__factory(deployer); + + const zChainPortal = await hre.upgrades.deployProxy( + factory, + [ + destNetworkId, + destChainName, + destChainId, + bridgeAddress, + contractAddresses, + ], + { + kind: "uups", + } + ); + + await zChainPortal.waitForDeployment(); + const proxyAddress = await zChainPortal.getAddress(); + + if (isTenderlyRun) { + await hre.tenderly.verify({ + name: erc1967ProxyName, + address: proxyAddress, + }); + + const impl = await getProxyImplAddress(proxyAddress); + + await hre.tenderly.verify({ + name: znsNames.zPortal.contract, address: impl, }); - console.log(`${subRegistrarName} deployed at: + console.log(`${znsNames.zPortal.contract} deployed at: proxy: ${proxyAddress} implementation: ${impl}`); } - return subRegistrar as unknown as ZNSSubRegistrar; + return zChainPortal as unknown as ZNSZChainPortal; +}; + +export const deployEthPortal = async ({ + deployer, + accessController, + zkEvmBridgeAddress, + srcZnsPortalAddress, + registryAddress, + domainTokenAddress, + rootRegistrarAddress, + subRegistrarAddress, + isTenderlyRun, +} : { + deployer : SignerWithAddress; + accessController : ZNSAccessController; + zkEvmBridgeAddress : string; + srcZnsPortalAddress : string; + registryAddress : string; + domainTokenAddress : string; + rootRegistrarAddress : string; + subRegistrarAddress : string; + isTenderlyRun : boolean; +}) => { + const factory = new ZNSEthereumPortal__factory(deployer); + + const ethPortal = await hre.upgrades.deployProxy( + factory, + [ + accessController.target, + zkEvmBridgeAddress, + srcZnsPortalAddress, + registryAddress, + domainTokenAddress, + rootRegistrarAddress, + subRegistrarAddress, + ], + { + kind: "uups", + } + ); + + await ethPortal.waitForDeployment(); + const proxyAddress = await ethPortal.getAddress(); + + await accessController.connect(deployer).grantRole(PORTAL_ROLE, proxyAddress); + + if (isTenderlyRun) { + await hre.tenderly.verify({ + name: erc1967ProxyName, + address: proxyAddress, + }); + + const impl = await getProxyImplAddress(proxyAddress); + + await hre.tenderly.verify({ + name: znsNames.ethPortal.contract, + address: impl, + }); + + console.log(`${znsNames.ethPortal.contract} deployed at: + proxy: ${proxyAddress} + implementation: ${impl}`); + } + + return ethPortal as unknown as ZNSEthereumPortal; }; /** @@ -521,6 +819,13 @@ export const deployZNS = async ({ adminAddresses, priceConfig = DEFAULT_PRICE_CONFIG, zeroVaultAddress = deployer.address, + srcChainName = SupportedChains.eth, + srcNetworkId = NETWORK_ID_L1_TEST_DEFAULT, + bridgeTokenAddress = ethers.ZeroAddress, + destNetworkId = NETWORK_ID_L2_TEST_DEFAULT, + destChainName = SupportedChains.z, + destChainId = ZCHAIN_ID_TEST_DEFAULT, + srcZnsPortalAddress = ethers.ZeroAddress, isTenderlyRun = false, } : DeployZNSParams) : Promise => { // We deploy every contract as a UUPS proxy, but ZERO is already @@ -567,6 +872,13 @@ export const deployZNS = async ({ isTenderlyRun ); + const stringResolver = await deployStringResolver( + deployer, + await accessController.getAddress(), + await registry.getAddress(), + isTenderlyRun + ); + const curvePricer = await deployCurvePricer({ deployer, accessControllerAddress: await accessController.getAddress(), @@ -595,6 +907,7 @@ export const deployZNS = async ({ deployer, accessController, config, + srcChainName, isTenderlyRun ); @@ -614,17 +927,69 @@ export const deployZNS = async ({ isTenderlyRun, }); + const chainResolver = await deployChainResolver( + deployer, + await accessController.getAddress(), + await registry.getAddress(), + isTenderlyRun + ); + + const zkEvmBridge = await deployZkEvmBridgeMock( + deployer, + srcNetworkId, + bridgeTokenAddress, + isTenderlyRun + ); + + let zChainPortal; + let ethPortal; + if (srcChainName === SupportedChains.eth) { + zChainPortal = await deployZChainPortal({ + deployer, + destNetworkId, + destChainName, + destChainId, + bridgeAddress: await zkEvmBridge.getAddress(), + contractAddresses: { + accessController: await accessController.getAddress(), + rootRegistrar: await rootRegistrar.getAddress(), + subRegistrar: await subRegistrar.getAddress(), + treasury: await treasury.getAddress(), + registry: await registry.getAddress(), + chainResolver: await chainResolver.getAddress(), + }, + isTenderlyRun, + }); + } else { + ethPortal = await deployEthPortal({ + deployer, + accessController, + zkEvmBridgeAddress: await zkEvmBridge.getAddress(), + srcZnsPortalAddress, + registryAddress: await registry.getAddress(), + domainTokenAddress: await domainToken.getAddress(), + rootRegistrarAddress: await rootRegistrar.getAddress(), + subRegistrarAddress: await subRegistrar.getAddress(), + isTenderlyRun, + }); + } + const znsContracts : IZNSContractsLocal = { accessController, registry, domainToken, meowToken: meowTokenMock, addressResolver, + stringResolver, curvePricer, treasury, rootRegistrar, fixedPricer, subRegistrar, + chainResolver, + zkEvmBridge, + zChainPortal, + ethPortal, zeroVaultAddress, }; diff --git a/test/helpers/register-setup.ts b/test/helpers/register-setup.ts index a87d4c94d..2cbed2b40 100644 --- a/test/helpers/register-setup.ts +++ b/test/helpers/register-setup.ts @@ -93,7 +93,7 @@ export const approveForDomain = async ({ await tx.wait(confNum); } - const spender = isBridging ? await zns.zPortal.getAddress() : await zns.treasury.getAddress(); + const spender = isBridging ? await zns.zChainPortal.getAddress() : await zns.treasury.getAddress(); const tx = await tokenContract.connect(user).approve(spender, toApprove); await tx.wait(confNum); }; @@ -151,7 +151,7 @@ export const defaultBridgingRegistration = async ({ domainLabel : string; tokenURI ?: string; }) => { - const tx = await zns.zPortal.connect(user).registerAndBridgeDomain( + const tx = await zns.zChainPortal.connect(user).registerAndBridgeDomain( parentHash, domainLabel, tokenURI From ac0cebdbff7f603f5dab432ecee674eee2d16e10 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Fri, 22 Nov 2024 15:57:25 -0800 Subject: [PATCH 109/124] wrap all calls in DMs and HardhatDeployer in a temporary wrapper that determines the amount of confirmations and waits for them when running on actual networks [temp solution] --- .../registrar/IZNSRootRegistrarTypes.sol | 1 + .../contracts/cross-chain/chain-resolver.ts | 9 ++- .../cross-chain/portals/eth-portal.ts | 9 ++- .../contracts/cross-chain/zk-evm-bridge.ts | 59 +++++++++++++-- .../contracts/zns-base/address-resolver.ts | 12 +++- .../zns-base/meow-token/meow-token.ts | 25 +++++-- .../contracts/zns-base/root-registrar.ts | 9 ++- .../contracts/zns-base/string-resolver.ts | 9 ++- .../contracts/zns-base/sub-registrar.ts | 13 ++-- src/deploy/zns-campaign.ts | 72 ++++++++++++++++++- 10 files changed, 186 insertions(+), 32 deletions(-) diff --git a/contracts/registrar/IZNSRootRegistrarTypes.sol b/contracts/registrar/IZNSRootRegistrarTypes.sol index 45f8f55a4..e7ff4db18 100644 --- a/contracts/registrar/IZNSRootRegistrarTypes.sol +++ b/contracts/registrar/IZNSRootRegistrarTypes.sol @@ -52,6 +52,7 @@ interface IZNSRootRegistrarTypes is IDistributionConfig { * @param registrant The address that called `ZNSRootRegistrar.registerRootDomain()` * @param domainAddress The domain address of the domain registered */ + // TODO multi: make parentHash indexed instead of tokenId !!! event DomainRegistered( bytes32 parentHash, bytes32 indexed domainHash, diff --git a/src/deploy/missions/contracts/cross-chain/chain-resolver.ts b/src/deploy/missions/contracts/cross-chain/chain-resolver.ts index 85c1d2291..15a17b5e7 100644 --- a/src/deploy/missions/contracts/cross-chain/chain-resolver.ts +++ b/src/deploy/missions/contracts/cross-chain/chain-resolver.ts @@ -4,6 +4,7 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { ProxyKinds, ResolverTypes } from "../../../constants"; import { znsNames } from "../names"; +import { executeWithConfirmation } from "../../../zns-campaign"; export class ZNSChainResolverDM extends BaseDeployMission< @@ -56,9 +57,11 @@ IZNSContracts }, } = this.campaign; - await registry.connect(deployAdmin).addResolverType( - ResolverTypes.chain, - await chainResolver.getAddress(), + await executeWithConfirmation( + registry.connect(deployAdmin).addResolverType( + ResolverTypes.chain, + await chainResolver.getAddress(), + ) ); this.logger.debug(`${this.contractName} post deploy sequence completed`); diff --git a/src/deploy/missions/contracts/cross-chain/portals/eth-portal.ts b/src/deploy/missions/contracts/cross-chain/portals/eth-portal.ts index dd4b49d85..195e74109 100644 --- a/src/deploy/missions/contracts/cross-chain/portals/eth-portal.ts +++ b/src/deploy/missions/contracts/cross-chain/portals/eth-portal.ts @@ -4,6 +4,7 @@ import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { IZNSCampaignConfig, IZNSContracts, IZNSZChainCrossConfig } from "../../../../campaign/types"; import { PORTAL_ROLE, ProxyKinds } from "../../../../constants"; import { znsNames } from "../../names"; +import { executeWithConfirmation } from "../../../../zns-campaign"; export class ZNSEthereumPortalDM extends BaseDeployMission< @@ -75,9 +76,11 @@ IZNSContracts config: { deployAdmin }, } = this.campaign; - await accessController.connect(deployAdmin).grantRole( - PORTAL_ROLE, - ethPortal.target + await executeWithConfirmation( + accessController.connect(deployAdmin).grantRole( + PORTAL_ROLE, + ethPortal.target + ) ); this.logger.debug(`${this.contractName} post deploy sequence completed`); diff --git a/src/deploy/missions/contracts/cross-chain/zk-evm-bridge.ts b/src/deploy/missions/contracts/cross-chain/zk-evm-bridge.ts index 60499f2c0..21e7b427d 100644 --- a/src/deploy/missions/contracts/cross-chain/zk-evm-bridge.ts +++ b/src/deploy/missions/contracts/cross-chain/zk-evm-bridge.ts @@ -1,10 +1,10 @@ -import { BaseDeployMission, IDeployMissionArgs, TDeployArgs } from "@zero-tech/zdc"; +import { BaseDeployMission, IContractArtifact, IDeployMissionArgs, TDeployArgs } from "@zero-tech/zdc"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; import { ProxyKinds } from "../../../constants"; import { znsNames } from "../names"; -import { ethers } from "ethers"; +import { ethers, Interface } from "ethers"; export class PolygonZkEVMBridgeV2DM extends BaseDeployMission< @@ -44,12 +44,15 @@ IZNSContracts this.logger.info("Using PolygonZkEvmBridgeV2 deployed on chain"); - if (!zkEvmBridgeAddress) throw new Error("No existing ZkEvmBridge address has been passed!"); + if (!zkEvmBridgeAddress) + throw new Error("No existing ZkEvmBridge address has been passed to the campaign config!"); this.logger.debug(`Writing ${this.contractName} to DB...`); - const factory = await this.campaign.deployer.getFactory(this.contractName); - const contract = factory.attach(zkEvmBridgeAddress); + // TODO multi: + // const factory = await this.campaign.deployer.getFactory(this.contractName); + // const contract = factory.attach(zkEvmBridgeAddress); + const contract = this.getContractObject(zkEvmBridgeAddress); await this.saveToDB(contract); @@ -62,6 +65,52 @@ IZNSContracts } } + getContractObject (address : string) { + // TODO multi: make this better when figured out how to compile the Bridge !!! + + const { abi } = this.getArtifact(); + // TODO multi: fix this ! + const contract = new ethers.Contract(address, abi as unknown as Interface, this.campaign.config.deployAdmin); + + return contract; + } + + // TODO multi: make this better !!! maybe add a new getContractObject() method to BaseDeployMission for this !!! + async needsDeploy () { + const dbContract = await this.getFromDB(); + + if (!dbContract) { + this.logger.info(`${this.dbName} not found in DB, proceeding to deploy...`); + } else { + this.logger.info(`${this.dbName} found in DB at ${dbContract.address}, no deployment needed.`); + + const contract = this.getContractObject(dbContract.address); + + // eslint-disable-next-line max-len + this.logger.debug(`Updating ${this.contractName} in state from DB data with address ${await contract.getAddress()}`); + + this.campaign.updateStateContract(this.instanceName, this.contractName, contract); + } + + return !dbContract; + } + + async verify () { + if (!this.config.crosschain.mockZkEvmBridge) { + this.logger.info("Skipping verification for PolygonZkEvmBridge since it's already verified."); + return; + } + + await super.verify(); + } + + // TODO multi: make this better !!! + getArtifact () : IContractArtifact { + return require( + `${process.cwd()}/node_modules/@zero-tech/zkevm-contracts/compiled-contracts/PolygonZkEVMBridgeV2.json` + ); + } + async deployArgs () : Promise { // this is ONLY for the Mock version of the Bridge ! const { diff --git a/src/deploy/missions/contracts/zns-base/address-resolver.ts b/src/deploy/missions/contracts/zns-base/address-resolver.ts index 70c9bb25c..2d580f6d5 100644 --- a/src/deploy/missions/contracts/zns-base/address-resolver.ts +++ b/src/deploy/missions/contracts/zns-base/address-resolver.ts @@ -7,6 +7,7 @@ import { znsNames } from "../names"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; +import { executeWithConfirmation } from "../../../zns-campaign"; export class ZNSAddressResolverDM extends BaseDeployMission< @@ -56,9 +57,14 @@ IZNSContracts }, } = this.campaign; - await registry.connect(deployAdmin).addResolverType( - ResolverTypes.address, - await addressResolver.getAddress(), + // TODO multi: wrap this in a tx runner that will wait for every tx if not on "dev" + // amount of confirmations should be a var passed to the config! + // do this for all DMs here after the zDC code is changed! + await executeWithConfirmation( + registry.connect(deployAdmin).addResolverType( + ResolverTypes.address, + await addressResolver.getAddress() + ) ); this.logger.debug(`${this.contractName} post deploy sequence completed`); diff --git a/src/deploy/missions/contracts/zns-base/meow-token/meow-token.ts b/src/deploy/missions/contracts/zns-base/meow-token/meow-token.ts index 3b4017768..aaf8e8805 100644 --- a/src/deploy/missions/contracts/zns-base/meow-token/meow-token.ts +++ b/src/deploy/missions/contracts/zns-base/meow-token/meow-token.ts @@ -11,6 +11,7 @@ import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { IZNSCampaignConfig, IZNSContracts } from "../../../../campaign/types"; import { MeowToken__factory } from "@zero-tech/ztoken/typechain-js"; import meowArtifact from "@zero-tech/ztoken/artifacts/contracts/MeowToken.sol/MeowToken.json"; +import { executeWithConfirmation } from "../../../../zns-campaign"; export const meowTokenName = "MEOW"; @@ -87,11 +88,23 @@ IZNSContracts } async needsPostDeploy () { - const msg = this.config.mockMeowToken ? "needs" : "doesn't need"; + const { + meowToken, + config: { + deployAdmin, + mockMeowToken, + }, + } = this.campaign; + + const balance = await meowToken.balanceOf(deployAdmin.address); + + const needs = mockMeowToken && balance === 0n; + + const msg = needs ? "needs" : "doesn't need"; this.logger.debug(`${this.contractName} ${msg} post deploy sequence`); - return this.config.mockMeowToken ; + return needs; } async postDeploy () { @@ -103,9 +116,11 @@ IZNSContracts } = this.campaign; // Mint 100,000 MEOW to the deployer - await meowToken.connect(deployAdmin).mint( - await deployAdmin.getAddress?.(), - ethers.parseEther("100000") + await executeWithConfirmation( + meowToken.connect(deployAdmin).mint( + await deployAdmin.getAddress(), + ethers.parseEther("100000"), + ) ); this.logger.debug(`${this.contractName} post deploy sequence completed`); diff --git a/src/deploy/missions/contracts/zns-base/root-registrar.ts b/src/deploy/missions/contracts/zns-base/root-registrar.ts index 7f7f9c768..3a26d1e75 100644 --- a/src/deploy/missions/contracts/zns-base/root-registrar.ts +++ b/src/deploy/missions/contracts/zns-base/root-registrar.ts @@ -8,6 +8,7 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; import { SupportedChains } from "../cross-chain/portals/get-portal-dm"; +import { executeWithConfirmation } from "../../../zns-campaign"; export class ZNSRootRegistrarDM extends BaseDeployMission< @@ -87,9 +88,11 @@ IZNSContracts }, } = this.campaign; - await accessController - .connect(deployAdmin) - .grantRole(REGISTRAR_ROLE, await rootRegistrar.getAddress()); + await executeWithConfirmation( + accessController + .connect(deployAdmin) + .grantRole(REGISTRAR_ROLE, await rootRegistrar.getAddress()) + ); this.logger.debug(`${this.contractName} post deploy sequence completed`); } diff --git a/src/deploy/missions/contracts/zns-base/string-resolver.ts b/src/deploy/missions/contracts/zns-base/string-resolver.ts index 9e2296731..142c54d68 100644 --- a/src/deploy/missions/contracts/zns-base/string-resolver.ts +++ b/src/deploy/missions/contracts/zns-base/string-resolver.ts @@ -4,6 +4,7 @@ import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; import { ProxyKinds, ResolverTypes } from "../../../constants"; import { znsNames } from "../names"; +import { executeWithConfirmation } from "../../../zns-campaign"; export class ZNSStringResolverDM extends BaseDeployMission< @@ -56,9 +57,11 @@ IZNSContracts }, } = this.campaign; - await registry.connect(deployAdmin).addResolverType( - ResolverTypes.string, - await stringResolver.getAddress(), + await executeWithConfirmation( + registry.connect(deployAdmin).addResolverType( + ResolverTypes.string, + await stringResolver.getAddress(), + ) ); this.logger.debug(`${this.contractName} post deploy sequence completed`); diff --git a/src/deploy/missions/contracts/zns-base/sub-registrar.ts b/src/deploy/missions/contracts/zns-base/sub-registrar.ts index af3c8d0e2..a55d59d29 100644 --- a/src/deploy/missions/contracts/zns-base/sub-registrar.ts +++ b/src/deploy/missions/contracts/zns-base/sub-registrar.ts @@ -8,6 +8,7 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; import { SupportedChains } from "../cross-chain/portals/get-portal-dm"; +import { executeWithConfirmation } from "../../../zns-campaign"; export class ZNSSubRegistrarDM extends BaseDeployMission< @@ -95,13 +96,17 @@ IZNSContracts } = this.campaign; if (!this.isSetOnRoot) { - await rootRegistrar.connect(deployAdmin).setSubRegistrar(await subRegistrar.getAddress()); + await executeWithConfirmation( + rootRegistrar.connect(deployAdmin).setSubRegistrar(await subRegistrar.getAddress()) + ); } if (!this.hasRegistrarRole) { - await accessController - .connect(deployAdmin) - .grantRole(REGISTRAR_ROLE, await subRegistrar.getAddress()); + await executeWithConfirmation( + accessController + .connect(deployAdmin) + .grantRole(REGISTRAR_ROLE, await subRegistrar.getAddress()) + ); } this.logger.debug(`${this.contractName} post deploy sequence completed`); diff --git a/src/deploy/zns-campaign.ts b/src/deploy/zns-campaign.ts index 39cff28a7..1766cac3e 100644 --- a/src/deploy/zns-campaign.ts +++ b/src/deploy/zns-campaign.ts @@ -3,7 +3,7 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; import { HardhatDeployer, DeployCampaign, - getLogger, + getLogger, IHardhatDeployerArgs, TDeployArgs, TProxyKind, IContractV6, } from "@zero-tech/zdc"; import { MeowTokenDM, @@ -17,14 +17,79 @@ import { IZNSCampaignConfig, IZNSContracts } from "./campaign/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { getZnsMongoAdapter } from "./mongo"; import { getPortalDM } from "./missions/contracts/cross-chain/portals/get-portal-dm"; +import { ContractTransactionResponse, Wallet } from "ethers"; +import { getConfirmationsNumber } from "../../test/helpers/tx"; +export const executeWithConfirmation = async ( + tx : Promise, + confNum ?: number, +) => { + confNum = confNum ?? getConfirmationsNumber(); + const txRes = await tx; + return txRes.wait(confNum); +}; + +// TODO multi: move this or change zDC code to include this !! +class HardhatDeployerWrapper extends HardhatDeployer { + constructor ({ + hre, + signer, + env, + } : IHardhatDeployerArgs) { + super({ + hre, + signer, + env, + }); + } + + async deployProxy ({ + contractName, + args, + kind, + } : { + contractName : string; + args : TDeployArgs; + kind : TProxyKind; + }) : Promise { + const contract = await super.deployProxy({ + contractName, + args, + kind, + }); + + if (this.env !== "dev") { + // TODO multi: fix this in zDC since there is a wrong type in IContractV6 for this method + const deployTx = contract.deploymentTransaction() as ContractTransactionResponse; + // TODO multi: make the amount of blocks a var passed to deployed by the config ?? + if (deployTx) await deployTx.wait(2); + } + + return contract; + } + + async deployContract (contractName : string, args : TDeployArgs) : Promise { + const contract = await super.deployContract(contractName, args); + + if (this.env !== "dev") { + // TODO multi: fix this in zDC since there is a wrong type in IContractV6 for this method + const deployTx = contract.deploymentTransaction() as ContractTransactionResponse; + // TODO multi: make the amount of blocks a var passed to deployed by the config ?? + // this may be needed to be higher than 2 in times of network congestion + if (deployTx) await deployTx.wait(2); + } + + return contract; + } +} + export const runZnsCampaign = async ({ config, dbVersion, deployer, } : { - config : IZNSCampaignConfig; + config : IZNSCampaignConfig; dbVersion ?: string; deployer ?: HardhatDeployer; }) => { @@ -33,7 +98,8 @@ export const runZnsCampaign = async ({ const logger = getLogger(); if (!deployer) { - deployer = new HardhatDeployer({ + // TODO multi: change this when finalized ! + deployer = new HardhatDeployerWrapper({ hre, signer: config.deployAdmin, env: config.env, From e6057481661aceaee25e23b19fcda3e607b38d7e Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Fri, 22 Nov 2024 15:57:50 -0800 Subject: [PATCH 110/124] fix all tests --- test/DeployCampaignInt.test.ts | 58 ++++++++++++------- test/ZNSRootRegistrar.test.ts | 14 ++--- test/ZNSStringResolver.test.ts | 6 +- test/ZNSSubRegistrar.test.ts | 8 +-- .../CrossChainDomainBridging.network.test.ts | 56 +++++++++--------- test/cross-chain/ZNSDeploy.test.ts | 14 ++--- 6 files changed, 85 insertions(+), 71 deletions(-) diff --git a/test/DeployCampaignInt.test.ts b/test/DeployCampaignInt.test.ts index 5c8bd3b9d..113364efe 100644 --- a/test/DeployCampaignInt.test.ts +++ b/test/DeployCampaignInt.test.ts @@ -27,9 +27,9 @@ import { import { MeowTokenDM, meowTokenName, - meowTokenSymbol, + meowTokenSymbol, PolygonZkEVMBridgeV2DM, ZNSAccessControllerDM, - ZNSAddressResolverDM, + ZNSAddressResolverDM, ZNSChainResolverDM, ZNSCurvePricerDM, ZNSDomainTokenDM, ZNSFixedPricerDM, ZNSRegistryDM, ZNSRootRegistrarDM, ZNSSubRegistrarDM, ZNSTreasuryDM, @@ -39,14 +39,15 @@ import { znsNames } from "../src/deploy/missions/contracts/names"; import { runZnsCampaign } from "../src/deploy/zns-campaign"; import { MeowMainnet } from "../src/deploy/missions/contracts/zns-base/meow-token/mainnet-data"; import { ResolverTypes } from "../src/deploy/constants"; -import { getConfig } from "../src/deploy/campaign/environments"; -import { ethers } from "ethers"; +import { buildCrosschainConfig, getConfig } from "../src/deploy/campaign/environments"; +import { ethers, Wallet } from "ethers"; import { promisify } from "util"; import { exec } from "child_process"; import { saveTag } from "../src/utils/git-tag/save-tag"; import { IZNSCampaignConfig, IZNSContracts } from "../src/deploy/campaign/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { getZnsMongoAdapter } from "../src/deploy/mongo"; +import { getPortalDM } from "../src/deploy/missions/contracts/cross-chain/portals/get-portal-dm"; const execAsync = promisify(exec); @@ -92,6 +93,7 @@ describe("Deploy Campaign Test", () => { monitorContracts: false, verifyContracts: false, }, + crosschain: buildCrosschainConfig(), }; }); @@ -204,8 +206,8 @@ describe("Deploy Campaign Test", () => { IZNSContracts >>; placeOfFailure : string; - deployedNames : Array<{ contract : string; instance : string; }>; - undeployedNames : Array<{ contract : string; instance : string; }>; + deployedNames : Array<{ contract ?: string; contractTrunk ?: string; instance : string; }>; + undeployedNames : Array<{ contract ?: string; contractTrunk ?: string; instance : string; }>; failingInstanceName : string; // eslint-disable-next-line no-shadow callback ?: (failingCampaign : DeployCampaign< @@ -267,13 +269,14 @@ describe("Deploy Campaign Test", () => { const firstRunDeployed = await deployedNames.reduce( async ( acc : Promise>, - { contract, instance } : { contract : string; instance : string; } + { contract, contractTrunk, instance } : { contract ?: string; contractTrunk ?: string; instance : string; } ) : Promise> => { const akk = await acc; - const fromDB = await dbAdapter.getContract(contract); + const name = contract ?? contractTrunk; + const fromDB = await dbAdapter.getContract(name as string); expect(fromDB?.address).to.be.properAddress; - return [...akk, { contract, instance, address: fromDB?.address }]; + return [...akk, { contract: name as string, instance, address: fromDB?.address }]; }, Promise.resolve([]) ); @@ -281,10 +284,11 @@ describe("Deploy Campaign Test", () => { await undeployedNames.reduce( async ( acc : Promise, - { contract, instance } : { contract : string; instance : string; } + { contract, contractTrunk, instance } : { contract ?: string; contractTrunk ?: string; instance : string; } ) : Promise => { await acc; - const fromDB = await dbAdapter.getContract(contract); + const name = contract ?? contractTrunk; + const fromDB = await dbAdapter.getContract(name as string); const fromState = failingCampaign[instance]; expect(fromDB).to.be.null; @@ -314,9 +318,9 @@ describe("Deploy Campaign Test", () => { // state should have 11 contracts in it const { state } = nextCampaign; - expect(Object.keys(state.contracts).length).to.equal(11); - expect(Object.keys(state.instances).length).to.equal(11); - expect(state.missions.length).to.equal(11); + expect(Object.keys(state.contracts).length).to.equal(14); + expect(Object.keys(state.instances).length).to.equal(14); + expect(state.missions.length).to.equal(14); // it should deploy AddressResolver expect(await state.contracts.addressResolver.getAddress()).to.be.properAddress; @@ -326,10 +330,11 @@ describe("Deploy Campaign Test", () => { await allNames.reduce( async ( acc : Promise, - { contract } : { contract : string; } + { contract, contractTrunk } : { contract ?: string; contractTrunk ?: string; } ) : Promise => { await acc; - const fromDB = await dbAdapter.getContract(contract); + const name = contract ?? contractTrunk; + const fromDB = await dbAdapter.getContract(name as string); expect(fromDB?.address).to.be.properAddress; }, Promise.resolve() @@ -371,7 +376,6 @@ describe("Deploy Campaign Test", () => { }, rootPriceConfig: DEFAULT_PRICE_CONFIG, zeroVaultAddress: zeroVault.address, - // TODO dep: what do we pass here for test flow? we don't have a deployed MeowToken contract stakingTokenAddress: "", mockMeowToken: true, // 1700083028872 postDeploy: { @@ -379,6 +383,7 @@ describe("Deploy Campaign Test", () => { monitorContracts: false, verifyContracts: false, }, + crosschain: buildCrosschainConfig(), }; mongoAdapter = await getZnsMongoAdapter({ @@ -417,6 +422,12 @@ describe("Deploy Campaign Test", () => { znsNames.rootRegistrar, znsNames.fixedPricer, znsNames.subRegistrar, + znsNames.chainResolver, + { + contract: znsNames.zkEvmBridge.contractMock, + instance: znsNames.zkEvmBridge.instance, + }, + znsNames.zPortal, ]; // call test flow runner @@ -431,8 +442,11 @@ describe("Deploy Campaign Test", () => { ZNSCurvePricerDM, ZNSTreasuryDM, ZNSRootRegistrarDM, - ZNSFixedPricerDM, ZNSSubRegistrarDM, + ZNSFixedPricerDM, + ZNSChainResolverDM, + PolygonZkEVMBridgeV2DM, + getPortalDM(campaignConfig.crosschain.srcChainName), ], placeOfFailure: "deploy", deployedNames, @@ -657,7 +671,7 @@ describe("Deploy Campaign Test", () => { // for the environment specifically, that is ever only inferred from the `process.env.ENV_LEVEL` it("Gets the default configuration correctly", async () => { // set the environment to get the appropriate variables - const localConfig : IZNSCampaignConfig = await getConfig({ + const localConfig : IZNSCampaignConfig = await getConfig({ deployer: deployAdmin, zeroVaultAddress: zeroVault.address, governors: [governor.address], @@ -689,7 +703,7 @@ describe("Deploy Campaign Test", () => { let zns : IZNSContracts; - const config : IZNSCampaignConfig = await getConfig({ + const config : IZNSCampaignConfig = await getConfig({ deployer: userB, zeroVaultAddress: userA.address, governors: [userB.address, admin.address], // governors @@ -838,7 +852,7 @@ describe("Deploy Campaign Test", () => { }); /* eslint-disable @typescript-eslint/no-explicit-any */ } catch (e : any) { - expect(e.message).includes("Must provide a Mongo URI used for prod environment!"); + expect(e.message).includes("Missing required environment variables: MONGO_DB_URI"); } process.env.MOCK_MEOW_TOKEN = "false"; @@ -892,6 +906,7 @@ describe("Deploy Campaign Test", () => { monitorContracts: false, verifyContracts: false, }, + crosschain: buildCrosschainConfig(), }; campaign = await runZnsCampaign({ @@ -1073,6 +1088,7 @@ describe("Deploy Campaign Test", () => { monitorContracts: false, verifyContracts: true, }, + crosschain: buildCrosschainConfig(), }; }); diff --git a/test/ZNSRootRegistrar.test.ts b/test/ZNSRootRegistrar.test.ts index db5b4e0bc..b7ddaea0c 100644 --- a/test/ZNSRootRegistrar.test.ts +++ b/test/ZNSRootRegistrar.test.ts @@ -35,7 +35,7 @@ import { ADMIN_ROLE, GOVERNOR_ROLE } from "../src/deploy/constants"; import { IERC20, ZNSRootRegistrar, - ZNSRootRegistrar__factory, + ZNSRootRegistrar__factory, ZNSRootRegistrarTrunk, ZNSRootRegistrarTrunk__factory, ZNSRootRegistrarUpgradeMock__factory, } from "../typechain"; import { PaymentConfigStruct } from "../typechain/contracts/treasury/IZNSTreasury"; @@ -51,6 +51,7 @@ require("@nomicfoundation/hardhat-chai-matchers"); // This is the only test converted to use the new Campaign, other // contract specific tests are using `deployZNS()` helper +// TODO multi: test both RootRegistrar types here, add missing tests for Branch and fix types !!! describe("ZNSRootRegistrar", () => { let deployer : SignerWithAddress; let user : SignerWithAddress; @@ -206,10 +207,9 @@ describe("ZNSRootRegistrar", () => { }); it("Should NOT initialize the implementation contract", async () => { - const factory = new ZNSRootRegistrar__factory(deployer); + const factory = new ZNSRootRegistrarTrunk__factory(deployer); const impl = await getProxyImplAddress(await zns.rootRegistrar.getAddress()); - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - const implContract = factory.attach(impl) as ZNSRootRegistrar; + const implContract = factory.attach(impl) as ZNSRootRegistrarTrunk; await expect( implContract.initialize( @@ -292,7 +292,7 @@ describe("ZNSRootRegistrar", () => { const userHasAdmin = await zns.accessController.hasRole(ADMIN_ROLE, user.address); expect(userHasAdmin).to.be.false; - const registrarFactory = new ZNSRootRegistrar__factory(user); + const registrarFactory = new ZNSRootRegistrarTrunk__factory(user); const tx = upgrades.deployProxy( registrarFactory, @@ -1386,7 +1386,7 @@ describe("ZNSRootRegistrar", () => { // Confirm deployer has the correct role first await expect(zns.accessController.checkGovernor(deployer.address)).to.not.be.reverted; - const registrarFactory = new ZNSRootRegistrar__factory(deployer); + const registrarFactory = new ZNSRootRegistrarTrunk__factory(deployer); const registrar = await registrarFactory.deploy(); await registrar.waitForDeployment(); @@ -1398,7 +1398,7 @@ describe("ZNSRootRegistrar", () => { }); it("Fails to upgrade when an unauthorized users calls", async () => { - const registrarFactory = new ZNSRootRegistrar__factory(deployer); + const registrarFactory = new ZNSRootRegistrarTrunk__factory(deployer); const registrar = await registrarFactory.deploy(); await registrar.waitForDeployment(); diff --git a/test/ZNSStringResolver.test.ts b/test/ZNSStringResolver.test.ts index 13d6f19d8..a026aa422 100644 --- a/test/ZNSStringResolver.test.ts +++ b/test/ZNSStringResolver.test.ts @@ -256,6 +256,10 @@ describe("ZNSStringResolver", () => { await meowToken.connect(deployer).approve(await treasury.getAddress(), ethers.MaxUint256); }); + afterEach(async () => { + await mongoAdapter.dropDB(); + }); + it("Should not allow non-owner address to setString (similar domain and string)", async () => { const curStringDomain = "shouldbrake"; @@ -442,4 +446,4 @@ describe("ZNSStringResolver", () => { }); }); }); -}); \ No newline at end of file +}); diff --git a/test/ZNSSubRegistrar.test.ts b/test/ZNSSubRegistrar.test.ts index 4fd14a25b..04e2e0598 100644 --- a/test/ZNSSubRegistrar.test.ts +++ b/test/ZNSSubRegistrar.test.ts @@ -36,9 +36,9 @@ import { defaultSubdomainRegistration, registrationWithSetup } from "./helpers/r import { getDomainHashFromEvent } from "./helpers/events"; import { time } from "@nomicfoundation/hardhat-toolbox/network-helpers"; import { - CustomDecimalTokenMock, + CustomDecimalTokenMock, ZNSRootRegistrarTrunk__factory, ZNSSubRegistrar, - ZNSSubRegistrar__factory, + ZNSSubRegistrar__factory, ZNSSubRegistrarTrunk, ZNSSubRegistrarTrunk__factory, ZNSSubRegistrarUpgradeMock, ZNSSubRegistrarUpgradeMock__factory, } from "../typechain"; @@ -3386,9 +3386,9 @@ describe("ZNSSubRegistrar", () => { }); it("Should NOT let initialize the implementation contract", async () => { - const factory = new ZNSSubRegistrar__factory(deployer); + const factory = new ZNSSubRegistrarTrunk__factory(deployer); const impl = await getProxyImplAddress(await zns.subRegistrar.getAddress()); - const implContract = factory.attach(impl) as ZNSSubRegistrar; + const implContract = factory.attach(impl) as ZNSSubRegistrarTrunk; await expect( implContract.initialize( diff --git a/test/cross-chain/CrossChainDomainBridging.network.test.ts b/test/cross-chain/CrossChainDomainBridging.network.test.ts index 43e69591d..4e0eb060c 100644 --- a/test/cross-chain/CrossChainDomainBridging.network.test.ts +++ b/test/cross-chain/CrossChainDomainBridging.network.test.ts @@ -37,7 +37,7 @@ import assert from "assert"; import { getConfirmationsNumber } from "../helpers/tx"; import { getClaimArgsFromApi } from "../helpers/cc-claim"; import { NETWORK_ID_L1_TEST_DEFAULT, NETWORK_ID_L2_TEST_DEFAULT, ZCHAIN_ID_TEST_DEFAULT } from "./ZNSDeploy.test"; -import { resetEnvVars } from "../helpers/env"; +import { setDefaultEnvironment } from "../../src/environment/set-env"; // TODO multi: add ChainResolver tests !!! @@ -146,7 +146,7 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => if (!isRealNetwork) { // set vars for ZChain ZNS deployment - process.env.SRC_ZNS_PORTAL = znsL1.zPortal.target as string; + process.env.SRC_ZNS_PORTAL = znsL1.zChainPortal.target as string; process.env.NETWORK_ID = NETWORK_ID_L2_TEST_DEFAULT.toString(); process.env.MONGO_DB_NAME = "zns-l2"; // TODO multi: create zkEVM bridge tests for predeployed bridge !!! @@ -159,7 +159,7 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => userL2 = new ethers.Wallet(`0x${process.env.TESTNET_PRIVATE_KEY_B}`, zChainProvider); subUserL2 = new ethers.Wallet(`0x${process.env.TESTNET_PRIVATE_KEY_C}`, zChainProvider); // swap to another DB where L2 contracts are located - process.env.MONGO_DB_NAME = process.env.MONGO_DB_NAME_DEST; + process.env.MONGO_DB_NAME = process.env.MONGO_DB_NAME_DEST as string; process.env.MONGO_DB_VERSION = process.env.MONGO_DB_VERSION_DEST; } @@ -181,16 +181,16 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => }); after(async () => { - resetEnvVars(); await dbAdapter1.dropDB(); await dbAdapter2.dropDB(); + setDefaultEnvironment(); }); it("#registerAndBridgeDomain() should revert if `destZnsPortal` is not set", async () => { - const curPortal = await znsL1.zPortal.destZnsPortal(); + const curPortal = await znsL1.zChainPortal.destZnsPortal(); if (curPortal !== hre.ethers.ZeroAddress) { - await znsL1.zPortal.connect(deployAdmin).setDestZnsPortal(hre.ethers.ZeroAddress); + await znsL1.zChainPortal.connect(deployAdmin).setDestZnsPortal(hre.ethers.ZeroAddress); } await approveForDomain({ @@ -202,16 +202,16 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => }); await expect( - znsL1.zPortal.connect(user).registerAndBridgeDomain( + znsL1.zChainPortal.connect(user).registerAndBridgeDomain( hre.ethers.ZeroHash, "test", DEFAULT_TOKEN_URI, ) - ).to.be.revertedWithCustomError(znsL1.zPortal, DEST_PORTAL_NOT_SET_ERR); + ).to.be.revertedWithCustomError(znsL1.zChainPortal, DEST_PORTAL_NOT_SET_ERR); // TODO multi: add a proper way to set this programmatically on actual chains !!! // set L2 portal address on L1 - await znsL1.zPortal.connect(deployAdmin).setDestZnsPortal(znsL2.ethPortal.target); + await znsL1.zChainPortal.connect(deployAdmin).setDestZnsPortal(znsL2.ethPortal.target); }); it("should NOT allow to register root domain on ZChain", async () => { @@ -291,7 +291,7 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => balanceBeforeBridge = await znsL1.meowToken.balanceOf(user.address); - const tx = await znsL1.zPortal.connect(user).registerAndBridgeDomain( + const tx = await znsL1.zChainPortal.connect(user).registerAndBridgeDomain( parentHash as string, label, DEFAULT_TOKEN_URI @@ -301,7 +301,7 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => domainHash = await getDomainHashFromEvent({ zns: znsL1, - registrantAddress: znsL1.zPortal.target as string, + registrantAddress: znsL1.zChainPortal.target as string, }); }); @@ -312,7 +312,7 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => // check if domain is registered on L1 // check events const events = await getEvents({ - contract: znsL1.zPortal, + contract: znsL1.zChainPortal, eventName: "DomainBridged", }); const event = events[events.length - 1]; @@ -343,7 +343,7 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => ); expect(bridgedEventData.originNetwork).to.equal(NETWORK_ID_L1_TEST_DEFAULT); - expect(bridgedEventData.originAddress).to.equal(znsL1.zPortal.target); + expect(bridgedEventData.originAddress).to.equal(znsL1.zChainPortal.target); expect(bridgedEventData.destinationNetwork).to.equal(NETWORK_ID_L2_TEST_DEFAULT); expect(bridgedEventData.destinationAddress).to.equal(znsL2.ethPortal.target); expect(bridgedEventData.amount).to.equal(0n); @@ -354,11 +354,11 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => owner: ownerL1, resolver: resolverL1, } = await znsL1.registry.getDomainRecord(domainHash); - expect(ownerL1).to.equal(znsL1.zPortal.target); + expect(ownerL1).to.equal(znsL1.zChainPortal.target); expect(resolverL1).to.equal(znsL1.chainResolver.target); const tokenOwner = await znsL1.domainToken.ownerOf(BigInt(domainHash)); - expect(tokenOwner).to.equal(znsL1.zPortal.target); + expect(tokenOwner).to.equal(znsL1.zChainPortal.target); }); it("should withdraw the correct amount of tokens from the caller", async () => { @@ -485,7 +485,7 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => }); const event = events[events.length - 1]; expect(event.args.originNetwork).to.equal(NETWORK_ID_L1_TEST_DEFAULT); - expect(event.args.originAddress).to.equal(znsL1.zPortal.target); + expect(event.args.originAddress).to.equal(znsL1.zChainPortal.target); expect(event.args.destinationAddress).to.equal(znsL2.ethPortal.target); expect(event.args.amount).to.equal(0n); }); @@ -500,7 +500,7 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => }); const event = events[events.length - 1]; expect(event.args.srcNetworkId).to.equal(NETWORK_ID_L1_TEST_DEFAULT); - expect(event.args.srcPortalAddress).to.equal(znsL1.zPortal.target); + expect(event.args.srcPortalAddress).to.equal(znsL1.zChainPortal.target); expect(event.args.domainHash).to.equal(domainHash); expect(event.args.domainOwner).to.equal(user.address); @@ -609,7 +609,7 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => describe("ZNSZChainPortal", () => { it("#initialize() should revert when trying to reinitialize", async () => { await expect( - znsL1.zPortal.initialize( + znsL1.zChainPortal.initialize( "1", "Z", "1", @@ -623,43 +623,39 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => subRegistrar: znsL1.subRegistrar.target, }, ) - ).to.be.revertedWithCustomError(znsL1.zPortal, INITIALIZED_ERR); + ).to.be.revertedWithCustomError(znsL1.zChainPortal, INITIALIZED_ERR); }); it("#setDestZnsPortal() should revert when called by non-ADMIN", async () => { await expect( - znsL1.zPortal.connect(user).setDestZnsPortal(znsL2.ethPortal.target) + znsL1.zChainPortal.connect(user).setDestZnsPortal(znsL2.ethPortal.target) ).to.be.revertedWithCustomError(znsL1.accessController, AC_UNAUTHORIZED_ERR); }); it("#setDestZnsPortal() should revert when setting 0x0 address", async () => { await expect( - znsL1.zPortal.connect(deployAdmin).setDestZnsPortal(hre.ethers.ZeroAddress) - ).to.be.revertedWithCustomError(znsL1.zPortal, ZERO_ADDRESS_ERR); + znsL1.zChainPortal.connect(deployAdmin).setDestZnsPortal(hre.ethers.ZeroAddress) + ).to.be.revertedWithCustomError(znsL1.zChainPortal, ZERO_ADDRESS_ERR); }); it("#setDestZnsPortal() should set the destination portal address", async () => { - await znsL1.zPortal.connect(deployAdmin).setDestZnsPortal(user.address); + await znsL1.zChainPortal.connect(deployAdmin).setDestZnsPortal(user.address); - const destPortal = await znsL1.zPortal.destZnsPortal(); + const destPortal = await znsL1.zChainPortal.destZnsPortal(); expect(destPortal).to.equal(user.address); // set back to L2 portal address - await znsL1.zPortal.connect(deployAdmin).setDestZnsPortal(znsL2.ethPortal.target); + await znsL1.zChainPortal.connect(deployAdmin).setDestZnsPortal(znsL2.ethPortal.target); }); }); describe("ZNSEthereumPortal", () => { it("#initialize() should revert when trying to reinitialize", async () => { - const { - srcZnsPortal, - } = configL1.crosschain as IZNSZChainCrossConfig; - await expect( znsL2.ethPortal.connect(deployAdmin).initialize( znsL2.accessController.target, znsL2.zkEvmBridge.target, - srcZnsPortal, + znsL1.zChainPortal.target, znsL2.registry.target, znsL2.domainToken.target, znsL2.rootRegistrar.target, diff --git a/test/cross-chain/ZNSDeploy.test.ts b/test/cross-chain/ZNSDeploy.test.ts index 623eb7043..10e5a4ef9 100644 --- a/test/cross-chain/ZNSDeploy.test.ts +++ b/test/cross-chain/ZNSDeploy.test.ts @@ -8,32 +8,30 @@ import { Wallet } from "ethers"; import { getConfig } from "../../src/deploy/campaign/environments"; import { runZnsCampaign } from "../../src/deploy/zns-campaign"; import { SupportedChains } from "../../src/deploy/missions/contracts/cross-chain/portals/get-portal-dm"; -import { resetEnvVars } from "../../src/environment/env"; import { PolygonZkEVMBridgeV2Mock } from "../../typechain"; -import { findMissingEnvVars } from "../../src/environment/validate"; +import { setDefaultEnvironment } from "../../src/environment/set-env"; export const NETWORK_ID_L1_TEST_DEFAULT = 0n; export const NETWORK_ID_L2_TEST_DEFAULT = 1n; export const ZCHAIN_ID_TEST_DEFAULT = 2012605151n; -describe.only("ZNS Cross-Chain Deploy Test", () => { +describe("ZNS Cross-Chain Deploy Test", () => { let znsL1 : IZNSContracts; let znsL2 : IZNSContracts; - let configL1 : IZNSCampaignConfig; + let configL1 : IZNSCampaignConfig; let configL2 : IZNSCampaignConfig; let dbAdapter1 : MongoDBAdapter; let dbAdapter2 : MongoDBAdapter; let deployAdmin : SignerWithAddress; - let user : SignerWithAddress; let predeployedBridge : PolygonZkEVMBridgeV2Mock; before(async () => { - [ deployAdmin, user ] = await hre.ethers.getSigners(); + [ deployAdmin ] = await hre.ethers.getSigners(); // set ENV vars for the Ethereum ZNS deployment process.env.SRC_CHAIN_NAME = SupportedChains.eth; @@ -65,7 +63,7 @@ describe.only("ZNS Cross-Chain Deploy Test", () => { // set ENV vars for ZChain ZNS deployment process.env.SRC_CHAIN_NAME = SupportedChains.z; - process.env.SRC_ZNS_PORTAL = znsL1.zPortal.target as string; + process.env.SRC_ZNS_PORTAL = znsL1.zChainPortal.target as string; process.env.MONGO_DB_NAME = "zns-l2"; // for L2 we are deploying the Bridge separately, so that we can test @@ -104,9 +102,9 @@ describe.only("ZNS Cross-Chain Deploy Test", () => { }); after(async () => { - resetEnvVars(); await dbAdapter1.dropDB(); await dbAdapter2.dropDB(); + setDefaultEnvironment(); }); it("should deploy a mocked zkEVM Bridge if MOCK_ZKEVM_BRIDGE is 'true'", async () => { From b3bcda1616f99f64eda3b1e6d44887929f2a8d59 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Fri, 22 Nov 2024 15:58:09 -0800 Subject: [PATCH 111/124] commit temp helpers used on test networks [to be deleted later] --- test/cross-chain/claim.ts | 85 +++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 25 deletions(-) diff --git a/test/cross-chain/claim.ts b/test/cross-chain/claim.ts index 1254e1a32..b7f15fd05 100644 --- a/test/cross-chain/claim.ts +++ b/test/cross-chain/claim.ts @@ -4,7 +4,13 @@ import axios from "axios"; import { ErrorDecoder } from "ethers-decode-error"; import { receiverAddress } from "./addresses.json"; import * as ethers from "ethers"; -import { ZNSSubRegistrar, ZNSSubRegistrar__factory } from "../../typechain"; +import { + MeowTokenMock, + MeowTokenMock__factory, + ZNSRootRegistrarTrunk, + ZNSSubRegistrar, + ZNSSubRegistrar__factory, +} from "../../typechain"; import { DEFAULT_TOKEN_URI, distrConfigEmpty, paymentConfigEmpty } from "../helpers"; @@ -16,7 +22,6 @@ const zChainRpcUrl = "https://zchain-testnet-rpc.eu-north-2.gateway.fm/"; const zChainTestBridgeAddress = "0x528e26b25a34a4A5d0dbDa1d57D318153d2ED582"; - const main = async () => { // launch HH script with "--network zchaintest" flag to get this! const [deployerZChain] = await hre.ethers.getSigners(); @@ -83,29 +88,59 @@ const main = async () => { }; -const register = async () => { - const [caller] = await hre.ethers.getSigners(); - const fact = new ZNSSubRegistrar__factory(caller); - const znsSubRegistrar = fact.attach("0x0629076F9851dd5AE881d2d68790E4b7176aB5fd") as ZNSSubRegistrar; - - const parentHash = "0x4d7459e21a4603da1084e91d4d1ec4f0255be54312073d256d7f1881c81c167d"; - const label = "subone"; - - const tx = await znsSubRegistrar.registerSubdomain( - parentHash, - label, - caller.address, - DEFAULT_TOKEN_URI, - distrConfigEmpty, - paymentConfigEmpty, +const decodeError = async () => { + // const [caller] = await hre.ethers.getSigners(); + // const fact = new ZNSSubRegistrar__factory(caller); + // const znsSubRegistrar = fact.attach("0x0629076F9851dd5AE881d2d68790E4b7176aB5fd") as ZNSSubRegistrar; + // + // const parentHash = "0x4d7459e21a4603da1084e91d4d1ec4f0255be54312073d256d7f1881c81c167d"; + // const label = "subone"; + // + // const tx = await znsSubRegistrar.registerSubdomain( + // parentHash, + // label, + // caller.address, + // DEFAULT_TOKEN_URI, + // distrConfigEmpty, + // paymentConfigEmpty, + // ); + // const receipt = await tx.wait(); + // + // + // console.log("Subdomain registered successfully!", JSON.stringify(receipt, null, "\t")); + // const bridgeFactory = await hre.ethers.getContractFactory("ZNSRootRegistrarTrunk"); + // const bridgeContract = bridgeFactory.attach("0xfbcC64F59Ad11a0972F0Ca9D14C56E5c300bf5a5") as ZNSRootRegistrarTrunk; + + const interfaceArr = await [ + "ZNSAccessController", + "ZNSDomainToken", + "ZNSRegistry", + "ZNSAddressResolver", + "ZNSRootRegistrarTrunk", + "MeowTokenMock", + "ZNSCurvePricer", + "ZNSFixedPricer", + "ZNSTreasury", + "ZNSSubRegistrarTrunk", + ].reduce( + async (acc, val) => { + const res = await acc; + const factory = await hre.ethers.getContractFactory(val); + res.push(factory.interface); + return res; + }, + Promise.resolve([]), ); - const receipt = await tx.wait(); - - console.log("Subdomain registered successfully!", JSON.stringify(receipt, null, "\t")); + const errorDecoder = ErrorDecoder.create(interfaceArr); + const errorData = "0xfb08014488161a02799642778b953fbe428133912f53a5face7a2028dd8d57f905297fa4"; + const decoded = await errorDecoder.decode(errorData); + + // const reason = ethers.toUtf8String( + // errorData, + // ethers.Utf8ErrorFuncs.ignore, + // ); + // + // const result = ethers.AbiCoder.defaultAbiCoder().decode([ "string", "string" ], errorData); + console.log("Decoded:", decoded); }; - -// register().catch(error => { -// console.error(error); -// process.exit(1); -// }); From 7c7f6bc0ade704ab40a97500afc38e7eec1ad199 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Fri, 22 Nov 2024 16:03:08 -0800 Subject: [PATCH 112/124] delete redundant test contracts and files --- contracts/L2-BRIDGE-TEST/BridgeReceiver.sol | 53 ------- contracts/L2-BRIDGE-TEST/BridgeSender.sol | 41 ------ test/cross-chain/addresses.json | 4 - test/cross-chain/claim.ts | 146 -------------------- test/cross-chain/deploy.ts | 52 ------- test/cross-chain/send.ts | 37 ----- 6 files changed, 333 deletions(-) delete mode 100644 contracts/L2-BRIDGE-TEST/BridgeReceiver.sol delete mode 100644 contracts/L2-BRIDGE-TEST/BridgeSender.sol delete mode 100644 test/cross-chain/addresses.json delete mode 100644 test/cross-chain/claim.ts delete mode 100644 test/cross-chain/deploy.ts delete mode 100644 test/cross-chain/send.ts diff --git a/contracts/L2-BRIDGE-TEST/BridgeReceiver.sol b/contracts/L2-BRIDGE-TEST/BridgeReceiver.sol deleted file mode 100644 index 8e83e699b..000000000 --- a/contracts/L2-BRIDGE-TEST/BridgeReceiver.sol +++ /dev/null @@ -1,53 +0,0 @@ -//// SPDX-License-Identifier: MIT -//pragma solidity 0.8.26; -// -//import { IBridgeMessageReceiver } from "@zero-tech/zkevm-contracts/contracts/interfaces/IBridgeMessageReceiver.sol"; -//import { PolygonZkEVMBridgeV2 } from "@zero-tech/zkevm-contracts/contracts/v2/PolygonZkEVMBridgeV2.sol"; -//import { IPolygonZkEVMBridgeV2Ext } from "./IPolygonZkEVMBridgeV2Ext.sol"; -//import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; -// -// -//contract BridgeReceiver is IBridgeMessageReceiver { -// event MessageReceived( -// address originAddress, -// uint32 originNetwork, -// string message -// ); -// -// error NotPolygonZkEVMBridge(); -// -// // Global Exit Root address -// IPolygonZkEVMBridgeV2Ext public immutable polygonZkEVMBridge; -// -// // Current network identifier -// uint32 public immutable networkID; -// -// string public messageState; -// -// address public senderContract; -// -// constructor(IPolygonZkEVMBridgeV2Ext bridgeAddress) { -// if (address(bridgeAddress) == address(0)) revert ZeroAddressPassed(); -// polygonZkEVMBridge = bridgeAddress; -// networkID = polygonZkEVMBridge.networkID(); -// } -// -// function onMessageReceived( -// address originAddress, -// uint32 originNetwork, -// bytes memory data -// ) external payable override { -// // Can only be called by the bridge -// // Can only be called by the sender on the other network -// // require( -// // pingSender == originAddress, -// // "PingReceiver::onMessageReceived: Not ping Sender" -// // ); -// -// string memory message = abi.decode(data, (string)); -// messageState = message; -// senderContract = originAddress; -// -// emit MessageReceived(originAddress, originNetwork, message); -// } -//} diff --git a/contracts/L2-BRIDGE-TEST/BridgeSender.sol b/contracts/L2-BRIDGE-TEST/BridgeSender.sol deleted file mode 100644 index 843e2314c..000000000 --- a/contracts/L2-BRIDGE-TEST/BridgeSender.sol +++ /dev/null @@ -1,41 +0,0 @@ -//// SPDX-License-Identifier: MIT -//pragma solidity 0.8.26; -// -//import { IPolygonZkEVMBridgeV2 } from "@zero-tech/zkevm-contracts/contracts/v2/interfaces/IPolygonZkEVMBridgeV2.sol"; -//import { ZeroAddressPassed } from "../utils/CommonErrors.sol"; -// -// -//contract BridgeSender { -// -// event MessageBridged( -// uint32 destinationNetwork, -// address destinationAddress, -// string message -// ); -// -// // Global Exit Root address -// IPolygonZkEVMBridgeV2 public immutable polygonZkEVMBridge; -// -// constructor(IPolygonZkEVMBridgeV2 bridgeAddress) { -// if (address(bridgeAddress) == address(0)) revert ZeroAddressPassed(); -// polygonZkEVMBridge = bridgeAddress; -// } -// -// function bridgeMessage( -// uint32 destinationNetwork, -// address destinationAddress, -// bool forceUpdateGlobalExitRoot, -// string memory message -// ) external { -// bytes memory encodedMsg = abi.encode(message); -// -// polygonZkEVMBridge.bridgeMessage( -// destinationNetwork, -// destinationAddress, -// forceUpdateGlobalExitRoot, -// encodedMsg -// ); -// -// emit MessageBridged(destinationNetwork, destinationAddress, message); -// } -//} diff --git a/test/cross-chain/addresses.json b/test/cross-chain/addresses.json deleted file mode 100644 index 56f70e7c1..000000000 --- a/test/cross-chain/addresses.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "senderAddress": "0xdC9d716D91ECE21CB5d83B2E8d7b5fd586931dCa", - "receiverAddress": "0x3560C7Fde749d1ca5cf1076Fc0E893AdcA9F3714" -} diff --git a/test/cross-chain/claim.ts b/test/cross-chain/claim.ts deleted file mode 100644 index b7f15fd05..000000000 --- a/test/cross-chain/claim.ts +++ /dev/null @@ -1,146 +0,0 @@ -/* eslint-disable @typescript-eslint/no-var-requires, camelcase */ -import * as hre from "hardhat"; -import axios from "axios"; -import { ErrorDecoder } from "ethers-decode-error"; -import { receiverAddress } from "./addresses.json"; -import * as ethers from "ethers"; -import { - MeowTokenMock, - MeowTokenMock__factory, - ZNSRootRegistrarTrunk, - ZNSSubRegistrar, - ZNSSubRegistrar__factory, -} from "../../typechain"; -import { DEFAULT_TOKEN_URI, distrConfigEmpty, paymentConfigEmpty } from "../helpers"; - - -// TODO multi: make this into something usable or delete -const mekrleProofString = "/merkle-proof"; -const getClaimsFromAcc = "/bridges/"; -const zChainBridgeApiUrl = "https://zchain-testnet-bridge-api.eu-north-2.gateway.fm/"; -const zChainRpcUrl = "https://zchain-testnet-rpc.eu-north-2.gateway.fm/"; -const zChainTestBridgeAddress = "0x528e26b25a34a4A5d0dbDa1d57D318153d2ED582"; - - -const main = async () => { - // launch HH script with "--network zchaintest" flag to get this! - const [deployerZChain] = await hre.ethers.getSigners(); - - // const bridgeArt = require("./PolygonZkEVMBridgeV2.json"); - // const bridgeContract = new hre.ethers.Contract(zChainTestBridgeAddress, bridgeArt.abi, deployerZChain); - const bridgeFactory = await hre.ethers.getContractFactory("PolygonZkEVMBridgeV2", deployerZChain); - const bridgeContract = bridgeFactory.attach(zChainTestBridgeAddress) as PolygonZkEVMBridgeV2; - - const axio = axios.create({ baseURL: zChainBridgeApiUrl }); - const result = await axio.get( - getClaimsFromAcc + receiverAddress, - { params: { limit: 100, offset: 0 } } - ); - - const { data: { deposits } } = result; - - console.log("Deposits acquired:", JSON.stringify(deposits, null, "\t")); - - const latestDeposit = deposits[deposits.length - 1]; - if (latestDeposit.ready_for_claim) { - const { data: { proof } } = await axio.get( - mekrleProofString, - { - params: { - deposit_cnt: latestDeposit.deposit_cnt, - net_id: latestDeposit.orig_net, - }, - } - ); - - console.log("Proof acquired:", JSON.stringify(proof, null, "\t")); - - const errorDecoder = ErrorDecoder.create([bridgeContract.interface]); - let tx; - try { - // claim message - tx = await bridgeContract.claimMessage( - proof.merkle_proof, - proof.rollup_merkle_proof, - latestDeposit.global_index, - proof.main_exit_root, - proof.rollup_exit_root, - latestDeposit.orig_net, - latestDeposit.orig_addr, - latestDeposit.dest_net, - latestDeposit.dest_addr, - latestDeposit.amount, - latestDeposit.metadata - ); - } catch (error) { - const decoded = await errorDecoder.decode(error); - console.error("Claim failed!", decoded); - } - - console.log(`Claim sent successfully! Tx hash: ${tx.hash}`); - const rec = await tx.wait(); - console.log(`Claim message mined! Tx receipt: ${rec}`); - } else { - console.log("Bridged message NOT ready for claim!"); - } - - console.log("Claim process completed successfully!"); -}; - - -const decodeError = async () => { - // const [caller] = await hre.ethers.getSigners(); - // const fact = new ZNSSubRegistrar__factory(caller); - // const znsSubRegistrar = fact.attach("0x0629076F9851dd5AE881d2d68790E4b7176aB5fd") as ZNSSubRegistrar; - // - // const parentHash = "0x4d7459e21a4603da1084e91d4d1ec4f0255be54312073d256d7f1881c81c167d"; - // const label = "subone"; - // - // const tx = await znsSubRegistrar.registerSubdomain( - // parentHash, - // label, - // caller.address, - // DEFAULT_TOKEN_URI, - // distrConfigEmpty, - // paymentConfigEmpty, - // ); - // const receipt = await tx.wait(); - // - // - // console.log("Subdomain registered successfully!", JSON.stringify(receipt, null, "\t")); - // const bridgeFactory = await hre.ethers.getContractFactory("ZNSRootRegistrarTrunk"); - // const bridgeContract = bridgeFactory.attach("0xfbcC64F59Ad11a0972F0Ca9D14C56E5c300bf5a5") as ZNSRootRegistrarTrunk; - - const interfaceArr = await [ - "ZNSAccessController", - "ZNSDomainToken", - "ZNSRegistry", - "ZNSAddressResolver", - "ZNSRootRegistrarTrunk", - "MeowTokenMock", - "ZNSCurvePricer", - "ZNSFixedPricer", - "ZNSTreasury", - "ZNSSubRegistrarTrunk", - ].reduce( - async (acc, val) => { - const res = await acc; - const factory = await hre.ethers.getContractFactory(val); - res.push(factory.interface); - return res; - }, - Promise.resolve([]), - ); - - const errorDecoder = ErrorDecoder.create(interfaceArr); - const errorData = "0xfb08014488161a02799642778b953fbe428133912f53a5face7a2028dd8d57f905297fa4"; - const decoded = await errorDecoder.decode(errorData); - - // const reason = ethers.toUtf8String( - // errorData, - // ethers.Utf8ErrorFuncs.ignore, - // ); - // - // const result = ethers.AbiCoder.defaultAbiCoder().decode([ "string", "string" ], errorData); - console.log("Decoded:", decoded); -}; diff --git a/test/cross-chain/deploy.ts b/test/cross-chain/deploy.ts deleted file mode 100644 index 3893b2e51..000000000 --- a/test/cross-chain/deploy.ts +++ /dev/null @@ -1,52 +0,0 @@ -import path from "path"; -import * as hre from "hardhat"; -import fs from "fs"; -import { ethers } from "ethers"; - - -const sepoliaBridgeAddress = "0x528e26b25a34a4A5d0dbDa1d57D318153d2ED582"; -const zChainTestBridgeAddress = "0x528e26b25a34a4A5d0dbDa1d57D318153d2ED582"; -const zChainRpcUrl = "https://zchain-testnet-rpc.eu-north-2.gateway.fm/"; - - -const main = async () => { - const [deployerSepolia] = await hre.ethers.getSigners(); - - const providerZChain = new ethers.JsonRpcProvider(zChainRpcUrl); - const deployerZChain = new ethers.Wallet(`0x${process.env.TESTNET_PRIVATE_KEY_A}`, providerZChain); - - // deploy BridgeSender contract to Sepolia - const senderFactory = await hre.ethers.getContractFactory("BridgeSender", deployerSepolia); - const senderContract = await senderFactory.deploy(sepoliaBridgeAddress); - await senderContract.waitForDeployment(); - console.log("BridgeSender deployed to:", senderContract.target); - - // deploy BridgeReceiver contract to ZChain - const receiverFactory = await hre.ethers.getContractFactory("BridgeReceiver", deployerZChain); - const receiverContract = await receiverFactory.deploy(zChainTestBridgeAddress); - await receiverContract.waitForDeployment(); - console.log("BridgeReceiver deployed to:", receiverContract.target); - - await hre.run("verify:verify", { - address: receiverContract.target, - constructorArguments: [zChainTestBridgeAddress], - }); - - // Write output - // ! Please note that this will OVERWRITE whatever was in the file, - // copy the file or change this code to keep the previous data - // Contract are already deployed and can be accessed by addresses from addresses.json! - const outputJson = { - senderAddress: senderContract.target, - receiverAddress: receiverContract.target, - }; - console.log(`Contract data: ${JSON.stringify(outputJson, null, "\t")}`); - - const pathOutputJson = path.join(__dirname, "./addresses.json"); - fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, "\t")); -}; - -// main().catch(error => { -// console.error(error); -// process.exit(1); -// }); diff --git a/test/cross-chain/send.ts b/test/cross-chain/send.ts deleted file mode 100644 index 663263fd1..000000000 --- a/test/cross-chain/send.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ -import * as hre from "hardhat"; -import path from "path"; -import { BridgeSender } from "../../typechain"; - - -const networkIDzChainTest = 19n; - -const deployData = path.join(__dirname, "./addresses.json"); -const { senderAddress, receiverAddress } = require(deployData); - - -const main = async () => { - const [deployerSepolia] = await hre.ethers.getSigners(); - - const senderFact = await hre.ethers.getContractFactory("BridgeSender", deployerSepolia); - const bridgeSender = senderFact.attach(senderAddress) as BridgeSender; - - const forceUpdateGlobalExitRoot = true; // fast bridge - const message = "0://setstatestringdomain"; // change this string for test calls - - const tx = await bridgeSender.bridgeMessage( - networkIDzChainTest, - receiverAddress, - forceUpdateGlobalExitRoot, - message - ); - - console.log("Transaction receipt:\n", await tx.wait()); - - console.log("Message bridged successfully!"); -}; - -// main().catch(error => { -// console.error(error); -// process.exit(1); -// }); From 778d6b56c424005ec20994784851d5b5a9611344 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Fri, 22 Nov 2024 16:32:40 -0800 Subject: [PATCH 113/124] fix all solhint and eslint errors across the repo, fix event helper calls --- contracts/cross-chain/ZNSEthereumPortal.sol | 7 +-- contracts/registrar/ZNSRootRegistrarBase.sol | 2 +- .../registrar/ZNSRootRegistrarBranch.sol | 2 +- contracts/registrar/ZNSRootRegistrarTrunk.sol | 2 +- contracts/registrar/ZNSSubRegistrarBranch.sol | 1 - contracts/resolver/ZNSChainResolver.sol | 3 +- .../{environments.ts => get-config.ts} | 8 +--- src/deploy/run-campaign.ts | 2 +- src/deploy/zns-campaign.ts | 1 + src/utils/cross-chain/bridge-api.ts | 1 - test/DeployCampaign.integration.test.ts | 2 +- test/DeployCampaignInt.test.ts | 2 +- test/ZNSRootRegistrar.test.ts | 46 +++++++++---------- test/ZNSStringResolver.test.ts | 5 +- test/ZNSSubRegistrar.test.ts | 5 +- .../CrossChainDomainBridging.network.test.ts | 3 +- test/cross-chain/ZNSDeploy.test.ts | 2 +- test/cross-chain/mint-looper.temp.ts | 1 + test/helpers/deploy/deploy-zns.ts | 5 -- test/helpers/events.ts | 4 +- test/helpers/register-setup.ts | 4 +- test/helpers/types.ts | 9 ---- 22 files changed, 45 insertions(+), 72 deletions(-) rename src/deploy/campaign/{environments.ts => get-config.ts} (97%) diff --git a/contracts/cross-chain/ZNSEthereumPortal.sol b/contracts/cross-chain/ZNSEthereumPortal.sol index ff43f3bba..e2a74dd6c 100644 --- a/contracts/cross-chain/ZNSEthereumPortal.sol +++ b/contracts/cross-chain/ZNSEthereumPortal.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.26; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { AAccessControlled } from "../access/AAccessControlled.sol"; import { IZNSEthereumPortal } from "./IZNSEthereumPortal.sol"; import { IPolygonZkEVMBridgeV2Ext } from "./IPolygonZkEVMBridgeV2Ext.sol"; @@ -12,8 +11,6 @@ import { IZNSRootRegistrarBranch } from "../registrar/IZNSRootRegistrarBranch.so import { IZNSSubRegistrarBranch } from "../registrar/IZNSSubRegistrarBranch.sol"; import { IZNSRegistry } from "../registry/IZNSRegistry.sol"; import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; -import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; -import { IZNSPricer } from "../types/IZNSPricer.sol"; contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPortal { @@ -118,7 +115,7 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPo ); } - function setSrcZnsPortal(address newAddress) external onlyAdmin { + function setSrcZnsPortal(address newAddress) external override onlyAdmin { if (newAddress == address(0)) revert ZeroAddressPassed(); srcZnsPortal = newAddress; @@ -131,7 +128,7 @@ contract ZNSEthereumPortal is UUPSUpgradeable, AAccessControlled, IZNSEthereumPo address, uint256, bytes calldata - ) external pure returns (bytes4) { + ) external pure override returns (bytes4) { return this.onERC721Received.selector; } diff --git a/contracts/registrar/ZNSRootRegistrarBase.sol b/contracts/registrar/ZNSRootRegistrarBase.sol index feca8779b..62fd04175 100644 --- a/contracts/registrar/ZNSRootRegistrarBase.sol +++ b/contracts/registrar/ZNSRootRegistrarBase.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.26; import { AAccessControlled } from "../access/AAccessControlled.sol"; import { ARegistryWired } from "../registry/ARegistryWired.sol"; import { IZNSRootRegistrarBase } from "./IZNSRootRegistrarBase.sol"; -import { IZNSRootRegistrarTypes, CoreRegisterArgs } from "./IZNSRootRegistrarTypes.sol"; +import { CoreRegisterArgs } from "./IZNSRootRegistrarTypes.sol"; import { IZNSTreasury, PaymentConfig } from "../treasury/IZNSTreasury.sol"; import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; import { IZNSAddressResolver } from "../resolver/IZNSAddressResolver.sol"; diff --git a/contracts/registrar/ZNSRootRegistrarBranch.sol b/contracts/registrar/ZNSRootRegistrarBranch.sol index 7d73050f0..acd531f2d 100644 --- a/contracts/registrar/ZNSRootRegistrarBranch.sol +++ b/contracts/registrar/ZNSRootRegistrarBranch.sol @@ -29,7 +29,7 @@ contract ZNSRootRegistrarBranch is function registerBridgedRootDomain( string calldata label, string calldata tokenURI - ) external returns (bytes32) { + ) external override returns (bytes32) { accessController.checkPortal(msg.sender); DistributionConfig memory emptyDistrConfig; diff --git a/contracts/registrar/ZNSRootRegistrarTrunk.sol b/contracts/registrar/ZNSRootRegistrarTrunk.sol index 584dc93b4..2ee966c0b 100644 --- a/contracts/registrar/ZNSRootRegistrarTrunk.sol +++ b/contracts/registrar/ZNSRootRegistrarTrunk.sol @@ -49,7 +49,7 @@ contract ZNSRootRegistrarTrunk is string calldata tokenURI, DistributionConfig calldata distributionConfig, PaymentConfig calldata paymentConfig - ) external returns (bytes32) { + ) external override returns (bytes32) { return _coreRootRegister( label, domainAddress, diff --git a/contracts/registrar/ZNSSubRegistrarBranch.sol b/contracts/registrar/ZNSSubRegistrarBranch.sol index fc2823093..7b8154293 100644 --- a/contracts/registrar/ZNSSubRegistrarBranch.sol +++ b/contracts/registrar/ZNSSubRegistrarBranch.sol @@ -4,7 +4,6 @@ pragma solidity 0.8.26; import { IZNSSubRegistrarBranch } from "./IZNSSubRegistrarBranch.sol"; import { ZNSSubRegistrarTrunk } from "./ZNSSubRegistrarTrunk.sol"; import { IZNSSubRegistrarTrunk } from "./IZNSSubRegistrarTrunk.sol"; -import { IDistributionConfig } from "../types/IDistributionConfig.sol"; import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; diff --git a/contracts/resolver/ZNSChainResolver.sol b/contracts/resolver/ZNSChainResolver.sol index 9de901def..033140b4e 100644 --- a/contracts/resolver/ZNSChainResolver.sol +++ b/contracts/resolver/ZNSChainResolver.sol @@ -3,7 +3,6 @@ pragma solidity 0.8.26; import { ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import { IZNSStringResolver } from "./IZNSStringResolver.sol"; import { AAccessControlled } from "../access/AAccessControlled.sol"; import { ARegistryWired } from "../registry/ARegistryWired.sol"; import { NotAuthorizedForDomain } from "../utils/CommonErrors.sol"; @@ -17,7 +16,7 @@ contract ZNSChainResolver is ERC165, IZNSChainResolver { - mapping(bytes32 => ChainData) internal chainData; + mapping(bytes32 domainHash => ChainData data) internal chainData; /// @custom:oz-upgrades-unsafe-allow constructor constructor() { diff --git a/src/deploy/campaign/environments.ts b/src/deploy/campaign/get-config.ts similarity index 97% rename from src/deploy/campaign/environments.ts rename to src/deploy/campaign/get-config.ts index 50a59655d..f0a57411e 100644 --- a/src/deploy/campaign/environments.ts +++ b/src/deploy/campaign/get-config.ts @@ -1,26 +1,20 @@ import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { - IZNSBaseCrossConfig, IZNSCampaignConfig, IZNSEthCrossConfig, IZNSZChainCrossConfig, TZNSCrossConfig, } from "./types"; import { - DEFAULT_PROTOCOL_FEE_PERCENT, - DEFAULT_ROYALTY_FRACTION, - ZNS_DOMAIN_TOKEN_NAME, - ZNS_DOMAIN_TOKEN_SYMBOL, DEFAULT_DECIMALS, DEFAULT_PRECISION, - DEFAULT_PRICE_CONFIG, getCurvePrice, NO_MOCK_PROD_ERR, STAKING_TOKEN_ERR, INVALID_CURVE_ERR, MONGO_URI_ERR, - INVALID_ENV_ERR, NO_ZERO_VAULT_ERR, + INVALID_ENV_ERR, } from "../../../test/helpers"; import { ethers, Wallet } from "ethers"; import { ICurvePriceConfig } from "../missions/types"; diff --git a/src/deploy/run-campaign.ts b/src/deploy/run-campaign.ts index c11d57554..8ff168ae2 100644 --- a/src/deploy/run-campaign.ts +++ b/src/deploy/run-campaign.ts @@ -1,4 +1,4 @@ -import { getConfig } from "./campaign/environments"; +import { getConfig } from "./campaign/get-config"; import { runZnsCampaign } from "./zns-campaign"; import * as hre from "hardhat"; import { getLogger } from "@zero-tech/zdc"; diff --git a/src/deploy/zns-campaign.ts b/src/deploy/zns-campaign.ts index 1766cac3e..810d22fbb 100644 --- a/src/deploy/zns-campaign.ts +++ b/src/deploy/zns-campaign.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-shadow, no-shadow */ import * as hre from "hardhat"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { diff --git a/src/utils/cross-chain/bridge-api.ts b/src/utils/cross-chain/bridge-api.ts index 62b92ef1a..fb3a2655b 100644 --- a/src/utils/cross-chain/bridge-api.ts +++ b/src/utils/cross-chain/bridge-api.ts @@ -7,7 +7,6 @@ import { TEMP_DATA_DIR_PATH, ZCHAIN_TEST_BRIDGE_API_URL, } from "./constants"; -import path from "path"; import fs from "fs"; diff --git a/test/DeployCampaign.integration.test.ts b/test/DeployCampaign.integration.test.ts index abe782552..b365c9a33 100644 --- a/test/DeployCampaign.integration.test.ts +++ b/test/DeployCampaign.integration.test.ts @@ -3,7 +3,7 @@ import { } from "@zero-tech/zdc"; import * as hre from "hardhat"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { getConfig } from "../src/deploy/campaign/environments"; +import { getConfig } from "../src/deploy/campaign/get-config"; import { runZnsCampaign } from "../src/deploy/zns-campaign"; import { ethers } from "ethers"; import { IDistributionConfig } from "./helpers/types"; diff --git a/test/DeployCampaignInt.test.ts b/test/DeployCampaignInt.test.ts index 113364efe..6b1bab277 100644 --- a/test/DeployCampaignInt.test.ts +++ b/test/DeployCampaignInt.test.ts @@ -39,7 +39,7 @@ import { znsNames } from "../src/deploy/missions/contracts/names"; import { runZnsCampaign } from "../src/deploy/zns-campaign"; import { MeowMainnet } from "../src/deploy/missions/contracts/zns-base/meow-token/mainnet-data"; import { ResolverTypes } from "../src/deploy/constants"; -import { buildCrosschainConfig, getConfig } from "../src/deploy/campaign/environments"; +import { buildCrosschainConfig, getConfig } from "../src/deploy/campaign/get-config"; import { ethers, Wallet } from "ethers"; import { promisify } from "util"; import { exec } from "child_process"; diff --git a/test/ZNSRootRegistrar.test.ts b/test/ZNSRootRegistrar.test.ts index b7ddaea0c..bd5f71fb3 100644 --- a/test/ZNSRootRegistrar.test.ts +++ b/test/ZNSRootRegistrar.test.ts @@ -34,15 +34,15 @@ import { getDomainHashFromEvent } from "./helpers/events"; import { ADMIN_ROLE, GOVERNOR_ROLE } from "../src/deploy/constants"; import { IERC20, - ZNSRootRegistrar, - ZNSRootRegistrar__factory, ZNSRootRegistrarTrunk, ZNSRootRegistrarTrunk__factory, + ZNSRootRegistrarTrunk, + ZNSRootRegistrarTrunk__factory, ZNSRootRegistrarUpgradeMock__factory, } from "../typechain"; import { PaymentConfigStruct } from "../typechain/contracts/treasury/IZNSTreasury"; import { runZnsCampaign } from "../src/deploy/zns-campaign"; import { getProxyImplAddress } from "./helpers/utils"; import { upgrades } from "hardhat"; -import { getConfig } from "../src/deploy/campaign/environments"; +import { getConfig } from "../src/deploy/campaign/get-config"; import { IZNSContracts } from "../src/deploy/campaign/types"; import { ZeroHash } from "ethers"; @@ -170,7 +170,7 @@ describe("ZNSRootRegistrar", () => { const domainHash = await getDomainHashFromEvent({ zns, - registrantAddress: deployer, + registrantAddress: deployer.address, }); // Registering as deployer (owner of parent) and user is different gas values @@ -355,7 +355,7 @@ describe("ZNSRootRegistrar", () => { }); const domainHash = await getDomainHashFromEvent({ zns, - registrantAddress: user, + registrantAddress: user.address, }); const tokenId = BigInt(domainHash); @@ -619,7 +619,7 @@ describe("ZNSRootRegistrar", () => { const domainHash = await getDomainHashFromEvent({ zns, - registrantAddress: user, + registrantAddress: user.address, }); const { @@ -648,7 +648,7 @@ describe("ZNSRootRegistrar", () => { }); const domainHash = await getDomainHashFromEvent({ zns, - registrantAddress: user, + registrantAddress: user.address, }); const { @@ -688,7 +688,7 @@ describe("ZNSRootRegistrar", () => { const namehashRef = hashDomainLabel(defaultDomain); const domainHash = await getDomainHashFromEvent({ zns, - registrantAddress: user, + registrantAddress: user.address, }); expect(domainHash).to.eq(namehashRef); @@ -759,7 +759,7 @@ describe("ZNSRootRegistrar", () => { const domainHash = await getDomainHashFromEvent({ zns, - registrantAddress: user, + registrantAddress: user.address, }); const exists = await zns.registry.exists(domainHash); @@ -777,7 +777,7 @@ describe("ZNSRootRegistrar", () => { const tokenId = BigInt( await getDomainHashFromEvent({ zns, - registrantAddress: user, + registrantAddress: user.address, }) ); const owner = await zns.domainToken.ownerOf(tokenId); @@ -793,7 +793,7 @@ describe("ZNSRootRegistrar", () => { }); const domainHash = await getDomainHashFromEvent({ zns, - registrantAddress: user, + registrantAddress: user.address, }); const resolvedAddress = await zns.addressResolver.resolveDomainAddress(domainHash); @@ -846,7 +846,7 @@ describe("ZNSRootRegistrar", () => { await defaultRootRegistration({ user: deployer, zns, domainName: defaultDomain }); const domainHash = await getDomainHashFromEvent({ zns, - registrantAddress: deployer, + registrantAddress: deployer.address, }); const tokenId = BigInt(domainHash); const { amount: staked, token } = await zns.treasury.stakedForDomain(domainHash); @@ -880,7 +880,7 @@ describe("ZNSRootRegistrar", () => { await defaultRootRegistration({ user: deployer, zns, domainName: defaultDomain }); const domainHash = await getDomainHashFromEvent({ zns, - registrantAddress: deployer, + registrantAddress: deployer.address, }); const tokenId = BigInt(domainHash); @@ -898,7 +898,7 @@ describe("ZNSRootRegistrar", () => { await defaultRootRegistration({ user: deployer, zns, domainName: defaultDomain }); const domainHash = await getDomainHashFromEvent({ zns, - registrantAddress: deployer, + registrantAddress: deployer.address, }); // Reclaim the Domain const tx = zns.rootRegistrar.connect(user).reclaimDomain(domainHash); @@ -929,7 +929,7 @@ describe("ZNSRootRegistrar", () => { await defaultRootRegistration({ user: deployer, zns, domainName: defaultDomain }); const domainHash = await getDomainHashFromEvent({ zns, - registrantAddress: deployer, + registrantAddress: deployer.address, }); const tokenId = BigInt(domainHash); const { amount: staked, token } = await zns.treasury.stakedForDomain(domainHash); @@ -973,7 +973,7 @@ describe("ZNSRootRegistrar", () => { await defaultRootRegistration({ user: deployer, zns, domainName: defaultDomain }); const domainHash = await getDomainHashFromEvent({ zns, - registrantAddress: deployer, + registrantAddress: deployer.address, }); const tokenId = BigInt(domainHash); @@ -1023,7 +1023,7 @@ describe("ZNSRootRegistrar", () => { const domainHash = await getDomainHashFromEvent({ zns, - registrantAddress: user, + registrantAddress: user.address, }); const price = await zns.curvePricer.getPrice(ethers.ZeroHash, defaultDomain, false); @@ -1054,7 +1054,7 @@ describe("ZNSRootRegistrar", () => { const domainHash = await getDomainHashFromEvent({ zns, - registrantAddress: user, + registrantAddress: user.address, }); // add mintlist to check revocation @@ -1078,7 +1078,7 @@ describe("ZNSRootRegistrar", () => { const tokenId = BigInt( await getDomainHashFromEvent({ zns, - registrantAddress: user, + registrantAddress: user.address, }) ); @@ -1128,7 +1128,7 @@ describe("ZNSRootRegistrar", () => { await defaultRootRegistration({ user, zns, domainName: defaultDomain }); const domainHash = await getDomainHashFromEvent({ zns, - registrantAddress: user, + registrantAddress: user.address, }); // Validated staked values @@ -1167,7 +1167,7 @@ describe("ZNSRootRegistrar", () => { await defaultRootRegistration({ user: deployer, zns, domainName: defaultDomain }); const parentDomainHash = await getDomainHashFromEvent({ zns, - registrantAddress: deployer, + registrantAddress: deployer.address, }); const owner = await zns.registry.connect(user).getDomainOwner(parentDomainHash); expect(owner).to.not.equal(user.address); @@ -1185,7 +1185,7 @@ describe("ZNSRootRegistrar", () => { await defaultRootRegistration({ user: deployer, zns, domainName: defaultDomain }); const parentDomainHash = await getDomainHashFromEvent({ zns, - registrantAddress: deployer, + registrantAddress: deployer.address, }); const owner = await zns.registry.connect(user).getDomainOwner(parentDomainHash); expect(owner).to.not.equal(user.address); @@ -1210,7 +1210,7 @@ describe("ZNSRootRegistrar", () => { await defaultRootRegistration({ user, zns, domainName: defaultDomain }); const domainHash = await getDomainHashFromEvent({ zns, - registrantAddress: user, + registrantAddress: user.address, }); // assign an operator diff --git a/test/ZNSStringResolver.test.ts b/test/ZNSStringResolver.test.ts index a026aa422..85e7d7fed 100644 --- a/test/ZNSStringResolver.test.ts +++ b/test/ZNSStringResolver.test.ts @@ -16,15 +16,14 @@ import * as ethers from "ethers"; import { registrationWithSetup } from "./helpers/register-setup"; import { ERC165__factory, - MeowTokenMock, ZNSAccessController, ZNSDomainToken, ZNSRegistry, ZNSRootRegistrar, + MeowTokenMock, ZNSAccessController, ZNSDomainToken, ZNSRegistry, ZNSStringResolver, ZNSStringResolverUpgradeMock__factory, ZNSTreasury, } from "../typechain"; import { DeployCampaign, MongoDBAdapter } from "@zero-tech/zdc"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { DefenderRelayProvider } from "@openzeppelin/defender-sdk-relay-signer-client/lib/ethers"; -import { getConfig } from "../src/deploy/campaign/environments"; +import { getConfig } from "../src/deploy/campaign/get-config"; import { IZNSContractsLocal } from "./helpers/types"; diff --git a/test/ZNSSubRegistrar.test.ts b/test/ZNSSubRegistrar.test.ts index 04e2e0598..c84333af9 100644 --- a/test/ZNSSubRegistrar.test.ts +++ b/test/ZNSSubRegistrar.test.ts @@ -36,9 +36,8 @@ import { defaultSubdomainRegistration, registrationWithSetup } from "./helpers/r import { getDomainHashFromEvent } from "./helpers/events"; import { time } from "@nomicfoundation/hardhat-toolbox/network-helpers"; import { - CustomDecimalTokenMock, ZNSRootRegistrarTrunk__factory, - ZNSSubRegistrar, - ZNSSubRegistrar__factory, ZNSSubRegistrarTrunk, ZNSSubRegistrarTrunk__factory, + CustomDecimalTokenMock, + ZNSSubRegistrarTrunk, ZNSSubRegistrarTrunk__factory, ZNSSubRegistrarUpgradeMock, ZNSSubRegistrarUpgradeMock__factory, } from "../typechain"; diff --git a/test/cross-chain/CrossChainDomainBridging.network.test.ts b/test/cross-chain/CrossChainDomainBridging.network.test.ts index 4e0eb060c..3e8ed2416 100644 --- a/test/cross-chain/CrossChainDomainBridging.network.test.ts +++ b/test/cross-chain/CrossChainDomainBridging.network.test.ts @@ -1,10 +1,9 @@ import * as hre from "hardhat"; -import { getConfig, getValidateRootPriceConfig } from "../../src/deploy/campaign/environments"; +import { getConfig, getValidateRootPriceConfig } from "../../src/deploy/campaign/get-config"; import { runZnsCampaign } from "../../src/deploy/zns-campaign"; import { IZNSCampaignConfig, IZNSContracts, - IZNSZChainCrossConfig, } from "../../src/deploy/campaign/types"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { approveForDomain, registrationWithSetup } from "../helpers/register-setup"; diff --git a/test/cross-chain/ZNSDeploy.test.ts b/test/cross-chain/ZNSDeploy.test.ts index 10e5a4ef9..f536b5a18 100644 --- a/test/cross-chain/ZNSDeploy.test.ts +++ b/test/cross-chain/ZNSDeploy.test.ts @@ -5,7 +5,7 @@ import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { IZNSCampaignConfig, IZNSContracts } from "../../src/deploy/campaign/types"; import { MongoDBAdapter, resetMongoAdapter } from "@zero-tech/zdc"; import { Wallet } from "ethers"; -import { getConfig } from "../../src/deploy/campaign/environments"; +import { getConfig } from "../../src/deploy/campaign/get-config"; import { runZnsCampaign } from "../../src/deploy/zns-campaign"; import { SupportedChains } from "../../src/deploy/missions/contracts/cross-chain/portals/get-portal-dm"; import { PolygonZkEVMBridgeV2Mock } from "../../typechain"; diff --git a/test/cross-chain/mint-looper.temp.ts b/test/cross-chain/mint-looper.temp.ts index cf3ff6a29..393ef5a75 100644 --- a/test/cross-chain/mint-looper.temp.ts +++ b/test/cross-chain/mint-looper.temp.ts @@ -2,6 +2,7 @@ import * as hre from "hardhat"; import { MeowTokenMock, MeowTokenMock__factory } from "../../typechain"; +// eslint-disable-next-line @typescript-eslint/no-unused-vars const sendTxes = async () => { const amounts = Array.from({ length: 50 }, (_, i) => BigInt(i + 1) * BigInt(1e18)); diff --git a/test/helpers/deploy/deploy-zns.ts b/test/helpers/deploy/deploy-zns.ts index e2f559625..ec610538c 100644 --- a/test/helpers/deploy/deploy-zns.ts +++ b/test/helpers/deploy/deploy-zns.ts @@ -38,15 +38,10 @@ import * as hre from "hardhat"; import { ethers, upgrades } from "hardhat"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { - accessControllerName, - addressResolverName, - domainTokenName, erc1967ProxyName, fixedPricerName, DEFAULT_PRICE_CONFIG, curvePricerName, - registryName, - treasuryName, meowTokenMockName, ZNS_DOMAIN_TOKEN_NAME, ZNS_DOMAIN_TOKEN_SYMBOL, diff --git a/test/helpers/events.ts b/test/helpers/events.ts index 93ba7b412..c18bb3c8b 100644 --- a/test/helpers/events.ts +++ b/test/helpers/events.ts @@ -2,7 +2,7 @@ import { time } from "@nomicfoundation/hardhat-toolbox/network-helpers"; import { TypedContractEvent, TypedEventLog } from "../../typechain/common"; import { IZNSContractsLocal } from "./types"; -import { IZNSContracts, ZNSContract } from "../../src/deploy/campaign/types"; +import { IZNSContracts } from "../../src/deploy/campaign/types"; import * as hre from "hardhat"; @@ -44,7 +44,7 @@ export const getDomainHashFromEvent = async ({ }) : Promise => { if (!fromBlock && hre.network.name === "hardhat") { const latest = await zns.rootRegistrar.runner?.provider?.getBlockNumber(); - fromBlock = latest! - 50; + fromBlock = latest as number - 50; } const filter = zns.rootRegistrar.filters.DomainRegistered( diff --git a/test/helpers/register-setup.ts b/test/helpers/register-setup.ts index 2cbed2b40..0e4149eb7 100644 --- a/test/helpers/register-setup.ts +++ b/test/helpers/register-setup.ts @@ -3,7 +3,6 @@ import { IDistributionConfig, IFixedPriceConfig, IFullDistributionConfig, IZNSContractsLocal, - } from "./types"; import { ContractTransactionReceipt, ethers } from "ethers"; import { getDomainHashFromEvent } from "./events"; @@ -12,7 +11,7 @@ import { getTokenContract } from "./tokens"; import { ICurvePriceConfig } from "../../src/deploy/missions/types"; import { expect } from "chai"; import { IZNSContracts } from "../../src/deploy/campaign/types"; -import { MeowTokenMock, ZNSRootRegistrarTrunk } from "../../typechain"; +import { ZNSRootRegistrarTrunk } from "../../typechain"; import { getConfirmationsNumber } from "./tx"; const { ZeroAddress } = ethers; @@ -89,6 +88,7 @@ export const approveForDomain = async ({ const userBal = await tokenContract.balanceOf(user.address); if (userBal < toApprove) { + // eslint-disable-next-line no-shadow const tx = await tokenContract.connect(user).mint(user.address, toApprove); await tx.wait(confNum); } diff --git a/test/helpers/types.ts b/test/helpers/types.ts index 29f52ec0b..5f675b769 100644 --- a/test/helpers/types.ts +++ b/test/helpers/types.ts @@ -29,18 +29,9 @@ import { import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { ICurvePriceConfig } from "../../src/deploy/missions/types"; import { Addressable } from "ethers"; -import { SupportedChains } from "../../src/deploy/missions/contracts/cross-chain/portals/get-portal-dm"; -import { - NETWORK_ID_L1_TEST_DEFAULT, - NETWORK_ID_L2_TEST_DEFAULT, - ZCHAIN_ID_TEST_DEFAULT, -} from "../cross-chain/ZNSDeploy.test"; -import { ethers } from "hardhat"; import { TSupportedChain } from "../../src/deploy/missions/contracts/cross-chain/portals/types"; -export type Maybe = T | undefined; - export type GeneralContractGetter = Promise< string | boolean From 3a37559cb061c10a0ecf130f6051efe23ff423b8 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Fri, 22 Nov 2024 16:37:07 -0800 Subject: [PATCH 114/124] use viaIR when running coverage scripts --- hardhat.config.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 2b15d48fb..2316e8143 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -48,9 +48,9 @@ const config : HardhatUserConfig = { enabled: true, runs: 20000, }, - // TODO multi: we are not using this, but solcover gives an error if we don't have it - // figure out what to do here for it to work in CI! - // viaIR: true, + // Only use this when running coverage + // TODO multi: figure out if this is worth using for actual deploys to networks and tests + viaIR: process.argv.includes("coverage"), }, }, { From 3bab0dd9abbb5dd0d415dc85f0f1452ef4d3488f Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Fri, 22 Nov 2024 16:46:35 -0800 Subject: [PATCH 115/124] try changing the mongo uri dynamically for coverage run --- src/environment/env.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/environment/env.ts b/src/environment/env.ts index ead18a4cc..1ad66a75b 100644 --- a/src/environment/env.ts +++ b/src/environment/env.ts @@ -19,7 +19,7 @@ export const environment : IZNSEnvironment = { // MongoDB setup // TODO multi: should we split these into 2 for L1 and L2 ZNS contracts ?? // how do we structure the DB here ?? - MONGO_DB_URI: "mongodb://localhost:27018", + MONGO_DB_URI: `mongodb://localhost:2701${process.argv.includes("coverage") ? "7" : "8"}`, MONGO_DB_NAME: "zns-campaign", MONGO_DB_CLIENT_OPTS: "", MONGO_DB_VERSION: "", From 4b5b6bc0ed3b6da4ca243addd5c122052378de3f Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 25 Nov 2024 13:15:31 -0800 Subject: [PATCH 116/124] update to newer axios that is not affected by vulnerabilty --- package.json | 2 +- yarn.lock | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 379d746f7..3c7786101 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ }, "dependencies": { "@zero-tech/zdc": "0.1.6", - "axios": "^1.4.0", + "axios": "1.7.4", "dotenv": "16.0.3", "mongodb": "^6.1.0", "winston": "^3.11.0" diff --git a/yarn.lock b/yarn.lock index e4c3a6e9b..271bc8381 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2389,6 +2389,15 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" +axios@1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.4.tgz#4c8ded1b43683c8dd362973c393f3ede24052aa2" + integrity sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + axios@^0.21.1: version "0.21.4" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" @@ -2404,7 +2413,7 @@ axios@^0.27.2: follow-redirects "^1.14.9" form-data "^4.0.0" -axios@^1.4.0, axios@^1.5.1, axios@^1.6.5, axios@^1.6.7, axios@^1.6.8: +axios@^1.5.1, axios@^1.6.5, axios@^1.6.7, axios@^1.6.8: version "1.7.2" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621" integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw== From 17e83875ae3a959f6f0702c967ad8e00bbfb2a85 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Mon, 25 Nov 2024 14:17:15 -0800 Subject: [PATCH 117/124] small refactors and fixes --- src/deploy/zns-campaign.ts | 4 ++-- src/environment/env.ts | 13 +------------ src/environment/types.ts | 1 + .../CrossChainDomainBridging.network.test.ts | 5 ++--- test/cross-chain/ZNSDeploy.test.ts | 5 +---- test/helpers/constants.ts | 5 +++++ test/helpers/deploy/deploy-zns.ts | 8 +++----- 7 files changed, 15 insertions(+), 26 deletions(-) diff --git a/src/deploy/zns-campaign.ts b/src/deploy/zns-campaign.ts index 810d22fbb..98c461972 100644 --- a/src/deploy/zns-campaign.ts +++ b/src/deploy/zns-campaign.ts @@ -64,7 +64,7 @@ class HardhatDeployerWrapper extends HardhatDeployer { - delete process.env.SRC_CHAIN_NAME; - delete process.env.MOCK_ZKEVM_BRIDGE; - delete process.env.NETWORK_ID; - delete process.env.DEST_NETWORK_ID; - delete process.env.DEST_CHAIN_NAME; - delete process.env.DEST_CHAIN_ID; - delete process.env.SRC_ZNS_PORTAL; -}; - diff --git a/src/environment/types.ts b/src/environment/types.ts index 1dcaeec87..af5a33dce 100644 --- a/src/environment/types.ts +++ b/src/environment/types.ts @@ -1,5 +1,6 @@ export interface IZNSEnvironment { ENV_LEVEL : string; + CONFIRMATION_N ?: string; MAINNET_RPC_URL ?: string; SEPOLIA_RPC_URL ?: string; ZCHAIN_TEST_RPC_URL ?: string; diff --git a/test/cross-chain/CrossChainDomainBridging.network.test.ts b/test/cross-chain/CrossChainDomainBridging.network.test.ts index 3e8ed2416..859bc8486 100644 --- a/test/cross-chain/CrossChainDomainBridging.network.test.ts +++ b/test/cross-chain/CrossChainDomainBridging.network.test.ts @@ -20,10 +20,10 @@ import { hashDomainLabel, INITIALIZED_ERR, INVALID_CALLER_ERR, - MESSAGE_FAILED_ERR, + MESSAGE_FAILED_ERR, NETWORK_ID_L1_TEST_DEFAULT, NETWORK_ID_L2_TEST_DEFAULT, NOT_AUTHORIZED_ERR, NOT_OWNER_OF_ERR, - PaymentType, + PaymentType, ZCHAIN_ID_TEST_DEFAULT, ZERO_ADDRESS_ERR, } from "../helpers"; import { expect } from "chai"; @@ -35,7 +35,6 @@ import { MongoDBAdapter, resetMongoAdapter } from "@zero-tech/zdc"; import assert from "assert"; import { getConfirmationsNumber } from "../helpers/tx"; import { getClaimArgsFromApi } from "../helpers/cc-claim"; -import { NETWORK_ID_L1_TEST_DEFAULT, NETWORK_ID_L2_TEST_DEFAULT, ZCHAIN_ID_TEST_DEFAULT } from "./ZNSDeploy.test"; import { setDefaultEnvironment } from "../../src/environment/set-env"; diff --git a/test/cross-chain/ZNSDeploy.test.ts b/test/cross-chain/ZNSDeploy.test.ts index f536b5a18..631dde763 100644 --- a/test/cross-chain/ZNSDeploy.test.ts +++ b/test/cross-chain/ZNSDeploy.test.ts @@ -10,12 +10,9 @@ import { runZnsCampaign } from "../../src/deploy/zns-campaign"; import { SupportedChains } from "../../src/deploy/missions/contracts/cross-chain/portals/get-portal-dm"; import { PolygonZkEVMBridgeV2Mock } from "../../typechain"; import { setDefaultEnvironment } from "../../src/environment/set-env"; +import { NETWORK_ID_L1_TEST_DEFAULT, NETWORK_ID_L2_TEST_DEFAULT, ZCHAIN_ID_TEST_DEFAULT } from "../helpers"; -export const NETWORK_ID_L1_TEST_DEFAULT = 0n; -export const NETWORK_ID_L2_TEST_DEFAULT = 1n; -export const ZCHAIN_ID_TEST_DEFAULT = 2012605151n; - describe("ZNS Cross-Chain Deploy Test", () => { let znsL1 : IZNSContracts; let znsL2 : IZNSContracts; diff --git a/test/helpers/constants.ts b/test/helpers/constants.ts index 9ba5a0084..9e73663ac 100644 --- a/test/helpers/constants.ts +++ b/test/helpers/constants.ts @@ -86,3 +86,8 @@ export const treasuryName = "ZNSTreasury"; export const registrarName = "ZNSRootRegistrar"; export const erc1967ProxyName = "ERC1967Proxy"; export const subRegistrarName = "ZNSSubRegistrar"; + +// Cross-Chain +export const NETWORK_ID_L1_TEST_DEFAULT = 0n; +export const NETWORK_ID_L2_TEST_DEFAULT = 1n; +export const ZCHAIN_ID_TEST_DEFAULT = 2012605151n; diff --git a/test/helpers/deploy/deploy-zns.ts b/test/helpers/deploy/deploy-zns.ts index ec610538c..ecd308ceb 100644 --- a/test/helpers/deploy/deploy-zns.ts +++ b/test/helpers/deploy/deploy-zns.ts @@ -47,6 +47,9 @@ import { ZNS_DOMAIN_TOKEN_SYMBOL, DEFAULT_ROYALTY_FRACTION, DEFAULT_RESOLVER_TYPE, + ZCHAIN_ID_TEST_DEFAULT, + NETWORK_ID_L2_TEST_DEFAULT, + NETWORK_ID_L1_TEST_DEFAULT, } from "../constants"; import { PORTAL_ROLE, REGISTRAR_ROLE } from "../../../src/deploy/constants"; import { getProxyImplAddress } from "../utils"; @@ -55,11 +58,6 @@ import { meowTokenName, meowTokenSymbol } from "../../../src/deploy/missions/con import { transparentProxyName, znsNames } from "../../../src/deploy/missions/contracts/names"; import { TSupportedChain } from "../../../src/deploy/missions/contracts/cross-chain/portals/types"; import { SupportedChains } from "../../../src/deploy/missions/contracts/cross-chain/portals/get-portal-dm"; -import { - NETWORK_ID_L1_TEST_DEFAULT, - NETWORK_ID_L2_TEST_DEFAULT, - ZCHAIN_ID_TEST_DEFAULT, -} from "../../cross-chain/ZNSDeploy.test"; export const deployAccessController = async ({ From 976f74a06849acbe6fb3d810d03194b1193b818a Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 18 Dec 2024 16:04:59 -0800 Subject: [PATCH 118/124] regenerate yarn.lock --- yarn.lock | 1755 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 986 insertions(+), 769 deletions(-) diff --git a/yarn.lock b/yarn.lock index c2a838d75..f90db8e14 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26,11 +26,11 @@ tslib "^1.11.1" "@aws-sdk/types@^3.1.0": - version "3.654.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.654.0.tgz#d368dda5e8aff9e7b6575985bb425bbbaf67aa97" - integrity sha512-VWvbED3SV+10QJIcmU/PKjsKilsTV16d1I7/on4bvD/jo1qGeMXqLDBSen3ks/tuvXZF/mFc7ZW/W2DiLVtO7A== + version "3.714.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.714.0.tgz#de6afee1436d2d95364efa0663887f3bf0b1303a" + integrity sha512-ZjpP2gYbSFlxxaUDa1Il5AVvfggvUPbjzzB/l3q0gIE5Thd6xKW+yzEpt2mLZ5s5UaYSABZbF94g8NUOF4CVGA== dependencies: - "@smithy/types" "^3.4.2" + "@smithy/types" "^3.7.2" tslib "^2.6.2" "@aws-sdk/util-utf8-browser@^3.0.0": @@ -41,35 +41,31 @@ tslib "^2.3.1" "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.21.4": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" - integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== + version "7.26.2" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" + integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== dependencies: - "@babel/highlight" "^7.24.7" - picocolors "^1.0.0" - -"@babel/helper-validator-identifier@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" - integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== - -"@babel/highlight@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" - integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== - dependencies: - "@babel/helper-validator-identifier" "^7.24.7" - chalk "^2.4.2" + "@babel/helper-validator-identifier" "^7.25.9" js-tokens "^4.0.0" picocolors "^1.0.0" +"@babel/helper-validator-identifier@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" + integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== + "@babel/runtime@^7.4.4": - version "7.25.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.6.tgz#9afc3289f7184d8d7f98b099884c26317b9264d2" - integrity sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ== + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1" + integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== dependencies: regenerator-runtime "^0.14.0" +"@bytecodealliance/preview2-shim@0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@bytecodealliance/preview2-shim/-/preview2-shim-0.17.0.tgz#9bc1cadbb9f86c446c6f579d3431c08a06a6672e" + integrity sha512-JorcEwe4ud0x5BS/Ar2aQWOQoFzjq/7jcnxYXCvSMh0oRm0dQXzOA+hqLDBnOMks1LLBA7dmiLLsEBl09Yd6iQ== + "@colors/colors@1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" @@ -139,26 +135,26 @@ resolved "https://registry.yarnpkg.com/@ensdomains/resolver/-/resolver-0.2.4.tgz#c10fe28bf5efbf49bff4666d909aed0265efbc89" integrity sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA== -"@es-joy/jsdoccomment@~0.48.0": - version "0.48.0" - resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.48.0.tgz#5d9dc1a295cf5d1ed224dffafb4800d5c7206c27" - integrity sha512-G6QUWIcC+KvSwXNsJyDTHvqUdNoAVJPPgkc3+Uk4WBKqZvoXhlvazOgm9aL0HwihJLQf0l+tOE2UFzXBqCqgDw== +"@es-joy/jsdoccomment@~0.49.0": + version "0.49.0" + resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.49.0.tgz#e5ec1eda837c802eca67d3b29e577197f14ba1db" + integrity sha512-xjZTSFgECpb9Ohuk5yMX5RhUEbfeQcuOp8IF60e+wyzWEF0M5xeSgqsfLtvPEX8BIyOX9saZqzuGPmZ8oWc+5Q== dependencies: comment-parser "1.4.1" esquery "^1.6.0" jsdoc-type-pratt-parser "~4.1.0" "@eslint-community/eslint-utils@^4.2.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" - integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + version "4.4.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" + integrity sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA== dependencies: - eslint-visitor-keys "^3.3.0" + eslint-visitor-keys "^3.4.3" "@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1": - version "4.11.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.1.tgz#a547badfc719eb3e5f4b556325e542fbe9d7a18f" - integrity sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q== + version "4.12.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== "@eslint/eslintrc@^2.1.4": version "2.1.4" @@ -622,7 +618,7 @@ tweetnacl "^1.0.3" tweetnacl-util "^0.15.1" -"@mongodb-js/saslprep@^1.1.5": +"@mongodb-js/saslprep@^1.1.9": version "1.1.9" resolved "https://registry.yarnpkg.com/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz#e974bab8eca9faa88677d4ea4da8d09a52069004" integrity sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw== @@ -659,9 +655,9 @@ integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== "@noble/hashes@^1.4.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.5.0.tgz#abadc5ca20332db2b1b2aa3e496e9af1213570b0" - integrity sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA== + version "1.6.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.6.1.tgz#df6e5943edcea504bac61395926d6fd67869a0d5" + integrity sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w== "@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": version "1.7.1" @@ -689,53 +685,53 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@nomicfoundation/edr-darwin-arm64@0.6.2": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.6.2.tgz#52c3da9dcdab72c0447b41faa63264de84c9b6c3" - integrity sha512-o4A9SaPlxJ1MS6u8Ozqq7Y0ri2XO0jASw+qkytQyBYowNFNReoGqVSs7SCwenYCDiN+1il8+M0VAUq7wOovnCQ== +"@nomicfoundation/edr-darwin-arm64@0.6.5": + version "0.6.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.6.5.tgz#37a31565d7ef42bed9028ac44aed82144de30bd1" + integrity sha512-A9zCCbbNxBpLgjS1kEJSpqxIvGGAX4cYbpDYCU2f3jVqOwaZ/NU761y1SvuCRVpOwhoCXqByN9b7HPpHi0L4hw== -"@nomicfoundation/edr-darwin-x64@0.6.2": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.6.2.tgz#327deb548f2ae62eb456ba183970b022eb98c509" - integrity sha512-WG8BeG2eR3rFC+2/9V1hoPGW7tmNRUcuztdHUijO1h2flRsf2YWv+kEHO+EEnhGkEbgBUiwOrwlwlSMxhe2cGA== +"@nomicfoundation/edr-darwin-x64@0.6.5": + version "0.6.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.6.5.tgz#3252f6e86397af460b7a480bfe1b889464d75b89" + integrity sha512-x3zBY/v3R0modR5CzlL6qMfFMdgwd6oHrWpTkuuXnPFOX8SU31qq87/230f4szM+ukGK8Hi+mNq7Ro2VF4Fj+w== -"@nomicfoundation/edr-linux-arm64-gnu@0.6.2": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.6.2.tgz#83daecf1ced46bb4c70326e9358d0c2ae69b472a" - integrity sha512-wvHaTmOwuPjRIOqBB+paI3RBdNlG8f3e1F2zWj75EdeWwefimPzzFUs05JxOYuPO0JhDQIn2tbYUgdZbBQ+mqg== +"@nomicfoundation/edr-linux-arm64-gnu@0.6.5": + version "0.6.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.6.5.tgz#e7dc2934920b6cfabeb5ee7a5e26c8fb0d4964ac" + integrity sha512-HGpB8f1h8ogqPHTyUpyPRKZxUk2lu061g97dOQ/W4CxevI0s/qiw5DB3U3smLvSnBHKOzYS1jkxlMeGN01ky7A== -"@nomicfoundation/edr-linux-arm64-musl@0.6.2": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.6.2.tgz#b0666da450d68364975562ec5f7c2b6ee718e36b" - integrity sha512-UrOAxnsywUcEngQM2ZxIuucci0VX29hYxX7jcpwZU50HICCjxNsxnuXYPxv+IM+6gbhBY1FYvYJGW4PJcP1Nyw== +"@nomicfoundation/edr-linux-arm64-musl@0.6.5": + version "0.6.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.6.5.tgz#00459cd53e9fb7bd5b7e32128b508a6e89079d89" + integrity sha512-ESvJM5Y9XC03fZg9KaQg3Hl+mbx7dsSkTIAndoJS7X2SyakpL9KZpOSYrDk135o8s9P9lYJdPOyiq+Sh+XoCbQ== -"@nomicfoundation/edr-linux-x64-gnu@0.6.2": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.6.2.tgz#c61ae692ddf906e65078962e6d86daaa04f95d0d" - integrity sha512-gYxlPLi7fkNcmDmCwZWQa5eOfNcTDundE+TWjpyafxLAjodQuKBD4I0p4XbnuocHjoBEeNzLWdE5RShbZEXEJA== +"@nomicfoundation/edr-linux-x64-gnu@0.6.5": + version "0.6.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.6.5.tgz#5c9e4e2655caba48e0196977cba395bbde6fe97d" + integrity sha512-HCM1usyAR1Ew6RYf5AkMYGvHBy64cPA5NMbaeY72r0mpKaH3txiMyydcHibByOGdQ8iFLWpyUdpl1egotw+Tgg== -"@nomicfoundation/edr-linux-x64-musl@0.6.2": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.6.2.tgz#a2714ee7a62faf55c7994c7eaddeb32d0622801d" - integrity sha512-ev5hy9wmiHZi1GKQ1l6PJ2+UpsUh+DvK9AwiCZVEdaicuhmTfO6fdL4szgE4An8RU+Ou9DeiI1tZcq6iw++Wuw== +"@nomicfoundation/edr-linux-x64-musl@0.6.5": + version "0.6.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.6.5.tgz#9c220751b66452dc43a365f380e1e236a0a8c5a9" + integrity sha512-nB2uFRyczhAvWUH7NjCsIO6rHnQrof3xcCe6Mpmnzfl2PYcGyxN7iO4ZMmRcQS7R1Y670VH6+8ZBiRn8k43m7A== -"@nomicfoundation/edr-win32-x64-msvc@0.6.2": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.6.2.tgz#5507884a81d57f337363b7fbf9bf4ae93ff69c0c" - integrity sha512-2ZXVVcmdmEeX0Hb3IAurHUjgU3H1GIk9h7Okosdjgl3tl+BaNHxi84Us+DblynO1LRj8nL/ATeVtSfBuW3Z1vw== +"@nomicfoundation/edr-win32-x64-msvc@0.6.5": + version "0.6.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.6.5.tgz#90d3ac2a6a8a687522bda5ff2e92dd97e68126ea" + integrity sha512-B9QD/4DSSCFtWicO8A3BrsnitO1FPv7axB62wq5Q+qeJ50yJlTmyeGY3cw62gWItdvy2mh3fRM6L1LpnHiB77A== -"@nomicfoundation/edr@^0.6.1": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.6.2.tgz#6911d9a0b36bc054747dcd1ae894ce447400be31" - integrity sha512-yPUegN3sTWiAkRatCmGRkuvMgD9HSSpivl2ebAqq0aU2xgC7qmIO+YQPxQ3Z46MUoi7MrTf4e6GpbT4S/8x0ew== +"@nomicfoundation/edr@^0.6.5": + version "0.6.5" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.6.5.tgz#b3b1ebcdd0148cfe67cca128e7ebe8092e200359" + integrity sha512-tAqMslLP+/2b2sZP4qe9AuGxG3OkQ5gGgHE4isUuq6dUVjwCRPFhAOhpdFl+OjY5P3yEv3hmq9HjUGRa2VNjng== dependencies: - "@nomicfoundation/edr-darwin-arm64" "0.6.2" - "@nomicfoundation/edr-darwin-x64" "0.6.2" - "@nomicfoundation/edr-linux-arm64-gnu" "0.6.2" - "@nomicfoundation/edr-linux-arm64-musl" "0.6.2" - "@nomicfoundation/edr-linux-x64-gnu" "0.6.2" - "@nomicfoundation/edr-linux-x64-musl" "0.6.2" - "@nomicfoundation/edr-win32-x64-msvc" "0.6.2" + "@nomicfoundation/edr-darwin-arm64" "0.6.5" + "@nomicfoundation/edr-darwin-x64" "0.6.5" + "@nomicfoundation/edr-linux-arm64-gnu" "0.6.5" + "@nomicfoundation/edr-linux-arm64-musl" "0.6.5" + "@nomicfoundation/edr-linux-x64-gnu" "0.6.5" + "@nomicfoundation/edr-linux-x64-musl" "0.6.5" + "@nomicfoundation/edr-win32-x64-msvc" "0.6.5" "@nomicfoundation/ethereumjs-common@4.0.4": version "4.0.4" @@ -786,12 +782,12 @@ lodash.isequal "^4.5.0" "@nomicfoundation/hardhat-ignition@^0.15.5": - version "0.15.6" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-ignition/-/hardhat-ignition-0.15.6.tgz#7b62010e4aa37ec5afc4b1c8217b11dd21a99d93" - integrity sha512-PcMf4xlYvwHYej2jcuOd/rBNNMM5FO11vh9c+MF8+m7NxV4b6NOameL3uscoD7ghg0H2GNgnGXgQ67ryRqtdIQ== + version "0.15.9" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-ignition/-/hardhat-ignition-0.15.9.tgz#7f66ad928308f391e3ba8241655f835c7bb3546c" + integrity sha512-lSWqhaDOBt6gsqMadkRLvH6HdoFV1v8/bx7z+12cghaOloVwwn48CPoTH2iXXnkqilPGw8rdH5eVTE6UM+2v6Q== dependencies: - "@nomicfoundation/ignition-core" "^0.15.6" - "@nomicfoundation/ignition-ui" "^0.15.6" + "@nomicfoundation/ignition-core" "^0.15.9" + "@nomicfoundation/ignition-ui" "^0.15.9" chalk "^4.0.0" debug "^4.3.2" fs-extra "^10.0.0" @@ -811,24 +807,24 @@ integrity sha512-jhcWHp0aHaL0aDYj8IJl80v4SZXWMS1A2XxXa1CA6pBiFfJKuZinCkO6wb+POAt0LIfXB3gA3AgdcOccrcwBwA== "@nomicfoundation/hardhat-verify@^2.0.8": - version "2.0.11" - resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.11.tgz#4ce12b592e01ee93a81933924609c233ed00d951" - integrity sha512-lGIo4dNjVQFdsiEgZp3KP6ntLiF7xJEJsbNHfSyIiFCyI0Yv0518ElsFtMC5uCuHEChiBBMrib9jWQvHHT+X3Q== + version "2.0.12" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.12.tgz#480819a245a2db0b127e473c62079f7b4f16daa8" + integrity sha512-Lg3Nu7DCXASQRVI/YysjuAX2z8jwOCbS0w5tz2HalWGSTZThqA0v9N0v0psHbKNqzPJa8bNOeapIVSziyJTnAg== 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" + picocolors "^1.1.0" semver "^6.3.0" table "^6.8.0" undici "^5.14.0" -"@nomicfoundation/ignition-core@^0.15.6": - version "0.15.6" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ignition-core/-/ignition-core-0.15.6.tgz#bc5fd58f6281f4b8a43f4b9a2d29a112c451048c" - integrity sha512-9eD1NJ2G4vh7IleRNmCz/3bGVoNEPYrRVPqx0uvWzG2xD226GGQcTgtK+NovyxsQOE/AcLF1xjX3/+8kNc1sSg== +"@nomicfoundation/ignition-core@^0.15.9": + version "0.15.9" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ignition-core/-/ignition-core-0.15.9.tgz#5c9401ad93e0c15f633afaf9b3d055b57a881604" + integrity sha512-X8W+7UP/UQPorpHUnGvA1OdsEr/edGi8tDpNwEqzaLm83FMZVbRWdOsr3vNICHN2XMzNY/xIm18Cx7xGKL2PQw== dependencies: "@ethersproject/address" "5.6.1" "@nomicfoundation/solidity-analyzer" "^0.1.1" @@ -840,70 +836,17 @@ lodash "4.17.21" ndjson "2.0.0" -"@nomicfoundation/ignition-ui@^0.15.6": - version "0.15.6" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ignition-ui/-/ignition-ui-0.15.6.tgz#0f71a5f1bf38d91a875b8fd212f3eafc9a9d607b" - integrity sha512-CW14g/BVcGZtBSF1K4eZSCjyvtz1fr9yppkFKC+Z0+sm/lXFWpwcwaVN+UiugQ/9wz9HAfSk4Y0gagdAMiSs0w== - -"@nomicfoundation/slang-darwin-arm64@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-darwin-arm64/-/slang-darwin-arm64-0.17.0.tgz#8cded3c24322624e3b6618760caba8e840bd1c1d" - integrity sha512-O0q94EUtoWy9A5kOTOa9/khtxXDYnLqmuda9pQELurSiwbQEVCPQL8kb34VbOW+ifdre66JM/05Xw9JWhIZ9sA== - -"@nomicfoundation/slang-darwin-x64@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-darwin-x64/-/slang-darwin-x64-0.17.0.tgz#6ebeb33a2ced89fc6023f6cda4af96403486038a" - integrity sha512-IaDbHzvT08sBK2HyGzonWhq1uu8IxdjmTqAWHr25Oh/PYnamdi8u4qchZXXYKz/DHLoYN3vIpBXoqLQIomhD/g== - -"@nomicfoundation/slang-linux-arm64-gnu@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-linux-arm64-gnu/-/slang-linux-arm64-gnu-0.17.0.tgz#41c7e57a9b1a3aee6911f0cab22e683c149fb470" - integrity sha512-Lj4anvOsQZxs1SycG8VyT2Rl2oqIhyLSUCgGepTt3CiJ/bM+8r8bLJIgh8vKkki4BWz49YsYIgaJB2IPv8FFTw== - -"@nomicfoundation/slang-linux-arm64-musl@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-linux-arm64-musl/-/slang-linux-arm64-musl-0.17.0.tgz#9c4b51689274ae75c2c8a4cddd2e1cc0a79c191d" - integrity sha512-/xkTCa9d5SIWUBQE3BmLqDFfJRr4yUBwbl4ynPiGUpRXrD69cs6pWKkwjwz/FdBpXqVo36I+zY95qzoTj/YhOA== - -"@nomicfoundation/slang-linux-x64-gnu@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-linux-x64-gnu/-/slang-linux-x64-gnu-0.17.0.tgz#c3a3b6a7b775fc617832958d10e6664bf86d39d0" - integrity sha512-oe5IO5vntOqYvTd67deCHPIWuSuWm6aYtT2/0Kqz2/VLtGz4ClEulBSRwfnNzBVtw2nksWipE1w8BzhImI7Syg== - -"@nomicfoundation/slang-linux-x64-musl@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-linux-x64-musl/-/slang-linux-x64-musl-0.17.0.tgz#725118ff99a7217b9f1d1bd84411d9442084077d" - integrity sha512-PpYCI5K/kgLAMXaPY0V4VST5gCDprEOh7z/47tbI8kJQumI5odjsj/Cs8MpTo7/uRH6flKYbVNgUzcocWVYrAQ== +"@nomicfoundation/ignition-ui@^0.15.9": + version "0.15.9" + resolved "https://registry.yarnpkg.com/@nomicfoundation/ignition-ui/-/ignition-ui-0.15.9.tgz#ba94174f44e5c0de01d9968633fdf925a9585768" + integrity sha512-8lzbT7gpJ5PoowPQDQilkwdyqBviUKDMoHp/5rhgnwG1bDslnCS+Lxuo6s9R2akWu9LtEL14dNyqQb6WsURTag== -"@nomicfoundation/slang-win32-arm64-msvc@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-win32-arm64-msvc/-/slang-win32-arm64-msvc-0.17.0.tgz#9c8bc4ccf21eaaac0cfcb6d3954ede4e2dea4c02" - integrity sha512-u/Mkf7OjokdBilP7QOJj6QYJU4/mjkbKnTX21wLyCIzeVWS7yafRPYpBycKIBj2pRRZ6ceAY5EqRpb0aiCq+0Q== - -"@nomicfoundation/slang-win32-ia32-msvc@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-win32-ia32-msvc/-/slang-win32-ia32-msvc-0.17.0.tgz#3fc5d00a3f8c1d85a5e94146af78a5526a4f3d27" - integrity sha512-XJBVQfNnZQUv0tP2JSJ573S+pmgrLWgqSZOGaMllnB/TL1gRci4Z7dYRJUF2s82GlRJE+FHSI2Ro6JISKmlXCg== - -"@nomicfoundation/slang-win32-x64-msvc@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang-win32-x64-msvc/-/slang-win32-x64-msvc-0.17.0.tgz#f6a5e3250fa07cbda49151edeb80f09090e5b71a" - integrity sha512-zPGsAeiTfqfPNYHD8BfrahQmYzA78ZraoHKTGraq/1xwJwzBK4bu/NtvVA4pJjBV+B4L6DCxVhSbpn40q26JQA== - -"@nomicfoundation/slang@^0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang/-/slang-0.17.0.tgz#d9c25cd711ebf3490c9d0c99e9b4ca2481341a6b" - integrity sha512-1GlkGRcGpVnjFw9Z1vvDKOKo2mzparFt7qrl2pDxWp+jrVtlvej98yCMX52pVyrYE7ZeOSZFnx/DtsSgoukStQ== - dependencies: - "@nomicfoundation/slang-darwin-arm64" "0.17.0" - "@nomicfoundation/slang-darwin-x64" "0.17.0" - "@nomicfoundation/slang-linux-arm64-gnu" "0.17.0" - "@nomicfoundation/slang-linux-arm64-musl" "0.17.0" - "@nomicfoundation/slang-linux-x64-gnu" "0.17.0" - "@nomicfoundation/slang-linux-x64-musl" "0.17.0" - "@nomicfoundation/slang-win32-arm64-msvc" "0.17.0" - "@nomicfoundation/slang-win32-ia32-msvc" "0.17.0" - "@nomicfoundation/slang-win32-x64-msvc" "0.17.0" +"@nomicfoundation/slang@^0.18.3": + version "0.18.3" + resolved "https://registry.yarnpkg.com/@nomicfoundation/slang/-/slang-0.18.3.tgz#976b6c3820081cebf050afbea434038aac9313cc" + integrity sha512-YqAWgckqbHM0/CZxi9Nlf4hjk9wUNLC9ngWCWBiqMxPIZmzsVKYuChdlrfeBPQyvQQBoOhbx+7C1005kLVQDZQ== + dependencies: + "@bytecodealliance/preview2-shim" "0.17.0" "@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.2": version "0.1.2" @@ -1195,12 +1138,12 @@ "@octokit/types" "^12.6.0" "@octokit/plugin-retry@^6.0.0": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@octokit/plugin-retry/-/plugin-retry-6.0.1.tgz#3257404f7cc418e1c1f13a7f2012c1db848b7693" - integrity sha512-SKs+Tz9oj0g4p28qkZwl/topGcb0k0qPNX/i7vBKmDsjoeqnVfFUquqrE/O9oJY7+oLzdCtkiWSXLpLjvl6uog== + version "6.1.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-retry/-/plugin-retry-6.1.0.tgz#cf5b92223246327ca9c7e17262b93ffde028ab0a" + integrity sha512-WrO3bvq4E1Xh1r2mT9w6SDFg01gFmP81nIG77+p/MqW1JeXXgL++6umim3t6x0Zj5pZm3rXAN+0HEjmmdhIRig== dependencies: "@octokit/request-error" "^5.0.0" - "@octokit/types" "^12.0.0" + "@octokit/types" "^13.0.0" bottleneck "^2.15.3" "@octokit/plugin-throttling@^8.0.0": @@ -1230,7 +1173,7 @@ "@octokit/types" "^13.1.0" universal-user-agent "^6.0.0" -"@octokit/types@^12.0.0", "@octokit/types@^12.2.0", "@octokit/types@^12.6.0": +"@octokit/types@^12.2.0", "@octokit/types@^12.6.0": version "12.6.0" resolved "https://registry.yarnpkg.com/@octokit/types/-/types-12.6.0.tgz#8100fb9eeedfe083aae66473bd97b15b62aedcb2" integrity sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw== @@ -1238,9 +1181,9 @@ "@octokit/openapi-types" "^20.0.0" "@octokit/types@^13.0.0", "@octokit/types@^13.1.0": - version "13.5.1" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-13.5.1.tgz#5685a91f295195ddfff39723b093b0df9609ce6e" - integrity sha512-F41lGiWBKPIWPBgjSvaDXTTQptBujnozENAK3S//nj7xsFdYdirImKlBB/hTjr+Vii68SM+8jG3UJWRa6DMuDA== + version "13.6.2" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-13.6.2.tgz#e10fc4d2bdd65d836d1ced223b03ad4cfdb525bd" + integrity sha512-WpbZfZUcZU77DrSW4wbsSgTPfKcp286q3ItaIgvSbBpZJlu6mnYXAkjZz6LVZPXkEvLIM8McanyZejKTYUHipA== dependencies: "@octokit/openapi-types" "^22.2.0" @@ -1255,114 +1198,141 @@ integrity sha512-T5tO/KD++m+Ph74ppPPmNuhyrvNcsMDgQWt+pGshNJMsTf9UvmhBNyyOqVAL91UeuqDI0FHAbBV1+NnMg7ffFA== "@openzeppelin/contracts-upgradeable@^5.0.2": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.0.2.tgz#3e5321a2ecdd0b206064356798c21225b6ec7105" - integrity sha512-0MmkHSHiW2NRFiT9/r5Lu4eJq5UJ4/tzlOgYXNAIj/ONkQTVnz22pLxDvp4C4uZ9he7ZFvGn3Driptn1/iU7tQ== + version "5.1.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.1.0.tgz#4d37648b7402929c53e2ff6e45749ecff91eb2b6" + integrity sha512-AIElwP5Ck+cslNE+Hkemf5SxjJoF4wBvvjxc27Rp+9jaPs/CLIaUBMYe1FNzhdiN0cYuwGRmYaRHmmntuiju4Q== "@openzeppelin/contracts@^5.0.2": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.0.2.tgz#b1d03075e49290d06570b2fd42154d76c2a5d210" - integrity sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA== + version "5.1.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.1.0.tgz#4e61162f2a2bf414c4e10c45eca98ce5f1aadbd4" + integrity sha512-p1ULhl7BXzjjbha5aqst+QMLY+4/LCWADXOCsmLHRM77AqiPjnd9vvUN9sosUfhL9JGKpZ0TjEGxgvnizmWGSA== -"@openzeppelin/defender-sdk-account-client@^1.14.4": - version "1.14.4" - resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-account-client/-/defender-sdk-account-client-1.14.4.tgz#06f822cb57910fbfe15826397ede14785285626f" - integrity sha512-SxV4oTofO/xf1IcNJ5Dcc6XdXrxmu2jNPIeOx6GhdwVmO2LDVgi/9pAwXNlW1ihZ4wkJf/BSz3JsRJCgrwkadQ== +"@openzeppelin/defender-sdk-account-client@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-account-client/-/defender-sdk-account-client-1.15.2.tgz#be7d250acf0f86ce8f74309ddbb2ddfe0297e19c" + integrity sha512-lhYf1rBtac1MBbKP/ALgkjUhVulqo45RtaemTP9xI6BwUCCb4nq2SSKM82UN5sOE2I+VXSbPXf8w91bao5Mmmg== dependencies: - "@openzeppelin/defender-sdk-base-client" "^1.14.4" + "@openzeppelin/defender-sdk-base-client" "^1.15.2" axios "^1.7.2" lodash "^4.17.21" -"@openzeppelin/defender-sdk-action-client@^1.14.4": - version "1.14.4" - resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-action-client/-/defender-sdk-action-client-1.14.4.tgz#c2c6dd17f7c13e1bf7863730ac4d06a78d272689" - integrity sha512-YoRW3ZST1YCGkBIPtzJNPR0ajK9H0cxhT+evbRX9hgiUNJTgTDJeKGX+qOKOMjKOPXikiYUc2TpmKwP1I2tP5A== +"@openzeppelin/defender-sdk-action-client@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-action-client/-/defender-sdk-action-client-1.15.2.tgz#026e1257e98f8abd8d7b31f9a296e7beaee433f1" + integrity sha512-PpVFKaDU9jBNIoJWfwIA5/9I+qse/4rzEY3CqPvH1z7qGsUjKmImTcQA6SpEzbbvLFOjBY/cuHz6vaf/Vdttcg== dependencies: - "@openzeppelin/defender-sdk-base-client" "^1.14.4" + "@openzeppelin/defender-sdk-base-client" "^1.15.2" axios "^1.7.2" dotenv "^16.3.1" glob "^11.0.0" jszip "^3.10.1" lodash "^4.17.21" -"@openzeppelin/defender-sdk-base-client@^1.14.4": - version "1.14.4" - resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-base-client/-/defender-sdk-base-client-1.14.4.tgz#3ccd3beb94cba61883f769afe7e6fdbdc5daa12d" - integrity sha512-tOePVQLKpqfGQ1GMzHvSBNd2psPYd86LDNpvdl5gjD0Y2kW/zNh5qBXy29RraGtk/qc8zs9hzS5pAOh0vhGkGQ== +"@openzeppelin/defender-sdk-address-book-client@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-address-book-client/-/defender-sdk-address-book-client-1.15.2.tgz#eae24b9f948e736ffe4161bbd6778d199596cf66" + integrity sha512-t6T3DA1BOMhttQ+EOLM9a+M4ls3XSdJlDV1+LfY0G70gLKcMSuNHJpNE83GuRW8P6k5544CaEYy6bgPy0m5myw== + dependencies: + "@openzeppelin/defender-sdk-base-client" "^1.15.2" + dotenv "^16.3.1" + lodash "^4.17.21" + +"@openzeppelin/defender-sdk-approval-process-client@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-approval-process-client/-/defender-sdk-approval-process-client-1.15.2.tgz#e719d994dc0646df8620714b78688454338cf936" + integrity sha512-8XuNlHFJuANwkOMKBOsvPHgihdsQj8SXoPsBToMXlGJTu/joQ4LaNd78+0f2QegqVTbRiEoaW6gu0o24zi/6kg== + dependencies: + "@openzeppelin/defender-sdk-base-client" "^1.15.2" + axios "^1.6.7" + lodash "^4.17.21" + +"@openzeppelin/defender-sdk-base-client@^1.14.4", "@openzeppelin/defender-sdk-base-client@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-base-client/-/defender-sdk-base-client-1.15.2.tgz#aae7ec001365968b81ccce087f39a6eb52fa13f9" + integrity sha512-N3ZTeH8TXyklL7yNPMLUv0dxQwT78DTkOEDhzMS2/QE2FxbXrclSseoeeXxl6UYI61RBtZKn+okbSsbwiB5QWQ== dependencies: amazon-cognito-identity-js "^6.3.6" async-retry "^1.3.3" -"@openzeppelin/defender-sdk-deploy-client@^1.14.4": - version "1.14.4" - resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-deploy-client/-/defender-sdk-deploy-client-1.14.4.tgz#1feb94575a32ed4ddee81d03cdb060064936a528" - integrity sha512-+diSoz1zid37LMsY2RDxI+uAsYx9Eryg8Vz+yfvuyd56fXrzjQEln7BBtYQw+2zp9yvyAByOL5XSQdrQga9OBQ== +"@openzeppelin/defender-sdk-deploy-client@^1.14.4", "@openzeppelin/defender-sdk-deploy-client@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-deploy-client/-/defender-sdk-deploy-client-1.15.2.tgz#3b1d953aa66b6cdee13e7e672a488af2e2acf974" + integrity sha512-zspzMqh+OC8arXAkgBqTUDVO+NfCkt54UrsmQHbA3UAjr5TiDXKycBKU5ORb01hE+2gAmoPwEpDW9uS2VLg33A== dependencies: - "@openzeppelin/defender-sdk-base-client" "^1.14.4" + "@openzeppelin/defender-sdk-base-client" "^1.15.2" axios "^1.7.2" lodash "^4.17.21" -"@openzeppelin/defender-sdk-key-value-store-client@^1.14.4": - version "1.14.4" - resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-key-value-store-client/-/defender-sdk-key-value-store-client-1.14.4.tgz#2e9e93e41f41fcaef4f05fbe50af61e1227dc79f" - integrity sha512-8InEiGeUpahKuWTgFWUyS5DS9HkXeHWMW+yxolGwxCy+OIGEPfxg/oMBXC2UzGn3BfIvWic/CLspFzuWIlarEQ== +"@openzeppelin/defender-sdk-key-value-store-client@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-key-value-store-client/-/defender-sdk-key-value-store-client-1.15.2.tgz#36a24be4f16da56ddd00d1ab4d5b655b2f0945b9" + integrity sha512-b98uKFr8psdSh7UPjLqij5B6OpnYQuQIqCzXWf6RNVIJHlrdlhme2eClcZUVxN2L0AjcpELISRTq24t/sCyd8Q== dependencies: - "@openzeppelin/defender-sdk-base-client" "^1.14.4" + "@openzeppelin/defender-sdk-base-client" "^1.15.2" axios "^1.7.2" fs-extra "^11.2.0" lodash "^4.17.21" -"@openzeppelin/defender-sdk-monitor-client@^1.14.4": - version "1.14.4" - resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-monitor-client/-/defender-sdk-monitor-client-1.14.4.tgz#092e6cb3d18f4872b6fe81b6a1c769c7a08095a1" - integrity sha512-PSesKNicY37LiHD2EVsyZXQrHRZsPYaVhUuMdqfNoJZexPZfnhv7c2A481tt+hTwAccJguQF69NLqylpdgtpFQ== +"@openzeppelin/defender-sdk-monitor-client@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-monitor-client/-/defender-sdk-monitor-client-1.15.2.tgz#c8e741737e6f4080da9922550c3c879a9a060f4e" + integrity sha512-SW+je3RvfAbS43gFtyPcPfloFiAj0VJJZpXsYpolA28j94pEBz5EdYczfNwq/QqyK5adAvASdHobCU9ywVlokw== dependencies: - "@openzeppelin/defender-sdk-base-client" "^1.14.4" + "@openzeppelin/defender-sdk-base-client" "^1.15.2" axios "^1.7.2" ethers "^6.9.0" lodash "^4.17.21" -"@openzeppelin/defender-sdk-network-client@^1.14.4": - version "1.14.4" - resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-network-client/-/defender-sdk-network-client-1.14.4.tgz#0f89c45f601e28c2f87c487b62b48d9cd4b5b956" - integrity sha512-OS0H5b0vgYacJcwkvUFJUaRuyUaXhIRl916W5xLvGia5H6i/qn3dP8MZ7oLcPwKc8jB+ucRytO4H/AHsea0aVA== +"@openzeppelin/defender-sdk-network-client@^1.14.4", "@openzeppelin/defender-sdk-network-client@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-network-client/-/defender-sdk-network-client-1.15.2.tgz#7178836d9861272ad509d93dea8739a5c4bf86c1" + integrity sha512-9r9pegc1aR7xzP9fmj1zvkk0OXMRJE10JabxxiJzAQQgmNXDeTGI6W5bFgrNJfxzcImNGqddJ3K4weKdLyL21A== dependencies: - "@openzeppelin/defender-sdk-base-client" "^1.14.4" + "@openzeppelin/defender-sdk-base-client" "^1.15.2" axios "^1.7.2" lodash "^4.17.21" -"@openzeppelin/defender-sdk-notification-channel-client@^1.14.4": - version "1.14.4" - resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-notification-channel-client/-/defender-sdk-notification-channel-client-1.14.4.tgz#5387d0f14f344a1c0dfb9aedf75f64ab22c3ded1" - integrity sha512-xCMUe4pseRA+tQMrd6PDoZ4aToDi0LPrVAlBXFDFxCZ6/TzcsVA/PgfM4Hy6R+9vF+S5gMFGuJkCpDtlcYfo5A== +"@openzeppelin/defender-sdk-notification-channel-client@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-notification-channel-client/-/defender-sdk-notification-channel-client-1.15.2.tgz#8539b5f0ed3a6a3b931afb777e7ef41ca5e09027" + integrity sha512-42c9rpQdFS9vQgwOetrsnMbnLPeQnD680Ex6jSvOK497NI7RNP8eFI4vHgzNBhCQYdlMj+oEY7gIhD7Vs0kUow== dependencies: - "@openzeppelin/defender-sdk-base-client" "^1.14.4" + "@openzeppelin/defender-sdk-base-client" "^1.15.2" axios "^1.7.2" lodash "^4.17.21" -"@openzeppelin/defender-sdk-proposal-client@^1.14.4": - version "1.14.4" - resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-proposal-client/-/defender-sdk-proposal-client-1.14.4.tgz#fec7080fc7712e8c7daef923883ddbbdc20e76ee" - integrity sha512-xVI5A6wJb/XfqVAEkSsINrgGkNznw0eZL7CnzX1OUnZ4irrlaD4HpG/CkFgVWLx8tRIMFlUtb3as3KMc/sO8eg== +"@openzeppelin/defender-sdk-proposal-client@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-proposal-client/-/defender-sdk-proposal-client-1.15.2.tgz#52ae0cfd6ff323d79a98de6ac4ad195d1dd56df9" + integrity sha512-Ib2pHGbgtEEnLagWIzW1eesbzGqIc0QKyHVyM1aIqcCJpvKZU9TKCgT7FMqo8m/g2HdJNY74qW3964j9/6ehbw== dependencies: - "@openzeppelin/defender-sdk-base-client" "^1.14.4" + "@openzeppelin/defender-sdk-base-client" "^1.15.2" axios "^1.7.2" ethers "^6.9.0" lodash "^4.17.21" -"@openzeppelin/defender-sdk-relay-client@^1.14.4": - version "1.14.4" - resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-relay-client/-/defender-sdk-relay-client-1.14.4.tgz#2649c5e7b237626df50943aef6001fb0ec18f08d" - integrity sha512-L+vPUeeg36muOy1Oh8wqNEJ8qXXQrFytYZerPS9N/Vf7TQBZoKUkuVq69dw7+XYq/ouqbppvAvUtV9SnyDkYpQ== +"@openzeppelin/defender-sdk-relay-client@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-relay-client/-/defender-sdk-relay-client-1.15.2.tgz#ede03f9680624dfc82187ab03021bd5135450f05" + integrity sha512-QqqprIcVcSS/xlos1gRtW2RIh5AtsOzY9vGnJ2jo5YcutUQrfUCICBigkn+BbeSHesleUxk/zGJInPKol9ir0g== dependencies: - "@openzeppelin/defender-sdk-base-client" "^1.14.4" + "@openzeppelin/defender-sdk-base-client" "^1.15.2" + axios "^1.7.2" + lodash "^4.17.21" + +"@openzeppelin/defender-sdk-relay-group-client@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-relay-group-client/-/defender-sdk-relay-group-client-1.15.2.tgz#e12bbcff5cbd21c011b9699aa3f8c5ba84b3ddd4" + integrity sha512-lVip1lrk7F42a3Em6B6FRY8GH05oAUJX5vYFI0m6Ucr5pKEmz221Q1J8GL7NJU5S7THdOpXqEvGzJRmHeYOPwg== + dependencies: + "@openzeppelin/defender-sdk-base-client" "^1.15.2" axios "^1.7.2" lodash "^4.17.21" -"@openzeppelin/defender-sdk-relay-signer-client@^1.14.4": - version "1.14.4" - resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-relay-signer-client/-/defender-sdk-relay-signer-client-1.14.4.tgz#583b7a202ac5f619b5c4f954c42c2a85c0f39a32" - integrity sha512-zjVhor/LEHYG6Gf+GEFTrwsuGZjVbzqTqQew4X622FY38P13PpcEIdXDgbokqdlX8zpECcggD2kmTTDgVWRqjA== +"@openzeppelin/defender-sdk-relay-signer-client@^1.15.2": + version "1.15.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk-relay-signer-client/-/defender-sdk-relay-signer-client-1.15.2.tgz#6b195d7db8b94dbc894b3cb620dae412c4b6a35b" + integrity sha512-AqQOAkqOdpO7J+n1hzUWHVRvsb93t8Nb3wQEXJN+/UMcWfoKTOLSYOvjOMQ4PbEUmM8aI+YcQxJL5VfJlIXngQ== dependencies: "@ethersproject/bignumber" "^5.7.0" "@ethersproject/bytes" "^5.7.0" @@ -1371,50 +1341,53 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/providers" "^5.7.2" "@ethersproject/strings" "^5.7.0" - "@openzeppelin/defender-sdk-base-client" "^1.14.4" + "@openzeppelin/defender-sdk-base-client" "^1.15.2" amazon-cognito-identity-js "^6.3.6" axios "^1.7.2" ethers "^6.9.0" lodash "^4.17.21" "@openzeppelin/defender-sdk@^1.7.0": - version "1.14.4" - resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk/-/defender-sdk-1.14.4.tgz#e7953976fef682d28e3885a905bb70397f028bb0" - integrity sha512-QFXvqeLzfFxyRq5bw+7h2pq65pztNKBUy0vtizdSeQMA6MZ5wqDyTu/8bziYdQH+BmKzMqYBgErJAmic2XCzZQ== - dependencies: - "@openzeppelin/defender-sdk-account-client" "^1.14.4" - "@openzeppelin/defender-sdk-action-client" "^1.14.4" - "@openzeppelin/defender-sdk-base-client" "^1.14.4" - "@openzeppelin/defender-sdk-deploy-client" "^1.14.4" - "@openzeppelin/defender-sdk-key-value-store-client" "^1.14.4" - "@openzeppelin/defender-sdk-monitor-client" "^1.14.4" - "@openzeppelin/defender-sdk-network-client" "^1.14.4" - "@openzeppelin/defender-sdk-notification-channel-client" "^1.14.4" - "@openzeppelin/defender-sdk-proposal-client" "^1.14.4" - "@openzeppelin/defender-sdk-relay-client" "^1.14.4" - "@openzeppelin/defender-sdk-relay-signer-client" "^1.14.4" + version "1.15.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/defender-sdk/-/defender-sdk-1.15.2.tgz#8ce5d4e27a3cbf1371490f4319d4c19bae178bb0" + integrity sha512-Pt7MR+kzhsBfEQvW/cAOgLGb498x3Oq91G15GQ+g+cl978IpQgqx8rneZPv3aoQE5ipIk6EtWJlOl+tIAARKVg== + dependencies: + "@openzeppelin/defender-sdk-account-client" "^1.15.2" + "@openzeppelin/defender-sdk-action-client" "^1.15.2" + "@openzeppelin/defender-sdk-address-book-client" "^1.15.2" + "@openzeppelin/defender-sdk-approval-process-client" "^1.15.2" + "@openzeppelin/defender-sdk-base-client" "^1.15.2" + "@openzeppelin/defender-sdk-deploy-client" "^1.15.2" + "@openzeppelin/defender-sdk-key-value-store-client" "^1.15.2" + "@openzeppelin/defender-sdk-monitor-client" "^1.15.2" + "@openzeppelin/defender-sdk-network-client" "^1.15.2" + "@openzeppelin/defender-sdk-notification-channel-client" "^1.15.2" + "@openzeppelin/defender-sdk-proposal-client" "^1.15.2" + "@openzeppelin/defender-sdk-relay-client" "^1.15.2" + "@openzeppelin/defender-sdk-relay-group-client" "^1.15.2" + "@openzeppelin/defender-sdk-relay-signer-client" "^1.15.2" "@openzeppelin/hardhat-upgrades@^3.1.1", "@openzeppelin/hardhat-upgrades@^3.3.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-3.4.0.tgz#a67e9510c5c6a8ebb2534458164bd168cf4cb6b1" - integrity sha512-bfPtUCmRT6kfh/Mz56tAAGS8N22Zr3rdCMG3E3g8CW61QRGsaeFHnZRetBgu1JoKocjCavEtis5/x60m+o5XUQ== + version "3.7.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-3.7.0.tgz#fc9562ab01edfa1eafb49870d8bf37e038a3ce49" + integrity sha512-dTnqqTIZUOyEzL62FIusZPeac9CqTD+x3Q5h+46JBALgS9DubUq/jXMhiE3JKLco3RELZQCh/9GYKBoUA0R2DQ== dependencies: "@openzeppelin/defender-sdk-base-client" "^1.14.4" "@openzeppelin/defender-sdk-deploy-client" "^1.14.4" "@openzeppelin/defender-sdk-network-client" "^1.14.4" - "@openzeppelin/upgrades-core" "^1.38.0" + "@openzeppelin/upgrades-core" "^1.41.0" chalk "^4.1.0" debug "^4.1.1" ethereumjs-util "^7.1.5" proper-lockfile "^4.1.1" undici "^6.11.1" -"@openzeppelin/upgrades-core@^1.32.2", "@openzeppelin/upgrades-core@^1.38.0": - version "1.38.0" - resolved "https://registry.yarnpkg.com/@openzeppelin/upgrades-core/-/upgrades-core-1.38.0.tgz#883f3ff55a63122b329fd8b0107815411ed0fbdd" - integrity sha512-0kbc6Wd6S8/Kmhg7oqRIn+GBpAL+EccYQh+SjgVBEktpkzTDN56KHuuxYHXnpXclWaO6l7u/TRMe6LsHCHqJHw== +"@openzeppelin/upgrades-core@^1.32.2", "@openzeppelin/upgrades-core@^1.41.0": + version "1.41.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/upgrades-core/-/upgrades-core-1.41.0.tgz#3a5e044cf53acd50c392f3297e7c37e4ff8f8355" + integrity sha512-+oryinqZnxkiZvg7bWqWX4Ki/CNwVUZEqC6Elpi5PQoahpL3/6Sq9xjIozD5AiI2O61h8JHQ+A//5NtczyavJw== dependencies: - "@nomicfoundation/slang" "^0.17.0" + "@nomicfoundation/slang" "^0.18.3" cbor "^9.0.0" chalk "^4.1.0" compare-versions "^6.0.0" @@ -1701,10 +1674,10 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz#719df7fb41766bc143369eaa0dd56d8dc87c9958" integrity sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg== -"@smithy/types@^3.4.2": - version "3.4.2" - resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.4.2.tgz#aa2d087922d57205dbad68df8a45c848699c551e" - integrity sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w== +"@smithy/types@^3.7.2": + version "3.7.2" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.7.2.tgz#05cb14840ada6f966de1bf9a9c7dd86027343e10" + integrity sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg== dependencies: tslib "^2.6.2" @@ -1720,6 +1693,11 @@ resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.18.0.tgz#8e77a02a09ecce957255a2f48c9a7178ec191908" integrity sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA== +"@solidity-parser/parser@^0.19.0": + version "0.19.0" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.19.0.tgz#37a8983b2725af9b14ff8c4a475fa0e98d773c3f" + integrity sha512-RV16k/qIxW/wWc+mLzV3ARyKUaMUTBy9tOLMzFhtNSKYeTAanQ3a5MudJKf/8arIFnA2L27SNjarQKmFg0w/jA== + "@szmarczak/http-timer@^5.0.1": version "5.0.1" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a" @@ -1727,10 +1705,10 @@ dependencies: defer-to-connect "^2.0.1" -"@tenderly/api-client@^1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@tenderly/api-client/-/api-client-1.0.1.tgz#0238bf5cc48e9a87a8f4b4c4a13743aab8721ea8" - integrity sha512-u/982299rccyvkuGuyM93AxnGXFHpIs8ZozD+E8gXHIRxLPyz/rZW/mjrcOGW9EBJwCvimVpLKcdDTKQ+DJTlQ== +"@tenderly/api-client@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@tenderly/api-client/-/api-client-1.1.0.tgz#fa06adf17ecc1ef83c5fb8536b71b542e7023228" + integrity sha512-kyye7TQ+RbDbJ7bSUjNf/O9fTtRYNUDIEUZQSrmNonowMw5/EpNi664eWaOoC00NEzxgttVrtme/GHvIOu7rNg== dependencies: axios "^0.27.2" cli-table3 "^0.6.2" @@ -1741,12 +1719,12 @@ prompts "^2.4.2" tslog "^4.4.0" -"@tenderly/hardhat-integration@^1.0.0": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@tenderly/hardhat-integration/-/hardhat-integration-1.0.2.tgz#639519ad1d47bf11bf68d34a30355a50ed85130f" - integrity sha512-ZcmorNYGEdmNJ2SVZx90bpOcK43Ay6fOAJem+qbL3o8iRlxfcDvr72kTBq7Ed/CPyfvLWBVwcyGxQIsQWNMruQ== +"@tenderly/hardhat-integration@^1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@tenderly/hardhat-integration/-/hardhat-integration-1.1.1.tgz#6921c3f524d344efdd9b5f18c0500e9ac7ddcd27" + integrity sha512-VHa380DrKv+KA1N4vbJGLDoghbVqMZ4wEozbxRfCzlkSs5V1keNgudRSUFK6lgfKhkoAWRO+dA8MZYnJOvUOkA== dependencies: - "@tenderly/api-client" "^1.0.0" + "@tenderly/api-client" "^1.1.0" axios "^1.6.7" dotenv "^16.4.5" fs-extra "^10.1.0" @@ -1758,9 +1736,9 @@ typescript "^5.5.4" "@tenderly/hardhat-tenderly@^2.0.1": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@tenderly/hardhat-tenderly/-/hardhat-tenderly-2.4.0.tgz#c1a7e5fc4a88323169253f24a9c0d7acc61bf1b9" - integrity sha512-WbKdjJ03JK2lTjtkNorOQiN6QRqzBkCUbkPcxfYAJHEaQSfIEZrP9Ui7mFl1quP9L5mFfu8PFZtXcxzzHGIBWA== + version "2.5.1" + resolved "https://registry.yarnpkg.com/@tenderly/hardhat-tenderly/-/hardhat-tenderly-2.5.1.tgz#b15544a2690d71e4a76e008f820e9afa921834d2" + integrity sha512-RdDl4gY5W2ZYistPkIIdHZRe3vHqs6JOgqQjqmI2OaE9y5FRlPeVUHRLAqoroVU+PkQhFPrgjBv5er/pJSonLA== dependencies: "@ethersproject/bignumber" "^5.7.0" "@nomicfoundation/hardhat-ethers" "^3.0.0" @@ -1768,7 +1746,7 @@ "@nomicfoundation/hardhat-verify" "^2.0.8" "@openzeppelin/hardhat-upgrades" "^3.3.0" "@openzeppelin/upgrades-core" "^1.32.2" - "@tenderly/hardhat-integration" "^1.0.0" + "@tenderly/hardhat-integration" "^1.1.0" dotenv "^16.4.5" ethers "^6.8.1" @@ -1847,9 +1825,11 @@ "@types/chai" "*" "@types/chai@*": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-5.0.0.tgz#7f981e71e69c9b2d422f58f78de1c59179782133" - integrity sha512-+DwhEHAaFPPdJ2ral3kNHFQXnTfscEEFsUxzD+d7nlcLrFK23JtNjH71RGasTcHb88b4vVi4mTyfpf8u2L8bdA== + version "5.0.1" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-5.0.1.tgz#2c3705555cf11f5f59c836a84c44afcfe4e5689d" + integrity sha512-5T8ajsg3M/FOncpLYW7sdOcD6yf4+722sze/tc4KQV0P8Z2rAr3SAuHCIkYmYpt8VbcQlnz8SxlOlPQYefe4cA== + dependencies: + "@types/deep-eql" "*" "@types/chai@^4.3.11": version "4.3.20" @@ -1863,6 +1843,11 @@ dependencies: "@types/node" "*" +"@types/deep-eql@*": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/deep-eql/-/deep-eql-4.0.2.tgz#334311971d3a07121e7eb91b684a605e7eea9cbd" + integrity sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw== + "@types/form-data@0.0.33": version "0.0.33" resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-0.0.33.tgz#c9ac85b2a5fd18435b8c85d9ecb50e6d6c893ff8" @@ -1914,16 +1899,18 @@ integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== "@types/node@*": - version "22.7.3" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.3.tgz#7ddf1ddf13078692b4cfadb835852b2a718ee1ef" - integrity sha512-qXKfhXXqGTyBskvWEzJZPUxSslAiLaB6JGP1ic/XTH9ctGgzdgYguuLP1C601aRTSDNlLb0jbKqXjZ48GNraSA== + version "22.10.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.2.tgz#a485426e6d1fdafc7b0d4c7b24e2c78182ddabb9" + integrity sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ== dependencies: - undici-types "~6.19.2" + undici-types "~6.20.0" -"@types/node@18.15.13": - version "18.15.13" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" - integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q== +"@types/node@22.7.5": + version "22.7.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b" + integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ== + dependencies: + undici-types "~6.19.2" "@types/node@^10.0.3": version "10.17.60" @@ -1931,9 +1918,9 @@ integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== "@types/node@^18.15.11": - version "18.19.53" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.53.tgz#1e2f83eeede6031f03bc4780826b8b02b42ac50d" - integrity sha512-GLxgUgHhDKO1Edw9Q0lvMbiO/IQXJwJlMaqxSGBXMpPy8uhkCs2iiPFaB2Q/gmobnFkckD3rqTBMVjXdwq+nKg== + version "18.19.68" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.68.tgz#f4f10d9927a7eaf3568c46a6d739cc0967ccb701" + integrity sha512-QGtpFH1vB99ZmTa63K4/FU8twThj4fuVSBkGddTp7uIL/cuoLWIUSL2RcOaigBhfR+hg5pgGkBnkoOxrTVBMKw== dependencies: undici-types "~5.26.4" @@ -1960,9 +1947,9 @@ integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== "@types/qs@^6.2.31", "@types/qs@^6.9.7": - version "6.9.16" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.16.tgz#52bba125a07c0482d26747d5d4947a64daf8f794" - integrity sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A== + version "6.9.17" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.17.tgz#fc560f60946d0aeff2f914eb41679659d3310e1a" + integrity sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ== "@types/secp256k1@^4.0.1": version "4.0.6" @@ -2078,9 +2065,9 @@ eslint-visitor-keys "^3.3.0" "@ungap/structured-clone@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + version "1.2.1" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.1.tgz#28fa185f67daaf7b7a1a8c1d445132c5d979f8bd" + integrity sha512-fEzPV3hSkSMltkw152tJKNARhOupqbH96MZWyRjNaYZOMIzbrTeQDG+MTc6Mr2pgzFQzFxAfmhGDNP5QK++2ZA== "@zero-tech/eslint-config-cpt@0.2.8": version "0.2.8" @@ -2111,6 +2098,11 @@ mongodb "^6.3.0" winston "^3.11.0" +"@zero-tech/zkevm-contracts@6.0.0-fork-9": + version "6.0.0-fork-9" + resolved "https://registry.yarnpkg.com/@zero-tech/zkevm-contracts/-/zkevm-contracts-6.0.0-fork-9.tgz#6ef7c889762542562485bf2ba3c6124ea00c0aa2" + integrity sha512-iSBm3wEvzkHAnqJYIWJlvIuBU1rKnnI8+IlqHLvz2r+3Ml228KaSNZi0SG8O1DW/oqNnHnMTDZzKv7NPR9wIrQ== + JSONStream@^1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" @@ -2146,10 +2138,10 @@ acorn-walk@^8.1.1: dependencies: acorn "^8.11.0" -acorn@^8.11.0, acorn@^8.12.0, acorn@^8.4.1, acorn@^8.9.0: - version "8.12.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" - integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== +acorn@^8.11.0, acorn@^8.14.0, acorn@^8.4.1, acorn@^8.9.0: + version "8.14.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" + integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== adm-zip@^0.4.16: version "0.4.16" @@ -2173,12 +2165,10 @@ agent-base@6, agent-base@^6.0.2: dependencies: debug "4" -agent-base@^7.0.2, agent-base@^7.1.0, agent-base@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.1.tgz#bdbded7dfb096b751a2a087eeeb9664725b2e317" - integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== - dependencies: - debug "^4.3.4" +agent-base@^7.1.0, agent-base@^7.1.2: + version "7.1.3" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.3.tgz#29435eb821bc4194633a5b89e5bc4703bafc25a1" + integrity sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw== agentkeepalive@^4.2.1: version "4.5.0" @@ -2433,38 +2423,37 @@ array.prototype.findlastindex@^1.2.5: es-shim-unscopables "^1.0.2" array.prototype.flat@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" - integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== + version "1.3.3" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz#534aaf9e6e8dd79fb6b9a9917f839ef1ec63afe5" + integrity sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-shim-unscopables "^1.0.2" array.prototype.flatmap@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" - integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== + version "1.3.3" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz#712cc792ae70370ae40586264629e33aab5dd38b" + integrity sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-shim-unscopables "^1.0.2" -arraybuffer.prototype.slice@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" - integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== +arraybuffer.prototype.slice@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz#9d760d84dbdd06d0cbf92c8849615a1a7ab3183c" + integrity sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ== dependencies: array-buffer-byte-length "^1.0.1" - call-bind "^1.0.5" + call-bind "^1.0.8" define-properties "^1.2.1" - es-abstract "^1.22.3" - es-errors "^1.2.1" - get-intrinsic "^1.2.3" + es-abstract "^1.23.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" is-array-buffer "^3.0.4" - is-shared-array-buffer "^1.0.2" arrify@^1.0.1: version "1.0.1" @@ -2525,6 +2514,15 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" +axios@1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.4.tgz#4c8ded1b43683c8dd362973c393f3ede24052aa2" + integrity sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + axios@^0.21.1: version "0.21.4" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" @@ -2540,10 +2538,10 @@ axios@^0.27.2: follow-redirects "^1.14.9" form-data "^4.0.0" -axios@^1.4.0, axios@^1.5.1, axios@^1.6.5, axios@^1.6.7, axios@^1.7.2: - version "1.7.7" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" - integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== +axios@^1.5.1, axios@^1.6.5, axios@^1.6.7, axios@^1.7.2: + version "1.7.9" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.9.tgz#d7d071380c132a24accda1b2cfc1535b79ec650a" + integrity sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw== dependencies: follow-redirects "^1.15.6" form-data "^4.0.0" @@ -2612,9 +2610,9 @@ bn.js@4.11.6: integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== bn.js@^4.11.0, bn.js@^4.11.8, bn.js@^4.11.9: - version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + version "4.12.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.1.tgz#215741fe3c9dba2d7e12c001d0cfdbae43975ba7" + integrity sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg== bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: version "5.2.1" @@ -2700,10 +2698,10 @@ bs58check@^2.1.2: create-hash "^1.1.0" safe-buffer "^5.1.2" -bson@^6.7.0: - version "6.8.0" - resolved "https://registry.yarnpkg.com/bson/-/bson-6.8.0.tgz#5063c41ba2437c2b8ff851b50d9e36cb7aaa7525" - integrity sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ== +bson@^6.10.1: + version "6.10.1" + resolved "https://registry.yarnpkg.com/bson/-/bson-6.10.1.tgz#dcd04703178f5ecf5b25de04edd2a95ec79385d3" + integrity sha512-P92xmHDQjSKPLHqFxefqMxASNq/aWJMEZugpCjf+AF/pgcUpMMQCg7t7+ewko0/u8AapvF3luf/FoehddEK+sA== buffer-from@^1.0.0: version "1.1.2" @@ -2823,16 +2821,31 @@ cacheable-request@^10.2.8: normalize-url "^8.0.0" responselike "^3.0.0" -call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz#32e5892e6361b29b0b545ba6f7763378daca2840" + integrity sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g== dependencies: - es-define-property "^1.0.0" es-errors "^1.3.0" function-bind "^1.1.2" + +call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7, call-bind@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" + integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== + dependencies: + call-bind-apply-helpers "^1.0.0" + es-define-property "^1.0.0" get-intrinsic "^1.2.4" - set-function-length "^1.2.1" + set-function-length "^1.2.2" + +call-bound@^1.0.2, call-bound@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.3.tgz#41cfd032b593e39176a71533ab4f384aa04fd681" + integrity sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA== + dependencies: + call-bind-apply-helpers "^1.0.1" + get-intrinsic "^1.2.6" callsites@^3.0.0: version "3.1.0" @@ -2928,9 +2941,9 @@ chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: supports-color "^7.1.0" chalk@^5.2.0, chalk@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" - integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== + version "5.4.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.4.0.tgz#846fdb5d5d939d6fa3d565cd5545697b6f8b6923" + integrity sha512-ZkD35Mx92acjB2yNJgziGqT9oKHEOxjTBTDRpOsRWtdecL/0jM3z5kM/CTzHWvHIen1GvkM85p6TuFfDGfc8/Q== "charenc@>= 0.0.1": version "0.0.2" @@ -2960,9 +2973,9 @@ chokidar@^3.5.2, chokidar@^3.5.3: fsevents "~2.3.2" chokidar@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.1.tgz#4a6dff66798fb0f72a94f616abbd7e1a19f31d41" - integrity sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA== + version "4.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== dependencies: readdirp "^4.0.1" @@ -2977,9 +2990,9 @@ ci-info@^2.0.0: integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== ci-info@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.0.0.tgz#65466f8b280fc019b9f50a5388115d17a63a44f2" - integrity sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg== + version "4.1.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.1.0.tgz#92319d2fa29d2620180ea5afed31f589bc98cf83" + integrity sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A== cidr-regex@^3.1.1: version "3.1.1" @@ -3000,12 +3013,12 @@ cids@^0.7.1: multihashes "~0.4.15" cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + version "1.0.6" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.6.tgz#8fe672437d01cd6c4561af5334e0cc50ff1955f7" + integrity sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw== dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" + inherits "^2.0.4" + safe-buffer "^5.2.1" class-is@^1.1.0: version "1.1.0" @@ -3368,9 +3381,9 @@ create-require@^1.1.0: integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" @@ -3444,9 +3457,9 @@ death@^1.1.0: integrity sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w== debug@4, debug@^4.0.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@^4.3.5, debug@^4.3.6: - version "4.3.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" - integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + version "4.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== dependencies: ms "^2.1.3" @@ -3525,7 +3538,7 @@ define-lazy-prop@^2.0.0: resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== -define-properties@^1.2.0, define-properties@^1.2.1: +define-properties@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== @@ -3605,9 +3618,18 @@ dotenv@16.0.3: integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== dotenv@^16.3.1, dotenv@^16.4.5: - version "16.4.5" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" - integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== + version "16.4.7" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26" + integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ== + +dunder-proto@^1.0.0, dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" duplexer2@~0.1.0: version "0.1.4" @@ -3634,10 +3656,10 @@ elliptic@6.5.4: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" -elliptic@^6.5.2, elliptic@^6.5.4: - version "6.5.7" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b" - integrity sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q== +elliptic@^6.5.2, elliptic@^6.5.7: + version "6.6.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" + integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== dependencies: bn.js "^4.11.9" brorand "^1.1.0" @@ -3707,66 +3729,66 @@ error-ex@^1.2.0, error-ex@^1.3.1, error-ex@^1.3.2: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.2: - version "1.23.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" - integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== +es-abstract@^1.23.2, es-abstract@^1.23.5, es-abstract@^1.23.6: + version "1.23.6" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.6.tgz#55f0e1ce7128995cc04ace0a57d7dca348345108" + integrity sha512-Ifco6n3yj2tMZDWNLyloZrytt9lqqlwvS83P3HtaETR0NUOYnIULGGHpktqYGObGy+8wc1okO25p8TjemhImvA== dependencies: array-buffer-byte-length "^1.0.1" - arraybuffer.prototype.slice "^1.0.3" + arraybuffer.prototype.slice "^1.0.4" available-typed-arrays "^1.0.7" - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.3" data-view-buffer "^1.0.1" data-view-byte-length "^1.0.1" data-view-byte-offset "^1.0.0" - es-define-property "^1.0.0" + es-define-property "^1.0.1" es-errors "^1.3.0" es-object-atoms "^1.0.0" es-set-tostringtag "^2.0.3" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.6" - get-intrinsic "^1.2.4" + es-to-primitive "^1.3.0" + function.prototype.name "^1.1.7" + get-intrinsic "^1.2.6" get-symbol-description "^1.0.2" - globalthis "^1.0.3" - gopd "^1.0.1" + globalthis "^1.0.4" + gopd "^1.2.0" has-property-descriptors "^1.0.2" - has-proto "^1.0.3" - has-symbols "^1.0.3" + has-proto "^1.2.0" + has-symbols "^1.1.0" hasown "^2.0.2" - internal-slot "^1.0.7" + internal-slot "^1.1.0" is-array-buffer "^3.0.4" is-callable "^1.2.7" - is-data-view "^1.0.1" + is-data-view "^1.0.2" is-negative-zero "^2.0.3" - is-regex "^1.1.4" + is-regex "^1.2.1" is-shared-array-buffer "^1.0.3" - is-string "^1.0.7" + is-string "^1.1.1" is-typed-array "^1.1.13" - is-weakref "^1.0.2" - object-inspect "^1.13.1" + is-weakref "^1.1.0" + math-intrinsics "^1.0.0" + object-inspect "^1.13.3" object-keys "^1.1.1" object.assign "^4.1.5" - regexp.prototype.flags "^1.5.2" - safe-array-concat "^1.1.2" - safe-regex-test "^1.0.3" - string.prototype.trim "^1.2.9" - string.prototype.trimend "^1.0.8" + regexp.prototype.flags "^1.5.3" + safe-array-concat "^1.1.3" + safe-regex-test "^1.1.0" + string.prototype.trim "^1.2.10" + string.prototype.trimend "^1.0.9" string.prototype.trimstart "^1.0.8" typed-array-buffer "^1.0.2" typed-array-byte-length "^1.0.1" - typed-array-byte-offset "^1.0.2" - typed-array-length "^1.0.6" + typed-array-byte-offset "^1.0.3" + typed-array-length "^1.0.7" unbox-primitive "^1.0.2" - which-typed-array "^1.1.15" + which-typed-array "^1.1.16" -es-define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" - integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== - dependencies: - get-intrinsic "^1.2.4" +es-define-property@^1.0.0, es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== -es-errors@^1.2.1, es-errors@^1.3.0: +es-errors@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== @@ -3792,21 +3814,21 @@ es-set-tostringtag@^2.0.3: has-tostringtag "^1.0.2" hasown "^2.0.1" -es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: +es-shim-unscopables@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== dependencies: hasown "^2.0.0" -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== +es-to-primitive@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.3.0.tgz#96c89c82cc49fd8794a24835ba3e1ff87f214e18" + integrity sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g== dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" + is-callable "^1.2.7" + is-date-object "^1.0.5" + is-symbol "^1.0.4" escalade@^3.1.1: version "3.2.0" @@ -3868,7 +3890,7 @@ eslint-import-resolver-node@^0.3.9: is-core-module "^2.13.0" resolve "^1.22.4" -eslint-module-utils@^2.9.0: +eslint-module-utils@^2.12.0: version "2.12.0" resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz#fe4cfb948d61f49203d7b08871982b65b9af0b0b" integrity sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg== @@ -3876,9 +3898,9 @@ eslint-module-utils@^2.9.0: debug "^3.2.7" eslint-plugin-import@^2.27.5: - version "2.30.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.30.0.tgz#21ceea0fc462657195989dd780e50c92fe95f449" - integrity sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw== + version "2.31.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz#310ce7e720ca1d9c0bb3f69adfd1c6bdd7d9e0e7" + integrity sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A== dependencies: "@rtsao/scc" "^1.1.0" array-includes "^3.1.8" @@ -3888,7 +3910,7 @@ eslint-plugin-import@^2.27.5: debug "^3.2.7" doctrine "^2.1.0" eslint-import-resolver-node "^0.3.9" - eslint-module-utils "^2.9.0" + eslint-module-utils "^2.12.0" hasown "^2.0.2" is-core-module "^2.15.1" is-glob "^4.0.3" @@ -3897,14 +3919,15 @@ eslint-plugin-import@^2.27.5: object.groupby "^1.0.3" object.values "^1.2.0" semver "^6.3.1" + string.prototype.trimend "^1.0.8" tsconfig-paths "^3.15.0" eslint-plugin-jsdoc@^50.3.0: - version "50.3.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.3.0.tgz#2a4d1ac7f45b2b62de42389ba8006fd00b7f08dd" - integrity sha512-P7qDB/RckdKETpBM4CtjHRQ5qXByPmFhRi86sN3E+J+tySchq+RSOGGhI2hDIefmmKFuTi/1ACjqsnDJDDDfzg== + version "50.6.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.6.1.tgz#791a668fd4b0700a759e9a16a741a6a805f5b95c" + integrity sha512-UWyaYi6iURdSfdVVqvfOs2vdCVz0J40O/z/HTsv2sFjdjmdlUI/qlKLOTmwbPQ2tAfQnE5F9vqx+B+poF71DBQ== dependencies: - "@es-joy/jsdoccomment" "~0.48.0" + "@es-joy/jsdoccomment" "~0.49.0" are-docs-informative "^0.0.2" comment-parser "1.4.1" debug "^4.3.6" @@ -3942,10 +3965,10 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint-visitor-keys@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz#e3adc021aa038a2a8e0b2f8b0ce8f66b9483b1fb" - integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw== +eslint-visitor-keys@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" + integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== eslint@^8.37.0: version "8.57.1" @@ -3992,13 +4015,13 @@ eslint@^8.37.0: text-table "^0.2.0" espree@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-10.1.0.tgz#8788dae611574c0f070691f522e4116c5a11fc56" - integrity sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA== + version "10.3.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a" + integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg== dependencies: - acorn "^8.12.0" + acorn "^8.14.0" acorn-jsx "^5.3.2" - eslint-visitor-keys "^4.0.0" + eslint-visitor-keys "^4.2.0" espree@^9.6.0, espree@^9.6.1: version "9.6.1" @@ -4160,6 +4183,11 @@ ethereumjs-util@^7.0.3, ethereumjs-util@^7.1.4, ethereumjs-util@^7.1.5: ethereum-cryptography "^0.1.3" rlp "^2.2.4" +ethers-decode-error@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ethers-decode-error/-/ethers-decode-error-2.1.3.tgz#ed0c81a400e9b66bba8c3ce356a4e52eab878e3f" + integrity sha512-x27u04XC/s8MRpuqiylIXbj4KMrt/5clYS2nle1b0bgbWFuoUZocDzjfXEfc5KzVmCQuITD9elqyO2VyxTGwdw== + ethers@^5.0.13, ethers@^5.7.0, ethers@^5.7.2: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" @@ -4197,16 +4225,16 @@ ethers@^5.0.13, ethers@^5.7.0, ethers@^5.7.2: "@ethersproject/wordlists" "5.7.0" ethers@^6.7.0, ethers@^6.8.1, ethers@^6.9.0: - version "6.13.2" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.13.2.tgz#4b67d4b49e69b59893931a032560999e5e4419fe" - integrity sha512-9VkriTTed+/27BGuY1s0hf441kqwHJ1wtN2edksEtiRvXx+soxRX3iSXTfFqq2+YwrOqbDoTHjIhQnjJRlzKmg== + version "6.13.4" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.13.4.tgz#bd3e1c3dc1e7dc8ce10f9ffb4ee40967a651b53c" + integrity sha512-21YtnZVg4/zKkCQPjrDj38B1r4nQvTZLopUGMLQ1ePU2zV/joCfDC3t3iKQjWRzjjjbzR+mdAIoikeBRNkdllA== dependencies: "@adraffy/ens-normalize" "1.10.1" "@noble/curves" "1.2.0" "@noble/hashes" "1.3.2" - "@types/node" "18.15.13" + "@types/node" "22.7.5" aes-js "4.0.0-beta.5" - tslib "2.4.0" + tslib "2.7.0" ws "8.17.1" ethjs-unit@0.1.6: @@ -4320,9 +4348,9 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fast-uri@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.2.tgz#d78b298cf70fd3b752fd951175a3da6a7b48f024" - integrity sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row== + version "3.0.3" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.3.tgz#892a1c91802d5d7860de728f18608a0573142241" + integrity sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw== fastest-levenshtein@^1.0.16: version "1.0.16" @@ -4336,6 +4364,11 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fdir@^6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.2.tgz#ddaa7ce1831b161bc3657bb99cb36e1622702689" + integrity sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ== + fecha@^4.2.0: version "4.2.3" resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" @@ -4385,7 +4418,7 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" -find-up@^2.0.0, find-up@^2.1.0: +find-up@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== @@ -4438,9 +4471,9 @@ flat@^5.0.2: integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== flatted@^3.2.9: - version "3.3.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" - integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== + version "3.3.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.2.tgz#adba1448a9841bec72b42c532ea23dbbedef1a27" + integrity sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA== fmix@^0.1.0: version "0.1.0" @@ -4480,18 +4513,19 @@ form-data-encoder@^2.1.2: integrity sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw== form-data@^2.2.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" - integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== + version "2.5.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.2.tgz#dc653743d1de2fcc340ceea38079daf6e9069fd2" + integrity sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q== dependencies: asynckit "^0.4.0" combined-stream "^1.0.6" mime-types "^2.1.12" + safe-buffer "^5.2.1" form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + version "4.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48" + integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw== dependencies: asynckit "^0.4.0" combined-stream "^1.0.8" @@ -4606,15 +4640,16 @@ function-bind@^1.1.2: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== -function.prototype.name@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" - integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== +function.prototype.name@^1.1.6, function.prototype.name@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.7.tgz#9df48ea5f746bf577d7e15b5da89df8952a98e7b" + integrity sha512-2g4x+HqTJKM9zcJqBSpjoRmdcPFtJM60J3xJisTQSXBWka5XqyBN/2tNUgma1mztTXyDuUsEtYe5qcs7xYzYQA== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" + call-bind "^1.0.8" + define-properties "^1.2.1" functions-have-names "^1.2.3" + hasown "^2.0.2" + is-callable "^1.2.7" functions-have-names@^1.2.3: version "1.2.3" @@ -4664,16 +4699,21 @@ get-func-name@^2.0.1, get-func-name@^2.0.2: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== -get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== +get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.6.tgz#43dd3dd0e7b49b82b2dfcad10dc824bf7fc265d5" + integrity sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA== dependencies: + call-bind-apply-helpers "^1.0.1" + dunder-proto "^1.0.0" + es-define-property "^1.0.1" es-errors "^1.3.0" + es-object-atoms "^1.0.0" function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.0.0" get-port@^3.1.0: version "3.2.0" @@ -4696,13 +4736,13 @@ get-stream@^8.0.1: integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== get-symbol-description@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" - integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== + version "1.1.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.1.0.tgz#7bdd54e0befe8ffc9f3b4e203220d9f1e881b6ee" + integrity sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg== dependencies: - call-bind "^1.0.5" + call-bound "^1.0.3" es-errors "^1.3.0" - get-intrinsic "^1.2.4" + get-intrinsic "^1.2.6" ghost-testrpc@^0.0.2: version "0.0.2" @@ -4750,18 +4790,6 @@ glob@7.1.7: once "^1.3.0" path-is-absolute "^1.0.0" -glob@7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@^10.2.2, glob@^10.3.10: version "10.4.5" resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" @@ -4843,7 +4871,7 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" -globalthis@^1.0.3: +globalthis@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== @@ -4889,12 +4917,10 @@ globby@^14.0.0: slash "^5.1.0" unicorn-magic "^0.1.0" -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" +gopd@^1.0.1, gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== got@^12.1.0: version "12.6.1" @@ -4985,13 +5011,13 @@ hardhat-gas-reporter@^1.0.9: sha1 "^1.1.1" hardhat@^2.22.6: - version "2.22.12" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.12.tgz#a6d0be011fc009c50c454da367ad28c29f58d446" - integrity sha512-yok65M+LsOeTBHQsjg//QreGCyrsaNmeLVzhTFqlOvZ4ZE5y69N0wRxH1b2BC9dGK8S8OPUJMNiL9X0RAvbm8w== + version "2.22.17" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.17.tgz#96036bbe6bad8eb6a6b65c54dc5fbc1324541612" + integrity sha512-tDlI475ccz4d/dajnADUTRc1OJ3H8fpP9sWhXhBPpYsQOg8JHq5xrDimo53UhWPl7KJmAeDCm1bFG74xvpGRpg== dependencies: "@ethersproject/abi" "^5.1.2" "@metamask/eth-sig-util" "^4.0.0" - "@nomicfoundation/edr" "^0.6.1" + "@nomicfoundation/edr" "^0.6.5" "@nomicfoundation/ethereumjs-common" "4.0.4" "@nomicfoundation/ethereumjs-tx" "5.0.4" "@nomicfoundation/ethereumjs-util" "9.0.4" @@ -5003,7 +5029,6 @@ hardhat@^2.22.6: aggregate-error "^3.0.0" ansi-escapes "^4.3.0" boxen "^5.1.2" - chalk "^2.4.2" chokidar "^4.0.0" ci-info "^2.0.0" debug "^4.1.1" @@ -5011,10 +5036,9 @@ hardhat@^2.22.6: env-paths "^2.2.0" ethereum-cryptography "^1.0.3" ethereumjs-abi "^0.6.8" - find-up "^2.1.0" + find-up "^5.0.0" fp-ts "1.19.3" fs-extra "^7.0.1" - glob "7.2.0" immutable "^4.0.0-rc.12" io-ts "1.10.4" json-stream-stringify "^3.1.4" @@ -5023,21 +5047,23 @@ hardhat@^2.22.6: mnemonist "^0.38.0" mocha "^10.0.0" p-map "^4.0.0" + picocolors "^1.1.0" raw-body "^2.4.1" resolve "1.17.0" semver "^6.3.0" solc "0.8.26" source-map-support "^0.5.13" stacktrace-parser "^0.1.10" + tinyglobby "^0.2.6" tsort "0.0.1" undici "^5.14.0" uuid "^8.3.2" ws "^7.4.6" -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== +has-bigints@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.1.0.tgz#28607e965ac967e03cd2a2c70a2636a1edad49fe" + integrity sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg== has-flag@^1.0.0: version "1.0.0" @@ -5061,15 +5087,17 @@ has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: dependencies: es-define-property "^1.0.0" -has-proto@^1.0.1, has-proto@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" - integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== +has-proto@^1.0.3, has-proto@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.2.0.tgz#5de5a6eabd95fdffd9818b43055e8065e39fe9d5" + integrity sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ== + dependencies: + dunder-proto "^1.0.0" -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: version "1.0.2" @@ -5143,10 +5171,10 @@ hosted-git-info@^4.0.1: dependencies: lru-cache "^6.0.0" -hosted-git-info@^6.0.0, hosted-git-info@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-6.1.1.tgz#629442c7889a69c05de604d52996b74fe6f26d58" - integrity sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w== +hosted-git-info@^6.0.0, hosted-git-info@^6.1.1, hosted-git-info@^6.1.3: + version "6.1.3" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-6.1.3.tgz#2ee1a14a097a1236bddf8672c35b613c46c55946" + integrity sha512-HVJyzUrLIL1c0QmviVh5E8VGyUS7xCFPS6yydaVd1UegW+ibV/CohqTH9MkOLDp5o+rb82DMo77PTuc9F/8GKw== dependencies: lru-cache "^7.5.1" @@ -5224,11 +5252,11 @@ https-proxy-agent@^5.0.0: debug "4" https-proxy-agent@^7.0.0, https-proxy-agent@^7.0.1: - version "7.0.5" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz#9e8b5013873299e11fab6fd548405da2d6c602b2" - integrity sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw== + version "7.0.6" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" + integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== dependencies: - agent-base "^7.0.2" + agent-base "^7.1.2" debug "4" human-signals@^2.1.0: @@ -5380,14 +5408,14 @@ init-package-json@^5.0.0: validate-npm-package-license "^3.0.4" validate-npm-package-name "^5.0.0" -internal-slot@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" - integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== +internal-slot@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.1.0.tgz#1eac91762947d2f7056bc838d93e13b2e9604961" + integrity sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw== dependencies: es-errors "^1.3.0" - hasown "^2.0.0" - side-channel "^1.0.4" + hasown "^2.0.2" + side-channel "^1.1.0" interpret@^1.0.0: version "1.4.0" @@ -5428,12 +5456,13 @@ ip-regex@^4.1.0: integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== is-array-buffer@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" - integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== + version "3.0.5" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.5.tgz#65742e1e687bd2cc666253068fd8707fe4d44280" + integrity sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.1" + call-bind "^1.0.8" + call-bound "^1.0.3" + get-intrinsic "^1.2.6" is-arrayish@^0.2.1: version "0.2.1" @@ -5445,12 +5474,19 @@ is-arrayish@^0.3.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== +is-async-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" + integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== dependencies: - has-bigints "^1.0.1" + has-tostringtag "^1.0.0" + +is-bigint@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.1.0.tgz#dda7a3445df57a42583db4228682eba7c4170672" + integrity sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ== + dependencies: + has-bigints "^1.0.2" is-binary-path@~2.1.0: version "2.1.0" @@ -5459,15 +5495,15 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== +is-boolean-object@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.2.1.tgz#c20d0c654be05da4fbc23c562635c019e93daf89" + integrity sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng== dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" + call-bound "^1.0.2" + has-tostringtag "^1.0.2" -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: +is-callable@^1.1.3, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== @@ -5479,26 +5515,29 @@ is-cidr@^4.0.2: dependencies: cidr-regex "^3.1.1" -is-core-module@^2.13.0, is-core-module@^2.15.1, is-core-module@^2.5.0, is-core-module@^2.8.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37" - integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ== +is-core-module@^2.13.0, is-core-module@^2.15.1, is-core-module@^2.16.0, is-core-module@^2.5.0, is-core-module@^2.8.1: + version "2.16.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.0.tgz#6c01ffdd5e33c49c1d2abfa93334a85cb56bd81c" + integrity sha512-urTSINYfAYgcbLb0yDQ6egFm6h3Mo1DcF9EkyXSRjjzdHbsulg01qhwWuXdOoUBuTkbQ80KDboXa0vFJ+BDH+g== dependencies: hasown "^2.0.2" -is-data-view@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" - integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w== +is-data-view@^1.0.1, is-data-view@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.2.tgz#bae0a41b9688986c2188dda6657e56b8f9e63b8e" + integrity sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw== dependencies: + call-bound "^1.0.2" + get-intrinsic "^1.2.6" is-typed-array "^1.1.13" -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== +is-date-object@^1.0.5, is-date-object@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.1.0.tgz#ad85541996fc7aa8b2729701d27b7319f95d82f7" + integrity sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg== dependencies: - has-tostringtag "^1.0.0" + call-bound "^1.0.2" + has-tostringtag "^1.0.2" is-docker@^2.0.0, is-docker@^2.1.1: version "2.2.1" @@ -5510,6 +5549,13 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== +is-finalizationregistry@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz#eefdcdc6c94ddd0674d9c85887bf93f944a97c90" + integrity sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg== + dependencies: + call-bound "^1.0.3" + is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" @@ -5527,6 +5573,13 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== +is-generator-function@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -5544,17 +5597,23 @@ is-lambda@^1.0.1: resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ== +is-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" + integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== + is-negative-zero@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== +is-number-object@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.1.1.tgz#144b21e95a1bc148205dcc2814a9134ec41b2541" + integrity sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw== dependencies: - has-tostringtag "^1.0.0" + call-bound "^1.0.3" + has-tostringtag "^1.0.2" is-number@^7.0.0: version "7.0.0" @@ -5581,20 +5640,27 @@ is-plain-obj@^2.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== +is-regex@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" + integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" + call-bound "^1.0.2" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + hasown "^2.0.2" -is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688" - integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg== +is-set@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" + integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== + +is-shared-array-buffer@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz#9b67844bd9b7f246ba0708c3a93e34269c774f6f" + integrity sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A== dependencies: - call-bind "^1.0.7" + call-bound "^1.0.3" is-stream@^2.0.0: version "2.0.1" @@ -5606,19 +5672,22 @@ is-stream@^3.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== +is-string@^1.0.7, is-string@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.1.1.tgz#92ea3f3d5c5b6e039ca8677e5ac8d07ea773cbb9" + integrity sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA== dependencies: - has-tostringtag "^1.0.0" + call-bound "^1.0.3" + has-tostringtag "^1.0.2" -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== +is-symbol@^1.0.4, is-symbol@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.1.1.tgz#f47761279f532e2b05a7024a7506dbbedacd0634" + integrity sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w== dependencies: - has-symbols "^1.0.2" + call-bound "^1.0.2" + has-symbols "^1.1.0" + safe-regex-test "^1.1.0" is-text-path@^2.0.0: version "2.0.0" @@ -5627,12 +5696,12 @@ is-text-path@^2.0.0: dependencies: text-extensions "^2.0.0" -is-typed-array@^1.1.13: - version "1.1.13" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" - integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== +is-typed-array@^1.1.13, is-typed-array@^1.1.14: + version "1.1.15" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" + integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== dependencies: - which-typed-array "^1.1.14" + which-typed-array "^1.1.16" is-unicode-supported@^0.1.0: version "0.1.0" @@ -5649,12 +5718,25 @@ is-utf8@^0.2.0: resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q== -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== +is-weakmap@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" + integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== + +is-weakref@^1.0.2, is-weakref@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.1.0.tgz#47e3472ae95a63fa9cf25660bcf0c181c39770ef" + integrity sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q== dependencies: - call-bind "^1.0.2" + call-bound "^1.0.2" + +is-weakset@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.4.tgz#c9f5deb0bc1906c6d6f1027f284ddf459249daca" + integrity sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ== + dependencies: + call-bound "^1.0.3" + get-intrinsic "^1.2.6" is-wsl@^2.2.0: version "2.2.0" @@ -5799,9 +5881,9 @@ json-stable-stringify-without-jsonify@^1.0.1: integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== json-stream-stringify@^3.1.4: - version "3.1.4" - resolved "https://registry.yarnpkg.com/json-stream-stringify/-/json-stream-stringify-3.1.4.tgz#d5b10c4c709b27d3c3ef07a1926ffcc1b67c4c5d" - integrity sha512-oGoz05ft577LolnXFQHD2CjnXDxXVA5b8lHwfEZgRXQUZeCMo6sObQQRq+NXuHQ3oTeMZHHmmPY2rjVwyqR62A== + version "3.1.6" + resolved "https://registry.yarnpkg.com/json-stream-stringify/-/json-stream-stringify-3.1.6.tgz#ebe32193876fb99d4ec9f612389a8d8e2b5d54d4" + integrity sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog== json-stringify-nice@^1.1.4: version "1.1.4" @@ -6204,10 +6286,10 @@ log-symbols@^4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" -logform@^2.6.0, logform@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/logform/-/logform-2.6.1.tgz#71403a7d8cae04b2b734147963236205db9b3df0" - integrity sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA== +logform@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/logform/-/logform-2.7.0.tgz#cfca97528ef290f2e125a08396805002b2d060d1" + integrity sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ== dependencies: "@colors/colors" "1.6.0" "@types/triple-beam" "^1.3.2" @@ -6234,9 +6316,9 @@ lru-cache@^10.0.1, lru-cache@^10.2.0: integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== lru-cache@^11.0.0: - version "11.0.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.0.1.tgz#3a732fbfedb82c5ba7bca6564ad3f42afcb6e147" - integrity sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ== + version "11.0.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.0.2.tgz#fbd8e7cf8211f5e7e5d91905c415a3f55755ca39" + integrity sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA== lru-cache@^6.0.0: version "6.0.0" @@ -6358,6 +6440,11 @@ match-all@^1.2.6: resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.6.tgz#66d276ad6b49655551e63d3a6ee53e8be0566f8d" integrity sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ== +math-intrinsics@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.0.0.tgz#4e04bf87c85aa51e90d078dac2252b4eb5260817" + integrity sha512-4MqMiKP90ybymYvsut0CH2g4XWbfLtmlCkXmtmdcDCxNB+mQcu1w/1+L/VD7vi/PSv7X2JYV7SCcR+jiPXnQtA== + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -6435,9 +6522,9 @@ mime-types@^2.1.12: mime-db "1.52.0" mime@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/mime/-/mime-4.0.4.tgz#9f851b0fc3c289d063b20a7a8055b3014b25664b" - integrity sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ== + version "4.0.6" + resolved "https://registry.yarnpkg.com/mime/-/mime-4.0.6.tgz#ca83bec0bcf2a02353d0e02da99be05603d04839" + integrity sha512-4rGt7rvQHBbaSOF9POGkk1ocRP16Md1x36Xma8sz8h8/vfCUI2OtEIeCqe4Ofes853x4xDoPiFLIT47J5fI/7A== mimic-fn@^2.1.0: version "2.1.0" @@ -6626,9 +6713,9 @@ mnemonist@^0.38.0: obliterator "^2.0.0" mocha@^10.0.0, mocha@^10.2.0: - version "10.7.3" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.7.3.tgz#ae32003cabbd52b59aece17846056a68eb4b0752" - integrity sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A== + version "10.8.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.8.2.tgz#8d8342d016ed411b12a429eb731b825f961afb96" + integrity sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg== dependencies: ansi-colors "^4.1.3" browser-stdout "^1.3.1" @@ -6665,12 +6752,12 @@ mongodb-connection-string-url@^3.0.0: whatwg-url "^13.0.0" mongodb@^6.1.0, mongodb@^6.3.0: - version "6.9.0" - resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-6.9.0.tgz#743ebfff6b3c14b04ac6e00a55e30d4127d3016d" - integrity sha512-UMopBVx1LmEUbW/QE0Hw18u583PEDVQmUmVzzBRH0o/xtE9DBRA5ZYLOjpLIa03i8FXjzvQECJcqoMvCXftTUA== + version "6.12.0" + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-6.12.0.tgz#8b0bda1b18cbb3f0aec8ab4119c5dc535a43c444" + integrity sha512-RM7AHlvYfS7jv7+BXund/kR64DryVI+cHbVAy9P61fnb1RcWZqOW1/Wj2YhqMCx+MuYhqTRGv7AwHBzmsCKBfA== dependencies: - "@mongodb-js/saslprep" "^1.1.5" - bson "^6.7.0" + "@mongodb-js/saslprep" "^1.1.9" + bson "^6.10.1" mongodb-connection-string-url "^3.0.0" ms@^2.0.0, ms@^2.1.1, ms@^2.1.2, ms@^2.1.3: @@ -6759,9 +6846,9 @@ ndjson@2.0.0: through2 "^4.0.0" negotiator@^0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + version "0.6.4" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7" + integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w== neo-async@^2.6.2: version "2.6.2" @@ -6778,6 +6865,11 @@ node-addon-api@^2.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== +node-addon-api@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" + integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== + node-emoji@^1.10.0, node-emoji@^1.11.0: version "1.11.0" resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" @@ -6793,9 +6885,9 @@ node-fetch@^2.6.1: whatwg-url "^5.0.0" node-gyp-build@^4.2.0: - version "4.8.2" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.2.tgz#4f802b71c1ab2ca16af830e6c1ea7dd1ad9496fa" - integrity sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw== + version "4.8.4" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.4.tgz#8a70ee85464ae52327772a90d66c6077a900cfc8" + integrity sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ== node-gyp@^9.0.0, node-gyp@^9.4.1: version "9.4.1" @@ -7005,9 +7097,9 @@ npm-user-validate@^2.0.0: integrity sha512-d17PKaF2h8LSGFl5j4b1gHOJt1fgH7YUcCm1kNSJvaLWWKXlBsuUvx0bBEkr0qhsVA9XP5LtRZ83hdlhm2QkgA== npm@^9.5.0: - version "9.9.3" - resolved "https://registry.yarnpkg.com/npm/-/npm-9.9.3.tgz#18272a7b966721417691fec0ca18f7fbe4a9794e" - integrity sha512-Z1l+rcQ5kYb17F3hHtO601arEpvdRYnCLtg8xo3AGtyj3IthwaraEOexI9903uANkifFbqHC8hT53KIrozWg8A== + version "9.9.4" + resolved "https://registry.yarnpkg.com/npm/-/npm-9.9.4.tgz#572bef36e61852c5a391bb3b4eb86c231b1365cd" + integrity sha512-NzcQiLpqDuLhavdyJ2J3tGJ/ni/ebcqHVFZkv1C4/6lblraUPbPgCJ4Vhb4oa3FFhRa2Yj9gA58jGH/ztKueNQ== dependencies: "@isaacs/string-locale-compare" "^1.1.0" "@npmcli/arborist" "^6.5.0" @@ -7029,7 +7121,7 @@ npm@^9.5.0: fs-minipass "^3.0.3" glob "^10.3.10" graceful-fs "^4.2.11" - hosted-git-info "^6.1.1" + hosted-git-info "^6.1.3" ini "^4.1.1" init-package-json "^5.0.0" is-cidr "^4.0.2" @@ -7072,7 +7164,7 @@ npm@^9.5.0: spdx-expression-parse "^3.0.1" ssri "^10.0.5" supports-color "^9.4.0" - tar "^6.2.0" + tar "^6.2.1" text-table "~0.2.0" tiny-relative-date "^1.3.0" treeverse "^3.0.0" @@ -7118,10 +7210,10 @@ object-assign@^4.1.0: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-inspect@^1.13.1: - version "1.13.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" - integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== +object-inspect@^1.13.3: + version "1.13.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.3.tgz#f14c183de51130243d6d18ae149375ff50ea488a" + integrity sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA== object-keys@^1.1.1: version "1.1.1" @@ -7129,13 +7221,15 @@ object-keys@^1.1.1: integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object.assign@^4.1.2, object.assign@^4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" - integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== + version "4.1.7" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.7.tgz#8c14ca1a424c6a561b0bb2a22f66f5049a945d3d" + integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== dependencies: - call-bind "^1.0.5" + call-bind "^1.0.8" + call-bound "^1.0.3" define-properties "^1.2.1" - has-symbols "^1.0.3" + es-object-atoms "^1.0.0" + has-symbols "^1.1.0" object-keys "^1.1.1" object.entries@^1.1.5: @@ -7344,9 +7438,9 @@ p-map@^4.0.0: aggregate-error "^3.0.0" p-map@^7.0.1: - version "7.0.2" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-7.0.2.tgz#7c5119fada4755660f70199a66aa3fe2f85a1fe8" - integrity sha512-z4cYYMMdKHzw4O5UkWJImbZynVIo0lSGTXc7bzB1e/rrDqkgGUNysK/o4bTr+0+xKvvLoTyGqYC4Fgljy9qe1Q== + version "7.0.3" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-7.0.3.tgz#7ac210a2d36f81ec28b736134810f7ba4418cdb6" + integrity sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA== p-reduce@^2.0.0: version "2.1.0" @@ -7570,16 +7664,21 @@ pbkdf2@^3.0.17: safe-buffer "^5.0.1" sha.js "^2.4.8" -picocolors@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.0.tgz#5358b76a78cde483ba5cef6a9dc9671440b27d59" - integrity sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw== +picocolors@^1.0.0, picocolors@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +picomatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" + integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== + pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -7743,9 +7842,9 @@ qrcode-terminal@^0.12.0: integrity sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ== qs@^6.4.0, qs@^6.9.4: - version "6.13.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" - integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== + version "6.13.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.1.tgz#3ce5fc72bd3a8171b85c99b93c65dd20b7d1b16e" + integrity sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg== dependencies: side-channel "^1.0.6" @@ -7906,9 +8005,9 @@ readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.2.2, readable util-deprecate "~1.0.1" readdirp@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.0.1.tgz#b2fe35f8dca63183cd3b86883ecc8f720ea96ae6" - integrity sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw== + version "4.0.2" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.0.2.tgz#388fccb8b75665da3abffe2d8f8ed59fe74c230a" + integrity sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA== readdirp@~3.6.0: version "3.6.0" @@ -7951,25 +8050,39 @@ reduce-flatten@^2.0.0: resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== +reflect.getprototypeof@^1.0.6: + version "1.0.9" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.9.tgz#c905f3386008de95a62315f3ea8630404be19e2f" + integrity sha512-r0Ay04Snci87djAsI4U+WNRcSw5S4pOH7qFjd/veA5gC7TbqESR3tcj28ia95L/fYUDw11JKP7uqUKUAfVvV5Q== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + dunder-proto "^1.0.1" + es-abstract "^1.23.6" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + gopd "^1.2.0" + which-builtin-type "^1.2.1" + regenerator-runtime@^0.14.0: version "0.14.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== -regexp.prototype.flags@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" - integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== +regexp.prototype.flags@^1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz#b3ae40b1d2499b8350ab2c3fe6ef3845d3a96f42" + integrity sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ== dependencies: - call-bind "^1.0.6" + call-bind "^1.0.7" define-properties "^1.2.1" es-errors "^1.3.0" - set-function-name "^2.0.1" + set-function-name "^2.0.2" registry-auth-token@^5.0.0, registry-auth-token@^5.0.1: - version "5.0.2" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-5.0.2.tgz#8b026cc507c8552ebbe06724136267e63302f756" - integrity sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ== + version "5.0.3" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-5.0.3.tgz#417d758c8164569de8cf5cabff16cc937902dcc6" + integrity sha512-1bpc9IyC+e+CNFRaWyn77tk4xGG4PPUyfakSmA6F6cvUDjrm58dfyJ3II+9yb10EDkHoy1LaPSmHaWLOH3m6HA== dependencies: "@pnpm/npm-conf" "^2.1.0" @@ -8047,11 +8160,11 @@ resolve@1.17.0: path-parse "^1.0.6" resolve@^1.1.6, resolve@^1.10.0, resolve@^1.22.4: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + version "1.22.9" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.9.tgz#6da76e4cdc57181fa4471231400e8851d0a924f3" + integrity sha512-QxrmX1DzraFIi9PxdG5VkRfRwIgjwyud+z/iBwfRRrVmHc+P9Q7u2lSSpQ6bjr2gy5lrqIiU9vb6iAeGf2400A== dependencies: - is-core-module "^2.13.0" + is-core-module "^2.16.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -8118,17 +8231,18 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -safe-array-concat@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" - integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== +safe-array-concat@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3" + integrity sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q== dependencies: - call-bind "^1.0.7" - get-intrinsic "^1.2.4" - has-symbols "^1.0.3" + call-bind "^1.0.8" + call-bound "^1.0.2" + get-intrinsic "^1.2.6" + has-symbols "^1.1.0" isarray "^2.0.5" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -8138,14 +8252,14 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-regex-test@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" - integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== +safe-regex-test@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" + integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== dependencies: - call-bind "^1.0.6" + call-bound "^1.0.2" es-errors "^1.3.0" - is-regex "^1.1.4" + is-regex "^1.2.1" safe-stable-stringify@^2.3.1: version "2.5.0" @@ -8183,12 +8297,12 @@ scrypt-js@3.0.1, scrypt-js@^3.0.0: integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== secp256k1@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" - integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== + version "4.0.4" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.4.tgz#58f0bfe1830fe777d9ca1ffc7574962a8189f8ab" + integrity sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw== dependencies: - elliptic "^6.5.4" - node-addon-api "^2.0.0" + elliptic "^6.5.7" + node-addon-api "^5.0.0" node-gyp-build "^4.2.0" semantic-release@^21.0.1: @@ -8264,7 +8378,7 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== -set-function-length@^1.2.1: +set-function-length@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== @@ -8276,7 +8390,7 @@ set-function-length@^1.2.1: gopd "^1.0.1" has-property-descriptors "^1.0.2" -set-function-name@^2.0.1: +set-function-name@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== @@ -8340,15 +8454,45 @@ shelljs@^0.8.3: interpret "^1.0.0" rechoir "^0.6.2" -side-channel@^1.0.4, side-channel@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" - integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== dependencies: - call-bind "^1.0.7" es-errors "^1.3.0" - get-intrinsic "^1.2.4" - object-inspect "^1.13.1" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + +side-channel@^1.0.6, side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" @@ -8431,11 +8575,11 @@ socks-proxy-agent@^7.0.0: socks "^2.6.2" socks-proxy-agent@^8.0.3: - version "8.0.4" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz#9071dca17af95f483300316f4b063578fa0db08c" - integrity sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw== + version "8.0.5" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz#b9cdb4e7e998509d7659d689ce7697ac21645bee" + integrity sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw== dependencies: - agent-base "^7.1.1" + agent-base "^7.1.2" debug "^4.3.4" socks "^2.8.3" @@ -8503,12 +8647,12 @@ solidity-ast@^0.4.38, solidity-ast@^0.4.51: integrity sha512-I+CX0wrYUN9jDfYtcgWSe+OAowaXy8/1YQy7NS4ni5IBDmIYBq7ZzaP/7QqouLjzZapmQtvGLqCaYgoUWqBo5g== solidity-coverage@^0.8.12: - version "0.8.13" - resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.13.tgz#8eeada2e82ae19d25568368aa782a2baad0e0ce7" - integrity sha512-RiBoI+kF94V3Rv0+iwOj3HQVSqNzA9qm/qDP1ZDXK5IX0Cvho1qiz8hAXTsAo6KOIUeP73jfscq0KlLqVxzGWA== + version "0.8.14" + resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.14.tgz#db9bfcc10e3bc369fc074b35b267d665bcc6ae2e" + integrity sha512-ItAAObe5GaEOp20kXC2BZRnph+9P7Rtoqg2mQc2SXGEHgSDF2wWd1Wxz3ntzQWXkbCtIIGdJT918HG00cObwbA== dependencies: "@ethersproject/abi" "^5.0.9" - "@solidity-parser/parser" "^0.18.0" + "@solidity-parser/parser" "^0.19.0" chalk "^2.4.2" death "^1.1.0" difflib "^0.2.4" @@ -8681,7 +8825,7 @@ string-format@^2.0.0: resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -8699,6 +8843,15 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" @@ -8716,22 +8869,26 @@ string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" -string.prototype.trim@^1.2.9: - version "1.2.9" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" - integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== +string.prototype.trim@^1.2.10: + version "1.2.10" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz#40b2dd5ee94c959b4dcfb1d65ce72e90da480c81" + integrity sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.2" + define-data-property "^1.1.4" define-properties "^1.2.1" - es-abstract "^1.23.0" + es-abstract "^1.23.5" es-object-atoms "^1.0.0" + has-property-descriptors "^1.0.2" -string.prototype.trimend@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229" - integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ== +string.prototype.trimend@^1.0.8, string.prototype.trimend@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz#62e2731272cd285041b36596054e9f66569b6942" + integrity sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.2" define-properties "^1.2.1" es-object-atoms "^1.0.0" @@ -8758,7 +8915,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -8779,6 +8936,13 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -8895,9 +9059,9 @@ sync-rpc@^1.2.1: get-port "^3.1.0" synckit@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.9.1.tgz#febbfbb6649979450131f64735aa3f6c14575c88" - integrity sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A== + version "0.9.2" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.9.2.tgz#a3a935eca7922d48b9e7d6c61822ee6c3ae4ec62" + integrity sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw== dependencies: "@pkgr/core" "^0.1.0" tslib "^2.6.2" @@ -8913,9 +9077,9 @@ table-layout@^1.0.2: wordwrapjs "^4.0.0" table@^6.8.0, table@^6.8.1: - version "6.8.2" - resolved "https://registry.yarnpkg.com/table/-/table-6.8.2.tgz#c5504ccf201213fa227248bdc8c5569716ac6c58" - integrity sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA== + version "6.9.0" + resolved "https://registry.yarnpkg.com/table/-/table-6.9.0.tgz#50040afa6264141c7566b3b81d4d82c47a8668f5" + integrity sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A== dependencies: ajv "^8.0.1" lodash.truncate "^4.4.2" @@ -8923,7 +9087,7 @@ table@^6.8.0, table@^6.8.1: string-width "^4.2.3" strip-ansi "^6.0.1" -tar@^6.1.11, tar@^6.1.13, tar@^6.1.2, tar@^6.2.0: +tar@^6.1.11, tar@^6.1.13, tar@^6.1.2, tar@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== @@ -9012,6 +9176,14 @@ tiny-relative-date@^1.3.0: resolved "https://registry.yarnpkg.com/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz#fa08aad501ed730f31cc043181d995c39a935e07" integrity sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A== +tinyglobby@^0.2.6: + version "0.2.10" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.10.tgz#e712cf2dc9b95a1f5c5bbd159720e15833977a0f" + integrity sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew== + dependencies: + fdir "^6.4.2" + picomatch "^4.0.2" + tmp@0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -9126,10 +9298,10 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== +tslib@2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.3: version "1.14.1" @@ -9137,9 +9309,9 @@ tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.3: integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tslib@^2.3.1, tslib@^2.6.2: - version "2.7.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" - integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== tslog@^4.3.1, tslog@^4.4.0: version "4.9.3" @@ -9242,9 +9414,9 @@ type-fest@^3.8.0: integrity sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g== type-fest@^4.2.0: - version "4.26.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.26.1.tgz#a4a17fa314f976dd3e6d6675ef6c775c16d7955e" - integrity sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg== + version "4.30.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.30.2.tgz#d94429edde1f7deacf554741650aab394197a4cc" + integrity sha512-UJShLPYi1aWqCdq9HycOL/gwsuqda1OISdBO3t8RlXQC4QvtuIz4b5FCfe2dQIWEpmlRExKmcTBfP1r9bhY7ig== typechain@^8.3.2: version "8.3.2" @@ -9263,29 +9435,29 @@ typechain@^8.3.2: ts-essentials "^7.0.1" typed-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" - integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536" + integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw== dependencies: - call-bind "^1.0.7" + call-bound "^1.0.3" es-errors "^1.3.0" - is-typed-array "^1.1.13" + is-typed-array "^1.1.14" typed-array-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67" - integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw== + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz#8407a04f7d78684f3d252aa1a143d2b77b4160ce" + integrity sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" + gopd "^1.2.0" + has-proto "^1.2.0" + is-typed-array "^1.1.14" -typed-array-byte-offset@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" - integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== +typed-array-byte-offset@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.3.tgz#3fa9f22567700cc86aaf86a1e7176f74b59600f2" + integrity sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw== dependencies: available-typed-arrays "^1.0.7" call-bind "^1.0.7" @@ -9293,18 +9465,19 @@ typed-array-byte-offset@^1.0.2: gopd "^1.0.1" has-proto "^1.0.3" is-typed-array "^1.1.13" + reflect.getprototypeof "^1.0.6" -typed-array-length@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" - integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== +typed-array-length@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.7.tgz#ee4deff984b64be1e118b0de8c9c877d5ce73d3d" + integrity sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg== dependencies: call-bind "^1.0.7" for-each "^0.3.3" gopd "^1.0.1" - has-proto "^1.0.3" is-typed-array "^1.1.13" possible-typed-array-names "^1.0.0" + reflect.getprototypeof "^1.0.6" typedarray@^0.0.6: version "0.0.6" @@ -9312,9 +9485,9 @@ typedarray@^0.0.6: integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== typescript@^5.0.2, typescript@^5.5.4: - version "5.6.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.2.tgz#d1de67b6bef77c41823f822df8f0b3bcff60a5a0" - integrity sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw== + version "5.7.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6" + integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg== typical@^4.0.0: version "4.0.0" @@ -9332,14 +9505,14 @@ uglify-js@^3.1.4: integrity sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ== unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.1.0.tgz#8d9d2c9edeea8460c7f35033a88867944934d1e2" + integrity sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw== dependencies: - call-bind "^1.0.2" + call-bound "^1.0.3" has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" + has-symbols "^1.1.0" + which-boxed-primitive "^1.1.1" undici-types@~5.26.4: version "5.26.5" @@ -9351,6 +9524,11 @@ undici-types@~6.19.2: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== +undici-types@~6.20.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" + integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== + undici@^5.14.0: version "5.28.4" resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.4.tgz#6b280408edb6a1a604a9b20340f45b422e373068" @@ -9359,9 +9537,9 @@ undici@^5.14.0: "@fastify/busboy" "^2.0.0" undici@^6.11.1: - version "6.19.8" - resolved "https://registry.yarnpkg.com/undici/-/undici-6.19.8.tgz#002d7c8a28f8cc3a44ff33c3d4be4d85e15d40e1" - integrity sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g== + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-6.21.0.tgz#4b3d3afaef984e07b48e7620c34ed8a285ed4cd4" + integrity sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw== unfetch@^4.2.0: version "4.2.0" @@ -9530,31 +9708,61 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" -which-boxed-primitive@^1.0.2: +which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz#d76ec27df7fa165f18d5808374a5fe23c29b176e" + integrity sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA== + dependencies: + is-bigint "^1.1.0" + is-boolean-object "^1.2.1" + is-number-object "^1.1.1" + is-string "^1.1.1" + is-symbol "^1.1.1" + +which-builtin-type@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.2.1.tgz#89183da1b4907ab089a6b02029cc5d8d6574270e" + integrity sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q== + dependencies: + call-bound "^1.0.2" + function.prototype.name "^1.1.6" + has-tostringtag "^1.0.2" + is-async-function "^2.0.0" + is-date-object "^1.1.0" + is-finalizationregistry "^1.1.0" + is-generator-function "^1.0.10" + is-regex "^1.2.1" + is-weakref "^1.0.2" + isarray "^2.0.5" + which-boxed-primitive "^1.1.0" + which-collection "^1.0.2" + which-typed-array "^1.1.16" + +which-collection@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" + integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" + is-map "^2.0.3" + is-set "^2.0.3" + is-weakmap "^2.0.2" + is-weakset "^2.0.3" which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" integrity sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ== -which-typed-array@^1.1.14, which-typed-array@^1.1.15: - version "1.1.15" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" - integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== +which-typed-array@^1.1.16: + version "1.1.18" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.18.tgz#df2389ebf3fbb246a71390e90730a9edb6ce17ad" + integrity sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA== dependencies: available-typed-arrays "^1.0.7" - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.3" for-each "^0.3.3" - gopd "^1.0.1" + gopd "^1.2.0" has-tostringtag "^1.0.2" which@^1.1.1, which@^1.3.1: @@ -9597,31 +9805,31 @@ window-size@^0.2.0: resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" integrity sha512-UD7d8HFA2+PZsbKyaOCEy8gMh1oDtHgJh1LfgjQ4zVXmYjAT/kvz3PueITKuqDiIXQe7yzpPnxX3lNc+AhQMyw== -winston-transport@^4.7.0: - version "4.7.1" - resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.7.1.tgz#52ff1bcfe452ad89991a0aaff9c3b18e7f392569" - integrity sha512-wQCXXVgfv/wUPOfb2x0ruxzwkcZfxcktz6JIMUaPLmcNhO4bZTwA/WtDWK74xV3F2dKu8YadrFv0qhwYjVEwhA== +winston-transport@^4.9.0: + version "4.9.0" + resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.9.0.tgz#3bba345de10297654ea6f33519424560003b3bf9" + integrity sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A== dependencies: - logform "^2.6.1" + logform "^2.7.0" readable-stream "^3.6.2" triple-beam "^1.3.0" winston@^3.11.0: - version "3.14.2" - resolved "https://registry.yarnpkg.com/winston/-/winston-3.14.2.tgz#94ce5fd26d374f563c969d12f0cd9c641065adab" - integrity sha512-CO8cdpBB2yqzEf8v895L+GNKYJiEq8eKlHU38af3snQBQ+sdAIUepjMSguOIJC7ICbzm0ZI+Af2If4vIJrtmOg== + version "3.17.0" + resolved "https://registry.yarnpkg.com/winston/-/winston-3.17.0.tgz#74b8665ce9b4ea7b29d0922cfccf852a08a11423" + integrity sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw== dependencies: "@colors/colors" "^1.6.0" "@dabh/diagnostics" "^2.0.2" async "^3.2.3" is-stream "^2.0.0" - logform "^2.6.0" + logform "^2.7.0" one-time "^1.0.0" readable-stream "^3.4.0" safe-stable-stringify "^2.3.1" stack-trace "0.0.x" triple-beam "^1.3.0" - winston-transport "^4.7.0" + winston-transport "^4.9.0" word-wrap@^1.2.5, word-wrap@~1.2.3: version "1.2.5" @@ -9646,7 +9854,7 @@ workerpool@^6.5.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -9663,6 +9871,15 @@ wrap-ansi@^2.0.0: string-width "^1.0.1" strip-ansi "^3.0.1" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 3381b4cb13b63831411bfc31c6cea2e1cce02f3c Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 18 Dec 2024 16:27:20 -0800 Subject: [PATCH 119/124] remove meow token ts files and move z-token folder to zns-base for DMs --- .../zns-base/meow-token/mainnet-data.ts | 0 .../zns-base/meow-token/meow-token.ts | 0 .../{ => zns-base}/z-token/mainnet-data.ts | 0 .../{ => zns-base}/z-token/z-token.ts | 265 +++++++----------- 4 files changed, 106 insertions(+), 159 deletions(-) delete mode 100644 src/deploy/missions/contracts/zns-base/meow-token/mainnet-data.ts delete mode 100644 src/deploy/missions/contracts/zns-base/meow-token/meow-token.ts rename src/deploy/missions/contracts/{ => zns-base}/z-token/mainnet-data.ts (100%) rename src/deploy/missions/contracts/{ => zns-base}/z-token/z-token.ts (54%) diff --git a/src/deploy/missions/contracts/zns-base/meow-token/mainnet-data.ts b/src/deploy/missions/contracts/zns-base/meow-token/mainnet-data.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/deploy/missions/contracts/zns-base/meow-token/meow-token.ts b/src/deploy/missions/contracts/zns-base/meow-token/meow-token.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/deploy/missions/contracts/z-token/mainnet-data.ts b/src/deploy/missions/contracts/zns-base/z-token/mainnet-data.ts similarity index 100% rename from src/deploy/missions/contracts/z-token/mainnet-data.ts rename to src/deploy/missions/contracts/zns-base/z-token/mainnet-data.ts diff --git a/src/deploy/missions/contracts/z-token/z-token.ts b/src/deploy/missions/contracts/zns-base/z-token/z-token.ts similarity index 54% rename from src/deploy/missions/contracts/z-token/z-token.ts rename to src/deploy/missions/contracts/zns-base/z-token/z-token.ts index aaa7269eb..1ae93b622 100644 --- a/src/deploy/missions/contracts/z-token/z-token.ts +++ b/src/deploy/missions/contracts/zns-base/z-token/z-token.ts @@ -1,159 +1,106 @@ -/* eslint-disable prefer-const */ -import { - BaseDeployMission, - IDeployMissionArgs, - TDeployArgs, -} from "@zero-tech/zdc"; -<<<<<<<< HEAD:src/deploy/missions/contracts/zns-base/meow-token/meow-token.ts -import { ProxyKinds } from "../../../../constants"; -import { ethers } from "ethers"; -import { znsNames } from "../../names"; -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { IZNSCampaignConfig, IZNSContracts } from "../../../../campaign/types"; -import { MeowToken__factory } from "@zero-tech/ztoken/typechain-js"; -import meowArtifact from "@zero-tech/ztoken/artifacts/contracts/MeowToken.sol/MeowToken.json"; -import { executeWithConfirmation } from "../../../../zns-campaign"; -======== -import { znsNames } from "../names"; -import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { IZNSCampaignConfig, IZNSContracts } from "../../../campaign/types"; -import { IZTokenConfig } from "../../types"; -import { ZToken__factory } from "../../../../../typechain"; ->>>>>>>> rc/multi-zns-main:src/deploy/missions/contracts/z-token/z-token.ts - - -export class ZTokenDM extends BaseDeployMission< -HardhatRuntimeEnvironment, -SignerWithAddress, -IZNSCampaignConfig, -IZNSContracts -> { - proxyData = { - isProxy: false, - }; - - contractName = znsNames.zToken.contract; - instanceName = znsNames.zToken.instance; - - constructor (args : IDeployMissionArgs< - HardhatRuntimeEnvironment, - SignerWithAddress, - IZNSCampaignConfig, - IZNSContracts - >) { - super(args); - -<<<<<<<< HEAD:src/deploy/missions/contracts/zns-base/meow-token/meow-token.ts - if (this.config.mockMeowToken) { - this.contractName = znsNames.meowToken.contractMock; -======== - if (this.config.mockZToken) { - this.contractName = znsNames.zToken.contractMock; - } else { - this.contractName = znsNames.zToken.contract; ->>>>>>>> rc/multi-zns-main:src/deploy/missions/contracts/z-token/z-token.ts - } - } - - async deploy () { - if (!this.config.mockZToken) { - this.logger.info("Using Z token from Mainnet"); - - // TODO dep: add proper bytecode comparison here and throw if different! - // const bytecodeFromChain = await this.campaign.deployer.getBytecodeFromChain(this.config.stakingTokenAddress); - - // const { - // bytecode, - // } = this.getArtifact(); - - // if (!compareBytecodeStrict(bytecode, bytecodeFromChain)) { - // this.logger.error("Z token bytecode compiled in this module differs from Mainnet"); - // throw new Error( - // "Z token bytecode compiled in this module differs from Mainnet" - // ); - // } - - this.logger.debug(`Writing ${this.contractName} to DB...`); - - const factory = new ZToken__factory(this.config.deployAdmin); - const baseContract = factory.attach(this.config.stakingTokenAddress); - - await this.saveToDB(baseContract); - - this.campaign.updateStateContract(this.instanceName, this.contractName, baseContract); - - // eslint-disable-next-line max-len - this.logger.info(`Successfully created ${this.contractName} contract from Mainnet data at ${await baseContract.getAddress()}`); - } else { - await super.deploy(); - } - } - - async deployArgs () : Promise { - let { - name, - symbol, - defaultAdmin, - initialAdminDelay, - minter, - mintBeneficiary, - initialSupplyBase, - inflationRates, - finalInflationRate, - } = this.config.zTokenConfig as IZTokenConfig; - -<<<<<<<< HEAD:src/deploy/missions/contracts/zns-base/meow-token/meow-token.ts - async needsPostDeploy () { - const { - meowToken, - config: { - deployAdmin, - mockMeowToken, - }, - } = this.campaign; - - const balance = await meowToken.balanceOf(deployAdmin.address); - - const needs = mockMeowToken && balance === 0n; - - const msg = needs ? "needs" : "doesn't need"; - - this.logger.debug(`${this.contractName} ${msg} post deploy sequence`); - - return needs; - } - - async postDeploy () { - const { - meowToken, - config: { - deployAdmin, - }, - } = this.campaign; - - // Mint 100,000 MEOW to the deployer - await executeWithConfirmation( - meowToken.connect(deployAdmin).mint( - await deployAdmin.getAddress(), - ethers.parseEther("100000"), - ) - ); - - this.logger.debug(`${this.contractName} post deploy sequence completed`); -======== - return [ - name, - symbol, - defaultAdmin, - initialAdminDelay, - minter, - mintBeneficiary, - initialSupplyBase, - inflationRates, - finalInflationRate, - ]; ->>>>>>>> rc/multi-zns-main:src/deploy/missions/contracts/z-token/z-token.ts - } -} +import { + BaseDeployMission, + IDeployMissionArgs, + TDeployArgs, +} from "@zero-tech/zdc"; +import { znsNames } from "../../names"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; +import { IZNSCampaignConfig, IZNSContracts } from "../../../../campaign/types"; +import { IZTokenConfig } from "../../../types"; +import { ZToken__factory } from "../../../../../../typechain"; + + +export class ZTokenDM extends BaseDeployMission< +HardhatRuntimeEnvironment, +SignerWithAddress, +IZNSCampaignConfig, +IZNSContracts +> { + proxyData = { + isProxy: false, + }; + + contractName = znsNames.zToken.contract; + instanceName = znsNames.zToken.instance; + + constructor (args : IDeployMissionArgs< + HardhatRuntimeEnvironment, + SignerWithAddress, + IZNSCampaignConfig, + IZNSContracts + >) { + super(args); + + if (this.config.mockZToken) { + this.contractName = znsNames.zToken.contractMock; + } else { + this.contractName = znsNames.zToken.contract; + } + } + + async deploy () { + if (!this.config.mockZToken) { + this.logger.info("Using Z token from Mainnet"); + + // TODO dep: add proper bytecode comparison here and throw if different! + // const bytecodeFromChain = await this.campaign.deployer.getBytecodeFromChain(this.config.stakingTokenAddress); + + // const { + // bytecode, + // } = this.getArtifact(); + + // if (!compareBytecodeStrict(bytecode, bytecodeFromChain)) { + // this.logger.error("Z token bytecode compiled in this module differs from Mainnet"); + // throw new Error( + // "Z token bytecode compiled in this module differs from Mainnet" + // ); + // } + + this.logger.debug(`Writing ${this.contractName} to DB...`); + + const factory = new ZToken__factory(this.config.deployAdmin); + const baseContract = factory.attach(this.config.stakingTokenAddress); + // TODO remove! + // const baseContract = await this.campaign.deployer.getContractObject( + // this.contractName, + // this.config.stakingTokenAddress as string, + // ); + + await this.saveToDB(baseContract); + + this.campaign.updateStateContract(this.instanceName, this.contractName, baseContract); + + // eslint-disable-next-line max-len + this.logger.info(`Successfully created ${this.contractName} contract from Mainnet data at ${await baseContract.getAddress()}`); + } else { + await super.deploy(); + } + } + + async deployArgs () : Promise { + const { + name, + symbol, + defaultAdmin, + initialAdminDelay, + minter, + mintBeneficiary, + initialSupplyBase, + inflationRates, + finalInflationRate, + } = this.config.zTokenConfig as IZTokenConfig; + + return [ + name, + symbol, + defaultAdmin, + initialAdminDelay, + minter, + mintBeneficiary, + initialSupplyBase, + inflationRates, + finalInflationRate, + ]; + } +} From fa5d0f80b2a478dd094f5aac24ff2d7c0e482d4f Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 18 Dec 2024 16:27:39 -0800 Subject: [PATCH 120/124] fix eslintrc --- .eslintrc | 3 +-- test/DeployCampaignInt.test.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.eslintrc b/.eslintrc index 56fe5bd49..f8804a29e 100644 --- a/.eslintrc +++ b/.eslintrc @@ -10,8 +10,7 @@ "no-console": "off", "no-shadow": "warn", "@typescript-eslint/no-shadow": "warn", - "no-invalid-this": "off", - "jsdoc/newline-after-description": "off" + "no-invalid-this": "off" // "@typescript-eslint/no-unused-vars": "off" // For debugging } } diff --git a/test/DeployCampaignInt.test.ts b/test/DeployCampaignInt.test.ts index 85d3ef064..596538b57 100644 --- a/test/DeployCampaignInt.test.ts +++ b/test/DeployCampaignInt.test.ts @@ -43,7 +43,7 @@ import { ZNSStringResolverDM } from "../src/deploy/missions/contracts/zns-base/s import { znsNames } from "../src/deploy/missions/contracts/names"; import { runZnsCampaign } from "../src/deploy/zns-campaign"; // TODO multi: why does this have Sepolia in the name ?! Check and validate ! -import { ZSepolia } from "../src/deploy/missions/contracts/z-token/mainnet-data"; +import { ZSepolia } from "../src/deploy/missions/contracts/zns-base/z-token/mainnet-data"; import { MeowMainnet } from "../src/deploy/missions/contracts/zns-base/meow-token/mainnet-data"; import { ResolverTypes } from "../src/deploy/constants"; import { buildCrosschainConfig, getConfig } from "../src/deploy/campaign/get-config"; From 1c2d4bf09a6696c95acec429ff426750033c02a3 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 18 Dec 2024 16:49:33 -0800 Subject: [PATCH 121/124] fix get-config file --- src/deploy/campaign/get-config.ts | 143 ++++++++++++++---------------- 1 file changed, 68 insertions(+), 75 deletions(-) diff --git a/src/deploy/campaign/get-config.ts b/src/deploy/campaign/get-config.ts index 568587987..f77bb6423 100644 --- a/src/deploy/campaign/get-config.ts +++ b/src/deploy/campaign/get-config.ts @@ -1,5 +1,4 @@ import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; - import { IZNSCampaignConfig, IZNSEthCrossConfig, @@ -9,13 +8,11 @@ import { import { DEFAULT_DECIMALS, DEFAULT_PRECISION, - getCurvePrice, - DEFAULT_PRICE_CONFIG, NO_MOCK_PROD_ERR, STAKING_TOKEN_ERR, INVALID_CURVE_ERR, MONGO_URI_ERR, - INVALID_ENV_ERR, NO_ZERO_VAULT_ERR, + INVALID_ENV_ERR, INITIAL_ADMIN_DELAY_DEFAULT, INITIAL_SUPPLY_DEFAULT, INFLATION_RATES_DEFAULT, @@ -24,13 +21,12 @@ import { Z_SYMBOL_DEFAULT, } from "../../../test/helpers"; import { ethers, Wallet } from "ethers"; -import { MeowMainnet } from "../missions/contracts/zns-base/meow-token/mainnet-data"; import { TSupportedChain } from "../missions/contracts/cross-chain/portals/types"; import { SupportedChains } from "../missions/contracts/cross-chain/portals/get-portal-dm"; import { findMissingEnvVars } from "../../environment/validate"; import { ICurvePriceConfig, IZTokenConfig } from "../missions/types"; import process from "process"; -import { ZSepolia } from "../missions/contracts/z-token/mainnet-data"; +import { ZSepolia, ZTokenMainnet } from "../missions/contracts/zns-base/z-token/mainnet-data"; const getCustomAddresses = ( @@ -65,6 +61,65 @@ const getCustomAddresses = ( return addresses; }; +export const buildCrosschainConfig = () : TZNSCrossConfig => { + const srcChainName = process.env.SRC_CHAIN_NAME as TSupportedChain; + const mockZkEvmBridge = process.env.MOCK_ZKEVM_BRIDGE === "true"; + + let curNetworkId; + let zkEvmBridgeAddress; + if (!mockZkEvmBridge) { + requires( + !!process.env.ZK_EVM_BRIDGE, + "Must provide source zkEVM bridge address from this chain if not mocking!" + ); + zkEvmBridgeAddress = process.env.ZK_EVM_BRIDGE; + } else { + requires( + !!process.env.NETWORK_ID, + "Must provide current network ID for mocked bridge!" + ); + curNetworkId = BigInt(process.env.NETWORK_ID); + } + + const baseConfig = { + mockZkEvmBridge, + srcChainName, + zkEvmBridgeAddress, + curNetworkId, + bridgeToken: process.env.BRIDGE_TOKEN, + }; + + let crossConfig; + switch (srcChainName) { + case SupportedChains.eth: + requires(!!process.env.DEST_NETWORK_ID, "Must provide destination network ID!"); + requires(!!process.env.DEST_CHAIN_NAME, "Must provide destination chain name!"); + requires(!!process.env.DEST_CHAIN_ID, "Must provide destination chain ID!"); + + crossConfig = { + ...baseConfig, + destNetworkId: BigInt(process.env.DEST_NETWORK_ID), + destChainName: process.env.DEST_CHAIN_NAME, + destChainId: BigInt(process.env.DEST_CHAIN_ID), + } as IZNSEthCrossConfig; + + break; + case SupportedChains.z: + requires(!!process.env.SRC_ZNS_PORTAL, "Must provide source ZNSZChainPortal address!"); + + crossConfig = { + ...baseConfig, + srcZnsPortal: process.env.SRC_ZNS_PORTAL, + } as IZNSZChainCrossConfig; + + break; + default: + throw new Error(`Unsupported chain: ${srcChainName}!`); + } + + return crossConfig; +}; + // This function builds a config with default values but overrides them with any values that are set export const getConfig = async ({ deployer, @@ -94,7 +149,6 @@ export const getConfig = async ({ let zeroVaultAddressConf : string; const zeroVaultAddressEnv = process.env.ZERO_VAULT_ADDRESS; - const mockZTokenEnv = process.env.MOCK_Z_TOKEN; const envLevel = process.env.ENV_LEVEL; // Get governor addresses set through env, if any @@ -126,18 +180,16 @@ export const getConfig = async ({ finalInflationRate: FINAL_INFLATION_RATE_DEFAULT, }; } else { - zeroVaultAddressConf = zeroVaultAddressEnv; + zeroVaultAddressConf = zeroVaultAddressEnv; + } } // Domain Token Values const royaltyReceiver = envLevel !== "dev" ? process.env.ROYALTY_RECEIVER! : zeroVaultAddressConf; - const royaltyFraction = - process.env.ROYALTY_FRACTION - ? BigInt(process.env.ROYALTY_FRACTION) - : DEFAULT_ROYALTY_FRACTION; + const royaltyFraction = BigInt(process.env.ROYALTY_FRACTION); - const config : IZNSCampaignConfig = { - env: envLevel!, + const config : IZNSCampaignConfig = { + env: envLevel, deployAdmin: deployer, governorAddresses, adminAddresses, @@ -150,7 +202,7 @@ export const getConfig = async ({ rootPriceConfig: priceConfig, zTokenConfig: zConfig, zeroVaultAddress: zeroVaultAddressConf, - mockMeowToken: process.env.MOCK_MEOW_TOKEN === "true", + mockZToken: process.env.MOCK_Z_TOKEN === "true", stakingTokenAddress: process.env.STAKING_TOKEN_ADDRESS, postDeploy: { tenderlyProjectSlug: process.env.TENDERLY_PROJECT_SLUG ?? "", @@ -201,7 +253,7 @@ export const validateEnv = ( if (envLevel === "prod") { requires(!process.env.MONGO_DB_URI.includes("localhost"), MONGO_URI_ERR); requires(mockZTokenEnv === "false", NO_MOCK_PROD_ERR); - requires(process.env.STAKING_TOKEN_ADDRESS === ZSepolia.address, STAKING_TOKEN_ERR); + requires(process.env.STAKING_TOKEN_ADDRESS === ZTokenMainnet.address, STAKING_TOKEN_ERR); } if (process.env.VERIFY_CONTRACTS === "true") { @@ -257,62 +309,3 @@ const validateConfig = (config : ICurvePriceConfig) => { requires(false, INVALID_CURVE_ERR); } }; - -export const buildCrosschainConfig = () : TZNSCrossConfig => { - const srcChainName = process.env.SRC_CHAIN_NAME as TSupportedChain; - const mockZkEvmBridge = process.env.MOCK_ZKEVM_BRIDGE === "true"; - - let curNetworkId; - let zkEvmBridgeAddress; - if (!mockZkEvmBridge) { - requires( - !!process.env.ZK_EVM_BRIDGE, - "Must provide source zkEVM bridge address from this chain if not mocking!" - ); - zkEvmBridgeAddress = process.env.ZK_EVM_BRIDGE; - } else { - requires( - !!process.env.NETWORK_ID, - "Must provide current network ID for mocked bridge!" - ); - curNetworkId = BigInt(process.env.NETWORK_ID); - } - - const baseConfig = { - mockZkEvmBridge, - srcChainName, - zkEvmBridgeAddress, - curNetworkId, - bridgeToken: process.env.BRIDGE_TOKEN, - }; - - let crossConfig; - switch (srcChainName) { - case SupportedChains.eth: - requires(!!process.env.DEST_NETWORK_ID, "Must provide destination network ID!"); - requires(!!process.env.DEST_CHAIN_NAME, "Must provide destination chain name!"); - requires(!!process.env.DEST_CHAIN_ID, "Must provide destination chain ID!"); - - crossConfig = { - ...baseConfig, - destNetworkId: BigInt(process.env.DEST_NETWORK_ID), - destChainName: process.env.DEST_CHAIN_NAME, - destChainId: BigInt(process.env.DEST_CHAIN_ID), - } as IZNSEthCrossConfig; - - break; - case SupportedChains.z: - requires(!!process.env.SRC_ZNS_PORTAL, "Must provide source ZNSZChainPortal address!"); - - crossConfig = { - ...baseConfig, - srcZnsPortal: process.env.SRC_ZNS_PORTAL, - } as IZNSZChainCrossConfig; - - break; - default: - throw new Error(`Unsupported chain: ${srcChainName}!`); - } - - return crossConfig; -}; From 109b5c5aa2e6e3e469e47cd65884cdd0bf15e345 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Wed, 18 Dec 2024 16:50:01 -0800 Subject: [PATCH 122/124] small initial fixes after merge --- .../zns-base/z-token/mainnet-data.ts | 4 +++ src/environment/env.ts | 7 ++-- src/environment/types.ts | 4 +-- test/DeployCampaign.integration.test.ts | 3 +- test/DeployCampaignInt.test.ts | 19 +++++------ .../CrossChainDomainBridging.network.test.ts | 2 +- test/cross-chain/mint-looper.temp.ts | 33 ------------------- test/helpers/deploy/deploy-zns.ts | 6 +--- test/helpers/tokens.ts | 8 ++--- 9 files changed, 26 insertions(+), 60 deletions(-) delete mode 100644 test/cross-chain/mint-looper.temp.ts diff --git a/src/deploy/missions/contracts/zns-base/z-token/mainnet-data.ts b/src/deploy/missions/contracts/zns-base/z-token/mainnet-data.ts index bc2879a8c..4783e9836 100644 --- a/src/deploy/missions/contracts/zns-base/z-token/mainnet-data.ts +++ b/src/deploy/missions/contracts/zns-base/z-token/mainnet-data.ts @@ -2,3 +2,7 @@ export const ZSepolia = { address: "0x7148Db73c78Ded8e4f81784A121Bbe7E163f4834", }; +// TODO multi: fix this to have actual MAINNET DATA HERE! +export const ZTokenMainnet = { + address: "NOT IMPLEMENTED!", +}; diff --git a/src/environment/env.ts b/src/environment/env.ts index 3ef0f575a..4826f4cab 100644 --- a/src/environment/env.ts +++ b/src/environment/env.ts @@ -46,12 +46,13 @@ export const environment : IZNSEnvironment = { // ! System Administration ! GOVERNOR_ADDRESSES: "", ADMIN_ADDRESSES: "", - // ZNS Payment Token (e.g. MEOW or Z) - MOCK_MEOW_TOKEN: "true", + // ZNS Payment Token (e.g. Z) + MOCK_Z_TOKEN: "true", STAKING_TOKEN_ADDRESS: "", // CurvePricer Config [without decimals!] + // TODO multi: check defaults for the new formula and update !!! MAX_PRICE: "25000", - MIN_PRICE: "2000", + CURVE_MULTIPLIER: "1000", MAX_LENGTH: "50", BASE_LENGTH: "4", PROTOCOL_FEE_PERC: "222", diff --git a/src/environment/types.ts b/src/environment/types.ts index af5a33dce..ed8523cc9 100644 --- a/src/environment/types.ts +++ b/src/environment/types.ts @@ -23,10 +23,10 @@ export interface IZNSEnvironment { DEVNET_RPC_URL ?: string; GOVERNOR_ADDRESSES ?: string; ADMIN_ADDRESSES ?: string; - MOCK_MEOW_TOKEN : string; + MOCK_Z_TOKEN : string; STAKING_TOKEN_ADDRESS ?: string; MAX_PRICE : string; - MIN_PRICE : string; + CURVE_MULTIPLIER : string; MAX_LENGTH : string; BASE_LENGTH : string; PROTOCOL_FEE_PERC : string; diff --git a/test/DeployCampaign.integration.test.ts b/test/DeployCampaign.integration.test.ts index 1e26c428e..f3206ebd4 100644 --- a/test/DeployCampaign.integration.test.ts +++ b/test/DeployCampaign.integration.test.ts @@ -16,6 +16,7 @@ import { registerSubdomainBulk, } from "./helpers/deploy-helpers"; import { IZNSCampaignConfig, IZNSContracts } from "../src/deploy/campaign/types"; +import { Wallet } from "ethers"; describe("zNS + zDC Single Integration Test", () => { @@ -29,7 +30,7 @@ describe("zNS + zDC Single Integration Test", () => { let userE : SignerWithAddress; let userF : SignerWithAddress; - let config : IZNSCampaignConfig; + let config : IZNSCampaignConfig; let zns : IZNSContracts; // let mongoAdapter : MongoDBAdapter; diff --git a/test/DeployCampaignInt.test.ts b/test/DeployCampaignInt.test.ts index 596538b57..e2b55b948 100644 --- a/test/DeployCampaignInt.test.ts +++ b/test/DeployCampaignInt.test.ts @@ -30,9 +30,7 @@ import { Z_SYMBOL_DEFAULT, } from "./helpers"; import { - ZTokenDM, - meowTokenName, - meowTokenSymbol, PolygonZkEVMBridgeV2DM, + ZTokenDM, PolygonZkEVMBridgeV2DM, ZNSAccessControllerDM, ZNSAddressResolverDM, ZNSChainResolverDM, ZNSCurvePricerDM, @@ -44,7 +42,6 @@ import { znsNames } from "../src/deploy/missions/contracts/names"; import { runZnsCampaign } from "../src/deploy/zns-campaign"; // TODO multi: why does this have Sepolia in the name ?! Check and validate ! import { ZSepolia } from "../src/deploy/missions/contracts/zns-base/z-token/mainnet-data"; -import { MeowMainnet } from "../src/deploy/missions/contracts/zns-base/meow-token/mainnet-data"; import { ResolverTypes } from "../src/deploy/constants"; import { buildCrosschainConfig, getConfig } from "../src/deploy/campaign/get-config"; import { ethers, Wallet } from "ethers"; @@ -94,8 +91,8 @@ describe("Deploy Campaign Test", () => { }, rootPriceConfig: DEFAULT_PRICE_CONFIG, zeroVaultAddress: zeroVault.address, - stakingTokenAddress: MeowMainnet.address, - mockMeowToken: true, + stakingTokenAddress: ZSepolia.address, + mockZToken: true, postDeploy: { tenderlyProjectSlug: "", monitorContracts: false, @@ -398,7 +395,7 @@ describe("Deploy Campaign Test", () => { rootPriceConfig: DEFAULT_PRICE_CONFIG, zeroVaultAddress: zeroVault.address, stakingTokenAddress: "", - mockMeowToken: true, // 1700083028872 + mockZToken: true, postDeploy: { tenderlyProjectSlug: "", monitorContracts: false, @@ -903,8 +900,8 @@ describe("Deploy Campaign Test", () => { }, rootPriceConfig: DEFAULT_PRICE_CONFIG, zeroVaultAddress: zeroVault.address, - stakingTokenAddress: MeowMainnet.address, - mockMeowToken: true, + stakingTokenAddress: ZSepolia.address, + mockZToken: true, postDeploy: { tenderlyProjectSlug: "", monitorContracts: false, @@ -1090,8 +1087,8 @@ describe("Deploy Campaign Test", () => { }, rootPriceConfig: DEFAULT_PRICE_CONFIG, zeroVaultAddress: zeroVault.address, - stakingTokenAddress: MeowMainnet.address, - mockMeowToken: true, + stakingTokenAddress: ZSepolia.address, + mockZToken: true, postDeploy: { tenderlyProjectSlug: "", monitorContracts: false, diff --git a/test/cross-chain/CrossChainDomainBridging.network.test.ts b/test/cross-chain/CrossChainDomainBridging.network.test.ts index 859bc8486..92eb9c8fe 100644 --- a/test/cross-chain/CrossChainDomainBridging.network.test.ts +++ b/test/cross-chain/CrossChainDomainBridging.network.test.ts @@ -54,7 +54,7 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => let subUser : SignerWithAddress; let subUserL2 : Wallet | SignerWithAddress; - let configL1 : IZNSCampaignConfig; + let configL1 : IZNSCampaignConfig; let configL2 : IZNSCampaignConfig; const rootDomainLabel = "jeffbridges"; diff --git a/test/cross-chain/mint-looper.temp.ts b/test/cross-chain/mint-looper.temp.ts deleted file mode 100644 index 393ef5a75..000000000 --- a/test/cross-chain/mint-looper.temp.ts +++ /dev/null @@ -1,33 +0,0 @@ -import * as hre from "hardhat"; -import { MeowTokenMock, MeowTokenMock__factory } from "../../typechain"; - - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -const sendTxes = async () => { - const amounts = Array.from({ length: 50 }, (_, i) => BigInt(i + 1) * BigInt(1e18)); - - const [caller, caller2, caller3] = await hre.ethers.getSigners(); - const fact = new MeowTokenMock__factory(); - const meowToken = fact.attach("0x50e6DFFf992747775C9c49717CFC4970b40594Dc") as MeowTokenMock; - - const resArr = await amounts.reduce( - async (acc, amt, idx) => { - const res = await acc; - - const txCaller = idx % 3 === 0 ? caller : idx % 3 === 1 ? caller2 : caller3; - console.log(`Minting tx #${idx} from ${txCaller.address}`); - - const tx = await meowToken.connect(txCaller).mint(txCaller.address, amt); - const rec = await tx.wait(1); - res.push(rec); - return res; - }, Promise.resolve([]), - ); - - console.log("Minted tokens:", JSON.stringify(resArr, null, "\t")); -}; - -// sendTxes().catch(error => { -// console.error(error); -// process.exit(1); -// }); diff --git a/test/helpers/deploy/deploy-zns.ts b/test/helpers/deploy/deploy-zns.ts index d844edf20..352f95239 100644 --- a/test/helpers/deploy/deploy-zns.ts +++ b/test/helpers/deploy/deploy-zns.ts @@ -35,14 +35,12 @@ import { } from "../../../typechain"; import { DeployZNSParams, RegistrarConfig, IZNSContractsLocal } from "../types"; import * as hre from "hardhat"; -import { upgrades } from "hardhat"; +import { upgrades, ethers } from "hardhat"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { erc1967ProxyName, fixedPricerName, DEFAULT_PRICE_CONFIG, - curvePricerName, - zTokenMockName, ZNS_DOMAIN_TOKEN_NAME, ZNS_DOMAIN_TOKEN_SYMBOL, DEFAULT_ROYALTY_FRACTION, @@ -60,11 +58,9 @@ import { import { PORTAL_ROLE, DOMAIN_TOKEN_ROLE, REGISTRAR_ROLE } from "../../../src/deploy/constants"; import { getProxyImplAddress } from "../utils"; import { ICurvePriceConfig } from "../../../src/deploy/missions/types"; -import { meowTokenName, meowTokenSymbol } from "../../../src/deploy/missions/contracts"; import { transparentProxyName, znsNames } from "../../../src/deploy/missions/contracts/names"; import { TSupportedChain } from "../../../src/deploy/missions/contracts/cross-chain/portals/types"; import { SupportedChains } from "../../../src/deploy/missions/contracts/cross-chain/portals/get-portal-dm"; -import { transparentProxyName } from "../../../src/deploy/missions/contracts/names"; export const deployAccessController = async ({ diff --git a/test/helpers/tokens.ts b/test/helpers/tokens.ts index fc6a6da3a..af418ca08 100644 --- a/test/helpers/tokens.ts +++ b/test/helpers/tokens.ts @@ -1,11 +1,11 @@ -import { MeowTokenMock, MeowTokenMock__factory } from "../../typechain"; +import { ZTokenMock, ZTokenMock__factory } from "../../typechain"; import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; export const getTokenContract = ( address : string, signer : SignerWithAddress -) : MeowTokenMock => { - const ierc20 = MeowTokenMock__factory.connect(address, signer); - return ierc20.attach(address) as MeowTokenMock; +) : ZTokenMock => { + const ierc20 = ZTokenMock__factory.connect(address, signer); + return ierc20.attach(address) as ZTokenMock; }; From 4767b84ef9a12922524c2f8a4cbcf89e0e12d291 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Fri, 20 Dec 2024 12:32:38 -0800 Subject: [PATCH 123/124] more test fixes --- hardhat.config.ts | 59 ++++++++++++------- src/environment/validate.ts | 2 +- test/DeployCampaignInt.test.ts | 44 ++++++++++++++ .../CrossChainDomainBridging.network.test.ts | 8 +-- test/gas/gas-costs.json | 6 +- 5 files changed, 91 insertions(+), 28 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 45827571e..64d7bcea2 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -61,26 +61,27 @@ const config : HardhatUserConfig = { }, }, ], - overrides: { - "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol": { - version: "0.8.20", - settings: { - optimizer: { - enabled: true, - runs: 20000, - }, - }, - }, - "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol": { - version: "0.8.20", - settings: { - optimizer: { - enabled: true, - runs: 20000, - }, - }, - }, - }, + // TODO multi: figure out why this breaks the compilation even though the version is correct ?? + // overrides: { + // "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol": { + // version: "0.8.20", + // settings: { + // optimizer: { + // enabled: true, + // runs: 20000, + // }, + // }, + // }, + // "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol": { + // version: "0.8.20", + // settings: { + // optimizer: { + // enabled: true, + // runs: 20000, + // }, + // }, + // }, + // }, }, paths: { sources: "./contracts", @@ -90,6 +91,7 @@ const config : HardhatUserConfig = { }, typechain: { outDir: "typechain", + externalArtifacts: ["./node_modules/@zero-tech/zkevm-contracts/compiled-contracts/*.json"], }, mocha: { timeout: 5000000, @@ -130,10 +132,27 @@ const config : HardhatUserConfig = { // `${process.env.TESTNET_PRIVATE_KEY_C}`, ], }, + moonwalker: { + url: `${process.env.MOONWALKER_RPC_URL}`, + chainId: 1828369849, + accounts: [ + `${process.env.ZTOKEN_BENEFICIARY}`, + // `${process.env.TESTNET_PRIVATE_KEY_B}`, + // `${process.env.TESTNET_PRIVATE_KEY_C}`, + ], + }, }, etherscan: { apiKey: `${process.env.ETHERSCAN_API_KEY}`, customChains: [ + { + network: "moonwalker", + chainId: 1828369849, + urls: { + apiURL: "https://moonwalker-blockscout.eu-north-2.gateway.fm/api/", + browserURL: "https://moonwalker-blockscout.eu-north-2.gateway.fm/", + }, + }, { network: "zchaintest", chainId: 2012605151, diff --git a/src/environment/validate.ts b/src/environment/validate.ts index 9f02151f6..4d596868f 100644 --- a/src/environment/validate.ts +++ b/src/environment/validate.ts @@ -1,7 +1,7 @@ const required = [ "MONGO_DB_URI", "MONGO_DB_NAME", "ARCHIVE_PREVIOUS_DB_VERSION", "LOG_LEVEL", "ARCHIVE_PREVIOUS_DB_VERSION", - "LOG_LEVEL", "ENV_LEVEL", "MAX_PRICE", "MIN_PRICE", "MAX_LENGTH", "BASE_LENGTH", "PROTOCOL_FEE_PERC", + "LOG_LEVEL", "ENV_LEVEL", "MAX_PRICE", "CURVE_MULTIPLIER", "MAX_LENGTH", "BASE_LENGTH", "PROTOCOL_FEE_PERC", "DECIMALS", "PRECISION", "DOMAIN_TOKEN_NAME", "DOMAIN_TOKEN_SYMBOL", "ROYALTY_FRACTION", "MOCK_MEOW_TOKEN", "SRC_CHAIN_NAME", "MOCK_ZKEVM_BRIDGE", ]; diff --git a/test/DeployCampaignInt.test.ts b/test/DeployCampaignInt.test.ts index e2b55b948..3b71dd059 100644 --- a/test/DeployCampaignInt.test.ts +++ b/test/DeployCampaignInt.test.ts @@ -93,6 +93,17 @@ describe("Deploy Campaign Test", () => { zeroVaultAddress: zeroVault.address, stakingTokenAddress: ZSepolia.address, mockZToken: true, + zTokenConfig: { + name: Z_NAME_DEFAULT, + symbol: Z_SYMBOL_DEFAULT, + defaultAdmin: deployAdmin.address, + initialAdminDelay: INITIAL_ADMIN_DELAY_DEFAULT, + minter: deployAdmin.address, + mintBeneficiary: deployAdmin.address, + initialSupplyBase: INITIAL_SUPPLY_DEFAULT, + inflationRates: INFLATION_RATES_DEFAULT, + finalInflationRate: FINAL_INFLATION_RATE_DEFAULT, + }, postDeploy: { tenderlyProjectSlug: "", monitorContracts: false, @@ -396,6 +407,17 @@ describe("Deploy Campaign Test", () => { zeroVaultAddress: zeroVault.address, stakingTokenAddress: "", mockZToken: true, + zTokenConfig: { + name: Z_NAME_DEFAULT, + symbol: Z_SYMBOL_DEFAULT, + defaultAdmin: deployAdmin.address, + initialAdminDelay: INITIAL_ADMIN_DELAY_DEFAULT, + minter: deployAdmin.address, + mintBeneficiary: deployAdmin.address, + initialSupplyBase: INITIAL_SUPPLY_DEFAULT, + inflationRates: INFLATION_RATES_DEFAULT, + finalInflationRate: FINAL_INFLATION_RATE_DEFAULT, + }, postDeploy: { tenderlyProjectSlug: "", monitorContracts: false, @@ -902,6 +924,17 @@ describe("Deploy Campaign Test", () => { zeroVaultAddress: zeroVault.address, stakingTokenAddress: ZSepolia.address, mockZToken: true, + zTokenConfig: { + name: Z_NAME_DEFAULT, + symbol: Z_SYMBOL_DEFAULT, + defaultAdmin: deployAdmin.address, + initialAdminDelay: INITIAL_ADMIN_DELAY_DEFAULT, + minter: deployAdmin.address, + mintBeneficiary: deployAdmin.address, + initialSupplyBase: INITIAL_SUPPLY_DEFAULT, + inflationRates: INFLATION_RATES_DEFAULT, + finalInflationRate: FINAL_INFLATION_RATE_DEFAULT, + }, postDeploy: { tenderlyProjectSlug: "", monitorContracts: false, @@ -1089,6 +1122,17 @@ describe("Deploy Campaign Test", () => { zeroVaultAddress: zeroVault.address, stakingTokenAddress: ZSepolia.address, mockZToken: true, + zTokenConfig: { + name: Z_NAME_DEFAULT, + symbol: Z_SYMBOL_DEFAULT, + defaultAdmin: deployAdmin.address, + initialAdminDelay: INITIAL_ADMIN_DELAY_DEFAULT, + minter: deployAdmin.address, + mintBeneficiary: deployAdmin.address, + initialSupplyBase: INITIAL_SUPPLY_DEFAULT, + inflationRates: INFLATION_RATES_DEFAULT, + finalInflationRate: FINAL_INFLATION_RATE_DEFAULT, + }, postDeploy: { tenderlyProjectSlug: "", monitorContracts: false, diff --git a/test/cross-chain/CrossChainDomainBridging.network.test.ts b/test/cross-chain/CrossChainDomainBridging.network.test.ts index 92eb9c8fe..bc930248f 100644 --- a/test/cross-chain/CrossChainDomainBridging.network.test.ts +++ b/test/cross-chain/CrossChainDomainBridging.network.test.ts @@ -270,7 +270,7 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => pricerContract: znsL1.curvePricer.target, }, paymentConfig: { - token: znsL1.meowToken.target, + token: znsL1.zToken.target, beneficiary: deployAdmin.address, }, priceConfig: DEFAULT_PRICE_CONFIG, @@ -287,7 +287,7 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => isBridging: true, }); - balanceBeforeBridge = await znsL1.meowToken.balanceOf(user.address); + balanceBeforeBridge = await znsL1.zToken.balanceOf(user.address); const tx = await znsL1.zChainPortal.connect(user).registerAndBridgeDomain( parentHash as string, @@ -360,7 +360,7 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => }); it("should withdraw the correct amount of tokens from the caller", async () => { - const balanceAfterBridge = await znsL1.meowToken.balanceOf(user.address); + const balanceAfterBridge = await znsL1.zToken.balanceOf(user.address); const priceConfig = isRealNetwork ? getValidateRootPriceConfig() : DEFAULT_PRICE_CONFIG; const priceRef = getCurvePrice(label, priceConfig); @@ -538,7 +538,7 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => await tx.wait(confNum); const paymentConfigToSet = { - token: znsL2.meowToken.target, + token: znsL2.zToken.target, beneficiary: user.address, }; tx = await znsL2.treasury.connect(userL2).setPaymentConfig( diff --git a/test/gas/gas-costs.json b/test/gas/gas-costs.json index 957af37b9..496ba4a27 100644 --- a/test/gas/gas-costs.json +++ b/test/gas/gas-costs.json @@ -1,4 +1,4 @@ { - "Root Domain Price": "470187", - "Subdomain Price": "463250" -} + "Root Domain Price": "463047", + "Subdomain Price": "456881" +} \ No newline at end of file From b2701971cdbfa8f132fc0a3f8364b29051674286 Mon Sep 17 00:00:00 2001 From: Whytecrowe Date: Fri, 3 Jan 2025 17:14:13 -0800 Subject: [PATCH 124/124] fix test helpers to include zToken properly and transfer instead of mint --- hardhat.config.ts | 4 ++-- .../CrossChainDomainBridging.network.test.ts | 3 +++ test/helpers/register-setup.ts | 14 ++++++++++---- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 64d7bcea2..578419caf 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -91,7 +91,7 @@ const config : HardhatUserConfig = { }, typechain: { outDir: "typechain", - externalArtifacts: ["./node_modules/@zero-tech/zkevm-contracts/compiled-contracts/*.json"], + // externalArtifacts: ["./node_modules/@zero-tech/zkevm-contracts/compiled-contracts/*.json"], }, mocha: { timeout: 5000000, @@ -136,7 +136,7 @@ const config : HardhatUserConfig = { url: `${process.env.MOONWALKER_RPC_URL}`, chainId: 1828369849, accounts: [ - `${process.env.ZTOKEN_BENEFICIARY}`, + // `${process.env.ZTOKEN_BENEFICIARY}`, // `${process.env.TESTNET_PRIVATE_KEY_B}`, // `${process.env.TESTNET_PRIVATE_KEY_C}`, ], diff --git a/test/cross-chain/CrossChainDomainBridging.network.test.ts b/test/cross-chain/CrossChainDomainBridging.network.test.ts index bc930248f..71e428889 100644 --- a/test/cross-chain/CrossChainDomainBridging.network.test.ts +++ b/test/cross-chain/CrossChainDomainBridging.network.test.ts @@ -194,6 +194,7 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => await approveForDomain({ zns: znsL1, parentHash: hre.ethers.ZeroHash, + tokenHolder: deployAdmin, user, domainLabel: "test", isBridging: true, @@ -283,6 +284,7 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => zns: znsL1, parentHash: parentHash as string, user, + tokenHolder: deployAdmin, domainLabel: label, isBridging: true, }); @@ -570,6 +572,7 @@ describe("Cross-Chain Domain Bridging Test [for local and test networks]", () => const subdomainHash = await registrationWithSetup({ zns: znsL2, user: subUserL2, + tokenHolder: deployAdminL2, parentHash: domainHash, domainLabel: subdomainChildLabel, fullConfig: fullDistrConfigEmpty, diff --git a/test/helpers/register-setup.ts b/test/helpers/register-setup.ts index 0e4149eb7..1cb983093 100644 --- a/test/helpers/register-setup.ts +++ b/test/helpers/register-setup.ts @@ -11,7 +11,7 @@ import { getTokenContract } from "./tokens"; import { ICurvePriceConfig } from "../../src/deploy/missions/types"; import { expect } from "chai"; import { IZNSContracts } from "../../src/deploy/campaign/types"; -import { ZNSRootRegistrarTrunk } from "../../typechain"; +import { ZNSRootRegistrarTrunk, ZNSZChainPortal } from "../../typechain"; import { getConfirmationsNumber } from "./tx"; const { ZeroAddress } = ethers; @@ -54,12 +54,14 @@ export const approveForDomain = async ({ zns, parentHash, user, + tokenHolder, domainLabel, isBridging = false, } : { zns : IZNSContractsLocal | IZNSContracts; parentHash : string; user : SignerWithAddress; + tokenHolder ?: SignerWithAddress; domainLabel : string; isBridging ?: boolean; }) => { @@ -88,12 +90,13 @@ export const approveForDomain = async ({ const userBal = await tokenContract.balanceOf(user.address); if (userBal < toApprove) { - // eslint-disable-next-line no-shadow - const tx = await tokenContract.connect(user).mint(user.address, toApprove); + const tx = await tokenContract.connect(tokenHolder).transfer(user.address, toApprove); await tx.wait(confNum); } - const spender = isBridging ? await zns.zChainPortal.getAddress() : await zns.treasury.getAddress(); + const spender = isBridging + ? await (zns.zChainPortal as ZNSZChainPortal).getAddress() + : await zns.treasury.getAddress(); const tx = await tokenContract.connect(user).approve(spender, toApprove); await tx.wait(confNum); }; @@ -163,6 +166,7 @@ export const defaultBridgingRegistration = async ({ export const registrationWithSetup = async ({ zns, user, + tokenHolder, parentHash, domainLabel, domainContent = user.address, @@ -173,6 +177,7 @@ export const registrationWithSetup = async ({ } : { zns : IZNSContractsLocal | IZNSContracts; user : SignerWithAddress; + tokenHolder ?: SignerWithAddress; parentHash ?: string; domainLabel : string; domainContent ?: string; @@ -192,6 +197,7 @@ export const registrationWithSetup = async ({ zns, parentHash, user, + tokenHolder, domainLabel, isBridging: bridgeDomain, });