Solidity

未能在 pancakeswap 中添加流動性

  • May 1, 2021

我正在嘗試使用作為 PANCAKESWAP 複製的 solidity 和 truffle 腳本在 binance 測試網上進行一些交易。我能夠成功編譯並執行一次腳本。當我嘗試在路由器和工廠的不同地址上再次執行此操作時,它給了我以下錯誤:

StatusError: Transaction: 0xc94424b8c6037e75e0eaf5f21982e2f73f88e71e18e0e5e783c642d6210e686f exited with an error (status 0). 
   at module.exports (D:\Blockchain\pancake\createpool\scripts\deploypool.js:18:18)
   at runMicrotasks (<anonymous>)
   at processTicksAndRejections (internal/process/task_queues.js:97:5) {
 tx: '0xc94424b8c6037e75e0eaf5f21982e2f73f88e71e18e0e5e783c642d6210e686f',
 receipt: {
   blockHash: '0xc4bea040096811e809c18216d85fc82813b60db9545d4e1bf6ab7c4dd344fe87',
   blockNumber: 8023495,
   contractAddress: null,
   cumulativeGasUsed: 699140,
   from: '0xe95745a8f4e3cdb1cf5bffd4a94f0b249e99f489',
   gasUsed: 29046,
   logs: [],
   logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
   status: false,
   to: '0x7632ae832440032fb4ca93e56873a92a01b06e13',
   transactionHash: '0xc94424b8c6037e75e0eaf5f21982e2f73f88e71e18e0e5e783c642d6210e686f',
   transactionIndex: 2,
   rawLogs: []
 },
 reason: undefined,
 hijackedStack: 'StatusError: Transaction: 0xc94424b8c6037e75e0eaf5f21982e2f73f88e71e18e0e5e783c642d6210e686f exited with an error (status 0). \n' +
   '     Please check that the transaction:\n' +
   '     - satisfies all conditions set by Solidity `require` statements.\n' +
   '     - does not trigger a Solidity `revert` statement.\n' +
   '\n' +
   '    at Object.receipt (C:\\Users\\DELL\\AppData\\Roaming\\npm\\node_modules\\truffle\\build\\webpack:\\packages\\contract\\lib\\handlers.js:124:1)\n' +
   '    at runMicrotasks (<anonymous>)\n' +
   '    at processTicksAndRejections (internal/process/task_queues.js:97:5)\n' +
   '    at Function.start (C:\\Users\\DELL\\AppData\\Roaming\\npm\\node_modules\\truffle\\build\\webpack:\\packages\\contract\\lib\\override.js:49:1)'

的 truffle-config.js

//SPDX-License-Identifier: MIT 
require('dotenv').config();
var HDWalletProvider = require("truffle-hdwallet-provider");

const infuraKey = process.env.infuraKey;
const mnemonic = process.env.mnemonic;

module.exports = {

 networks: {
   // Useful for testing. The `development` name is special - truffle uses it by default
   // if it's defined here and no other network is specified at the command line.
   // You should run a client (like ganache-cli, geth or parity) in a separate terminal
   // tab if you use this network and you must also set the `host`, `port` and `network_id`
   // options below to some value.
   //
   development: {
     host: "127.0.0.1",     // Localhost (default: none)
     port: 8545,            // Standard Ethereum port (default: none)
     network_id: "*",       // Any network (default: none)
   },
   rinkeby: {
     provider: function () {
       return new HDWalletProvider(mnemonic, "https://rinkeby.infura.io/v3/" + infuraKey);
     },

     network_id: 4,
     gas: 4500000,
     gasPrice: 10000000000,
   },

   bscTestnet: {
     provider: () => new HDWalletProvider(
       mnemonic,
       'https://data-seed-prebsc-1-s1.binance.org:8545'
     ),
     from: '0xe95745a8F4E3cDb1cF5bfFD4A94F0B249e99f489',
     network_id: 97,
     gas: 4500000,
     gasPrice: 10000000000,
     skipDryRun: true
   },
   mainnet: {
     provider: () => new HDWalletProvider(
       mnemonic,
       'https://bsc-dataseed.binance.org/'
     ),
     network_id: 56,
     gas: 4500000,
     gasPrice: 10000000000,
     skipDryRun: true
   }

 },

 mocha: {
   // timeout: 100000
 },

 // Configure your compilers
 compilers: {
   solc: {
     version: "0.8.0",    // Fetch exact version from solc-bin (default: truffle's version)
     // docker: true,        // Use "0.5.1" you've installed locally with docker (default: false)
     // settings: {          // See the solidity docs for advice about optimization and evmVersion
     //  optimizer: {
     //    enabled: false,
     //    runs: 200
     //  },
     //  evmVersion: "byzantium"
     // }
   },
 },
};

當我嘗試使用 truffle 命令而不是腳本來做同樣的事情時,它給了我同樣的錯誤。松露命令是:

pool.addLiquidity("0x84D2A9d0D51fd578c76908603bfdd91417F54915","0x22E692b514690757Bc26DE1C01d4Fc7207d30f90",4000,4000,7000,7000,"0xe95745a8F4E3cDb1cF5bfFD4A94F0B249e99f489",Math.floor(Date.now() / 1000) + 60 * 10).then(function(r){console.log(r);});

我的流動性函式如下:我什至嘗試刪除斷言語句並用 if 替換它,但面臨同樣的錯誤。

// **** ADD LIQUIDITY ****
   function _addLiquidity(
       address tokenA,
       address tokenB,
       uint amountADesired,
       uint amountBDesired,
       uint amountAMin,
       uint amountBMin
   ) private returns (uint amountA, uint amountB) {
       // create the pair if it doesn't exist yet
       if (INiftFactory(factory).getPair(tokenA, tokenB) == address(0)) {
           INiftFactory(factory).createPair(tokenA, tokenB);
       }
       (uint reserveA, uint reserveB) = NiftLibrary.getReserves(factory, tokenA, tokenB);
       if (reserveA == 0 && reserveB == 0) {
           (amountA, amountB) = (amountADesired, amountBDesired);
       } else {
           uint amountBOptimal = NiftLibrary.quote(amountADesired, reserveA, reserveB);
           if (amountBOptimal <= amountBDesired) {
               require(amountBOptimal >= amountBMin, 'NiftRouter: INSUFFICIENT_B_AMOUNT');
               (amountA, amountB) = (amountADesired, amountBOptimal);
           } else {
               uint amountAOptimal = NiftLibrary.quote(amountBDesired, reserveB, reserveA);
               assert(amountAOptimal <= amountADesired);
               require(amountAOptimal >= amountAMin, 'NiftRouter: INSUFFICIENT_A_AMOUNT');
               (amountA, amountB) = (amountAOptimal, amountBDesired);
           }
       }
   }
   function addLiquidity(
       address tokenA,
       address tokenB,
       uint amountADesired,
       uint amountBDesired,
       uint amountAMin,
       uint amountBMin,
       address to,
       uint deadline
   ) external override ensure(deadline) returns (uint amountA, uint amountB, uint liquidity) {
       (amountA, amountB) = _addLiquidity(tokenA, tokenB, amountADesired, amountBDesired, amountAMin, amountBMin);
       address pair = NiftLibrary.pairFor(factory, tokenA, tokenB);
       TransferHelper.safeTransferFrom(tokenA, msg.sender, pair, amountA);
       TransferHelper.safeTransferFrom(tokenB, msg.sender, pair, amountB);
       liquidity = INiftPair(pair).mint(to);
   }
   function addLiquidityETH(
       address token,
       uint amountTokenDesired,
       uint amountTokenMin,
       uint amountETHMin,
       address to,
       uint deadline
   ) external override payable ensure(deadline) returns (uint amountToken, uint amountETH, uint liquidity) {
       (amountToken, amountETH) = _addLiquidity(
           token,
           WETH,
           amountTokenDesired,
           msg.value,
           amountTokenMin,
           amountETHMin
       );
       address pair = NiftLibrary.pairFor(factory, token, WETH);
       TransferHelper.safeTransferFrom(token, msg.sender, pair, amountToken);
       IWETH(WETH).deposit{value: amountETH}();
       assert(IWETH(WETH).transfer(pair, amountETH));
       liquidity = INiftPair(pair).mint(to);
       if (msg.value > amountETH) TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH); // refund dust eth, if any
   }

