Skip to content

Commit aa2dcd5

Browse files
committed
feat: add update default pod controller method
1 parent e35bcf9 commit aa2dcd5

File tree

7 files changed

+94
-10
lines changed

7 files changed

+94
-10
lines changed

contracts/pods/PodFactory.sol

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ contract PodFactory is CoreRef, IPodFactory {
2727
PodExecutor public immutable podExecutor;
2828

2929
/// @notice Constant podController used to create pods
30-
ControllerV1 public immutable defaultPodController;
30+
ControllerV1 public override defaultPodController;
3131

3232
/// @notice Mapping between podId and it's timelock
3333
mapping(uint256 => address) public override getPodTimelock;
@@ -87,10 +87,7 @@ contract PodFactory is CoreRef, IPodFactory {
8787
override
8888
returns (ControllerV1)
8989
{
90-
ControllerV1 podController = ControllerV1(
91-
memberToken.memberController(podId)
92-
);
93-
return podController;
90+
return ControllerV1(memberToken.memberController(podId));
9491
}
9592

9693
/// @notice Get the address of the Gnosis safe that represents a pod
@@ -215,6 +212,20 @@ contract PodFactory is CoreRef, IPodFactory {
215212
return (podId, timelock, safe);
216213
}
217214

215+
/// @notice Update the default pod controller
216+
function updateDefaultPodController(address _newDefaultController)
217+
external
218+
override
219+
hasAnyOfTwoRoles(TribeRoles.GOVERNOR, TribeRoles.POD_ADMIN)
220+
{
221+
address oldDefaultController = address(defaultPodController);
222+
defaultPodController = ControllerV1(_newDefaultController);
223+
emit UpdateDefaultPodController(
224+
oldDefaultController,
225+
_newDefaultController
226+
);
227+
}
228+
218229
//////////////////////// INTERNAL ////////////////////////////
219230

220231
/// @notice Internal method to create a child optimistic pod

contracts/pods/interfaces/IPodFactory.sol

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ interface IPodFactory {
3333
address indexed newController
3434
);
3535

36+
event UpdateDefaultPodController(
37+
address indexed oldController,
38+
address indexed newController
39+
);
40+
3641
function deployCouncilPod(PodConfig calldata _config)
3742
external
3843
returns (
@@ -41,6 +46,8 @@ interface IPodFactory {
4146
address
4247
);
4348

49+
function defaultPodController() external view returns (ControllerV1);
50+
4451
function getMemberToken() external view returns (MemberToken);
4552

4653
function getPodSafeAddresses() external view returns (address[] memory);
@@ -81,4 +88,6 @@ interface IPodFactory {
8188
address,
8289
address
8390
);
91+
92+
function updateDefaultPodController(address _newDefaultController) external;
8493
}

contracts/test/integration/fixtures/MainnetAddresses.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ library MainnetAddresses {
88
address public constant TRIBE = 0xc7283b66Eb1EB5FB86327f08e1B5816b0720212B;
99
address public constant MEMBER_TOKEN =
1010
0x0762aA185b6ed2dCA77945Ebe92De705e0C37AE3;
11-
address public constant POD_CONTROLLER =
11+
address public constant ORCA_POD_CONTROLLER_V1 =
12+
0xD89AAd5348A34E440E72f5F596De4fA7e291A3e8;
13+
address public constant ORCA_POD_CONTROLLER_V1_2 =
1214
0x17FDC2Eaf2bd46f3e1052CCbccD9e6AD0296C42c;
1315
}

contracts/test/integration/governance/NopeDAO.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ contract NopeDAOIntegrationTest is DSTest {
6262
podConfig
6363
) = deployPodWithSystem(
6464
MainnetAddresses.CORE,
65-
MainnetAddresses.POD_CONTROLLER,
65+
MainnetAddresses.ORCA_POD_CONTROLLER_V1_2,
6666
MainnetAddresses.MEMBER_TOKEN,
6767
podExecutor,
6868
MainnetAddresses.FEI_DAO_TIMELOCK,

contracts/test/integration/governance/OptimisticPodTest.t.sol

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ contract OptimisticPodIntegrationTest is DSTest {
2222

2323
MemberToken memberToken = MemberToken(MainnetAddresses.MEMBER_TOKEN);
2424

25-
ControllerV1 controller = ControllerV1(MainnetAddresses.POD_CONTROLLER);
25+
ControllerV1 controller =
26+
ControllerV1(MainnetAddresses.ORCA_POD_CONTROLLER_V1_2);
2627

2728
address proposer = address(0x1);
2829
address executor = address(0x2);

contracts/test/integration/governance/PodAdminGateway.t.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ contract PodAdminGatewayIntegrationTest is DSTest {
2929

3030
address core = MainnetAddresses.CORE;
3131
address memberToken = MainnetAddresses.MEMBER_TOKEN;
32-
address podController = MainnetAddresses.POD_CONTROLLER;
32+
address podController = MainnetAddresses.ORCA_POD_CONTROLLER_V1_2;
3333
address feiDAOTimelock = MainnetAddresses.FEI_DAO_TIMELOCK;
3434

3535
function setUp() public {

contracts/test/integration/governance/PodFactory.t.sol

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ pragma solidity ^0.8.0;
33

44
import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol";
55
import {ControllerV1} from "@orcaprotocol/contracts/contracts/ControllerV1.sol";
6+
import {MemberToken} from "@orcaprotocol/contracts/contracts/MemberToken.sol";
67
import {IGnosisSafe} from "../../../pods/interfaces/IGnosisSafe.sol";
78
import {PodFactory} from "../../../pods/PodFactory.sol";
89
import {PodExecutor} from "../../../pods/PodExecutor.sol";
@@ -31,7 +32,7 @@ contract PodFactoryIntegrationTest is DSTest {
3132

3233
address core = MainnetAddresses.CORE;
3334
address memberToken = MainnetAddresses.MEMBER_TOKEN;
34-
address podController = MainnetAddresses.POD_CONTROLLER;
35+
address podController = MainnetAddresses.ORCA_POD_CONTROLLER_V1_2;
3536
address feiDAOTimelock = MainnetAddresses.FEI_DAO_TIMELOCK;
3637

3738
function setUp() public {
@@ -69,6 +70,7 @@ contract PodFactoryIntegrationTest is DSTest {
6970
assertEq(address(factory.podExecutor()), address(podExecutor));
7071
assertEq(address(factory.getMemberToken()), memberToken);
7172
assertEq(factory.MIN_TIMELOCK_DELAY(), 1 days);
73+
assertEq(address(factory.defaultPodController()), podController);
7274

7375
address[] memory podSafeAddresses = factory.getPodSafeAddresses();
7476
assertEq(podSafeAddresses.length, 0);
@@ -406,4 +408,63 @@ contract PodFactoryIntegrationTest is DSTest {
406408
assertTrue(timelockContract.isOperationDone(txHash));
407409
assertEq(dummyContract.getVariable(), newDummyContractVar);
408410
}
411+
412+
/// @notice Validate that the default pod controller can be updated
413+
function testUpdateDefaultPodController() public {
414+
address newDefaultPodController = address(0x123);
415+
vm.prank(feiDAOTimelock);
416+
factory.updateDefaultPodController(newDefaultPodController);
417+
assertEq(
418+
address(factory.defaultPodController()),
419+
newDefaultPodController
420+
);
421+
}
422+
423+
/// @notice Validate that a pod controller can be updated and that will be reflected
424+
/// on the pod factory
425+
function testPodControllerUpdate() public {
426+
IPodFactory.PodConfig memory podConfig = getPodParamsWithTimelock(
427+
podAdmin
428+
);
429+
430+
// Set default to old version, to create pod with old controller
431+
vm.prank(feiDAOTimelock);
432+
factory.updateDefaultPodController(
433+
MainnetAddresses.ORCA_POD_CONTROLLER_V1
434+
);
435+
assertEq(
436+
address(factory.defaultPodController()),
437+
MainnetAddresses.ORCA_POD_CONTROLLER_V1
438+
);
439+
440+
vm.prank(feiDAOTimelock);
441+
(uint256 podId, address timelock, address safe) = factory
442+
.deployCouncilPod(podConfig);
443+
444+
// 1. Get pod controller
445+
address defaultPodController = address(factory.defaultPodController());
446+
address initialPodController = address(factory.getPodController(podId));
447+
assertEq(defaultPodController, initialPodController);
448+
449+
// 2. Pod migrates it's own pod controller to another minor version
450+
vm.prank(safe);
451+
ControllerV1(initialPodController).migratePodController(
452+
podId,
453+
MainnetAddresses.ORCA_POD_CONTROLLER_V1_2,
454+
MainnetAddresses.ORCA_POD_CONTROLLER_V1_2
455+
);
456+
457+
// 3. Verify pod's controller was updated on the memberToken and factory
458+
address newPodControllerOnFactory = address(
459+
factory.getPodController(podId)
460+
);
461+
address expectedNewPodController = MemberToken(memberToken)
462+
.memberController(podId);
463+
464+
assertEq(expectedNewPodController, newPodControllerOnFactory);
465+
assertEq(
466+
newPodControllerOnFactory,
467+
MainnetAddresses.ORCA_POD_CONTROLLER_V1_2
468+
);
469+
}
409470
}

0 commit comments

Comments
 (0)