-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Track uptimes for delegation period #520
Changes from all commits
b59614d
feef247
31f4c83
59b83c1
3f20e79
1d21ca7
03f58d2
0834d6c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
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 |
---|---|---|
|
@@ -36,8 +36,6 @@ | |
/// @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 validationID to the uptime of the validator. | ||
mapping(bytes32 validationID => uint64) _validatorUptimes; | ||
} | ||
// solhint-enable private-vars-leading-underscore | ||
|
||
|
@@ -79,11 +77,11 @@ | |
uint64 minimumStakeDuration, | ||
IRewardCalculator rewardCalculator | ||
) internal onlyInitializing { | ||
PoSValidatorManagerStorage storage s = _getPoSValidatorManagerStorage(); | ||
s._minimumStakeAmount = minimumStakeAmount; | ||
s._maximumStakeAmount = maximumStakeAmount; | ||
s._minimumStakeDuration = minimumStakeDuration; | ||
s._rewardCalculator = rewardCalculator; | ||
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); | ||
$._minimumStakeAmount = minimumStakeAmount; | ||
$._maximumStakeAmount = maximumStakeAmount; | ||
$._minimumStakeDuration = minimumStakeDuration; | ||
$._rewardCalculator = rewardCalculator; | ||
} | ||
|
||
function initializeEndValidation( | ||
|
@@ -92,34 +90,36 @@ | |
uint32 messageIndex | ||
) external { | ||
if (includeUptimeProof) { | ||
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); | ||
(WarpMessage memory warpMessage, bool valid) = | ||
WARP_MESSENGER.getVerifiedWarpMessage(messageIndex); | ||
require(valid, "PoSValidatorManager: invalid warp message"); | ||
|
||
require( | ||
warpMessage.sourceChainID == WARP_MESSENGER.getBlockchainID(), | ||
"PoSValidatorManager: invalid source chain ID" | ||
); | ||
require( | ||
warpMessage.originSenderAddress == address(0), | ||
"PoSValidatorManager: invalid origin sender address" | ||
); | ||
|
||
(bytes32 uptimeValidationID, uint64 uptime) = | ||
ValidatorMessages.unpackValidationUptimeMessage(warpMessage.payload); | ||
require( | ||
validationID == uptimeValidationID, | ||
"PoSValidatorManager: invalid uptime validation ID" | ||
); | ||
|
||
$._validatorUptimes[validationID] = uptime; | ||
emit ValidationUptimeUpdated(validationID, uptime); | ||
_getUptime(validationID, messageIndex); | ||
} | ||
// TODO: Calculate the reward for the validator, but do not unlock it | ||
|
||
_initializeEndValidation(validationID); | ||
} | ||
|
||
function _getUptime(bytes32 validationID, uint32 messageIndex) internal view returns (uint64) { | ||
(WarpMessage memory warpMessage, bool valid) = | ||
WARP_MESSENGER.getVerifiedWarpMessage(messageIndex); | ||
require(valid, "PoSValidatorManager: invalid warp message"); | ||
|
||
require( | ||
warpMessage.sourceChainID == WARP_MESSENGER.getBlockchainID(), | ||
"PoSValidatorManager: invalid source chain ID" | ||
); | ||
require( | ||
warpMessage.originSenderAddress == address(0), | ||
"PoSValidatorManager: invalid origin sender address" | ||
); | ||
|
||
(bytes32 uptimeValidationID, uint64 uptime) = | ||
ValidatorMessages.unpackValidationUptimeMessage(warpMessage.payload); | ||
require( | ||
validationID == uptimeValidationID, "PoSValidatorManager: invalid uptime validation ID" | ||
); | ||
|
||
return uptime; | ||
} | ||
|
||
function _processStake(uint256 stakeAmount) internal virtual returns (uint64) { | ||
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage(); | ||
// Lock the stake in the contract. | ||
|
@@ -241,41 +241,52 @@ | |
}); | ||
} | ||
|
||
function initializeEndDelegation(bytes32 validationID) external { | ||
function initializeEndDelegation( | ||
bytes32 validationID, | ||
bool includeUptimeProof, | ||
uint32 messageIndex | ||
) external { | ||
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()]; | ||
require( | ||
delegator.status == DelegatorStatus.Active, "PoSValidatorManager: delegator not active" | ||
); | ||
uint64 nonce = _getAndIncrementNonce(validationID); | ||
delegator.status = DelegatorStatus.PendingRemoved; | ||
delegator.endedAt = uint64(block.timestamp); | ||
delegator.endingNonce = nonce; | ||
|
||
$._delegatorStakes[validationID][_msgSender()] = delegator; | ||
|
||
Validator memory validator = _getValidator(validationID); | ||
require(validator.weight > delegator.weight, "PoSValidatorManager: Invalid weight"); | ||
validator.weight -= delegator.weight; | ||
_setValidator(validationID, validator); | ||
|
||
// Submit the message to the Warp precompile. | ||
bytes memory setValidatorWeightPayload = ValidatorMessages | ||
.packSetSubnetValidatorWeightMessage(validationID, nonce, validator.weight); | ||
$._pendingEndDelegatorMessages[validationID][_msgSender()] = setValidatorWeightPayload; | ||
bytes32 messageID = WARP_MESSENGER.sendWarpMessage(setValidatorWeightPayload); | ||
|
||
emit DelegatorRemovalInitialized({ | ||
validationID: validationID, | ||
setWeightMessageID: messageID, | ||
delegator: _msgSender(), | ||
validatorWeight: validator.weight, | ||
nonce: nonce, | ||
endTime: block.timestamp | ||
}); | ||
} | ||
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({validationID:validationID,setWeightMessageID:messageID,delegator:_msgSender(),validatorWeight:validator.weight,nonce:nonce,endTime:block.timestamp}) Check notice Code scanning / Slither Block timestamp Low
PoSValidatorManager.initializeEndDelegation(bytes32,bool,uint32) uses timestamp for comparisons
Dangerous comparisons: - require(bool,string)(delegator.status == DelegatorStatus.Active,PoSValidatorManager: delegator not active) - require(bool,string)(validator.weight > delegator.weight,PoSValidatorManager: Invalid weight) |
||
|
||
function resendEndDelegation(bytes32 validationID, address delegator) external { | ||
_checkPendingEndDelegatorMessage(validationID, delegator); | ||
|
@@ -310,6 +321,8 @@ | |
// Update the delegator status | ||
$._delegatorStakes[validationID][delegator].status = DelegatorStatus.Completed; | ||
|
||
// TODO: Unlock the delegator's stake and their reward | ||
|
||
emit DelegationEnded(validationID, delegator, nonce); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for my own understanding, does uptime return the absolute amount of time that the validator was up, or a percent of time that it was up during the staking period? I'm just thinking of whether other information is necessary to calculate rewards.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It returns the absolute number of seconds the validator has been up