我的deploypool.js文件:

const Factory = artifacts.require('Factory.sol');
const Router = artifacts.require('Router.sol');
const Pair = artifacts.require('Pair.sol');
const Token1 = artifacts.require('token1.sol');
const Token2 = artifacts.require('token2.sol');

module.exports = async done => {
 try {
   //const [admin, _] = await web3.eth.getAccounts();
   const factory = await Factory.at('0x81338c4e7a7f30297aF1dd1dBF02Fc1299b0EA12');
   const router = await Router.at('0x73D58041eDdD468e016Cfbc13f3BDc4248cCD65D');
   const token1 = await Token1.new();
   const token2 = await Token2.new();
   const pairAddress = await factory.createPair.call(token1.address, token2.address);
   const tx = await factory.createPair(token1.address, token2.address);
   await token1.approve(router.address, 10000);
   await token2.approve(router.address, 10000);
   await router.addLiquidity(
     token1.address,
     token2.address,
     9000,
     9000,
     10000,
     10000,
     'mymetamaskaddress',
     Math.floor(Date.now() / 1000) + 60 * 10
   );
   const pair = await Pair.at(pairAddress);
   const balance = await pair.balanceOf("0xe95745a8F4E3cDb1cF5bfFD4A94F0B249e99f489");
   console.log(`balance LP: ${balance.toString()}`);
 } catch (e) {
   console.log(e);
 }
 done();
};

