Skip to main content

Power

1. Summary​

The vePWN Power contract provides computation functions for voting power in PWN DAO. This contract is inherited by vePWN.

3. Contract details​

  • VoteEscrowedPWNPower.sol is written in Solidity version 0.8.25

Features​

  • Calculate voting power for stakers
  • Calculate total voting power for an epoch(s)
  • Get all stake IDs of a staker in given epoch

Inherited contracts, implemented Interfaces and ERCs​

Functions​

stakePowers(uint256 initialEpoch, uint256 amount, uint256 lockUpEpochs)

Overview​

Function to compute powers in epochs for given stake parameters.

This function takes three arguments:

  • uint256initialEpoch - initial epoch of the stake power
  • uint256amount - amount of PWN tokens staked
  • uint256lockUpEpochs - number of epochs the stake is locked up for

Implementation​

function stakePowers(uint256 initialEpoch, uint256 amount, uint256 lockUpEpochs)
external
pure
returns (EpochPower[] memory powers)
{
if (amount < 100 || amount % 100 > 0 || amount > type(uint88).max) {
revert Error.InvalidAmount();
}
if (lockUpEpochs < 1 || lockUpEpochs > EPOCHS_IN_YEAR * 10) {
revert Error.InvalidLockUpPeriod();
}
// calculate how many epochs are needed
uint256 epochs;
if (lockUpEpochs > EPOCHS_IN_YEAR * 5) {
epochs = 7;
} else {
epochs = lockUpEpochs / EPOCHS_IN_YEAR + (lockUpEpochs % EPOCHS_IN_YEAR > 0 ? 2 : 1);
}

powers = new EpochPower[](epochs);
uint16 epoch = SafeCast.toUint16(initialEpoch);
uint8 remainingLockup = uint8(lockUpEpochs);
int104 _amount = SafeCast.toInt104(int256(uint256(amount)));
int104 power = _power(_amount, remainingLockup);
// calculate epoch powers
powers[0] = EpochPower({ epoch: epoch, power: power });
for (uint256 i = 1; i < epochs; ++i) {
uint8 epochsToNextPowerChange = _epochsToNextPowerChange(remainingLockup);
remainingLockup -= epochsToNextPowerChange;
epoch += epochsToNextPowerChange;
power += _powerDecrease(_amount, remainingLockup);
powers[i] = EpochPower({ epoch: epoch, power: power });
}
}
stakerPowers(address staker, uint256[] calldata epochs)

Overview​

Function to compute power of a staker at given epochs.

This function takes two arguments:

  • addressstaker
  • uint256[] calldataepochs

Implementation​

function stakerPowers(address staker, uint256[] calldata epochs) external view returns (uint256[] memory) {
uint256[] memory powers = new uint256[](epochs.length);
for (uint256 i; i < epochs.length;) {
powers[i] = stakerPowerAt({
staker: staker,
epoch: epochs[i]
});
unchecked { ++i; }
}
return powers;
}
stakerPowerAt

Overview​

Function to compute staker power at the given epoch.

This function takes two arguments:

  • addressstaker
  • uint256epoch

Implementation​

function stakerPowerAt(address staker, uint256 epoch) override virtual public view returns (uint256) {
uint16 _epoch = SafeCast.toUint16(epoch);
uint256[] memory stakeIds = beneficiaryOfStakesAt(staker, _epoch);
uint256 stakesLength = stakeIds.length;
int104 power;
for (uint256 i; i < stakesLength;) {
// sum up all stake powers
power += _stakePowerAt({
stake: _stakes[stakeIds[i]],
epoch: _epoch
});

unchecked { ++i; }
}

return SafeCast.toUint256(int256(power));
}
beneficiaryOfStakesAt

Overview​

Function to get the list of stake IDs the staker is a beneficiary of in an given epoch.

This function takes two arguments:

  • addressstaker
  • uint16epoch

Implementation​

function beneficiaryOfStakesAt(address staker, uint16 epoch) public view returns (uint256[] memory) {
StakesInEpoch[] storage stakesInEpoch = beneficiaryOfStakes[staker];
// no owned stakes
if (stakesInEpoch.length == 0) {
return new uint256[](0);
}
// first owned stake is in the future
if (epoch < stakesInEpoch[0].epoch) {
return new uint256[](0);
}

// find change epoch
uint256 changeIndex = stakesInEpoch.length - 1;
while (stakesInEpoch[changeIndex].epoch > epoch) {
changeIndex--;
}

// collect ids as uint256
uint256 length = stakesInEpoch[changeIndex].ids.length;
uint256[] memory ids = new uint256[](length);
for (uint256 i; i < length;) {
ids[i] = stakesInEpoch[changeIndex].ids[i];
unchecked { ++i; }
}

return ids;
}
totalPowers

Overview​

Function to get total power at given epochs.

This function takes one argument:

  • uint256[] calldataepochs

Implementation​

function totalPowers(uint256[] calldata epochs) external view returns (uint256[] memory) {
uint256[] memory powers = new uint256[](epochs.length);
for (uint256 i; i < epochs.length;) {
powers[i] = totalPowerAt(epochs[i]);
unchecked { ++i; }
}
return powers;
}
totalPowerAt

Overview​

Function to get total power at a given epoch.

This function takes one argument:

  • uint256epoch

Implementation​

function totalPowerAt(uint256 epoch) override virtual public view returns (uint256) {
if (lastCalculatedTotalPowerEpoch >= epoch) {
return SafeCast.toUint256(int256(TOTAL_POWER_NAMESPACE.getEpochPower(epoch)));
}

// sum the rest of epochs
int104 totalPower;
for (uint256 i = lastCalculatedTotalPowerEpoch; i <= epoch;) {
totalPower += TOTAL_POWER_NAMESPACE.getEpochPower(i);
unchecked { ++i; }
}

return SafeCast.toUint256(int256(totalPower));
}
calculateTotalPower

Overview​

Function to calculate total power in current epoch.

This function doesn't take any arguments.

Implementation​

function calculateTotalPower() external {
calculateTotalPowerUpTo(epochClock.currentEpoch());
}
calculateTotalPowerUpTo

Overview​

Function to calculate total power for all epochs up to the given epoch.

This function takes one argument:

  • uint256epoch

Implementation​

function calculateTotalPowerUpTo(uint256 epoch) public {
if (epoch > epochClock.currentEpoch()) {
revert Error.EpochStillRunning();
}
if (lastCalculatedTotalPowerEpoch >= epoch) {
revert Error.PowerAlreadyCalculated(lastCalculatedTotalPowerEpoch);
}

for (uint256 i = lastCalculatedTotalPowerEpoch; i < epoch;) {
TOTAL_POWER_NAMESPACE.updateEpochPower({
epoch: i + 1,
power: TOTAL_POWER_NAMESPACE.getEpochPower(i)
});

unchecked { ++i; }
}

lastCalculatedTotalPowerEpoch = epoch;

emit TotalPowerCalculated(epoch);
}

Events​

event TotalPowerCalculated(uint256 indexed epoch);
TotalPowerCalculated

TotalPowerCalculated event is emitted when the total power for an epoch is calculated.

This event has one parameter:

  • uint256 indexedepoch

EpochPower Struct​

struct EpochPower {
uint16 epoch;
int104 power;
}