Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/subdomain registrar #98

Draft
wants to merge 60 commits into
base: master
Choose a base branch
from
Draft

Conversation

jefflau
Copy link
Member

@jefflau jefflau commented Jul 4, 2022

Subdomain registrar using the new wrapper expiry.

  • Uses ERC20 for fees
  • Allows rentable and free subdomains

86400,
[]
)
).to.be.revertedWith(
Copy link
Member

@makoto makoto Jul 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, once this PR gets merged, this test will start failing as I enabled throwOnCallFailures: false to be able to test CCIP-read.

Please refer to this part for the fix

@makoto
Copy link
Member

makoto commented Jul 5, 2022

I wonder if it's worth making compatible with the NDT rental EIP which went it into final status recently https://github.com/ethereum/EIPs/blob/master/EIPS/eip-4907.md

@jefflau jefflau force-pushed the feature/subdomain-registrar branch from c2a5417 to d014bc9 Compare July 7, 2022 16:11
@jefflau jefflau force-pushed the feature/subdomain-registrar branch from d1a9d3e to b6b00fc Compare July 13, 2022 11:07

const labelhash = (label) => utils.keccak256(utils.toUtf8Bytes(label))
const ROOT_NODE =
'0x0000000000000000000000000000000000000000000000000000000000000000'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ROOT_NODE and EMPTY_BYTES32 are the same so no need to hard code twice. It should rather use const { EMPTY_BYTES32 } = require('../test-utils/constants')

const GRACE_PERIOD = 86400 * 90

const EMPTY_BYTES32 =
'0x0000000000000000000000000000000000000000000000000000000000000000'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use const { EMPTY_BYTES32 } = require('../test-utils/constants')


const EMPTY_BYTES32 =
'0x0000000000000000000000000000000000000000000000000000000000000000'
const EMPTY_ADDRESS = '0x0000000000000000000000000000000000000000'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use const { EMPTY_ADDRESS } = require('../test-utils/constants')

const EMPTY_ADDRESS = '0x0000000000000000000000000000000000000000'
const MAX_EXPIRY = 2n ** 64n - 1n

function increaseTime(delay) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should put them in test-utils/constants

return ethers.provider.send('evm_increaseTime', [delay])
}

function mine() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should put them in test-utils/constants

'PublicResolver',
EnsRegistry.address,
NameWrapper.address,
'0x0000000000000000000000000000000000000000',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use EMPTY_ADDRESS

_checkParent(parentNode, duration);

if (fee > 0) {
IERC20(token).transferFrom(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why we only accept fee in ERC20 token, rather than using ETH with existing price oracle?

expect(fuses).to.equal(CAN_EXTEND_EXPIRY | PARENT_CANNOT_CONTROL)
})

it('should not allow subdomains to be registerd over another domain', async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean 'should not allow subdomains to be registered twice, or should not allow subdomains to be registered when already registered? Wasn't quite sure whatover another domain` mean.


const labelhash = (label) => utils.keccak256(utils.toUtf8Bytes(label))
const ROOT_NODE =
'0x0000000000000000000000000000000000000000000000000000000000000000'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please reuse from ../test-utils/constants

const ROOT_NODE =
'0x0000000000000000000000000000000000000000000000000000000000000000'

const EMPTY_BYTES32 =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please reuse from ../test-utils/constants


const EMPTY_BYTES32 =
'0x0000000000000000000000000000000000000000000000000000000000000000'
const EMPTY_ADDRESS = '0x0000000000000000000000000000000000000000'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please reuse from ../test-utils/constants

BaseRegistrar.address,
)

// setup .xyz
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you test .xyz domains?

)

// setup .xyz
await EnsRegistry.setSubnodeOwner(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same. Do you test .xyz domains?

expect(expiry).to.equal(block.timestamp + duration)
expect(fuses).to.equal(PARENT_CANNOT_CONTROL)
})
it('should not allow subdomains to be created on unapproved parents', async () => {
Copy link
Member

@makoto makoto Dec 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should't the same test exist on TestForeverSubdomainRegistrar.js?

)
})

it('should allow subdomains to be registered without a fee', async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should't the same test exist on TestForeverSubdomainRegistrar.js?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or extract common functions between rental and forever registrar into seperate test, or use shouldBehaveLike* pattern you used for NameWrapper tests.

expect(fuses).to.equal(PARENT_CANNOT_CONTROL)
})

it('should revert if user has insufficient balance of the token', async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should't the same test exist on TestForeverSubdomainRegistrar.js?

).to.be.revertedWith(`ERC20: transfer amount exceeds balance`)
})

it('should revert if parent is expired', async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should't the same test exist on TestForeverSubdomainRegistrar.js?

expect(await NameWrapper.ownerOf(subNode)).to.equal(account2)
})
it('should allow subdomains to be renewed', async () => {
const [owner, , expiry] = await NameWrapper.getData(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is owner variable in use?

expect(expiry2.toNumber()).to.equal(expiry.toNumber() + 500)
})

it('should allow subdomains to be renewed even with 0 registration fee', async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this actually testing what you want to test? The only difference with the test one above is the duration, not registration fee

expect(expiry2.toNumber()).to.equal(expiry.toNumber() + 86400)
})

it('should revert if expiry is greater than parent', async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the parent expiry? If 84600, it would be great to set that into a meaningful variable so that the test is easier to read

// expect(await NameWrapper.ownerOf(subNode)).to.equal(account2)
// expect(await NameWrapper.ownerOf(subNode2)).to.equal(account3)
// expect(await PublicResolver['addr(bytes32)'](subNode)).to.equal(account2)
// expect(await PublicResolver['addr(bytes32)'](subNode2)).to.equal(account3)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you either uncomment or delete if not needed?

).to.be.revertedWith(`Unavailable()`)
})

it('Names can extend their own expiry', async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this not possible for RenstalSubdomainRegistrar? If not, there should be a test for that. Otherwise, I am not sure if this test is necessary as it's not extending through subname registrar but rather directly interacting with the name wrapper.

true,
)
await NameWrapper.setApprovalForAll(SubdomainRegistrar.address, true)
await Erc20WithAccount2.approve(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need to approve? Assuming you are testing registration without fee as the next one is explicitly testing with fee

true,
)
const fee = (await SubdomainRegistrar.names(node)).registrationFee
const balanceBefore = await Erc20WithAccount2.balanceOf(account2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this variable is not in use

import {IForeverSubdomainRegistrar} from "./IForeverSubdomainRegistrar.sol";
import {ISubdomainPricer} from "./pricers/ISubdomainPricer.sol";

error ParentNameNotSetup(bytes32 parentNode);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no test case to cover this error


error Unavailable();
error Unauthorised(bytes32 node);
error NameNotRegistered();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no test case to cover this error

error Unavailable();
error Unauthorised(bytes32 node);
error NameNotRegistered();
error InvalidTokenAddress(address);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no test case to cover this error

error Unauthorised(bytes32 node);
error NameNotRegistered();
error InvalidTokenAddress(address);
error NameNotSetup(bytes32 node);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no test case to cover this error

error NameNotSetup(bytes32 node);
error DataMissing();
error ParentExpired(bytes32 node);
error ParentNotWrapped(bytes32 node);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no test case to cover this error

}
}

function _checkParent(bytes32 parentNode, uint64 duration) internal view {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think test coverage exists for these cases

  • parent name is not wrapped -> Error
  • parent is NOT .eth (DNS, subname)
  • parent expiry is in grace period
  • parent expiry does not exist (subname?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants