【问题标题】:1% on every transaction and purchase - Smart Contract每笔交易和购买 1% - 智能合约
【发布时间】:2021-10-29 04:47:49
【问题描述】:

我对 Solidity 还是很陌生。我尝试整理一份智能合约。 第一个是创建代币的普通合约:

https://github.com/jklepatch/eattheblocks/blob/master/screencast/308-create-bep20-token-bsc/Token.sol

在那里,我想执行两个合同。 我在教程中找到了以下代码: 1:

contract ReceiveETHERandSendPercentageToAnotherAddress{

    // if funds are received in this contract then 
    // Pay 1% to the target address
    address payable target = ENTERANADDRESSHERE;

    // Fallback function for incoming ether 
    function () payable external{
       
        //Send 1% to the target address configured above
        target.transfer(msg.value/100);

        //continue processing
    }
}

2:

contract TransfertTokenAndPercentageToTargetAddress{

    // pay 1% of all transactions to target address
    address payable target = ENTERANADDRESSHERE;

    // state variables for your token to track balances and to test
    mapping (address => uint) public balanceOf;
    uint public totalSupply;

    // create a token and assign all the tokens to the creator to test
    constructor(uint _totalSupply) public {
        totalSupply = _totalSupply;
        balanceOf[msg.sender] = totalSupply;
    }

    // the token transfer function with the addition of a 1% share that
    // goes to the target address specified above
    function transfer(address _to, uint amount) public {

        // calculate the share of tokens for your target address
        uint shareForX = amount/100;

        // save the previous balance of the sender for later assertion
        // verify that all works as intended
        uint senderBalance = balanceOf[msg.sender];
        
        // check the sender actually has enough tokens to transfer with function 
        // modifier
        require(senderBalance >= amount, 'Not enough balance');
        
        // reduce senders balance first to prevent the sender from sending more 
        // than he owns by submitting multiple transactions
        balanceOf[msg.sender] -= amount;
        
        // store the previous balance of the receiver for later assertion
        // verify that all works as intended
        uint receiverBalance = balanceOf[_to];

        // add the amount of tokens to the receiver but deduct the share for the
        // target address
        balanceOf[_to] += amount-shareForX;
        
        // add the share to the target address
        balanceOf[target] += shareForX;

        // check that everything works as intended, specifically checking that
        // the sum of tokens in all accounts is the same before and after
        // the transaction. 
        assert(balanceOf[msg.sender] + balanceOf[_to] + shareForX ==
            senderBalance + receiverBalance);
    }
}

我想在我的智能合约中包含这两种变体,并按如下方式进行:

pragma solidity ^0.8.2;

contract Token {
    mapping(address => uint) public balances;
    mapping(address => mapping(address => uint)) public allowance;
    uint public constant totalSupply = 21000000;
    string public name = "TESTING";
    string public symbol = "TES";
    uint public decimals = 18;
    address payable target = XXX;

    event Transfer(address indexed from, address indexed to, uint value);
    event Approval(address indexed owner, address indexed spender, uint value);
    
    constructor() {
        balances[msg.sender] = totalSupply;
    }
      function () payable external{
       
        target.transfer(msg.value/100);

    }
    
    function transfer(address _to, uint amount) public {

        // calculate the share of tokens for your target address
        uint shareForX = amount/100;

        // save the previous balance of the sender for later assertion
        // verify that all works as intended
        uint senderBalance = balanceOf[msg.sender];
        
        // check the sender actually has enough tokens to transfer with function 
        // modifier
        require(senderBalance >= amount, 'Not enough balance');
        
        // reduce senders balance first to prevent the sender from sending more 
        // than he owns by submitting multiple transactions
        balanceOf[msg.sender] -= amount;
        
        // store the previous balance of the receiver for later assertion
        // verify that all works as intended
        uint receiverBalance = balanceOf[_to];

        // add the amount of tokens to the receiver but deduct the share for the
        // target address
        balanceOf[_to] += amount-shareForX;
        
        // add the share to the target address
        balanceOf[target] += shareForX;

        // check that everything works as intended, specifically checking that
        // the sum of tokens in all accounts is the same before and after
        // the transaction. 
        assert(balanceOf[msg.sender] + balanceOf[_to] + shareForX ==
            senderBalance + receiverBalance);
    }
    
    function balanceOf(address owner) public returns(uint) {
        return balances[owner];
    }
    
    function transfer(address to, uint value) public returns(bool) {
        require(balanceOf(msg.sender) >= value, 'balance too low');
        balances[to] += value;
        balances[msg.sender] -= value;
       emit Transfer(msg.sender, to, value);
        return true;
    }
    
    function transferFrom(address from, address to, uint value) public returns(bool) {
        require(balanceOf(from) >= value, 'balance too low');
        require(allowance[from][msg.sender] >= value, 'allowance too low');
        balances[to] += value;
        balances[from] -= value;
        emit Transfer(from, to, value);
        return true;   
    }
    
    function approve(address spender, uint value) public returns (bool) {
        allowance[msg.sender][spender] = value;
        emit Approval(msg.sender, spender, value);
        return true;   
    }
}

