From 6a54552800532ff237b32a268ae9a0c27790dff3 Mon Sep 17 00:00:00 2001 From: James Earle Date: Mon, 27 Nov 2023 14:10:16 -0800 Subject: [PATCH 1/7] Add ability to set the payment config in the default registration flow --- contracts/registrar/IZNSRootRegistrar.sol | 4 +- contracts/registrar/ZNSRootRegistrar.sol | 18 ++-- contracts/treasury/ZNSTreasury.sol | 6 +- test/ZNSRootRegistrar.test.ts | 108 +++++++++++++++++++--- test/helpers/register-setup.ts | 6 +- 5 files changed, 120 insertions(+), 22 deletions(-) diff --git a/contracts/registrar/IZNSRootRegistrar.sol b/contracts/registrar/IZNSRootRegistrar.sol index 561fa3e2..f761c2d6 100644 --- a/contracts/registrar/IZNSRootRegistrar.sol +++ b/contracts/registrar/IZNSRootRegistrar.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.18; import { IDistributionConfig } from "../types/IDistributionConfig.sol"; +import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; /** @@ -127,7 +128,8 @@ interface IZNSRootRegistrar is IDistributionConfig { string calldata name, address domainAddress, string calldata tokenURI, - DistributionConfig calldata distributionConfig + DistributionConfig calldata distributionConfig, + PaymentConfig calldata paymentConfig ) external returns (bytes32); function coreRegister( diff --git a/contracts/registrar/ZNSRootRegistrar.sol b/contracts/registrar/ZNSRootRegistrar.sol index 64ac038e..19a01c82 100644 --- a/contracts/registrar/ZNSRootRegistrar.sol +++ b/contracts/registrar/ZNSRootRegistrar.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.18; +import { AAccessControlled } from "../access/AAccessControlled.sol"; +import { ARegistryWired } from "../registry/ARegistryWired.sol"; import { IZNSRootRegistrar, CoreRegisterArgs } from "./IZNSRootRegistrar.sol"; -import { IZNSTreasury } from "../treasury/IZNSTreasury.sol"; +import { IZNSTreasury, PaymentConfig } from "../treasury/IZNSTreasury.sol"; import { IZNSDomainToken } from "../token/IZNSDomainToken.sol"; import { IZNSAddressResolver } from "../resolver/IZNSAddressResolver.sol"; -import { AAccessControlled } from "../access/AAccessControlled.sol"; -import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { IZNSSubRegistrar } from "../registrar/IZNSSubRegistrar.sol"; -import { ARegistryWired } from "../registry/ARegistryWired.sol"; import { IZNSPricer } from "../types/IZNSPricer.sol"; +import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { StringUtils } from "../utils/StringUtils.sol"; @@ -75,7 +75,7 @@ contract ZNSRootRegistrar is * 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. + * and, possibly, `ZNSAddressResolver`. Emits a `DomainRegistered` event. * @param name 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 @@ -88,7 +88,8 @@ contract ZNSRootRegistrar is string calldata name, address domainAddress, string calldata tokenURI, - DistributionConfig calldata distributionConfig + DistributionConfig calldata distributionConfig, + PaymentConfig calldata paymentConfig ) external override returns (bytes32) { // Confirms string values are only [a-z0-9-] name.validate(); @@ -123,6 +124,11 @@ contract ZNSRootRegistrar is subRegistrar.setDistributionConfigForDomain(domainHash, distributionConfig); } + // We check for both in the web app before setting, so we just need to verify at least one exists here + if (paymentConfig.beneficiary != address(0)) { + treasury.setPaymentConfig(domainHash, paymentConfig); + } + return domainHash; } diff --git a/contracts/treasury/ZNSTreasury.sol b/contracts/treasury/ZNSTreasury.sol index d9ecead1..5645ebe1 100644 --- a/contracts/treasury/ZNSTreasury.sol +++ b/contracts/treasury/ZNSTreasury.sol @@ -234,7 +234,11 @@ contract ZNSTreasury is AAccessControlled, ARegistryWired, UUPSUpgradeable, IZNS function setPaymentConfig( bytes32 domainHash, PaymentConfig memory paymentConfig - ) external override onlyOwnerOrOperator(domainHash) { + ) external override { + require( + registry.isOwnerOrOperator(domainHash, msg.sender) || accessController.isRegistrar(msg.sender), + "ZNSTreasury: Not authorized. Only Owner or Operator allowed" + ); _setBeneficiary(domainHash, paymentConfig.beneficiary); _setPaymentToken(domainHash, address(paymentConfig.token)); } diff --git a/test/ZNSRootRegistrar.test.ts b/test/ZNSRootRegistrar.test.ts index 3967543f..7a03415e 100644 --- a/test/ZNSRootRegistrar.test.ts +++ b/test/ZNSRootRegistrar.test.ts @@ -38,7 +38,6 @@ import { IERC20, ZNSRootRegistrar__factory, ZNSRootRegistrarUpgradeMock__factory import { PaymentConfigStruct } from "../typechain/contracts/treasury/IZNSTreasury"; import { parseEther } from "ethers/lib/utils"; import { runZnsCampaign } from "../src/deploy/zns-campaign"; -import { getLogger } from "../src/deploy/logger/create-logger"; import { getProxyImplAddress } from "./helpers/utils"; import { upgrades } from "hardhat"; import { MongoDBAdapter } from "../src/deploy/db/mongo-adapter/mongo-adapter"; @@ -76,11 +75,8 @@ describe("ZNSRootRegistrar", () => { [deployer.address, admin.address], ); - const logger = getLogger(); - const campaign = await runZnsCampaign({ config, - logger, }); zns = campaign.state.contracts; @@ -102,6 +98,56 @@ describe("ZNSRootRegistrar", () => { await mongoAdapter.dropDB(); }); + it("Sets the payment config when provided with the domain registration", async () => { + const tokenURI = "https://example.com/817c64af"; + const distrConfig : IDistributionConfig = { + pricerContract: zns.curvePricer.address, + paymentType: 1, + accessType: 1, + }; + + await zns.rootRegistrar.connect(user).registerRootDomain( + defaultDomain, + zns.addressResolver.address, + tokenURI, + distrConfig, + { + token: zns.meowToken.address, + beneficiary: user.address, + } + ); + + const domainHash = hashDomainLabel(defaultDomain); + const config = await zns.treasury.paymentConfigs(domainHash); + expect(config.token).to.eq(zns.meowToken.address); + expect(config.beneficiary).to.eq(user.address); + }); + + it("Does not try to set the payment config when the beneficiary is the zero address", async () => { + const tokenURI = "https://example.com/817c64af"; + const distrConfig : IDistributionConfig = { + pricerContract: zns.curvePricer.address, + paymentType: 1, + accessType: 1, + }; + + await zns.rootRegistrar.connect(user).registerRootDomain( + defaultDomain, + zns.addressResolver.address, + tokenURI, + distrConfig, + { + token: ethers.constants.AddressZero, + beneficiary: ethers.constants.AddressZero, + } + ); + + const domainHash = hashDomainLabel(defaultDomain); + const config = await zns.treasury.paymentConfigs(domainHash); + expect(config.token).to.eq(ethers.constants.AddressZero); + expect(config.beneficiary).to.eq(ethers.constants.AddressZero); + }); + it("Gas tests", async () => { const tokenURI = "https://example.com/817c64af"; const distrConfig : IDistributionConfig = { @@ -114,7 +160,11 @@ describe("ZNSRootRegistrar", () => { defaultDomain, deployer.address, tokenURI, - distrConfig + distrConfig, + { + token: ethers.constants.AddressZero, + beneficiary: ethers.constants.AddressZero, + } ); const receipt = await tx.wait(); @@ -405,7 +455,11 @@ describe("ZNSRootRegistrar", () => { letters, ethers.constants.AddressZero, DEFAULT_TOKEN_URI, - distrConfigEmpty + distrConfigEmpty, + { + token: ethers.constants.AddressZero, + beneficiary: ethers.constants.AddressZero, + } ); await expect(tx1).to.emit(zns.rootRegistrar, "DomainRegistered").withArgs( @@ -421,7 +475,11 @@ describe("ZNSRootRegistrar", () => { alphaNumeric, ethers.constants.AddressZero, DEFAULT_TOKEN_URI, - distrConfigEmpty + distrConfigEmpty, + { + token: ethers.constants.AddressZero, + beneficiary: ethers.constants.AddressZero, + } ); await expect(tx2).to.emit(zns.rootRegistrar, "DomainRegistered").withArgs( @@ -437,7 +495,11 @@ describe("ZNSRootRegistrar", () => { withHyphen, ethers.constants.AddressZero, DEFAULT_TOKEN_URI, - distrConfigEmpty + distrConfigEmpty, + { + token: ethers.constants.AddressZero, + beneficiary: ethers.constants.AddressZero, + } ); await expect(tx3).to.emit(zns.rootRegistrar, "DomainRegistered").withArgs( @@ -497,7 +559,11 @@ describe("ZNSRootRegistrar", () => { defaultDomain, ethers.constants.AddressZero, tokenURI, - distrConfigEmpty + distrConfigEmpty, + { + token: ethers.constants.AddressZero, + beneficiary: ethers.constants.AddressZero, + } ); const hashFromTS = hashDomainLabel(defaultDomain); @@ -527,7 +593,11 @@ describe("ZNSRootRegistrar", () => { defaultDomain, ethers.constants.AddressZero, tokenURI, - distrConfig + distrConfig, + { + token: ethers.constants.AddressZero, + beneficiary: ethers.constants.AddressZero, + } ); const receipt = await tx.wait(0); @@ -638,7 +708,11 @@ describe("ZNSRootRegistrar", () => { defaultDomain, ethers.constants.AddressZero, DEFAULT_TOKEN_URI, - distrConfigEmpty + distrConfigEmpty, + { + token: ethers.constants.AddressZero, + beneficiary: ethers.constants.AddressZero, + } ); await expect(tx).to.not.be.reverted; @@ -696,7 +770,11 @@ describe("ZNSRootRegistrar", () => { defaultDomain, ethers.constants.AddressZero, DEFAULT_TOKEN_URI, - distrConfigEmpty + distrConfigEmpty, + { + token: ethers.constants.AddressZero, + beneficiary: ethers.constants.AddressZero, + } ); const userBalanceAfter = await zns.meowToken.balanceOf(user.address); @@ -1199,7 +1277,11 @@ describe("ZNSRootRegistrar", () => { domainName, randomUser.address, DEFAULT_TOKEN_URI, - distrConfigEmpty + distrConfigEmpty, + { + token: ethers.constants.AddressZero, + beneficiary: ethers.constants.AddressZero, + } ); diff --git a/test/helpers/register-setup.ts b/test/helpers/register-setup.ts index 189f06a1..21f9401f 100644 --- a/test/helpers/register-setup.ts +++ b/test/helpers/register-setup.ts @@ -33,7 +33,11 @@ export const defaultRootRegistration = async ({ domainName, domainContent, // Arbitrary address value tokenURI, - distrConfig + distrConfig, + { + token: AddressZero, + beneficiary: AddressZero, + } ); return tx.wait(); From 957ea7178152543263c70713fbe5d3d73eaa10e5 Mon Sep 17 00:00:00 2001 From: James Earle Date: Mon, 27 Nov 2023 15:45:45 -0800 Subject: [PATCH 2/7] updates to support subdomains as well, moved setting payment config to _coreRegister funcs for both --- contracts/registrar/IZNSRootRegistrar.sol | 1 + contracts/registrar/IZNSSubRegistrar.sol | 4 +- contracts/registrar/ZNSRootRegistrar.sol | 14 ++-- contracts/registrar/ZNSSubRegistrar.sol | 7 +- .../distribution/ZNSSubRegistrarMock.sol | 7 +- test/ZNSRootRegistrar.test.ts | 12 +-- test/ZNSSubRegistrar.test.ts | 83 +++++++++++++++++-- test/helpers/constants.ts | 1 - test/helpers/register-setup.ts | 10 +-- 9 files changed, 106 insertions(+), 33 deletions(-) diff --git a/contracts/registrar/IZNSRootRegistrar.sol b/contracts/registrar/IZNSRootRegistrar.sol index f761c2d6..4672f448 100644 --- a/contracts/registrar/IZNSRootRegistrar.sol +++ b/contracts/registrar/IZNSRootRegistrar.sol @@ -19,6 +19,7 @@ struct CoreRegisterArgs { string label; string tokenURI; bool isStakePayment; + PaymentConfig paymentConfig; } /** diff --git a/contracts/registrar/IZNSSubRegistrar.sol b/contracts/registrar/IZNSSubRegistrar.sol index cd0d3833..85aeac3f 100644 --- a/contracts/registrar/IZNSSubRegistrar.sol +++ b/contracts/registrar/IZNSSubRegistrar.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.18; import { IDistributionConfig } from "../types/IDistributionConfig.sol"; +import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; import { IZNSPricer } from "../types/IZNSPricer.sol"; @@ -79,7 +80,8 @@ interface IZNSSubRegistrar is IDistributionConfig { string calldata label, address domainAddress, string calldata tokenURI, - DistributionConfig calldata configForSubdomains + DistributionConfig calldata configForSubdomains, + PaymentConfig calldata paymentConfig ) external returns (bytes32); function hashWithParent( diff --git a/contracts/registrar/ZNSRootRegistrar.sol b/contracts/registrar/ZNSRootRegistrar.sol index 19a01c82..127ba574 100644 --- a/contracts/registrar/ZNSRootRegistrar.sol +++ b/contracts/registrar/ZNSRootRegistrar.sol @@ -115,7 +115,8 @@ contract ZNSRootRegistrar is 0, name, tokenURI, - true + true, + paymentConfig ) ); @@ -124,11 +125,6 @@ contract ZNSRootRegistrar is subRegistrar.setDistributionConfigForDomain(domainHash, distributionConfig); } - // We check for both in the web app before setting, so we just need to verify at least one exists here - if (paymentConfig.beneficiary != address(0)) { - treasury.setPaymentConfig(domainHash, paymentConfig); - } - return domainHash; } @@ -190,6 +186,12 @@ contract ZNSRootRegistrar is registry.createDomainRecord(args.domainHash, args.registrant, ""); } + // Because we check in the web app for the existance of both values in a payment config, + // it's fine to just check for one here + if (args.paymentConfig.beneficiary != address(0)) { + treasury.setPaymentConfig(args.domainHash, args.paymentConfig); + } + emit DomainRegistered( args.parentHash, args.domainHash, diff --git a/contracts/registrar/ZNSSubRegistrar.sol b/contracts/registrar/ZNSSubRegistrar.sol index bf0a2b90..df137614 100644 --- a/contracts/registrar/ZNSSubRegistrar.sol +++ b/contracts/registrar/ZNSSubRegistrar.sol @@ -7,6 +7,7 @@ import { IZNSSubRegistrar } from "./IZNSSubRegistrar.sol"; import { AAccessControlled } from "../access/AAccessControlled.sol"; import { ARegistryWired } from "../registry/ARegistryWired.sol"; import { StringUtils } from "../utils/StringUtils.sol"; +import { PaymentConfig } from "../treasury/IZNSTreasury.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; @@ -84,7 +85,8 @@ contract ZNSSubRegistrar is AAccessControlled, ARegistryWired, UUPSUpgradeable, string calldata label, address domainAddress, string calldata tokenURI, - DistributionConfig calldata distrConfig + DistributionConfig calldata distrConfig, + PaymentConfig calldata paymentConfig ) external override returns (bytes32) { // Confirms string values are only [a-z0-9-] label.validate(); @@ -122,7 +124,8 @@ contract ZNSSubRegistrar is AAccessControlled, ARegistryWired, UUPSUpgradeable, stakeFee: 0, domainAddress: domainAddress, tokenURI: tokenURI, - isStakePayment: parentConfig.paymentType == PaymentType.STAKE + isStakePayment: parentConfig.paymentType == PaymentType.STAKE, + paymentConfig: paymentConfig }); if (!isOwnerOrOperator) { diff --git a/contracts/upgrade-test-mocks/distribution/ZNSSubRegistrarMock.sol b/contracts/upgrade-test-mocks/distribution/ZNSSubRegistrarMock.sol index 53532b47..95269a9f 100644 --- a/contracts/upgrade-test-mocks/distribution/ZNSSubRegistrarMock.sol +++ b/contracts/upgrade-test-mocks/distribution/ZNSSubRegistrarMock.sol @@ -11,6 +11,7 @@ import { AAccessControlled } from "../../access/AAccessControlled.sol"; import { ARegistryWired } from "../../registry/ARegistryWired.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { StringUtils } from "../../utils/StringUtils.sol"; +import { PaymentConfig } from "../../treasury/IZNSTreasury.sol"; enum AccessType { @@ -75,7 +76,8 @@ contract ZNSSubRegistrarUpgradeMock is string calldata label, address domainAddress, string memory tokenURI, - DistributionConfig calldata distrConfig + DistributionConfig calldata distrConfig, + PaymentConfig calldata paymentConfig ) external returns (bytes32) { label.validate(); @@ -103,7 +105,8 @@ contract ZNSSubRegistrarUpgradeMock is stakeFee: 0, domainAddress: domainAddress, tokenURI: tokenURI, - isStakePayment: parentConfig.paymentType == PaymentType.STAKE + isStakePayment: parentConfig.paymentType == PaymentType.STAKE, + paymentConfig: paymentConfig }); require( diff --git a/test/ZNSRootRegistrar.test.ts b/test/ZNSRootRegistrar.test.ts index 7a03415e..cbe20376 100644 --- a/test/ZNSRootRegistrar.test.ts +++ b/test/ZNSRootRegistrar.test.ts @@ -24,6 +24,7 @@ import { ONLY_NAME_OWNER_REG_ERR, ONLY_OWNER_REGISTRAR_REG_ERR, INVALID_NAME_ERR, + paymentConfigEmpty, } from "./helpers"; import { IDistributionConfig } from "./helpers/types"; import * as ethers from "ethers"; @@ -123,7 +124,7 @@ describe("ZNSRootRegistrar", () => { expect(config.beneficiary).to.eq(user.address); }); - it("Does not try to set the payment config when the beneficiary is the zero address", async () => { + it("Does not set the payment config when the beneficiary is the zero address", async () => { const tokenURI = "https://example.com/817c64af"; const distrConfig : IDistributionConfig = { pricerContract: zns.curvePricer.address, @@ -136,10 +137,7 @@ describe("ZNSRootRegistrar", () => { zns.addressResolver.address, tokenURI, distrConfig, - { - token: ethers.constants.AddressZero, - beneficiary: ethers.constants.AddressZero, - } + paymentConfigEmpty ); const domainHash = hashDomainLabel(defaultDomain); @@ -177,7 +175,8 @@ describe("ZNSRootRegistrar", () => { "subdomain", deployer.address, tokenURI, - distrConfigEmpty + distrConfigEmpty, + paymentConfigEmpty, ); const candidates = [ @@ -336,6 +335,7 @@ describe("ZNSRootRegistrar", () => { domainAddress: ethers.constants.AddressZero, tokenURI: "", isStakePayment: false, + paymentConfig: paymentConfigEmpty, }) ).to.be.revertedWith( getAccessRevertMsg(randomUser.address, REGISTRAR_ROLE) diff --git a/test/ZNSSubRegistrar.test.ts b/test/ZNSSubRegistrar.test.ts index 46e37b73..e1a1bc35 100644 --- a/test/ZNSSubRegistrar.test.ts +++ b/test/ZNSSubRegistrar.test.ts @@ -112,6 +112,48 @@ describe("ZNSSubRegistrar", () => { }); }); + it("Sets the payment config when given", async () => { + const subdomain = "world-subdomain"; + + await zns.meowToken.connect(lvl2SubOwner).approve(zns.treasury.address, ethers.constants.MaxUint256); + + await zns.subRegistrar.connect(lvl2SubOwner).registerSubdomain( + rootHash, + subdomain, + lvl2SubOwner.address, + subTokenURI, + distrConfigEmpty, + { + token: zns.meowToken.address, + beneficiary: lvl2SubOwner.address, + }, + ); + + const subHash = await zns.subRegistrar.hashWithParent(rootHash, subdomain); + const config = await zns.treasury.paymentConfigs(subHash); + expect(config.token).to.eq(zns.meowToken.address); + expect(config.beneficiary).to.eq(lvl2SubOwner.address); + }); + + it("Does not set the payment config when the beneficiary is the zero address", async () => { + const subdomain = "not-world-subdomain"; + await expect( + zns.subRegistrar.connect(lvl2SubOwner).registerSubdomain( + rootHash, + subdomain, + lvl2SubOwner.address, + subTokenURI, + distrConfigEmpty, + paymentConfigEmpty + ) + ); + + const subHash = await zns.subRegistrar.hashWithParent(rootHash, subdomain); + const config = await zns.treasury.paymentConfigs(subHash); + expect(config.token).to.eq(ethers.constants.AddressZero); + expect(config.beneficiary).to.eq(ethers.constants.AddressZero); + }); + // eslint-disable-next-line max-len it("should revert when trying to register a subdomain before parent has set it's config with FixedPricer", async () => { // register a new root domain @@ -144,6 +186,10 @@ describe("ZNSSubRegistrar", () => { lvl2SubOwner.address, subTokenURI, distrConfigEmpty, + { + token: zns.meowToken.address, + beneficiary: rootOwner.address, + }, ) ).to.be.revertedWith( "ZNSFixedPricer: parent's price config has not been set properly through IZNSPricer.setPriceConfig()" @@ -179,6 +225,7 @@ describe("ZNSSubRegistrar", () => { lvl2SubOwner.address, subTokenURI, distrConfigEmpty, + paymentConfigEmpty, ) ).to.be.revertedWith( "ZNSCurvePricer: parent's price config has not been set properly through IZNSPricer.setPriceConfig()" @@ -300,6 +347,7 @@ describe("ZNSSubRegistrar", () => { lvl2SubOwner.address, subTokenURI, distrConfigEmpty, + paymentConfigEmpty, ) ).to.be.revertedWith( DISTRIBUTION_LOCKED_NOT_EXIST_ERR @@ -314,6 +362,7 @@ describe("ZNSSubRegistrar", () => { lvl2SubOwner.address, subTokenURI, distrConfigEmpty, + paymentConfigEmpty, ) ).to.be.revertedWith( DISTRIBUTION_LOCKED_NOT_EXIST_ERR @@ -392,6 +441,7 @@ describe("ZNSSubRegistrar", () => { lvl2SubOwner.address, subTokenURI, distrConfigEmpty, + paymentConfigEmpty, ) ).to.be.revertedWith( "ERC20: transfer amount exceeds balance" @@ -415,6 +465,7 @@ describe("ZNSSubRegistrar", () => { lvl2SubOwner.address, subTokenURI, distrConfigEmpty, + paymentConfigEmpty, ) ).to.be.revertedWith( "ERC20: insufficient allowance" @@ -885,6 +936,7 @@ describe("ZNSSubRegistrar", () => { lvl6SubOwner.address, DEFAULT_TOKEN_URI, distrConfigEmpty, + paymentConfigEmpty, ) ).to.be.revertedWith( DISTRIBUTION_LOCKED_NOT_EXIST_ERR @@ -949,6 +1001,7 @@ describe("ZNSSubRegistrar", () => { lvl6SubOwner.address, DEFAULT_TOKEN_URI, distrConfigEmpty, + paymentConfigEmpty, ) ).to.be.revertedWith( DISTRIBUTION_LOCKED_NOT_EXIST_ERR @@ -1176,6 +1229,7 @@ describe("ZNSSubRegistrar", () => { branchLvl1Owner.address, DEFAULT_TOKEN_URI, distrConfigEmpty, + paymentConfigEmpty, ) ).to.be.revertedWith(DISTRIBUTION_LOCKED_NOT_EXIST_ERR); @@ -1207,6 +1261,7 @@ describe("ZNSSubRegistrar", () => { branchLvl2Owner.address, DEFAULT_TOKEN_URI, distrConfigEmpty, + paymentConfigEmpty, ) ).to.be.revertedWith(DISTRIBUTION_LOCKED_NOT_EXIST_ERR); }); @@ -2290,6 +2345,7 @@ describe("ZNSSubRegistrar", () => { lvl3SubOwner.address, DEFAULT_TOKEN_URI, distrConfigEmpty, + paymentConfigEmpty, ) ).to.be.revertedWith("ERC20: insufficient allowance"); @@ -2469,7 +2525,8 @@ describe("ZNSSubRegistrar", () => { "tobedenied", ethers.constants.AddressZero, DEFAULT_TOKEN_URI, - distrConfigEmpty + distrConfigEmpty, + paymentConfigEmpty, ) ).to.be.revertedWith( DISTRIBUTION_LOCKED_NOT_EXIST_ERR @@ -2499,7 +2556,8 @@ describe("ZNSSubRegistrar", () => { domainLabel, ethers.constants.AddressZero, DEFAULT_TOKEN_URI, - distrConfigEmpty + distrConfigEmpty, + paymentConfigEmpty, ); const hash = await getDomainHashFromEvent({ @@ -2574,7 +2632,8 @@ describe("ZNSSubRegistrar", () => { "notmintlisted", ethers.constants.AddressZero, DEFAULT_TOKEN_URI, - distrConfigEmpty + distrConfigEmpty, + paymentConfigEmpty, ) ).to.be.revertedWith( "ZNSSubRegistrar: Sender is not approved for purchase" @@ -2594,7 +2653,8 @@ describe("ZNSSubRegistrar", () => { "notmintlistednow", ethers.constants.AddressZero, DEFAULT_TOKEN_URI, - distrConfigEmpty + distrConfigEmpty, + paymentConfigEmpty, ) ).to.be.revertedWith( "ZNSSubRegistrar: Sender is not approved for purchase" @@ -2686,7 +2746,8 @@ describe("ZNSSubRegistrar", () => { "notallowed", ethers.constants.AddressZero, DEFAULT_TOKEN_URI, - distrConfigEmpty + distrConfigEmpty, + paymentConfigEmpty, ) ).to.be.revertedWith( DISTRIBUTION_LOCKED_NOT_EXIST_ERR @@ -2731,7 +2792,8 @@ describe("ZNSSubRegistrar", () => { "alloweddddd", ethers.constants.AddressZero, DEFAULT_TOKEN_URI, - distrConfigEmpty + distrConfigEmpty, + paymentConfigEmpty, ); const hash = await getDomainHashFromEvent({ @@ -2766,7 +2828,8 @@ describe("ZNSSubRegistrar", () => { "notallowed", ethers.constants.AddressZero, DEFAULT_TOKEN_URI, - distrConfigEmpty + distrConfigEmpty, + paymentConfigEmpty, ) ).to.be.revertedWith( DISTRIBUTION_LOCKED_NOT_EXIST_ERR @@ -2886,7 +2949,8 @@ describe("ZNSSubRegistrar", () => { domainConfigs[1].domainLabel, lvl2SubOwner.address, DEFAULT_TOKEN_URI, - domainConfigs[1].fullConfig.distrConfig + domainConfigs[1].fullConfig.distrConfig, + paymentConfigEmpty, ) ).to.be.revertedWith( "ZNSSubRegistrar: Subdomain already exists" @@ -3482,7 +3546,8 @@ describe("ZNSSubRegistrar", () => { "subbb", lvl2SubOwner.address, DEFAULT_TOKEN_URI, - subConfigToSet + subConfigToSet, + paymentConfigEmpty, ); const subHash = await getDomainHashFromEvent({ diff --git a/test/helpers/constants.ts b/test/helpers/constants.ts index f1144500..35dffb96 100644 --- a/test/helpers/constants.ts +++ b/test/helpers/constants.ts @@ -59,7 +59,6 @@ export const curvePriceConfigEmpty : ICurvePriceConfig = { export const paymentConfigEmpty = { token: ethers.constants.AddressZero, beneficiary: ethers.constants.AddressZero, - paymentType: PaymentType.DIRECT, }; export const distrConfigEmpty = { diff --git a/test/helpers/register-setup.ts b/test/helpers/register-setup.ts index 21f9401f..97f54c37 100644 --- a/test/helpers/register-setup.ts +++ b/test/helpers/register-setup.ts @@ -8,7 +8,7 @@ import { } from "./types"; import { BigNumber, ContractReceipt, ethers } from "ethers"; import { getDomainHashFromEvent } from "./events"; -import { distrConfigEmpty, fullDistrConfigEmpty, DEFAULT_TOKEN_URI } from "./constants"; +import { distrConfigEmpty, fullDistrConfigEmpty, DEFAULT_TOKEN_URI, paymentConfigEmpty} from "./constants"; import { getTokenContract } from "./tokens"; const { AddressZero } = ethers.constants; @@ -34,10 +34,7 @@ export const defaultRootRegistration = async ({ domainContent, // Arbitrary address value tokenURI, distrConfig, - { - token: AddressZero, - beneficiary: AddressZero, - } + paymentConfigEmpty ); return tx.wait(); @@ -100,7 +97,8 @@ export const defaultSubdomainRegistration = async ({ subdomainLabel, domainContent, // Arbitrary address value tokenURI, - distrConfig + distrConfig, + paymentConfigEmpty ); return tx.wait(); From d7560cb3cb1bd3bde0c05e07cd75bcea1d751d4b Mon Sep 17 00:00:00 2001 From: James Earle Date: Mon, 27 Nov 2023 15:49:55 -0800 Subject: [PATCH 3/7] fix lint --- test/ZNSSubRegistrar.test.ts | 2 +- test/helpers/register-setup.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ZNSSubRegistrar.test.ts b/test/ZNSSubRegistrar.test.ts index e1a1bc35..3e64f5cd 100644 --- a/test/ZNSSubRegistrar.test.ts +++ b/test/ZNSSubRegistrar.test.ts @@ -116,7 +116,7 @@ describe("ZNSSubRegistrar", () => { const subdomain = "world-subdomain"; await zns.meowToken.connect(lvl2SubOwner).approve(zns.treasury.address, ethers.constants.MaxUint256); - + await zns.subRegistrar.connect(lvl2SubOwner).registerSubdomain( rootHash, subdomain, diff --git a/test/helpers/register-setup.ts b/test/helpers/register-setup.ts index 97f54c37..bff7a099 100644 --- a/test/helpers/register-setup.ts +++ b/test/helpers/register-setup.ts @@ -8,7 +8,7 @@ import { } from "./types"; import { BigNumber, ContractReceipt, ethers } from "ethers"; import { getDomainHashFromEvent } from "./events"; -import { distrConfigEmpty, fullDistrConfigEmpty, DEFAULT_TOKEN_URI, paymentConfigEmpty} from "./constants"; +import { distrConfigEmpty, fullDistrConfigEmpty, DEFAULT_TOKEN_URI, paymentConfigEmpty } from "./constants"; import { getTokenContract } from "./tokens"; const { AddressZero } = ethers.constants; From c3bd9def16916970379f979659a106efdc21e3b5 Mon Sep 17 00:00:00 2001 From: James Earle Date: Tue, 28 Nov 2023 13:15:13 -0800 Subject: [PATCH 4/7] fix treasury tests for upgraded param that now sets payment config in register --- test/ZNSTreasury.test.ts | 18 ++++++++++++------ test/helpers/errors.ts | 1 + 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/test/ZNSTreasury.test.ts b/test/ZNSTreasury.test.ts index 6e285e64..673953a3 100644 --- a/test/ZNSTreasury.test.ts +++ b/test/ZNSTreasury.test.ts @@ -16,7 +16,7 @@ import { DeployZNSParams, IZNSContracts } from "./helpers/types"; import * as ethers from "ethers"; import { hashDomainLabel, hashSubdomainName } from "./helpers/hashing"; import { ADMIN_ROLE, REGISTRAR_ROLE, GOVERNOR_ROLE } from "../src/deploy/constants"; -import { getAccessRevertMsg } from "./helpers/errors"; +import { NOT_AUTHORIZED_TREASURY_ERR, getAccessRevertMsg } from "./helpers/errors"; import { ZNSTreasury__factory, ZNSTreasuryUpgradeMock__factory } from "../typechain"; import { parseEther } from "ethers/lib/utils"; import { getProxyImplAddress } from "./helpers/utils"; @@ -57,6 +57,11 @@ describe("ZNSTreasury", () => { zns = await deployZNS(params); + const paymentConfig = { + token: zns.meowToken.address, + beneficiary: user.address, + }; + // give REGISTRAR_ROLE to a wallet address to be calling guarded functions await zns.accessController.connect(admin).grantRole(REGISTRAR_ROLE, mockRegistrar.address); @@ -69,7 +74,8 @@ describe("ZNSTreasury", () => { domainName, user.address, DEFAULT_TOKEN_URI, - distrConfigEmpty + distrConfigEmpty, + paymentConfig, ); }); @@ -373,13 +379,13 @@ describe("ZNSTreasury", () => { }); describe("#setPaymentConfig(), BeneficiarySet and PaymentTokenSet", () => { - it("should re-set payment config for an existing subdomain", async () => { + it("should set payment config for an existing subdomain", async () => { const { token: paymentTokenBefore, beneficiary: beneficiaryBefore, } = await zns.treasury.paymentConfigs(domainHash); - expect(paymentTokenBefore).to.eq(ethers.constants.AddressZero); - expect(beneficiaryBefore).to.eq(ethers.constants.AddressZero); + expect(paymentTokenBefore).to.eq(zns.meowToken.address); + expect(beneficiaryBefore).to.eq(user.address); const configToSet = { token: randomAcc.address, @@ -420,7 +426,7 @@ describe("ZNSTreasury", () => { configToSet, ) ).to.be.revertedWith( - NOT_AUTHORIZED_REG_WIRED_ERR + NOT_AUTHORIZED_TREASURY_ERR ); }); diff --git a/test/helpers/errors.ts b/test/helpers/errors.ts index 070dd189..7b7c1272 100644 --- a/test/helpers/errors.ts +++ b/test/helpers/errors.ts @@ -34,6 +34,7 @@ export const INVALID_LENGTH_ERR = "StringUtils: Domain label too long or nonexis // Treasury export const NO_BENEFICIARY_ERR = "ZNSTreasury: parent domain has no beneficiary set"; +export const NOT_AUTHORIZED_TREASURY_ERR = "ZNSTreasury: Not authorized. Only Owner or Operator allowed"; // OpenZeppelin export const INVALID_TOKENID_ERC_ERR = "ERC721: invalid token ID"; From a351a8965f4be54c25ec6d25817f03134e51526f Mon Sep 17 00:00:00 2001 From: James Earle Date: Tue, 28 Nov 2023 17:11:49 -0800 Subject: [PATCH 5/7] fix arguments for register functions --- test/gas/TransactionGasCosts.test.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/test/gas/TransactionGasCosts.test.ts b/test/gas/TransactionGasCosts.test.ts index 186dcc70..2c17befc 100644 --- a/test/gas/TransactionGasCosts.test.ts +++ b/test/gas/TransactionGasCosts.test.ts @@ -111,11 +111,17 @@ describe("Transaction Gas Costs Test", () => { // approve await zns.meowToken.connect(rootOwner).approve(zns.treasury.address, ethers.constants.MaxUint256); // register root domain + const paymentConfig = { + token: zns.meowToken.address, + beneficiary: rootOwner.address, + } + const tx = await zns.rootRegistrar.connect(rootOwner).registerRootDomain( "root", rootOwner.address, DEFAULT_TOKEN_URI, - config + config, + paymentConfig ); const { gasUsed } = await tx.wait(); @@ -154,12 +160,18 @@ describe("Transaction Gas Costs Test", () => { // approve await zns.meowToken.connect(lvl2SubOwner).approve(zns.treasury.address, ethers.constants.MaxUint256); // register subdomain + const paymentConfig = { + token: zns.meowToken.address, + beneficiary: rootOwner.address, + } + const tx = await zns.subRegistrar.connect(lvl2SubOwner).registerSubdomain( rootHashDirect, "subdomain", lvl2SubOwner.address, DEFAULT_TOKEN_URI, config, + paymentConfig ); const { gasUsed } = await tx.wait(); From b9ee3d4b5f6b50d5c174bf5e2b1177578ad98b96 Mon Sep 17 00:00:00 2001 From: James Earle Date: Tue, 28 Nov 2023 17:18:35 -0800 Subject: [PATCH 6/7] fix lint --- test/gas/TransactionGasCosts.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/gas/TransactionGasCosts.test.ts b/test/gas/TransactionGasCosts.test.ts index 2c17befc..306387d3 100644 --- a/test/gas/TransactionGasCosts.test.ts +++ b/test/gas/TransactionGasCosts.test.ts @@ -114,7 +114,7 @@ describe("Transaction Gas Costs Test", () => { const paymentConfig = { token: zns.meowToken.address, beneficiary: rootOwner.address, - } + }; const tx = await zns.rootRegistrar.connect(rootOwner).registerRootDomain( "root", @@ -163,7 +163,7 @@ describe("Transaction Gas Costs Test", () => { const paymentConfig = { token: zns.meowToken.address, beneficiary: rootOwner.address, - } + }; const tx = await zns.subRegistrar.connect(lvl2SubOwner).registerSubdomain( rootHashDirect, From 2c4d39b5af45d68b5717d158356a26bd4dc1ed01 Mon Sep 17 00:00:00 2001 From: James Earle Date: Thu, 30 Nov 2023 16:15:53 -0800 Subject: [PATCH 7/7] fixe to use enum types for dist configs --- contracts/treasury/ZNSTreasury.sol | 2 +- src/tenderly/devnet/run-all-flows.ts | 5 +++-- test/ZNSCurvePricer.test.ts | 3 ++- test/ZNSFixedPricer.test.ts | 5 +++-- test/ZNSRootRegistrar.test.ts | 13 +++++++------ test/gas/gas-costs.json | 4 ++-- test/helpers/constants.ts | 4 ++-- test/helpers/errors.ts | 2 +- 8 files changed, 21 insertions(+), 17 deletions(-) diff --git a/contracts/treasury/ZNSTreasury.sol b/contracts/treasury/ZNSTreasury.sol index 5645ebe1..46350608 100644 --- a/contracts/treasury/ZNSTreasury.sol +++ b/contracts/treasury/ZNSTreasury.sol @@ -237,7 +237,7 @@ contract ZNSTreasury is AAccessControlled, ARegistryWired, UUPSUpgradeable, IZNS ) external override { require( registry.isOwnerOrOperator(domainHash, msg.sender) || accessController.isRegistrar(msg.sender), - "ZNSTreasury: Not authorized. Only Owner or Operator allowed" + "ZNSTreasury: Not authorized." ); _setBeneficiary(domainHash, paymentConfig.beneficiary); _setPaymentToken(domainHash, address(paymentConfig.token)); diff --git a/src/tenderly/devnet/run-all-flows.ts b/src/tenderly/devnet/run-all-flows.ts index a1185d59..cdbfebfe 100644 --- a/src/tenderly/devnet/run-all-flows.ts +++ b/src/tenderly/devnet/run-all-flows.ts @@ -5,6 +5,7 @@ import { deployZNS, hashDomainLabel, PaymentType, DEFAULT_PRICE_CONFIG, + AccessType, } from "../../../test/helpers"; import { registrationWithSetup } from "../../../test/helpers/register-setup"; @@ -34,7 +35,7 @@ export const runAllFlows = async () => { distrConfig: { pricerContract: zns.fixedPricer.address, paymentType: PaymentType.STAKE, - accessType: 1, + accessType: AccessType.OPEN, }, paymentConfig: { token: zns.meowToken.address, @@ -61,7 +62,7 @@ export const runAllFlows = async () => { distrConfig: { pricerContract: zns.curvePricer.address, paymentType: PaymentType.DIRECT, - accessType: 1, + accessType: AccessType.OPEN, }, paymentConfig: { token: zns.meowToken.address, diff --git a/test/ZNSCurvePricer.test.ts b/test/ZNSCurvePricer.test.ts index 477f3149..2b73be8d 100644 --- a/test/ZNSCurvePricer.test.ts +++ b/test/ZNSCurvePricer.test.ts @@ -17,6 +17,7 @@ import { INVALID_NAME_ERR, } from "./helpers"; import { + AccessType, DEFAULT_DECIMALS, DEFAULT_PRICE_CONFIG, DEFAULT_REGISTRATION_FEE_PERCENT, @@ -64,7 +65,7 @@ describe("ZNSCurvePricer", () => { distrConfig: { paymentType: PaymentType.DIRECT, pricerContract: zns.curvePricer.address, - accessType: 1, + accessType: AccessType.OPEN, }, paymentConfig: { token: zns.meowToken.address, diff --git a/test/ZNSFixedPricer.test.ts b/test/ZNSFixedPricer.test.ts index 6aa9d83c..b8190924 100644 --- a/test/ZNSFixedPricer.test.ts +++ b/test/ZNSFixedPricer.test.ts @@ -10,6 +10,7 @@ import { DEFAULT_PERCENTAGE_BASIS, DEFAULT_PRICE_CONFIG, validateUpgrade, + AccessType, } from "./helpers"; import * as hre from "hardhat"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; @@ -54,7 +55,7 @@ describe("ZNSFixedPricer", () => { distrConfig: { paymentType: PaymentType.DIRECT, pricerContract: zns.fixedPricer.address, - accessType: 1, + accessType: AccessType.OPEN, }, paymentConfig: { token: zns.meowToken.address, @@ -311,7 +312,7 @@ describe("ZNSFixedPricer", () => { distrConfig: { paymentType: PaymentType.DIRECT, pricerContract: zns.fixedPricer.address, - accessType: 1, + accessType: AccessType.OPEN, }, paymentConfig: { token: zns.meowToken.address, diff --git a/test/ZNSRootRegistrar.test.ts b/test/ZNSRootRegistrar.test.ts index cbe20376..9f4d46cd 100644 --- a/test/ZNSRootRegistrar.test.ts +++ b/test/ZNSRootRegistrar.test.ts @@ -43,6 +43,7 @@ import { getProxyImplAddress } from "./helpers/utils"; import { upgrades } from "hardhat"; import { MongoDBAdapter } from "../src/deploy/db/mongo-adapter/mongo-adapter"; import { getConfig } from "../src/deploy/campaign/environments"; +import { access } from "fs"; require("@nomicfoundation/hardhat-chai-matchers"); @@ -103,8 +104,8 @@ describe("ZNSRootRegistrar", () => { const tokenURI = "https://example.com/817c64af"; const distrConfig : IDistributionConfig = { pricerContract: zns.curvePricer.address, - paymentType: 1, - accessType: 1, + paymentType: PaymentType.STAKE, + accessType: AccessType.OPEN, }; await zns.rootRegistrar.connect(user).registerRootDomain( @@ -128,8 +129,8 @@ describe("ZNSRootRegistrar", () => { const tokenURI = "https://example.com/817c64af"; const distrConfig : IDistributionConfig = { pricerContract: zns.curvePricer.address, - paymentType: 1, - accessType: 1, + paymentType: PaymentType.STAKE, + accessType: AccessType.OPEN, }; await zns.rootRegistrar.connect(user).registerRootDomain( @@ -150,8 +151,8 @@ describe("ZNSRootRegistrar", () => { const tokenURI = "https://example.com/817c64af"; const distrConfig : IDistributionConfig = { pricerContract: zns.curvePricer.address, - paymentType: 1, - accessType: 1, + paymentType: PaymentType.STAKE, + accessType: AccessType.OPEN, }; const tx = await zns.rootRegistrar.connect(deployer).registerRootDomain( diff --git a/test/gas/gas-costs.json b/test/gas/gas-costs.json index bf6973b2..216ec18a 100644 --- a/test/gas/gas-costs.json +++ b/test/gas/gas-costs.json @@ -1,4 +1,4 @@ { - "Root Domain Price": "412399", - "Subdomain Price": "405780" + "Root Domain Price": "413444", + "Subdomain Price": "406832" } \ No newline at end of file diff --git a/test/helpers/constants.ts b/test/helpers/constants.ts index 35dffb96..43cbe886 100644 --- a/test/helpers/constants.ts +++ b/test/helpers/constants.ts @@ -63,8 +63,8 @@ export const paymentConfigEmpty = { export const distrConfigEmpty = { pricerContract: ethers.constants.AddressZero, - paymentType: 0, - accessType: 0, + paymentType: PaymentType.DIRECT, + accessType: AccessType.LOCKED, }; export const fullDistrConfigEmpty = { diff --git a/test/helpers/errors.ts b/test/helpers/errors.ts index 7b7c1272..5cc45677 100644 --- a/test/helpers/errors.ts +++ b/test/helpers/errors.ts @@ -34,7 +34,7 @@ export const INVALID_LENGTH_ERR = "StringUtils: Domain label too long or nonexis // Treasury export const NO_BENEFICIARY_ERR = "ZNSTreasury: parent domain has no beneficiary set"; -export const NOT_AUTHORIZED_TREASURY_ERR = "ZNSTreasury: Not authorized. Only Owner or Operator allowed"; +export const NOT_AUTHORIZED_TREASURY_ERR = "ZNSTreasury: Not authorized."; // OpenZeppelin export const INVALID_TOKENID_ERC_ERR = "ERC721: invalid token ID";