The Stakinator Facet is a core component of the Vaultinator Protocol that provides staking functionality. This document outlines the technical implementation details, including the contract architecture, function specifications, storage layout, and security considerations.
Contract Architecture
The Stakinator Facet follows the Diamond Standard (EIP-2535) pattern and is implemented as a facet that can be added to the Vaultinator Diamond. It manages staking pools and user stakes through a standardized interface.
The Stakinator Facet uses the Diamond Storage pattern to store its state. The storage layout is defined in the LibStakinatorStorage library.
Events
The Stakinator Facet emits the following events:
Security Considerations
Reentrancy Protection
The Stakinator Facet uses a reentrancy guard to prevent reentrancy attacks. All external functions that interact with other contracts are protected by the reentrancy guard.
Access Control
The Stakinator Facet uses role-based access control to restrict access to certain functions. The access control is implemented through the Vaultinator Facet.
Pause Mechanism
The Stakinator Facet includes a pause mechanism that allows administrators to pause all operations in case of an emergency.
Lock Period Enforcement
The Stakinator Facet enforces lock periods for stakes. Users cannot unstake their tokens until the lock period has ended.
Emergency Unstake
The Stakinator Facet includes an emergency unstake function that allows users to unstake their tokens before the lock period has ended, but with a penalty.
Reward Calculation
The Stakinator Facet uses a time-based reward calculation to ensure that rewards are distributed fairly.
Integration with Other Facets
The Stakinator Facet integrates with other facets in the Vaultinator Protocol:
Vaultinator Facet: For vault management and access control
Yieldinator Facet: For staking yield-generating assets
Collatinator Facet: For using staked assets as collateral
Vaultinator Integration
Yieldinator Integration
Collatinator Integration
Staking Strategies
The Stakinator Facet supports multiple staking strategies:
Fixed APR Staking
Fixed APR staking provides a guaranteed return on staked assets, regardless of external factors.
Variable APR Staking
Variable APR staking provides a return that varies based on external factors, such as protocol performance.
Tiered Staking
Tiered staking provides different APRs based on the amount staked and the lock duration.
Boosted Staking
Boosted staking provides increased rewards for users who also stake a secondary token.
Conclusion
The Stakinator Facet is a powerful component of the Vaultinator Protocol that enables users to stake tokens and earn rewards. Its modular design, security features, and integration with other facets make it a flexible and robust solution for staking.
function calculateRewards(uint256 stakeId) internal view returns (uint256) {
LibStakinatorStorage.StakinatorStorage storage s = LibStakinatorStorage.stakinatorStorage();
LibStakinatorStorage.Stake storage stake = s.stakes[stakeId];
LibStakinatorStorage.Pool storage pool = s.pools[stake.poolId];
uint256 timeStaked = block.timestamp - stake.createdAt;
uint256 apr = pool.apr;
uint256 rewards = stake.amount * apr * timeStaked / (365 days * 10000); // APR is in basis points
return rewards - stake.rewardsClaimed;
}
function stakeFromVault(uint256 vaultId, uint256 poolId, uint256 amount, uint256 lockDuration) external nonReentrant whenNotPaused onlyVaultOwner(vaultId) returns (uint256) {
// Implementation details...
// Transfer assets from vault to this contract
// Create stake
// Update vault balance
// More implementation details...
emit VaultStaked(vaultId, stakeId, poolId, amount, lockDuration);
return stakeId;
}
function stakeYieldToken(uint256 poolId, address yieldAdapter, address asset, uint256 amount, uint256 lockDuration) external nonReentrant whenNotPaused returns (uint256) {
// Implementation details...
// Transfer yield token from Yieldinator to this contract
// Create stake
// More implementation details...
return stakeId;
}
function useStakeAsCollateral(uint256 stakeId, address protocol, address debtAsset, uint256 debtAmount) external nonReentrant whenNotPaused onlyStakeOwner(stakeId) returns (uint256) {
// Implementation details...
// Check if stake can be used as collateral
// Create collateralized position
// More implementation details...
return positionId;
}
function createFixedAPRPool(
address stakingToken,
address rewardToken,
uint256 apr,
uint256 minStake,
uint256 maxStake,
uint256 lockDuration
) external onlyAdmin returns (uint256) {
// Implementation details...
// Create pool with fixed APR
// More implementation details...
return poolId;
}
function createVariableAPRPool(
address stakingToken,
address rewardToken,
address aprOracle,
uint256 minStake,
uint256 maxStake,
uint256 lockDuration
) external onlyAdmin returns (uint256) {
// Implementation details...
// Create pool with variable APR
// More implementation details...
return poolId;
}
function updateVariableAPR(uint256 poolId) external onlyAdmin returns (uint256) {
// Implementation details...
// Update APR based on oracle
// More implementation details...
return newAPR;
}
function createTieredPool(
address stakingToken,
address rewardToken,
uint256[] memory tiers,
uint256[] memory aprs,
uint256[] memory lockDurations
) external onlyAdmin returns (uint256) {
// Implementation details...
// Create pool with tiered APRs
// More implementation details...
return poolId;
}
function getTierAPR(uint256 poolId, uint256 amount, uint256 lockDuration) external view returns (uint256) {
// Implementation details...
// Calculate APR based on amount and lock duration
// More implementation details...
return apr;
}