Tadle

Tadle
DeFi
30,000 USDC
View results
Submission Details
Severity: high
Valid

Memory Struct Changes Doesn't Reflect on Storage for `originOfferInfo`

Summary

In the PreMarkets::listOffer function, the originOfferInfo.abortOfferStatus is intended to be updated to AbortOfferStatus.SubOfferListed to prevent the offer from being aborted. However, because originOfferInfo is a memory copy rather than a storage reference, changes made to originOfferInfo do not persist in the offerInfoMap[originOffer]. This oversight leads to the abortOfferStatus update having no effect, allowing the check in abortAskOffer to be bypassed and resulting in the potential incorrect abortion of the ask offer.

Vulnerability Details

The vulnerability arises from the following code in the PreMarkets::listOffer function:

if (makerInfo.offerSettleType == OfferSettleType.Turbo) {
address originOffer = makerInfo.originOffer;
@=> OfferInfo memory originOfferInfo = offerInfoMap[originOffer];
if (_collateralRate != originOfferInfo.collateralRate) {
revert InvalidCollateralRate();
}
@=> originOfferInfo.abortOfferStatus = AbortOfferStatus.SubOfferListed; // status if not written back
}

Here, the originOfferInfo variable is declared as a memory reference, which creates a copy of the data from offerInfoMap[originOffer] rather than a reference to the actual storage data. When originOfferInfo.abortOfferStatus is updated, the change is made to the in-memory copy, not the actual storage value in offerInfoMap.

As a result, the update to abortOfferStatus does not persist, and the abortOfferStatus remains unchanged in storage.

The unchanged abortOfferStatus is later checked in the abortAskOffer function:

function abortAskOffer(address _stock, address _offer) external {
...
if (offerInfo.abortOfferStatus != AbortOfferStatus.Initialized) {
revert InvalidAbortOfferStatus(
AbortOfferStatus.Initialized,
offerInfo.abortOfferStatus
);
}
...
}

Because the abortOfferStatus was not correctly updated, this check can be bypassed, allowing an offer to be incorrectly aborted, potentially causing disruptions or unexpected behavior in the market.

Impact

The impact of this vulnerability is significant as it undermines the logic designed to prevent the incorrect abortion of ask offers. By bypassing the abortOfferStatus check, offers that should not be aborted can be aborted, leading to potential financial loss or market instability.

Tools Used

Manual

Recommendations

To fix this issue, the originOfferInfo should be a storage reference rather than a memory copy. This ensures that any updates to originOfferInfo are directly reflected in the offerInfoMap storage.

Updates

Lead Judging Commences

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

finding-PreMarkets-listOffer-originIOfferInfo-storage-memory

Valid high severity, because the `abortOfferStatus` of the offer is not updated and persist through `storage` when listing an offer for turbo mode within the `offerInfoMap` mapping, it allows premature abortion given the `abortOfferStatus` defaults to `Initialized`, allowing the bypass of this [check](https://github.com/Cyfrin/2024-08-tadle/blob/04fd8634701697184a3f3a5558b41c109866e5f8/src/core/PreMarkets.sol#L552-L557) here and allow complete refund of initial collateral + stealing of trade tax which can potentially be gamed for profits using multiple addresses

Support

FAQs

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