简言:

网上的合约案例太少,并且已经过了很久,web3更新很快,当然笔者还合约不完善,后续会补充 这个案例主要适合新手学完solidity 需要案例:
1.是学会使用样例合约ERC20
2.学会使用动态价格,继承接口
3.路径验证
4.后续会补充完整案例解读

 注释代码解释全在代码里 

一.二话不说上代码 

引入四个包 没有的需要 npm 下载

npm install -save-dev @openzeppelin/contracts

npm install -save-dev @chainlink/contracts

第一个sol.创建一个流动性池
pragma solidity 0.8.20;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";//引入erc20 合约
import "@openzeppelin/contracts/access/Ownable.sol";//引入Ownable合约
import "@chainlink/contracts/src/v0.6/dev/AggregatorInterface.sol";//引入chainlink计价合约
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router01.sol";


interface ILiquidityPool {//定义一个流动性池
    //事件 当某个账户从流动性池中撤回资金时触发的事件 收到资金地址,撤回的金额,用户最终收到的的金额
    event Withdraw(      
        address indexed account,
        uint256 amount,
        uint256 writeAmount
    );
    //当某个账户向流动性池提供资金时触发的事件
    event Provide(
     address indexed account,
     uint256 amount, 
     uint256 writeAmount
    );
    function lock(uint256 amount) external;//锁定一定数量的资金到流动性池中。
    function unlock(uint256 amount) external;//解锁一定数量的已锁定资金
    function unlockPremium(uint256 amount) external;//用于解锁某些特殊条件下的额外奖励或高级解锁功能
    function send(address payable account, uint256 amount) external;//将一定数量的资金发送到指定的以太坊账户
    function setLockupPeriod(uint value) external;//设置资金的锁定周期
    function totalBalance() external view returns (uint256 amount);//查询流动性池中的总余额
}


interface IERCLiquidityPool is ILiquidityPool {//继承流动性池 添加ERC20合约功能
    function sendPremium(uint256 amount) external;//发送一定数量的额外奖励
    function token() external view returns (IERC20);//回与流动性池关联的ERC20代币的接口
}


interface IETHLiquidityPool is ILiquidityPool {//继承流动性池
    function sendPremium() external payable;//可以接受以太坊的转账
}
第二个个.sol 
pragma solidity 0.8.20;
import "../contracts/Interfaces.sol";

//模拟一个货币交易所 允许用户用以太币(ETH)交换FakeUSD伪装代币
contract FakeExchange {
    AggregatorInterface price; //用于获取FakeUSD相对于ETH的价格

    uint256 public spread = 99;//交易的手续费,以百分比形式表示(这里是99%,意味着实际得到的FakeUSD会少于按价格计算得到的数量)

    address public WETH = address(this); //address(this)就是获取当前合约的地址 赋值黑WETH

    constructor(AggregatorInterface pp, FakeUSD t) public {
        price = pp;// 构造函数 定义价格  价格提供者接口
        token = t;// FakeUSD代币合约的 地址
    }

    receive() external payable {} //接收以太币的fallback函数

    FakeUSD token; //FakeUSD代币合约的引用
    //允许用户支付ETH以换取FakeUSD。函数检查路径是否有效,计算应得到的FakeUSD数量,并调用FakeUSD合约的mintTo方法将代币发送到用户的地址
    function swapExactETHForTokens(
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256
    ) external payable returns (uint256[] memory amounts) {
        // 验证路径   路径相同 下一步
        require(path[0] == WETH, "UniswapV2Router: INVALID_PATH");
        //计算应得到的FakeUSD 价格(数量)  调用getEthToTokenInputPrice函数  当前数量*当前价格
        uint256 amount = getEthToTokenInputPrice(msg.value);
        // 检查手续费后的数量是否足够  当前FakeUSD是否大于 最小值
        require(amount >= amountOutMin, "Spread is too high");
        //通过FakeUSD函数  铸造(创建)并发送到指定地址
        token.mintTo(to, amount);
        // 初始化输出数组
        amounts = new uint256[](path.length);
        // 输入ETH数量 当前数量
        amounts[0] = msg.value;
        // 输出FakeUSD数量
        amounts[path.length - 1] = amount;
    }
    //计算从FakeUSD到ETH的交换价格  
    function getTokenToEthInputPrice(uint256 tokens_sold)
        public
        view
        returns (uint256 eth_bought)
    {
        eth_bought =
            ((tokens_sold * 1e6) / uint256(price.latestAnswer())) *
            spread;//将代币数量乘以1e6(即1,000,000) 除以 返回的价格 再 乘以99% spread(手续费)
    }
    //ETH到FakeUSD的交换价格
    function getEthToTokenInputPrice(uint256 eth_sold)
        public
        view
        returns (uint256 tokens_bought)
    {
        tokens_bought =
            (eth_sold * uint256(price.latestAnswer()) * spread) / 
            1e10;//表示要卖出的以太坊数量 乘以 返回的价格  乘以99% spread(手续费)
    }

    function withdrow() public {
        // 注意:这里可能需要添加权限检查,以确保只有特定用户可以提取资金
        msg.sender.transfer(address(this).balance);// 将合约余额转移到调用者地址
    }
}


contract FakePriceProvider {// 价格提供者
    uint256 public price;

    constructor(uint256 p) public {
        price = p;//定义一个价格 构造函数加载一次
    }

    function latestAnswer() external view returns (uint256) {
        return price; //返回当前的价格
    }

    function setPrice(uint256 _price) public {
        price = _price;//允许修改价格
    }
}


contract FakeUSD is ERC20("FakeUSD", "FAKE") {// 继承了ERC20标准的稳定币的合约
    function mintTo(address account, uint256 amount) public {
        _mint(account, amount);//通过调用_mint方法 向指定地址铸造(创建)指定数量的FakeUSD
    }

    function mint(uint256 amount) public {
        _mint(msg.sender, amount);//通过调用_mint方法 向调用者的地址铸造 指定数量的FakeUSD。
    }
}

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