-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
Delegation ID
- Loading branch information
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,14 +28,12 @@ abstract contract PoSValidatorManager is IPoSValidatorManager, ValidatorManager | |
uint64 _minimumStakeDuration; | ||
/// @notice The reward calculator for this validator manager. | ||
IRewardCalculator _rewardCalculator; | ||
/// @notice Maps the validationID to a mapping of delegator address to delegator information. | ||
mapping(bytes32 validationID => mapping(address delegator => Delegator)) _delegatorStakes; | ||
/// @notice Maps the validationID to a mapping of delegator address to pending register delegator messages. | ||
mapping(bytes32 validationID => mapping(address delegator => bytes)) | ||
_pendingRegisterDelegatorMessages; | ||
/// @notice Maps the validationID to a mapping of delegator address to pending end delegator messages. | ||
mapping(bytes32 validationID => mapping(address delegator => bytes)) | ||
_pendingEndDelegatorMessages; | ||
/// @notice Maps the delegationID to the delegator information. | ||
mapping(bytes32 delegationID => Delegator) _delegatorStakes; | ||
/// @notice Maps the delegationID to pending register delegator messages. | ||
mapping(bytes32 delegationID => bytes) _pendingRegisterDelegatorMessages; | ||
/// @notice Maps the delegationID to pending end delegator messages. | ||
mapping(bytes32 delegationID => bytes) _pendingEndDelegatorMessages; | ||
} | ||
// solhint-enable private-vars-leading-underscore | ||
|
||
|
@@ -147,9 +145,9 @@ abstract contract PoSValidatorManager is IPoSValidatorManager, ValidatorManager | |
|
||
function _initializeDelegatorRegistration( | ||
bytes32 validationID, | ||
address delegator, | ||
address delegatorAddress, | ||
uint256 delegationAmount | ||
) internal nonReentrant { | ||
) internal nonReentrant returns (bytes32) { | ||
uint64 weight = valueToWeight(_lock(delegationAmount)); | ||
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); | ||
|
||
|
@@ -158,29 +156,28 @@ abstract contract PoSValidatorManager is IPoSValidatorManager, ValidatorManager | |
require( | ||
validator.status == ValidatorStatus.Active, "PoSValidatorManager: validator not active" | ||
); | ||
// Update the validator weight | ||
uint64 newValidatorWeight = validator.weight + weight; | ||
_setValidatorWeight(validationID, newValidatorWeight); | ||
|
||
// Ensure the delegator is not already registered | ||
require( | ||
$._delegatorStakes[validationID][delegator].weight == 0, | ||
"PoSValidatorManager: delegator already registered" | ||
); | ||
// Construct the delegation ID. This is guaranteed to be unique since it is | ||
// constructed using a new nonce. | ||
uint64 nonce = _getAndIncrementNonce(validationID); | ||
bytes32 delegationID = keccak256(abi.encodePacked(validationID, delegatorAddress, nonce)); | ||
|
||
_checkAndUpdateChurnTracker(weight); | ||
|
||
// Update the validator weight | ||
validator.weight += weight; | ||
_setValidator(validationID, validator); | ||
|
||
// Submit the message to the Warp precompile. | ||
uint64 nonce = _getAndIncrementNonce(validationID); | ||
bytes memory setValidatorWeightPayload = ValidatorMessages | ||
.packSetSubnetValidatorWeightMessage(validationID, nonce, validator.weight); | ||
$._pendingRegisterDelegatorMessages[validationID][delegator] = setValidatorWeightPayload; | ||
.packSetSubnetValidatorWeightMessage(validationID, nonce, newValidatorWeight); | ||
$._pendingRegisterDelegatorMessages[delegationID] = setValidatorWeightPayload; | ||
bytes32 messageID = WARP_MESSENGER.sendWarpMessage(setValidatorWeightPayload); | ||
|
||
// Store the delegator information | ||
$._delegatorStakes[validationID][delegator] = Delegator({ | ||
// Store the delegation information | ||
$._delegatorStakes[delegationID] = Delegator({ | ||
status: DelegatorStatus.PendingAdded, | ||
owner: delegatorAddress, | ||
validationID: validationID, | ||
weight: weight, | ||
startedAt: 0, | ||
endedAt: 0, | ||
|
@@ -189,164 +186,163 @@ abstract contract PoSValidatorManager is IPoSValidatorManager, ValidatorManager | |
}); | ||
|
||
emit DelegatorAdded({ | ||
delegationID: delegationID, | ||
validationID: validationID, | ||
setWeightMessageID: messageID, | ||
delegator: delegator, | ||
delegatorAddress: delegatorAddress, | ||
nonce: nonce, | ||
validatorWeight: newValidatorWeight, | ||
delegatorWeight: weight, | ||
validatorWeight: validator.weight, | ||
nonce: nonce | ||
setWeightMessageID: messageID | ||
}); | ||
return delegationID; | ||
} | ||
|
||
function resendDelegatorRegistration(bytes32 validationID, address delegator) external { | ||
_checkPendingRegisterDelegatorMessages(validationID, delegator); | ||
function resendDelegatorRegistration(bytes32 delegationID) external { | ||
_checkPendingRegisterDelegatorMessages(delegationID); | ||
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); | ||
// Submit the message to the Warp precompile. | ||
WARP_MESSENGER.sendWarpMessage($._pendingRegisterDelegatorMessages[validationID][delegator]); | ||
WARP_MESSENGER.sendWarpMessage($._pendingRegisterDelegatorMessages[delegationID]); | ||
} | ||
Check warning Code scanning / Slither Unused return Medium |
||
|
||
function completeDelegatorRegistration(uint32 messageIndex, address delegator) external { | ||
function completeDelegatorRegistration(uint32 messageIndex, bytes32 delegationID) external { | ||
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); | ||
|
||
// Unpack the Warp message | ||
WarpMessage memory warpMessage = _getPChainWarpMessage(messageIndex); | ||
(bytes32 validationID, uint64 nonce,) = | ||
ValidatorMessages.unpackSubnetValidatorWeightUpdateMessage(warpMessage.payload); | ||
_checkPendingRegisterDelegatorMessages(validationID, delegator); | ||
delete $._pendingRegisterDelegatorMessages[validationID][delegator]; | ||
_checkPendingRegisterDelegatorMessages(delegationID); | ||
delete $._pendingRegisterDelegatorMessages[delegationID]; | ||
|
||
Validator memory validator = _getValidator(validationID); | ||
|
||
// The received nonce should be no greater than the highest sent nonce | ||
require(validator.messageNonce >= nonce, "PoSValidatorManager: invalid nonce"); | ||
// It should also be greater than or equal to the delegator's starting nonce | ||
// It should also be greater than or equal to the delegationID's starting nonce | ||
require( | ||
$._delegatorStakes[validationID][delegator].startingNonce <= nonce, | ||
$._delegatorStakes[delegationID].startingNonce <= nonce, | ||
"PoSValidatorManager: nonce does not match" | ||
); | ||
|
||
require( | ||
$._delegatorStakes[validationID][delegator].status == DelegatorStatus.PendingAdded, | ||
"PoSValidatorManager: delegator not pending added" | ||
$._delegatorStakes[delegationID].status == DelegatorStatus.PendingAdded, | ||
"PoSValidatorManager: delegationID not pending added" | ||
); | ||
// Update the delegator status | ||
$._delegatorStakes[validationID][delegator].status = DelegatorStatus.Active; | ||
$._delegatorStakes[validationID][delegator].startedAt = uint64(block.timestamp); | ||
|
||
// Update the delegation status | ||
$._delegatorStakes[delegationID].status = DelegatorStatus.Active; | ||
$._delegatorStakes[delegationID].startedAt = uint64(block.timestamp); | ||
emit DelegatorRegistered({ | ||
delegationID: delegationID, | ||
validationID: validationID, | ||
delegator: delegator, | ||
nonce: nonce, | ||
startTime: block.timestamp | ||
}); | ||
} | ||
Check warning Code scanning / Slither Unused return Medium |
||
|
||
function initializeEndDelegation( | ||
bytes32 validationID, | ||
bytes32 delegationID, | ||
bool includeUptimeProof, | ||
uint32 messageIndex | ||
) external { | ||
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); | ||
bytes32 validationID = $._delegatorStakes[delegationID].validationID; | ||
|
||
uint64 uptime; | ||
if (includeUptimeProof) { | ||
uptime = _getUptime(validationID, messageIndex); | ||
} | ||
|
||
// TODO: Calculate the delegator's reward, but do not unlock it | ||
|
||
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); | ||
|
||
// Ensure the delegator is active | ||
Delegator memory delegator = $._delegatorStakes[validationID][_msgSender()]; | ||
Delegator memory delegator = $._delegatorStakes[delegationID]; | ||
require( | ||
delegator.owner == _msgSender(), "PoSValidatorManager: delegation not owned by sender" | ||
); | ||
require( | ||
delegator.status == DelegatorStatus.Active, "PoSValidatorManager: delegator not active" | ||
delegator.status == DelegatorStatus.Active, "PoSValidatorManager: delegation not active" | ||
); | ||
uint64 nonce = _getAndIncrementNonce(validationID); | ||
delegator.status = DelegatorStatus.PendingRemoved; | ||
delegator.endedAt = uint64(block.timestamp); | ||
delegator.endingNonce = nonce; | ||
|
||
$._delegatorStakes[validationID][_msgSender()] = delegator; | ||
$._delegatorStakes[delegationID] = delegator; | ||
|
||
Validator memory validator = _getValidator(validationID); | ||
require(validator.weight > delegator.weight, "PoSValidatorManager: Invalid weight"); | ||
validator.weight -= delegator.weight; | ||
_setValidator(validationID, validator); | ||
uint64 newValidatorWeight = validator.weight - delegator.weight; | ||
_setValidatorWeight(validationID, newValidatorWeight); | ||
|
||
// Submit the message to the Warp precompile. | ||
bytes memory setValidatorWeightPayload = ValidatorMessages | ||
.packSetSubnetValidatorWeightMessage(validationID, nonce, validator.weight); | ||
$._pendingEndDelegatorMessages[validationID][_msgSender()] = setValidatorWeightPayload; | ||
.packSetSubnetValidatorWeightMessage(validationID, nonce, newValidatorWeight); | ||
$._pendingEndDelegatorMessages[delegationID] = setValidatorWeightPayload; | ||
bytes32 messageID = WARP_MESSENGER.sendWarpMessage(setValidatorWeightPayload); | ||
|
||
emit DelegatorRemovalInitialized({ | ||
delegationID: delegationID, | ||
validationID: validationID, | ||
setWeightMessageID: messageID, | ||
delegator: _msgSender(), | ||
validatorWeight: validator.weight, | ||
nonce: nonce, | ||
endTime: block.timestamp | ||
validatorWeight: newValidatorWeight, | ||
endTime: block.timestamp, | ||
setWeightMessageID: messageID | ||
}); | ||
} | ||
Check notice Code scanning / Slither Reentrancy vulnerabilities Low
Reentrancy in PoSValidatorManager.initializeEndDelegation(bytes32,bool,uint32):
External calls: - messageID = WARP_MESSENGER.sendWarpMessage(setValidatorWeightPayload) Event emitted after the call(s): - DelegatorRemovalInitialized({delegationID:delegationID,validationID:validationID,nonce:nonce,validatorWeight:newValidatorWeight,endTime:block.timestamp,setWeightMessageID:messageID}) Check notice Code scanning / Slither Block timestamp Low
PoSValidatorManager.initializeEndDelegation(bytes32,bool,uint32) uses timestamp for comparisons
Dangerous comparisons: - require(bool,string)(delegator.owner == _msgSender(),PoSValidatorManager: delegation not owned by sender) - require(bool,string)(delegator.status == DelegatorStatus.Active,PoSValidatorManager: delegation not active) - require(bool,string)(validator.weight > delegator.weight,PoSValidatorManager: Invalid weight) |
||
|
||
function resendEndDelegation(bytes32 validationID, address delegator) external { | ||
_checkPendingEndDelegatorMessage(validationID, delegator); | ||
function resendEndDelegation(bytes32 delegationID) external { | ||
_checkPendingEndDelegatorMessage(delegationID); | ||
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); | ||
WARP_MESSENGER.sendWarpMessage($._pendingEndDelegatorMessages[validationID][delegator]); | ||
WARP_MESSENGER.sendWarpMessage($._pendingEndDelegatorMessages[delegationID]); | ||
} | ||
Check warning Code scanning / Slither Unused return Medium |
||
|
||
function completeEndDelegation(uint32 messageIndex, address delegator) external { | ||
function completeEndDelegation(uint32 messageIndex, bytes32 delegationID) external { | ||
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); | ||
|
||
// Unpack the Warp message | ||
WarpMessage memory warpMessage = _getPChainWarpMessage(messageIndex); | ||
(bytes32 validationID, uint64 nonce,) = | ||
ValidatorMessages.unpackSubnetValidatorWeightUpdateMessage(warpMessage.payload); | ||
_checkPendingEndDelegatorMessage(validationID, delegator); | ||
delete $._pendingEndDelegatorMessages[validationID][delegator]; | ||
_checkPendingEndDelegatorMessage(delegationID); | ||
delete $._pendingEndDelegatorMessages[delegationID]; | ||
|
||
Validator memory validator = _getValidator(validationID); | ||
// The received nonce should be no greater than the highest sent nonce | ||
require(validator.messageNonce >= nonce, "PoSValidatorManager: invalid nonce"); | ||
// It should also be greater than or equal to the delegator's ending nonce | ||
require( | ||
$._delegatorStakes[validationID][delegator].endingNonce <= nonce, | ||
$._delegatorStakes[delegationID].endingNonce <= nonce, | ||
"PoSValidatorManager: nonce does not match" | ||
); | ||
|
||
require( | ||
$._delegatorStakes[validationID][delegator].status == DelegatorStatus.PendingRemoved, | ||
"PoSValidatorManager: delegator not pending added" | ||
$._delegatorStakes[delegationID].status == DelegatorStatus.PendingRemoved, | ||
"PoSValidatorManager: delegation not pending added" | ||
); | ||
|
||
// Update the delegator status | ||
$._delegatorStakes[validationID][delegator].status = DelegatorStatus.Completed; | ||
$._delegatorStakes[delegationID].status = DelegatorStatus.Completed; | ||
|
||
// TODO: Unlock the delegator's stake and their reward | ||
|
||
emit DelegationEnded(validationID, delegator, nonce); | ||
emit DelegationEnded(delegationID, validationID, nonce); | ||
} | ||
Check warning Code scanning / Slither Unused return Medium |
||
|
||
function _checkPendingEndDelegatorMessage( | ||
bytes32 validationID, | ||
address delegator | ||
) private view { | ||
function _checkPendingEndDelegatorMessage(bytes32 delegationID) private view { | ||
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); | ||
require( | ||
$._pendingEndDelegatorMessages[validationID][delegator].length > 0 | ||
&& $._delegatorStakes[validationID][delegator].status == DelegatorStatus.PendingRemoved, | ||
"PoSValidatorManager: delegator removal not pending" | ||
$._pendingEndDelegatorMessages[delegationID].length > 0 | ||
&& $._delegatorStakes[delegationID].status == DelegatorStatus.PendingRemoved, | ||
"PoSValidatorManager: delegation removal not pending" | ||
); | ||
} | ||
|
||
function _checkPendingRegisterDelegatorMessages( | ||
bytes32 validationID, | ||
address delegator | ||
) private view { | ||
function _checkPendingRegisterDelegatorMessages(bytes32 delegationID) private view { | ||
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); | ||
require( | ||
$._pendingRegisterDelegatorMessages[validationID][delegator].length > 0 | ||
&& $._delegatorStakes[validationID][delegator].status == DelegatorStatus.PendingAdded, | ||
"PoSValidatorManager: delegator registration not pending" | ||
$._pendingRegisterDelegatorMessages[delegationID].length > 0 | ||
&& $._delegatorStakes[delegationID].status == DelegatorStatus.PendingAdded, | ||
"PoSValidatorManager: delegation registration not pending" | ||
); | ||
} | ||
} |