Tadle

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

Validation of `collateralRate` in `PerMarkets::createOffer` function

Summary

The PerMarkets::createOffer function currently includes a validation check to ensure that the collateralRate parameter is at least 100% by comparing it against a constant (Constants.COLLATERAL_RATE_DECIMAL_SCALER). However, the documentation specifies that the collateralRate must be greater than 100% * @dev collateralRate must be more than 100%, decimal scaler is 10000.

Vulnerability Details

The current implementation only enforces that the collateralRate is not less than 100%, which means a collateralRate equal to 100% would be incorrectly accepted.

function createOffer(CreateOfferParams calldata params) external payable {
/**
* @dev points and amount must be greater than 0
* @dev eachTradeTax must be less than 100%, decimal scaler is 10000
* @dev collateralRate must be more than 100%, decimal scaler is 10000
*/
if (params.points == 0x0 || params.amount == 0x0) {
revert Errors.AmountIsZero();
}
if (params.eachTradeTax > Constants.EACH_TRADE_TAX_DECIMAL_SCALER) {
revert InvalidEachTradeTaxRate();
}
@>> if (params.collateralRate < Constants.COLLATERAL_RATE_DECIMAL_SCALER) {
revert InvalidCollateralRate();
}

POC

function test_ask_offer_turbo_usdc() public {
vm.startPrank(user);
preMarktes.createOffer(
CreateOfferParams(
marketPlace,
address(mockUSDCToken),
1000,
0.01 * 1e18,
@>> 10000,
300,
OfferType.Ask,
OfferSettleType.Turbo
)
);
address offerAddr = GenerateAddress.generateOfferAddress(0);
preMarktes.createTaker(offerAddr, 500);
address stock1Addr = GenerateAddress.generateStockAddress(1);
preMarktes.listOffer(stock1Addr, 0.006 * 1e18, 10000);
address offer1Addr = GenerateAddress.generateOfferAddress(1);
preMarktes.closeOffer(stock1Addr, offer1Addr);
preMarktes.relistOffer(stock1Addr, offer1Addr);
vm.stopPrank();
vm.prank(user1);
systemConfig.updateMarket(
"Backpack",
address(mockPointToken),
0.01 * 1e18,
block.timestamp - 1,
3600
);
vm.startPrank(user);
mockPointToken.approve(address(tokenManager), 10000 * 10 ** 18);
deliveryPlace.settleAskMaker(offerAddr, 500);
deliveryPlace.closeBidTaker(stock1Addr);
vm.stopPrank();
}
Ran 1 test for test/PreMarkets.t.sol:PreMarketsTest
[PASS] test_ask_offer_turbo_usdc() (gas: 1356543)
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 7.13ms (1.68ms CPU time)

Impact

Allowing a collateralRate of exactly 100% when the system requires it to be strictly greater than 100% could lead to inadequate collateralization.

Tools Used

Manual Review

Recommendations

Update the validation logic to enforce that the collateralRate must be strictly greater than 100%. The condition should be modified as follows:

- if (params.collateralRate < Constants.COLLATERAL_RATE_DECIMAL_SCALER) {
+ if (params.collateralRate <= Constants.COLLATERAL_RATE_DECIMAL_SCALER) {
revert InvalidCollateralRate();
}
Updates

Lead Judging Commences

0xnevi Lead Judge 12 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-PreMarkets-off-by-one-Collateral-Rate-100%

I believe this is borderline informational/low. Despite this off-by-one error of the intended check, the difference between 100% and 101% is minimal, so I believe whether or not 100% is allowed has minimal impact. Ultimately, it still comes down to the risk level that users are willing to take

Support

FAQs

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