epoch finalization executes at about 25k gas / active maker

This commit is contained in:
Greg Hysen
2019-06-10 23:02:18 -07:00
parent 2d39454ce1
commit b2a7e0536e
4 changed files with 125 additions and 5 deletions

View File

@@ -248,8 +248,8 @@ contract Staking is
function goToNextEpoch()
external
{
_goToNextEpoch();
_payRebates();
_goToNextEpoch();
}
function getEpochPeriodInSeconds()

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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