Solidity Price Oracles
A price oracle is a contract that reports a price other contracts can read. Other contracts use that reported price instead of working out a price on their own.
A mock feed stores a price its owner sets
The owner sets the price and anyone can read it back. A reader who is not the owner cannot change it.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
contract MockFeed {
address public owner;
uint256 public price;
constructor() {
owner = msg.sender;
}
function setPrice(uint256 newPrice) public {
require(msg.sender == owner, "only owner sets price");
price = newPrice;
}
}
A consumer reads the price from the feed
The consumer holds the feed behind an interface and reads through it. The consumer never stores the price itself.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
interface IFeed {
function price() external view returns (uint256);
}
contract MockFeed {
address public owner;
uint256 public price;
constructor() {
owner = msg.sender;
}
function setPrice(uint256 newPrice) public {
require(msg.sender == owner, "only owner sets price");
price = newPrice;
}
}
contract PriceReader {
IFeed public feed;
constructor(IFeed feedAddress) {
feed = feedAddress;
}
function readPrice() public view returns (uint256) {
return feed.price();
}
}
An owner update changes what consumers read
The owner sets a new price and the same consumer reads the new value. No change to the consumer is needed.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
interface IFeed {
function price() external view returns (uint256);
}
contract MockFeed {
address public owner;
uint256 public price;
constructor() {
owner = msg.sender;
}
function setPrice(uint256 newPrice) public {
require(msg.sender == owner, "only owner sets price");
price = newPrice;
}
}
contract PriceReader {
IFeed public feed;
constructor(IFeed feedAddress) {
feed = feedAddress;
}
function readPrice() public view returns (uint256) {
return feed.price();
}
}
Example
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
interface IFeed {
function price() external view returns (uint256);
}
contract MockFeed {
address public owner;
uint256 public price;
constructor() {
owner = msg.sender;
}
function setPrice(uint256 newPrice) public {
require(msg.sender == owner, "only owner sets price");
price = newPrice;
}
}
contract PriceConverter {
IFeed public feed;
constructor(IFeed feedAddress) {
feed = feedAddress;
}
function convert(uint256 amount) public view returns (uint256) {
return amount * feed.price();
}
}
Key points
- Oracle: a contract that reports a price for other contracts to read.
- Mock feed: a toy feed whose price its owner sets, used for teaching and testing.
- Consumer: a contract that reads the price from an oracle.
- Shared price: many consumers reading one oracle all see the same price.
- Price update: the owner changes the stored price and later reads show the new price.
In this example, a mock feed holds a price and a converter reads that price through an interface. Converting an amount multiplies it by the current price, so an owner update changes every later conversion.
Note
a mock feed price is set by its owner, so it is trusted input and not a market price.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Remix IDE
Exercise
Who sets the price in a mock feed?