Skip to content

Commit

Permalink
acp99 delegation handling
Browse files Browse the repository at this point in the history
  • Loading branch information
cam-schultz committed Dec 3, 2024
1 parent 510f5fe commit d5b5b93
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 171 deletions.
4 changes: 2 additions & 2 deletions contracts/validator-manager/PoAValidatorManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@ contract PoAValidatorManager is IACP99SecurityModule, ACP99ValidatorManager, Own
// No-op
}

function handleInitializeValidatorWeightChange() external {
function handleInitializeValidatorWeightChange(bytes32 validationID, uint64 weight, bytes calldata args) external {
// No-op
}

function handleCompleteValidatorWeightChange() external {
function handleCompleteValidatorWeightChange(bytes32 validationID, bytes calldata args) external {
// No-op
}
}
106 changes: 30 additions & 76 deletions contracts/validator-manager/PoSValidatorManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,31 @@ abstract contract PoSValidatorManager is
_completeEndValidation(validationID);
}

function handleInitializeValidatorWeightChange() external {
function handleInitializeValidatorWeightChange(bytes32 validationID, uint64 weight, bytes calldata args) external {
(bytes32 delegationID, bytes memory innerArgs) = abi.decode(args, (bytes32, bytes));
if (_getPoSValidatorManagerStorage()._delegatorStakes[delegationID].status == DelegatorStatus.Unknown) {
address delegatorAddress = abi.decode(innerArgs, (address));
uint64 delegatorWeight = getValidator(validationID).weight - weight;
_initializeDelegatorRegistration(validationID, delegatorAddress, weightToValue(delegatorWeight));
} else {
(bool force, bool includeUptimeProof, uint32 messageIndex, address rewardRecipient) = abi.decode(innerArgs, (bool, bool, uint32, address));
bool success = _initializeEndDelegation(delegationID, includeUptimeProof, messageIndex, rewardRecipient);
if (force) {
return;
}
if (!success) {
revert DelegatorIneligibleForRewards(delegationID);
}
}
}

function handleCompleteValidatorWeightChange() external {
function handleCompleteValidatorWeightChange(bytes32, bytes calldata args) external {
(bytes32 delegationID, uint32 messageIndex) = abi.decode(args, (bytes32, uint32));
if (_getPoSValidatorManagerStorage()._delegatorStakes[delegationID].status == DelegatorStatus.PendingAdded) {
_completeDelegatorRegistration(delegationID, messageIndex);
} else {
_completeEndDelegation(delegationID, messageIndex);
}
}

/**
Expand Down Expand Up @@ -536,7 +557,7 @@ abstract contract PoSValidatorManager is
/**
* @notice See {IPoSValidatorManager-completeDelegatorRegistration}.
*/
function completeDelegatorRegistration(bytes32 delegationID, uint32 messageIndex) external {
function _completeDelegatorRegistration(bytes32 delegationID, uint32 messageIndex) internal {
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage();

Delegator memory delegator = $._delegatorStakes[delegationID];
Expand All @@ -553,7 +574,7 @@ abstract contract PoSValidatorManager is
// In the case where the validator has completed its validation period, we can no
// longer stake and should move our status directly to completed and return the stake.
if (validator.status == ValidatorStatus.Completed) {
return _completeEndDelegation(delegationID);
return _endDelegation(delegationID);
}

// Unpack the Warp message
Expand Down Expand Up @@ -583,73 +604,6 @@ abstract contract PoSValidatorManager is
});
}

/**
* @notice See {IPoSValidatorManager-initializeEndDelegation}.
*/
function initializeEndDelegation(
bytes32 delegationID,
bool includeUptimeProof,
uint32 messageIndex
) external {
_initializeEndDelegationWithCheck(
delegationID, includeUptimeProof, messageIndex, address(0)
);
}

/**
* @notice See {IPoSValidatorManager-initializeEndDelegation}.
*/
function initializeEndDelegation(
bytes32 delegationID,
bool includeUptimeProof,
uint32 messageIndex,
address rewardRecipient
) external {
_initializeEndDelegationWithCheck(
delegationID, includeUptimeProof, messageIndex, rewardRecipient
);
}

function _initializeEndDelegationWithCheck(
bytes32 delegationID,
bool includeUptimeProof,
uint32 messageIndex,
address rewardRecipient
) internal {
if (
!_initializeEndDelegation(
delegationID, includeUptimeProof, messageIndex, rewardRecipient
)
) {
revert DelegatorIneligibleForRewards(delegationID);
}
}

/**
* @notice See {IPoSValidatorManager-forceInitializeEndDelegation}.
*/
function forceInitializeEndDelegation(
bytes32 delegationID,
bool includeUptimeProof,
uint32 messageIndex
) external {
// Ignore the return value here to force end delegation, regardless of possible missed rewards
_initializeEndDelegation(delegationID, includeUptimeProof, messageIndex, address(0));
}

/**
* @notice See {IPoSValidatorManager-forceInitializeEndDelegation}.
*/
function forceInitializeEndDelegation(
bytes32 delegationID,
bool includeUptimeProof,
uint32 messageIndex,
address rewardRecipient
) external {
// Ignore the return value here to force end delegation, regardless of possible missed rewards
_initializeEndDelegation(delegationID, includeUptimeProof, messageIndex, rewardRecipient);
}

/**
* @dev Helper function that initializes the end of a PoS delegation period.
* Returns false if it is possible for the delegator to claim rewards, but it is not eligible.
Expand Down Expand Up @@ -716,7 +670,7 @@ abstract contract PoSValidatorManager is
return (reward > 0);
} else if (validator.status == ValidatorStatus.Completed) {
_calculateAndSetDelegationReward(delegator, rewardRecipient, delegationID);
_completeEndDelegation(delegationID);
_endDelegation(delegationID);
// If the validator has completed, then no further uptimes may be submitted, so we always
// end the delegation.
return true;
Expand Down Expand Up @@ -803,10 +757,10 @@ abstract contract PoSValidatorManager is
/**
* @notice See {IPoSValidatorManager-completeEndDelegation}.
*/
function completeEndDelegation(
function _completeEndDelegation(
bytes32 delegationID,
uint32 messageIndex
) external nonReentrant {
) internal nonReentrant {
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage();
Delegator memory delegator = $._delegatorStakes[delegationID];

Expand Down Expand Up @@ -836,10 +790,10 @@ abstract contract PoSValidatorManager is
}
}

_completeEndDelegation(delegationID);
_endDelegation(delegationID);
}

