Skip to content

Commit 755e25b

Browse files
committed
Initial access manager setup
1 parent bf17f44 commit 755e25b

17 files changed

+963
-46
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ docs/
1212

1313
# Dotenv file
1414
.env
15+
.DS_Store

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[submodule "lib/forge-std"]
22
path = lib/forge-std
33
url = https://github.com/foundry-rs/forge-std
4+
[submodule "lib/openzeppelin-contracts"]
5+
path = lib/openzeppelin-contracts
6+
url = https://github.com/OpenZeppelin/openzeppelin-contracts

foundry.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@ libs = ["lib"]
66
fs_permissions = [{ access = "read", path = "./"}]
77

88
# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
9+
10+
remappings = [
11+
"forge-std/=lib/forge-std/src/",
12+
"@openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
13+
]

lib/openzeppelin-contracts

Submodule openzeppelin-contracts added at e4f7021

roles-configuration.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"admin": "0xDE2974737dcE6FCce14924C87506b6249E3Bf189",
3+
"customExternalCallers": [
4+
"0xC0896ab1A8cae8c2C1d27d011eb955Cca955580d",
5+
"0xDE2974737dcE6FCce14924C87506b6249E3Bf189"
6+
],
7+
"pufferOpsMultisig": "0xC0896ab1A8cae8c2C1d27d011eb955Cca955580d",
8+
"vault": "0x2ce0b4c55be864c9c5dfc71bcd522dec9378f368",
9+
"withdrawalManager": "0xDE2974737dcE6FCce14924C87506b6249E3Bf189"
10+
}

script/CustomExternalCallNonRestakingValidators.s.sol

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ interface IBeaconDepositContract {
1818
) external payable;
1919
}
2020

