Contract-Development

無法在恢復的測試網事務上部署需要 uniswap 路由器的 ERC20 代幣?

  • April 2, 2022

所以它是一個對每筆交易都有稅費的代幣。但是在部署時它失敗了你知道為什麼嗎?

  • 完整原始碼:https://pastebin.com/KyJMBie1
  • 交易編號:https://ropsten.etherscan.io/tx/0x70c2e6d9e5001ea794aec54cc00b0bd7647698eed1ef693e180db3904bc55ab4

錯誤指的是儲氣不足。為了繞過這個錯誤,可以使用庫的導入。

試試這個:

// SPDX-License-Identifier: Unlicensed 
pragma solidity ^0.8.4;

import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol";
import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router01.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";


library Address {

   function isContract(address account) internal view returns (bool) {
       // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
       // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
       // for accounts without code, i.e. `keccak256('')`
       bytes32 codehash;
       bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
       // solhint-disable-next-line no-inline-assembly
       assembly { codehash := extcodehash(account) }
       return (codehash != accountHash && codehash != 0x0);
   }

   function sendValue(address payable recipient, uint256 amount) internal {
       require(address(this).balance >= amount, "Address: insufficient balance");

       // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
       (bool success, ) = recipient.call{ value: amount }("");
       require(success, "Address: unable to send value, recipient may have reverted");
   }


   function functionCall(address target, bytes memory data) internal returns (bytes memory) {
     return functionCall(target, data, "Address: low-level call failed");
   }

   function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
       return _functionCallWithValue(target, data, 0, errorMessage);
   }

   function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
       return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
   }

   function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
       require(address(this).balance >= value, "Address: insufficient balance for call");
       return _functionCallWithValue(target, data, value, errorMessage);
   }

   function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
       require(isContract(target), "Address: call to non-contract");

       (bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
       if (success) {
           return returndata;
       } else {

           if (returndata.length > 0) {
               assembly {
                   let returndata_size := mload(returndata)
                   revert(add(32, returndata), returndata_size)
               }
           } else {
               revert(errorMessage);
           }
       }
   }
}