function _completeEndDelegation(bytes32 delegationID) internal {
function _endDelegation(bytes32 delegationID) internal {
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage();

Delegator memory delegator = $._delegatorStakes[delegationID];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
pragma solidity 0.8.25;

interface IACP99SecurityModule {
// Called by the ValidatorManager on initializeRegisterValidator
function handleInitializeValidatorRegistration(
bytes32 validationID,
uint64 weight,
Expand All @@ -19,8 +18,7 @@ interface IACP99SecurityModule {

function handleCompleteEndValidation(bytes32 validationID) external;

// Called by the ValidatorManager on initializeSetValidatorWeight
function handleInitializeValidatorWeightChange() external;
function handleInitializeValidatorWeightChange(bytes32 validationID, uint64 weight, bytes calldata args) external;

function handleCompleteValidatorWeightChange() external;
function handleCompleteValidatorWeightChange(bytes32 validationID, bytes calldata args) external;
}
89 changes: 0 additions & 89 deletions contracts/validator-manager/interfaces/IPoSValidatorManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -134,102 +134,13 @@ interface IPoSValidatorManager is IValidatorManager {
*/
function submitUptimeProof(bytes32 validationID, uint32 messageIndex) external;

/**
* @notice Completes the delegator registration process by submitting an acknowledgement of the registration of a
* validationID from the P-Chain. After this function is called, the validator's weight is updated in the contract state.
* Any P-Chain acknowledgement with a nonce greater than or equal to the nonce used to initialize registration of the
* delegator is valid, as long as that nonce has been sent by the contract. For the purposes of computing delegation rewards,
* the delegation is considered active after this function is completed.
* Note: Only the specified delegation will be marked as registered, even if the validator weight update
* message implicitly includes multiple weight changes.
* @param delegationID The ID of the delegation being registered.
* @param messageIndex The index of the Warp message to be received providing the acknowledgement.
*/
function completeDelegatorRegistration(bytes32 delegationID, uint32 messageIndex) external;

/**
* @notice Begins the process of removing a delegator from a validation period, and reverts if the delegation is not eligible for rewards.
* The delegator must have been previously registered with the given validationID. For the purposes of computing delegation rewards,
* the delegation period is considered ended when this function is called. Uses the supplied uptime proof to calculate rewards.
* If none is provided in the call, the latest known uptime will be used. Reverts if the uptime is not eligible for rewards.
* Note: This function can only be called by the address that registered the delegation.
* Note: Reverts if the uptime is not eligible for rewards.
* @param delegationID The ID of the delegation being removed.
* @param includeUptimeProof Whether or not an uptime proof is provided for the validation period.
* If the validator has completed its validation period, it has already provided an uptime proof, so {includeUptimeProof}
* will be ignored and can be set to false. If the validator has not completed its validation period and no uptime proof
* is provided, the latest known uptime will be used.
* @param messageIndex If {includeUptimeProof} is true, the index of the Warp message to be received providing the
* uptime proof.
*/
function initializeEndDelegation(
bytes32 delegationID,
bool includeUptimeProof,
uint32 messageIndex
) external;

/**
* @notice See {IPoSValidatorManager-initializeEndDelegation} for details of the first three parameters
* @param recipientAddress The address to receive the rewards.
*/
function initializeEndDelegation(
bytes32 delegationID,
bool includeUptimeProof,
uint32 messageIndex,
address recipientAddress
) external;

/**
* @notice Begins the process of removing a delegator from a validation period, but does not revert if the delegation is not eligible for rewards.
* The delegator must have been previously registered with the given validationID. For the purposes of computing delegation rewards,
* the delegation period is considered ended when this function is called. Uses the supplied uptime proof to calculate rewards.
* If none is provided in the call, the latest known uptime will be used. Reverts if the uptime is not eligible for rewards.
* Note: This function can only be called by the address that registered the delegation.
* @param delegationID The ID of the delegation being removed.
* @param includeUptimeProof Whether or not an uptime proof is provided for the validation period.
* If the validator has completed its validation period, it has already provided an uptime proof, so {includeUptimeProof}
* will be ignored and can be set to false. If the validator has not completed its validation period and no uptime proof
* is provided, the latest known uptime will be used.
* @param messageIndex If {includeUptimeProof} is true, the index of the Warp message to be received providing the
* uptime proof.
*/
function forceInitializeEndDelegation(
bytes32 delegationID,
bool includeUptimeProof,
uint32 messageIndex
) external;

/**
* @notice See {IPoSValidatorManager-forceInitializeEndDelegation} for details of the first three parameters
* @param recipientAddress The address to receive the rewards.
*/
function forceInitializeEndDelegation(
bytes32 delegationID,
bool includeUptimeProof,
uint32 messageIndex,
address recipientAddress
) external;

/**
* @notice Resubmits a delegator registration or delegator end message to be sent to the P-Chain.
* Only necessary if the original message can't be delivered due to validator churn.
* @param delegationID The ID of the delegation.
*/
function resendUpdateDelegation(bytes32 delegationID) external;

/**
* @notice Completes the process of ending a delegation by receiving an acknowledgement from the P-Chain.
* After this function is called, the validator's weight is updated in the contract state.
* Any P-Chain acknowledgement with a nonce greater than or equal to the nonce used to initialize the end of the
* delegator's delegation is valid, as long as that nonce has been sent by the contract. This is because the validator
* weight change pertaining to the delegation ending is included in any subsequent validator weight update messages.
* Note: Only the specified delegation will be marked as completed, even if the validator weight update
* message implicitly includes multiple weight changes.
* @param delegationID The ID of the delegation being removed.
* @param messageIndex The index of the Warp message to be received providing the acknowledgement.
*/
function completeEndDelegation(bytes32 delegationID, uint32 messageIndex) external;

/**
* @notice Withdraws the delegation fees from completed delegations to the owner of the validator.
* @param validationID The ID of the validation period being ended.
Expand Down

0 comments on commit d5b5b93

Please sign in to comment.