-
Notifications
You must be signed in to change notification settings - Fork 51
Add UpgradeableRegistrarController #123
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
Merged
Merged
Changes from 19 commits
Commits
Show all changes
48 commits
Select commit
Hold shift + click to select a range
c307e78
Add upgradeable RegistrarController, make it EIP-7201 compliant'
stevieraykatz a578e14
Add interface to new ENS contract, add support for setting primary to…
stevieraykatz 5dfed4a
Add initializer for reverse resolver contract
stevieraykatz 43a53a7
Add shim for migration period
stevieraykatz fc735bf
Add tests for Shim
stevieraykatz 7a0d049
lint
stevieraykatz 8151302
Testing start
stevieraykatz 1fc8be7
chore: forge fmt
abdulla-cb 15ebd14
chore: typos
abdulla-cb d256095
forge install: openzeppelin-contracts-upgradeable
abdulla-cb 5214bc2
feat: use v5.0.0 of openzeppelin-contracts-upgradeable
abdulla-cb 34a313a
feat: update tests to use OpenZeppelin Upgradeable
abdulla-cb 78e3f28
chore: fix typo
abdulla-cb 5e64d7d
Update interface to ENS reverse resolver
stevieraykatz 5f78d9f
Remove launch logic
stevieraykatz d747ca0
remove shim from this branch
stevieraykatz c2bc49f
Add support for new cointypes array in reverse set
stevieraykatz 48feaf1
Add cointypes to test helper
stevieraykatz 6211b51
Remove test for removed method
stevieraykatz 0e17adf
Merge branch 'main' into upgradeable-registrar
stevieraykatz 148cb2c
attempt to fix ci
stevieraykatz eb85c2e
Cleanup test mocks
stevieraykatz 50a2c3f
Remove launch logic, cleanup test base
stevieraykatz 438d626
Fix missing refs from rename
stevieraykatz 91ce6d5
Remove reference to unused test var
stevieraykatz 2b85da9
fix _getExpiry
stevieraykatz e35b156
Fix Register test to use a duration
stevieraykatz 752aeb3
lint
stevieraykatz 3de1f8f
fix natspec
stevieraykatz cadfc45
Fixes to natspec and typos per comments on PR #95
stevieraykatz cdd4326
Add registrar controller switch-over integration test
stevieraykatz 4317ccc
chore: cleanup logging, formatting
stevieraykatz 6b124db
feat: add grace period renewal test
stevieraykatz c1a274a
chore: typos and gas
stevieraykatz 44be9dc
Merge branch 'main' into upgradeable-registrar
stevieraykatz 9d91fa3
Fix ext link ref to branch with updated code
stevieraykatz 3e0a849
add interface for new reverse registrar
stevieraykatz 465e843
lint interface
stevieraykatz 0102186
refactor reverse registration to leverage updated reverse registrar v2
stevieraykatz e48a19d
finish refactor to IReverseRegistrarV2
stevieraykatz b5a815c
Fix tests to account for new reverse registrar v2
stevieraykatz cce8e36
lint
stevieraykatz 51dc6e9
Nits from PR comments
stevieraykatz d8cb250
cleanup tests based on renamings
stevieraykatz 5a956e9
update submodules, pin solady version
stevieraykatz a3eb0c8
Revert "update submodules, pin solady version"
stevieraykatz 73afd8b
Natspec and cleanup from PR
stevieraykatz ad21ff6
Reorder modifiers
stevieraykatz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Submodule openzeppelin-contracts-upgradeable
added at
fa5253
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.4; | ||
stevieraykatz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/// @notice Interface for the L2 Reverse Registrar. | ||
interface IL2ReverseRegistrar { | ||
/// @notice Sets the `nameForAddr()` record for the calling account. | ||
/// | ||
/// @param name The name to set. | ||
function setName(string memory name) external; | ||
|
||
/// @notice Sets the `nameForAddr()` record for the addr provided account. | ||
/// | ||
/// @param addr The address to set the name for. | ||
/// @param name The name to set. | ||
function setNameForAddr(address addr, string memory name) external; | ||
|
||
/// @notice Sets the `nameForAddr()` record for the addr provided account using a signature. | ||
/// | ||
/// @param addr The address to set the name for. | ||
/// @param name The name to set. | ||
/// @param coinTypes The coin types to set. Must be inclusive of the coin type for the contract. | ||
/// @param signatureExpiry Date when the signature expires. | ||
/// @param signature The signature from the addr. | ||
function setNameForAddrWithSignature( | ||
address addr, | ||
uint256 signatureExpiry, | ||
string memory name, | ||
uint256[] memory coinTypes, | ||
bytes memory signature | ||
) external; | ||
|
||
/// @notice Sets the `nameForAddr()` record for the contract provided that is owned with `Ownable`. | ||
/// | ||
/// @param contractAddr The address of the contract to set the name for (implementing Ownable). | ||
/// @param owner The owner of the contract (via Ownable). | ||
/// @param signatureExpiry The expiry of the signature. | ||
/// @param name The name to set. | ||
/// @param coinTypes The coin types to set. Must be inclusive of the coin type for the contract. | ||
/// @param signature The signature of an address that will return true on isValidSignature for the owner. | ||
function setNameForOwnableWithSignature( | ||
address contractAddr, | ||
address owner, | ||
uint256 signatureExpiry, | ||
string memory name, | ||
uint256[] memory coinTypes, | ||
bytes memory signature | ||
) external; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.23; | ||
|
||
import {UpgradeableRegistrarControllerBase} from "./UpgradeableRegistrarControllerBase.t.sol"; | ||
|
||
contract Available is UpgradeableRegistrarControllerBase { | ||
function test_returnsFalse_whenNotAvailableOnBase() public { | ||
base.setAvailable(uint256(nameLabel), false); | ||
assertFalse(controller.available(name)); | ||
} | ||
|
||
function test_returnsFalse_whenInvalidLength() public { | ||
base.setAvailable(uint256(shortNameLabel), true); | ||
assertFalse(controller.available(shortName)); | ||
} | ||
|
||
function test_returnsTrue_whenValidAndAvailable() public { | ||
base.setAvailable(uint256(nameLabel), true); | ||
assertTrue(controller.available(name)); | ||
} | ||
} |
148 changes: 148 additions & 0 deletions
148
test/UpgradeableRegistrarController/DiscountedRegister.t.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.23; | ||
|
||
import {UpgradeableRegistrarControllerBase} from "./UpgradeableRegistrarControllerBase.t.sol"; | ||
import {UpgradeableRegistrarController} from "src/L2/UpgradeableRegistrarController.sol"; | ||
import {IPriceOracle} from "src/L2/interface/IPriceOracle.sol"; | ||
|
||
contract DiscountedRegister is UpgradeableRegistrarControllerBase { | ||
function test_reverts_ifTheDiscountIsInactive() public { | ||
UpgradeableRegistrarController.DiscountDetails memory inactiveDiscount = _getDefaultDiscount(); | ||
vm.deal(user, 1 ether); | ||
|
||
inactiveDiscount.active = false; | ||
vm.prank(owner); | ||
controller.setDiscountDetails(inactiveDiscount); | ||
uint256 price = controller.discountedRegisterPrice(name, duration, discountKey); | ||
|
||
vm.expectRevert(abi.encodeWithSelector(UpgradeableRegistrarController.InactiveDiscount.selector, discountKey)); | ||
vm.prank(user); | ||
controller.discountedRegister{value: price}(_getDefaultRegisterRequest(), discountKey, ""); | ||
} | ||
|
||
function test_reverts_whenInvalidDiscountRegistration() public { | ||
vm.deal(user, 1 ether); | ||
vm.prank(owner); | ||
controller.setDiscountDetails(_getDefaultDiscount()); | ||
validator.setReturnValue(false); | ||
uint256 price = controller.discountedRegisterPrice(name, duration, discountKey); | ||
|
||
vm.expectRevert( | ||
abi.encodeWithSelector(UpgradeableRegistrarController.InvalidDiscount.selector, discountKey, "") | ||
); | ||
vm.prank(user); | ||
controller.discountedRegister{value: price}(_getDefaultRegisterRequest(), discountKey, ""); | ||
} | ||
|
||
function test_reverts_whenNameNotAvailble() public { | ||
vm.deal(user, 1 ether); | ||
vm.prank(owner); | ||
controller.setDiscountDetails(_getDefaultDiscount()); | ||
uint256 price = controller.discountedRegisterPrice(name, duration, discountKey); | ||
validator.setReturnValue(true); | ||
base.setAvailable(uint256(nameLabel), false); | ||
|
||
vm.expectRevert(abi.encodeWithSelector(UpgradeableRegistrarController.NameNotAvailable.selector, name)); | ||
vm.prank(user); | ||
controller.discountedRegister{value: price}(_getDefaultRegisterRequest(), discountKey, ""); | ||
} | ||
|
||
function test_reverts_whenDurationTooShort() public { | ||
vm.deal(user, 1 ether); | ||
vm.prank(owner); | ||
controller.setDiscountDetails(_getDefaultDiscount()); | ||
uint256 price = controller.discountedRegisterPrice(name, duration, discountKey); | ||
validator.setReturnValue(true); | ||
base.setAvailable(uint256(nameLabel), true); | ||
|
||
UpgradeableRegistrarController.RegisterRequest memory shortDurationRequest = _getDefaultRegisterRequest(); | ||
uint256 shortDuration = controller.MIN_REGISTRATION_DURATION() - 1; | ||
shortDurationRequest.duration = shortDuration; | ||
vm.expectRevert(abi.encodeWithSelector(UpgradeableRegistrarController.DurationTooShort.selector, shortDuration)); | ||
vm.prank(user); | ||
controller.discountedRegister{value: price}(shortDurationRequest, discountKey, ""); | ||
} | ||
|
||
function test_reverts_whenValueTooSmall() public { | ||
vm.deal(user, 1 ether); | ||
vm.prank(owner); | ||
controller.setDiscountDetails(_getDefaultDiscount()); | ||
prices.setPrice(name, IPriceOracle.Price({base: 1 ether, premium: 0})); | ||
uint256 price = controller.discountedRegisterPrice(name, duration, discountKey); | ||
validator.setReturnValue(true); | ||
base.setAvailable(uint256(nameLabel), true); | ||
|
||
vm.expectRevert(UpgradeableRegistrarController.InsufficientValue.selector); | ||
vm.prank(user); | ||
controller.discountedRegister{value: price - 1}(_getDefaultRegisterRequest(), discountKey, ""); | ||
} | ||
|
||
function test_registersWithDiscountSuccessfully() public { | ||
vm.deal(user, 1 ether); | ||
vm.prank(owner); | ||
controller.setDiscountDetails(_getDefaultDiscount()); | ||
validator.setReturnValue(true); | ||
base.setAvailable(uint256(nameLabel), true); | ||
UpgradeableRegistrarController.RegisterRequest memory request = _getDefaultRegisterRequest(); | ||
uint256 expires = block.timestamp + request.duration; | ||
base.setNameExpires(uint256(nameLabel), expires); | ||
uint256 price = controller.discountedRegisterPrice(name, duration, discountKey); | ||
|
||
vm.expectEmit(address(controller)); | ||
emit UpgradeableRegistrarController.ETHPaymentProcessed(user, price); | ||
vm.expectEmit(address(controller)); | ||
emit UpgradeableRegistrarController.NameRegistered(request.name, nameLabel, user, expires); | ||
vm.expectEmit(address(controller)); | ||
emit UpgradeableRegistrarController.DiscountApplied(user, discountKey); | ||
|
||
vm.prank(user); | ||
controller.discountedRegister{value: price}(request, discountKey, ""); | ||
|
||
bytes memory retByte = resolver.firstBytes(); | ||
assertEq(keccak256(retByte), keccak256(request.data[0])); | ||
assertTrue(reverse.hasClaimed(user)); | ||
address[] memory addrs = new address[](1); | ||
addrs[0] = user; | ||
assertTrue(controller.hasRegisteredWithDiscount(addrs)); | ||
} | ||
|
||
function test_sendsARefund_ifUserOverpayed() public { | ||
vm.deal(user, 1 ether); | ||
vm.prank(owner); | ||
controller.setDiscountDetails(_getDefaultDiscount()); | ||
validator.setReturnValue(true); | ||
base.setAvailable(uint256(nameLabel), true); | ||
UpgradeableRegistrarController.RegisterRequest memory request = _getDefaultRegisterRequest(); | ||
uint256 expires = block.timestamp + request.duration; | ||
base.setNameExpires(uint256(nameLabel), expires); | ||
uint256 price = controller.discountedRegisterPrice(name, duration, discountKey); | ||
|
||
vm.prank(user); | ||
controller.discountedRegister{value: price + 1}(request, discountKey, ""); | ||
|
||
uint256 expectedBalance = 1 ether - price; | ||
assertEq(user.balance, expectedBalance); | ||
} | ||
|
||
function test_reverts_ifTheRegistrantHasAlreadyRegisteredWithDiscount() public { | ||
vm.deal(user, 1 ether); | ||
vm.prank(owner); | ||
controller.setDiscountDetails(_getDefaultDiscount()); | ||
validator.setReturnValue(true); | ||
base.setAvailable(uint256(nameLabel), true); | ||
UpgradeableRegistrarController.RegisterRequest memory request = _getDefaultRegisterRequest(); | ||
uint256 expires = block.timestamp + request.duration; | ||
base.setNameExpires(uint256(nameLabel), expires); | ||
uint256 price = controller.discountedRegisterPrice(name, duration, discountKey); | ||
|
||
vm.prank(user); | ||
controller.discountedRegister{value: price}(request, discountKey, ""); | ||
|
||
vm.expectRevert( | ||
abi.encodeWithSelector(UpgradeableRegistrarController.AlreadyRegisteredWithDiscount.selector, user) | ||
); | ||
request.name = "newname"; | ||
vm.prank(user); | ||
controller.discountedRegister{value: price}(request, discountKey, ""); | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
test/UpgradeableRegistrarController/DiscountedRegisterPrice.t.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.23; | ||
|
||
import {UpgradeableRegistrarControllerBase} from "./UpgradeableRegistrarControllerBase.t.sol"; | ||
import {RegistrarController} from "src/L2/RegistrarController.sol"; | ||
import {IPriceOracle} from "src/L2/interface/IPriceOracle.sol"; | ||
|
||
contract DiscountedRegisterPrice is UpgradeableRegistrarControllerBase { | ||
function test_returnsADiscountedPrice_whenThePriceIsGreaterThanTheDiscount(uint256 price) public { | ||
vm.assume(price > discountAmount); | ||
prices.setPrice(name, IPriceOracle.Price({base: price, premium: 0})); | ||
vm.prank(owner); | ||
controller.setDiscountDetails(_getDefaultDiscount()); | ||
|
||
uint256 expectedPrice = price - discountAmount; | ||
uint256 retPrice = controller.discountedRegisterPrice(name, duration, discountKey); | ||
assertEq(retPrice, expectedPrice); | ||
} | ||
|
||
function test_returnsZero_whenThePriceIsLessThanOrEqualToTheDiscount(uint256 price) public { | ||
vm.assume(price > 0 && price <= discountAmount); | ||
prices.setPrice(name, IPriceOracle.Price({base: price, premium: 0})); | ||
vm.prank(owner); | ||
controller.setDiscountDetails(_getDefaultDiscount()); | ||
|
||
uint256 retPrice = controller.discountedRegisterPrice(name, duration, discountKey); | ||
assertEq(retPrice, 0); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.23; | ||
|
||
import {UpgradeableRegistrarControllerBase} from "./UpgradeableRegistrarControllerBase.t.sol"; | ||
import {UpgradeableRegistrarController} from "src/L2/UpgradeableRegistrarController.sol"; | ||
import {IPriceOracle} from "src/L2/interface/IPriceOracle.sol"; | ||
|
||
contract Register is UpgradeableRegistrarControllerBase { | ||
function test_reverts_whenResolverRequiredAndNotSupplied() public { | ||
vm.deal(user, 1 ether); | ||
uint256 price = controller.registerPrice(name, duration); | ||
vm.expectRevert(UpgradeableRegistrarController.ResolverRequiredWhenDataSupplied.selector); | ||
vm.prank(user); | ||
UpgradeableRegistrarController.RegisterRequest memory noResolverRequest = _getDefaultRegisterRequest(); | ||
noResolverRequest.resolver = address(0); | ||
controller.register{value: price}(noResolverRequest); | ||
} | ||
|
||
function test_reverts_whenNameNotAvailble() public { | ||
vm.deal(user, 1 ether); | ||
uint256 price = controller.registerPrice(name, duration); | ||
base.setAvailable(uint256(nameLabel), false); | ||
vm.expectRevert(abi.encodeWithSelector(UpgradeableRegistrarController.NameNotAvailable.selector, name)); | ||
vm.prank(user); | ||
controller.register{value: price}(_getDefaultRegisterRequest()); | ||
} | ||
|
||
function test_reverts_whenDurationTooShort() public { | ||
vm.deal(user, 1 ether); | ||
uint256 price = controller.registerPrice(name, duration); | ||
base.setAvailable(uint256(nameLabel), true); | ||
UpgradeableRegistrarController.RegisterRequest memory shortDurationRequest = _getDefaultRegisterRequest(); | ||
uint256 shortDuration = controller.MIN_REGISTRATION_DURATION() - 1; | ||
shortDurationRequest.duration = shortDuration; | ||
vm.expectRevert(abi.encodeWithSelector(UpgradeableRegistrarController.DurationTooShort.selector, shortDuration)); | ||
vm.prank(user); | ||
controller.register{value: price}(shortDurationRequest); | ||
} | ||
|
||
function test_reverts_whenValueTooSmall() public { | ||
vm.deal(user, 1 ether); | ||
uint256 price = controller.registerPrice(name, duration); | ||
base.setAvailable(uint256(nameLabel), true); | ||
vm.expectRevert(UpgradeableRegistrarController.InsufficientValue.selector); | ||
vm.prank(user); | ||
controller.register{value: price - 1}(_getDefaultRegisterRequest()); | ||
} | ||
|
||
function test_registersSuccessfully() public { | ||
vm.deal(user, 1 ether); | ||
UpgradeableRegistrarController.RegisterRequest memory request = _getDefaultRegisterRequest(); | ||
|
||
base.setAvailable(uint256(nameLabel), true); | ||
uint256 expires = block.timestamp + request.duration; | ||
base.setNameExpires(uint256(nameLabel), expires); | ||
uint256 price = controller.registerPrice(request.name, request.duration); | ||
|
||
vm.expectEmit(address(controller)); | ||
emit UpgradeableRegistrarController.ETHPaymentProcessed(user, price); | ||
vm.expectEmit(address(controller)); | ||
emit UpgradeableRegistrarController.NameRegistered(request.name, nameLabel, user, expires); | ||
|
||
vm.prank(user); | ||
controller.register{value: price}(request); | ||
|
||
bytes memory retByte = resolver.firstBytes(); | ||
assertEq(keccak256(retByte), keccak256(request.data[0])); | ||
assertTrue(reverse.hasClaimed(user)); | ||
} | ||
|
||
function test_sendsARefund_ifUserOverpayed() public { | ||
vm.deal(user, 1 ether); | ||
UpgradeableRegistrarController.RegisterRequest memory request = _getDefaultRegisterRequest(); | ||
|
||
base.setAvailable(uint256(nameLabel), true); | ||
uint256 expires = block.timestamp + request.duration; | ||
base.setNameExpires(uint256(nameLabel), expires); | ||
uint256 price = controller.registerPrice(request.name, request.duration); | ||
|
||
vm.prank(user); | ||
controller.register{value: price + 1}(request); | ||
|
||
uint256 expectedBalance = 1 ether - price; | ||
assertEq(user.balance, expectedBalance); | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.