solidity

How to find proper address to use AggregatorV3Interface?


I am using hardhat and metamask on a local blockchain and I have imported AggregatorV3Interface and am trying to get the latest price of USDT in my contract to exchange Ethereuem to USDT. Here is the minimized version of my contract:

// SPDX-License-Identifier: Unlicensed

pragma solidity ^0.8.28;

import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol";


contract token {
    AggregatorV3Interface internal dataFeed;

    constructor() {
        dataFeed = AggregatorV3Interface(
            0x89983A2FDd082FA40d8062BCE3986Fc601D2d29B // Where this address must come from?
        );
    }

    function buyTokenWithETH(address receivingAddress, uint256 ethBalance) public payable returns (bool) {
        uint256 ethPrice = getChainlinkDataFeedLatestAnswer();
        return true;
    }


    function getChainlinkDataFeedLatestAnswer() public view returns (uint256) {
        // prettier-ignore
        (
            /* uint80 roundId */,
            int256 answer,
            /*uint256 startedAt*/,
            /*uint256 updatedAt*/,
            /*uint80 answeredInRound*/
        ) = dataFeed.latestRoundData();
        return uint256(answer);
    }

and here is the frontend:

let walletAddress = "0x7...8";
let tokenAddress = "0xc...d";
...
let ethBalance = await provider.getBalance(tokenAddress)/decimals;
let buy_Token = await tokenContract['buyTokenWithETH'](walletAddress, ethBalance);

If I hard code the value of ethPrice it works, but when I call the function getChainlinkDataFeedLatestAnswer() then I get the error:

> Error: execution reverted (no data present; likely require(false) occurred
(action="estimateGas", data="0x", reason="require(false)",
transaction={ "data": "0xb...003", "from": "0x7...8", "to": "0xc...d" },
invocation=null, revert=null, code=CALL_EXCEPTION, version=6.15.0)

If I hard code the return value of getChainlinkDataFeedLatestAnswer() function (e.g., return uint256(1);) it works without problem.

So I think getChainlinkDataFeedLatestAnswer() function doesn't do what it suppose to do!Does anyone know what can be the problem? Thanks in advance!


Solution

  • Chainlink uses its own data feed smart contracts (that implement the AggregatorV3Interface) and keeps them updated with current data (prices, volumes, etc). On a public chain, you need to use their list of contracts as the source of truth: https://data.chain.link/feeds

    For example, the USD price feed for ETH on Ethereum mainnet is deployed at 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419, as linked from the page https://data.chain.link/feeds/ethereum/mainnet/eth-usd.

    ---

    On a local chain (assuming the local chain is not forked from a public one), you'll need to build a mock data feed, deploy it to a new address, and then pass this MockFeed address into your token constructor.

    Your local chain is empty when you start it (unless forked), there's no predeployed contracts from Chainlink or anyone else. So you need to deploy your own price feed.

    pragma solidity ^0.8;
    
    contract MockFeed {
        uint8 public constant decimals = 8;
    
        function latestRoundData() external pure returns (uint80,int256,uint256,uint256,uint80)
        {
            return (
                0, // roundId
                100000000, // answer - price of 1.0 with 8 decimals
                0, // startedAt
                0, // updatedAt
                0 // answeredInRound
            );
        }
    }
    
    contract token {
        AggregatorV3Interface internal dataFeed;
    
        // pass the feed address in constructor
        // the feed address depends on chain
        // on local chain, you need to deploy your own feed
        constructor(AggregatorV3Interface _datafeed) {
            dataFeed = _datafeed;
        }
    
        // ... rest of your code
    }
    

    ---

    On a public chain (or a local fork of a public chain), you should pass the Chainlink contract address from the list linked above to your constructor.