View Source: contracts/governance/Staking/modules/StakingGovernanceModule.sol
↗ Extends: IFunctionsList, StakingShared, CheckpointsShared
Implements voting power and delegation functionality
- getPriorTotalVotingPower(uint32 blockNumber, uint256 time)
- _totalPowerByDate(uint256 date, uint256 startDate, uint256 blockNumber)
- getCurrentVotes(address account)
- getPriorVotes(address account, uint256 blockNumber, uint256 date)
- _totalPowerByDateForDelegatee(address account, uint256 date, uint256 startDate, uint256 blockNumber)
- getPriorStakeByDateForDelegatee(address account, uint256 date, uint256 blockNumber)
- _getPriorStakeByDateForDelegatee(address account, uint256 date, uint256 blockNumber)
- getPriorTotalStakesForDate(uint256 date, uint256 blockNumber)
- _getPriorTotalStakesForDate(uint256 date, uint256 blockNumber)
- _delegate(address delegator, address delegatee, uint256 lockedTS)
- _delegateNext(address delegator, address delegatee, uint256 lockedTS)
- _moveDelegates(address srcRep, address dstRep, uint96 amount, uint256 lockedTS)
- _getChainId()
- delegate(address delegatee, uint256 lockDate)
- getFunctionsList()
Compute the total voting power at a given time.
function getPriorTotalVotingPower(uint32 blockNumber, uint256 time) public view
returns(totalVotingPower uint96)
Arguments
Name | Type | Description |
---|---|---|
blockNumber | uint32 | The block number, needed for checkpointing. |
time | uint256 | The timestamp for which to calculate the total voting power. |
Returns
The total voting power at the given time.
Source Code
function getPriorTotalVotingPower(uint32 blockNumber, uint256 time)
public
view
returns (uint96 totalVotingPower)
{
/// @dev Start the computation with the exact or previous unlocking date (voting weight remians the same until the next break point).
uint256 start = _timestampToLockDate(time);
uint256 end = start + MAX_DURATION;
/// @dev Max 78 iterations.
for (uint256 i = start; i <= end; i += TWO_WEEKS) {
totalVotingPower = add96(
totalVotingPower,
_totalPowerByDate(i, start, blockNumber),
"arrays mismatch"
); // WS06
}
}
Compute the voting power for a specific date. Power = stake * weight
function _totalPowerByDate(uint256 date, uint256 startDate, uint256 blockNumber) internal view
returns(power uint96)
Arguments
Name | Type | Description |
---|---|---|
date | uint256 | The staking date to compute the power for. |
startDate | uint256 | The date for which we need to know the power of the stake. |
blockNumber | uint256 | The block number, needed for checkpointing. |
Returns
The stacking power.
Source Code
function _totalPowerByDate(
uint256 date,
uint256 startDate,
uint256 blockNumber
) internal view returns (uint96 power) {
uint96 weight = _computeWeightByDate(date, startDate);
uint96 staked = _getPriorTotalStakesForDate(date, blockNumber);
/// @dev weight is multiplied by some factor to allow decimals.
power = mul96(staked, weight, "mul overflow") / WEIGHT_FACTOR; // WS07
}
Get the current votes balance for a user account.
function getCurrentVotes(address account) external view
returns(uint96)
Arguments
Name | Type | Description |
---|---|---|
account | address | The address to get votes balance. |
Returns
The number of current votes for a user account.
Source Code
function getCurrentVotes(address account) external view returns (uint96) {
return getPriorVotes(account, block.number - 1, block.timestamp);
}
Determine the prior number of votes for a delegatee as of a block number. Iterate through checkpoints adding up voting power.
function getPriorVotes(address account, uint256 blockNumber, uint256 date) public view
returns(votes uint96)
Arguments
Name | Type | Description |
---|---|---|
account | address | The address of the account to check. |
blockNumber | uint256 | The block number to get the vote balance at. |
date | uint256 | The staking date to compute the power for. |
Returns
The number of votes the delegatee had as of the given block.
Source Code
function getPriorVotes(
address account,
uint256 blockNumber,
uint256 date
) public view returns (uint96 votes) {
/// @dev If date is not an exact break point, start weight computation from the previous break point (alternative would be the next).
uint256 start = _timestampToLockDate(date);
uint256 end = start + MAX_DURATION;
/// @dev Max 78 iterations.
for (uint256 i = start; i <= end; i += TWO_WEEKS) {
votes = add96(
votes,
_totalPowerByDateForDelegatee(account, i, start, blockNumber),
"overflow - total VP"
); // WS09
}
}
Compute the voting power for a specific date. Power = stake * weight
function _totalPowerByDateForDelegatee(address account, uint256 date, uint256 startDate, uint256 blockNumber) internal view
returns(power uint96)
Arguments
Name | Type | Description |
---|---|---|
account | address | The address of the account to check. |
date | uint256 | The staking date to compute the power for. |
startDate | uint256 | The date for which we need to know the power of the stake. |
blockNumber | uint256 | The block number, needed for checkpointing. |
Returns
The stacking power.
Source Code
function _totalPowerByDateForDelegatee(
address account,
uint256 date,
uint256 startDate,
uint256 blockNumber
) internal view returns (uint96 power) {
uint96 weight = _computeWeightByDate(date, startDate);
uint96 staked = _getPriorStakeByDateForDelegatee(account, date, blockNumber);
power = mul96(staked, weight, "mul overflow") / WEIGHT_FACTOR; // WS10
}
Determine the prior number of stake for an account as of a block number.
function getPriorStakeByDateForDelegatee(address account, uint256 date, uint256 blockNumber) external view
returns(uint96)
Arguments
Name | Type | Description |
---|---|---|
account | address | The address of the account to check. |
date | uint256 | The staking date to compute the power for. Adjusted to the next valid lock date, if necessary. |
blockNumber | uint256 | The block number to get the vote balance at. |
Returns
The number of votes the account had as of the given block.
Source Code
function getPriorStakeByDateForDelegatee(
address account,
uint256 date,
uint256 blockNumber
) external view returns (uint96) {
date = _adjustDateForOrigin(date);
return _getPriorStakeByDateForDelegatee(account, date, blockNumber);
}
Determine the prior number of stake for an account as of a block number.
function _getPriorStakeByDateForDelegatee(address account, uint256 date, uint256 blockNumber) internal view
returns(uint96)
Arguments
Name | Type | Description |
---|---|---|
account | address | The address of the account to check. |
date | uint256 | The staking date to compute the power for. |
blockNumber | uint256 | The block number to get the vote balance at. |
Returns
The number of votes the account had as of the given block.
Source Code
function _getPriorStakeByDateForDelegatee(
address account,
uint256 date,
uint256 blockNumber
) internal view returns (uint96) {
require(blockNumber < _getCurrentBlockNumber(), "not determined yet"); // WS11
uint32 nCheckpoints = numDelegateStakingCheckpoints[account][date];
if (nCheckpoints == 0) {
return 0;
}
/// @dev First check most recent balance.
if (delegateStakingCheckpoints[account][date][nCheckpoints - 1].fromBlock <= blockNumber) {
return delegateStakingCheckpoints[account][date][nCheckpoints - 1].stake;
}
/// @dev Next check implicit zero balance.
if (delegateStakingCheckpoints[account][date][0].fromBlock > blockNumber) {
return 0;
}
uint32 lower = 0;
uint32 upper = nCheckpoints - 1;
while (upper > lower) {
uint32 center = upper - (upper - lower) / 2; /// @dev ceil, avoiding overflow.
Checkpoint memory cp = delegateStakingCheckpoints[account][date][center];
if (cp.fromBlock == blockNumber) {
return cp.stake;
} else if (cp.fromBlock < blockNumber) {
lower = center;
} else {
upper = center - 1;
}
}
return delegateStakingCheckpoints[account][date][lower].stake;
}
Determine the prior number of stake for an unlocking date as of a block number.
function getPriorTotalStakesForDate(uint256 date, uint256 blockNumber) public view
returns(uint96)
Arguments
Name | Type | Description |
---|---|---|
date | uint256 | The date to check the stakes for. Adjusted to the next valid lock date, as necessary |
blockNumber | uint256 | The block number to get the vote balance at. |
Returns
The total number of votes as of the given block.
Source Code
function getPriorTotalStakesForDate(uint256 date, uint256 blockNumber)
public
view
returns (uint96)
{
date = _adjustDateForOrigin(date);
return _getPriorTotalStakesForDate(date, blockNumber);
}
Determine the prior number of stake for an unlocking date as of a block number.
function _getPriorTotalStakesForDate(uint256 date, uint256 blockNumber) internal view
returns(uint96)
Arguments
Name | Type | Description |
---|---|---|
date | uint256 | The date to check the stakes for. |
blockNumber | uint256 | The block number to get the vote balance at. |
Returns
The total number of votes as of the given block.
Source Code
function _getPriorTotalStakesForDate(uint256 date, uint256 blockNumber)
internal
view
returns (uint96)
{
require(blockNumber < _getCurrentBlockNumber(), "not determined"); // WS08
uint32 nCheckpoints = numTotalStakingCheckpoints[date];
if (nCheckpoints == 0) {
return 0;
}
// First check most recent balance
if (totalStakingCheckpoints[date][nCheckpoints - 1].fromBlock <= blockNumber) {
return totalStakingCheckpoints[date][nCheckpoints - 1].stake;
}
// Next check implicit zero balance
if (totalStakingCheckpoints[date][0].fromBlock > blockNumber) {
return 0;
}
uint32 lower = 0;
uint32 upper = nCheckpoints - 1;
while (upper > lower) {
uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
Checkpoint memory cp = totalStakingCheckpoints[date][center];
if (cp.fromBlock == blockNumber) {
return cp.stake;
} else if (cp.fromBlock < blockNumber) {
lower = center;
} else {
upper = center - 1;
}
}
return totalStakingCheckpoints[date][lower].stake;
}
Set new delegatee. Move from user's current delegate to a new delegatee the stake balance.
function _delegate(address delegator, address delegatee, uint256 lockedTS) internal nonpayable
Arguments
Name | Type | Description |
---|---|---|
delegator | address | The user address to move stake balance from its current delegatee. |
delegatee | address | The new delegatee. The address to move stake balance to. |
lockedTS | uint256 | The lock date. |
Source Code
function _delegate(
address delegator,
address delegatee,
uint256 lockedTS
) internal {
address currentDelegate = delegates[delegator][lockedTS];
uint96 delegatorBalance = _currentBalance(delegator, lockedTS);
// vesting contracts will in multiple cases try to delegate a zero balance
// or to the existing delegatee
if (_isVestingContract(msg.sender)) {
if (delegatorBalance == 0 || currentDelegate == delegatee) {
return;
}
} else {
require(delegatorBalance > 0, "no stake to delegate");
require(currentDelegate != delegatee, "cannot delegate to the existing delegatee");
}
delegates[delegator][lockedTS] = delegatee;
emit DelegateChanged(delegator, lockedTS, currentDelegate, delegatee);
_moveDelegates(currentDelegate, delegatee, delegatorBalance, lockedTS);
}
function _delegateNext(address delegator, address delegatee, uint256 lockedTS) internal nonpayable
Arguments
Name | Type | Description |
---|---|---|
delegator | address | |
delegatee | address | |
lockedTS | uint256 |
Source Code
function _delegateNext(
address delegator,
address delegatee,
uint256 lockedTS
) internal {
if (_isVestingContract(msg.sender)) {
uint256 nextLock = lockedTS.add(TWO_WEEKS);
address currentDelegate = delegates[delegator][nextLock];
if (currentDelegate != delegatee) {
_delegate(delegator, delegatee, nextLock);
}
// @dev workaround for the issue with a delegation of the latest stake
uint256 endDate = IVesting(msg.sender).endDate();
nextLock = lockedTS.add(FOUR_WEEKS);
if (nextLock == endDate) {
currentDelegate = delegates[delegator][nextLock];
if (currentDelegate != delegatee) {
_delegate(delegator, delegatee, nextLock);
}
}
}
}
Move an amount of delegate stake from a source address to a destination address.
function _moveDelegates(address srcRep, address dstRep, uint96 amount, uint256 lockedTS) internal nonpayable
Arguments
Name | Type | Description |
---|---|---|
srcRep | address | The address to get the staked amount from. |
dstRep | address | The address to send the staked amount to. |
amount | uint96 | The staked amount to move. |
lockedTS | uint256 | The lock date. |
Source Code
function _moveDelegates(
address srcRep,
address dstRep,
uint96 amount,
uint256 lockedTS
) internal {
if (srcRep != dstRep && amount > 0) {
if (srcRep != address(0)) _decreaseDelegateStake(srcRep, lockedTS, amount);
if (dstRep != address(0)) _increaseDelegateStake(dstRep, lockedTS, amount);
}
}
Retrieve CHAIN_ID of the executing chain. * Chain identifier (chainID) introduced in EIP-155 protects transaction included into one chain from being included into another chain. Basically, chain identifier is an integer number being used in the processes of signing transactions and verifying transaction signatures. *
function _getChainId() internal pure
returns(uint256)
Source Code
function _getChainId() internal pure returns (uint256) {
uint256 chainId;
assembly {
chainId := chainid()
}
return chainId;
}
Delegate votes from msg.sender
which are locked until lockDate to delegatee
.
function delegate(address delegatee, uint256 lockDate) external nonpayable whenNotPaused
Arguments
Name | Type | Description |
---|---|---|
delegatee | address | The address to delegate votes to. |
lockDate | uint256 | the date if the position to delegate. |
Source Code
function delegate(address delegatee, uint256 lockDate) external whenNotPaused {
require(delegatee != address(0), "cannot delegate to the zero address");
_notSameBlockAsStakingCheckpoint(lockDate, msg.sender);
_delegate(msg.sender, delegatee, lockDate);
// @dev delegates tokens for lock date 2 weeks later than given lock date
// if message sender is a contract
_delegateNext(msg.sender, delegatee, lockDate);
}
⤾ overrides IFunctionsList.getFunctionsList
function getFunctionsList() external pure
returns(bytes4[])
Source Code
function getFunctionsList() external pure returns (bytes4[] memory) {
bytes4[] memory functionsList = new bytes4[](6);
functionsList[0] = this.getPriorTotalVotingPower.selector;
functionsList[1] = this.getCurrentVotes.selector;
functionsList[2] = this.getPriorVotes.selector;
functionsList[3] = this.getPriorStakeByDateForDelegatee.selector;
functionsList[4] = this.getPriorTotalStakesForDate.selector;
functionsList[5] = this.delegate.selector;
return functionsList;
}
- Address
- Administered
- AdminRole
- AdvancedToken
- AdvancedTokenStorage
- Affiliates
- AffiliatesEvents
- ApprovalReceiver
- BProPriceFeed
- CheckpointsShared
- Constants
- Context
- DevelopmentFund
- DummyContract
- EnumerableAddressSet
- EnumerableBytes32Set
- EnumerableBytes4Set
- ERC20
- ERC20Detailed
- ErrorDecoder
- Escrow
- EscrowReward
- FeedsLike
- FeesEvents
- FeeSharingCollector
- FeeSharingCollectorProxy
- FeeSharingCollectorStorage
- FeesHelper
- FourYearVesting
- FourYearVestingFactory
- FourYearVestingLogic
- FourYearVestingStorage
- GenericTokenSender
- GovernorAlpha
- GovernorVault
- IApproveAndCall
- IChai
- IContractRegistry
- IConverterAMM
- IERC1820Registry
- IERC20_
- IERC20
- IERC777
- IERC777Recipient
- IERC777Sender
- IFeeSharingCollector
- IFourYearVesting
- IFourYearVestingFactory
- IFunctionsList
- ILiquidityMining
- ILiquidityPoolV1Converter
- ILoanPool
- ILoanToken
- ILoanTokenLogicBeacon
- ILoanTokenLogicModules
- ILoanTokenLogicProxy
- ILoanTokenModules
- ILoanTokenWRBTC
- ILockedSOV
- IMoCState
- IModulesProxyRegistry
- Initializable
- InterestUser
- IPot
- IPriceFeeds
- IPriceFeedsExt
- IProtocol
- IRSKOracle
- ISovryn
- ISovrynSwapNetwork
- IStaking
- ISwapsImpl
- ITeamVesting
- ITimelock
- IV1PoolOracle
- IVesting
- IVestingFactory
- IVestingRegistry
- IWrbtc
- IWrbtcERC20
- LenderInterestStruct
- LiquidationHelper
- LiquidityMining
- LiquidityMiningConfigToken
- LiquidityMiningProxy
- LiquidityMiningStorage
- LoanClosingsEvents
- LoanClosingsLiquidation
- LoanClosingsRollover
- LoanClosingsShared
- LoanClosingsWith
- LoanClosingsWithoutInvariantCheck
- LoanInterestStruct
- LoanMaintenance
- LoanMaintenanceEvents
- LoanOpenings
- LoanOpeningsEvents
- LoanParamsStruct
- LoanSettings
- LoanSettingsEvents
- LoanStruct
- LoanToken
- LoanTokenBase
- LoanTokenLogicBeacon
- LoanTokenLogicLM
- LoanTokenLogicProxy
- LoanTokenLogicStandard
- LoanTokenLogicStorage
- LoanTokenLogicWrbtc
- LoanTokenSettingsLowerAdmin
- LockedSOV
- MarginTradeStructHelpers
- Medianizer
- ModuleCommonFunctionalities
- ModulesCommonEvents
- ModulesProxy
- ModulesProxyRegistry
- MultiSigKeyHolders
- MultiSigWallet
- Mutex
- Objects
- OrderStruct
- OrigingVestingCreator
- OriginInvestorsClaim
- Ownable
- Pausable
- PausableOz
- PreviousLoanToken
- PreviousLoanTokenSettingsLowerAdmin
- PriceFeedRSKOracle
- PriceFeeds
- PriceFeedsLocal
- PriceFeedsMoC
- PriceFeedV1PoolOracle
- ProtocolAffiliatesInterface
- ProtocolLike
- ProtocolSettings
- ProtocolSettingsEvents
- ProtocolSettingsLike
- ProtocolSwapExternalInterface
- ProtocolTokenUser
- Proxy
- ProxyOwnable
- ReentrancyGuard
- RewardHelper
- RSKAddrValidator
- SafeERC20
- SafeMath
- SafeMath96
- setGet
- SharedReentrancyGuard
- SignedSafeMath
- SOV
- sovrynProtocol
- StakingAdminModule
- StakingGovernanceModule
- StakingInterface
- StakingProxy
- StakingRewards
- StakingRewardsProxy
- StakingRewardsStorage
- StakingShared
- StakingStakeModule
- StakingStorageModule
- StakingStorageShared
- StakingVestingModule
- StakingWithdrawModule
- State
- SwapsEvents
- SwapsExternal
- SwapsImplLocal
- SwapsImplSovrynSwap
- SwapsUser
- TeamVesting
- Timelock
- TimelockHarness
- TimelockInterface
- TokenSender
- UpgradableProxy
- USDTPriceFeed
- Utils
- VaultController
- Vesting
- VestingCreator
- VestingFactory
- VestingLogic
- VestingRegistry
- VestingRegistry2
- VestingRegistry3
- VestingRegistryLogic
- VestingRegistryProxy
- VestingRegistryStorage
- VestingStorage
- WeightedStakingModule
- WRBTC