Skip to content

Commit

Permalink
Add getActualSupply (#1704)
Browse files Browse the repository at this point in the history
* Add getActualSupply

* Update pkg/pool-stable/test/ComposableStablePool.test.ts

Co-authored-by: Tom French <[email protected]>

* Update pkg/pool-stable/contracts/ComposableStablePool.sol

Co-authored-by: Tom French <[email protected]>

* Remove virtual supply

Co-authored-by: Tom French <[email protected]>
  • Loading branch information
nventuro and TomAFrench committed Nov 24, 2022
1 parent e0bd86a commit 9280c32
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 50 deletions.
56 changes: 26 additions & 30 deletions pkg/pool-stable/contracts/ComposableStablePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -997,28 +997,16 @@ contract ComposableStablePool is
// accrued but are not yet minted: in calculating these we'll actually end up fetching most of the data we need
// for the invariant.

// First we query the Vault for current registered balances (which includes preminted BPT), to then calculate
// the current scaled balances and virtual supply.
(, uint256[] memory registeredBalances, ) = getVault().getPoolTokens(getPoolId());
_upscaleArray(registeredBalances, _scalingFactors());
(uint256 virtualSupply, uint256[] memory balances) = _dropBptItemFromBalances(registeredBalances);

// Now we need to calculate any BPT due in the form of protocol fees. This requires data from the last join or
// exit operation.
(uint256 lastJoinExitAmp, uint256 lastPostJoinExitInvariant) = getLastJoinExitData();

(
uint256 expectedProtocolOwnershipPercentage,
uint256[] memory balances,
uint256 virtualSupply,
uint256 protocolFeeAmount,
uint256 lastJoinExitAmp,
uint256 currentInvariantWithLastJoinExitAmp
) = _getProtocolPoolOwnershipPercentage(balances, lastJoinExitAmp, lastPostJoinExitInvariant);

uint256 protocolFeeAmount = _calculateAdjustedProtocolFeeAmount(
virtualSupply,
expectedProtocolOwnershipPercentage
);
) = _getSupplyAndFeesData();

// Due protocol fees will be minted at the next join or exit, so we can simply add them to the current virtual
// supply to make the calculation with the correct amount.
// supply to get the actual supply.
uint256 actualTotalSupply = virtualSupply.add(protocolFeeAmount);

// All that's missing now is the invariant. We have the balances required to calculate it already, but still
Expand Down Expand Up @@ -1067,21 +1055,29 @@ contract ComposableStablePool is
// not paused.
_ensureNotPaused();

// First we need to get the data required to compute and pay due protocol fees.
(, uint256[] memory registeredBalances, ) = getVault().getPoolTokens(getPoolId());
_upscaleArray(registeredBalances, _scalingFactors());
(uint256 lastJoinExitAmp, uint256 lastPostJoinExitInvariant) = getLastJoinExitData();

(, uint256[] memory balances, uint256 currentInvariantWithLastJoinExitAmp) = _payProtocolFeesBeforeJoinExit(
registeredBalances,
lastJoinExitAmp,
lastPostJoinExitInvariant
);
// We need to calculate the amount of unminted BPT that represents protocol fees to then pay those. This yields
// some auxiliary values that turn out to also be useful for the rest of the tasks we want to perform.
(
uint256[] memory balances,
,
uint256 protocolFeeAmount,
uint256 lastJoinExitAmp,
uint256 currentInvariantWithLastJoinExitAmp
) = _getSupplyAndFeesData();

// With the fees paid, we now store the current invariant and the amplification factor used to compute it,
// marking the Pool as free of protocol debt.
if (protocolFeeAmount > 0) {
_payProtocolFees(protocolFeeAmount);
}

// With the fees paid, we now need to calculate the current invariant so we can store it alongside the current
// amplification factor, marking the Pool as free of protocol debt.
(uint256 currentAmp, ) = _getAmplificationParameter();

// It turns out that the process for due protocol fee calculation involves computing the current invariant,
// except using the amplification factor at the last join or exit. This would typically not be terribly useful,
// but since the amplification factor only changes rarely there is high probability of its current value being
// the same as it was in the last join or exit. If that is the case, then we can skip the costly invariant
// computation altogether.
uint256 currentInvariant = (currentAmp == lastJoinExitAmp)
? currentInvariantWithLastJoinExitAmp
: StableMath._calculateInvariant(currentAmp, balances);
Expand Down
21 changes: 1 addition & 20 deletions pkg/pool-stable/contracts/ComposableStablePoolProtocolFees.sol
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ abstract contract ComposableStablePoolProtocolFees is
);

if (protocolOwnershipPercentage > 0) {
uint256 protocolFeeAmount = _calculateAdjustedProtocolFeeAmount(
uint256 protocolFeeAmount = ProtocolFees.bptForPoolOwnershipPercentage(
postJoinExitSupply,
protocolOwnershipPercentage
);
Expand Down Expand Up @@ -306,25 +306,6 @@ abstract contract ComposableStablePoolProtocolFees is
_updateOldRates();
}

/**
* @dev Adjust a protocol fee percentage calculated before minting, to the equivalent value after minting.
*/
function _calculateAdjustedProtocolFeeAmount(uint256 supply, uint256 basePercentage)
internal
pure
returns (uint256)
{
// Since this fee amount will be minted as BPT, which increases the total supply, we need to mint
// slightly more so that it reflects this percentage of the total supply after minting.
//
// The percentage of the Pool the protocol will own after minting is given by:
// `protocol percentage = to mint / (current supply + to mint)`.
// Solving for `to mint`, we arrive at:
// `to mint = current supply * protocol percentage / (1 - protocol percentage)`.
//
return supply.mulDown(basePercentage).divDown(basePercentage.complement());
}

/**
* @notice Return the amplification factor and invariant as of the most recent join or exit (including BPT swaps)
*/
Expand Down
7 changes: 7 additions & 0 deletions pkg/pool-stable/test/ComposableStablePool.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1622,6 +1622,13 @@ describe('ComposableStablePool', () => {
unmintedBPT = virtualSupply.mul(protocolOwnership).div(fp(1).sub(protocolOwnership));
});

it('the actual supply takes into account unminted protocol fees', async () => {
const virtualSupply = await pool.getVirtualSupply();
const expectedActualSupply = virtualSupply.add(unmintedBPT);

expect(await pool.getActualSupply()).to.almostEqual(expectedActualSupply, 1e-6);
});

it('rate takes into account unminted protocol fees', async () => {
const scaledBalances = arrayFpMul(await pool.getBalances(), await pool.getScalingFactors()).filter(
(_, i) => i != bptIndex
Expand Down

0 comments on commit 9280c32

Please sign in to comment.