Skip to content

Commit 30fddbf

Browse files
committed
Add initLimitsAndControllerData
1 parent 914de30 commit 30fddbf

2 files changed

Lines changed: 129 additions & 2 deletions

File tree

deploy/PASInit.sol

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,18 @@ interface PASMomLike {
6767
function setAuthority(address) external;
6868
}
6969

70+
struct InitRateLimitConfig {
71+
bytes32 key;
72+
address rateLimits;
73+
uint256 maxAmount;
74+
uint256 slope;
75+
}
76+
77+
struct InitControllerActionConfig {
78+
bytes data;
79+
address controller;
80+
}
81+
7082
library PASInit {
7183

7284
// It is noted that delayed and immediate operations order is non deterministic.
@@ -158,6 +170,29 @@ library PASInit {
158170
}
159171
}
160172

173+
function initLimitsAndControllerData(
174+
PASInstance memory pasInstance,
175+
InitRateLimitConfig[] memory rateLimitConfigs,
176+
InitControllerActionConfig[] memory controllerActionConfigs
177+
) internal {
178+
BeamStateLike beamState = BeamStateLike(pasInstance.beamState);
179+
180+
for (uint256 i; i < rateLimitConfigs.length; i++) {
181+
beamState.addInitRateLimits(
182+
rateLimitConfigs[i].key,
183+
rateLimitConfigs[i].rateLimits,
184+
rateLimitConfigs[i].maxAmount,
185+
rateLimitConfigs[i].slope
186+
);
187+
}
188+
for (uint256 i; i < controllerActionConfigs.length; i++) {
189+
beamState.addInitControllerActions(
190+
controllerActionConfigs[i].data,
191+
controllerActionConfigs[i].controller
192+
);
193+
}
194+
}
195+
161196
function addCoreToChainlog(
162197
DssInstance memory dss,
163198
PASInstance memory pasInstance,

test/Integration.t.sol

Lines changed: 94 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import "dss-test/DssTest.sol";
2020
import { MCD, DssInstance } from "dss-test/MCD.sol";
2121
import { PASInstance } from "deploy/PASInstance.sol";
2222
import { PASDeploy } from "deploy/PASDeploy.sol";
23-
import { PASInit } from "deploy/PASInit.sol";
23+
import { PASInit, InitRateLimitConfig, InitControllerActionConfig } from "deploy/PASInit.sol";
2424
import { BeamState } from "src/BeamState.sol";
2525
import { Configurator, RateLimitsLike } from "src/Configurator.sol";
2626
import { Timelock } from "src/timelock/Timelock.sol";
@@ -265,6 +265,51 @@ contract IntegrationTest is DssTest {
265265
this.initExtras();
266266
}
267267

268+
function testInitLimitsAndControllerData() public {
269+
PASInstance memory freshPas = PASDeploy.deploy(address(this), pauseProxy, MIN_DELAY);
270+
271+
// Setup rate limit configs
272+
InitRateLimitConfig[] memory rlConfigs = new InitRateLimitConfig[](2);
273+
rlConfigs[0] = InitRateLimitConfig({
274+
key: bytes32(0),
275+
rateLimits: SPARK_RATE_LIMITS,
276+
maxAmount: 1_000_000 ether,
277+
slope: 100 ether
278+
});
279+
rlConfigs[1] = InitRateLimitConfig({
280+
key: bytes32(uint256(1)),
281+
rateLimits: address(0x42),
282+
maxAmount: 500_000 ether,
283+
slope: 50 ether
284+
});
285+
286+
// Setup controller action configs
287+
bytes memory actionData1 = abi.encodeWithSelector(bytes4(0xdeadbeef), uint256(123));
288+
bytes memory actionData2 = abi.encodeWithSelector(bytes4(0xcafebabe), address(0x99));
289+
InitControllerActionConfig[] memory caConfigs = new InitControllerActionConfig[](2);
290+
caConfigs[0] = InitControllerActionConfig({data: actionData1, controller: SPARK_CONTROLLER});
291+
caConfigs[1] = InitControllerActionConfig({data: actionData2, controller: address(0)});
292+
293+
BeamState freshBeamState = BeamState(freshPas.beamState);
294+
295+
vm.startPrank(pauseProxy);
296+
PASInit.initLimitsAndControllerData(freshPas, rlConfigs, caConfigs);
297+
vm.stopPrank();
298+
299+
// Verify init rate limits
300+
(uint256 maxAmount0, uint256 slope0) = freshBeamState.initRateLimits(bytes32(0), SPARK_RATE_LIMITS);
301+
assertEq(maxAmount0, 1_000_000 ether, "first rate limit maxAmount");
302+
assertEq(slope0, 100 ether, "first rate limit slope");
303+
304+
(uint256 maxAmount1, uint256 slope1) = freshBeamState.initRateLimits(bytes32(uint256(1)), address(0x42));
305+
assertEq(maxAmount1, 500_000 ether, "second rate limit maxAmount");
306+
assertEq(slope1, 50 ether, "second rate limit slope");
307+
308+
// Verify init controller actions
309+
assertEq(freshBeamState.initControllerActions(keccak256(actionData1), SPARK_CONTROLLER), 1, "first controller action");
310+
assertEq(freshBeamState.initControllerActions(keccak256(actionData2), address(0)), 1, "second controller action");
311+
}
312+
268313
// ============================================================================
269314
// CoreCouncil Direct Actions (IMMEDIATE Role) Tests
270315
// ============================================================================
@@ -872,6 +917,32 @@ contract IntegrationTest is DssTest {
872917
bytes32(uint256(uint160(testRecipient)))
873918
);
874919

920+
// ========================================
921+
// Phase 0: Init some defaults via spell (PASInit.initLimitsAndControllerData)
922+
// ========================================
923+
bytes32 spellRateLimitKey = keccak256("spell-init-key");
924+
bytes memory spellControllerAction = abi.encodeWithSelector(
925+
ControllerLike.setMintRecipient.selector,
926+
uint32(7), // different domain than the timelock-onboarded action
927+
bytes32(uint256(uint160(testRecipient)))
928+
);
929+
{
930+
InitRateLimitConfig[] memory rlConfigs = new InitRateLimitConfig[](1);
931+
rlConfigs[0] = InitRateLimitConfig({
932+
key: spellRateLimitKey,
933+
rateLimits: SPARK_RATE_LIMITS,
934+
maxAmount: 2_000_000e18,
935+
slope: 200_000e18
936+
});
937+
938+
InitControllerActionConfig[] memory caConfigs = new InitControllerActionConfig[](1);
939+
caConfigs[0] = InitControllerActionConfig({data: spellControllerAction, controller: SPARK_CONTROLLER});
940+
941+
vm.startPrank(pauseProxy);
942+
PASInit.initLimitsAndControllerData(pas, rlConfigs, caConfigs);
943+
vm.stopPrank();
944+
}
945+
875946
// ========================================
876947
// Phase 1: Onboard via Timelock (Role 1)
877948
// ========================================
@@ -932,6 +1003,13 @@ contract IntegrationTest is DssTest {
9321003
assertEq(limits.slope, 100_000e18, "init rate limit slope should be set");
9331004
}
9341005
assertTrue(beamState.isControllerActionEnabled(keccak256(setMintRecipientAction), SPARK_CONTROLLER), "controller action should be enabled");
1006+
// Verify spell-configured defaults
1007+
{
1008+
BeamState.DefaultRateLimits memory spellLimits = beamState.getInitRateLimits(spellRateLimitKey, SPARK_RATE_LIMITS);
1009+
assertEq(spellLimits.maxAmount, 2_000_000e18, "spell init rate limit maxAmount should be set");
1010+
assertEq(spellLimits.slope, 200_000e18, "spell init rate limit slope should be set");
1011+
}
1012+
assertTrue(beamState.isControllerActionEnabled(keccak256(spellControllerAction), SPARK_CONTROLLER), "spell controller action should be enabled");
9351013

9361014
// ========================================
9371015
// Phase 2: Grant admin role to configurator and associate cBeam (Role 2 - direct)
@@ -973,6 +1051,20 @@ contract IntegrationTest is DssTest {
9731051
bytes32 expectedRecipient = bytes32(uint256(uint160(testRecipient)));
9741052
assertEq(ControllerLike(SPARK_CONTROLLER).mintRecipients(6), expectedRecipient, "mintRecipient should be set on real controller");
9751053

1054+
// 3c. cBeam sets rate limit using spell-configured defaults
1055+
vm.prank(cBeam);
1056+
configurator.setRateLimit(SPARK_RATE_LIMITS, spellRateLimitKey, 1_500_000e18, 150_000e18);
1057+
{
1058+
RateLimitsLike.RateLimitData memory data = RateLimitsLike(SPARK_RATE_LIMITS).getRateLimitData(spellRateLimitKey);
1059+
assertEq(data.maxAmount, 1_500_000e18, "spell rate limit maxAmount should be set by cBeam on real contract");
1060+
assertEq(data.slope, 150_000e18, "spell rate limit slope should be set by cBeam on real contract");
1061+
}
1062+
1063+
// 3d. cBeam calls spell-configured controller action
1064+
vm.prank(cBeam);
1065+
configurator.callControllerAction(SPARK_CONTROLLER, spellControllerAction);
1066+
assertEq(ControllerLike(SPARK_CONTROLLER).mintRecipients(7), expectedRecipient, "spell mintRecipient should be set on real controller");
1067+
9761068
// ========================================
9771069
// Phase 4: Verify restrictions
9781070
// ========================================
@@ -991,7 +1083,7 @@ contract IntegrationTest is DssTest {
9911083
// 4c. cBeam cannot call non-whitelisted action
9921084
bytes memory nonWhitelistedAction = abi.encodeWithSelector(
9931085
ControllerLike.setMintRecipient.selector,
994-
uint32(7), // different domain
1086+
uint32(8), // domain not whitelisted by either timelock or spell
9951087
bytes32(uint256(uint160(testRecipient)))
9961088
);
9971089
vm.prank(cBeam);

0 commit comments

Comments
 (0)