Skip to content

Commit b413651

Browse files
authored
feat(script): implement add-v0.3.4-rns-unified-migration-script (#185)
2 parents 0b32c2e + a374601 commit b413651

11 files changed

+513
-6
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@ docs/
2020
node_modules/
2121
yarn-error.log
2222
.yarn
23-
.yarnrc.yml
23+
.yarnrc.yml
24+
script/data/*

config.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ loadConfig() {
2828
ERC721_BATCH_TRANSFER=0x2368dfed532842db89b470fde9fd584d48d4f644
2929

3030
if [ "$MODE" == "broadcast" ]; then
31-
PK=$TESTNET_PK
31+
PK=$MAINNET_PK
3232
fi
3333
else
3434
RPC=$TESTNET_URL
@@ -37,18 +37,20 @@ loadConfig() {
3737
ERC721_BATCH_TRANSFER=0x2e889348bd37f192063bfec8ff39bd3635949e20
3838

3939
if [ "$MODE" == "broadcast" ]; then
40-
PK=$MAINNET_PK
40+
PK=$TESTNET_PK
4141
fi
4242
fi
4343

4444
if [ "$MODE" == "broadcast" ]; then
45-
CURRENT_NONCE=$(cast nonce --rpc-url $RPC $FROM)
4645
CURRENT_GAS_PRICE=$(cast gas-price --rpc-url $RPC)
4746

4847
if [[ "$PK" == op://* ]]; then
4948
PK=$(op read "$PK")
5049
fi
5150
fi
51+
52+
CURRENT_NONCE=$(cast nonce --rpc-url $RPC $FROM)
53+
echo "Current nonce: $CURRENT_NONCE"
5254
}
5355

5456
# Function to load address from deployment file
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.19;
3+
4+
import { StdStyle } from "forge-std/StdStyle.sol";
5+
import { IMulticall3 } from "forge-std/interfaces/IMulticall3.sol";
6+
import { LibString } from "solady/utils/LibString.sol";
7+
import { DefaultNetwork } from "foundry-deployment-kit/utils/DefaultNetwork.sol";
8+
import { DefaultContract } from "foundry-deployment-kit/utils/DefaultContract.sol";
9+
import { Contract } from "../utils/Contract.sol";
10+
import { INSDomainPrice, RNSDomainPrice } from "@rns-contracts/RNSDomainPrice.sol";
11+
import "./20240215_Migration.s.sol";
12+
13+
contract Migration__01_UpgradeRNSDomainPriceAndOverrideTierForCommunityNames_RNSDomainPrice is Migration__20240215 {
14+
using StdStyle for *;
15+
using LibString for *;
16+
17+
RNSDomainPrice internal _domainPrice;
18+
IMulticall3 internal _multicall;
19+
bytes32[] internal _lbHashes;
20+
21+
function run() external {
22+
_domainPrice = RNSDomainPrice(_upgradeProxy(Contract.RNSDomainPrice.key()));
23+
}
24+
25+
function _postCheck() internal override logFn("_postChecking ...") {
26+
_multicall = IMulticall3(loadContract(DefaultContract.Multicall3.key()));
27+
28+
(_labels, _tiers) = _parseData(DATA_PATH);
29+
30+
_lbHashes = toLabelHashes(_labels);
31+
32+
uint256 batchSize = 100;
33+
uint256 totalElements = _lbHashes.length;
34+
uint256 totalBatches = (totalElements + batchSize - 1) / batchSize;
35+
36+
address overrider = _domainPrice.getRoleMember(_domainPrice.OVERRIDER_ROLE(), 0);
37+
console.log("Overrider".yellow(), overrider);
38+
39+
for (uint256 i; i < totalBatches; i++) {
40+
console.log("Processing batch", i, "of", totalBatches);
41+
uint256 start = i * batchSize;
42+
uint256 end = (i + 1) * batchSize;
43+
if (end > totalElements) end = totalElements;
44+
45+
bytes32[] memory batchHashes = new bytes32[](end - start);
46+
INSDomainPrice.Tier[] memory batchTiers = new INSDomainPrice.Tier[](end - start);
47+
48+
for (uint256 j = start; j < end; j++) {
49+
batchHashes[j - start] = _lbHashes[j];
50+
batchTiers[j - start] = _tiers[j];
51+
}
52+
53+
vm.prank(overrider);
54+
_domainPrice.bulkOverrideTiers(batchHashes, batchTiers);
55+
}
56+
57+
_validateOverridenTiers();
58+
_validateOtherDomainTiers();
59+
}
60+
61+
function _validateOtherDomainTiers() internal logFn("_validating other domain tiers ...") {
62+
if (network() == DefaultNetwork.RoninMainnet.key()) {
63+
assertEq(uint8(_domainPrice.getTier("tudo")), uint8(INSDomainPrice.Tier.Tier2), "invalid tier for tudo");
64+
assertEq(uint8(_domainPrice.getTier("duke")), uint8(INSDomainPrice.Tier.Tier2), "invalid tier for duke");
65+
assertEq(uint8(_domainPrice.getTier("ace")), uint8(INSDomainPrice.Tier.Tier1), "invalid tier for ace");
66+
assertEq(uint8(_domainPrice.getTier("dragon")), uint8(INSDomainPrice.Tier.Tier2), "invalid tier for dragon");
67+
assertEq(uint8(_domainPrice.getTier("tokuda")), uint8(INSDomainPrice.Tier.Tier3), "invalid tier for tokuda");
68+
assertEq(uint8(_domainPrice.getTier("metaverse")), uint8(INSDomainPrice.Tier.Tier2), "invalid tier for metaverse");
69+
assertEq(uint8(_domainPrice.getTier("nuke")), uint8(INSDomainPrice.Tier.Tier2), "invalid tier for nuke");
70+
assertEq(
71+
uint8(_domainPrice.getTier("merchandising")), uint8(INSDomainPrice.Tier.Tier3), "invalid tier for merchandising"
72+
);
73+
}
74+
}
75+
76+
function _validateOverridenTiers() internal logFn("_validating overriden tiers ...") {
77+
IMulticall3.Call[] memory calls = new IMulticall3.Call[](_lbHashes.length);
78+
79+
for (uint256 i; i < _lbHashes.length; ++i) {
80+
calls[i] = IMulticall3.Call({
81+
target: address(_domainPrice),
82+
callData: abi.encodeCall(_domainPrice.getTier, (_labels[i]))
83+
});
84+
}
85+
86+
(, bytes[] memory returnData) = _multicall.aggregate(calls);
87+
INSDomainPrice.Tier[] memory tiers = new INSDomainPrice.Tier[](_lbHashes.length);
88+
89+
for (uint256 i; i < _lbHashes.length; ++i) {
90+
tiers[i] = abi.decode(returnData[i], (INSDomainPrice.Tier));
91+
assertEq(uint8(tiers[i]), uint8(_tiers[i]), string.concat("tier not set", vm.toString(i)));
92+
}
93+
}
94+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.19;
3+
4+
import { INSDomainPrice, RNSDomainPrice } from "@rns-contracts/RNSDomainPrice.sol";
5+
import { Contract } from "../utils/Contract.sol";
6+
import "./20240215_Migration.s.sol";
7+
8+
contract Migration__02_ResetCommunityNamesRenewalFees_RNSDomainPrice is Migration__20240215 {
9+
bytes32[] internal _lbHashes;
10+
11+
function run() external {
12+
RNSDomainPrice rnsDomainPrice = RNSDomainPrice(loadContract(Contract.RNSDomainPrice.key()));
13+
14+
_lbHashes = toLabelHashes(_labels);
15+
16+
address overrider = rnsDomainPrice.getRoleMember(rnsDomainPrice.OVERRIDER_ROLE(), 0);
17+
uint256 batchSize = 100;
18+
uint256 totalBatches = (_lbHashes.length + batchSize - 1) / batchSize;
19+
20+
for (uint256 batchIndex = 0; batchIndex < totalBatches; batchIndex++) {
21+
uint256 startIndex = batchIndex * batchSize;
22+
uint256 endIndex = startIndex + batchSize;
23+
if (endIndex > _lbHashes.length) {
24+
endIndex = _lbHashes.length;
25+
}
26+
27+
bytes32[] memory batchLbHashes = new bytes32[](endIndex - startIndex);
28+
uint256[] memory batchRenewalFees = new uint256[](endIndex - startIndex);
29+
30+
for (uint256 i = startIndex; i < endIndex; i++) {
31+
batchLbHashes[i - startIndex] = _lbHashes[i];
32+
batchRenewalFees[i - startIndex] = type(uint256).max;
33+
}
34+
35+
vm.broadcast(overrider);
36+
rnsDomainPrice.bulkOverrideRenewalFees(batchLbHashes, batchRenewalFees);
37+
}
38+
}
39+
40+
function _postCheck() internal override logFn("_postChecking ...") {
41+
RNSDomainPrice rnsDomainPrice = RNSDomainPrice(loadContract(Contract.RNSDomainPrice.key()));
42+
43+
for (uint256 i; i < _lbHashes.length; ++i) {
44+
vm.expectRevert(INSDomainPrice.RenewalFeeIsNotOverriden.selector);
45+
rnsDomainPrice.getOverriddenRenewalFee(_labels[i]);
46+
}
47+
}
48+
}
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.19;
3+
4+
import { StdStyle } from "forge-std/StdStyle.sol";
5+
import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
6+
import { console2 as console } from "forge-std/console2.sol";
7+
import { Contract } from "script/utils/Contract.sol";
8+
import { Migration } from "script/Migration.s.sol";
9+
import { RNSUnified } from "@rns-contracts/RNSUnified.sol";
10+
import { INSDomainPrice, RNSDomainPrice } from "@rns-contracts/RNSDomainPrice.sol";
11+
import { INSAuction, RNSAuction } from "@rns-contracts/RNSAuction.sol";
12+
import { LibRNSDomain } from "@rns-contracts/libraries/LibRNSDomain.sol";
13+
import { RNSOperation, RNSOperationDeploy } from "script/contracts/RNSOperationDeploy.s.sol";
14+
15+
contract Migration_03_DeployNewRNSOperation_RNSOperation is Migration {
16+
using LibRNSDomain for string;
17+
using StdStyle for *;
18+
19+
RNSUnified private rns;
20+
RNSAuction private auction;
21+
RNSOperation private rnsOperation;
22+
RNSDomainPrice private domainPrice;
23+
24+
function run() public {
25+
rnsOperation = new RNSOperationDeploy().run();
26+
27+
domainPrice = RNSDomainPrice(loadContract(Contract.RNSDomainPrice.key()));
28+
rns = RNSUnified(loadContract(Contract.RNSUnified.key()));
29+
auction = RNSAuction(loadContract(Contract.RNSAuction.key()));
30+
31+
address admin = rns.ownerOf(LibRNSDomain.RON_ID);
32+
console.log("admin".yellow(), admin);
33+
34+
vm.broadcast(rnsOperation.owner());
35+
rnsOperation.transferOwnership(admin);
36+
37+
vm.startBroadcast(admin);
38+
39+
rns.setApprovalForAll(address(rnsOperation), true);
40+
auction.grantRole(auction.OPERATOR_ROLE(), address(rnsOperation));
41+
rns.grantRole(rns.PROTECTED_SETTLER_ROLE(), address(rnsOperation));
42+
domainPrice.grantRole(domainPrice.OVERRIDER_ROLE(), address(rnsOperation));
43+
44+
vm.stopBroadcast();
45+
}
46+
47+
function _postCheck() internal override {
48+
_validateBulkMint();
49+
_validateOverridenTiers();
50+
_validateBulkSetProtected();
51+
_validateBulkOverrideRenewalFees();
52+
_validateReclaimAuctionNames({ searchSize: 20 });
53+
}
54+
55+
function _validateOverridenTiers() internal logFn("_validateOverridenTiers") {
56+
string[] memory labels = new string[](5);
57+
labels[0] = "heidi";
58+
labels[1] = "luke";
59+
labels[2] = "sophia";
60+
labels[3] = "chief";
61+
labels[4] = "slim";
62+
63+
for (uint256 i; i < labels.length; ++i) {
64+
assertEq(
65+
uint8(domainPrice.getTier(labels[i])),
66+
uint8(INSDomainPrice.Tier.Tier1),
67+
string.concat("invalid tier for auction label ", labels[i])
68+
);
69+
}
70+
}
71+
72+
function _validateBulkOverrideRenewalFees() internal logFn("_validateBulkOverrideRenewalFees") {
73+
string memory label = "tudo-provip-maximum-ultra";
74+
string[] memory labels = new string[](1);
75+
labels[0] = label;
76+
uint256[] memory yearlyUSDPrices = new uint256[](1);
77+
// 10 usd per year
78+
yearlyUSDPrices[0] = 10;
79+
80+
vm.prank(rnsOperation.owner());
81+
rnsOperation.bulkOverrideRenewalFees(labels, yearlyUSDPrices);
82+
83+
assertEq(domainPrice.getOverriddenRenewalFee(label), Math.mulDiv(yearlyUSDPrices[0], 1 ether, 365 days));
84+
}
85+
86+
function _validateReclaimAuctionNames(uint256 searchSize) internal logFn("_validateReclaimAuctionNames") {
87+
INSAuction.DomainAuction[] memory domainAuctions = new INSAuction.DomainAuction[](searchSize);
88+
uint256[] memory reservedIds = new uint256[](searchSize);
89+
for (uint256 i; i < searchSize; ++i) {
90+
reservedIds[i] = rns.tokenOfOwnerByIndex(address(auction), i);
91+
(domainAuctions[i],) = auction.getAuction(reservedIds[i]);
92+
}
93+
94+
uint256 reclaimableAuctionNameId;
95+
for (uint256 i; i < searchSize; ++i) {
96+
if (domainAuctions[i].bid.bidder == address(0x0)) {
97+
reclaimableAuctionNameId = reservedIds[i];
98+
break;
99+
}
100+
}
101+
102+
address to = makeAddr("to");
103+
address[] memory tos = new address[](1);
104+
tos[0] = to;
105+
string memory label = rns.getRecord(reclaimableAuctionNameId).immut.label;
106+
console.log("reclaimable auction label", label);
107+
string[] memory labels = new string[](1);
108+
labels[0] = label;
109+
110+
vm.prank(rnsOperation.owner());
111+
rnsOperation.reclaimUnbiddedNames({ tos: tos, labels: labels, allowFailure: false });
112+
}
113+
114+
function _validateBulkMint() internal logFn("_validateBulkMint") {
115+
address to = makeAddr("to");
116+
address[] memory tos = new address[](1);
117+
tos[0] = to;
118+
string[] memory labels = new string[](1);
119+
labels[0] = "tudo-provip-maximum-utra";
120+
uint64 duration = uint64(3 days);
121+
122+
vm.prank(rnsOperation.owner());
123+
rnsOperation.bulkMint(tos, labels, duration);
124+
125+
uint256 id = uint256(string.concat(labels[0], ".ron").namehash());
126+
assertEq(rns.ownerOf(id), to);
127+
}
128+
129+
function _validateBulkSetProtected() internal logFn("_validateBulkSetProtected") {
130+
string[] memory labels = new string[](1);
131+
labels[0] = "tudo-provip-maximum-utra";
132+
133+
bool shouldProtect = true;
134+
135+
vm.prank(rnsOperation.owner());
136+
rnsOperation.bulkSetProtected(labels, shouldProtect);
137+
138+
uint256 id = uint256(string.concat(labels[0], ".ron").namehash());
139+
assertTrue(rns.getRecord(id).mut.protected);
140+
141+
shouldProtect = false;
142+
143+
vm.prank(rnsOperation.owner());
144+
rnsOperation.bulkSetProtected(labels, shouldProtect);
145+
146+
assertFalse(rns.getRecord(id).mut.protected);
147+
}
148+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.19;
3+
4+
import { console2 as console } from "forge-std/console2.sol";
5+
import { JSONParserLib } from "solady/utils/JSONParserLib.sol";
6+
import { Migration, ISharedArgument } from "../Migration.s.sol";
7+
import { LibRNSDomain } from "@rns-contracts/libraries/LibRNSDomain.sol";
8+
import { INSDomainPrice } from "@rns-contracts/interfaces/INSDomainPrice.sol";
9+
10+
contract Migration__20240215 is Migration {
11+
using JSONParserLib for *;
12+
using LibRNSDomain for *;
13+
14+
string internal constant DATA_PATH = "script/data/517 Community names (Tier 1) - _3 characters.json";
15+
16+
INSDomainPrice.Tier[] internal _tiers;
17+
string[] internal _labels;
18+
19+
constructor() { }
20+
21+
function toLabelHashes(string[] memory labels) internal pure returns (bytes32[] memory) {
22+
bytes32[] memory hashes = new bytes32[](labels.length);
23+
for (uint256 i; i < labels.length; ++i) {
24+
hashes[i] = labels[i].hashLabel();
25+
}
26+
return hashes;
27+
}
28+
29+
function toNameHashes(string[] memory labels) internal pure returns (uint256[] memory) {
30+
uint256[] memory hashes = new uint256[](labels.length);
31+
for (uint256 i; i < labels.length; ++i) {
32+
hashes[i] = uint256(labels[i].namehash());
33+
}
34+
return hashes;
35+
}
36+
37+
function _parseData(string memory path)
38+
internal
39+
view
40+
returns (string[] memory labels, INSDomainPrice.Tier[] memory tiers)
41+
{
42+
string memory raw = vm.readFile(path);
43+
JSONParserLib.Item memory communityNames = raw.parse().at('"communityNames"');
44+
uint256 length = communityNames.size();
45+
console.log("length", length);
46+
47+
labels = new string[](length);
48+
tiers = new INSDomainPrice.Tier[](length);
49+
50+
for (uint256 i; i < length; ++i) {
51+
tiers[i] = INSDomainPrice.Tier(uint8(vm.parseUint(communityNames.at(i).at('"tier"').value().decodeString())));
52+
labels[i] = (communityNames.at(i).at('"domain"').value().decodeString());
53+
}
54+
}
55+
}

0 commit comments

Comments
 (0)