ERC20:转账金额超过限额

问题描述

我有两个智能合约传销代币。在传销智能合约中注册后,我必须从代币智能合约中转移代币。为此,我在 MLM 智能合约中使用了 Token 的合约地址和 transferFrom 方法。这是我的传销智能合约代码

pragma solidity >=0.4.23 <0.6.0;

interface IERC20 {
    function transferFrom(address sender,address recipient,uint256 amount) external returns (bool);
}

contract SmartLearningMLM {
    
    struct User {
        uint id;
        address referrer;
        uint partnersCount;
        
        mapping(uint8 => bool) activeX3Levels;
        mapping(uint8 => bool) activeX6Levels;
        
        mapping(uint8 => X3) x3Matrix;
        mapping(uint8 => X6) x6Matrix;
    }
    
    struct X3 {
        address currentReferrer;
        address[] referrals;
        bool blocked;
        uint reinvestCount;
    }
    
    struct X6 {
        address currentReferrer;
        address[] firstLevelReferrals;
        address[] secondLevelReferrals;
        bool blocked;
        uint reinvestCount;

        address closedPart;
    }

    uint8 public constant LAST_LEVEL = 12;
    
    mapping(address => User) public users;
    mapping(uint => address) public idToAddress;
    mapping(uint => address) public userIds;
    mapping(address => uint) public balances; 

    uint public lastUserId = 2;
    address public owner;
    
    IERC20 private _token;
    
    mapping(uint8 => uint) public levelPrice;
    
    event Registration(address indexed user,address indexed referrer,uint indexed userId,uint referrerId);
    event Reinvest(address indexed user,address indexed currentReferrer,address indexed caller,uint8 matrix,uint8 level);
    event Upgrade(address indexed user,uint8 level);
    event NewUserPlace(address indexed user,uint8 level,uint8 place);
    event MissedEthReceive(address indexed receiver,address indexed from,uint8 level);
    event SentExtraEthdividends(address indexed from,address indexed receiver,uint8 level);
    
    
    constructor(address ownerAddress,IERC20 token) public {
        levelPrice[1] = 5 * 10 ** 18;
        for (uint8 i = 2; i <= LAST_LEVEL; i++) {
            levelPrice[i] = levelPrice[i-1] * 2;
        }
        
        owner = ownerAddress;
        _token = token;
        User memory user = User({
            id: 1,referrer: address(0),partnersCount: uint(0)
        });
        
        users[ownerAddress] = user;
        idToAddress[1] = ownerAddress;
        
        for (uint8 i = 1; i <= LAST_LEVEL; i++) {
            users[ownerAddress].activeX3Levels[i] = true;
            users[ownerAddress].activeX6Levels[i] = true;
        }
        
        userIds[1] = ownerAddress;
    }
    
    function() external payable {
        if(msg.data.length == 0) {
            return registration(msg.sender,owner);
        }
        
        registration(msg.sender,bytesToAddress(msg.data));
    }

    function registrationExt(address referrerAddress) external payable {
        registration(msg.sender,referrerAddress);
    }
    
    function buyNewLevel(uint8 matrix,uint8 level) external payable {
        require(isUserExists(msg.sender),"user is not exists. Register first.");
        require(matrix == 1 || matrix == 2,"invalid matrix");
        require(level > 1 && level <= LAST_LEVEL,"invalid level");

        if (matrix == 1) {
            require(!users[msg.sender].activeX3Levels[level],"level already activated");

            if (users[msg.sender].x3Matrix[level-1].blocked) {
                users[msg.sender].x3Matrix[level-1].blocked = false;
            }
    
            address freeX3Referrer = findFreeX3Referrer(msg.sender,level);
            users[msg.sender].x3Matrix[level].currentReferrer = freeX3Referrer;
            users[msg.sender].activeX3Levels[level] = true;
            updateX3Referrer(msg.sender,freeX3Referrer,level);
            
            emit Upgrade(msg.sender,1,level);

        } else {
            require(!users[msg.sender].activeX6Levels[level],"level already activated"); 

            if (users[msg.sender].x6Matrix[level-1].blocked) {
                users[msg.sender].x6Matrix[level-1].blocked = false;
            }

            address freeX6Referrer = findFreeX6Referrer(msg.sender,level);
            
            users[msg.sender].activeX6Levels[level] = true;
            updateX6Referrer(msg.sender,freeX6Referrer,2,level);
        }
    }    
    
    function registration(address userAddress,address referrerAddress) private {
        require(!isUserExists(userAddress),"user exists");
        require(isUserExists(referrerAddress),"referrer not exists");
        
        uint32 size;
        assembly {
            size := extcodesize(userAddress)
        }
        require(size == 0,"cannot be a contract");
        
        User memory user = User({
            id: lastUserId,referrer: referrerAddress,partnersCount: 0
        });
        
        users[userAddress] = user;
        idToAddress[lastUserId] = userAddress;
        
        users[userAddress].referrer = referrerAddress;
        
        users[userAddress].activeX3Levels[1] = true; 
        users[userAddress].activeX6Levels[1] = true;
        
        
        userIds[lastUserId] = userAddress;
        lastUserId++;
        
        users[referrerAddress].partnersCount++;

        address freeX3Referrer = findFreeX3Referrer(userAddress,1);
        users[userAddress].x3Matrix[1].currentReferrer = freeX3Referrer;
        updateX3Referrer(userAddress,1);

        updateX6Referrer(userAddress,findFreeX6Referrer(userAddress,1),1);
        
        emit Registration(userAddress,referrerAddress,users[userAddress].id,users[referrerAddress].id);
    }
    
    function updateX3Referrer(address userAddress,address referrerAddress,uint8 level) private {
        users[referrerAddress].x3Matrix[level].referrals.push(userAddress);

        if (users[referrerAddress].x3Matrix[level].referrals.length < 3) {
            emit NewUserPlace(userAddress,level,uint8(users[referrerAddress].x3Matrix[level].referrals.length));
            return sendEThdividends(referrerAddress,userAddress,level);
        }
        
        emit NewUserPlace(userAddress,3);
        //close matrix
        users[referrerAddress].x3Matrix[level].referrals = new address[](0);
        if (!users[referrerAddress].activeX3Levels[level+1] && level != LAST_LEVEL) {
            users[referrerAddress].x3Matrix[level].blocked = true;
        }

        //create new one by recursion
        if (referrerAddress != owner) {
            //check referrer active level
            address freeReferrerAddress = findFreeX3Referrer(referrerAddress,level);
            if (users[referrerAddress].x3Matrix[level].currentReferrer != freeReferrerAddress) {
                users[referrerAddress].x3Matrix[level].currentReferrer = freeReferrerAddress;
            }
            
            users[referrerAddress].x3Matrix[level].reinvestCount++;
            emit Reinvest(referrerAddress,freeReferrerAddress,level);
            updateX3Referrer(referrerAddress,level);
        } else {
            sendEThdividends(owner,level);
            users[owner].x3Matrix[level].reinvestCount++;
            emit Reinvest(owner,address(0),level);
        }
    }

    function updateX6Referrer(address userAddress,uint8 level) private {
        require(users[referrerAddress].activeX6Levels[level],"500. Referrer level is inactive");
        
        if (users[referrerAddress].x6Matrix[level].firstLevelReferrals.length < 2) {
            users[referrerAddress].x6Matrix[level].firstLevelReferrals.push(userAddress);
            emit NewUserPlace(userAddress,uint8(users[referrerAddress].x6Matrix[level].firstLevelReferrals.length));
            
            //set current level
            users[userAddress].x6Matrix[level].currentReferrer = referrerAddress;

            if (referrerAddress == owner) {
                return sendEThdividends(referrerAddress,level);
            }
            
            address ref = users[referrerAddress].x6Matrix[level].currentReferrer;            
            users[ref].x6Matrix[level].secondLevelReferrals.push(userAddress); 
            
            uint len = users[ref].x6Matrix[level].firstLevelReferrals.length;
            
            if ((len == 2) && 
                (users[ref].x6Matrix[level].firstLevelReferrals[0] == referrerAddress) &&
                (users[ref].x6Matrix[level].firstLevelReferrals[1] == referrerAddress)) {
                if (users[referrerAddress].x6Matrix[level].firstLevelReferrals.length == 1) {
                    emit NewUserPlace(userAddress,ref,5);
                } else {
                    emit NewUserPlace(userAddress,6);
                }
            }  else if ((len == 1 || len == 2) &&
                    users[ref].x6Matrix[level].firstLevelReferrals[0] == referrerAddress) {
                if (users[referrerAddress].x6Matrix[level].firstLevelReferrals.length == 1) {
                    emit NewUserPlace(userAddress,3);
                } else {
                    emit NewUserPlace(userAddress,4);
                }
            } else if (len == 2 && users[ref].x6Matrix[level].firstLevelReferrals[1] == referrerAddress) {
                if (users[referrerAddress].x6Matrix[level].firstLevelReferrals.length == 1) {
                    emit NewUserPlace(userAddress,6);
                }
            }

            return updateX6ReferrerSecondLevel(userAddress,level);
        }
        
        users[referrerAddress].x6Matrix[level].secondLevelReferrals.push(userAddress);

        if (users[referrerAddress].x6Matrix[level].closedPart != address(0)) {
            if ((users[referrerAddress].x6Matrix[level].firstLevelReferrals[0] == 
                users[referrerAddress].x6Matrix[level].firstLevelReferrals[1]) &&
                (users[referrerAddress].x6Matrix[level].firstLevelReferrals[0] ==
                users[referrerAddress].x6Matrix[level].closedPart)) {

                updateX6(userAddress,true);
                return updateX6ReferrerSecondLevel(userAddress,level);
            } else if (users[referrerAddress].x6Matrix[level].firstLevelReferrals[0] == 
                users[referrerAddress].x6Matrix[level].closedPart) {
                updateX6(userAddress,level);
            } else {
                updateX6(userAddress,false);
                return updateX6ReferrerSecondLevel(userAddress,level);
            }
        }

        if (users[referrerAddress].x6Matrix[level].firstLevelReferrals[1] == userAddress) {
            updateX6(userAddress,false);
            return updateX6ReferrerSecondLevel(userAddress,level);
        } else if (users[referrerAddress].x6Matrix[level].firstLevelReferrals[0] == userAddress) {
            updateX6(userAddress,true);
            return updateX6ReferrerSecondLevel(userAddress,level);
        }
        
        if (users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[0]].x6Matrix[level].firstLevelReferrals.length <= 
            users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[1]].x6Matrix[level].firstLevelReferrals.length) {
            updateX6(userAddress,false);
        } else {
            updateX6(userAddress,true);
        }
        
        updateX6ReferrerSecondLevel(userAddress,level);
    }

    function updateX6(address userAddress,bool x2) private {
        if (!x2) {
            users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[0]].x6Matrix[level].firstLevelReferrals.push(userAddress);
            emit NewUserPlace(userAddress,users[referrerAddress].x6Matrix[level].firstLevelReferrals[0],uint8(users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[0]].x6Matrix[level].firstLevelReferrals.length));
            emit NewUserPlace(userAddress,2 + uint8(users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[0]].x6Matrix[level].firstLevelReferrals.length));
            //set current level
            users[userAddress].x6Matrix[level].currentReferrer = users[referrerAddress].x6Matrix[level].firstLevelReferrals[0];
        } else {
            users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[1]].x6Matrix[level].firstLevelReferrals.push(userAddress);
            emit NewUserPlace(userAddress,users[referrerAddress].x6Matrix[level].firstLevelReferrals[1],uint8(users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[1]].x6Matrix[level].firstLevelReferrals.length));
            emit NewUserPlace(userAddress,4 + uint8(users[users[referrerAddress].x6Matrix[level].firstLevelReferrals[1]].x6Matrix[level].firstLevelReferrals.length));
            //set current level
            users[userAddress].x6Matrix[level].currentReferrer = users[referrerAddress].x6Matrix[level].firstLevelReferrals[1];
        }
    }
    
    function updateX6ReferrerSecondLevel(address userAddress,uint8 level) private {
        if (users[referrerAddress].x6Matrix[level].secondLevelReferrals.length < 4) {
            return sendEThdividends(referrerAddress,level);
        }
        
        address[] memory x6 = users[users[referrerAddress].x6Matrix[level].currentReferrer].x6Matrix[level].firstLevelReferrals;
        
        if (x6.length == 2) {
            if (x6[0] == referrerAddress ||
                x6[1] == referrerAddress) {
                users[users[referrerAddress].x6Matrix[level].currentReferrer].x6Matrix[level].closedPart = referrerAddress;
            } else if (x6.length == 1) {
                if (x6[0] == referrerAddress) {
                    users[users[referrerAddress].x6Matrix[level].currentReferrer].x6Matrix[level].closedPart = referrerAddress;
                }
            }
        }
        
        users[referrerAddress].x6Matrix[level].firstLevelReferrals = new address[](0);
        users[referrerAddress].x6Matrix[level].secondLevelReferrals = new address[](0);
        users[referrerAddress].x6Matrix[level].closedPart = address(0);

        if (!users[referrerAddress].activeX6Levels[level+1] && level != LAST_LEVEL) {
            users[referrerAddress].x6Matrix[level].blocked = true;
        }

        users[referrerAddress].x6Matrix[level].reinvestCount++;
        
        if (referrerAddress != owner) {
            address freeReferrerAddress = findFreeX6Referrer(referrerAddress,level);

            emit Reinvest(referrerAddress,level);
            updateX6Referrer(referrerAddress,level);
        } else {
            emit Reinvest(owner,level);
            sendEThdividends(owner,level);
        }
    }
    
    function findFreeX3Referrer(address userAddress,uint8 level) public view returns(address) {
        while (true) {
            if (users[users[userAddress].referrer].activeX3Levels[level]) {
                return users[userAddress].referrer;
            }
            
            userAddress = users[userAddress].referrer;
        }
    }
    
    function findFreeX6Referrer(address userAddress,uint8 level) public view returns(address) {
        while (true) {
            if (users[users[userAddress].referrer].activeX6Levels[level]) {
                return users[userAddress].referrer;
            }
            
            userAddress = users[userAddress].referrer;
        }
    }
        
    function usersActiveX3Levels(address userAddress,uint8 level) public view returns(bool) {
        return users[userAddress].activeX3Levels[level];
    }

    function usersActiveX6Levels(address userAddress,uint8 level) public view returns(bool) {
        return users[userAddress].activeX6Levels[level];
    }

    function usersX3Matrix(address userAddress,uint8 level) public view returns(address,address[] memory,bool) {
        return (users[userAddress].x3Matrix[level].currentReferrer,users[userAddress].x3Matrix[level].referrals,users[userAddress].x3Matrix[level].blocked);
    }

    function usersX6Matrix(address userAddress,bool,address) {
        return (users[userAddress].x6Matrix[level].currentReferrer,users[userAddress].x6Matrix[level].firstLevelReferrals,users[userAddress].x6Matrix[level].secondLevelReferrals,users[userAddress].x6Matrix[level].blocked,users[userAddress].x6Matrix[level].closedPart);
    }
    
    function isUserExists(address user) public view returns (bool) {
        return (users[user].id != 0);
    }

    function findEthReceiver(address userAddress,address _from,uint8 level) private returns(address,bool) {
        address receiver = userAddress;
        bool isExTradividends;
        if (matrix == 1) {
            while (true) {
                if (users[receiver].x3Matrix[level].blocked) {
                    emit MissedEthReceive(receiver,_from,level);
                    isExTradividends = true;
                    receiver = users[receiver].x3Matrix[level].currentReferrer;
                } else {
                    return (receiver,isExTradividends);
                }
            }
        } else {
            while (true) {
                if (users[receiver].x6Matrix[level].blocked) {
                    emit MissedEthReceive(receiver,level);
                    isExTradividends = true;
                    receiver = users[receiver].x6Matrix[level].currentReferrer;
                } else {
                    return (receiver,isExTradividends);
                }
            }
        }
    }

    function sendEThdividends(address userAddress,uint8 level) private {
        (address receiver,bool isExTradividends) = findEthReceiver(userAddress,matrix,level);

        _token.transferFrom(_from,address(uint160(receiver)),levelPrice[level]);
        
        if (isExTradividends) {
            emit SentExtraEthdividends(_from,receiver,level);
        }
    }
    
    function bytesToAddress(bytes memory bys) private pure returns (address addr) {
        assembly {
            addr := mload(add(bys,20))
        }
    }
}

