Skip to content

Commit 33976c4

Browse files
committed
add chainRootHash to ts code and tests
1 parent 6dce79b commit 33976c4

File tree

4 files changed

+157
-35
lines changed

4 files changed

+157
-35
lines changed

src/deploy/campaign/environments.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,14 @@ export const getConfig = async ({
6060
admins,
6161
zeroVaultAddress,
6262
env, // this is ONLY used for tests!
63+
chainRootHash, // this is ONLY used for tests! should be read from the env variable in prod
6364
} : {
6465
deployer : SignerWithAddress;
6566
governors ?: Array<string>;
6667
admins ?: Array<string>;
6768
zeroVaultAddress ?: string;
6869
env ?: string;
70+
chainRootHash ?: string;
6971
}) : Promise<IZNSCampaignConfig<SignerWithAddress>> => {
7072
// Will throw an error based on any invalid setup, given the `ENV_LEVEL` set
7173
const priceConfig = validateEnv(env);
@@ -102,11 +104,20 @@ export const getConfig = async ({
102104
// Get admin addresses set through env, if any
103105
const adminAddresses = getCustomAddresses("ADMIN_ADDRESSES", deployerAddress, admins);
104106

107+
let chainRootHashFinal;
108+
if (process.env.ENV_LEVEL === "dev") {
109+
chainRootHashFinal = chainRootHash || ethers.ZeroHash;
110+
} else {
111+
requires(!!process.env.CHAIN_ROOT_HASH, "Must provide a Chain Root Hash for 'prod' or 'test' environment");
112+
chainRootHashFinal = process.env.CHAIN_ROOT_HASH;
113+
}
114+
105115
const config : IZNSCampaignConfig<SignerWithAddress> = {
106116
env: process.env.ENV_LEVEL!,
107117
deployAdmin: deployer,
108118
governorAddresses,
109119
adminAddresses,
120+
chainRootHash: chainRootHashFinal as string,
110121
domainToken: {
111122
name: process.env.DOMAIN_TOKEN_NAME ? process.env.DOMAIN_TOKEN_NAME : ZNS_DOMAIN_TOKEN_NAME,
112123
symbol: process.env.DOMAIN_TOKEN_SYMBOL ? process.env.DOMAIN_TOKEN_SYMBOL : ZNS_DOMAIN_TOKEN_SYMBOL,

src/deploy/campaign/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export interface IZNSCampaignConfig <Signer> extends IDeployCampaignConfig<Signe
2424
deployAdmin : Signer;
2525
governorAddresses : Array<string>;
2626
adminAddresses : Array<string>;
27+
chainRootHash : string;
2728
domainToken : {
2829
name : string;
2930
symbol : string;
@@ -67,4 +68,4 @@ export interface IZNSContracts extends IContractState<ZNSContract> {
6768
rootRegistrar : ZNSRootRegistrar;
6869
fixedPricer : ZNSFixedPricer;
6970
subRegistrar : ZNSSubRegistrar;
70-
}
71+
}

src/deploy/missions/contracts/registry.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,13 @@ IZNSContracts
2424
instanceName = znsNames.registry.instance;
2525

2626
async deployArgs () : Promise<TDeployArgs> {
27-
const { accessController } = this.campaign;
28-
return [ await accessController.getAddress() ];
27+
const {
28+
accessController,
29+
config: {
30+
chainRootHash,
31+
},
32+
} = this.campaign;
33+
34+
return [ await accessController.getAddress(), chainRootHash ];
2935
}
3036
}

test/L2-BRIDGE-TEST/MultiZNS.test.ts

Lines changed: 136 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
AccessType,
99
distrConfigEmpty,
1010
DISTRIBUTION_LOCKED_NOT_EXIST_ERR,
11-
fullDistrConfigEmpty,
11+
fullDistrConfigEmpty, hashDomainLabel,
1212
NOT_AUTHORIZED_ERR,
1313
NOT_OWNER_OF_ERR,
1414
} from "../helpers";
@@ -17,41 +17,44 @@ import * as ethers from "ethers";
1717
import { ZNSChainResolver, ZNSChainResolver__factory } from "../../typechain";
1818

1919

20-
describe("MultiZNS", () => {
21-
let zns : IZNSContracts;
20+
describe.only("MultiZNS", () => {
21+
let znsL1 : IZNSContracts;
22+
let znsL2 : IZNSContracts;
2223

2324
let deployAdmin : SignerWithAddress;
2425
let registryMock : SignerWithAddress;
2526

26-
let config : IZNSCampaignConfig<SignerWithAddress>;
27+
let campaignConfig : IZNSCampaignConfig<SignerWithAddress>;
2728

2829
const chainDomainLabel = "zchain";
2930
let chainDomainHash : string;
31+
let rootDomainL2Hash : string;
3032

3133
let chainResolver : ZNSChainResolver;
3234

3335
before(async () => {
3436
[ deployAdmin, registryMock ] = await hre.ethers.getSigners();
3537

36-
config = await getConfig({
38+
campaignConfig = await getConfig({
3739
deployer: deployAdmin,
3840
zeroVaultAddress: deployAdmin.address,
41+
chainRootHash: ethers.ZeroHash,
3942
});
4043

41-
const campaign = await runZnsCampaign({ config });
44+
const campaign = await runZnsCampaign({ config: campaignConfig });
4245

43-
zns = campaign.state.contracts;
46+
znsL1 = campaign.state.contracts;
4447

45-
await zns.meowToken.mint(deployAdmin.address, 1000000000000000000000n);
46-
await zns.meowToken.connect(deployAdmin).approve(zns.treasury.target, ethers.MaxUint256);
48+
await znsL1.meowToken.mint(deployAdmin.address, 1000000000000000000000n);
49+
await znsL1.meowToken.connect(deployAdmin).approve(znsL1.treasury.target, ethers.MaxUint256);
4750

4851
// TODO multi: add deploy mission for ChainResolver if decided to leave it!
4952
const chainResFact = new ZNSChainResolver__factory(deployAdmin);
5053
chainResolver = await hre.upgrades.deployProxy(
5154
chainResFact,
5255
[
53-
zns.accessController.target,
54-
zns.registry.target,
56+
znsL1.accessController.target,
57+
znsL1.registry.target,
5558
],
5659
{
5760
kind: "uups",
@@ -61,16 +64,18 @@ describe("MultiZNS", () => {
6164
});
6265

6366
describe("Bridging Single Chain Specific Domain", () => {
64-
it.only("should register a new root domain for a chain regularly", async () => {
67+
it("should register a new root domain for a chain regularly", async () => {
6568
chainDomainHash = await registrationWithSetup({
66-
zns,
69+
zns: znsL1,
6770
user: deployAdmin,
6871
domainLabel: chainDomainLabel,
6972
fullConfig: fullDistrConfigEmpty,
7073
});
7174

75+
expect(chainDomainHash).to.equal(hashDomainLabel(chainDomainLabel));
76+
7277
// should be LOCKED to not allow any subdomains on L1
73-
const { accessType } = await zns.subRegistrar.distrConfigs(chainDomainHash);
78+
const { accessType } = await znsL1.subRegistrar.distrConfigs(chainDomainHash);
7479
expect(accessType).to.equal(0n);
7580

7681
// set ChainResolver ?!?!?!
@@ -88,63 +93,63 @@ describe("MultiZNS", () => {
8893
);
8994

9095
// transfer Domain Token to ZNSRegistry. It CAN NOT be transfered back! This is a final immutable operation!
91-
await zns.domainToken.connect(deployAdmin).transferFrom(
96+
await znsL1.domainToken.connect(deployAdmin).transferFrom(
9297
deployAdmin.address,
93-
zns.registry.target,
98+
znsL1.registry.target,
9499
BigInt(chainDomainHash)
95100
);
96101

97102
// [AS A LAST OPERATION] change owner to ZNSRegistry to signify that a domain is on another network
98-
await zns.registry.connect(deployAdmin).updateDomainOwner(chainDomainHash, zns.registry.target);
103+
await znsL1.registry.connect(deployAdmin).updateDomainOwner(chainDomainHash, znsL1.registry.target);
99104

100105
// make sure no domain related functions are available to the domain creator now
101106
await expect(
102-
zns.registry.connect(deployAdmin).updateDomainOwner(
107+
znsL1.registry.connect(deployAdmin).updateDomainOwner(
103108
chainDomainHash,
104109
deployAdmin.address
105110
)
106-
).to.be.revertedWithCustomError(zns.registry, NOT_AUTHORIZED_ERR);
111+
).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR);
107112

108113
await expect(
109-
zns.addressResolver.connect(deployAdmin).setAddress(
114+
znsL1.addressResolver.connect(deployAdmin).setAddress(
110115
chainDomainHash,
111116
deployAdmin.address
112117
)
113-
).to.be.revertedWithCustomError(zns.registry, NOT_AUTHORIZED_ERR);
118+
).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR);
114119

115120
await expect(
116-
zns.subRegistrar.connect(deployAdmin).setDistributionConfigForDomain(
121+
znsL1.subRegistrar.connect(deployAdmin).setDistributionConfigForDomain(
117122
chainDomainHash,
118123
{
119124
...distrConfigEmpty,
120125
accessType: AccessType.OPEN,
121126
}
122127
)
123-
).to.be.revertedWithCustomError(zns.registry, NOT_AUTHORIZED_ERR);
128+
).to.be.revertedWithCustomError(znsL1.registry, NOT_AUTHORIZED_ERR);
124129

125130
// can't Revoke or Reclaim domain
126131
await expect(
127-
zns.rootRegistrar.connect(deployAdmin).revokeDomain(chainDomainHash)
128-
).to.be.revertedWithCustomError(zns.rootRegistrar, NOT_OWNER_OF_ERR);
132+
znsL1.rootRegistrar.connect(deployAdmin).revokeDomain(chainDomainHash)
133+
).to.be.revertedWithCustomError(znsL1.rootRegistrar, NOT_OWNER_OF_ERR);
129134

130135
await expect(
131-
zns.rootRegistrar.connect(deployAdmin).reclaimDomain(chainDomainHash)
132-
).to.be.revertedWithCustomError(zns.rootRegistrar, NOT_OWNER_OF_ERR);
136+
znsL1.rootRegistrar.connect(deployAdmin).reclaimDomain(chainDomainHash)
137+
).to.be.revertedWithCustomError(znsL1.rootRegistrar, NOT_OWNER_OF_ERR);
133138

134139
// make sure no one can register subdomains
135140
await expect(
136141
registrationWithSetup({
137-
zns,
142+
zns: znsL1,
138143
user: deployAdmin,
139144
parentHash: chainDomainHash,
140145
domainLabel: "test",
141146
fullConfig: fullDistrConfigEmpty,
142147
})
143-
).to.be.revertedWithCustomError(zns.subRegistrar, DISTRIBUTION_LOCKED_NOT_EXIST_ERR);
148+
).to.be.revertedWithCustomError(znsL1.subRegistrar, DISTRIBUTION_LOCKED_NOT_EXIST_ERR);
144149

145-
const record = await zns.registry.getDomainRecord(chainDomainHash);
146-
expect(record.owner).to.equal(zns.registry.target);
147-
expect(record.resolver).to.equal(zns.addressResolver.target);
150+
const record = await znsL1.registry.getDomainRecord(chainDomainHash);
151+
expect(record.owner).to.equal(znsL1.registry.target);
152+
expect(record.resolver).to.equal(znsL1.addressResolver.target);
148153

149154
// check resolver data
150155
const resolverData = await chainResolver.resolveChainDataStruct(chainDomainHash);
@@ -153,5 +158,104 @@ describe("MultiZNS", () => {
153158
expect(resolverData.znsRegistryOnChain).to.equal(znsRegistryOnChain);
154159
expect(resolverData.auxData).to.equal(auxData);
155160
});
161+
162+
it("deploy ZNS L2", async () => {
163+
campaignConfig = {
164+
...campaignConfig,
165+
chainRootHash: chainDomainHash,
166+
};
167+
const campaignL2 = await runZnsCampaign({ config: campaignConfig });
168+
169+
znsL2 = campaignL2.state.contracts;
170+
171+
await znsL2.meowToken.mint(deployAdmin.address, 1000000000000000000000n);
172+
await znsL2.meowToken.connect(deployAdmin).approve(znsL2.treasury.target, ethers.MaxUint256);
173+
});
174+
175+
it("should set up ZNS L2 with proper domain as root", async () => {
176+
// check that the domain is properly set up
177+
const chainRootHash = await znsL2.registry.CHAIN_ROOT_HASH();
178+
expect(chainRootHash).to.equal(chainDomainHash);
179+
180+
// check pricer setup
181+
const distrConfigFromL2 = await znsL2.curvePricer.priceConfigs(chainRootHash);
182+
expect(distrConfigFromL2.maxPrice).to.deep.equal(campaignConfig.rootPriceConfig.maxPrice);
183+
expect(distrConfigFromL2.minPrice).to.deep.equal(campaignConfig.rootPriceConfig.minPrice);
184+
expect(distrConfigFromL2.maxLength).to.equal(campaignConfig.rootPriceConfig.maxLength);
185+
expect(distrConfigFromL2.baseLength).to.equal(campaignConfig.rootPriceConfig.baseLength);
186+
expect(distrConfigFromL2.precisionMultiplier).to.equal(campaignConfig.rootPriceConfig.precisionMultiplier);
187+
expect(distrConfigFromL2.feePercentage).to.equal(campaignConfig.rootPriceConfig.feePercentage);
188+
expect(distrConfigFromL2.isSet).to.equal(true);
189+
190+
// check treasury setup
191+
const paymentConfigFromL2 = await znsL2.treasury.paymentConfigs(chainRootHash);
192+
expect(paymentConfigFromL2.token).to.equal(znsL2.meowToken.target);
193+
expect(paymentConfigFromL2.beneficiary).to.equal(campaignConfig.zeroVaultAddress);
194+
});
195+
196+
it("should register a new root domain on L2", async () => {
197+
const rootDomainL2Label = "wilderworld";
198+
rootDomainL2Hash = await registrationWithSetup({
199+
zns: znsL2,
200+
user: deployAdmin,
201+
domainLabel: rootDomainL2Label,
202+
// TODO multi: add a config here to check later in test
203+
fullConfig: fullDistrConfigEmpty,
204+
});
205+
206+
// validate it hashed properly
207+
const chainRootHash = await znsL2.registry.CHAIN_ROOT_HASH();
208+
const abiCoder = new ethers.AbiCoder();
209+
const encoded = abiCoder.encode(
210+
["bytes32", "bytes32"],
211+
[chainRootHash, hashDomainLabel(rootDomainL2Label)]
212+
);
213+
const rootDomainHashRef = ethers.solidityPackedKeccak256(
214+
["bytes"],
215+
[encoded]
216+
);
217+
218+
expect(rootDomainL2Hash).to.equal(rootDomainHashRef);
219+
220+
// check owner and domain token
221+
const record = await znsL2.registry.getDomainRecord(rootDomainL2Hash);
222+
expect(record.owner).to.equal(deployAdmin.address);
223+
expect(record.resolver).to.equal(znsL2.addressResolver.target);
224+
225+
const domainTokenOwner = await znsL2.domainToken.ownerOf(BigInt(rootDomainL2Hash));
226+
expect(domainTokenOwner).to.equal(deployAdmin.address);
227+
});
228+
229+
it("should register a subdomain on L2", async () => {
230+
const subDomainLabel = "wheels";
231+
const subDomainHash = await registrationWithSetup({
232+
zns: znsL2,
233+
user: deployAdmin,
234+
parentHash: rootDomainL2Hash,
235+
domainLabel: subDomainLabel,
236+
fullConfig: fullDistrConfigEmpty,
237+
});
238+
239+
// validate hashing
240+
const abiCoder = new ethers.AbiCoder();
241+
const encoded = abiCoder.encode(
242+
["bytes32", "bytes32"],
243+
[rootDomainL2Hash, hashDomainLabel(subDomainLabel)]
244+
);
245+
const subDomainHashRef = ethers.solidityPackedKeccak256(
246+
["bytes"],
247+
[encoded]
248+
);
249+
250+
expect(subDomainHash).to.equal(subDomainHashRef);
251+
252+
// check owner and domain token
253+
const record = await znsL2.registry.getDomainRecord(subDomainHash);
254+
expect(record.owner).to.equal(deployAdmin.address);
255+
expect(record.resolver).to.equal(znsL2.addressResolver.target);
256+
257+
const domainTokenOwner = await znsL2.domainToken.ownerOf(BigInt(subDomainHash));
258+
expect(domainTokenOwner).to.equal(deployAdmin.address);
259+
});
156260
});
157261
});

0 commit comments

Comments
 (0)