Skip to content

Commit

Permalink
fix: Single integration test for deploy campaign (#77)
Browse files Browse the repository at this point in the history
  • Loading branch information
Whytecrowe authored Nov 28, 2023
2 parents 41aeef0 + e5a1b95 commit 6a8c490
Show file tree
Hide file tree
Showing 7 changed files with 470 additions and 29 deletions.
7 changes: 6 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,9 @@ STAKING_TOKEN_ADDRESS=

# base64 encoded value of a comma separated list of address e.g. "0x123,0x456" === "MHgxMjMsMHg0NTY="
GOVERNOR_ADDRESSES=
ADMIN_ADDRESSES=
ADMIN_ADDRESSES=

# The deploy campaign will automatically verify and monitor contracts on testnets or mainnet, but not hardhat
# to turn off this flow for testing, set these values to "false" and "true" otherwise
MONITOR_CONTRACTS="false"
VERIFY_CONTRACTS="false"
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"@nomicfoundation/hardhat-network-helpers": "^1.0.8",
"@nomicfoundation/hardhat-toolbox": "2.0.2",
"@nomiclabs/hardhat-ethers": "2.2.2",
"@nomiclabs/hardhat-etherscan": "3.0.0",
"@nomiclabs/hardhat-etherscan": "3.1.7",
"@openzeppelin/contracts": "4.8.3",
"@openzeppelin/contracts-400": "npm:@openzeppelin/[email protected]",
"@openzeppelin/contracts-upgradeable": "4.8.3",
Expand Down
313 changes: 313 additions & 0 deletions test/DeployCampaign.integration.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,313 @@
import * as hre from "hardhat";
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
import { getConfig } from "../src/deploy/campaign/environments";
import { getLogger } from "../src/deploy/logger/create-logger";
import { runZnsCampaign } from "../src/deploy/zns-campaign";
import { IDeployCampaignConfig, TZNSContractState } from "../src/deploy/campaign/types";
import { ethers } from "ethers";
import { IDistributionConfig } from "./helpers/types";
import { expect } from "chai";
import { hashDomainLabel, PaymentType, AccessType } from "./helpers";
import {
approveBulk,
getPriceBulk,
mintBulk,
registerRootDomainBulk,
registerSubdomainBulk,
} from "./helpers/deploy-helpers";

describe("DeployCampaign - Integration", () => {
let deployer : SignerWithAddress;
let zeroVault : SignerWithAddress;
let domainAddressMock : SignerWithAddress;

// Minters
let userA : SignerWithAddress;
let userB : SignerWithAddress;
let userC : SignerWithAddress;
let userD : SignerWithAddress;
let userE : SignerWithAddress;
let userF : SignerWithAddress;

let zns : TZNSContractState;

let config : IDeployCampaignConfig;

let users : Array<SignerWithAddress>;
let distConfig : IDistributionConfig;

const logger = getLogger();

// Default baselength is 4, maxLength is 50
const shortDomain = "wild"; // Length 4
const mediumDomain = "wilder"; // Length 6
const longDomain = "wilderwilderwilderwilderwilderwilderwilderwilderwil"; // Length 51
const shortHash = hashDomainLabel(shortDomain);
const mediumHash = hashDomainLabel(mediumDomain);
const longHash = hashDomainLabel(longDomain);

const freeShortSubdomain = "subd"; // Length 4
const freeMediumSubdomain = "subder"; // Length 6
const freeLongSubdomain = "subderwilderwilderwilderwilderwilderwilderwilderwil"; // Length 51

// Resolve through async call `hashWithParent` in `before` hook
let freeShortSubHash : string;
let freeMediumSubHash : string;
let freeLongSubHash : string;

const paidShortSubdomain = "surf"; // Length 4
const paidMediumSubdomain = "surfer"; // Length 6
const paidLongSubdomain = "surferwilderwilderwilderwilderwilderwilderwilderwil"; // Length 51

let paidShortSubHash : string;
let paidMediumSubHash : string;
let paidLongSubHash : string;

const mintAmount = ethers.utils.parseEther("10000000");

const domains = [shortDomain, mediumDomain, longDomain];

before(async () => {
[deployer, zeroVault, domainAddressMock, userA, userB, userC, userD, userE, userF] = await hre.ethers.getSigners();

// Reads `ENV_LEVEL` environment variable to determine rules to be enforced
config = getConfig(deployer, zeroVault);

config.mockMeowToken = hre.network.name === "hardhat";
const campaign = await runZnsCampaign({ config, dbVersion: "1.0.0" });

zns = campaign.state.contracts;

// CurvePricer, stake, open
distConfig = {
pricerContract: zns.curvePricer.address,
paymentType: PaymentType.STAKE,
accessType: AccessType.OPEN,
};

users = [
userA,
userB,
userC,
userD,
userE,
userF,
];

freeShortSubHash = await zns.subRegistrar.hashWithParent(shortHash, freeShortSubdomain);
freeMediumSubHash = await zns.subRegistrar.hashWithParent(mediumHash, freeMediumSubdomain);
freeLongSubHash = await zns.subRegistrar.hashWithParent(longHash, freeLongSubdomain);

paidShortSubHash = await zns.subRegistrar.hashWithParent(shortHash, paidShortSubdomain);
paidMediumSubHash = await zns.subRegistrar.hashWithParent(mediumHash, paidMediumSubdomain);
paidLongSubHash = await zns.subRegistrar.hashWithParent(longHash, paidLongSubdomain);

await approveBulk(users, zns);

// Give the user funds
if (config.mockMeowToken) {
await mintBulk(
users,
mintAmount,
zns
);
}
});

it("Successfully mints TLDs with varying length", async () => {
// Confirm the domains are available
expect(await zns.registry.exists(shortHash)).to.be.false;
expect(await zns.registry.exists(mediumHash)).to.be.false;
expect(await zns.registry.exists(longHash)).to.be.false;

// Get domain prices, including stake and protocol fee
const [priceShort, priceMedium, priceLong] = await getPriceBulk(domains, zns);

logger.info(`Price of ${shortDomain} is ${priceShort.toString()}`);
logger.info(`Price of ${mediumDomain} is ${priceMedium.toString()}`);
logger.info(`Price of ${longDomain} is ${priceLong.toString()}`);

const balanceBeforePromises = [
zns.meowToken.balanceOf(userA.address),
zns.meowToken.balanceOf(userB.address),
zns.meowToken.balanceOf(userC.address),
];

const [balanceBeforeA, balanceBeforeB, balanceBeforeC ]= await Promise.all(balanceBeforePromises);

// 1. Register root domains
// Note that this calls `setPriceConfig` internally for each TLD minted so we can also mint subdomains
await registerRootDomainBulk(
users,
domains,
domainAddressMock.address,
"https://zns.domains/", // tokenUri
distConfig,
config.rootPriceConfig,
zns
);

const balanceAfterPromises = [
zns.meowToken.balanceOf(userA.address),
zns.meowToken.balanceOf(userB.address),
zns.meowToken.balanceOf(userC.address),
];

const [balanceAfterA, balanceAfterB, balanceAfterC ]= await Promise.all(balanceAfterPromises);

expect(balanceAfterA).to.equal(balanceBeforeA.sub(priceShort));
expect(balanceAfterB).to.equal(balanceBeforeB.sub(priceMedium));
expect(balanceAfterC).to.equal(balanceBeforeC.sub(priceLong));

logger.info(`Domain ${shortHash} registered for user ${userA.address}`);
logger.info(`Domain ${mediumHash} registered for user ${userB.address}`);
logger.info(`Domain ${longHash} registered for user ${userC.address}`);
});

it("Mints subdomains with varying length for free as the owner of parent domain", async () => {
// Get price of subdomains
const parents = [shortHash, mediumHash, longHash];
const subdomains = [freeShortSubdomain, freeMediumSubdomain, freeLongSubdomain];

const balancePromises = [
zns.meowToken.balanceOf(userA.address),
zns.meowToken.balanceOf(userB.address),
zns.meowToken.balanceOf(userC.address),
];

const [balanceBeforeA, balanceBeforeB, balanceBeforeC ]= await Promise.all(balancePromises);

expect(await zns.registry.exists(freeShortSubHash)).to.be.false;
expect(await zns.registry.exists(freeMediumSubHash)).to.be.false;
expect(await zns.registry.exists(freeLongSubHash)).to.be.false;

// 2. Register subdomains
await registerSubdomainBulk(
users,
parents,
subdomains,
domainAddressMock.address,
"https://zns.domains/",
distConfig,
zns
);

const [
balanceAfterA,
balanceAfterB,
balanceAfterC,
]= await Promise.all(balancePromises);

// Owners of parent domains can mint subdomains for free
expect(balanceBeforeA).to.eq(balanceAfterA);
expect(balanceBeforeB).to.eq(balanceAfterB);
expect(balanceBeforeC).to.eq(balanceAfterC);

logger.info(`Subdomain ${freeShortSubHash} registered for user ${userA.address}`);
logger.info(`Subdomain ${freeMediumSubHash} registered for user ${userB.address}`);
logger.info(`Subdomain ${freeLongSubHash} registered for user ${userC.address}`);
});

it("Mints subdomains with varying length for a cost", async () => {
// Get price of subdomains
const parents = [shortHash, mediumHash, longHash];
const subdomains = [paidShortSubdomain, paidMediumSubdomain, paidLongSubdomain];

const balancePromises = [
zns.meowToken.balanceOf(userD.address),
zns.meowToken.balanceOf(userE.address),
zns.meowToken.balanceOf(userF.address),
];

const [
balanceBeforeD,
balanceBeforeE,
balanceBeforeF,
]= await Promise.all(balancePromises);

const [
priceShort,
priceMedium,
priceLong,
] = await getPriceBulk(subdomains, zns, parents, true);

expect(await zns.registry.exists(paidShortSubHash)).to.be.false;
expect(await zns.registry.exists(paidMediumSubHash)).to.be.false;
expect(await zns.registry.exists(paidLongSubHash)).to.be.false;

// 2. Register subdomains
await registerSubdomainBulk(
[userD, userE, userF],
parents,
subdomains,
domainAddressMock.address,
"https://zns.domains/",
distConfig,
zns
);

const balanceAfterPromises = [
zns.meowToken.balanceOf(userD.address),
zns.meowToken.balanceOf(userE.address),
zns.meowToken.balanceOf(userF.address),
];

const [
balanceAfterD,
balanceAfterE,
balanceAfterF,
]= await Promise.all(balanceAfterPromises);

// Owners of parent domains can mint subdomains for free
expect(balanceAfterD).to.eq(balanceBeforeD.sub(priceShort));
expect(balanceAfterE).to.eq(balanceBeforeE.sub(priceMedium));
expect(balanceAfterF).to.eq(balanceBeforeF.sub(priceLong));

logger.info(`Subdomain ${freeShortSubHash} registered for user ${userA.address}`);
logger.info(`Subdomain ${freeMediumSubHash} registered for user ${userB.address}`);
logger.info(`Subdomain ${freeLongSubHash} registered for user ${userC.address}`);
});

it("Revokes a domain correctly", async () => {
// 3. Revoke domain
const tx = zns.rootRegistrar.connect(userA).revokeDomain(freeShortSubHash);
await expect(tx).to.emit(zns.rootRegistrar, "DomainRevoked").withArgs(freeShortSubHash, userA.address, false);
logger.info(
"info",
`Subdomain ${freeShortSubHash} revoked by user ${userA.address}`
);
});

it("Reclaims a domain correctly", async () => {
// 4. Reclaim domain
await zns.registry.connect(userB).updateDomainOwner(freeMediumSubHash, userA.address);
logger.info(
"info",
`Subdomain ${freeMediumSubHash} ownership given to user ${userA.address} from user ${userB.address}`
);

const tx = zns.rootRegistrar.connect(userB).reclaimDomain(freeMediumSubHash);

await expect(tx).to.emit(zns.rootRegistrar, "DomainReclaimed").withArgs(freeMediumSubHash, userB.address);
expect(await zns.registry.getDomainOwner(freeMediumSubHash)).to.equal(userB.address);

logger.info(`Subdomain ${freeMediumSubHash} reclaimed by user ${userB.address} from user ${userA.address}`);
});

it("Reclaims then revokes correctly", async () => {
// 5. Reclaim and revoke domain
const tx = zns.registry.connect(userC).updateDomainOwner(freeLongSubHash, userA.address);
await expect(tx).to.emit(zns.registry, "DomainOwnerSet").withArgs(freeLongSubHash, userA.address);
logger.info(`Subdomain ${freeLongSubHash} ownership given to user ${userA.address} from user ${userC.address}`);

const tx1 = zns.rootRegistrar.connect(userC).reclaimDomain(freeLongSubHash);
await expect(tx1).to.emit(zns.rootRegistrar, "DomainReclaimed").withArgs(freeLongSubHash, userC.address);

logger.info(`Subdomain ${freeLongSubHash} reclaimed by user ${userC.address}`);
expect(await zns.registry.getDomainOwner(freeLongSubHash)).to.equal(userC.address);

const tx2 = zns.rootRegistrar.connect(userC).revokeDomain(freeLongSubHash);
await expect(tx2).to.emit(zns.rootRegistrar, "DomainRevoked").withArgs(freeLongSubHash, userC.address, false);
logger.info(`Subdomain ${freeLongSubHash} revoked by user ${userC.address}`);
});
});
2 changes: 1 addition & 1 deletion test/DeployCampaignInt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -977,4 +977,4 @@ describe("Deploy Campaign Test", () => {
);
});
});
});
});
5 changes: 2 additions & 3 deletions test/ZNSRootRegistrar.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -103,8 +102,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(
Expand Down
Loading

0 comments on commit 6a8c490

Please sign in to comment.