我的问题是以下行按预期工作。

_token.transferFrom(_from,levelPrice[level]);

我收到以下错误

Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
execution reverted: ERC20: transfer amount exceeds allowance { "originalError": { "code": 3,"data": "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002845524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365000000000000000000000000000000000000000000000000","message": "execution reverted: ERC20: transfer amount exceeds allowance" } }

但我已经添加了津贴 _from(所有者)和合同地址(支出者)。后来我测试了。津贴适当增加。但我得到的津贴超过错误。为了避免发件人和收件人地址的混淆,我硬编码如下,

_token.transferFrom(address(0xBc29513F0075736Bad940345ebBE366f993B22fC),address(0x0E6a6Bf011852cB607464f9088D05A2B1238a466),5000000000000000000);

但我遇到了同样的错误

如果我单独执行 transferFrom 逻辑,它工作正常。这是我没有传销逻辑的工作代码

pragma solidity >=0.4.23 <0.6.0;

interface IERC20 {
    function transferFrom(address sender,uint256 amount) external returns (bool);
}

contract SmartLearningMLM {
    
    IERC20 private _token;
    address public owner;
    
    constructor(address _owner,IERC20 token) public {
    
        _token = token;
        owner = _owner;
    }
    
    function() external payable {
        if(msg.data.length == 0) {
            return registration(msg.sender,referrerAddress);
    }
    
    function registration(address userAddress,address referrerAddress) private {
        _token.transferFrom(address(0xBc29513F0075736Bad940345ebBE366f993B22fC),5000000000000000000);

    }    
    function bytesToAddress(bytes memory bys) private pure returns (address addr) {
        assembly {
            addr := mload(add(bys,20))
        }
    }
    
}

帮我解决这个问题。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...