如何判断接收者是否为流动性池?

问题描述 投票:0回答:2

我正在创建一种代币,当在流动性池上出售时,会收取费用并燃烧一定数量的代币。

既然我有收款地址,我如何检查它是否是流动性池?

我想我也许可以使用这个:https://docs.uniswap.org/protocol/V2/reference/smart-contracts/pair-erc-20但是我不确定哪个功能可以工作或者是否可以还有另一种方法。

ethereum solidity smartcontracts uniswap
2个回答
4
投票

您可以针对 Uniswap Pair (V2)Uniswap Pool (V3) 接口测试该地址是否返回预期值。

更进一步,您可以将这些返回值传递回 Uniswap Factory 合约(地址可以在V2 docsV3 docs中找到),它会根据输入值告诉您一个矿池地址。这样你就可以确定查询的地址实际上是一个 Uniswap 池,而不仅仅是其他一些从同名函数返回值的合约。

pragma solidity ^0.8;

import "https://github.com/Uniswap/v2-core/blob/master/contracts/interfaces/IUniswapV2Factory.sol";
import "https://github.com/Uniswap/v3-core/blob/main/contracts/interfaces/IUniswapV3Factory.sol";
import "https://github.com/Uniswap/v2-core/blob/master/contracts/interfaces/IUniswapV2Pair.sol";
import "https://github.com/Uniswap/v3-core/blob/main/contracts/interfaces/IUniswapV3Pool.sol";

contract MyContract {
    IUniswapV2Factory constant v2Factory = IUniswapV2Factory(address(0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f));
    IUniswapV3Factory constant v3Factory = IUniswapV3Factory(address(0x1F98431c8aD98523631AE4a59f267346ea31F984));

    /**
     * true on Ethereum mainnet - 0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852
     * false on Ethereum mainnet - 0xdAC17F958D2ee523a2206206994597C13D831ec7
     */
    function isUniswapV2Pair(address target) external view returns (bool) {
        if (target.code.length == 0) {
            return false;
        }

        IUniswapV2Pair pairContract = IUniswapV2Pair(target);

        address token0;
        address token1;

        try pairContract.token0() returns (address _token0) {
            token0 = _token0;
        } catch (bytes memory) {
            return false;
        }

        try pairContract.token1() returns (address _token1) {
            token1 = _token1;
        } catch (bytes memory) {
            return false;
        }

        return target == v2Factory.getPair(token0, token1);
    }

    /**
     * true on Ethereum mainnet - 0x4e68Ccd3E89f51C3074ca5072bbAC773960dFa36
     * false on Ethereum mainnet - 0xdAC17F958D2ee523a2206206994597C13D831ec7
     */
    function isUniswapV3Pool(address target) external view returns (bool) {
        if (target.code.length == 0) {
            return false;
        }

        IUniswapV3Pool poolContract = IUniswapV3Pool(target);

        address token0;
        address token1;
        uint24 fee;

        try poolContract.token0() returns (address _token0) {
            token0 = _token0;
        } catch (bytes memory) {
            return false;
        }

        try poolContract.token1() returns (address _token1) {
            token1 = _token1;
        } catch (bytes memory) {
            return false;
        }

        try poolContract.fee() returns (uint24 _fee) {
            fee = _fee;
        } catch (bytes memory) {
            return false;
        }

        return target == v3Factory.getPool(token0, token1, fee);
    }
}

我还添加了一个条件检查目标地址是否是合约:

if (target.code.length == 0)
。如果是最终用户地址,则执行提前返回。

请注意,此代码段仅适用于部署 Uniswap 的网络(例如,主网的本地分支或某些测试网)。在其他网络(例如 Remix VM 模拟器)上,Uniswap 合约无法访问,这会导致调用恢复。


2
投票

在 Uniswap V3 中

 import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol";

 address poolAddress = IUniswapV3Factory(_factory).getPool(
        _token0,
        _token1,
        _fee
    );

您可以从这里获取_factory地址https://docs.uniswap.org/protocol/reference/deployments

getPool
是一个映射。

mapping(address => mapping(address => mapping(uint24 => address))) public override getPool;

当您调用

IUniswapV3Factory(_factory).getPool
时,如果密钥不存在,它将返回默认地址类型,即
address(0)
。所以你应该添加一个
require
条件

require(poolAddress!=address(0))

如果此条件通过,则意味着您从映射中获得了有效的池地址。

© www.soinside.com 2019 - 2024. All rights reserved.