Add premium doesn't collect fees #54
Labels
2 (Med Risk)
Assets not at direct risk, but function/availability of the protocol could be impacted or leak value
bug
Something isn't working
M-04
primary issue
Highest quality submission among a set of duplicates
selected for report
This submission will be included/highlighted in the audit report
sponsor acknowledged
Technically the issue is correct, but we're not going to resolve it for XYZ reasons
Lines of code
https://github.com/code-423n4/2023-12-particle/blob/a3af40839b24aa13f5764d4f84933dbfa8bc8134/contracts/protocol/ParticlePositionManager.sol#L501
Vulnerability details
Summary
Fees are applied to premiums when a new position is opened, but the same mechanism is not enforced when margin is added to an existing position.
Impact
When a new position is created in the LAMM protocol, fees are collected in favor of the LP owner that provides the liquidity for the position. The fee is calculated by applying a configurable rate over the tokens "from" amounts:
https://github.com/code-423n4/2023-12-particle/blob/a3af40839b24aa13f5764d4f84933dbfa8bc8134/contracts/protocol/ParticlePositionManager.sol#L191-L201
The fee is applied to
amountFromBorrowed
, the "from" amount from the LP liquidity, andmarginFrom
, the user provided margin to cover the required amount for the swap and provide a premium in the position.However, the same logic is not followed when the borrower adds more margin using
addPremium()
. In this case, the amounts are added in full to the position's premiums without incurring any fees.This not only represents an inconsistent behavior (which may be a design decision), but allows the borrower to avoid paying part of the fees. The borrower can provide enough
marginTo
so that the swap can reach the requiredcollateralTo
amount, leaving the token "from" premium at zero. Then, in a second call, provide the needed premium to cover for eventual LP fees usingaddPremium()
. This can be done with null liquidation risk and is greatly simplified by leveraging the multicall functionality. The borrower can bundle both operations in a single transaction, without even deploying a contract.Proof of Concept
A user can skip paying part of the fees by bundling two operations in a single transaction:
openPosition()
with the minimal required amount ofmarginFrom
so thatamountReceived + amountToBorrowed + marginTo >= collateralTo
.addPremium()
to provide the required premiums to cover for eventual fees.Recommendation
Apply the same fee schedule to
addPremium()
. Depending on the value ofzeroForOne
, determine the "from" token, apply theFEE_FACTOR
to it, and accrue the fee to the corresponding liquidity position.Assessed type
Other
The text was updated successfully, but these errors were encountered: