I am trying to build a smart contract that would give a fixed price in USD for each NFT to be minted by others, which they will need to pay in ETH. But I found a problem that the price of ETH is always changing, and each update of the NFT price in ETH would need some gas fee, which could cost a lot in long term for maintenance. Is there a way to periodically update ETH price inside the smart contract, or is manual updating the only way to do it?
Or I might have to remove the NFT price limit and completely rely on the frontend to handle the pricing part. But I think that's too risky.
You can use a Chainlink datafeed that returns the price of ETH in USD.
There are no datafeeds in emulators (e.g. Ganache or the Remix IDE built-in network), so you can test this snippet on your local fork of the Ethereum mainnet.
pragma solidity 0.8;
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract MyContract {
AggregatorV3Interface priceFeed;
// 18 decimals
uint256 requiredPriceInUsd = 1000 * 1e18;
constructor() {
// https://etherscan.io/address/0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419#code
// Chainlink ETH/USD Price Feed for Ethereum Mainnet
priceFeed = AggregatorV3Interface(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419);
}
// returns amount of wei
function getRequiredPriceInWei() public view returns (uint256) {
(,int answer,,,) = priceFeed.latestRoundData();
// returned price is 8 decimals, convert to 18 decimals
uint256 ethUsdPrice = uint256(answer) * 1e10;
// 36 decimals / 18 decimals = 18 decimals
return (requiredPriceInUsd * 1e18) / ethUsdPrice;
}
}
Output from my test:
answer
is 122884000000
(1228 USD and 8 decimals)getRequiredPriceInWei()
is 813775593242407473
(of wei, that's ~0.8 ETH for 1,000 USD)