Skip to content
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

Staking manager upgradability #477

Merged
merged 3 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions contracts/staking/NativeTokenStakingManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,16 @@ pragma solidity 0.8.25;
import {INativeTokenStakingManager} from "./interfaces/INativeTokenStakingManager.sol";
import {Address} from "@openzeppelin/[email protected]/utils/Address.sol";
import {StakingManager} from "./StakingManager.sol";
import {Initializable} from
"@openzeppelin/[email protected]/proxy/utils/Initializable.sol";

contract NativeTokenStakingManager is StakingManager, INativeTokenStakingManager {
contract NativeTokenStakingManager is Initializable, StakingManager, INativeTokenStakingManager {
using Address for address payable;

constructor() {
_disableInitializers();
}

/**
* @notice Begins the validator registration process. Locks the provided native asset in the contract as the stake.
* @param nodeID The node ID of the validator being registered.
Expand All @@ -22,7 +29,6 @@ contract NativeTokenStakingManager is StakingManager, INativeTokenStakingManager
* The signature field will be validated by the P-Chain. Implementations may choose to validate that the signature
* field is well-formed but it is not required.
*/

function initializeValidatorRegistration(
bytes32 nodeID,
uint64 registrationExpiry,
Expand Down
63 changes: 46 additions & 17 deletions contracts/staking/StakingManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,21 @@
WarpMessage,
IWarpMessenger
} from "@avalabs/[email protected]/contracts/interfaces/IWarpMessenger.sol";
import {ReentrancyGuard} from "@openzeppelin/[email protected]/utils/ReentrancyGuard.sol";
import {ReentrancyGuardUpgradeable} from
"@openzeppelin/[email protected]/utils/ReentrancyGuardUpgradeable.sol";
import {StakingMessages} from "./StakingMessages.sol";
import {IRewardCalculator} from "./interfaces/IRewardCalculator.sol";
import {Context} from "@openzeppelin/[email protected]/utils/Context.sol";

abstract contract StakingManager is Context, ReentrancyGuard, IStakingManager {
import {ContextUpgradeable} from
"@openzeppelin/[email protected]/utils/ContextUpgradeable.sol";
import {Initializable} from
"@openzeppelin/[email protected]/proxy/utils/Initializable.sol";

abstract contract StakingManager is
Initializable,
ContextUpgradeable,
ReentrancyGuardUpgradeable,
IStakingManager
{
enum ValidatorStatus {
Unknown,
PendingAdded,
Expand Down Expand Up @@ -46,7 +55,6 @@
// solhint-disable private-vars-leading-underscore
/// @custom:storage-location erc7201:avalanche-icm.storage.StakingManager
struct StakingManagerStorage {
IWarpMessenger _warpMessenger;
bytes32 _pChainBlockchainID;
bytes32 _subnetID;
uint256 _minimumStakeAmount;
Expand All @@ -66,9 +74,9 @@

// solhint-enable private-vars-leading-underscore
// keccak256(abi.encode(uint256(keccak256("avalanche-icm.storage.StakingManager")) - 1)) & ~bytes32(uint256(0xff));
// TODO: Update to correct storage slot
// TODO: Unit test for storage slot
bytes32 private constant _STAKING_MANAGER_STORAGE_LOCATION =
0x8568826440873e37a96cb0aab773b28d8154d963d2f0e41bd9b5c15f63625f91;
0xafe6c4731b852fc2be89a0896ae43d22d8b24989064d841b2a1586b4d39ab600;

// solhint-disable ordering
function _getStakingManagerStorage() private pure returns (StakingManagerStorage storage $) {
Expand All @@ -94,36 +102,57 @@
IRewardCalculator rewardCalculator;
}

function initialize(StakingManagerSettings calldata settings) public {
/**
* @notice Warp precompile used for sending and receiving Warp messages.
*/
IWarpMessenger public constant WARP_MESSENGER =
IWarpMessenger(0x0200000000000000000000000000000000000005);

function initialize(StakingManagerSettings calldata settings) public initializer {
__StakingManager_init(settings);
}

function __StakingManager_init(StakingManagerSettings calldata settings)
internal
onlyInitializing
{
__ReentrancyGuard_init();
__Context_init();
__StakingManager_init_unchained(settings);
}
Dismissed Show dismissed Hide dismissed

function __StakingManager_init_unchained(StakingManagerSettings calldata settings)
internal
onlyInitializing
{
StakingManagerStorage storage $ = _getStakingManagerStorage();
$._warpMessenger = IWarpMessenger(0x0200000000000000000000000000000000000005);
$._pChainBlockchainID = settings.pChainBlockchainID;
$._subnetID = settings.subnetID;
$._minimumStakeAmount = settings.minimumStakeAmount;
$._maximumStakeAmount = settings.maximumStakeAmount;
$._minimumStakeDuration = settings.minimumStakeDuration;
$._maximumHourlyChurn = settings.maximumHourlyChurn;
// Add each of the initial stakers as validators
uint64 initialStake;
for (uint256 i; i < settings.initialStakers.length; ++i) {
(bytes32 validationID,) =
StakingMessages.packValidationInfo(settings.initialStakers[i].validationInfo);
$._validationPeriods[validationID] = Validator({
status: ValidatorStatus.Active,
nodeID: settings.initialStakers[i].validationInfo.nodeID,
weight: settings.initialStakers[i].validationInfo.weight,
startedAt: uint64(block.timestamp),
endedAt: 0,
uptimeSeconds: 0,
owner: settings.initialStakers[i].owner,
rewarded: false,
messageNonce: 0
});
initialStake += settings.initialStakers[i].validationInfo.weight;
}
$._remainingInitialStake = initialStake;
$._rewardCalculator = settings.rewardCalculator;
}

Check warning

Code scanning / Slither

Conformance to Solidity naming conventions Warning


/**
* @notice Modifier to ensure that the initial stake has been provided.
Expand Down Expand Up @@ -208,7 +237,7 @@
$._pendingRegisterValidationMessages[validationID] = registerSubnetValidatorMessage;

// Submit the message to the Warp precompile.
bytes32 messageID = $._warpMessenger.sendWarpMessage(registerSubnetValidatorMessage);
bytes32 messageID = WARP_MESSENGER.sendWarpMessage(registerSubnetValidatorMessage);

$._validationPeriods[validationID] = Validator({
status: ValidatorStatus.PendingAdded,
Expand Down Expand Up @@ -239,7 +268,7 @@
);

// Submit the message to the Warp precompile.
$._warpMessenger.sendWarpMessage($._pendingRegisterValidationMessages[validationID]);
WARP_MESSENGER.sendWarpMessage($._pendingRegisterValidationMessages[validationID]);
}

/**
Expand All @@ -250,7 +279,7 @@
function completeValidatorRegistration(uint32 messageIndex) external {
StakingManagerStorage storage $ = _getStakingManagerStorage();
(WarpMessage memory warpMessage, bool valid) =
$._warpMessenger.getVerifiedWarpMessage(messageIndex);
WARP_MESSENGER.getVerifiedWarpMessage(messageIndex);
require(valid, "StakingManager: Invalid warp message");

require(
Expand Down Expand Up @@ -312,11 +341,11 @@
uint64 uptimeSeconds;
if (includeUptimeProof) {
(WarpMessage memory warpMessage, bool valid) =
$._warpMessenger.getVerifiedWarpMessage(messageIndex);
WARP_MESSENGER.getVerifiedWarpMessage(messageIndex);
require(valid, "StakingManager: Invalid warp message");

require(
warpMessage.sourceChainID == $._warpMessenger.getBlockchainID(),
warpMessage.sourceChainID == WARP_MESSENGER.getBlockchainID(),
"StakingManager: Invalid source chain ID"
);
require(
Expand All @@ -341,7 +370,7 @@
bytes memory setValidatorWeightPayload = StakingMessages.packSetSubnetValidatorWeightMessage(
validationID, validator.messageNonce, 0
);
bytes32 messageID = $._warpMessenger.sendWarpMessage(setValidatorWeightPayload);
bytes32 messageID = WARP_MESSENGER.sendWarpMessage(setValidatorWeightPayload);

// Emit the event to signal the start of the validator removal process.
emit ValidatorRemovalInitialized(
Expand All @@ -366,7 +395,7 @@
bytes memory setValidatorWeightPayload = StakingMessages.packSetSubnetValidatorWeightMessage(
validationID, validator.messageNonce, 0
);
$._warpMessenger.sendWarpMessage(setValidatorWeightPayload);
WARP_MESSENGER.sendWarpMessage(setValidatorWeightPayload);
}

/**
Expand All @@ -384,7 +413,7 @@

// Get the Warp message.
(WarpMessage memory warpMessage, bool valid) =
$._warpMessenger.getVerifiedWarpMessage(messageIndex);
WARP_MESSENGER.getVerifiedWarpMessage(messageIndex);
require(valid, "StakingManager: Invalid warp message");

bytes32 validationID;
Expand Down
Loading