【问题标题】:How do I determine whether a recipient is a liquidity pool?如何确定收款人是否为流动资金池?
【发布时间】:2022-11-07 04:30:29
【问题描述】:

我正在创建一个代币,当它在流动性池中出售时,会收取费用并烧掉一定数量。

鉴于我有一个收件人地址,我将如何检查它是否是流动资金池?

我想我可以使用这个:https://docs.uniswap.org/protocol/V2/reference/smart-contracts/pair-erc-20 但是我不确定哪个函数可以工作或者是否有其他方法。

编辑:

【问题讨论】:

    标签: solidity uniswap


    【解决方案1】:

    您可以针对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);
        }
    }
    

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

    【讨论】:

    • @Ayudh 此示例仅适用于 Uniswap(V2 和 V3)池。其他 DEX 通常实现 Uniswap 接口,但它们的工厂合约部署在不同的地址上。因此,将此示例扩展到例如Sushiswap(使用 Uniswap V2 接口),您需要创建一个新函数,它实际上复制现有的 isUniswapV2Pair() - 除了它查询 Sushiswap factory 地址 (0xC0AE...) 而不是 Uniswap 工厂 (@987654329 @)。
    • @Ayudh 一个“对合约”是他们 V2 对 V3 中池的措辞——一种持有两个代币流动性并允许用户交换它们的合约......在上下文中,一个“对(ERC-20)”是Uniswap V2 的代币,代表这种“配对合约”中的流动性。例如,您为 Pair 合约 A/B 提供流动性,并且作为交换,您铸造了这个 ERC-20 代币,代表您在这个总流动性中的 % 股份。当您决定移除流动性时,他们会销毁这些“Pair ERC20”代币并将原始 A 和 B 代币寄回给您。
    • 代币的这种附加逻辑代表您的流动性权益,也允许交易流动性代币。就像您可以在常规财务中将某人欠您的债务出售给第三方一样。
    • @Ayudh 很可能您已经在 Uniswap 不可用的网络上部署了合约(例如在 Remix VM 模拟器中)。请参阅答案中的最后一段。
    • @Ayudh 因此,我没有重构整个事情,而是添加了一个条件来检查目标地址是否是合约:if (target.code.length == 0)。如果它是最终用户地址,它会执行提前返回。请参阅更新的代码。
    【解决方案2】:

    在 Uniswap V3 中

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

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

    getPool 是一个映射。

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

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

    require(poolAddress!=address(0))
    

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

    【讨论】:

      猜你喜欢
      • 2021-12-01
      • 1970-01-01
      • 2022-09-28
      • 2013-06-25
      • 2023-02-03
      • 2014-07-15
      • 2017-03-24
      • 2022-01-05
      • 2018-12-20
      相关资源
      最近更新 更多