关于以太坊链上ETH转USD的转换逻辑

在编写合约中,觉得ETH转USD的金额转换很绕,因此记录一下。
这是一份合约代码:

pragma solidity ^0.8.0;

import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol";
//1、创建一个收款函数
//2、记录投资人并且查看
//3、在锁定期内,达到目标值,生产商可以提款
//4、在锁定期内,没有达到目标值,投资人在锁定期以后退款
contract FundMe{
    AggregatorV3Interface internal dataFeed;
    //投资人
    mapping(address =>uint256) public fundersToAmount;
    event EthToUsdEvent(string message ,uint256 money);
    event MoneySumEvent(string message, uint256 money);
    //最小额度
    uint256 MININUM_VALUE = 100 * 10 **18; //usd
    //关于TARGET为什么是1000 * 10 ** 18,因为合约中默认的金额但是为wei,此处的TARGET是wei的USD
    uint256 constant TARGET = 1000 * 10 ** 18; //目标值是1000
    function fund() external payable {
        //fundersToAmount[msg.sender]  = fundersToAmount[msg.sender]+msg.value;
        //限定最小额度
        uint256 money = convertEthToUsd(msg.value);
        emit EthToUsdEvent("convert monry is:",money);
        /**
        * 下面这一行代码等同于
        *uint256 convertToRealMoney = money/(10 **18);
        *require(money >= 100,"send more ETH");
         */
        require(money >= MININUM_VALUE,"send more ETH");
        fundersToAmount[msg.sender] = msg.value;
    }

    constructor(){
        //Sepolia Testnet的USD-ETH的地址
        dataFeed = AggregatorV3Interface(0x694AA1769357215DE4FAC081bf1f309aDC325306);
    }
    
    function getBalanceOf() public view returns (uint){
        return address(this).balance;
    }

    function getChainLinkDataFeedLatestAnswer() public view returns (int){
        //prettier-ignore
        (
            /*uint80 roundID */,
            int answer,
            /*uint startedAt*/,
            /*uint timeStamp*/,
            /*uint80 answeredInRound*/
        ) = dataFeed.latestRoundData();
        return answer;
    }
    //返回wei对应的usd
    function convertEthToUsd(uint256 ethAmount) internal view returns(uint256){
        //此处的ethAmount单位是wei,这块不能用ethAmount/(10 **18),有可能是小数
        uint256 ethPrice = uint256(getChainLinkDataFeedLatestAnswer());
        return ethAmount * ethPrice / (10 **8);
    }
    /**
    * @dev 提款功能,关于
     */
    function getFund() external{
        uint256 moneySum = convertEthToUsd(address(this).balance);
        emit MoneySumEvent("The money sum is:",moneySum);
        require( moneySum>= TARGET,"Target is not reached");
    }
} 

疑问:开始始终搞不明白100 * 10 **18为什么要这么写:uint256 MININUM_VALUE = 100 * 10 **18;

  1. 首先以fund()函数为例,在remix中输入eth金额,
  2. 点击fund,fund()函数内部调用convertEthToUsd(msg.value),
  3. 注意,在return ethAmount * ethPrice / (10 8)中除以(108)是因为Chainlink返回的汇率单位是 “美元价格 ×
    1e8”,而ethAmount的单位是wei,所以想要得到真是wei对应usd的价格需要除以(10 **8)。
  4. 这行代码中require(money >= MININUM_VALUE,"send more ETH");money是wei对应的usd价格,所以需要用
    MININUM_VALUE要用100 * 10 **18表示。
  5. 当然,这行代码也可以这样写,更容易理解:
function fund() external payable {
        //fundersToAmount[msg.sender]  = fundersToAmount[msg.sender]+msg.value;
        //限定最小额度
        uint256 money = convertEthToUsd(msg.value);
        emit EthToUsdEvent("convert monry is:",money);
        uint256 convertRealMoney = money/(10 **18);
        require(convertRealMoney >= 100,"send more ETH");
        fundersToAmount[msg.sender] = msg.value;
}
  1. 在这行代码中,uint256 convertRealMoney = money/(10 **18);先除以10 **18,再和100比较。
posted @ 2025-05-24 18:10  Charlie-Pang  阅读(107)  评论(0)    收藏  举报