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.
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:
191: // pay for fee
192: if (FEE_FACTOR > 0) {
193: cache.feeAmount = ((params.marginFrom + cache.amountFromBorrowed) * FEE_FACTOR) / Base.BASIS_POINT;
194: cache.treasuryAmount = (cache.feeAmount * _treasuryRate) / Base.BASIS_POINT;
195: _treasury[cache.tokenFrom] += cache.treasuryAmount;
196: if (params.zeroForOne) {
197: lps.addTokensOwed(params.tokenId, uint128(cache.feeAmount - cache.treasuryAmount), 0);
198: } else {
199: lps.addTokensOwed(params.tokenId, 0, uint128(cache.feeAmount - cache.treasuryAmount));
200: }
201: }
The fee is applied to amountFromBorrowed
, the "from" amount from the LP liquidity, and marginFrom
, 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 required collateralTo
amount, leaving the token "from" premium at zero. Then, in a second call, provide the needed premium to cover for eventual LP fees using addPremium()
. 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.
A user can skip paying part of the fees by bundling two operations in a single transaction:
- A call to
openPosition()
with the minimal required amount ofmarginFrom
so thatamountReceived + amountToBorrowed + marginTo >= collateralTo
. - A call to
addPremium()
to provide the required premiums to cover for eventual fees.
Apply the same fee schedule to addPremium()
. Depending on the value of zeroForOne
, determine the "from" token, apply the FEE_FACTOR
to it, and accrue the fee to the corresponding liquidity position.