Skip to content

Commit

Permalink
Add inflation
Browse files Browse the repository at this point in the history
  • Loading branch information
varasev committed Feb 19, 2020
1 parent 43b2582 commit 16ed5ff
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 24 deletions.
23 changes: 23 additions & 0 deletions contracts/base/BlockRewardAuRaBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,8 @@ contract BlockRewardAuRaBase is UpgradeableOwned, IBlockRewardAuRa {
uint256 internal constant VALIDATOR_MIN_REWARD_PERCENT = 30; // 30%
uint256 internal constant REWARD_PERCENT_MULTIPLIER = 1000000;

function _coinInflationAmount(uint256, address[] memory) internal view returns(uint256);

/// @dev Distributes rewards in native coins among pools at the latest block of a staking epoch.
/// This function is called by the `_distributeRewards` function.
/// @param _stakingEpoch The number of the current staking epoch.
Expand All @@ -583,6 +585,8 @@ contract BlockRewardAuRaBase is UpgradeableOwned, IBlockRewardAuRa {
) internal returns(uint256) {
uint256 totalReward = bridgeNativeFee + nativeRewardUndistributed;

totalReward += _coinInflationAmount(_stakingEpoch, _validators);

if (totalReward == 0) {
return 0;
}
Expand Down Expand Up @@ -690,6 +694,25 @@ contract BlockRewardAuRaBase is UpgradeableOwned, IBlockRewardAuRa {
return block.number;
}

/// @dev Calculates and returns inflation amount based on the specified
/// staking epoch, validator set, and inflation rate.
/// Used by `_coinInflationAmount` and `_distributeTokenRewards` functions.
/// @param _stakingEpoch The number of the current staking epoch.
/// @param _validators The array of the current validators (their mining addresses).
/// @param _inflationRate Inflation rate.
function _inflationAmount(
uint256 _stakingEpoch,
address[] memory _validators,
uint256 _inflationRate
) internal view returns(uint256) {
if (_inflationRate == 0) return 0;
uint256 snapshotTotalStakeAmount = 0;
for (uint256 i = 0; i < _validators.length; i++) {
snapshotTotalStakeAmount += snapshotPoolTotalStakeAmount[_stakingEpoch][_validators[i]];
}
return snapshotTotalStakeAmount * _inflationRate / 1 ether;
}

/// @dev Joins two native coin receiver elements into a single set and returns the result
/// to the `reward` function: the first element comes from the `erc-to-native` bridge fee distribution,
/// the second - from the `erc-to-native` bridge when native coins are minted for the specified addresses.
Expand Down
21 changes: 21 additions & 0 deletions contracts/base/BlockRewardAuRaCoins.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ import "../interfaces/IBlockRewardAuRaCoins.sol";

contract BlockRewardAuRaCoins is BlockRewardAuRaBase, IBlockRewardAuRaCoins {

// ============================================== Constants =======================================================

/// @dev Inflation rate per staking epoch. Calculated as follows:
/// 2.5% annual rate * 52 weeks per year / 100 * 10^18
/// This assumes that 1 staking epoch = 1 week
/// i.e. Inflation Rate = 2.5/52/100 * 1 ether
/// Recalculate it for different annual rate and/or different staking epoch duration.
uint256 public constant NATIVE_COIN_INFLATION_RATE = 480769230769231;

// =============================================== Setters ========================================================

/// @dev Called by the `StakingAuRa.claimReward` function to transfer native coins
Expand Down Expand Up @@ -65,6 +74,18 @@ contract BlockRewardAuRaCoins is BlockRewardAuRaBase, IBlockRewardAuRaCoins {

// ============================================== Internal ========================================================

/// @dev Calculates and returns inflation amount based on the specified
/// staking epoch and validator set. Uses NATIVE_COIN_INFLATION_RATE constant.
/// Used by `_distributeNativeRewards` internal function.
/// @param _stakingEpoch The number of the current staking epoch.
/// @param _validators The array of the current validators (their mining addresses).
function _coinInflationAmount(
uint256 _stakingEpoch,
address[] memory _validators
) internal view returns(uint256) {
return _inflationAmount(_stakingEpoch, _validators, NATIVE_COIN_INFLATION_RATE);
}

function _distributeTokenRewards(
address, uint256, uint256, uint256, address[] memory, uint256[] memory, uint256
) internal {
Expand Down
17 changes: 17 additions & 0 deletions contracts/base/BlockRewardAuRaTokens.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ contract BlockRewardAuRaTokens is BlockRewardAuRaBase, IBlockRewardAuRaTokens {
/// @dev The total reward amount in staking tokens which is not yet distributed among pools.
uint256 public tokenRewardUndistributed;

// ============================================== Constants =======================================================

/// @dev Inflation rate per staking epoch. Calculated as follows:
/// 15% annual rate * 52 weeks per year / 100 * 10^18
/// This assumes that 1 staking epoch = 1 week
/// i.e. Inflation Rate = 15/52/100 * 1 ether
/// Recalculate it for different annual rate and/or different staking epoch duration.
uint256 public constant STAKE_TOKEN_INFLATION_RATE = 2884615384615380;

// ================================================ Events ========================================================

/// @dev Emitted by the `addBridgeTokenFeeReceivers` function.
Expand Down Expand Up @@ -185,6 +194,12 @@ contract BlockRewardAuRaTokens is BlockRewardAuRaBase, IBlockRewardAuRaTokens {

// ============================================== Internal ========================================================

/// @dev See the description of `BlockRewardAuRaCoins._coinInflationAmount` internal function.
/// In this case (when ERC tokens are used for staking) the inflation for native coins is zero.
function _coinInflationAmount(uint256, address[] memory) internal view returns(uint256) {
return 0;
}

/// @dev Distributes rewards in tokens among pools at the latest block of a staking epoch.
/// This function is called by the `_distributeRewards` function.
/// @param _stakingContract The address of the StakingAuRa contract.
Expand All @@ -205,6 +220,8 @@ contract BlockRewardAuRaTokens is BlockRewardAuRaBase, IBlockRewardAuRaTokens {
) internal {
uint256 totalReward = bridgeTokenFee + tokenRewardUndistributed;

totalReward += _inflationAmount(_stakingEpoch, _validators, STAKE_TOKEN_INFLATION_RATE);

if (totalReward == 0) {
return;
}
Expand Down
49 changes: 48 additions & 1 deletion test/BlockRewardAuRa.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ contract('BlockRewardAuRa', async accounts => {
let candidateMinStake;
let delegatorMinStake;
let tokenRewardUndistributed = new BN(0);
let stakeTokenInflationRate;

const COLLECT_ROUND_LENGTH = 114;
const STAKING_EPOCH_DURATION = 120954;
Expand Down Expand Up @@ -85,6 +86,8 @@ contract('BlockRewardAuRa', async accounts => {
validatorSetAuRa.address
).should.be.fulfilled;

stakeTokenInflationRate = await blockRewardAuRa.STAKE_TOKEN_INFLATION_RATE.call();

// Initialize RandomAuRa
await randomAuRa.initialize(
COLLECT_ROUND_LENGTH,
Expand Down Expand Up @@ -272,6 +275,10 @@ contract('BlockRewardAuRa', async accounts => {
await randomAuRa.setSentReveal(validators[i]).should.be.fulfilled;
}

tokenRewardUndistributed = tokenRewardUndistributed.add(
await blockRewardAuRa.inflationAmount.call(stakingEpoch, validators, stakeTokenInflationRate)
);

(await validatorSetAuRa.emitInitiateChangeCallable.call()).should.be.equal(false);
await callReward();
const nextStakingEpoch = stakingEpoch.add(new BN(1)); // 3
Expand Down Expand Up @@ -395,6 +402,10 @@ contract('BlockRewardAuRa', async accounts => {
}
}

tokenRewardUndistributed = tokenRewardUndistributed.add(
await blockRewardAuRa.inflationAmount.call(stakingEpoch, validators, stakeTokenInflationRate)
);

const blockRewardBalanceBeforeReward = await erc677Token.balanceOf.call(blockRewardAuRa.address);

(await validatorSetAuRa.emitInitiateChangeCallable.call()).should.be.equal(false);
Expand Down Expand Up @@ -550,6 +561,10 @@ contract('BlockRewardAuRa', async accounts => {
await randomAuRa.setSentReveal(validators[i]).should.be.fulfilled;
}

tokenRewardUndistributed = tokenRewardUndistributed.add(
await blockRewardAuRa.inflationAmount.call(stakingEpoch, validators, stakeTokenInflationRate)
);

const blockRewardBalanceBeforeReward = await erc677Token.balanceOf.call(blockRewardAuRa.address);

(await validatorSetAuRa.emitInitiateChangeCallable.call()).should.be.equal(false);
Expand Down Expand Up @@ -685,6 +700,10 @@ contract('BlockRewardAuRa', async accounts => {
}
}

tokenRewardUndistributed = tokenRewardUndistributed.add(
await blockRewardAuRa.inflationAmount.call(stakingEpoch, validators, stakeTokenInflationRate)
);

const blockRewardBalanceBeforeReward = await erc677Token.balanceOf.call(blockRewardAuRa.address);

(await validatorSetAuRa.emitInitiateChangeCallable.call()).should.be.equal(false);
Expand Down Expand Up @@ -832,6 +851,10 @@ contract('BlockRewardAuRa', async accounts => {
}
}

tokenRewardUndistributed = tokenRewardUndistributed.add(
await blockRewardAuRa.inflationAmount.call(stakingEpoch, validators, stakeTokenInflationRate)
);

const blockRewardBalanceBeforeReward = await erc677Token.balanceOf.call(blockRewardAuRa.address);

(await validatorSetAuRa.emitInitiateChangeCallable.call()).should.be.equal(false);
Expand Down Expand Up @@ -984,6 +1007,10 @@ contract('BlockRewardAuRa', async accounts => {
}
}

tokenRewardUndistributed = tokenRewardUndistributed.add(
await blockRewardAuRa.inflationAmount.call(stakingEpoch, validators, stakeTokenInflationRate)
);

const blockRewardBalanceBeforeReward = await erc677Token.balanceOf.call(blockRewardAuRa.address);

const bannedUntil62 = await validatorSetAuRa.bannedUntil.call(accounts[62]);
Expand Down Expand Up @@ -1135,6 +1162,10 @@ contract('BlockRewardAuRa', async accounts => {
}
}

tokenRewardUndistributed = tokenRewardUndistributed.add(
await blockRewardAuRa.inflationAmount.call(stakingEpoch, validators, stakeTokenInflationRate)
);

const blockRewardBalanceBeforeReward = await erc677Token.balanceOf.call(blockRewardAuRa.address);

const bannedUntil62 = await validatorSetAuRa.bannedUntil.call(accounts[62]);
Expand Down Expand Up @@ -1307,6 +1338,10 @@ contract('BlockRewardAuRa', async accounts => {
await randomAuRa.setSentReveal(validators[i]).should.be.fulfilled;
}

tokenRewardUndistributed = tokenRewardUndistributed.add(
await blockRewardAuRa.inflationAmount.call(stakingEpoch, validators, stakeTokenInflationRate)
);

const blockRewardBalanceBeforeReward = await erc677Token.balanceOf.call(blockRewardAuRa.address);

(await validatorSetAuRa.emitInitiateChangeCallable.call()).should.be.equal(false);
Expand All @@ -1321,7 +1356,7 @@ contract('BlockRewardAuRa', async accounts => {
epochPoolTokenReward.should.be.bignumber.above(new BN(0));
rewardDistributed = rewardDistributed.add(epochPoolTokenReward);
}
rewardDistributed.toString().substring(0, 3).should.be.equal(tokenRewardUndistributed.div(new BN(2)).toString().substring(0, 3));
rewardDistributed.toString().substring(0, 2).should.be.equal(tokenRewardUndistributed.div(new BN(2)).toString().substring(0, 2));
tokenRewardUndistributed = tokenRewardUndistributed.sub(rewardDistributed);
tokenRewardUndistributed.should.be.bignumber.equal(await blockRewardAuRa.tokenRewardUndistributed.call());

Expand Down Expand Up @@ -1469,6 +1504,10 @@ contract('BlockRewardAuRa', async accounts => {
await randomAuRa.setSentReveal(validators[i]).should.be.fulfilled;
}

tokenRewardUndistributed = tokenRewardUndistributed.add(
await blockRewardAuRa.inflationAmount.call(stakingEpoch, validators, stakeTokenInflationRate)
);

const blockRewardBalanceBeforeReward = await erc677Token.balanceOf.call(blockRewardAuRa.address);

(await validatorSetAuRa.emitInitiateChangeCallable.call()).should.be.equal(false);
Expand Down Expand Up @@ -1611,6 +1650,10 @@ contract('BlockRewardAuRa', async accounts => {
}
(await validatorSetAuRa.validatorSetApplyBlock.call()).should.be.bignumber.equal(new BN(0));

tokenRewardUndistributed = tokenRewardUndistributed.add(
await blockRewardAuRa.inflationAmount.call(stakingEpoch, validators, stakeTokenInflationRate)
);

const blockRewardBalanceBeforeReward = await erc677Token.balanceOf.call(blockRewardAuRa.address);

(await validatorSetAuRa.emitInitiateChangeCallable.call()).should.be.equal(false);
Expand Down Expand Up @@ -1738,6 +1781,10 @@ contract('BlockRewardAuRa', async accounts => {
await randomAuRa.setSentReveal(validators[i]).should.be.fulfilled;
}

tokenRewardUndistributed = tokenRewardUndistributed.add(
await blockRewardAuRa.inflationAmount.call(stakingEpoch, validators, stakeTokenInflationRate)
);

const blockRewardBalanceBeforeReward = await erc677Token.balanceOf.call(blockRewardAuRa.address);

(await validatorSetAuRa.emitInitiateChangeCallable.call()).should.be.equal(false);
Expand Down

0 comments on commit 16ed5ff

Please sign in to comment.