epoch finalization executes at about 25k gas / active maker
This commit is contained in:
@@ -248,8 +248,8 @@ contract Staking is
|
||||
function goToNextEpoch()
|
||||
external
|
||||
{
|
||||
_goToNextEpoch();
|
||||
_payRebates();
|
||||
_goToNextEpoch();
|
||||
}
|
||||
|
||||
function getEpochPeriodInSeconds()
|
||||
|
@@ -70,6 +70,13 @@ contract MixinFees is
|
||||
return address(this).balance;
|
||||
}
|
||||
|
||||
event E(
|
||||
uint256 totalRewards,
|
||||
uint256 ownerFees,
|
||||
uint256 totalFees,
|
||||
uint256 ownerStake,
|
||||
uint256 totalStake
|
||||
);
|
||||
function _payRebates()
|
||||
internal
|
||||
{
|
||||
@@ -82,10 +89,19 @@ contract MixinFees is
|
||||
activePoolIds[i].feesCollected = protocolFeesThisEpochByPool[activePoolIds[i].poolId];
|
||||
totalFees = _safeAdd(totalFees, activePoolIds[i].feesCollected);
|
||||
}
|
||||
|
||||
// Step 2 - payout
|
||||
uint256 totalRewards = address(this).balance;
|
||||
uint256 totalStake = _getActivatedStakeAcrossAllOwners();
|
||||
|
||||
// no rebates available
|
||||
// note that there is a case in cobb-douglas where if we weigh either fees or stake at 100%,
|
||||
// then the other value doesn't matter. However, it's cheaper on gas to assume that there is some
|
||||
// non-zero split.
|
||||
if (totalRewards == 0 || totalFees == 0 || totalStake == 0) {
|
||||
revert("We don't want to hit this case in testing");
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 2 - payout
|
||||
uint256 totalRewardsRecordedInVault = 0;
|
||||
for (uint i = 0; i != numberOfActivePoolIds; i++) {
|
||||
uint256 stakeDelegatedToPool = _getStakeDelegatedToPool(activePoolIds[i].poolId);
|
||||
@@ -100,6 +116,13 @@ contract MixinFees is
|
||||
100
|
||||
)
|
||||
);
|
||||
/*emit E(
|
||||
totalRewards,
|
||||
activePoolIds[i].feesCollected,
|
||||
totalFees,
|
||||
scaledStake,
|
||||
totalStake
|
||||
);*/
|
||||
uint256 reward = LibMath._cobbDouglasSuperSimplified(
|
||||
totalRewards,
|
||||
activePoolIds[i].feesCollected,
|
||||
@@ -112,7 +135,7 @@ contract MixinFees is
|
||||
rewardVault.recordDepositFor(activePoolIds[i].poolId, reward);
|
||||
totalRewardsRecordedInVault = _safeAdd(totalRewardsRecordedInVault, reward);
|
||||
|
||||
// clear state
|
||||
// clear state for refunds
|
||||
protocolFeesThisEpochByPool[activePoolIds[i].poolId] = 0;
|
||||
activePoolIdsThisEpoch[i] = 0;
|
||||
}
|
||||
|
@@ -143,7 +143,8 @@ library LibMath {
|
||||
pure
|
||||
returns (uint256 root)
|
||||
{
|
||||
root = (TOKEN_MULTIPLIER * _nthRoot(base, COBB_DOUGLAS_ALPHA_DENOMINATOR)) / NTH_ROOT_OF_TOKEN_MULTIPLIER;
|
||||
uint256 numerator = _nthRoot(base, COBB_DOUGLAS_ALPHA_DENOMINATOR);
|
||||
root = (TOKEN_MULTIPLIER * numerator) / NTH_ROOT_OF_TOKEN_MULTIPLIER;
|
||||
return root;
|
||||
}
|
||||
|
||||
|
@@ -826,6 +826,102 @@ describe('Staking Core', () => {
|
||||
const makerAddressesForPoolAfterRemoving = await stakingWrapper.getMakerAddressesForPool(poolId);
|
||||
expect(makerAddressesForPoolAfterRemoving).to.be.deep.equal([]);
|
||||
});
|
||||
|
||||
it.only('Finalization with Protocol Fees', async () => {
|
||||
///// 0 DEPLOY EXCHANGE /////
|
||||
await stakingWrapper.addExchangeAddressAsync(exchange);
|
||||
///// 1 SETUP POOLS /////
|
||||
const poolOperators = stakers.slice(0, 3);
|
||||
const operatorShares = [39, 59, 43];
|
||||
const poolIds = await Promise.all([
|
||||
stakingWrapper.createPoolAsync(poolOperators[0], operatorShares[0]),
|
||||
stakingWrapper.createPoolAsync(poolOperators[1], operatorShares[1]),
|
||||
stakingWrapper.createPoolAsync(poolOperators[2], operatorShares[2]),
|
||||
]);
|
||||
const makersByPoolId = [
|
||||
[
|
||||
makers[0],
|
||||
],
|
||||
[
|
||||
makers[1],
|
||||
makers[2]
|
||||
],
|
||||
[
|
||||
makers[3],
|
||||
makers[4],
|
||||
makers[5]
|
||||
],
|
||||
];
|
||||
const protocolFeesByMaker = [
|
||||
// pool 1 - adds up to protocolFeesByPoolId[0]
|
||||
stakingWrapper.toBaseUnitAmount(0.304958),
|
||||
// pool 2 - adds up to protocolFeesByPoolId[1]
|
||||
stakingWrapper.toBaseUnitAmount(3.2),
|
||||
stakingWrapper.toBaseUnitAmount(12.123258),
|
||||
// pool 3 - adds up to protocolFeesByPoolId[2]
|
||||
stakingWrapper.toBaseUnitAmount(23.577),
|
||||
stakingWrapper.toBaseUnitAmount(4.54522236),
|
||||
stakingWrapper.toBaseUnitAmount(0)
|
||||
];
|
||||
await Promise.all([
|
||||
// pool 0
|
||||
stakingWrapper.addMakerToPoolAsync(poolIds[0], makersByPoolId[0][0], "0x00", poolOperators[0]),
|
||||
// pool 1
|
||||
stakingWrapper.addMakerToPoolAsync(poolIds[1], makersByPoolId[1][0], "0x00", poolOperators[1]),
|
||||
stakingWrapper.addMakerToPoolAsync(poolIds[1], makersByPoolId[1][1], "0x00", poolOperators[1]),
|
||||
// pool 2
|
||||
stakingWrapper.addMakerToPoolAsync(poolIds[2], makersByPoolId[2][0], "0x00", poolOperators[2]),
|
||||
stakingWrapper.addMakerToPoolAsync(poolIds[2], makersByPoolId[2][1], "0x00", poolOperators[2]),
|
||||
stakingWrapper.addMakerToPoolAsync(poolIds[2], makersByPoolId[2][2], "0x00", poolOperators[2]),
|
||||
]);
|
||||
///// 2 PAY FEES /////
|
||||
await Promise.all([
|
||||
// pool 0 - split into two payments
|
||||
stakingWrapper.payProtocolFeeAsync(makers[0], protocolFeesByMaker[0].div(2), exchange),
|
||||
stakingWrapper.payProtocolFeeAsync(makers[0], protocolFeesByMaker[0].div(2), exchange),
|
||||
// pool 1 - pay full amounts
|
||||
stakingWrapper.payProtocolFeeAsync(makers[1], protocolFeesByMaker[1], exchange),
|
||||
stakingWrapper.payProtocolFeeAsync(makers[2], protocolFeesByMaker[2], exchange),
|
||||
// pool 2 -- pay full amounts
|
||||
stakingWrapper.payProtocolFeeAsync(makers[3], protocolFeesByMaker[3], exchange),
|
||||
stakingWrapper.payProtocolFeeAsync(makers[4], protocolFeesByMaker[4], exchange),
|
||||
// maker 5 doesn't pay anything
|
||||
]);
|
||||
///// 3 VALIDATE FEES RECORDED FOR EACH POOL /////
|
||||
const recordedProtocolFeesByPool = await Promise.all([
|
||||
stakingWrapper.getProtocolFeesThisEpochByPoolAsync(poolIds[0]),
|
||||
stakingWrapper.getProtocolFeesThisEpochByPoolAsync(poolIds[1]),
|
||||
stakingWrapper.getProtocolFeesThisEpochByPoolAsync(poolIds[2]),
|
||||
]);
|
||||
expect(recordedProtocolFeesByPool[0]).to.be.bignumber.equal(protocolFeesByMaker[0]);
|
||||
expect(recordedProtocolFeesByPool[1]).to.be.bignumber.equal(protocolFeesByMaker[1].plus(protocolFeesByMaker[2]));
|
||||
expect(recordedProtocolFeesByPool[2]).to.be.bignumber.equal(protocolFeesByMaker[3].plus(protocolFeesByMaker[4]));
|
||||
///// 4 VALIDATE TOTAL FEES /////
|
||||
const recordedTotalProtocolFees = await stakingWrapper.getTotalProtocolFeesThisEpochAsync();
|
||||
const totalProtocolFeesAsNumber = _.sumBy(protocolFeesByMaker, (value: BigNumber) => {return value.toNumber()});
|
||||
const totalProtocolFees = new BigNumber(totalProtocolFeesAsNumber);
|
||||
expect(recordedTotalProtocolFees).to.be.bignumber.equal(totalProtocolFees);
|
||||
///// 5 STAKE /////
|
||||
const stakeByPoolOperator = [
|
||||
stakingWrapper.toBaseUnitAmount(42),
|
||||
stakingWrapper.toBaseUnitAmount(84),
|
||||
stakingWrapper.toBaseUnitAmount(97),
|
||||
];
|
||||
await Promise.all([
|
||||
// pool 0
|
||||
stakingWrapper.depositAndStakeAsync(poolOperators[0], stakeByPoolOperator[0]),
|
||||
// pool 1
|
||||
stakingWrapper.depositAndStakeAsync(poolOperators[1], stakeByPoolOperator[1]),
|
||||
// pool 2
|
||||
stakingWrapper.depositAndStakeAsync(poolOperators[2], stakeByPoolOperator[2]),
|
||||
]);
|
||||
|
||||
///// 6 FINALIZE /////
|
||||
await stakingWrapper.skipToNextEpochAsync();
|
||||
|
||||
///// 7 CHECK PROFITS /////
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
// tslint:enable:no-unnecessary-type-assertion
|
||||
|
Reference in New Issue
Block a user