Omniscia Moby Audit
FeeDistributor Manual Review Findings
FeeDistributor Manual Review Findings
FDR-01M: Inaccurate Distribution Mechanism
Type | Severity | Location |
---|---|---|
Mathematical Operations | FeeDistributor.sol:L150-L152, L154-L156 |
Description:
The RewardDistributor
implementation will employ a reward-per-second mechanism that represents a truncated token value as the rewards distributed will be divided by the distributionPeriod
.
Impact:
Amounts that are less than the distributionPeriod
will slowly accumulate within the reward distributors as they will not be properly dispersed in the period they are meant to.
Example:
143function distributeOLPRewards() external onlyKeeper {144 require(block.timestamp - lastOlpRewardsDistribution >= distributionPeriod, "not ready");145
146 IERC20(weth).safeTransfer(sRewardDistributor, pendingOLPRewards[sRewardDistributor]);147 IERC20(weth).safeTransfer(mRewardDistributor, pendingOLPRewards[mRewardDistributor]);148 IERC20(weth).safeTransfer(lRewardDistributor, pendingOLPRewards[lRewardDistributor]);149
150 uint256 sTokensPerInterval = pendingOLPRewards[sRewardDistributor] / distributionPeriod;151 uint256 mTokensPerInterval = pendingOLPRewards[mRewardDistributor] / distributionPeriod;152 uint256 lTokensPerInterval = pendingOLPRewards[lRewardDistributor] / distributionPeriod;153
154 IRewardDistributor(sRewardDistributor).setTokensPerInterval(sTokensPerInterval);155 IRewardDistributor(mRewardDistributor).setTokensPerInterval(mTokensPerInterval);156 IRewardDistributor(lRewardDistributor).setTokensPerInterval(lTokensPerInterval);157
158 pendingOLPRewards[sRewardDistributor] = 0;159 pendingOLPRewards[mRewardDistributor] = 0;160 pendingOLPRewards[lRewardDistributor] = 0;161
162 lastOlpRewardsDistribution = block.timestamp;163}
Recommendation:
We advise the code to either reduce each pendingOLPRewards
entry by the value of xTokensPerInterval * distributionPeriod
, or to transfer a value equal to xTokensPerInterval * distributionPeriod
towards each xRewardDistributor
.
Alleviation (b02fae335f62cc1f5f4236fb4d982ad16a32bd26):
The code was updated per our latter recommendation, evaluating the wholly divisible S
/M
/L
amount that can be transferred to each reward distributor and utilizing it for subtracting their pendingOLPRewards
entry.
FDR-02M: Unfair Fee Swaps
Type | Severity | Location |
---|---|---|
Mathematical Operations | FeeDistributor.sol:L101-L103 |
Description:
The FeeDistributor::distributeFee
function will perform three separate swaps of the same trading pair independently, thereby causing the last swap to trade at an "unfair" disadvantage due to the preceding swaps' lowering the price of the AMM pair.
Impact:
The fees accumulated for the lVault
(long position vault) will be less than the sVault
(short position vault) due to an inadvertently unfair swap order.
Example:
101sVaultOutcome += _swap(vaults[0], _path, feeFromSVault);102mVaultOutcome += _swap(vaults[1], _path, feeFromMVault);103lVaultOutcome += _swap(vaults[2], _path, feeFromLVault);
Recommendation:
We advise a single swap to be performed and split among the sVaultOutcome
, mVaultOutcome
, and lVaultOutcome
values as the mechanism will presently acquire more fees for the sVault
than the lVault
even for the same token amount.
Alleviation (b02fae335f62cc1f5f4236fb4d982ad16a32bd26):
The Moby team clarified that three independent swaps are performed to ensure that fees are captured independently per vault type, and we consider this approach to be sound.
As such, we consider the original exhibit nullified as it details desirable behaviour.