Documentation
The formulas for calculating the interest shares and fee shares are incorrect in the accompanying documentation and do not reflect the implementation in the code. These errors in documentaiton could result in end-user and developer confusion. However, the in-line code documentation is accurate and informative, and we applaud Jarvis for their committment to quality in-line developer documentation.
Interest shares
We advise that the formula for calculating interest shares in the documentation should be changed from
final_share = (minting_capacity_ratio + utilization)/2
to the following:
final_share = (minting_capacity_share + utilization_share)/2
Utilization shares
Where minting_capacity_share
corresponds with the definition of minting_capacity_ratio
in the current documentation and utilization_share
is given by
utilization[i] / total_utilization
Here, utilization_i
corresponds with the utilization of the i'th
liquidity provider:
utilization[i] = (tokensCollateralized[i] * price * overCollateralization[i]) / collateralDeposited[i].
This is consistent with the implementation in the multiple liquidity pool shown below:
SynthereumMultiLpLiquidityPool...
function _calculateInterest(
uint256 _totalInterests,
uint256 _price,
uint8 _collateralDecimals,
PositionCache[] memory _positionsCache
) internal view returns (uint256 prevTotalLPsCollateral) {
...
tempInterstArguments.utilizationShare = tempInterstArguments
.isTotUtilizationNotZero
? utilizationShares[j].div(tempInterstArguments.totalUtilization)
: 0;
...
The economic implications of the implementation of the formula responsible for calculating utilization shares is such that, if the entry/exit of LPs was not restricted by whitelist/registration, then an ecomonic attack becomes feasible where an attacker adds many LPs to a pool and collateralizes one token, resulting in 0% capacity shares but a 100% utilization rate. Due to the calculation of utilization shares, which relies on a fraction of the entire utilization, an attacker could steal/earn ~50% of a pool's interest due to their enormous stake into the utilization shares as a result of the many LP providers they control with a 100% utilization rate.
While this is not currently an issue due to the whitelist placed on MultiLpPools, if in the future a change was introduced to allow LPs to join freely, such an attack could take place.
Fee splitting
The formula for calculating the fees allocated to each liquidity provider is given by
redeemFeePaid * ratio[i]
Here, redeemFeePaid
corresponds with the total fee paid by the synthetic token minter:
ratio = (share[i] / totalNumberOfTokens )
// and
share[i] = (tokensCollateralized[i] / totalNumberOfTokens)
The formula for fees paid to each liquidity provider should be changed to the following:
redeemFeePaid * share[i]
This is consistent with the implementation in the multiple liquidity pool shown below.
// SynthereumMultiLpLiquidityPool.sol
// ...
function _calculateRedeemTokensAndFee(
uint256 _totalNumTokens,
uint256 _redeemNumTokens,
uint256 _feeAmount,
WithdrawDust memory _withdrawDust,
PositionCache[] memory _positionsCache
) internal pure {
...
redeemSplit.fees = _feeAmount.mul(
redeemSplit.lpPosition.tokensCollateralized.div(_totalNumTokens)
);
...