contract CronosNaut is Context, IERC20, Ownable {
   using SafeMath for uint256;
   using Address for address;

   address payable public marketingAddress = payable(0x3bfC545BdE045e3eef6Ce2e75928946D7C5591f8); // Marketing Address
   address public immutable deadAddress = 0x000000000000000000000000000000000000dEaD;
   mapping (address => uint256) private _rOwned;
   mapping (address => uint256) private _tOwned;
   mapping (address => mapping (address => uint256)) private _allowances;

   mapping (address => bool) private _isExcludedFromFee;

   mapping (address => bool) private _isExcluded;
   address[] private _excluded;

   uint256 private constant MAX = ~uint256(0);
   uint256 private _tTotal = 1000000000 * 10**6 * 10**9;
   uint256 private _rTotal = (MAX - (MAX % _tTotal));
   uint256 private _tFeeTotal;

   string private _name = "CronosNaut";
   string private _symbol = "CRON";
   uint8 private _decimals = 9;


   uint256 public _taxFee = 2;
   uint256 private _previousTaxFee = _taxFee;

   uint256 public _liquidityFee = 2;
   uint256 private _previousLiquidityFee = _liquidityFee;

   uint256 public marketingDivisor = 2;

   uint256 public _maxTxAmount = 3000000 * 10**6 * 10**9;
   uint256 private minimumTokensBeforeSwap = 200000 * 10**6 * 10**9; 
   uint256 private buyBackUpperLimit = 1 * 10**18;

   IUniswapV2Router02 public immutable uniswapV2Router;
   address public immutable uniswapV2Pair;

   bool inSwapAndLiquify;
   bool public swapAndLiquifyEnabled = false;
   bool public buyBackEnabled = true;


   event RewardLiquidityProviders(uint256 tokenAmount);
   event BuyBackEnabledUpdated(bool enabled);
   event SwapAndLiquifyEnabledUpdated(bool enabled);
   event SwapAndLiquify(
       uint256 tokensSwapped,
       uint256 ethReceived,
       uint256 tokensIntoLiqudity
   );

   event SwapETHForTokens(
       uint256 amountIn,
       address[] path
   );

   event SwapTokensForETH(
       uint256 amountIn,
       address[] path
   );

   modifier lockTheSwap {
       inSwapAndLiquify = true;
       _;
       inSwapAndLiquify = false;
   }

   constructor () {
       _rOwned[_msgSender()] = _rTotal;
       IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
       uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
           .createPair(address(this), _uniswapV2Router.WETH());

       uniswapV2Router = _uniswapV2Router;
       _isExcludedFromFee[owner()] = true;
       _isExcludedFromFee[address(this)] = true;

       emit Transfer(address(0), _msgSender(), _tTotal);
   }

   function name() public view returns (string memory) {
       return _name;
   }

   function symbol() public view returns (string memory) {
       return _symbol;
   }

   function decimals() public view returns (uint8) {
       return _decimals;
   }

   function totalSupply() public view override returns (uint256) {
       return _tTotal;
   }

   function balanceOf(address account) public view override returns (uint256) {
       if (_isExcluded[account]) return _tOwned[account];
       return tokenFromReflection(_rOwned[account]);
   }

   function transfer(address recipient, uint256 amount) public override returns (bool) {
       _transfer(_msgSender(), recipient, amount);
       return true;
   }

   function allowance(address owner, address spender) public view override returns (uint256) {
       return _allowances[owner][spender];
   }

   function approve(address spender, uint256 amount) public override returns (bool) {
       _approve(_msgSender(), spender, amount);
       return true;
   }

   function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
       _transfer(sender, recipient, amount);
       _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
       return true;
   }

   function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
       _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
       return true;
   }

   function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
       _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
       return true;
   }

   function isExcludedFromReward(address account) public view returns (bool) {
       return _isExcluded[account];
   }

   function totalFees() public view returns (uint256) {
       return _tFeeTotal;
   }

   function minimumTokensBeforeSwapAmount() public view returns (uint256) {
       return minimumTokensBeforeSwap;
   }

   function buyBackUpperLimitAmount() public view returns (uint256) {
       return buyBackUpperLimit;
   }

   function deliver(uint256 tAmount) public {
       address sender = _msgSender();
       require(!_isExcluded[sender], "Excluded addresses cannot call this function");
       (uint256 rAmount,,,,,) = _getValues(tAmount);
       _rOwned[sender] = _rOwned[sender].sub(rAmount);
       _rTotal = _rTotal.sub(rAmount);
       _tFeeTotal = _tFeeTotal.add(tAmount);
   }


   function reflectionFromToken(uint256 tAmount, bool deductTransferFee) public view returns(uint256) {
       require(tAmount <= _tTotal, "Amount must be less than supply");
       if (!deductTransferFee) {
           (uint256 rAmount,,,,,) = _getValues(tAmount);
           return rAmount;
       } else {
           (,uint256 rTransferAmount,,,,) = _getValues(tAmount);
           return rTransferAmount;
       }
   }

   function tokenFromReflection(uint256 rAmount) public view returns(uint256) {
       require(rAmount <= _rTotal, "Amount must be less than total reflections");
       uint256 currentRate =  _getRate();
       return rAmount.div(currentRate);
   }

   function excludeFromReward(address account) public onlyOwner() {

       require(!_isExcluded[account], "Account is already excluded");
       if(_rOwned[account] > 0) {
           _tOwned[account] = tokenFromReflection(_rOwned[account]);
       }
       _isExcluded[account] = true;
       _excluded.push(account);
   }

   function includeInReward(address account) external onlyOwner() {
       require(_isExcluded[account], "Account is already excluded");
       for (uint256 i = 0; i < _excluded.length; i++) {
           if (_excluded[i] == account) {
               _excluded[i] = _excluded[_excluded.length - 1];
               _tOwned[account] = 0;
               _isExcluded[account] = false;
               _excluded.pop();
               break;
           }
       }
   }

   function _approve(address owner, address spender, uint256 amount) private {
       require(owner != address(0), "ERC20: approve from the zero address");
       require(spender != address(0), "ERC20: approve to the zero address");

       _allowances[owner][spender] = amount;
       emit Approval(owner, spender, amount);
   }

   function _transfer(
       address from,
       address to,
       uint256 amount
   ) private {
       require(from != address(0), "ERC20: transfer from the zero address");
       require(to != address(0), "ERC20: transfer to the zero address");
       require(amount > 0, "Transfer amount must be greater than zero");
       if(from != owner() && to != owner()) {
           require(amount <= _maxTxAmount, "Transfer amount exceeds the maxTxAmount.");
       }

       uint256 contractTokenBalance = balanceOf(address(this));
       bool overMinimumTokenBalance = contractTokenBalance >= minimumTokensBeforeSwap;

       if (!inSwapAndLiquify && swapAndLiquifyEnabled && to == uniswapV2Pair) {
           if (overMinimumTokenBalance) {
               contractTokenBalance = minimumTokensBeforeSwap;
               swapTokens(contractTokenBalance);    
           }
           uint256 balance = address(this).balance;
           if (buyBackEnabled && balance > uint256(1 * 10**18)) {

               if (balance > buyBackUpperLimit)
                   balance = buyBackUpperLimit;

               buyBackTokens(balance.div(100));
           }
       }

       bool takeFee = true;

       //if any account belongs to _isExcludedFromFee account then remove the fee
       if(_isExcludedFromFee[from] || _isExcludedFromFee[to]){
           takeFee = false;
       }

       _tokenTransfer(from,to,amount,takeFee);
   }

   function swapTokens(uint256 contractTokenBalance) private lockTheSwap {

       uint256 initialBalance = address(this).balance;
       swapTokensForEth(contractTokenBalance);
       uint256 transferredBalance = address(this).balance.sub(initialBalance);

       //Send to Marketing address
       transferToAddressETH(marketingAddress, transferredBalance.div(_liquidityFee).mul(marketingDivisor));

   }


   function buyBackTokens(uint256 amount) private lockTheSwap {
       if (amount > 0) {
           swapETHForTokens(amount);
       }
   }

   function swapTokensForEth(uint256 tokenAmount) private {
       // generate the uniswap pair path of token -> weth
       address[] memory path = new address[](2);
       path[0] = address(this);
       path[1] = uniswapV2Router.WETH();

       _approve(address(this), address(uniswapV2Router), tokenAmount);

       // make the swap
       uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
           tokenAmount,
           0, // accept any amount of ETH
           path,
           address(this), // The contract
           block.timestamp
       );

       emit SwapTokensForETH(tokenAmount, path);
   }

   function swapETHForTokens(uint256 amount) private {
       // generate the uniswap pair path of token -> weth
       address[] memory path = new address[](2);
       path[0] = uniswapV2Router.WETH();
       path[1] = address(this);

     // make the swap
       uniswapV2Router.swapExactETHForTokensSupportingFeeOnTransferTokens{value: amount}(
           0, // accept any amount of Tokens
           path,
           deadAddress, // Burn address
           block.timestamp.add(300)
       );

       emit SwapETHForTokens(amount, path);
   }

   function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
       // approve token transfer to cover all possible scenarios
       _approve(address(this), address(uniswapV2Router), tokenAmount);

       // add the liquidity
       uniswapV2Router.addLiquidityETH{value: ethAmount}(
           address(this),
           tokenAmount,
           0, // slippage is unavoidable
           0, // slippage is unavoidable
           owner(),
           block.timestamp
       );
   }

   function _tokenTransfer(address sender, address recipient, uint256 amount,bool takeFee) private {
       if(!takeFee)
           removeAllFee();

       if (_isExcluded[sender] && !_isExcluded[recipient]) {
           _transferFromExcluded(sender, recipient, amount);
       } else if (!_isExcluded[sender] && _isExcluded[recipient]) {
           _transferToExcluded(sender, recipient, amount);
       } else if (_isExcluded[sender] && _isExcluded[recipient]) {
           _transferBothExcluded(sender, recipient, amount);
       } else {
           _transferStandard(sender, recipient, amount);
       }

       if(!takeFee)
           restoreAllFee();
   }

   function _transferStandard(address sender, address recipient, uint256 tAmount) private {
       (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
       _rOwned[sender] = _rOwned[sender].sub(rAmount);
       _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);
       _takeLiquidity(tLiquidity);
       _reflectFee(rFee, tFee);
       emit Transfer(sender, recipient, tTransferAmount);
   }

   function _transferToExcluded(address sender, address recipient, uint256 tAmount) private {
       (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
       _rOwned[sender] = _rOwned[sender].sub(rAmount);
       _tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
       _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);           
       _takeLiquidity(tLiquidity);
       _reflectFee(rFee, tFee);
       emit Transfer(sender, recipient, tTransferAmount);
   }

   function _transferFromExcluded(address sender, address recipient, uint256 tAmount) private {
       (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
       _tOwned[sender] = _tOwned[sender].sub(tAmount);
       _rOwned[sender] = _rOwned[sender].sub(rAmount);
       _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);   
       _takeLiquidity(tLiquidity);
       _reflectFee(rFee, tFee);
       emit Transfer(sender, recipient, tTransferAmount);
   }

   function _transferBothExcluded(address sender, address recipient, uint256 tAmount) private {
       (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getValues(tAmount);
       _tOwned[sender] = _tOwned[sender].sub(tAmount);
       _rOwned[sender] = _rOwned[sender].sub(rAmount);
       _tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
       _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);        
       _takeLiquidity(tLiquidity);
       _reflectFee(rFee, tFee);
       emit Transfer(sender, recipient, tTransferAmount);
   }

   function _reflectFee(uint256 rFee, uint256 tFee) private {
       _rTotal = _rTotal.sub(rFee);
       _tFeeTotal = _tFeeTotal.add(tFee);
   }

   function _getValues(uint256 tAmount) private view returns (uint256, uint256, uint256, uint256, uint256, uint256) {
       (uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity) = _getTValues(tAmount);
       (uint256 rAmount, uint256 rTransferAmount, uint256 rFee) = _getRValues(tAmount, tFee, tLiquidity, _getRate());
       return (rAmount, rTransferAmount, rFee, tTransferAmount, tFee, tLiquidity);
   }

   function _getTValues(uint256 tAmount) private view returns (uint256, uint256, uint256) {
       uint256 tFee = calculateTaxFee(tAmount);
       uint256 tLiquidity = calculateLiquidityFee(tAmount);
       uint256 tTransferAmount = tAmount.sub(tFee).sub(tLiquidity);
       return (tTransferAmount, tFee, tLiquidity);
   }

   function _getRValues(uint256 tAmount, uint256 tFee, uint256 tLiquidity, uint256 currentRate) private pure returns (uint256, uint256, uint256) {
       uint256 rAmount = tAmount.mul(currentRate);
       uint256 rFee = tFee.mul(currentRate);
       uint256 rLiquidity = tLiquidity.mul(currentRate);
       uint256 rTransferAmount = rAmount.sub(rFee).sub(rLiquidity);
       return (rAmount, rTransferAmount, rFee);
   }

   function _getRate() private view returns(uint256) {
       (uint256 rSupply, uint256 tSupply) = _getCurrentSupply();
       return rSupply.div(tSupply);
   }

   function _getCurrentSupply() private view returns(uint256, uint256) {
       uint256 rSupply = _rTotal;
       uint256 tSupply = _tTotal;      
       for (uint256 i = 0; i < _excluded.length; i++) {
           if (_rOwned[_excluded[i]] > rSupply || _tOwned[_excluded[i]] > tSupply) return (_rTotal, _tTotal);
           rSupply = rSupply.sub(_rOwned[_excluded[i]]);
           tSupply = tSupply.sub(_tOwned[_excluded[i]]);
       }
       if (rSupply < _rTotal.div(_tTotal)) return (_rTotal, _tTotal);
       return (rSupply, tSupply);
   }

   function _takeLiquidity(uint256 tLiquidity) private {
       uint256 currentRate =  _getRate();
       uint256 rLiquidity = tLiquidity.mul(currentRate);
       _rOwned[address(this)] = _rOwned[address(this)].add(rLiquidity);
       if(_isExcluded[address(this)])
           _tOwned[address(this)] = _tOwned[address(this)].add(tLiquidity);
   }

   function calculateTaxFee(uint256 _amount) private view returns (uint256) {
       return _amount.mul(_taxFee).div(
           10**2
       );
   }

   function calculateLiquidityFee(uint256 _amount) private view returns (uint256) {
       return _amount.mul(_liquidityFee).div(
           10**2
       );
   }

   function removeAllFee() private {
       if(_taxFee == 0 && _liquidityFee == 0) return;

       _previousTaxFee = _taxFee;
       _previousLiquidityFee = _liquidityFee;

       _taxFee = 0;
       _liquidityFee = 0;
   }

   function restoreAllFee() private {
       _taxFee = _previousTaxFee;
       _liquidityFee = _previousLiquidityFee;
   }

   function isExcludedFromFee(address account) public view returns(bool) {
       return _isExcludedFromFee[account];
   }

   function excludeFromFee(address account) public onlyOwner {
       _isExcludedFromFee[account] = true;
   }

   function includeInFee(address account) public onlyOwner {
       _isExcludedFromFee[account] = false;
   }

   function setTaxFeePercent(uint256 taxFee) external onlyOwner() {
       _taxFee = taxFee;
   }

   function setLiquidityFeePercent(uint256 liquidityFee) external onlyOwner() {
       _liquidityFee = liquidityFee;
   }

   function setMaxTxAmount(uint256 maxTxAmount) external onlyOwner() {
       _maxTxAmount = maxTxAmount;
   }

   function setMarketingDivisor(uint256 divisor) external onlyOwner() {
       marketingDivisor = divisor;
   }

   function setNumTokensSellToAddToLiquidity(uint256 _minimumTokensBeforeSwap) external onlyOwner() {
       minimumTokensBeforeSwap = _minimumTokensBeforeSwap;
   }

    function setBuybackUpperLimit(uint256 buyBackLimit) external onlyOwner() {
       buyBackUpperLimit = buyBackLimit * 10**18;
   }

   function setMarketingAddress(address _marketingAddress) external onlyOwner() {
       marketingAddress = payable(_marketingAddress);
   }

   function setSwapAndLiquifyEnabled(bool _enabled) public onlyOwner {
       swapAndLiquifyEnabled = _enabled;
       emit SwapAndLiquifyEnabledUpdated(_enabled);
   }

   function setBuyBackEnabled(bool _enabled) public onlyOwner {
       buyBackEnabled = _enabled;
       emit BuyBackEnabledUpdated(_enabled);
   }

   function prepareForPreSale() external onlyOwner {
       setSwapAndLiquifyEnabled(false);
       _taxFee = 0;
       _liquidityFee = 0;
       _maxTxAmount = 1000000000 * 10**6 * 10**9;
   }

   function afterPreSale() external onlyOwner {
       setSwapAndLiquifyEnabled(true);
       _taxFee = 2;
       _liquidityFee = 8;
       _maxTxAmount = 3000000 * 10**6 * 10**9;
   }

   function transferToAddressETH(address payable recipient, uint256 amount) private {
       recipient.transfer(amount);
   }

    //to recieve ETH from uniswapV2Router when swaping
   receive() external payable {}
}

我只導入帶import關鍵字的庫(智能合約程式碼與 pastebin 相同)。

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