@@ -179,7 +179,9 @@ contract ExternalStakingDistributor is Implementation, ERC721TokenReceiver {
179179 );
180180 event SetStakingProxyConfigs (address [] stakingProxies , uint256 [] proxyTypes );
181181 event SetManagingAgentStatuses (address [] managingAgents , bool [] statuses );
182- event SetCuratingAgentStatuses (address [] managingAgents , bool [] statuses );
182+ event SetCuratingAgentStatuses (
183+ address indexed stakingGuard , address indexed stakingProxy , address [] managingAgents , bool [] statuses
184+ );
183185 event Deposit (address indexed sender , bytes32 indexed operation , uint256 amount );
184186 event Withdraw (address indexed sender , bytes32 indexed operation , uint256 amount , uint256 unstakeRequestedAmount );
185187 event Claimed (address [] stakingProxies , uint256 [] serviceIds , uint256 [] rewards );
@@ -231,20 +233,23 @@ contract ExternalStakingDistributor is Implementation, ERC721TokenReceiver {
231233 uint256 internal _locked = 1 ;
232234
233235 // Mapping of whitelisted staking proxy address => (staking reward distributions | staking type)
234- // Staking config: collectorRewardFactor 16 bits | protocolRewardFactor 16 bits
236+ // Staking config: stakingGuard 160 bits | collectorRewardFactor 16 bits | protocolRewardFactor 16 bits
235237 // | curatingAgentRewardFactor 16 bits | stakingType 8 bits
236238 mapping (address => uint256 ) public mapStakingProxyConfigs;
237239 // Mapping of unstake requests: unstake operation => amount requested
238240 mapping (bytes32 => uint256 ) public mapUnstakeOperationRequestedAmounts;
239241 // Mapping of service Id => agent address curating it
240242 mapping (uint256 => address ) public mapServiceIdCuratingAgents;
241- // Mapping whitelisted curating agent addresses
243+ // UNUSED for now: Mapping whitelisted curating agent addresses
242244 mapping (address => bool ) public mapCuratingAgents;
243245 // Mapping of whitelisted managing agent addresses
244246 mapping (address => bool ) public mapManagingAgents;
245247 // Mapping of multisig address => service Id
246248 mapping (address => uint256 ) public mapMultisigServiceIds;
247249
250+ // Mapping of (staking guard + staking proxy) hash => whitelisted curating agent addresses
251+ mapping (bytes32 => mapping (address => bool )) public mapStakingGuardHashCuratingAgents;
252+
248253 /// @dev ExternalStakingDistributor constructor.
249254 /// @param _olas OLAS token address.
250255 /// @param _serviceManager Service manager address.
@@ -485,7 +490,7 @@ contract ExternalStakingDistributor is Implementation, ERC721TokenReceiver {
485490 uint256 config = mapStakingProxyConfigs[stakingProxy];
486491
487492 // Unwrap config
488- (uint256 collectorAmount , uint256 protocolAmount ,, StakingType stakingType ) = unwrapStakingConfig (config);
493+ (, uint256 collectorAmount , uint256 protocolAmount ,, StakingType stakingType ) = unwrapStakingConfig (config);
489494
490495 // Calculate reward distribution
491496 collectorAmount = (reward * collectorAmount) / MAX_REWARD_FACTOR;
@@ -580,16 +585,36 @@ contract ExternalStakingDistributor is Implementation, ERC721TokenReceiver {
580585 }
581586 _locked = 2 ;
582587
583- // Check for access: whitelisted curating agent or owner
584- if (! mapCuratingAgents[msg .sender ] && msg .sender != owner) {
585- revert UnauthorizedAccount (msg .sender );
586- }
588+ // Get proxy config value
589+ uint256 config = mapStakingProxyConfigs[stakingProxy];
587590
588591 // Check for whitelisted staking proxy type
589- if (mapStakingProxyConfigs[stakingProxy] == 0 ) {
592+ if (config == 0 ) {
590593 revert ZeroValue ();
591594 }
592595
596+ // If staker is not owner - check for curating agent access
597+ if (msg .sender != owner) {
598+ // Curating agent access is true, if not set otherwise
599+ bool curatingAgentAccess = true ;
600+
601+ // Get staking guard address
602+ (address stakingGuard ,,,,) = unwrapStakingConfig (config);
603+
604+ // Check for msg.sender access
605+ if (stakingGuard != address (0 )) {
606+ // Get staking hash
607+ bytes32 stakingHash = keccak256 (abi.encode (stakingGuard, stakingProxy));
608+ // Check access
609+ curatingAgentAccess = mapStakingGuardHashCuratingAgents[stakingHash][msg .sender ];
610+ }
611+
612+ // Check for access: whitelisted curating agent
613+ if (! curatingAgentAccess) {
614+ revert UnauthorizedAccount (msg .sender );
615+ }
616+ }
617+
593618 // Check for zero value
594619 if (configHash == 0 ) {
595620 revert ZeroValue ();
@@ -760,7 +785,7 @@ contract ExternalStakingDistributor is Implementation, ERC721TokenReceiver {
760785 }
761786
762787 // Check proxy configs
763- (uint256 collectorRewardFactor , uint256 protocolRewardFactor , uint256 curatingAgentRewardFactor ,) =
788+ (, uint256 collectorRewardFactor , uint256 protocolRewardFactor , uint256 curatingAgentRewardFactor ,) =
764789 unwrapStakingConfig (configs[i]);
765790
766791 // Check for collector and zero value
@@ -812,32 +837,48 @@ contract ExternalStakingDistributor is Implementation, ERC721TokenReceiver {
812837
813838 /// @dev Sets curating agents statuses.
814839 /// @notice This is required such that potential malicious agents do not stake for no reason.
840+ /// @notice Contract owner sets stakingProxy config, however this function call is for staking guards only.
841+ /// @param stakingProxy Staking proxy address.
815842 /// @param curatingAgents Set of curating agents.
816843 /// @param statuses Corresponding set of statuses: true / false.
817- function setCuratingAgents (address [] memory curatingAgents , bool [] memory statuses ) external {
818- // Check for the ownership
819- if (msg .sender != owner) {
820- revert OwnerOnly (msg .sender , owner);
821- }
822-
844+ function setCuratingAgents (address stakingProxy , address [] memory curatingAgents , bool [] memory statuses ) external {
823845 // Get number of agents
824846 uint256 numAgents = curatingAgents.length ;
825847 // Check for array length
826848 if (numAgents == 0 || numAgents != statuses.length ) {
827849 revert WrongArrayLength ();
828850 }
829851
852+ // Get proxy config value
853+ uint256 config = mapStakingProxyConfigs[stakingProxy];
854+
855+ // Check for whitelisted staking proxy type
856+ if (config == 0 ) {
857+ revert ZeroValue ();
858+ }
859+
860+ // Get staking guard address
861+ (address stakingGuard ,,,,) = unwrapStakingConfig (config);
862+
863+ // Check for access: only staking guard
864+ if (msg .sender != stakingGuard) {
865+ revert UnauthorizedAccount (msg .sender );
866+ }
867+
830868 // Traverse curating agents
831869 for (uint256 i = 0 ; i < numAgents; ++ i) {
832870 // Check for zero address
833871 if (curatingAgents[i] == address (0 )) {
834872 revert ZeroAddress ();
835873 }
836874
837- mapCuratingAgents[curatingAgents[i]] = statuses[i];
875+ // Encode staking hash
876+ bytes32 stakingHash = keccak256 (abi.encode (stakingGuard, stakingProxy));
877+ // Set curating agent status
878+ mapStakingGuardHashCuratingAgents[stakingHash][curatingAgents[i]] = statuses[i];
838879 }
839880
840- emit SetCuratingAgentStatuses (curatingAgents, statuses);
881+ emit SetCuratingAgentStatuses (stakingGuard, stakingProxy, curatingAgents, statuses);
841882 }
842883
843884 /// @dev Deposits OLAS for further staking.
@@ -962,11 +1003,13 @@ contract ExternalStakingDistributor is Implementation, ERC721TokenReceiver {
9621003 }
9631004
9641005 /// @dev Wraps staking proxy config: reward factors and staking type value.
1006+ /// @param stakingGuard Staking proxy proposer address.
9651007 /// @param collectorRewardFactor Collector reward factor.
9661008 /// @param protocolRewardFactor Protocol reward factor.
9671009 /// @param curatingAgentRewardFactor Curating agent reward factor.
9681010 /// @param stakingType Staking type.
9691011 function wrapStakingConfig (
1012+ address stakingGuard ,
9701013 uint256 collectorRewardFactor ,
9711014 uint256 protocolRewardFactor ,
9721015 uint256 curatingAgentRewardFactor ,
@@ -975,11 +1018,12 @@ contract ExternalStakingDistributor is Implementation, ERC721TokenReceiver {
9751018 // Staking config: collectorRewardFactor 16 bits | protocolRewardFactor 16 bits
9761019 // | curatingAgentRewardFactor 16 bits | stakingType 8 bits
9771020 config = uint8 (stakingType) | curatingAgentRewardFactor << 8 | protocolRewardFactor << 24
978- | collectorRewardFactor << 40 ;
1021+ | collectorRewardFactor << 40 | uint160 (stakingGuard) << 56 ;
9791022 }
9801023
9811024 /// @dev Unwraps staking proxy config: reward factors and staking type value.
9821025 /// @param config Staking proxy config value.
1026+ /// @return stakingGuard Staking proxy proposer address.
9831027 /// @return collectorRewardFactor Collector reward factor.
9841028 /// @return protocolRewardFactor Protocol reward factor.
9851029 /// @return curatingAgentRewardFactor Curating agent reward factor.
@@ -988,15 +1032,17 @@ contract ExternalStakingDistributor is Implementation, ERC721TokenReceiver {
9881032 public
9891033 pure
9901034 returns (
1035+ address stakingGuard ,
9911036 uint256 collectorRewardFactor ,
9921037 uint256 protocolRewardFactor ,
9931038 uint256 curatingAgentRewardFactor ,
9941039 StakingType stakingType
9951040 )
9961041 {
997- // Staking config: collectorRewardFactor 16 bits | protocolRewardFactor 16 bits
1042+ // Staking config: stakingGuard 160 bits | collectorRewardFactor 16 bits | protocolRewardFactor 16 bits
9981043 // | curatingAgentRewardFactor 16 bits | stakingType 8 bits
999- collectorRewardFactor = config >> 40 ;
1044+ stakingGuard = address (uint160 (config >> 56 ));
1045+ collectorRewardFactor = uint16 (config >> 40 );
10001046 protocolRewardFactor = uint16 (config >> 24 );
10011047 curatingAgentRewardFactor = uint16 (config >> 8 );
10021048 stakingType = StakingType (uint8 (config));
0 commit comments