Created
July 16, 2025 14:35
-
-
Save ShariqKhan2012/960b81b12ecbd5b30e8f28ec03e7badd to your computer and use it in GitHub Desktop.
A TokenShop implementation that demonstrates use of the ChainLink price feed to fetch ETH/USD prices
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.24; | |
| import {AggregatorV3Interface} from "@chainlink/contracts@1.3.0/src/v0.8/shared/interfaces/AggregatorV3Interface.sol"; | |
| import {Ownable} from "@openzeppelin/contracts@5.2.0/access/Ownable.sol"; | |
| import {MyERC20} from "./MyERC20_OpenZeppelin.sol"; | |
| contract TokenShop is Ownable { | |
| error TokenShop__CouldNotWithdraw(); | |
| error TokenShop__ZeroETHSent(); | |
| event BalanceWithdrawn(); | |
| uint256 public constant TOKEN_DECIMALS = 18; | |
| uint256 public constant TOKEN_PRICE_IN_USD = 2 * 10 ** TOKEN_DECIMALS; | |
| MyERC20 private immutable i_token; | |
| AggregatorV3Interface private immutable i_priceFeed; | |
| constructor(address tokenAddress) Ownable(msg.sender) { | |
| i_token = MyERC20(tokenAddress); | |
| /** | |
| * Network: Sepolia Testnet | |
| * Aggregator: ETH/USD | |
| * Address: 0x694AA1769357215DE4FAC081bf1f309aDC325306 | |
| */ | |
| i_priceFeed = AggregatorV3Interface(0x694AA1769357215DE4FAC081bf1f309aDC325306); | |
| } | |
| function getETHPriceInUSDFromChainLink() public view returns (int256) { | |
| ( | |
| /*uint256 roundId*/, | |
| int256 price, | |
| /*uint startedAt*/, | |
| /*uint timeStamp*/, | |
| /*uint80 answeredInRound*/ | |
| ) = i_priceFeed.latestRoundData(); | |
| return price; | |
| } | |
| function amountToMint(uint256 ethAmountInWei) public view returns(uint256) { | |
| /** | |
| * 1 Token = TOKEN_PRICE_IN_USD USD | |
| * => 1 USD = 1 / TOKEN_PRICE_IN_USD Tokens | |
| * | |
| * 1 ETH = getETHPriceInUSDFromChainLink() USD | |
| * => 1 ETH = ( getETHPriceInUSDFromChainLink() / TOKEN_PRICE_IN_USD ) Tokens | |
| * => N ETH = (N * getETHPriceInUSDFromChainLink() ) / TOKEN_PRICE_IN_USD ) Tokens | |
| * | |
| * Now, N (ethAmountInWei) has 18 decimals, as it is in Wei (1 ETH = 10**18 Wei) | |
| * TOKEN_PRICE_IN_USD too has 18 decimals | |
| * So, we need to normalize the result of getETHPriceInUSDFromChainLink as well to 18 | |
| * ChainLink returns the results with 8 decimals, so we need to multiply by 10**10 | |
| * | |
| * => N ETH = (N * getETHPriceInUSDFromChainLink() * 10 ** 10 ) / TOKEN_PRICE_IN_USD ) Tokens | |
| */ | |
| uint256 ethPriceInUSD = uint256( getETHPriceInUSDFromChainLink()); | |
| return (ethAmountInWei * ethPriceInUSD * 10**10) / TOKEN_PRICE_IN_USD; | |
| } | |
| receive() external payable { | |
| if(msg.value <= 0) { | |
| revert TokenShop__ZeroETHSent(); | |
| } | |
| uint256 numTokensToMint = amountToMint(msg.value); | |
| i_token.mint(msg.sender, numTokensToMint); | |
| } | |
| function withdraw() external onlyOwner { | |
| (bool success, ) = payable(msg.sender).call{value: address(this).balance}(""); | |
| if(!success) { | |
| revert TokenShop__CouldNotWithdraw(); | |
| } | |
| emit BalanceWithdrawn(); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment