Skip to content

Commit ac8e162

Browse files
committed
chore: update permission mechanism
1 parent 77907d8 commit ac8e162

9 files changed

Lines changed: 56 additions & 22 deletions

File tree

contracts/PoolSelector.sol

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,15 @@ contract PoolSelector is IPoolSelector, AccessControlUpgradeable {
108108

109109
/**
110110
* @notice update the target weights of existing pools
111-
* @dev only `CONFIGURATOR's` can call,
111+
* @dev only authorised callers can call,
112112
* @param _poolTargets new target weights of pools
113113
* `_poolTargets` array provide pool target in the same order of poolIDs that are stored in poolIdArray of poolUtils
114114
*/
115115
function updatePoolWeights(uint256[] calldata _poolTargets) external {
116-
UtilLib.onlyConfiguratorRole(msg.sender, staderConfig);
116+
if (!staderConfig.isAllowedToCall(msg.sender, "updatePoolWeights(uint256[])")) {
117+
revert AccessDenied(msg.sender);
118+
}
119+
117120
uint8[] memory poolIdArray = IPoolUtils(staderConfig.getPoolUtils()).getPoolIdArray();
118121
uint256 poolCount = poolIdArray.length;
119122
uint256 poolTargetLength = _poolTargets.length;

contracts/PoolUtils.sol

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,10 @@ contract PoolUtils is IPoolUtils, AccessControlUpgradeable {
7070
* @dev emit an event containing validator pubkey for offchain to exit the validator
7171
*/
7272
function processValidatorExitList(bytes[] calldata _pubkeys) external override {
73-
UtilLib.onlyConfiguratorRole(msg.sender, staderConfig);
73+
if (!staderConfig.isAllowedToCall(msg.sender, "processValidatorExitList(bytes[])")) {
74+
revert AccessDenied(msg.sender);
75+
}
76+
7477
uint256 exitValidatorCount = _pubkeys.length;
7578
for (uint256 i; i < exitValidatorCount; ) {
7679
emit ExitValidator(_pubkeys[i]);

contracts/StaderConfig.sol

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,6 @@ contract StaderConfig is IStaderConfig, AccessControlUpgradeable {
8080
bytes32 public constant override SD_UTILITY_POOL = keccak256("SD_UTILITY_POOL");
8181
bytes32 public constant override SD_INCENTIVE_CONTROLLER = keccak256("SD_INCENTIVE_CONTROLLER");
8282

83-
// Role define to manage pools config
84-
bytes32 public constant override CONFIGURATOR = keccak256("CONFIGURATOR");
85-
8683
/// @custom:oz-upgrades-unsafe-allow constructor
8784
constructor() {
8885
_disableInitializers();
@@ -300,6 +297,27 @@ contract StaderConfig is IStaderConfig, AccessControlUpgradeable {
300297
setContract(SD_INCENTIVE_CONTROLLER, _sdIncentiveController);
301298
}
302299

300+
// Access Control
301+
function giveCallPermission(
302+
address contractAddress,
303+
string calldata functionSig,
304+
address accountToPermit
305+
) external override onlyRole(DEFAULT_ADMIN_ROLE) {
306+
bytes32 role = keccak256(abi.encodePacked(contractAddress, functionSig));
307+
grantRole(role, accountToPermit);
308+
emit PermissionGranted(accountToPermit, contractAddress, functionSig);
309+
}
310+
311+
function revokeCallPermission(
312+
address contractAddress,
313+
string calldata functionSig,
314+
address accountToRevoke
315+
) external override onlyRole(DEFAULT_ADMIN_ROLE) {
316+
bytes32 role = keccak256(abi.encodePacked(contractAddress, functionSig));
317+
revokeRole(role, accountToRevoke);
318+
emit PermissionRevoked(accountToRevoke, contractAddress, functionSig);
319+
}
320+
303321
//Constants Getters
304322

305323
function getStakedEthPerNode() external view override returns (uint256) {
@@ -540,8 +558,9 @@ contract StaderConfig is IStaderConfig, AccessControlUpgradeable {
540558
return hasRole(OPERATOR, account);
541559
}
542560

543-
function onlyConfiguratorRole(address account) external view override returns (bool) {
544-
return hasRole(CONFIGURATOR, account);
561+
function isAllowedToCall(address account, string calldata functionSig) external view override returns (bool) {
562+
bytes32 role = keccak256(abi.encodePacked(msg.sender, functionSig));
563+
return hasRole(role, account);
545564
}
546565

547566
function verifyDepositAndWithdrawLimits() internal view {

contracts/interfaces/IPoolSelector.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ interface IPoolSelector {
66
error InvalidTargetWeight();
77
error InvalidNewTargetInput();
88
error InvalidSumOfPoolWeights();
9+
error AccessDenied(address account);
910

1011
// Events
1112

contracts/interfaces/IPoolUtils.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ interface IPoolUtils {
1414
error OperatorIsNotOnboarded();
1515
error InvalidLengthOfSignature();
1616
error ExistingOrMismatchingPoolId();
17+
error AccessDenied(address account);
1718

1819
// Events
1920
event PoolAdded(uint8 indexed poolId, address poolAddress);

contracts/interfaces/IStaderConfig.sol

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ interface IStaderConfig {
1616
event SetAccount(bytes32 key, address newAddress);
1717
event SetContract(bytes32 key, address newAddress);
1818
event SetToken(bytes32 key, address newAddress);
19+
event PermissionGranted(address indexed accountToPermit, address indexed contractAddress, string functionSig);
20+
event PermissionRevoked(address indexed accountToRevoke, address indexed contractAddress, string functionSig);
1921

2022
//Contracts
2123
function POOL_UTILS() external view returns (bytes32);
@@ -74,8 +76,6 @@ interface IStaderConfig {
7476

7577
function OPERATOR() external view returns (bytes32);
7678

77-
function CONFIGURATOR() external view returns (bytes32);
78-
7979
// Constants
8080
function getStakedEthPerNode() external view returns (uint256);
8181

@@ -174,5 +174,13 @@ interface IStaderConfig {
174174

175175
function onlyOperatorRole(address account) external view returns (bool);
176176

177-
function onlyConfiguratorRole(address account) external view returns (bool);
177+
function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);
178+
179+
function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;
180+
181+
function revokeCallPermission(
182+
address contractAddress,
183+
string calldata functionSig,
184+
address accountToRevoke
185+
) external;
178186
}

contracts/library/UtilLib.sol

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ library UtilLib {
1414
error CallerNotStaderContract();
1515
error CallerNotWithdrawVault();
1616
error TransferFailed();
17-
error CallerNotConfigurator();
1817

1918
uint64 private constant VALIDATOR_PUBKEY_LENGTH = 48;
2019

@@ -36,12 +35,6 @@ library UtilLib {
3635
}
3736
}
3837

39-
function onlyConfiguratorRole(address _addr, IStaderConfig _staderConfig) internal view {
40-
if (!_staderConfig.onlyConfiguratorRole(_addr)) {
41-
revert CallerNotConfigurator();
42-
}
43-
}
44-
4538
//checks if caller is a stader contract address
4639
function onlyStaderContract(address _addr, IStaderConfig _staderConfig, bytes32 _contractName) internal view {
4740
if (!_staderConfig.onlyStaderContract(_addr, _contractName)) {

test/foundry_tests/PoolSelector.t.sol

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ contract PoolSelectorTest is Test {
1717
address staderManager;
1818
address operator;
1919
address configurator;
20+
address naiveAddress;
2021

2122
address staderStakePoolManager;
2223

@@ -30,6 +31,7 @@ contract PoolSelectorTest is Test {
3031
staderManager = vm.addr(101);
3132
operator = vm.addr(102);
3233
configurator = vm.addr(116);
34+
naiveAddress = vm.addr(117);
3335
staderStakePoolManager = vm.addr(110);
3436

3537
address ethDepositAddr = vm.addr(103);
@@ -61,7 +63,7 @@ contract PoolSelectorTest is Test {
6163
staderConfig.updateStakePoolManager(staderStakePoolManager);
6264
staderConfig.grantRole(staderConfig.MANAGER(), staderManager);
6365
staderConfig.grantRole(staderConfig.OPERATOR(), operator);
64-
staderConfig.grantRole(staderConfig.CONFIGURATOR(), configurator);
66+
staderConfig.giveCallPermission(address(poolSelector), "updatePoolWeights(uint256[])", configurator);
6567
vm.stopPrank();
6668
}
6769

@@ -98,7 +100,8 @@ contract PoolSelectorTest is Test {
98100
invalidSizePoolWeight[1] = 4000;
99101
invalidSizePoolWeight[2] = 4000;
100102

101-
vm.expectRevert(UtilLib.CallerNotConfigurator.selector);
103+
vm.prank(naiveAddress);
104+
vm.expectRevert(abi.encodeWithSignature("AccessDenied(address)", naiveAddress));
102105
poolSelector.updatePoolWeights(poolWeight);
103106

104107
vm.startPrank(configurator);

test/foundry_tests/PoolUtils.t.sol

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ contract PoolUtilsTest is Test {
1818
address staderManager;
1919
address operator;
2020
address configurator;
21+
address naiveAddress;
2122

2223
PoolUtils poolUtils;
2324
StaderConfig staderConfig;
@@ -33,6 +34,7 @@ contract PoolUtilsTest is Test {
3334
staderManager = vm.addr(101);
3435
operator = vm.addr(102);
3536
configurator = vm.addr(114);
37+
naiveAddress = vm.addr(117);
3638

3739
address ethDepositAddr = vm.addr(103);
3840
nodeRegistry = new NodeRegistryMock(operator);
@@ -61,7 +63,7 @@ contract PoolUtilsTest is Test {
6163
vm.startPrank(staderAdmin);
6264
staderConfig.grantRole(staderConfig.MANAGER(), staderManager);
6365
staderConfig.grantRole(staderConfig.OPERATOR(), operator);
64-
staderConfig.grantRole(staderConfig.CONFIGURATOR(), configurator);
66+
staderConfig.giveCallPermission(address(poolUtils), "processValidatorExitList(bytes[])", configurator);
6567
vm.stopPrank();
6668
}
6769

@@ -137,7 +139,8 @@ contract PoolUtilsTest is Test {
137139
pubkey[0] = "0x8faa339ba46c649885ea0fc9c34d32f9d99c5bde336750";
138140
pubkey[1] = "0x8faa339ba46c649885ea0fc9c34d32f9d99c5bde336750";
139141

140-
vm.expectRevert(UtilLib.CallerNotConfigurator.selector);
142+
vm.prank(naiveAddress);
143+
vm.expectRevert(abi.encodeWithSignature("AccessDenied(address)", naiveAddress));
141144
poolUtils.processValidatorExitList(pubkey);
142145

143146
vm.prank(configurator);

0 commit comments

Comments
 (0)