但它不起作用。购买时和每次交易时,应将总金额的 1% 自动发送到钱包地址。

如果有人可以帮助我,我将非常感激!

【问题讨论】:

  • 如果现在找到了一个解决方案,可以通过以下方式实现它们:“合约令牌是 ERC20,ReceiveETHERandSendPercentageToAnotherAddress,TransfertTokenAndPercentageToTargetAddress...”现在我遇到了问题,因为它有不同版本的 Solidity。我很乐意寻求帮助。提前致谢。

标签: transactions contract remix fee


【解决方案1】:

我刚找到一份合同。复制和改编。它正是我想要的。每笔交易的 1% 将被转发到捐赠钱包。但奇怪的是,每笔交易的代币总供应量增加了 1%。我一直在疯狂地浏览代码,我真的只是一个初学者,如果你能提供帮助将非常高兴。

这是一个问题的例子: https://goerli.etherscan.io/token/tokenholderchart/0xfdb5cac9f9de78596f59959b9b743540b0c29a42

代码如下:

    contract CoinToken is Context, IBEP20, Ownable {
    using SafeMath for uint256;
    using Address for address;

    mapping (address => uint256) private _rOwned;
    mapping (address => uint256) private _tOwned;
    mapping (address => mapping (address => uint256)) private _allowances;

    mapping (address => bool) private _isExcluded;
    mapping (address => bool) private _isCharity;
    address[] private _excluded;
    
    string  private _NAME;
    string  private _SYMBOL;
    uint256   private _DECIMALS;
    address public FeeAddress;
   
    uint256 private _MAX = ~uint256(0);
    uint256 private _DECIMALFACTOR;
    uint256 private _GRANULARITY = 100;
    
    uint256 private _tTotal;
    uint256 private _rTotal;

    uint256 private _tCharityTotal;

    uint256 public _CHARITY_FEE;

    // Track original fees to bypass fees for charity account
 
    uint256 private ORIG_CHARITY_FEE;

    constructor (string memory _name, string memory _symbol, uint256 _decimals, uint256 _supply, uint256 _charityFee,address _FeeAddress,address tokenOwner) {
        _NAME = _name;
        _SYMBOL = _symbol;
        _DECIMALS = _decimals;
        _DECIMALFACTOR = 10 ** uint256(_DECIMALS);
        _tTotal =_supply * _DECIMALFACTOR;
        _rTotal = (_MAX - (_MAX % _tTotal));
        
        _CHARITY_FEE = _charityFee* 100;
        
        ORIG_CHARITY_FEE = _CHARITY_FEE;
        _isCharity[_FeeAddress] = true;
        FeeAddress = _FeeAddress;
        _owner = tokenOwner;
        _rOwned[tokenOwner] = _rTotal;
        
        emit Transfer(address(0),tokenOwner, _tTotal);
    }

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

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

    function decimals() public view returns (uint256) {
        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, "TOKEN20: 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, "TOKEN20: decreased allowance below zero"));
        return true;
    }

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


    
    function totalCharity() public view returns (uint256) {
        return _tCharityTotal;
    }

    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);
    }

    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 excludeAccount(address account) external onlyOwner() {
        require(!_isExcluded[account], "Account is already excluded");
        if(_rOwned[account] > 0) {
            _tOwned[account] = tokenFromReflection(_rOwned[account]);
        }
        _isExcluded[account] = true;
        _excluded.push(account);
    }

    function includeAccount(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 setAsCharityAccount(address account) external onlyOwner() {
        require(!_isCharity[account], "Account is already charity account");
        _isCharity[account] = true;
        FeeAddress = account;
    }


    function updateFee(uint256 _charityFee) onlyOwner() public{
     
        _CHARITY_FEE = _charityFee* 100;
    
        ORIG_CHARITY_FEE = _CHARITY_FEE;
    }
    

    

    function mint(address account, uint256 amount) onlyOwner() public {

        _tTotal = _tTotal.add(amount);
        _rOwned[account] = _rOwned[account].add(amount);
        emit Transfer(address(0), account, amount);
    }



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

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

    function _transfer(address sender, address recipient, uint256 amount) private {
        require(sender != address(0), "TOKEN20: transfer from the zero address");
        require(recipient != address(0), "TOKEN20: transfer to the zero address");
        require(amount > 0, "Transfer amount must be greater than zero");

        // Remove fees for transfers to and from charity account or to excluded account
        bool takeFee = true;
        if (_isCharity[sender] || _isCharity[recipient] || _isExcluded[recipient]) {
            takeFee = false;
        }

        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]) {
            _transferStandard(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 currentRate =  _getRate();
        (uint256 rAmount, uint256 rTransferAmount, uint256 tTransferAmount, uint256 tCharity) = _getValues(tAmount);
       
        uint256 rCharity = tCharity.mul(currentRate);     
        _standardTransferContent(sender, recipient, rAmount, rTransferAmount);
        _sendToCharity(tCharity, sender);
        _reflectFee(rCharity,tCharity);
        emit Transfer(sender, recipient, tTransferAmount);
    }
    
    function _standardTransferContent(address sender, address recipient, uint256 rAmount, uint256 rTransferAmount) private {
        _rOwned[sender] = _rOwned[sender].sub(rAmount);
        _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);
    }
    
    function _transferToExcluded(address sender, address recipient, uint256 tAmount) private {
        uint256 currentRate =  _getRate();
        (uint256 rAmount, uint256 rTransferAmount, uint256 tTransferAmount, uint256 tCharity) = _getValues(tAmount);
       
        uint256 rCharity = tCharity.mul(currentRate);
        _excludedFromTransferContent(sender, recipient, tTransferAmount, rAmount, rTransferAmount);        
        _sendToCharity(tCharity, sender);
        _reflectFee(rCharity, tCharity);
        emit Transfer(sender, recipient, tTransferAmount);
    }
    
    function _excludedFromTransferContent(address sender, address recipient, uint256 tTransferAmount, uint256 rAmount, uint256 rTransferAmount) private {
        _rOwned[sender] = _rOwned[sender].sub(rAmount);
        _tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
        _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);    
    }
    

    function _transferFromExcluded(address sender, address recipient, uint256 tAmount) private {
        uint256 currentRate =  _getRate();
        (uint256 rAmount, uint256 rTransferAmount, uint256 tTransferAmount, uint256 tCharity) = _getValues(tAmount);
       
        uint256 rCharity = tCharity.mul(currentRate);
        _excludedToTransferContent(sender, recipient, tAmount, rAmount, rTransferAmount);
        _sendToCharity(tCharity, sender);
        _reflectFee(rCharity,tCharity);
        emit Transfer(sender, recipient, tTransferAmount);
    }
    
    function _excludedToTransferContent(address sender, address recipient, uint256 tAmount, uint256 rAmount, uint256 rTransferAmount) private {
        _tOwned[sender] = _tOwned[sender].sub(tAmount);
        _rOwned[sender] = _rOwned[sender].sub(rAmount);
        _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);  
    }

    function _transferBothExcluded(address sender, address recipient, uint256 tAmount) private {
        uint256 currentRate =  _getRate();
        (uint256 rAmount, uint256 rTransferAmount, uint256 tTransferAmount,uint256 tCharity) = _getValues(tAmount);
        
        uint256 rCharity = tCharity.mul(currentRate);    
        _bothTransferContent(sender, recipient, tAmount, rAmount, tTransferAmount, rTransferAmount);  
        _sendToCharity(tCharity, sender);
        _reflectFee(rCharity, tCharity);
        emit Transfer(sender, recipient, tTransferAmount);
    }
    
    function _bothTransferContent(address sender, address recipient, uint256 tAmount, uint256 rAmount, uint256 tTransferAmount, uint256 rTransferAmount) private {
        _tOwned[sender] = _tOwned[sender].sub(tAmount);
        _rOwned[sender] = _rOwned[sender].sub(rAmount);
        _tOwned[recipient] = _tOwned[recipient].add(tTransferAmount);
        _rOwned[recipient] = _rOwned[recipient].add(rTransferAmount);  
    }

    function _reflectFee(uint256 rCharity, uint256 tCharity) private {
        _rTotal = _rTotal.sub(rCharity);
       
        _tCharityTotal = _tCharityTotal.add(tCharity);
        
    }
    

    function _getValues(uint256 tAmount) private view returns (uint256, uint256, uint256, uint256) {
        (uint256 tCharity) = _getTBasics(tAmount,_CHARITY_FEE);
        uint256 tTransferAmount = getTTransferAmount(tAmount, tCharity);
        uint256 currentRate =  _getRate();
        (uint256 rAmount) = _getRBasics(tAmount, currentRate);
        uint256 rTransferAmount = _getRTransferAmount(rAmount, tCharity, currentRate);
        return (rAmount, rTransferAmount, tTransferAmount, tCharity);
    }
    
    function _getTBasics(uint256 tAmount, uint256 charityFee) private view returns (uint256) {
       
       
        uint256 tCharity = ((tAmount.mul(charityFee)).div(_GRANULARITY)).div(100);
        return (tCharity);
    }
    
    function getTTransferAmount(uint256 tAmount, uint256 tCharity) private pure returns (uint256) {
        return tAmount.sub(tCharity);
    }
    
    function _getRBasics(uint256 tAmount, uint256 currentRate) private pure returns (uint256) {
        uint256 rAmount = tAmount.mul(currentRate);
        
        return (rAmount);
    }
    
    function _getRTransferAmount(uint256 rAmount, uint256 tCharity, uint256 currentRate) private pure returns (uint256) {
        
        uint256 rCharity = tCharity.mul(currentRate);
        uint256 rTransferAmount = rAmount.sub(rCharity);
        return rTransferAmount;
    }

    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 _sendToCharity(uint256 tCharity, address sender) private {
        uint256 currentRate = _getRate();
        uint256 rCharity = tCharity.mul(currentRate);
        _rOwned[FeeAddress] = _rOwned[FeeAddress].add(rCharity);
        _tOwned[FeeAddress] = _tOwned[FeeAddress].add(tCharity);
        emit Transfer(sender, FeeAddress, tCharity);
    }

    function removeAllFee() private {
        if(_CHARITY_FEE == 0) return;
        
       
        ORIG_CHARITY_FEE = _CHARITY_FEE;
        
        
        _CHARITY_FEE = 0;
    }
    
    function restoreAllFee() private {
        
        _CHARITY_FEE = ORIG_CHARITY_FEE;
    }
    



}

【讨论】:

  • 听起来虽然这几乎回答了你的问题,但它也引入了一个新问题。 Stack Overflow 不适合这种类型的交互。由于此问题没有任何其他答案,您可以尝试更新您的问题以包含新信息。或者,您可以发布一个新问题。但不要在回答中提出新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-26
  • 2021-04-03
  • 1970-01-01
  • 2021-03-12
  • 1970-01-01
相关资源
最近更新 更多