已驗證路由器地址 https://testnet.bscscan.com/address/0x73D58041eDdD468e016Cfbc13f3BDc4248cCD65D#code

驗證工廠地址 https://testnet.bscscan.com/address/0x81338c4e7a7f30297af1dd1dbf02fc1299b0ea12#code

上一個使用不同的工廠和路由器地址成功交易 https://testnet.bscscan.com/tx/0x9ca6e07ffcc0ab50c2f181783a14a17e850ad16dbd15c1590e4f2321cc9d44b5

好吧,在這個問題上花了幾天時間後,我才知道我只是在通過 testnet 進行多次部署之前更改了一次 init_hash。init_hash 每次都會更改,因此您必須每次將 init_hash 從 pancake pair 文件複製到 pancake 庫中。這樣做之後,我能夠使用我自己的路由器和工廠地址通過 bsc 測試網成功添加流動性。

您的部署腳本在以下位置失敗:

await router.addLiquidity(...)

在呼叫 addLiquidity() 時,當它到達:

(uint reserveA, uint reserveB) = PancakeLibrary.getReserves(factory, tokenA, tokenB);

反過來又失敗了:

(uint reserve0, uint reserve1,) = IPancakePair(pairFor(factory, tokenA, tokenB)).getReserves();

這裡 tokenA 和 tokenB 的 pairFor 的輸出是0x78715162d94936c07d811a03e3e0411a4270bf6c你的令牌對部署在0xb8c774F637C2B40d2a834Bb6c1EecD7c96166Cf9. _addLiquidity如果它不存在(通過呼叫檢查getPair() == 0x000...0),路由器的功能會創建對,如果對存在則呼叫getReserves()它反過來呼叫pairFor()。如果您對 PancakePair 進行了更改,則 init_hash 可能會更改,並且pairFor()find pair 計算的地址可能會有所不同。您可以嘗試刪除對工廠的 createPair 呼叫並在沒有它的情況下進行檢查。

引用自:https://ethereum.stackexchange.com/questions/97328