Skip to content

Commit

Permalink
Merge branch 'main' into uint64-weights
Browse files Browse the repository at this point in the history
  • Loading branch information
cam-schultz committed Nov 22, 2024
2 parents 342cd2a + aec3442 commit f6c5cdf
Show file tree
Hide file tree
Showing 16 changed files with 1,119 additions and 131 deletions.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions audits/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Audits

Below is the list of most recent audit for contracts in this repo. Please check out __only__ listed audited versions for production code. Code used should be the final commit audited.

See `audits/historical` for older audits. These audits may now be obsolete, and legacy code superseded by new versions are __not__ recommended for production deployments.

| Date | Commit | Auditor | Scope | Links |
| ------------ | ---------- | ------------ | -------------------- | ----------------------------------------------------------- |
| Nov 2023 | `6ba46565` | OpenZeppelin | All contracts in the top-level of `contracts/teleporter/` | [🔗](./Teleporter%20Audit%20(November%2016th%202023)%20-%20OpenZeppelin.pdf) |
| Jan 2024 | `9fcdf42d` | Louis | Some contracts in `contracts/teleporter/registry` and `contracts/utilities`, see audit for details | [🔗](./Teleporter%20Upgradeable%20Audit%20(January%2010th%202024)%20-%20Louis.pdf) |
| Jun 2024 | `9e03a1e5` | OpenZeppelin | All contracts in `contracts/ictt/` excluding `mocks/` | [🔗](./ICTT%20Audit%20(June%2026th%202024)%20-%20OpenZeppelin.pdf) |
| Oct 2024 | `93920df6` | OpenZeppelin | All contracts in `contracts/validator-manager/` | [🔗](./Validator%20Manager%20Audit%20(October%2030th%202024)%20-%20OpenZeppelin.pdf) |
Binary file not shown.
8 changes: 0 additions & 8 deletions contracts/ictt/audits/README.md

This file was deleted.

195 changes: 177 additions & 18 deletions contracts/validator-manager/PoSValidatorManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,10 @@ abstract contract PoSValidatorManager is
mapping(bytes32 delegationID => Delegator) _delegatorStakes;
/// @notice Maps the delegation ID to its pending staking rewards.
mapping(bytes32 delegationID => uint256) _redeemableDelegatorRewards;
mapping(bytes32 delegationID => address) _delegatorRewardRecipients;
/// @notice Maps the validation ID to its pending staking rewards.
mapping(bytes32 validationID => uint256) _redeemableValidatorRewards;
mapping(bytes32 validationID => address) _rewardRecipients;
}
// solhint-enable private-vars-leading-underscore

Expand All @@ -84,6 +86,7 @@ abstract contract PoSValidatorManager is
error InvalidDelegationID(bytes32 delegationID);
error InvalidDelegatorStatus(DelegatorStatus status);
error InvalidNonce(uint64 nonce);
error InvalidRewardRecipient(address rewardRecipient);
error InvalidStakeAmount(uint256 stakeAmount);
error InvalidMinStakeDuration(uint64 minStakeDuration);
error InvalidStakeMultiplier(uint8 maximumStakeMultiplier);
Expand Down Expand Up @@ -213,7 +216,36 @@ abstract contract PoSValidatorManager is
bool includeUptimeProof,
uint32 messageIndex
) external {
if (!_initializeEndPoSValidation(validationID, includeUptimeProof, messageIndex)) {
_initializeEndValidationWithCheck(
validationID, includeUptimeProof, messageIndex, address(0)
);
}

/**
* @notice See {IPoSValidatorManager-initializeEndValidation}.
*/
function initializeEndValidation(
bytes32 validationID,
bool includeUptimeProof,
uint32 messageIndex,
address rewardRecipient
) external {
_initializeEndValidationWithCheck(
validationID, includeUptimeProof, messageIndex, rewardRecipient
);
}

function _initializeEndValidationWithCheck(
bytes32 validationID,
bool includeUptimeProof,
uint32 messageIndex,
address rewardRecipient
) internal {
if (
!_initializeEndPoSValidation(
validationID, includeUptimeProof, messageIndex, rewardRecipient
)
) {
revert ValidatorIneligibleForRewards(validationID);
}
}
Expand All @@ -227,7 +259,62 @@ abstract contract PoSValidatorManager is
uint32 messageIndex
) external {
// Ignore the return value here to force end validation, regardless of possible missed rewards
_initializeEndPoSValidation(validationID, includeUptimeProof, messageIndex);
_initializeEndPoSValidation(validationID, includeUptimeProof, messageIndex, address(0));
}

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

function changeValidatorRewardRecipient(
bytes32 validationID,
address rewardRecipient
) external {
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage();

if (rewardRecipient == address(0)) {
revert InvalidRewardRecipient(rewardRecipient);
}

if ($._posValidatorInfo[validationID].owner != _msgSender()) {
revert UnauthorizedOwner(_msgSender());
}

if (rewardRecipient == _msgSender()) {
delete $._rewardRecipients[validationID];
} else {
$._rewardRecipients[validationID] = rewardRecipient;
}
}

