Skip to content

Commit 60b51f6

Browse files
authored
Spell: Set missing hook wards in spell (#795)
1 parent eefb3b0 commit 60b51f6

File tree

6 files changed

+158
-50
lines changed

6 files changed

+158
-50
lines changed

script/PoolHooks.s.sol

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ contract PoolHooks is BaseDeployer {
3838

3939
uint16 public centrifugeId;
4040

41-
address public freelyTransferableHook;
41+
address public contractUpdater;
4242
address public fullRestrictionsHook;
43+
address public freelyTransferableHook;
4344
Root public root;
4445
Spoke public spoke;
4546
BalanceSheet public balanceSheet;
@@ -48,14 +49,15 @@ contract PoolHooks is BaseDeployer {
4849
function run() external {
4950
EnvConfig memory config = Env.load(vm.envString("NETWORK"));
5051

52+
centrifugeId = config.network.centrifugeId;
53+
5154
root = Root(config.contracts.root);
5255
spoke = Spoke(config.contracts.spoke);
5356
balanceSheet = BalanceSheet(config.contracts.balanceSheet);
5457
poolEscrowFactory = IPoolEscrowProvider(config.contracts.poolEscrowFactory);
5558
freelyTransferableHook = config.contracts.freelyTransferableHook;
5659
fullRestrictionsHook = config.contracts.fullRestrictionsHook;
57-
58-
centrifugeId = config.network.centrifugeId;
60+
contractUpdater = config.contracts.contractUpdater;
5961

6062
GraphQLQuery graphQL = new GraphQLQuery(config.network.graphQLApi());
6163

@@ -88,7 +90,7 @@ contract PoolHooks is BaseDeployer {
8890
string memory params = string.concat(
8991
"limit: 1000,"
9092
"where: {"
91-
" centrifugeId: ", vm.toString(centrifugeId),
93+
" centrifugeId: ", vm.toString(centrifugeId).asJsonString(),
9294
"}"
9395
);
9496

@@ -222,6 +224,7 @@ contract PoolHooks is BaseDeployer {
222224

223225
hook.rely(address(root));
224226
hook.rely(address(spoke));
227+
hook.rely(address(contractUpdater));
225228
hook.deny(msg.sender);
226229
}
227230

script/spell/V2Cleanings.s.sol

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
// SPDX-License-Identifier: BUSL-1.1
22
pragma solidity 0.8.28;
33

4+
import {Root} from "../../src/admin/Root.sol";
5+
46
import "forge-std/Script.sol";
57

68
import {V2CleaningsSpell} from "../../src/spell/V2CleaningsSpell.sol";
9+
import {EnvConfig, Env, prettyEnvString} from "../utils/EnvConfig.s.sol";
710

811
contract V2CleaningsDeployer is Script {
912
function run() external {
@@ -20,16 +23,19 @@ contract V2CleaningsExecutor is Script {
2023
address deployer;
2124

2225
function run(V2CleaningsSpell spell) external {
26+
EnvConfig memory config = Env.load(prettyEnvString("NETWORK"));
27+
Root rootV3 = Root(config.contracts.root);
28+
2329
vm.startBroadcast();
2430

25-
migrate(spell);
31+
migrate(spell, rootV3);
2632

2733
vm.stopBroadcast();
2834
}
2935

30-
function migrate(V2CleaningsSpell spell) public {
36+
function migrate(V2CleaningsSpell spell, Root rootV3) public {
3137
vm.label(address(spell), "V2CleaningsSpell");
3238

33-
spell.cast();
39+
spell.cast(rootV3);
3440
}
3541
}

src/deployment/ActionBatchers.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,10 @@ contract NonCoreActionBatcher {
354354
// Rely contractUpdater
355355
report.syncManager.rely(address(report.core.contractUpdater));
356356
report.asyncRequestManager.rely(address(report.core.contractUpdater));
357+
report.freezeOnlyHook.rely(address(report.core.contractUpdater));
358+
report.fullRestrictionsHook.rely(address(report.core.contractUpdater));
359+
report.freelyTransferableHook.rely(address(report.core.contractUpdater));
360+
report.redemptionRestrictionsHook.rely(address(report.core.contractUpdater));
357361

358362
// Rely hub
359363
report.batchRequestManager.rely(address(report.core.hub));

src/spell/V2CleaningsSpell.sol

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ import {IERC20} from "../misc/interfaces/IERC20.sol";
77
import {Root} from "../admin/Root.sol";
88

99
Root constant ROOT_V2 = Root(0x0C1fDfd6a1331a875EA013F3897fc8a76ada5DfC);
10-
Root constant ROOT_V3 = Root(0x7Ed48C31f2fdC40d37407cBaBf0870B2b688368f);
10+
11+
address constant CONTRACT_UPDATER = 0x3B150B19245D2C366bc8f18c775b725DFB298F71;
12+
address constant FREEZE_ONLY_HOOK = 0xd5B243F05b2906F1f6C80c6096945faADa0731C1;
13+
address constant FULL_RESTRICTIONS_HOOK = 0x8E680873b4C77e6088b4Ba0aBD59d100c3D224a4;
14+
address constant FREELY_TRANSFERABLE_HOOK = 0x2a9B9C14851Baf7AD19f26607C9171CA1E7a1A61;
15+
address constant REDEMPTION_RESTRICTIONS_HOOK = 0xE5423eD8602Fa0F263e17b6212d88Efe42317f06;
1116

1217
address constant CFG = 0xcccCCCcCCC33D538DBC2EE4fEab0a7A1FF4e8A94;
1318
address constant WCFG = 0xc221b7E65FfC80DE234bbB6667aBDd46593D34F0;
@@ -38,45 +43,52 @@ contract V2CleaningsSpell {
3843
bool public done;
3944
string public constant description = "Pending cleanings from V2";
4045

41-
function cast() external {
46+
function cast(Root rootV3) external {
4247
require(!done, "Spell already executed");
4348
done = true;
4449

45-
_updateCFGWards();
46-
_disableRootV2FromShareTokensV2();
50+
_updateCFGWards(rootV3);
51+
_disableRootV2FromShareTokensV2(rootV3);
4752
_moveFundsFromEscrowToTreasury();
53+
_relyContractUpdaterOnHooks(rootV3);
4854

49-
ROOT_V2.deny(address(this));
50-
ROOT_V3.deny(address(this));
55+
if (address(ROOT_V2).code.length > 0) {
56+
ROOT_V2.deny(address(this));
57+
}
58+
rootV3.deny(address(this));
5159
}
5260

53-
function _updateCFGWards() internal {
61+
function _updateCFGWards(Root rootV3) internal {
5462
// Check if CFG exists
5563
if (CFG.code.length > 0) {
5664
// Mainnet CFG only has the v2 root relied, need to replace with v3 root
5765
if (block.chainid == ETHEREUM_CHAIN_ID) {
58-
ROOT_V2.relyContract(CFG, address(ROOT_V3));
59-
ROOT_V2.relyContract(CFG, CFG_MINTER);
60-
ROOT_V3.denyContract(CFG, IOU_CFG);
61-
ROOT_V3.denyContract(CFG, address(ROOT_V2));
66+
if (address(ROOT_V2).code.length > 0) {
67+
ROOT_V2.relyContract(CFG, address(rootV3));
68+
ROOT_V2.relyContract(CFG, CFG_MINTER);
69+
rootV3.denyContract(CFG, address(ROOT_V2));
70+
}
71+
rootV3.denyContract(CFG, IOU_CFG);
6272
}
6373

6474
// Deny CREATE3 proxy on new chains
6575
if (block.chainid != ETHEREUM_CHAIN_ID) {
66-
ROOT_V3.denyContract(CFG, CREATE3_PROXY);
76+
rootV3.denyContract(CFG, CREATE3_PROXY);
6777
}
6878
}
6979

7080
// Check if WCFG exists (only in Ethereum)
7181
if (WCFG.code.length > 0) {
72-
Root(ROOT_V2).relyContract(WCFG, address(ROOT_V3));
73-
ROOT_V3.denyContract(WCFG, WCFG_MULTISIG);
74-
ROOT_V3.denyContract(WCFG, CHAINBRIDGE_ERC20_HANDLER);
75-
ROOT_V3.denyContract(WCFG, address(ROOT_V2));
82+
if (address(ROOT_V2).code.length > 0) {
83+
Root(ROOT_V2).relyContract(WCFG, address(rootV3));
84+
rootV3.denyContract(WCFG, address(ROOT_V2));
85+
}
86+
rootV3.denyContract(WCFG, WCFG_MULTISIG);
87+
rootV3.denyContract(WCFG, CHAINBRIDGE_ERC20_HANDLER);
7688
}
7789
}
7890

79-
function _disableRootV2FromShareTokensV2() internal {
91+
function _disableRootV2FromShareTokensV2(Root rootV3) internal {
8092
address[] memory shareTokens = new address[](2);
8193
shareTokens[0] = TRANCHE_JTRSY;
8294
shareTokens[1] = TRANCHE_JAAA;
@@ -87,11 +99,11 @@ contract V2CleaningsSpell {
8799
// forgefmt: disable-next-item
88100
if (address(shareTokenV2).code.length > 0 &&
89101
shareTokenV2.wards(address(ROOT_V2)) == 1 &&
90-
shareTokenV2.wards(address(ROOT_V3)) == 1
102+
shareTokenV2.wards(address(rootV3)) == 1
91103
) {
92-
ROOT_V3.relyContract(address(shareTokenV2), address(this));
104+
rootV3.relyContract(address(shareTokenV2), address(this));
93105
shareTokenV2.deny(address(ROOT_V2));
94-
ROOT_V3.denyContract(address(shareTokenV2), address(this));
106+
rootV3.denyContract(address(shareTokenV2), address(this));
95107
}
96108
}
97109
}
@@ -105,6 +117,8 @@ contract V2CleaningsSpell {
105117
usdc = USDC_BASE;
106118
} else if (block.chainid == ARBITRUM_CHAIN_ID) {
107119
usdc = USDC_ARBITRUM;
120+
} else {
121+
return;
108122
}
109123

110124
ROOT_V2.relyContract(address(ESCROW_V2), address(this));
@@ -115,4 +129,11 @@ contract V2CleaningsSpell {
115129
ROOT_V2.denyContract(address(ESCROW_V2), address(this));
116130
}
117131
}
132+
133+
function _relyContractUpdaterOnHooks(Root rootV3) internal {
134+
rootV3.relyContract(FREEZE_ONLY_HOOK, CONTRACT_UPDATER);
135+
rootV3.relyContract(FULL_RESTRICTIONS_HOOK, CONTRACT_UPDATER);
136+
rootV3.relyContract(FREELY_TRANSFERABLE_HOOK, CONTRACT_UPDATER);
137+
rootV3.relyContract(REDEMPTION_RESTRICTIONS_HOOK, CONTRACT_UPDATER);
138+
}
118139
}

test/integration/Deployer.t.sol

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,9 +554,11 @@ contract FullDeploymentTestNonCore is FullDeploymentConfigTest {
554554
// permissions set correctly
555555
vm.assume(nonWard != address(root));
556556
vm.assume(nonWard != address(spoke));
557+
vm.assume(nonWard != address(contractUpdater));
557558

558559
assertEq(freezeOnlyHook.wards(address(root)), 1);
559560
assertEq(freezeOnlyHook.wards(address(spoke)), 1);
561+
assertEq(freezeOnlyHook.wards(address(contractUpdater)), 1);
560562
assertEq(freezeOnlyHook.wards(nonWard), 0);
561563

562564
// dependencies set correctly
@@ -567,9 +569,11 @@ contract FullDeploymentTestNonCore is FullDeploymentConfigTest {
567569
// permissions set correctly
568570
vm.assume(nonWard != address(root));
569571
vm.assume(nonWard != address(spoke));
572+
vm.assume(nonWard != address(contractUpdater));
570573

571574
assertEq(redemptionRestrictionsHook.wards(address(root)), 1);
572575
assertEq(redemptionRestrictionsHook.wards(address(spoke)), 1);
576+
assertEq(redemptionRestrictionsHook.wards(address(contractUpdater)), 1);
573577
assertEq(redemptionRestrictionsHook.wards(nonWard), 0);
574578

575579
// dependencies set correctly
@@ -580,9 +584,11 @@ contract FullDeploymentTestNonCore is FullDeploymentConfigTest {
580584
// permissions set correctly
581585
vm.assume(nonWard != address(root));
582586
vm.assume(nonWard != address(spoke));
587+
vm.assume(nonWard != address(contractUpdater));
583588

584589
assertEq(freelyTransferableHook.wards(address(root)), 1);
585590
assertEq(freelyTransferableHook.wards(address(spoke)), 1);
591+
assertEq(freelyTransferableHook.wards(address(contractUpdater)), 1);
586592
assertEq(freelyTransferableHook.wards(nonWard), 0);
587593

588594
// dependencies set correctly
@@ -593,9 +599,11 @@ contract FullDeploymentTestNonCore is FullDeploymentConfigTest {
593599
// permissions set correctly
594600
vm.assume(nonWard != address(root));
595601
vm.assume(nonWard != address(spoke));
602+
vm.assume(nonWard != address(contractUpdater));
596603

597604
assertEq(fullRestrictionsHook.wards(address(root)), 1);
598605
assertEq(fullRestrictionsHook.wards(address(spoke)), 1);
606+
assertEq(fullRestrictionsHook.wards(address(contractUpdater)), 1);
599607
assertEq(fullRestrictionsHook.wards(nonWard), 0);
600608

601609
// dependencies set correctly

0 commit comments

Comments
 (0)