Skip to content

Able Cinnamon Kestrel - updateTokenPrice() function in CentralizedOracle contract is vulnerable to front-running and back-running attack #199

@sherlock-admin3

Description

@sherlock-admin3

Able Cinnamon Kestrel

Medium

updateTokenPrice() function in CentralizedOracle contract is vulnerable to front-running and back-running attack

Summary

Due to Centralized oracle implementation, Attacker can front-run or back-run CentralizedOracle:updateTokenPrice() with PinlinkShop:purchase() or PinlinkShop :modifyListing() function to his benefit.

Root Cause

https://github.com/sherlock-audit/2025-03-pinlink-rwa-tokenized-depin-marketplace/blob/34cd70b66f1dbe191bd6f946e42f58eef4a00166/marketplace-contracts/src/oracles/CentralizedOracle.sol#L55C6-L57C97
Admin/Owner changes pin Token price by calling CentralizedOracle :updateTokenPrice() function and the new price can be in the range (currentPrice/5) < updatedPrice < (currenPrice*5)

 function updateTokenPrice(uint256 usdPerToken) external onlyOwner {
        uint256 _currentPrice = _tokenPriceInUsd;

        // sanity checks to avoid too large deviations caused by bot/human errors
        if (usdPerToken < _currentPrice / 5) revert PinlinkCentralizedOracle__NewPriceTooLow();
        if (usdPerToken > _currentPrice * 5) revert PinlinkCentralizedOracle__NewPriceTooHigh();

        _tokenPriceInUsd = usdPerToken;
        lastPriceUpdateTimestamp = block.timestamp;

        // todo potential improvement. Everytime we update, we crosscheck the price with the Uniswap spot price
        //  - centralized, but controlled by a decentralized oracle, so that we can't manipulate it
        //  - cheaper to run than a TWAP oracle
        //  - less manipulable (except by us)

        emit PriceUpdated(usdPerToken);
    }

If there's a big jump in price, Attacker can perform front-run or back-run to his benefit.

Internal Pre-conditions

No-Response

External Pre-conditions

No-Response

Attack Path

  1. Admin call CentralizedOracle:updateTokenPrice() to cahnge price. (Big jump in price)
  2. Attacker sees this in mempool
  3. Then Attacker can front-run or back-run this function call to his benefit by calling either purchase() or modifyListing() to his benefit

Impact

Likelihood is high as block cadence in Ethereum main net is around 12s. Front-running attacks are possible. Impact is medium.

PoC

Front running and back-running can be done in various combinations.

  1. Attacker can buy a listing with low price by back-running updateTokenPrice() function call with purchase() function call if price is falling down significantly
  2. Attacker can perform front-running updateTokenPrice() function call with modifyListing() function call to change the price of his listing.

Mitigation

Use Twap mechanisms in the oracle implementation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions