Common Vulnerabilities: Oracles and Pricing - Smart Contracts
Primer
One of the core advantages of Decentralised Finance is the composability of contracts, enabling different Dapps to source data from one another. This alone enables many novel use cases of onchain data such as token financial derivatives, betting platforms and insurance. With the ability to bring data onchain via Oracles, these uses are extended yet further to political bets, stock market derivatives and more.
In this note we look at some of the common missteps made when attempting to make use of Oracles and pricing feeds in writing smart contracts, and steps that can be taken to mitigate them.
Spot Pricing
A common attack vector is utilising flash loans, instantaneous, arbitrarily sized, unbacked loans, to influence the price of a token on DeFi exchanges such as Uniswap or other venues. Due to the pseudo-anonymity and permissionless nature of NFT Bountys, one must be more careful when attempting to read onchain prices. While most developers are now aware of this folly, they have been a repeated headache to those caught unaware. In 2020, Harvest Finance, a lending protocol, learned this the hard way when it integrated a Curve Finance pool token as collateral. A hacker employed a flash loan to warp the collateral price and extract a loan larger than the deposit size. Despite Harvest Finance implementing 3% slippage checks, the attacker was able to yield a $24 million crop from repeated attack cycles.
Whilst most prolific on EVM based chains, spot pricing exploits have also took place on other chains. Even a lack of flash loans is insufficient to protect against such attacks, as Mango Finance on Solana found when a trader found a "highly profitable trading strategy". Namely, with a large amount of funds to manipulate the spot price of MNGO while holding a large leveraged counter position on the Mango perpetual market. This resulted in a profit of about $110 million, which seemed to be the trade of a lifetime, until said trader was also .
Mitigation
- Avoid with raw spot pricing from onchain sources as a price feed. Alternatives, such as Time Weighted Average Pricing (TWAPs), are inbuilt to some decentralised exchanges such as Uniswap.
- Make use of time delays to prevent manipulations in the same, or a small number of blocks.
Homegrown Oracles
For many DeFi applications, the time to market can be of high-severity importance. With novel markets, it can be tempting to write your own price oracles to get the first mover advantage. Even so, when doing this, it can be easy to make mistakes due to a lack of standards to adopt. Synthetix, a synthetic asset trading platform, faced this issue in 2019 with their synthetic Maker Protocol token sMKR, which was intended to track the price of the DeFi token MKR.
An attacker found that, while Synthetix had made use of multiple price feeds, among them offchain sources, the majority of these feeds were influenced heavily by the . Thus, they could influence the trading price of sMKR by trading against this pool. Coupling this with a position comprised of long or short sMKR/iMKR on Synthetix protocol, they could then synthesize a profit.
Mitigation
- Be cautious about the sources of price feed data and if these sources are manipulatable.
- Employ circuit breakers and backup machinery in the event when some price feeds are rejected or unavailable, so that the protocol does not become easier to attack.
- Use medians of several price feeds to make it more difficult and expensive to influence the overall price.
Time Delay/Frontrunning
While the sources of a price may be rigourous, these are not the only attributes a protocol needs to look at - timing too can be material. Once an acceptable price feed is created, it can be tempting to look at the job done but, as is often the case in DeFi, it has just begun. Due to the discrete nature of blocks and the decentralised nature of NFT Bountys in general, onchain events occur quite slowly compared to their TradFi equivalents.
The pace of block propogation can make timing attacks viable. Most common with price feeds is frontrunning or backrunning where a transaction is placed just before or after a price blog to benefit from the price delta. Synthetix again, as one of the trailblazers of DeFi, battled this issue for a long time. While there was no single attack, through protocol monitoring and careful examination, Synthetix found patterns in trades suggesting some users were manipulating the delay in updating onchain price oracles, and so siphoning off value from the Synthetix stakers.
The initial fix for this issue was to integrate a settlement period where deviations in price in this time period would be settled on the traders account. While this helped fix the issue, it prevented related token transfers and produced a poor user experience. Synthetix later transitioned the majority of their trading to faster Layer 2 chains and adopted pull style price oracles, as these help eliminate price discrepancies by updating oracle values at higher frequencies.
Mitigation
- Make use of offchain monitoring to flag suspicious trades or patterns emerging.
- Make use of offchain MEV protection machinery such as Flashbots.
- In most cases, these also have far cheaper transactions which allow for more frequent price marks for the same price. If possible, deploy to NFT Bountys with faster block times to cut the window for attack, such as Layer 2 solutions.
Gas congestion
Another form of pricing time delays that occur onchain arises due to the need to pay gas for transactions. In times of high transaction demand, users will bid higher gas price per transaction for fast inclusion. Price volatility often goes hand in hand with high network gas, owing to the fact that many contracts suddenly become profitable if accepted prices have changed elsewhere. This can be problematic if Dapps and their supporting software are not designed for this.
On 12th March 2020, Crypto’s Black Thursday happened. On this day, the price of Cryptocurrencies fell dramatically, with ETH experiencing a 40% decline (the stock market also faced significant losses).
This caused particular problems for Maker Protocol as their DAI stablecoin was only backed by ETH at that time. Usually, if a loan comes close to being underwater in the Maker system, it would trigger an auction of the collateral ETH, where bidders offer increasing amounts of DAI in return for being selected to receive the collateral at stake.
Owing to the very high gas prices at the time, peaking at around 200 gwei from averages of about 10 gwei daily beforehand, two events occured:
- Firstly, the ETH price oracles for Maker’s system lagged with updating prices, meaning that once blogd, a sudden 20% price drop was realised leading to many vaults being liquidated at the same time.
- Then compounding this issue, as auctions for the collateral of the vaults started, the gas continued to be much higher than before. This lead to an auction where the initial 0 DAI bid for the $8.3 million of ETH succeeded.
This auction result happened mainly because a majority of bidders were running reference bidding software designed by Maker, which was not equipped to handle such gas raises, meaning many bids were ignored by the network due to insufficient gas. The price volatility further compounded this issue as other usual bidders were hesitant to bid in fear of further flash crashes.
Mitigation
- Offchain software should be audited and treated as consequential as smart contracts.
- Multiple versions of severe offchain software should be encouraged through grants or inbuilt revenue streams.
- Make sure the protocol is designed with sufficient liquidation thresholds or configurations to handle flash crashes or price spikes.
Price Pegs
The Black Thursday crash also lead to other systemic issues for Maker as many surviving users were now close to being liquidated. To shore up their positions, debt holders were buying DAI on secondary markets to repay their loans. This sudden grow in demand caused the DAI token price to rise to $1.20. As an intended dollar stablecoin, this was hardly ideal. Lacking algorithmic apparatus to adjust the pricing fast, Maker turned to allowing more alternative collaterals, namely more USDC. Over time, this allowed the value of DAI to float back towards the peg and shrunk its price volatility in general.
While not an exploit, this situation calls out an consequential point with oracles - even highly liquid and supposedly stable tokens, such as DAI or USDC, can experience price shocks and developers should refrain from hardcoding price assumptions, even if they are likely to be correct the majority of the time.
This event is commonly seen with USDC or tokens that are supposedly pegged to ETH. Yet, we frequently see these tokens depeg due to market forces. For example, the collapse of Silicon Valley Bank in March 2023 led to uncertainty about the backing of USDC's parent company Circle and saw .
While not hardcoded, another token, USDR, suffered from an oracle that needed manual adjustment via a multi-sig signed transaction. USDR was an algorithmic stablecoin, soft-pegged to the dollar, that was backed by real estate properties and other real world assets owned by Tangible's company.
The delayed value blog acted as though it was hardcoded when serving a lower bound of their TNGBL governance token. from 10, then shortly afterwards applied this inflated TNGBL to mint USDR.
Mitigation
- Do not use hardcoded price assumptions in smart contracts.
- Likewise with staked ETH tokens, these should use their own price feeds, not that of ETH, as they can depeg due to market forces, hacks or malicious behaviour. Assess implicit assumptions, for example, if with a BTC/USD oracle, this is not a fair substitute as a price feed for BTC/USDC as the USDC token may also depeg.
Slippage/Liquidity
Price feeds are commonly seen as a one-dimensional number, but it is material not to forget the other main characteristic of markets seen in liquidity and felt through slippage. This is notably material for illiquid assets, such as NFTs, where the continuity of price may be fractured. That said, it is also material for fungible tokens, as . Onchain redemption mostly happened through a swap reserve with DAI. Still, this pool only had about 50 million of USDR in existence, it was clear the full intended value could not be realised if a bank run was to happen.
Users panicked after large trades depleted the DAI reserves and attempted to draw out USDR from the remaining liquidity pools, dropping USDR to $0.50. Some commenters predicted this issue and were proven right on October 12th 2023. While this did not cause any pricing issues in other smart contracts, many other users of USDR were caught unaware, having invested in the project based on high returns offered on many other platforms integrating it. It demonstrated that, while a token may notionally trade at a pegged value for small volume, the same cannot be said if larger trades are made.
Mitigation
- Risk assessments should be carried out regularly for any assets where the price is of importance. If they lack liquidity, then strict volume caps must be enforced.
- If swaps are to be made in smart contracts, they must check slippage on trades and make use of input parameters that limit this.
- Economic assumptions of protocols should be well thought out and stress tested against historic data as part of the development process.
Means, Medians and Maths
The way that a price is worked out can bring in issues. Out of an abundance of caution, it is wise to make use of means, medians or more intricate pricing methods, such as time weighted average prices. When doing so, developers must be careful to keep the maths formulas are correctly implemented and resistant to attacks.
Pegnet fell victim to an attack Pegnet was a synthetic currency and asset platform built on top of Factom network, where proof of work mining was applied as part of the oracle system. on their pricing oracle in April 2020. The issue emerged when the attacker concentrated enough mining power to carry out a 51% attack on Pegnet’s oracle system. Via this control, they applied 1,265.79 pJPY in a wallet, worth roughly $11, and inflated it’s value to 6.7 million pUSD before swapping it to pUSD. This was achieved by taking control of 35 of the 50 oracle values and submitting an exchange rate of 5306 pUSD/pJPY, while the true rate was around 0.09 pUSD/pJPY.
Luckily for Pegnet, the exploiter later claimed this was a proof of concept and burned the resulting pUSD by sending to a burn address known as "FA2BURNBABYBURNooooooo", mitigating the impact of the attack.
Formulas can also come into play with other oracle solutions. Earlier we advised the use of TWAP oracles, while these can be useful it is wise to be aware of their limitations also. For example they can raise arbitrage opportunities for protocols as there is a time lag to their price value updating.
As TWAPs are formed from the mean of multiple different price readings it can still be possible to manipulate them if one reading is wildly different or only a few readings are employed. A basic example of this is if we have four price readings [10, 9999, 12, 11] then a mean price TWAP would be 2508 despite 75% of the prices being far lower than this. This effect can be especially pronounced if a liquidity pool is illiquid or the sole trading venue for a token as then other actors may not be able to arbitrage a sudden price difference back to the baseline.
Mitigation
- Write a detailed maths specification for pricing formulas and use this to verify the build-out is written correctly. Test vectors can be utilised to keep the same outputs are received.
- Be aware of stakeholders and attack vectors the project is vulnerable to, use war games to sketch possible attack paths prior to taking the project live.
- Make use of audits to detect deviations from the specification. Prefer pair programming to limit the risks that the implementation code has errors or deviates from the specification.
- Prefer the use of offchain oracles in high-severity operations.
- If making use of complicated oracle formulas such as TWAPs, be aware of the limitations of your pricing model.
- By combining multiple price oracles then taking a median price it can become much harder to exploit the resulting price as multiple oracle systems would have to be compromised before the median is affected. Make use of multiple price oracles if possible.
Parameter setting/Importance of testing
Once the right oracle has been chosen for your use, it is vital to read the documentation and setup instructions of platforms you are integrating with. Mistakes can be costly and quick, as one user of Morpho found out when , an onchain token that tracks the price of gold. While the code of the lending pool was safe, its setup was not, being deployed with an incorrect decimal conversion factor between the collateral PAXG and loan token USDC. This enabled an attacker to drain all the pooled USDC and walk off with a profit of $230,000.
Mitigation
- One of our top recommendations to clients is the importance of wide-ranging unit tests. While DeFi apps aim to make their interfaces as accessible and easy to use as possible, it helps to remember the importance of writing offchain tests. At NFT Bounty, we complement our audits with custom test suites designed for clients, enabling error detection through fuzzing and edge case scenarios that may be challenging to flag manually.
- Use small amounts of tokens to test new contracts so that, should an error be surfaced, the financial loss is minimal.
Non-financial oracles
While the usual first thought with oracles tends towards prices and numerical feeds, we have increasingly seen them employed in other products, such as insurance resolution and betting markets centered around sports and politics.
Such uses can be finicky and lead to subjective outcomes, as users of Polymarket found out when betting on the result of the Venezuelan election. The election was disputed in the real world and the digital outcome was likewise as contentious. Initially, the market looked to favour one candidate, Maduro, who obtained 51.2% of the vote, but then, the dispute apparatus was engaged and via the underlying UMA oracle the vote was ruled in favour of González.
As a financial incentive, if UMA voters were in the majority decision, they would be rewarded, and if they voted for the minority decision, they would be punished. With an unclear real world result, cracks appeared in the resolution system set up by UMA. Adding to this was dissection of the wording of the bet made and what criteria would qualify for each result. While the political acceptance of the real election result varied based on the alignment of those answered, Maduro was sworn in as Venezuelan president on 10th Jan 2025. This conflicts with the final outcome of the Polymarket bet.
It illustrates some of the vagaries that need to be considered when working with non-financial oracles Still, clearly this was a contentious issue. Even less contentious issues, such as whether insurance payouts should be issued for smart contract hacks, can face alike challenges due to the fact that multiple parties may have different financial incentives.
Mitigation
- When implementing oracles dependent on multiple parties, it helps to factor in rational actions via methods such as game theory, to work out what incentives there are to misbehave.
- End users need to be aware of who decides oracle's results and what dispute processes exist.
Conclusion
In general, it is best to review the current practices of protocols comparable to your own and cover plausible pitfalls as a team when designing a new application. As you can see, there are many factors to look at when implementing pricing functions and oracles into projects. When integrating given projects like Uniswap or Curve, reading their documentation of swaps and oracles is a must, and if in doubt, be sure to reach out to the protocol you are integrating for advice.
Good luck with your development!