UNPKG

@etherspot/contracts

Version:

Etherspot Solidity contracts

314 lines (313 loc) 14.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const hardhat_1 = require("hardhat"); const ethers_1 = require("ethers"); const shared_1 = require("../shared"); const { getSigners } = hardhat_1.ethers; describe('ENSController', () => { let signers; let sender; let guardian; let ensController; let ensRegistry; let subNodeRegistrationMessagePayloadFactory; const createNodeFactory = async (addNode = true) => { const name = (0, shared_1.randomName)(); const labelHash = ethers_1.utils.id(name); const node = ethers_1.utils.namehash(name); const owner = signers.pop(); await (0, shared_1.processTx)(ensRegistry.setSubnodeOwner(ethers_1.constants.HashZero, labelHash, owner.address)); if (addNode) { await (0, shared_1.processTx)(ensController.connect(owner).submitNode(node)); await (0, shared_1.processTx)(ensRegistry.connect(owner).setOwner(node, ensController.address)); await (0, shared_1.processTx)(ensController.connect(owner).verifyNode(node)); } return { owner, name, labelHash, node, createSubNode: () => { const label = (0, shared_1.randomName)(); return { name: `${label}.${name}`, labelHash: ethers_1.utils.id(label), node: ethers_1.utils.namehash(`${label}.${name}`), }; }, }; }; before(async () => { signers = await getSigners(); sender = signers.pop(); guardian = signers.pop(); ensController = await (0, shared_1.deployContract)('ENSController'); ensRegistry = await (0, shared_1.deployContract)('ENSRegistry', [], sender); await (0, shared_1.processTx)(ensController.initialize(ensRegistry.address, [guardian.address], (0, shared_1.randomAddress)())); subNodeRegistrationMessagePayloadFactory = (0, shared_1.createMessagePayloadFactory)(ensController, 'SubNodeRegistration', [ { name: 'account', type: 'address', }, { name: 'node', type: 'bytes32', }, { name: 'label', type: 'bytes32', }, ]); ensController = ensController.connect(sender); }); context('registry()', () => { it('expect to return current registry address', async () => { await expect(ensController.registry()).resolves.toBe(ensRegistry.address); }); }); context('setRegistry()', () => { const newRegistry = (0, shared_1.randomAddress)(); before(() => { ensController = ensController.connect(guardian); }); after(async () => { await (0, shared_1.processTx)(ensController.setRegistry(ensRegistry.address)); ensController = ensController.connect(sender); }); it('expect to change registry address', async () => { const { events: [event], } = await (0, shared_1.processTx)(ensController.setRegistry(newRegistry)); expect(event.event).toBe('RegistryChanged'); expect(event.args.registry).toBe(newRegistry); }); it('expect to revert on same registry address', async () => { await expect(ensController.setRegistry(newRegistry)).rejects.toThrow(/revert/); }); it('expect to revert when sender is not a guardian', async () => { await expect(ensController.connect(signers.pop()).setRegistry((0, shared_1.randomAddress)())).rejects.toThrow(/revert/); }); }); context('submitNode()', () => { let nodeFactory; before(async () => { nodeFactory = await createNodeFactory(false); }); it('expect to submit node', async () => { const { owner, node } = nodeFactory; const { events: [event], } = await (0, shared_1.processTx)(ensController.connect(owner).submitNode(node)); expect(event.event).toBe('NodeSubmitted'); expect(event.args.node).toBe(node); expect(event.args.owner).toBe(owner.address); }); it('expect to revert when node exists', async () => { const { node } = nodeFactory; await expect(ensController.submitNode(node)).rejects.toThrow(/revert/); }); it('expect to revert on invalid node', async () => { await expect(ensController.submitNode((0, shared_1.randomHex32)())).rejects.toThrow(/revert/); }); }); context('verifyNode()', () => { let nodeFactory; before(async () => { nodeFactory = await createNodeFactory(false); const { owner, node } = nodeFactory; await (0, shared_1.processTx)(ensController.connect(owner).submitNode(node)); await (0, shared_1.processTx)(ensRegistry.connect(owner).setOwner(node, ensController.address)); }); it('expect to verify node', async () => { const { owner, node } = nodeFactory; const { events } = await (0, shared_1.processTx)(ensController.connect(owner).verifyNode(node)); const event = events.find(({ event }) => event === 'NodeVerified'); expect(event.event).toBe('NodeVerified'); expect(event.args.node).toBe(node); await expect(ensRegistry.resolver(node)).resolves.toBe(ensController.address); }); it('expect to revert when node exists', async () => { const { node } = nodeFactory; await expect(ensController.verifyNode(node)).rejects.toThrow(/revert/); }); it('expect to revert on invalid node', async () => { await expect(ensController.verifyNode((0, shared_1.randomHex32)())).rejects.toThrow(/revert/); }); }); context('releaseNode()', () => { let nodeFactory; before(async () => { nodeFactory = await createNodeFactory(); }); it('expect to release node', async () => { const { owner, node } = nodeFactory; const { events } = await (0, shared_1.processTx)(ensController.connect(owner).releaseNode(node)); expect(events[1].event).toBe('NodeReleased'); expect(events[1].args.node).toBe(node); expect(events[1].args.owner).toBe(owner.address); await expect(ensRegistry.owner(node)).resolves.toBe(owner.address); }); it('expect to revert when node exists', async () => { const { node } = nodeFactory; await expect(ensController.releaseNode(node)).rejects.toThrow(/revert/); }); it('expect to revert on invalid node', async () => { await expect(ensController.releaseNode((0, shared_1.randomHex32)())).rejects.toThrow(/revert/); }); }); context('setAddr()', () => { let account; let subNode; before(async () => { account = signers.pop(); const nodeFactory = await createNodeFactory(); subNode = nodeFactory.createSubNode(); const { node } = nodeFactory; const guardianSignature = await subNodeRegistrationMessagePayloadFactory.sign(guardian, { account: account.address, label: subNode.labelHash, node, }); await (0, shared_1.processTx)(ensController .connect(account) .registerSubNode(node, subNode.labelHash, guardianSignature)); }); it('expect to update addr by creator', async () => { const { node } = subNode; const newOwner = (0, shared_1.randomAddress)(); const { events } = await (0, shared_1.processTx)(ensController .connect(account)['setAddr(bytes32,address)'](node, newOwner)); const event = events.find(({ event }) => event === 'AddrChanged'); expect(event).toBeDefined(); expect(event.event).toBe('AddrChanged'); expect(event.args.node).toBe(node); expect(event.args.addr).toBe(newOwner); }); it('expect to reject when sender is not node owner', async () => { const { node } = subNode; await expect(ensController['setAddr(bytes32,address)'](node, (0, shared_1.randomAddress)())).rejects.toThrow(/rever/); }); }); context('syncAddr()', () => { let owner; let node; before(async () => { ({ node, owner } = await createNodeFactory(false)); await (0, shared_1.processTx)(ensRegistry.connect(owner).setResolver(node, ensController.address)); }); it('expect to sync addr', async () => { const { events } = await (0, shared_1.processTx)(ensController.connect(owner).syncAddr(node)); const event = events.find(({ event }) => event === 'AddrChanged'); expect(event).toBeDefined(); expect(event.args.node).toBe(node); expect(event.args.addr).toBe(owner.address); }); it('expect to reject when already in sync', async () => { await expect(ensController.connect(owner).syncAddr(node)).rejects.toThrow(/rever/); }); }); context('registerSubNode()', () => { let nodeFactory; let subNode; before(async () => { nodeFactory = await createNodeFactory(); subNode = nodeFactory.createSubNode(); }); it('expect to register sub node', async () => { const account = signers.pop(); const { node } = nodeFactory; const guardianSignature = await subNodeRegistrationMessagePayloadFactory.sign(guardian, { account: account.address, label: subNode.labelHash, node, }); const { events } = await (0, shared_1.processTx)(ensController .connect(account) .registerSubNode(node, subNode.labelHash, guardianSignature)); const event = events.find(({ event }) => event === 'AddrChanged'); expect(event).toBeDefined(); expect(event.args.node).toBe(subNode.node); expect(event.args.addr).toBe(account.address); }); it('expect to revert when node is taken', async () => { const account = signers.pop(); const { node } = nodeFactory; const guardianSignature = await subNodeRegistrationMessagePayloadFactory.sign(guardian, { account: account.address, label: subNode.labelHash, node, }); await expect(ensController .connect(account) .registerSubNode(node, subNode.labelHash, guardianSignature)).rejects.toThrow(/revert/); }); it('expect to revert on invalid guardian signature', async () => { const subNode = nodeFactory.createSubNode(); const account = signers.pop(); const { node } = nodeFactory; const guardianSignature = await subNodeRegistrationMessagePayloadFactory.sign(guardian, { account: (0, shared_1.randomAddress)(), label: subNode.labelHash, node, }); await expect(ensController .connect(account) .registerSubNode(node, subNode.labelHash, guardianSignature)).rejects.toThrow(/revert/); }); }); context('addr()', () => { let account; let nodeFactory; let subNode; before(async () => { account = signers.pop(); nodeFactory = await createNodeFactory(); subNode = nodeFactory.createSubNode(); const { node } = nodeFactory; const guardianSignature = await subNodeRegistrationMessagePayloadFactory.sign(guardian, { account: account.address, label: subNode.labelHash, node, }); await (0, shared_1.processTx)(ensController .connect(account) .registerSubNode(node, subNode.labelHash, guardianSignature)); }); it('expect to return controller address for root node', async () => { await expect(ensController['addr(bytes32)'](nodeFactory.node)).resolves.toBe(ensController.address); }); it('expect to return owner address for sub node', async () => { await expect(ensController['addr(bytes32)'](subNode.node)).resolves.toBe(account.address); }); it('expect to return zero address for unknown node', async () => { await expect(ensController['addr(bytes32)']((0, shared_1.randomHex32)())).resolves.toBeZeroAddress(); }); }); context('supportsInterface()', () => { it('expect to return true for supportsInterface(bytes4) interface', async () => { await expect(ensController.supportsInterface(ethers_1.utils.id('supportsInterface(bytes4)').slice(0, 10))).resolves.toBeTruthy(); }); it('expect to return true for addr(bytes32) interface', async () => { await expect(ensController.supportsInterface(ethers_1.utils.id('addr(bytes32)').slice(0, 10))).resolves.toBeTruthy(); }); it('expect to return true for name(bytes32) interface', async () => { await expect(ensController.supportsInterface(ethers_1.utils.id('name(bytes32)').slice(0, 10))).resolves.toBeTruthy(); }); it('expect to return true for pubkey(bytes32) interface', async () => { await expect(ensController.supportsInterface(ethers_1.utils.id('pubkey(bytes32)').slice(0, 10))).resolves.toBeTruthy(); }); it('expect to return true for text(bytes32,string) interface', async () => { await expect(ensController.supportsInterface(ethers_1.utils.id('text(bytes32,string)').slice(0, 10))).resolves.toBeTruthy(); }); it('expect to return false for unsupported interface', async () => { await expect(ensController.supportsInterface(ethers_1.utils.id('test(address)').slice(0, 10))).resolves.toBeFalsy(); }); }); context('hashSubNodeRegistration()', () => { it('expect to return correct hash', async () => { const message = { account: (0, shared_1.randomAddress)(), node: (0, shared_1.randomHex32)(), label: (0, shared_1.randomHex32)(), }; const expected = subNodeRegistrationMessagePayloadFactory.hash(message); await expect(ensController.hashSubNodeRegistration(message)).resolves.toBe(expected); }); }); });