Tadle

Tadle
DeFiFoundry
27,750 USDC
View results
Submission Details
Severity: low
Valid

Critical tax rate validation flaw in `PreMarkets::createOffer` allows 100% tax rate, violating protocol design

Summary

The PreMarkets::createOffer function currently allows the eachTradeTax parameter to be set to 100%, which is contrary to the protocol's intended design where the tax should be less than 100%. This flaw can cause users to pay more than anticipated due to the tax consuming the full deposit amount, disrupting the protocol's intended operation.

Vulnerability Details

The createOffer function in the PreMarkets contract is designed to handle various parameters for creating an offer, including eachTradeTax. The function includes a check to validate the eachTradeTax parameter:

if (params.eachTradeTax > Constants.EACH_TRADE_TAX_DECIMAL_SCALER) {
revert InvalidEachTradeTaxRate();
}

In this check, Constants.EACH_TRADE_TAX_DECIMAL_SCALER is set to 10000, representing a 100% tax rate in the decimal scaling system. However, the comment above the function specifies that eachTradeTax should be less than 100%:

* @dev eachTradeTax must be less than 100%, decimal scaler is 10000

Expected Behavior

The comment indicates that eachTradeTax should be strictly less than 100%, meaning it should be less than 10000 in the decimal scaling system.

Actual Behavior

The current implementation allows eachTradeTax to be less or exactly 100% (i.e., 10000). This does not align with the intended behavior as described in the comment.

PoC Demonstrating Potential Issue

The following code snippet from the createTaker function illustrates how a 100% eachTradeTax could lead to users paying more than expected:

function createTaker(address _offer, uint256 _points) external payable {
...
/// @dev Transfer token from user to capital pool as collateral
uint256 depositAmount = _points.mulDiv(
offerInfo.amount,
offerInfo.points,
Math.Rounding.Ceil
);
uint256 platformFee = depositAmount.mulDiv(
platformFeeRate,
Constants.PLATFORM_FEE_DECIMAL_SCALER
);
@> uint256 tradeTax = depositAmount.mulDiv(
makerInfo.eachTradeTax,
Constants.EACH_TRADE_TAX_DECIMAL_SCALER
);
ITokenManager tokenManager = tadleFactory.getTokenManager();
_depositTokenWhenCreateTaker(
platformFee,
depositAmount,
tradeTax,
makerInfo,
offerInfo,
tokenManager
);
...
}

In this function:

  • depositAmount is calculated based on the points the user wishes to trade.

  • tradeTax is then computed as a percentage of depositAmount using makerInfo.eachTradeTax.

If makerInfo.eachTradeTax is set to 100%, tradeTax will equal depositAmount, meaning the user ends up paying tax equal to depositAmount. This leads to the user paying more than expected.

Impact

  1. Unexpected Financial Burden on Users: Users may pay more than anticipated due to the possibility that the tax could equal the deposit amount when eachTradeTax is set to 100%. This can lead to users experiencing unexpected financial losses.

  2. Protocol Invariant Breach: The protocol's design expects eachTradeTax to be less than 100%. Allowing a tax rate of 100% breaks this invariant, causing the protocol to behave differently from its intended design, which may lead to inconsistencies and unexpected behavior.

Tools Used

VSCode

Recommendations

To ensure the eachTradeTax adheres to the intended design and prevent users from paying more than expected, update the validation check for eachTradeTax as follows:

- if (params.eachTradeTax > Constants.EACH_TRADE_TAX_DECIMAL_SCALER)
+ if (params.eachTradeTax >= Constants.EACH_TRADE_TAX_DECIMAL_SCALER) {
revert InvalidEachTradeTaxRate();
}

This update ensures that eachTradeTax must be strictly less than 100%, aligning with the protocol's design and preventing users from being charged more than intended.

Updates

Lead Judging Commences

0xnevi Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-PreMarkets-off-by-one-Trade-TAX-100%

Similar to issue #1323, Despite this off-by-one error of the intended check, the difference between 99% and 100% is minimal, so I believe whether or not 100% is allowed has minimal impact. Ultimately, takers should not be realistically creating offer with such tradeTax

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.