
Instead of giving you the usual AI slop opener (like most of you do...) I would rather jump strait into the bugs. Enjoy:
When working with Redstone (not the minecraft one) you will most likely use the pull based mechanics (else you would use ChainLink), like this one:

Pretty simple. Users can updatePrice with the new prices in msg.data, which getOracleNumericValuesFromTxMsg uses to verify and return the price. Since Redstone validates that the data must be at least 3 min old (and no more than 1 min into the future) we don't need any validations here.
However there is still an issue here. We can travel in back and forth in time (figuratively speaking).
Since we do no checks here, we can technically update the price to be up to now, then update it again to be now - 3min. For example:
ETH is 3k at T = now (I wish D:)
Borrower borrows up to their max
Liquidator updates the price to be 2.9k for when T - 3min
Liquidates the user
The current price was $3000 and our borrower should not be liquidatable, but we did liquidate him.
Some projects use interesting token connections. For this example our project was lending/borrowing and 2 of the assets were BTC and UNI.
At first it sounds really simple, just denominate BTC in UNI, or UNI in BTC and decide how much each costs compared to the other. However that is not so simple, since ChainLink does not have a feed that reports BTC price in UNI, or UNI price in BTC. It has BTC/ETH and UNI/ETH.
So we must use 2 feeds, why is that a problem? It's not if you know how to handle it (as every issue out there). However it is if you didn't know about it.
The problem here is that 2, or in our case 3 feed wBTC -> BTC -> ETH -> UNI. We start with wBTC → BTC, because we are on ETH and don't have access to BTC directly and shouldn't assume 1 BTC == 1 wBTC.
The deviation threshold expands with each feed. Where in total we would have 4.5% deviation:
wBTC/BTC - 0.5%
BTC/ETH - 2%
UNI/ETH - 2%
Where that becomes a problem?
When you don't know that the total deviation can stack and set too tight liquidation margins. With a 4.5% compounded deviation (4% more realistically since BTC doesn't often deviate from wBTC), the oracle price can be up to 4.5% stale compared to the real market price in either direction.
This creates two problems:
Phantom solvency — A borrower whose position is underwater at real market prices still looks healthy to the protocol because the oracle hasn't crossed its deviation threshold yet. By the time the feed updates, the position is deep in bad debt and liquidators can't cover it profitably.
Wrongful borrowing — A user deposits collateral and the oracle overvalues their collateral relative to the market. They borrow more than they should be able to. When the next update lands, they're instantly liquidatable.
The worst part is that neither are an "attack", but can and will happen on occasion.
The fix is really simple. Make sure you check all deviations and lower the LTV by them. Also I will recommend to not allow borrowers to borrow up to the max LTV, but leave a gap (so they won't get liquidated in the next update).
See anything interesting here? Yes? No?

I had to include it. It's 2026 and even now I see people do it... AI knows to not write it like this so why do developers do it?
If you don't know what I am talking about it's the fact that feed may have different staleness timestamps. Some might have a few hours and others 24h. However if you use 1 for all, then you are either using stale data (for feeds that have smaller time allowance than the one you give) or marking perfectly fine data as stake (for feeds that have bigger allowance).
The solution? Just use a map and set each feed to it's own staleness.

We are back to Pyth and it's "mysterious" ways of working. Most people will assume since Pyth is instant, and they are pulling the price themselves, that the price is what it's returned. Simple right?
Not exactly. Pyth has confidence (unlike you) where the confidence is a +/- bracket where the price can be.
Simplest example is when you get the price of ETH at $2000 and Pyth returns $2000 with confidence of +/- 50. Now the price can be 2k, or 1950, or 2050, or 1967 (1969 for you old folks...). Ok, ok, but what's the issue here?
The issue is that your project will assume the price is X and allow things to happen based on that X price, be it a liquidation, or allowed borrowing, or let you 50x on your YES position on "will dickbut will rise by 6.7% by the end of week" (I spend too much time on X D:).
Where in fact the price was not X, but X+y or X-y... So how do you fix it?
Assume the worst case scenario. When borrowing the project should assume the coll token price is X-y and the borrow token price is X+y, aka. always favor the project over the user.
Did you happen to use stablecoins in your vault? If so how do you price them? Of course it's 1$, it's a stable coin after all! Why would you need a oracle for it?
It's 2026 and bugs like this still exist (some Morpho vaults can confirm).
The problem here is that you are either skipping an oracle all together or using one that essentially hardcodes the vaults of stable coins to 1 USD. And don't get me wrong, this will work 99.99% of the time, however when it fails is when you will get wrecked.
The correct way to do it is to assume everything will change it's price some time in the future. Assets will rise and fall in value, stable assets will depeg, everything that can happen will.
oracle setups that require 2+ feeds but also need to support single-feed assets like rETH → ETH
Building anything that deals with oracles?
If you have a mainnet launch, upgrade, or token event in the next 60 days and your contracts haven’t been re‑audited, you’re running on luck.
Book a security audit review call with us here:
https://phagesecurity.com/request-audit
or hit me up in my TG at @Pyro3b.

Instead of giving you the usual AI slop opener (like most of you do...) I would rather jump strait into the bugs. Enjoy:
When working with Redstone (not the minecraft one) you will most likely use the pull based mechanics (else you would use ChainLink), like this one:

Pretty simple. Users can updatePrice with the new prices in msg.data, which getOracleNumericValuesFromTxMsg uses to verify and return the price. Since Redstone validates that the data must be at least 3 min old (and no more than 1 min into the future) we don't need any validations here.
However there is still an issue here. We can travel in back and forth in time (figuratively speaking).
Since we do no checks here, we can technically update the price to be up to now, then update it again to be now - 3min. For example:
ETH is 3k at T = now (I wish D:)
Borrower borrows up to their max
Liquidator updates the price to be 2.9k for when T - 3min
Liquidates the user
The current price was $3000 and our borrower should not be liquidatable, but we did liquidate him.
Some projects use interesting token connections. For this example our project was lending/borrowing and 2 of the assets were BTC and UNI.
At first it sounds really simple, just denominate BTC in UNI, or UNI in BTC and decide how much each costs compared to the other. However that is not so simple, since ChainLink does not have a feed that reports BTC price in UNI, or UNI price in BTC. It has BTC/ETH and UNI/ETH.
So we must use 2 feeds, why is that a problem? It's not if you know how to handle it (as every issue out there). However it is if you didn't know about it.
The problem here is that 2, or in our case 3 feed wBTC -> BTC -> ETH -> UNI. We start with wBTC → BTC, because we are on ETH and don't have access to BTC directly and shouldn't assume 1 BTC == 1 wBTC.
The deviation threshold expands with each feed. Where in total we would have 4.5% deviation:
wBTC/BTC - 0.5%
BTC/ETH - 2%
UNI/ETH - 2%
Where that becomes a problem?
When you don't know that the total deviation can stack and set too tight liquidation margins. With a 4.5% compounded deviation (4% more realistically since BTC doesn't often deviate from wBTC), the oracle price can be up to 4.5% stale compared to the real market price in either direction.
This creates two problems:
Phantom solvency — A borrower whose position is underwater at real market prices still looks healthy to the protocol because the oracle hasn't crossed its deviation threshold yet. By the time the feed updates, the position is deep in bad debt and liquidators can't cover it profitably.
Wrongful borrowing — A user deposits collateral and the oracle overvalues their collateral relative to the market. They borrow more than they should be able to. When the next update lands, they're instantly liquidatable.
The worst part is that neither are an "attack", but can and will happen on occasion.
The fix is really simple. Make sure you check all deviations and lower the LTV by them. Also I will recommend to not allow borrowers to borrow up to the max LTV, but leave a gap (so they won't get liquidated in the next update).
See anything interesting here? Yes? No?

I had to include it. It's 2026 and even now I see people do it... AI knows to not write it like this so why do developers do it?
If you don't know what I am talking about it's the fact that feed may have different staleness timestamps. Some might have a few hours and others 24h. However if you use 1 for all, then you are either using stale data (for feeds that have smaller time allowance than the one you give) or marking perfectly fine data as stake (for feeds that have bigger allowance).
The solution? Just use a map and set each feed to it's own staleness.

We are back to Pyth and it's "mysterious" ways of working. Most people will assume since Pyth is instant, and they are pulling the price themselves, that the price is what it's returned. Simple right?
Not exactly. Pyth has confidence (unlike you) where the confidence is a +/- bracket where the price can be.
Simplest example is when you get the price of ETH at $2000 and Pyth returns $2000 with confidence of +/- 50. Now the price can be 2k, or 1950, or 2050, or 1967 (1969 for you old folks...). Ok, ok, but what's the issue here?
The issue is that your project will assume the price is X and allow things to happen based on that X price, be it a liquidation, or allowed borrowing, or let you 50x on your YES position on "will dickbut will rise by 6.7% by the end of week" (I spend too much time on X D:).
Where in fact the price was not X, but X+y or X-y... So how do you fix it?
Assume the worst case scenario. When borrowing the project should assume the coll token price is X-y and the borrow token price is X+y, aka. always favor the project over the user.
Did you happen to use stablecoins in your vault? If so how do you price them? Of course it's 1$, it's a stable coin after all! Why would you need a oracle for it?
It's 2026 and bugs like this still exist (some Morpho vaults can confirm).
The problem here is that you are either skipping an oracle all together or using one that essentially hardcodes the vaults of stable coins to 1 USD. And don't get me wrong, this will work 99.99% of the time, however when it fails is when you will get wrecked.
The correct way to do it is to assume everything will change it's price some time in the future. Assets will rise and fall in value, stable assets will depeg, everything that can happen will.
oracle setups that require 2+ feeds but also need to support single-feed assets like rETH → ETH
Building anything that deals with oracles?
If you have a mainnet launch, upgrade, or token event in the next 60 days and your contracts haven’t been re‑audited, you’re running on luck.
Book a security audit review call with us here:
https://phagesecurity.com/request-audit
or hit me up in my TG at @Pyro3b.

The most common vault bugs (from real audits)
Real bugs we keep finding in DeFi vaults: first depositor, bad debt, MEV, lockup gaming, insolvency, broken reward handling, and yield killing routing. If you’re building or integrating vaults, read this before mainnet or you’ll learn these the hard way.

The most common prediction market bugs (from real audits, not theory)
Prediction markets and the protocols building on top of them are booming. If you're one of those teams, this list of bugs should matter to you. I'm not going to claim this replaces an audit, but every bug here is something we at Phage Security have caught in real engagements, and the patterns were consistent enough that I thought they deserved a write up.

Focus ain't the secret
Focus ain't the secretAnother day, another segment of mastering your mind. As always, today you're going to realize that it wasn't your fault, not in your relationships (there you totally deserved everything), but in your career/business. I am going to show you how to unlock your secret potential and achieve what you truly desire.What you missedUp until now, you've been aware of only 25% of the equation. Everyone has explained why focus is essential and how to achieve it, ...

The most common vault bugs (from real audits)
Real bugs we keep finding in DeFi vaults: first depositor, bad debt, MEV, lockup gaming, insolvency, broken reward handling, and yield killing routing. If you’re building or integrating vaults, read this before mainnet or you’ll learn these the hard way.

The most common prediction market bugs (from real audits, not theory)
Prediction markets and the protocols building on top of them are booming. If you're one of those teams, this list of bugs should matter to you. I'm not going to claim this replaces an audit, but every bug here is something we at Phage Security have caught in real engagements, and the patterns were consistent enough that I thought they deserved a write up.

Focus ain't the secret
Focus ain't the secretAnother day, another segment of mastering your mind. As always, today you're going to realize that it wasn't your fault, not in your relationships (there you totally deserved everything), but in your career/business. I am going to show you how to unlock your secret potential and achieve what you truly desire.What you missedUp until now, you've been aware of only 25% of the equation. Everyone has explained why focus is essential and how to achieve it, ...
Smart contract security researcher. If you want an audit done, feel free to message me on twitter.
Smart contract security researcher. If you want an audit done, feel free to message me on twitter.
Working with oracles like Pyth isn’t just about fetching a price—it’s about understanding uncertainty. Pyth provides a confidence range, meaning the “true” price could sit anywhere within that bracket. If your project assumes the midpoint as exact, you risk mispricing collateral, triggering wrong liquidations, or letting users exploit positions. The fix is simple in theory: always assume the worst-case scenario for the project—collateral could be worth less, borrowed assets worth more. Even stablecoins aren’t immune; hardcoding them to $1 works most of the time, but a single depeg can ruin a vault. Robust oracle design means accounting for all possibilities, supporting multiple feeds while handling single-feed assets, and never ignoring the risk of future price shifts.
Share Dialog
Share Dialog

Subscribe to Pyro | 0x3b

Subscribe to Pyro | 0x3b
<100 subscribers
<100 subscribers
1 comment
Working with oracles like Pyth isn’t just about fetching a price—it’s about understanding uncertainty. Pyth provides a confidence range, meaning the “true” price could sit anywhere within that bracket. If your project assumes the midpoint as exact, you risk mispricing collateral, triggering wrong liquidations, or letting users exploit positions. The fix is simple in theory: always assume the worst-case scenario for the project—collateral could be worth less, borrowed assets worth more. Even stablecoins aren’t immune; hardcoding them to $1 works most of the time, but a single depeg can ruin a vault. Robust oracle design means accounting for all possibilities, supporting multiple feeds while handling single-feed assets, and never ignoring the risk of future price shifts.