function changeDelegatorRewardRecipient(
bytes32 delegationID,
address rewardRecipient
) external {
if (rewardRecipient == address(0)) {
revert InvalidRewardRecipient(rewardRecipient);
}

PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage();

if ($._delegatorStakes[delegationID].owner != _msgSender()) {
revert UnauthorizedOwner(_msgSender());
}

if (rewardRecipient == _msgSender()) {
delete $._delegatorRewardRecipients[delegationID];
} else {
$._delegatorRewardRecipients[delegationID] = rewardRecipient;
}
}

/**
Expand All @@ -238,7 +325,8 @@ abstract contract PoSValidatorManager is
function _initializeEndPoSValidation(
bytes32 validationID,
bool includeUptimeProof,
uint32 messageIndex
uint32 messageIndex,
address rewardRecipient
) internal returns (bool) {
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage();

Expand Down Expand Up @@ -278,6 +366,11 @@ abstract contract PoSValidatorManager is
uptimeSeconds: uptimeSeconds
});
$._redeemableValidatorRewards[validationID] += reward;

if (rewardRecipient != address(0)) {
$._rewardRecipients[validationID] = rewardRecipient;
}

return (reward > 0);
}

Expand All @@ -296,9 +389,18 @@ abstract contract PoSValidatorManager is
}

address owner = $._posValidatorInfo[validationID].owner;

address rewardRecipient = $._rewardRecipients[validationID];

if (rewardRecipient == address(0)) {
rewardRecipient = owner;
} else {
delete $._rewardRecipients[validationID];
}

// The validator can either be Completed or Invalidated here. We only grant rewards for Completed.
if (validator.status == ValidatorStatus.Completed) {
_withdrawValidationRewards(owner, validationID);
_withdrawValidationRewards(rewardRecipient, validationID);
}

// The stake is unlocked whether the validation period is completed or invalidated.
Expand Down Expand Up @@ -526,7 +628,36 @@ abstract contract PoSValidatorManager is
bool includeUptimeProof,
uint32 messageIndex
) external {
if (!_initializeEndDelegation(delegationID, includeUptimeProof, messageIndex)) {
_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);
}
}
Expand All @@ -540,7 +671,20 @@ abstract contract PoSValidatorManager is
uint32 messageIndex
) external {
// Ignore the return value here to force end delegation, regardless of possible missed rewards
_initializeEndDelegation(delegationID, includeUptimeProof, messageIndex);
_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);
}

/**
Expand All @@ -551,7 +695,8 @@ abstract contract PoSValidatorManager is
function _initializeEndDelegation(
bytes32 delegationID,
bool includeUptimeProof,
uint32 messageIndex
uint32 messageIndex,
address rewardRecipient
) internal returns (bool) {
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage();

Expand Down Expand Up @@ -598,17 +743,16 @@ abstract contract PoSValidatorManager is
($._delegatorStakes[delegationID].endingNonce,) =
_setValidatorWeight(validationID, validator.weight - delegator.weight);

uint256 reward = _calculateDelegationReward(delegator);
$._redeemableDelegatorRewards[delegationID] = reward;
uint256 reward =
_calculateAndSetDelegationReward(delegator, rewardRecipient, delegationID);

emit DelegatorRemovalInitialized({
delegationID: delegationID,
validationID: validationID
});
return (reward > 0);
} else if (validator.status == ValidatorStatus.Completed) {
$._redeemableDelegatorRewards[delegationID] = _calculateDelegationReward(delegator);

_calculateAndSetDelegationReward(delegator, rewardRecipient, delegationID);
_completeEndDelegation(delegationID);
// If the validator has completed, then no further uptimes may be submitted, so we always
// end the delegation.
Expand All @@ -619,11 +763,12 @@ abstract contract PoSValidatorManager is
}

/// @dev Calculates the reward owed to the delegator based on the state of the delegator and its corresponding validator.
function _calculateDelegationReward(Delegator memory delegator)
private
view
returns (uint256)
{
/// then set the reward and reward recipient in the storage.
function _calculateAndSetDelegationReward(
Delegator memory delegator,
address rewardRecipient,
bytes32 delegationID
) private returns (uint256) {
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage();

Validator memory validator = getValidator(delegator.validationID);
Expand All @@ -645,13 +790,21 @@ abstract contract PoSValidatorManager is
return 0;
}

return $._rewardCalculator.calculateReward({
uint256 reward = $._rewardCalculator.calculateReward({
stakeAmount: weightToValue(delegator.weight),
validatorStartTime: validator.startedAt,
stakingStartTime: delegator.startedAt,
stakingEndTime: delegationEndTime,
uptimeSeconds: $._posValidatorInfo[delegator.validationID].uptimeSeconds
});

$._redeemableDelegatorRewards[delegationID] = reward;

if (rewardRecipient != address(0)) {
$._delegatorRewardRecipients[delegationID] = rewardRecipient;
}

return reward;
}

/**
Expand Down Expand Up @@ -736,7 +889,13 @@ abstract contract PoSValidatorManager is
// Once this function completes, the delegation is completed so we can clear it from state now.
delete $._delegatorStakes[delegationID];

address rewardRecipient = delegator.owner;
address rewardRecipient = $._delegatorRewardRecipients[delegationID];

if (rewardRecipient == address(0)) {
rewardRecipient = delegator.owner;
} else {
delete $._delegatorRewardRecipients[delegationID];
}

(uint256 delegationRewards, uint256 validatorFees) =
_withdrawDelegationRewards(rewardRecipient, delegationID, validationID);
Expand Down
Loading

0 comments on commit f6c5cdf

Please sign in to comment.