-
Notifications
You must be signed in to change notification settings - Fork 32
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
Add Launch Auction Price Oracle with reduced half life #70
Changes from 24 commits
7dd9033
6b37b28
facd077
0e056b4
edea68f
0a6684a
4774c14
6fb4de2
a2f7087
17a5a48
0f0589f
d4534f7
9f22d48
ea08a84
61c873e
1563df6
f5826c9
71394e9
74310cb
1e46dc1
01ac27f
e9b954d
eba4cfa
ac267c2
11936e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,91 @@ | ||||||||||||||||||||||||||||
// SPDX-License-Identifier: MIT | ||||||||||||||||||||||||||||
pragma solidity ^0.8.23; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
import {FixedPointMathLib} from "solady/utils/FixedPointMathLib.sol"; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
import {EDAPrice} from "src/lib/EDAPrice.sol"; | ||||||||||||||||||||||||||||
import {StablePriceOracle} from "src/L2/StablePriceOracle.sol"; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
/// @title Launch Auction Price Oracle | ||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||
/// @notice The mechanism by which names are auctioned upon Basenames public launch. The RegistrarController | ||||||||||||||||||||||||||||
/// Passes the `launchTime` in place of expiry for all new names. The half life of this contract is hard-coded | ||||||||||||||||||||||||||||
/// to 1.5 hours, accomplished by bitshifting the `endValue` and by passing this period into the exponential decay | ||||||||||||||||||||||||||||
/// calculation. | ||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||
/// Inspired by the `ExponentialPremiumPriceOracle` implemented by ENS: | ||||||||||||||||||||||||||||
/// https://github.com/ensdomains/ens-contracts/blob/staging/contracts/ethregistrar/ExponentialPremiumPriceOracle.sol | ||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||
/// @author Coinbase (https://github.com/base-org/usernames) | ||||||||||||||||||||||||||||
contract LaunchAuctionPriceOracle is StablePriceOracle { | ||||||||||||||||||||||||||||
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ | ||||||||||||||||||||||||||||
/* STORAGE */ | ||||||||||||||||||||||||||||
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ | ||||||||||||||||||||||||||||
/// @notice Starting premium for the dutch auction. | ||||||||||||||||||||||||||||
uint256 public immutable startPremium; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
/// @notice Ending value of the auction, calculated on construction. | ||||||||||||||||||||||||||||
uint256 public immutable endValue; | ||||||||||||||||||||||||||||
Comment on lines
+21
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Immutable variables are not actually part of contract's storage if that's the intention of |
||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ | ||||||||||||||||||||||||||||
/* CONSTANTS */ | ||||||||||||||||||||||||||||
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
/// @notice The half-life of the premium price decay in seconds. | ||||||||||||||||||||||||||||
uint256 constant PRICE_PREMIUM_HALF_LIFE = 1.5 hours; | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ | ||||||||||||||||||||||||||||
/* ERRORS */ | ||||||||||||||||||||||||||||
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
/// @notice Thrown when the auction duration is not cleanly divisible by the auction halflife. | ||||||||||||||||||||||||||||
error InvalidDuration(); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ | ||||||||||||||||||||||||||||
/* IMPLEMENTATION */ | ||||||||||||||||||||||||||||
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
/// @notice Construction of the premium pricing oracle. | ||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||
/// @param rentPrices The base prices passed to construction of the StablePriceOracle. | ||||||||||||||||||||||||||||
/// @param startPremium_ The starting price for the dutch auction, denominated in wei. | ||||||||||||||||||||||||||||
/// @param totalHours The total duration (in hours) for the dutch auction. | ||||||||||||||||||||||||||||
constructor(uint256[] memory rentPrices, uint256 startPremium_, uint256 totalHours) StablePriceOracle(rentPrices) { | ||||||||||||||||||||||||||||
startPremium = startPremium_; | ||||||||||||||||||||||||||||
if ((totalHours * 1 hours) % PRICE_PREMIUM_HALF_LIFE != 0) revert InvalidDuration(); | ||||||||||||||||||||||||||||
endValue = startPremium >> ((totalHours * 1 hours) / PRICE_PREMIUM_HALF_LIFE); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
/// @notice The internal method for calculating pricing premium | ||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||
/// @dev This method handles three cases: | ||||||||||||||||||||||||||||
/// 1. The name is not yet expired, premium = 0. | ||||||||||||||||||||||||||||
/// 2. The name is expired and in the auction window, premium = calculated decayed premium. | ||||||||||||||||||||||||||||
/// 3. The name is expired and outside of the auction window, premium = 0. | ||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||
/// @param expires Timestamp of when the name will expire. | ||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||
/// @return Price premium denominated in wei. | ||||||||||||||||||||||||||||
function _premium(string memory, uint256 expires, uint256) internal view override returns (uint256) { | ||||||||||||||||||||||||||||
if (expires > block.timestamp) { | ||||||||||||||||||||||||||||
return 0; | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
uint256 elapsed = block.timestamp - expires; | ||||||||||||||||||||||||||||
uint256 premium_ = decayedPremium(elapsed); | ||||||||||||||||||||||||||||
if (premium_ > endValue) { | ||||||||||||||||||||||||||||
return premium_ - endValue; | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
return 0; | ||||||||||||||||||||||||||||
Comment on lines
+70
to
+78
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am really struggling to get a clear grasp of this code and how it behaves at the boundaries even after a few rereads. What do you think of rewriting without the
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While I generally agree that this code could use some cleanup, it's a forked and audited contract from ENS that we're making a slight tweak to. Not sure that the cleanup is worth the risk of introducing a regression. |
||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
/// @notice The mechanism for calculating the decayed premium. | ||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||
/// @param elapsed Seconds elapsed since the auction started. | ||||||||||||||||||||||||||||
/// | ||||||||||||||||||||||||||||
/// @return Dacayed price premium denominated in wei. | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Dacayed" -> "Decayed" |
||||||||||||||||||||||||||||
function decayedPremium(uint256 elapsed) public view returns (uint256) { | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I understand the computation mechanism Noting this more to confirm my own understanding, but maybe worth a dev natspec on this function that this value is an overestimate of what the user actually needs to pay given those two factors. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. F/E doesn't need to do anything special. The RegistrarController does the heavy lifting parsing the response. See: basenames/src/L2/RegistrarController.sol Lines 389 to 398 in b147ced
I think that the natspec here is accurate. This method only returns the pure price premium. The implementation handles the use-case specific logic. |
||||||||||||||||||||||||||||
/// @dev 50% decay per period in wad format | ||||||||||||||||||||||||||||
uint256 perPeriodDecayPercentWad = FixedPointMathLib.WAD / 2; | ||||||||||||||||||||||||||||
return EDAPrice.currentPrice(startPremium, elapsed, PRICE_PREMIUM_HALF_LIFE, perPeriodDecayPercentWad); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ import {IPriceOracle} from "src/L2/interface/IPriceOracle.sol"; | |
import {IReverseRegistrar} from "src/L2/interface/IReverseRegistrar.sol"; | ||
import {L1Resolver} from "src/L1/L1Resolver.sol"; | ||
import {L2Resolver} from "src/L2/L2Resolver.sol"; | ||
import {LaunchAuctionPriceOracle} from "src/L2/LaunchAuctionPriceOracle.sol"; | ||
import {RegistrarController} from "src/L2/RegistrarController.sol"; | ||
import {Registry} from "src/L2/Registry.sol"; | ||
import {ReverseRegistrar} from "src/L2/ReverseRegistrar.sol"; | ||
|
@@ -27,7 +28,7 @@ import { | |
BASE_ETH_NAME | ||
} from "src/util/Constants.sol"; | ||
|
||
contract IntegrationTest is Test { | ||
contract IntegrationTestBase is Test { | ||
address owner; | ||
address signer; | ||
address alice; | ||
|
@@ -40,6 +41,7 @@ contract IntegrationTest is Test { | |
RegistrarController registrarController; | ||
L2Resolver defaultL2Resolver; | ||
ReverseRegistrar reverseRegistrar; | ||
LaunchAuctionPriceOracle launchAuctionPriceOracle; | ||
ExponentialPremiumPriceOracle exponentialPremiumPriceOracle; | ||
|
||
AttestationValidator attestationValidator; | ||
|
@@ -52,7 +54,14 @@ contract IntegrationTest is Test { | |
bytes32 constant REVERSE_LABEL = 0xdec08c9dbbdd0890e300eb5062089b2d4b1c40e3673bbccb5423f7b37dcf9a9c; | ||
bytes32 constant ADDR_LABEL = 0xe5e14487b78f85faa6e1808e89246cf57dd34831548ff2e6097380d98db2504a; | ||
|
||
function setUp() public { | ||
uint256 constant LAUNCH_AUCTION_START_PRICE = 100 ether; | ||
uint256 constant LAUNCH_AUCTION_DURATION_HOURS = 36; | ||
uint256 constant LAUNCH_TIME = 1723420800; // Monday, August 12, 2024 12:00:00 AM GMT | ||
|
||
uint256 constant EXPIRY_AUCTION_START_PRICE = 1000 ether; | ||
uint256 constant EXPIRY_AUCTION_DURATION_DAYS = 21; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @stevieraykatz do the deploy scripts need to be updated? I'm currently having these assumptions, can you confirm if they're true for the actual deployment?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah that script is outdated. We use internal tooling to deploy. Exp. premium price oracle will use 21-day duration. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok, makes sense to me then |
||
|
||
function setUp() public virtual { | ||
owner = makeAddr("owner"); | ||
signer = makeAddr("signer"); | ||
alice = makeAddr("alice"); | ||
|
@@ -61,32 +70,23 @@ contract IntegrationTest is Test { | |
registry = new Registry(owner); | ||
reverseRegistrar = new ReverseRegistrar(registry, owner, BASE_REVERSE_NODE); | ||
|
||
uint256[] memory rentPrices = new uint256[](6); | ||
rentPrices[0] = 317_097_919_837; | ||
rentPrices[1] = 31_709_791_983; | ||
rentPrices[2] = 3_170_979_198; | ||
rentPrices[3] = 317_097_919; | ||
rentPrices[4] = 31_709_791; | ||
rentPrices[5] = 3_170_979; //3,170,979.1983764587 = 1e14 / (365 * 24 * 3600) | ||
|
||
exponentialPremiumPriceOracle = new ExponentialPremiumPriceOracle(rentPrices, 1e18, 21); | ||
launchAuctionPriceOracle = | ||
new LaunchAuctionPriceOracle(_getBasePrices(), LAUNCH_AUCTION_START_PRICE, LAUNCH_AUCTION_DURATION_HOURS); | ||
|
||
baseRegistrar = new BaseRegistrar(registry, owner, BASE_ETH_NODE, "", ""); | ||
|
||
_establishNamespaces(); | ||
|
||
registrarController = new RegistrarController( | ||
baseRegistrar, | ||
exponentialPremiumPriceOracle, | ||
IPriceOracle(launchAuctionPriceOracle), | ||
IReverseRegistrar(address(reverseRegistrar)), | ||
owner, | ||
BASE_ETH_NODE, | ||
".base.eth", | ||
payments | ||
); | ||
|
||
vm.prank(owner); | ||
baseRegistrar.addController(address(registrarController)); | ||
|
||
vm.prank(owner); | ||
reverseRegistrar.setControllerApproval(address(registrarController), true); | ||
|
||
|
@@ -98,7 +98,12 @@ contract IntegrationTest is Test { | |
vm.prank(owner); | ||
reverseRegistrar.setName("rootOwner"); | ||
|
||
vm.warp(GRACE_PERIOD * 10); | ||
vm.prank(owner); | ||
baseRegistrar.addController(address(registrarController)); | ||
|
||
vm.prank(owner); | ||
registrarController.setLaunchTime(LAUNCH_TIME); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @stevieraykatz what's the process for assuring Also at launch maybe us a multicall approach or set the launch time on the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're unable to use multicall due to the ownership restrictions on both methods. We're going to set the launchTime to say 12:00PST and then execute the TX at 12:00 so we'll miss the first couple seconds of the auction but it won't be in the future. |
||
vm.warp(LAUNCH_TIME); | ||
} | ||
|
||
function _establishNamespaces() internal { | ||
|
@@ -134,4 +139,15 @@ contract IntegrationTest is Test { | |
|
||
registrarController.register{value: registerPrice}(request); | ||
} | ||
|
||
function _getBasePrices() internal pure returns (uint256[] memory) { | ||
uint256[] memory rentPrices = new uint256[](6); | ||
rentPrices[0] = 316_808_781_402; | ||
rentPrices[1] = 31_680_878_140; | ||
rentPrices[2] = 3_168_087_814; | ||
rentPrices[3] = 316_808_781; | ||
rentPrices[4] = 31_680_878; | ||
rentPrices[5] = 3_168_087; // 3,168,808.781402895 = 1e14 / (365.25 * 24 * 3600) | ||
return rentPrices; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
//SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.23; | ||
|
||
import {Test, console} from "forge-std/Test.sol"; | ||
import {IntegrationTestBase} from "./IntegrationTestBase.t.sol"; | ||
import {RegistrarController} from "src/L2/RegistrarController.sol"; | ||
|
||
contract LaunchAuctionRegistrations is IntegrationTestBase { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @stevieraykatz Thanks so much for these. Was thinking it could help to see (lmk if I missed)
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
// Get price before oracle changes
uint256 priceBeforeSwitch = registrarController.registerPrice(name, duration);
...
assertEq(priceBeforeSwitch, price); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
output if we jump 1 day into the auction:
Basically we get what we expect. The price is 100 ether for the launch auction and 1000 ether with the prod auction contract at |
||
string name = "alice"; | ||
uint256 duration = 365.25 days; | ||
uint256 id = uint256(keccak256(bytes(name))); | ||
|
||
function test_register_at_LaunchTime() public { | ||
vm.warp(LAUNCH_TIME); | ||
_register("launch time"); | ||
} | ||
|
||
function test_register_oneHourAfter_LaunchTime() public { | ||
vm.warp(LAUNCH_TIME + 1 hours); | ||
_register("launch + 1 hour"); | ||
} | ||
|
||
function test_register_threeHoursAfter_LaunchTime() public { | ||
vm.warp(LAUNCH_TIME + 3 hours); | ||
_register("launch + 3 hours"); | ||
} | ||
|
||
function test_register_oneDayAfter_LaunchTime() public { | ||
vm.warp(LAUNCH_TIME + 1 days); | ||
_register("launch + 1 day"); | ||
} | ||
|
||
function test_register_justBefore_launchAuctionEnds() public { | ||
vm.warp(LAUNCH_TIME + (LAUNCH_AUCTION_DURATION_HOURS * 1 hours) - 1); | ||
_register("1 second before auction ends"); | ||
} | ||
|
||
function test_register_justAfter_launchAuctionEnds() public { | ||
vm.warp(LAUNCH_TIME + (LAUNCH_AUCTION_DURATION_HOURS * 1 hours)); | ||
_register("auction end time"); | ||
} | ||
|
||
function test_register_oneDayAfter_launchAuctionEnds() public { | ||
vm.warp(LAUNCH_TIME + (LAUNCH_AUCTION_DURATION_HOURS * 1 hours) + 1 days); | ||
_register("1 day after auction ends"); | ||
} | ||
|
||
function _register(string memory logCase) internal { | ||
uint256 price = registrarController.registerPrice(name, duration); | ||
vm.deal(alice, price); | ||
|
||
RegistrarController.RegisterRequest memory request = RegistrarController.RegisterRequest({ | ||
name: name, | ||
owner: alice, | ||
duration: duration, | ||
resolver: address(defaultL2Resolver), | ||
data: new bytes[](0), | ||
reverseRecord: true | ||
}); | ||
|
||
vm.expectEmit(address(registrarController)); | ||
emit RegistrarController.ETHPaymentProcessed(alice, price); | ||
|
||
vm.prank(alice); | ||
registrarController.register{value: price}(request); | ||
assertEq(baseRegistrar.ownerOf(id), alice); | ||
|
||
console.log("______________________________"); | ||
console.log("Registering at", logCase); | ||
console.log("Timestamp: ", block.timestamp); | ||
console.log("Price (WEI): ", price); | ||
console.log("______________________________"); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
//SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.23; | ||
|
||
import {Test, console} from "forge-std/Test.sol"; | ||
import {IntegrationTestBase} from "./IntegrationTestBase.t.sol"; | ||
import {RegistrarController} from "src/L2/RegistrarController.sol"; | ||
import {ExponentialPremiumPriceOracle} from "src/L2/ExponentialPremiumPriceOracle.sol"; | ||
import {IPriceOracle} from "src/L2/interface/IPriceOracle.sol"; | ||
|
||
contract PostLaunchAuctionConfig is IntegrationTestBase { | ||
string name = "alice"; | ||
uint256 duration = 365.25 days; | ||
uint256 id = uint256(keccak256(bytes(name))); | ||
|
||
function test_simulatePostAuctionConfig_register() public { | ||
// Deploy original price oracle, we will do this ahead of launch | ||
exponentialPremiumPriceOracle = new ExponentialPremiumPriceOracle( | ||
_getBasePrices(), EXPIRY_AUCTION_START_PRICE, EXPIRY_AUCTION_DURATION_DAYS | ||
); | ||
|
||
// Jump forward 30 days | ||
vm.warp(LAUNCH_TIME + 30 days); | ||
|
||
// Set new price oracle on registrar controller (ownerOnly method) | ||
vm.prank(owner); | ||
registrarController.setPriceOracle(IPriceOracle(exponentialPremiumPriceOracle)); | ||
|
||
//// Register a name and check price + success | ||
uint256 price = registrarController.registerPrice(name, duration); | ||
vm.deal(alice, price); | ||
|
||
RegistrarController.RegisterRequest memory request = RegistrarController.RegisterRequest({ | ||
name: name, | ||
owner: alice, | ||
duration: duration, | ||
resolver: address(defaultL2Resolver), | ||
data: new bytes[](0), | ||
reverseRecord: true | ||
}); | ||
|
||
vm.expectEmit(address(registrarController)); | ||
emit RegistrarController.ETHPaymentProcessed(alice, price); | ||
|
||
vm.prank(alice); | ||
registrarController.register{value: price}(request); | ||
assertEq(baseRegistrar.ownerOf(id), alice); | ||
|
||
uint256 expectedPrice = exponentialPremiumPriceOracle.price5Letter() * duration; | ||
assertEq(price, expectedPrice); | ||
|
||
console.log("______________________________"); | ||
console.log("Timestamp: ", block.timestamp); | ||
console.log("Price (WEI): ", price); | ||
console.log("______________________________"); | ||
} | ||
|
||
function test_simulateContingency() public { | ||
// Deploy original price oracle, we will do this ahead of launch | ||
exponentialPremiumPriceOracle = new ExponentialPremiumPriceOracle( | ||
_getBasePrices(), EXPIRY_AUCTION_START_PRICE, EXPIRY_AUCTION_DURATION_DAYS | ||
); | ||
|
||
// Jump forward 1 day | ||
vm.warp(LAUNCH_TIME + 1 days); | ||
|
||
// Set the launch time to 0 (no-op for launch pricing) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah bad comment. RegistrarController "launchTime" is used as a replacement for expiry on new names. This is what enables the launch auction (when normally names would only get an auction after expiring). I'll fix the comment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed comment. |
||
vm.prank(owner); | ||
registrarController.setLaunchTime(0); | ||
// Set new price oracle on registrar controller (ownerOnly method) | ||
vm.prank(owner); | ||
registrarController.setPriceOracle(IPriceOracle(exponentialPremiumPriceOracle)); | ||
|
||
//// Register a name and check price + success | ||
uint256 price = registrarController.registerPrice(name, duration); | ||
vm.deal(alice, price); | ||
|
||
RegistrarController.RegisterRequest memory request = RegistrarController.RegisterRequest({ | ||
name: name, | ||
owner: alice, | ||
duration: duration, | ||
resolver: address(defaultL2Resolver), | ||
data: new bytes[](0), | ||
reverseRecord: true | ||
}); | ||
|
||
vm.expectEmit(address(registrarController)); | ||
emit RegistrarController.ETHPaymentProcessed(alice, price); | ||
|
||
vm.prank(alice); | ||
registrarController.register{value: price}(request); | ||
assertEq(baseRegistrar.ownerOf(id), alice); | ||
|
||
uint256 expectedPrice = exponentialPremiumPriceOracle.price5Letter() * duration; | ||
assertEq(price, expectedPrice); | ||
|
||
console.log("______________________________"); | ||
console.log("Timestamp: ", block.timestamp); | ||
console.log("Price (WEI): ", price); | ||
console.log("______________________________"); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will there be a separate PR that utilizes this new oracle?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I follow. In case this context helps, the flow for launch will be:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How and when does 2. happen?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's set as the price oracle upon deployment of the GA Registrar Controller:
basenames/src/L2/RegistrarController.sol
Line 273 in b147ced
Then, we do a pair of transactions in quick succession to "turn on" registrations.
basenames/src/L2/RegistrarController.sol
Line 330 in b147ced
basenames/src/L2/BaseRegistrar.sol
Line 208 in b147ced