21-
// forge script script/CustomExternalCallNonRestakingValidators.s.sol:CustomExternalCallNonRestakingValidators --rpc-url=$HOLESKY_RPC_URL --account institutional-deployer-testnet -vvvv --sig "run(address,string)" 0x205A6BCF458a40E1a30a000166c793Ec54b0d9D5 example
22-
// add --broadcast to broadcast the transaction
21+
// forge script script/CustomExternalCallNonRestakingValidators.s.sol:CustomExternalCallNonRestakingValidators --rpc-url=$HOLESKY_RPC_URL --account institutional-deployer-testnet -vvvv --sig "run(string)" depositfilename
22+
// This script assumes that the calldata will be executed on mainnet, so the beacon deposit contract address is hardcoded
2323
contract CustomExternalCallNonRestakingValidators is Script {
2424
using stdJson for string;
2525

@@ -42,23 +42,36 @@ contract CustomExternalCallNonRestakingValidators is Script {
4242
string withdrawal_credentials;
4343
}
4444

45+
struct RolesConfiguration {
46+
address admin;
47+
address[] customExternalCallers;
48+
address pufferOpsMultisig;
49+
address vault;
50+
address withdrawalManager;
51+
}
52+
4553
bytes pubKey;
4654
bytes withdrawalCredentials;
4755
bytes signature;
4856
bytes32 depositDataRoot;
4957
uint256 amount;
5058

51-
function run(address payable institutionalVaultProxy, string calldata depositFileName) public {
52-
vm.startBroadcast();
59+
function run(string calldata depositFileName) public {
60+
// vm.startBroadcast();
5361

5462
string memory root = vm.projectRoot();
5563
string memory path = string.concat(root, "/validator_deposit_data/0x02/", depositFileName, ".json");
64+
string memory rolesConfigurationPath = string.concat(root, "/roles-configuration.json");
5665

5766
console.log("Path:", path);
67+
console.log("Roles configuration path:", rolesConfigurationPath);
5868

5969
string memory fileContent = vm.readFile(path);
6070
bytes memory rawJson = vm.parseJson(fileContent);
6171

72+
RolesConfiguration memory accessManagerConfiguration =
73+
abi.decode(vm.parseJson(vm.readFile(rolesConfigurationPath)), (RolesConfiguration));
74+
6275
ValidatorDepositData[] memory depositData = abi.decode(rawJson, (ValidatorDepositData[]));
6376

6477
for (uint256 i = 0; i < depositData.length; i++) {
@@ -71,12 +84,22 @@ contract CustomExternalCallNonRestakingValidators is Script {
7184
IBeaconDepositContract.deposit, (pubKey, withdrawalCredentials, signature, depositDataRoot)
7285
);
7386

74-
// TODO: Custom external call directly to the beacon deposit contract
75-
IInstitutionalVault(institutionalVaultProxy).customExternalCall(
76-
0x00000000219ab540356cBB839Cbe05303d7705Fa, data, amount
87+
bytes memory customExternalCallData = abi.encodeCall(
88+
IInstitutionalVault.customExternalCall,
89+
// Hardcoded the beacon deposit contract address
90+
(0x00000000219ab540356cBB839Cbe05303d7705Fa, data, amount)
7791
);
92+
93+
console.log("Custom external call to the beacon deposit contract");
94+
console.log("Vault:", accessManagerConfiguration.vault);
95+
console.logBytes(customExternalCallData);
96+
97+
// TODO: Custom external call directly to the beacon deposit contract
98+
// IInstitutionalVault(institutionalVaultProxy).customExternalCall(
99+
// accessManagerConfiguration.vault, data, amount
100+
// );
78101
}
79102

80-
vm.stopBroadcast();
103+
// vm.stopBroadcast();
81104
}
82105
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// SPDX-License-Identifier: GPL-3.0
2+
pragma solidity >=0.8.0 <0.9.0;
3+
4+
import {Script} from "forge-std/Script.sol";
5+
import {stdJson} from "forge-std/StdJson.sol";
6+
import {console} from "forge-std/console.sol";
7+
import {AccessManager} from "@openzeppelin-contracts/access/manager/AccessManager.sol";
8+
import {Multicall} from "@openzeppelin-contracts/utils/Multicall.sol";
9+
import {IInstitutionalVault} from "../src/interface/IInstitutionalVault.sol";
10+
11+
// forge script script/InitialAccessManagerSetup.s.sol:InitialAccessManagerSetup -vvvv
12+
contract InitialAccessManagerSetup is Script {
13+
using stdJson for string;
14+
15+
uint64 public constant ADMIN_ROLE_ID = type(uint64).min; // 0
16+
uint64 public constant DEPOSITOR_ROLE_ID = 1;
17+
uint64 public constant WITHDRAWER_ROLE_ID = 2;
18+
uint64 public constant CUSTOM_EXTERNAL_CALLER_ROLE_ID = 3;
19+
uint64 public constant WITHDRAWAL_MANAGER_ROLE_ID = 4;
20+
uint64 public constant ORACLE_ROLE_ID = 5;
21+
22+
struct RolesConfiguration {
23+
address admin;
24+
address[] customExternalCallers;
25+
address pufferOpsMultisig;
26+
address vault;
27+
address withdrawalManager;
28+
}
29+
30+
function run() public view {
31+
string memory root = vm.projectRoot();
32+
string memory path = string.concat(root, "/roles-configuration.json");
33+
34+
console.log("Path:", path);
35+
36+
string memory fileContent = vm.readFile(path);
37+
bytes memory rawJson = vm.parseJson(fileContent);
38+
39+
RolesConfiguration memory accessManagerConfiguration = abi.decode(rawJson, (RolesConfiguration));
40+
41+
console.log("Access manager institution admin:", address(accessManagerConfiguration.admin));
42+
43+
// Calculate total number of calldatas needed
44+
uint256 totalCalldatas = 14 + accessManagerConfiguration.customExternalCallers.length + 1; // +1 for revoke role
45+
bytes[] memory calldatas = new bytes[](totalCalldatas);
46+
uint256 calldataIndex = 0;
47+
48+
calldatas[calldataIndex++] = abi.encodeCall(AccessManager.labelRole, (DEPOSITOR_ROLE_ID, "Depositor"));
49+
calldatas[calldataIndex++] = abi.encodeCall(AccessManager.labelRole, (WITHDRAWER_ROLE_ID, "Withdrawer"));
50+
calldatas[calldataIndex++] =
51+
abi.encodeCall(AccessManager.labelRole, (CUSTOM_EXTERNAL_CALLER_ROLE_ID, "Custom External Caller"));
52+
calldatas[calldataIndex++] =
53+
abi.encodeCall(AccessManager.labelRole, (WITHDRAWAL_MANAGER_ROLE_ID, "Withdrawal Manager"));
54+
calldatas[calldataIndex++] = abi.encodeCall(AccessManager.labelRole, (ORACLE_ROLE_ID, "Oracle"));
55+
// Grant the admin role to the institution admin, without any delay
56+
calldatas[calldataIndex++] =
57+
abi.encodeCall(AccessManager.grantRole, (ADMIN_ROLE_ID, accessManagerConfiguration.admin, 0));
58+
59+
bytes4[] memory depositorSelectors = new bytes4[](3);
60+
depositorSelectors[0] = IInstitutionalVault.depositETH.selector;
61+
depositorSelectors[1] = IInstitutionalVault.mint.selector;
62+
depositorSelectors[2] = IInstitutionalVault.deposit.selector;
63+
64+
calldatas[calldataIndex++] = abi.encodeCall(
65+
AccessManager.setTargetFunctionRole,
66+
(accessManagerConfiguration.vault, depositorSelectors, DEPOSITOR_ROLE_ID)
67+
);
68+
69+
bytes4[] memory withdrawerSelectors = new bytes4[](2);
70+
withdrawerSelectors[0] = IInstitutionalVault.withdraw.selector;
71+
withdrawerSelectors[1] = IInstitutionalVault.redeem.selector;
72+
73+
calldatas[calldataIndex++] = abi.encodeCall(
74+
AccessManager.setTargetFunctionRole,
75+
(accessManagerConfiguration.vault, withdrawerSelectors, WITHDRAWER_ROLE_ID)
76+
);
77+
78+
bytes4[] memory withdrawalManagerSelectors = new bytes4[](2);
79+
withdrawalManagerSelectors[0] = IInstitutionalVault.queueWithdrawals.selector;
80+
withdrawalManagerSelectors[1] = IInstitutionalVault.completeQueuedWithdrawals.selector;
81+
82+
calldatas[calldataIndex++] = abi.encodeCall(
83+
AccessManager.grantRole, (WITHDRAWAL_MANAGER_ROLE_ID, accessManagerConfiguration.withdrawalManager, 0)
84+
);
85+
86+
calldatas[calldataIndex++] =
87+
abi.encodeCall(AccessManager.grantRole, (ORACLE_ROLE_ID, accessManagerConfiguration.admin, 0));
88+
89+
calldatas[calldataIndex++] = abi.encodeCall(
90+
AccessManager.setTargetFunctionRole,
91+
(accessManagerConfiguration.vault, withdrawalManagerSelectors, WITHDRAWAL_MANAGER_ROLE_ID)
92+
);
93+
94+
calldatas[calldataIndex++] =
95+
abi.encodeCall(AccessManager.grantRole, (DEPOSITOR_ROLE_ID, accessManagerConfiguration.admin, 0));
96+
97+
calldatas[calldataIndex++] =
98+
abi.encodeCall(AccessManager.grantRole, (WITHDRAWER_ROLE_ID, accessManagerConfiguration.admin, 0));
99+
100+
bytes4[] memory customExternalCallerSelectors = new bytes4[](1);
101+
customExternalCallerSelectors[0] = IInstitutionalVault.customExternalCall.selector;
102+
103+
calldatas[calldataIndex++] = abi.encodeCall(
104+
AccessManager.setTargetFunctionRole,
105+
(accessManagerConfiguration.vault, customExternalCallerSelectors, CUSTOM_EXTERNAL_CALLER_ROLE_ID)
106+
);
107+
108+
// Grant the custom external caller role to the custom external callers
109+
for (uint256 i = 0; i < accessManagerConfiguration.customExternalCallers.length; i++) {
110+
calldatas[calldataIndex++] = abi.encodeCall(
111+
AccessManager.grantRole,
112+
(CUSTOM_EXTERNAL_CALLER_ROLE_ID, accessManagerConfiguration.customExternalCallers[i], 0)
113+
);
114+
}
115+
116+
// Revoke the admin role from the puffer ops multisig - Clean up
117+
calldatas[calldataIndex++] =
118+
abi.encodeCall(AccessManager.revokeRole, (ADMIN_ROLE_ID, accessManagerConfiguration.pufferOpsMultisig));
119+
120+
bytes memory encodedMulticall = abi.encodeCall(Multicall.multicall, (calldatas));
121+
122+
console.log("Total calldatas:", totalCalldatas, "calldataIndex:", calldataIndex);
123+
console.log("Encoded multicall:");
124+
console.logBytes(encodedMulticall);
125+
}
126+
}

src/Counter.sol

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)