ETH Price: $2,675.32 (+0.50%)

Transaction Decoder

Block:
11063905 at Oct-16-2020 01:18:12 AM +UTC
Transaction Fee:
0.00798456 ETH $21.36
Gas Used:
399,228 Gas / 20 Gwei

Emitted Events:

272 UtahSilver.NewUserPlace( user=[Sender] 0xbd6b428d83af973216e637f29406d5bfda7b01f6, referrer=0x0866adae1ad3ff01057240954b1e3fba56e7db42, matrix=1, level=1, place=1 )
273 Go9tro.Transfer( from=0x0000000000000000000000000000000000000000, to=[Sender] 0xbd6b428d83af973216e637f29406d5bfda7b01f6, value=25000000000000000000 )
274 UtahSilver.RecievedEth( receiver=0x0866adae1ad3ff01057240954b1e3fba56e7db42, _from=[Sender] 0xbd6b428d83af973216e637f29406d5bfda7b01f6, matrix=1, level=1, amount=20000000000000000, time=1602811092 )
275 UtahSilver.NewUserPlace( user=[Sender] 0xbd6b428d83af973216e637f29406d5bfda7b01f6, referrer=0x0866adae1ad3ff01057240954b1e3fba56e7db42, matrix=2, level=1, place=2 )
276 UtahSilver.NewUserPlace( user=[Sender] 0xbd6b428d83af973216e637f29406d5bfda7b01f6, referrer=0x83016fd8305bc01237f621a9380a1493e5af2457, matrix=2, level=1, place=4 )
277 Go9tro.Transfer( from=0x0000000000000000000000000000000000000000, to=[Sender] 0xbd6b428d83af973216e637f29406d5bfda7b01f6, value=25000000000000000000 )
278 UtahSilver.RecievedEth( receiver=0x83016fd8305bc01237f621a9380a1493e5af2457, _from=[Sender] 0xbd6b428d83af973216e637f29406d5bfda7b01f6, matrix=2, level=1, amount=20000000000000000, time=1602811092 )
279 UtahSilver.Registration( user=[Sender] 0xbd6b428d83af973216e637f29406d5bfda7b01f6, referrer=0x0866adae1ad3ff01057240954b1e3fba56e7db42, userId=307, referrerId=304, amount=40000000000000000, time=1602811092 )

Account State Difference:

  Address   Before After State Difference Code
0x0866Adae...a56E7dB42 0 Eth0.02 Eth0.02
0x12C211dc...1b989e011
0x556237E8...c7d0E71a7
0x83016Fd8...3e5Af2457 0.229471128 Eth0.249471128 Eth0.02
0xBd6B428d...fdA7B01f6
0.212718351858109487 Eth
Nonce: 0
0.164733791858109487 Eth
Nonce: 1
0.04798456
(Ethermine)
589.891355988984682568 Eth589.899340548984682568 Eth0.00798456

Execution Trace

ETH 0.04 UtahSilver.registrationExt( referrerAddress=0x0866Adae1ad3fF01057240954b1E3fBa56E7dB42 )
  • ETH 0.02 0x0866adae1ad3ff01057240954b1e3fba56e7db42.CALL( )
  • Go9tro.mint( _receiver=0xBd6B428d83aF973216E637F29406d5BfdA7B01f6, _amount=25000000000000000000 ) => ( True )
  • ETH 0.02 0x83016fd8305bc01237f621a9380a1493e5af2457.CALL( )
  • Go9tro.mint( _receiver=0xBd6B428d83aF973216E637F29406d5BfdA7B01f6, _amount=25000000000000000000 ) => ( True )
    registrationExt[UtahSilver (ln:139)]
    File 1 of 2: UtahSilver
    pragma solidity 0.5.14;
    
    library SafeMath {
    
        function add(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a + b;
            require(c >= a, "SafeMath: addition overflow");
            return c;
        }
    
        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
            require(b <= a, "SafeMath: subtraction overflow");
            uint256 c = a - b;
            return c;
        }
    
        function mul(uint256 a, uint256 b) internal pure returns (uint256) {
            if (a == 0) {
                return 0;
            }
            uint256 c = a * b;
            require(c / a == b, "SafeMath: multiplication overflow");
            return c;
        }
    
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
            require(b > 0, "SafeMath: division by zero");
            uint256 c = a / b;
            return c;
        }
        
        function mod(uint256 a, uint256 b) internal pure returns (uint256) {
            require(b != 0, "SafeMath: modulo by zero");
            return a % b;
        }
    }
    
    
    contract ERC20 {
        function mint(address reciever, uint256 value) public returns(bool);
    }
    
    contract UtahSilver {
        
        struct User {
            uint id;
            address referrer;
            uint partnersCount;
            mapping(uint8 => bool) activeG3Levels;
            mapping(uint8 => bool) activeG4Levels;
            mapping(uint8 => G3Manual) G3Matrix;
            mapping(uint8 => G4Auto) G4Matrix;
        }
        
        struct G3Manual {
            address currentReferrer;
            address[] referrals;
            bool blocked;
            uint reinvestCount;
        }
        
        struct G4Auto {
            address currentReferrer;
            address[] firstLevelReferrals;
            address[] secondLevelReferrals;
            bool blocked;
            uint reinvestCount;
            address closedPart;
        }
    
        ERC20 Token;
        using SafeMath for uint256;
        bool public lockStatus;
        uint8 public constant LAST_LEVEL = 9;
        uint public lastUserId = 2;
        address public ownerAddress;
        
        mapping(uint8 => uint) public levelPrice;
        mapping(address => User) public users;
        mapping(uint => address) public userIds;
        
        
        modifier onlyOwner() {
            require(msg.sender == ownerAddress,"only Owner");
            _;
        }
        
        modifier isLock() {
            require(lockStatus == false,"Contract Locked");
            _;
        }
        
        event Registration(address indexed user, address indexed referrer, uint indexed userId, uint referrerId, uint amount, uint time);
        event Reinvest(address indexed user, address indexed currentReferrer, address indexed caller, uint8  matrix, uint8 level, uint amount, uint time);
        event Upgrade(address indexed user, address indexed referrer, uint8 indexed matrix, uint8 level,uint amount, uint time);
        event NewUserPlace(address indexed user, address indexed referrer, uint8 indexed matrix, uint8 level, uint8 place);
        event MissedEthReceive(address indexed receiver, address indexed _from, uint8 indexed matrix, uint8 level,uint amount, uint time);
        event RecievedEth(address indexed receiver, address indexed _from, uint8 indexed matrix, uint8 level,uint amount, uint time);
        event SentExtraEthDividends(address indexed _from, address indexed receiver, uint8 indexed matrix, uint8 level,uint amount, uint time);
        
        constructor(address _owner,address _tokenAddress) public {
            require(_tokenAddress != address(0),"Invalid Token Address");
            
            levelPrice[1] = 0.02 ether;
            levelPrice[2] = 0.04 ether;
            levelPrice[3] = 0.08 ether;
            levelPrice[4] = 0.16 ether;
            levelPrice[5] = 0.32 ether;
            levelPrice[6] = 0.64 ether;
            levelPrice[7] = 1.28 ether;
            levelPrice[8] = 2.56 ether;
            levelPrice[9] = 6 ether;
            
            
            ownerAddress = _owner;
            Token = ERC20(_tokenAddress);
            
            User memory user = User({
                id: 1,
                referrer: address(0),
                partnersCount: uint(0)
            });
            
            users[ownerAddress] = user;
            userIds[1] = ownerAddress;
           
            for (uint8 i = 1; i <= LAST_LEVEL; i++) {
                users[ownerAddress].activeG3Levels[i] = true;
                users[ownerAddress].activeG4Levels[i] = true;
            }
            
        }
        
        // external functions
        function() external payable {
            revert("Invalid Contract Transaction");
        }
        
        function registrationExt(address referrerAddress) isLock external payable {
            registration(msg.sender, referrerAddress);
        }
        
        function buyNewLevel(uint8 matrix, uint8 level) isLock external payable {
            require(isUserExists(msg.sender), "user is not exists. Register first.");
            require(matrix == 1 || matrix == 2, "invalid matrix");
            require(msg.value == levelPrice[level], "invalid price");
            require(level > 1 && level <= LAST_LEVEL, "invalid level");
    
            if (matrix == 1) {
                require(!users[msg.sender].activeG3Levels[level], "level already activated");
                if (users[msg.sender].G3Matrix[level-1].blocked) {
                    users[msg.sender].G3Matrix[level-1].blocked = false;
                }
                address freeG3Referrer = findFreeG3Referrer(msg.sender, level);
                users[msg.sender].G3Matrix[level].currentReferrer = freeG3Referrer;
                users[msg.sender].activeG3Levels[level] = true;
                updateG3Referrer(msg.sender, freeG3Referrer, level);
                emit Upgrade(msg.sender, freeG3Referrer, 1, level, msg.value, now);
            } else {
                require(!users[msg.sender].activeG4Levels[level], "level already activated"); 
                if (users[msg.sender].G4Matrix[level-1].blocked) {
                    users[msg.sender].G4Matrix[level-1].blocked = false;
                }
                address freeG4Referrer = findFreeG4Referrer(msg.sender, level);
                users[msg.sender].activeG4Levels[level] = true;
                updateG4Referrer(msg.sender, freeG4Referrer, level);
                emit Upgrade(msg.sender, freeG4Referrer, 2, level, msg.value, now);
            }
        }   
        
        // public functions
        function failSafe(address payable _toUser, uint _amount) onlyOwner public returns (bool) {
            require(_toUser != address(0), "Invalid Address");
            require(address(this).balance >= _amount, "Insufficient balance");
            (_toUser).transfer(_amount);
            return true;
        }
        
        function contractLock(bool _lockStatus) onlyOwner public returns(bool) {
            lockStatus = _lockStatus;
            return true;
        }
        
        function findFreeG3Referrer(address userAddress, uint8 level) public view returns(address) {
            while (true) {
                if (users[users[userAddress].referrer].activeG3Levels[level]) {
                    return users[userAddress].referrer;
                }
                
                userAddress = users[userAddress].referrer;
            }
        }
        
        function findFreeG4Referrer(address userAddress, uint8 level) public view returns(address) {
            while (true) {
                if (users[users[userAddress].referrer].activeG4Levels[level]) {
                    return users[userAddress].referrer;
                }
                
                userAddress = users[userAddress].referrer;
            }
        }
            
        function usersActiveG3Levels(address userAddress, uint8 level) public view returns(bool) {
            return users[userAddress].activeG3Levels[level];
        }
    
        function usersActiveG4Levels(address userAddress, uint8 level) public view returns(bool) {
            return users[userAddress].activeG4Levels[level];
        }
    
        function usersG3Matrix(address userAddress, uint8 level) public view returns(address, address[] memory,uint, bool) {
            return (users[userAddress].G3Matrix[level].currentReferrer,
                    users[userAddress].G3Matrix[level].referrals,
                    users[userAddress].G3Matrix[level].reinvestCount,
                    users[userAddress].G3Matrix[level].blocked);
        }
    
        function usersG4Matrix(address userAddress, uint8 level) public view returns(address, address[] memory, address[] memory, bool, address,uint) {
            return (users[userAddress].G4Matrix[level].currentReferrer,
                    users[userAddress].G4Matrix[level].firstLevelReferrals,
                    users[userAddress].G4Matrix[level].secondLevelReferrals,
                    users[userAddress].G4Matrix[level].blocked,
                    users[userAddress].G4Matrix[level].closedPart,
                    users[userAddress].G4Matrix[level].reinvestCount);
        }
        
        function isUserExists(address user) public view returns (bool) {
            return (users[user].id != 0);
        }
        
        //private functions
        function registration(address userAddress, address referrerAddress) isLock private {
            require(msg.value == levelPrice[1].mul(2), "registration cost 0.05");
            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;
            users[userAddress].referrer = referrerAddress;
            users[userAddress].activeG3Levels[1] = true; 
            users[userAddress].activeG4Levels[1] = true;
            
            userIds[lastUserId] = userAddress;
            lastUserId = lastUserId.add(1);
            users[referrerAddress].partnersCount = users[referrerAddress].partnersCount.add(1);
    
            address freeG3Referrer = findFreeG3Referrer(userAddress, 1);
            users[userAddress].G3Matrix[1].currentReferrer = freeG3Referrer;
            updateG3Referrer(userAddress, freeG3Referrer, 1);
    
            updateG4Referrer(userAddress, findFreeG4Referrer(userAddress, 1), 1);
            
            emit Registration(userAddress, referrerAddress, users[userAddress].id, users[referrerAddress].id, msg.value, now);
        }
        
        function updateG3Referrer(address userAddress, address referrerAddress, uint8 level) private {
            users[referrerAddress].G3Matrix[level].referrals.push(userAddress);
    
            if (users[referrerAddress].G3Matrix[level].referrals.length < 3) {
                emit NewUserPlace(userAddress, referrerAddress, 1, level, uint8(users[referrerAddress].G3Matrix[level].referrals.length));
                return sendETHDividends(referrerAddress, userAddress, 1, level);
            }
            
            emit NewUserPlace(userAddress, referrerAddress, 1, level, 3);
            //close matrix
            users[referrerAddress].G3Matrix[level].referrals = new address[](0);
            if (!users[referrerAddress].activeG3Levels[level+1] && level != LAST_LEVEL) {
                users[referrerAddress].G3Matrix[level].blocked = true;
            }
    
            //create new one by recursion
            if (referrerAddress != ownerAddress) {
                //check referrer active level
                address freeReferrerAddress = findFreeG3Referrer(referrerAddress, level);
                if (users[referrerAddress].G3Matrix[level].currentReferrer != freeReferrerAddress) {
                    users[referrerAddress].G3Matrix[level].currentReferrer = freeReferrerAddress;
                }
                users[referrerAddress].G3Matrix[level].reinvestCount = users[referrerAddress].G3Matrix[level].reinvestCount.add(1);
                emit Reinvest(referrerAddress, freeReferrerAddress, userAddress, 1, level, levelPrice[level], now);
                updateG3Referrer(referrerAddress, freeReferrerAddress, level);
            } else {
                sendETHDividends(ownerAddress, userAddress, 1, level);
                users[ownerAddress].G3Matrix[level].reinvestCount = users[ownerAddress].G3Matrix[level].reinvestCount.add(1);
                emit Reinvest(ownerAddress, address(0), userAddress, 1, level, levelPrice[level], now);
            }
        }
    
        function updateG4Referrer(address userAddress, address referrerAddress, uint8 level) private {
            require(users[referrerAddress].activeG4Levels[level], "500. Referrer level is inactive");
            
            if (users[referrerAddress].G4Matrix[level].firstLevelReferrals.length < 2) {
                users[referrerAddress].G4Matrix[level].firstLevelReferrals.push(userAddress);
                emit NewUserPlace(userAddress, referrerAddress, 2, level, uint8(users[referrerAddress].G4Matrix[level].firstLevelReferrals.length));
                
                //set current level
                users[userAddress].G4Matrix[level].currentReferrer = referrerAddress;
    
                if (referrerAddress == ownerAddress) {
                    return sendETHDividends(referrerAddress, userAddress, 2, level);
                }
                
                address ref = users[referrerAddress].G4Matrix[level].currentReferrer;            
                users[ref].G4Matrix[level].secondLevelReferrals.push(userAddress); 
                uint len = users[ref].G4Matrix[level].firstLevelReferrals.length;
                
                if ((len == 2) && 
                    (users[ref].G4Matrix[level].firstLevelReferrals[0] == referrerAddress) &&
                    (users[ref].G4Matrix[level].firstLevelReferrals[1] == referrerAddress)) {
                    if (users[referrerAddress].G4Matrix[level].firstLevelReferrals.length == 1) {
                        emit NewUserPlace(userAddress, ref, 2, level, 5);
                    } else {
                        emit NewUserPlace(userAddress, ref, 2, level, 6);
                    }
                }  else if ((len == 1 || len == 2) &&
                        users[ref].G4Matrix[level].firstLevelReferrals[0] == referrerAddress) {
                    if (users[referrerAddress].G4Matrix[level].firstLevelReferrals.length == 1) {
                        emit NewUserPlace(userAddress, ref, 2, level, 3);
                    } else {
                        emit NewUserPlace(userAddress, ref, 2, level, 4);
                    }
                } else if (len == 2 && users[ref].G4Matrix[level].firstLevelReferrals[1] == referrerAddress) {
                    if (users[referrerAddress].G4Matrix[level].firstLevelReferrals.length == 1) {
                        emit NewUserPlace(userAddress, ref, 2, level, 5);
                    } else {
                        emit NewUserPlace(userAddress, ref, 2, level, 6);
                    }
                }
                return updateG4ReferrerSecondLevel(userAddress, ref, level);
            }
            
            users[referrerAddress].G4Matrix[level].secondLevelReferrals.push(userAddress);
    
            if (users[referrerAddress].G4Matrix[level].closedPart != address(0)) {
                if ((users[referrerAddress].G4Matrix[level].firstLevelReferrals[0] == 
                    users[referrerAddress].G4Matrix[level].firstLevelReferrals[1]) &&
                    (users[referrerAddress].G4Matrix[level].firstLevelReferrals[0] ==
                    users[referrerAddress].G4Matrix[level].closedPart)) {
                    updateG4(userAddress, referrerAddress, level, true);
                    return updateG4ReferrerSecondLevel(userAddress, referrerAddress, level);
                } else if (users[referrerAddress].G4Matrix[level].firstLevelReferrals[0] == 
                    users[referrerAddress].G4Matrix[level].closedPart) {
                    updateG4(userAddress, referrerAddress, level, true);
                    return updateG4ReferrerSecondLevel(userAddress, referrerAddress, level);
                } else {
                    updateG4(userAddress, referrerAddress, level, false);
                    return updateG4ReferrerSecondLevel(userAddress, referrerAddress, level);
                }
            }
    
            if (users[referrerAddress].G4Matrix[level].firstLevelReferrals[1] == userAddress) {
                updateG4(userAddress, referrerAddress, level, false);
                return updateG4ReferrerSecondLevel(userAddress, referrerAddress, level);
            } else if (users[referrerAddress].G4Matrix[level].firstLevelReferrals[0] == userAddress) {
                updateG4(userAddress, referrerAddress, level, true);
                return updateG4ReferrerSecondLevel(userAddress, referrerAddress, level);
            }
            
            if (users[users[referrerAddress].G4Matrix[level].firstLevelReferrals[0]].G4Matrix[level].firstLevelReferrals.length <= 
                users[users[referrerAddress].G4Matrix[level].firstLevelReferrals[1]].G4Matrix[level].firstLevelReferrals.length) {
                updateG4(userAddress, referrerAddress, level, false);
            } else {
                updateG4(userAddress, referrerAddress, level, true);
            }
            
            updateG4ReferrerSecondLevel(userAddress, referrerAddress, level);
        }
    
        function updateG4(address userAddress, address referrerAddress, uint8 level, bool x2) private {
            if (!x2) {
                users[users[referrerAddress].G4Matrix[level].firstLevelReferrals[0]].G4Matrix[level].firstLevelReferrals.push(userAddress);
                emit NewUserPlace(userAddress, users[referrerAddress].G4Matrix[level].firstLevelReferrals[0], 2, level, uint8(users[users[referrerAddress].G4Matrix[level].firstLevelReferrals[0]].G4Matrix[level].firstLevelReferrals.length));
                emit NewUserPlace(userAddress, referrerAddress, 2, level, 2 + uint8(users[users[referrerAddress].G4Matrix[level].firstLevelReferrals[0]].G4Matrix[level].firstLevelReferrals.length));
                //set current level
                users[userAddress].G4Matrix[level].currentReferrer = users[referrerAddress].G4Matrix[level].firstLevelReferrals[0];
            } else {
                users[users[referrerAddress].G4Matrix[level].firstLevelReferrals[1]].G4Matrix[level].firstLevelReferrals.push(userAddress);
                emit NewUserPlace(userAddress, users[referrerAddress].G4Matrix[level].firstLevelReferrals[1], 2, level, uint8(users[users[referrerAddress].G4Matrix[level].firstLevelReferrals[1]].G4Matrix[level].firstLevelReferrals.length));
                emit NewUserPlace(userAddress, referrerAddress, 2, level, 4 + uint8(users[users[referrerAddress].G4Matrix[level].firstLevelReferrals[1]].G4Matrix[level].firstLevelReferrals.length));
                //set current level
                users[userAddress].G4Matrix[level].currentReferrer = users[referrerAddress].G4Matrix[level].firstLevelReferrals[1];
            }
        }
        
        function updateG4ReferrerSecondLevel(address userAddress, address referrerAddress, uint8 level) private {
            if (users[referrerAddress].G4Matrix[level].secondLevelReferrals.length < 4) {
                return sendETHDividends(referrerAddress, userAddress, 2, level);
            }
            
            address[] memory G4 = users[users[referrerAddress].G4Matrix[level].currentReferrer].G4Matrix[level].firstLevelReferrals;
            
            if (G4.length == 2) {
                if (G4[0] == referrerAddress ||
                    G4[1] == referrerAddress) {
                    users[users[referrerAddress].G4Matrix[level].currentReferrer].G4Matrix[level].closedPart = referrerAddress;
                } else if (G4.length == 1) {
                    if (G4[0] == referrerAddress) {
                        users[users[referrerAddress].G4Matrix[level].currentReferrer].G4Matrix[level].closedPart = referrerAddress;
                    }
                }
            }
            users[referrerAddress].G4Matrix[level].firstLevelReferrals = new address[](0);
            users[referrerAddress].G4Matrix[level].secondLevelReferrals = new address[](0);
            users[referrerAddress].G4Matrix[level].closedPart = address(0);
    
            if (!users[referrerAddress].activeG4Levels[level+1] && level != LAST_LEVEL) {
                users[referrerAddress].G4Matrix[level].blocked = true;
            }
    
            users[referrerAddress].G4Matrix[level].reinvestCount = users[referrerAddress].G4Matrix[level].reinvestCount.add(1);
            
            if (referrerAddress != ownerAddress) {
                address freeReferrerAddress = findFreeG4Referrer(referrerAddress, level);
    
                emit Reinvest(referrerAddress, freeReferrerAddress, userAddress, 2, level, levelPrice[level], now);
                updateG4Referrer(referrerAddress, freeReferrerAddress, level);
            } else {
                emit Reinvest(ownerAddress, address(0), userAddress, 2, level, levelPrice[level], now);
                sendETHDividends(ownerAddress, userAddress, 2, level);
            }
        }
        
        function findEthReceiver(address userAddress, address _from, uint8 matrix, uint8 level) private returns(address, bool) {
            address receiver = userAddress;
            bool isExtraDividends;
            if (matrix == 1) {
                while (true) {
                    if (users[receiver].G3Matrix[level].blocked) {
                        emit MissedEthReceive(receiver, _from, 1, level, levelPrice[level], now);
                        isExtraDividends = true;
                        receiver = users[receiver].G3Matrix[level].currentReferrer;
                    } else {
                        return (receiver, isExtraDividends);
                    }
                }
            } else {
                while (true) {
                    if (users[receiver].G4Matrix[level].blocked) {
                        emit MissedEthReceive(receiver, _from, 2, level, levelPrice[level], now);
                        isExtraDividends = true;
                        receiver = users[receiver].G4Matrix[level].currentReferrer;
                    } else {
                        return (receiver, isExtraDividends);
                    }
                }
            }
        }
    
        function sendETHDividends(address userAddress, address _from, uint8 matrix, uint8 level) private {
            (address receiver, bool isExtraDividends) = findEthReceiver(userAddress, _from, matrix, level);
            uint256 tobeminted;
            
            tobeminted = 25 ether;
            
            require( (address(uint160(receiver)).send(levelPrice[level])) && 
                Token.mint(msg.sender, tobeminted),"Invalid Transaction");
            
            if (isExtraDividends) {
                emit SentExtraEthDividends(_from, receiver, matrix, level, levelPrice[level], now);
            }
            else {
                 emit RecievedEth(receiver, _from, matrix, level, levelPrice[level], now);
            }
        }
        
        
    }

    File 2 of 2: Go9tro
    pragma solidity 0.5.14;
    
    library SafeMath {
    
        function add(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a + b;
            require(c >= a, "SafeMath: addition overflow");
            return c;
        }
    
        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
            require(b <= a, "SafeMath: subtraction overflow");
            uint256 c = a - b;
            return c;
        }
    
        function mul(uint256 a, uint256 b) internal pure returns (uint256) {
            if (a == 0) {
                return 0;
            }
            uint256 c = a * b;
            require(c / a == b, "SafeMath: multiplication overflow");
            return c;
        }
    
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
            require(b > 0, "SafeMath: division by zero");
            uint256 c = a / b;
            return c;
        }
        
        function mod(uint256 a, uint256 b) internal pure returns (uint256) {
            require(b != 0, "SafeMath: modulo by zero");
            return a % b;
        }
    }
    
    contract ERC20 {
        function transferFrom(address from, address to, uint256 value) public returns (bool);
        function approve(address spender, uint256 value) public returns (bool);
        function transfer(address to, uint256 value) public returns(bool);
        function allowance(address owner, address spender) public view returns (uint256);
        event Transfer(address indexed from, address indexed to, uint256 value);
        event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    
    contract Go9tro is ERC20 {
        
        using SafeMath for uint256;
        
        string public name;
        string public symbol;
        uint8 public decimals;
        uint256 public totalSupply;
        address public owner;
        address public mlmAddress;
        
        mapping (address => uint256) public balances;
        mapping (address => mapping (address => uint256)) public allowed;
       
        modifier onlyOwner() {
            require(msg.sender == owner, "Only owner");
            _;
        }
    
        constructor () public {
            symbol = "Go9tro";
            name = "Go9tro";
            decimals = 18;
            owner = msg.sender;
           
        }
        
        // public functions
        
        /**
         * @dev To change Owner Address
         * @param _newOwner New owner address
         */ 
        function changeOwner(address _newOwner) public onlyOwner returns(bool) {
            require(_newOwner != address(0), "Invalid Address");
            owner = _newOwner;
            return true;
        }
        
        /**
         * @dev To change MLM Address
         * @param _newMLMAddress New MLM address
         */ 
        function changeMLM(address _newMLMAddress) public onlyOwner returns(bool) {
            require(_newMLMAddress != address(0), "Invalid Address");
            mlmAddress = _newMLMAddress;
            return true;
        }
        
        /**
         * @dev To mint Go9tro Tokens by admin
         * @param _receiver Reciever address
         * @param _amount Amount to mint
         */ 
        function ownerMint(address _receiver, uint256 _amount) public onlyOwner returns (bool) {
            require(_receiver != address(0), "Invalid address");
            require(_amount >= 0, "Invalid amount");
            totalSupply = totalSupply.add(_amount);
            balances[_receiver] = balances[_receiver].add(_amount);
            emit Transfer(address(0), _receiver, _amount);
            return true;
        }
        
        /**
         * @dev To mint Go9tro Tokens by mlm
         * @param _receiver Reciever address
         * @param _amount Amount to mint
         */ 
        function mint(address _receiver, uint256 _amount) public returns (bool) {
            require(_receiver != address(0), "Invalid address");
            require(_amount >= 0, "Invalid amount");
            require(msg.sender == mlmAddress,"only From MLM");
            totalSupply = totalSupply.add(_amount);
            balances[_receiver] = balances[_receiver].add(_amount);
            emit Transfer(address(0), _receiver, _amount);
            return true;
        }
        
         /**
         * @dev Transfer token to specified address
         * @param _to Receiver address
         * @param _value Amount of the tokens
         */
        function transfer(address _to, uint256 _value) public returns (bool) {
            require(_to != address(0), "Invalid address");
            require(_value <= balances[msg.sender], "Insufficient balance");
            balances[msg.sender] = balances[msg.sender].sub(_value);
            balances[_to] = balances[_to].add(_value);
            emit Transfer(msg.sender, _to, _value);
            return true;
        }
    
        /**
         * @dev Transfer tokens from one address to another
         * @param _from  The holder address
         * @param _to  The Receiver address
         * @param _value  the amount of tokens to be transferred
         */
        function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
            require(_from != address(0), "Invalid from address");
            require(_to != address(0), "Invalid to address");
            require(_value <= balances[_from], "Insufficient balance");
            require(_value <= allowed[_from][msg.sender], "Insufficient allowance");
            balances[_from] = balances[_from].sub(_value);
            balances[msg.sender] = balances[msg.sender].add(_value);
            allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
            emit Transfer(_from, _to, _value);
            return true;
        }
        
        /**
         * @dev Approve respective tokens for spender
         * @param _spender Spender address
         * @param _value Amount of tokens to be allowed
         */
        function approve(address _spender, uint256 _value) public returns (bool) {
            require(_spender != address(0), "Null address");
            require(_value > 0, "Invalid value");
            allowed[msg.sender][_spender] = _value;
            emit Approval(msg.sender, _spender, _value);
            return true;
        }
        
        /**
         * @dev Check balance of the holder
         * @param _owner Token holder address
         */ 
        function balanceOf(address _owner) public view returns (uint256) {
            return balances[_owner];
        }
    
       
        /**
         * @dev To view approved balance
         * @param _owner Holder address
         * @param _spender Spender address
         */ 
        function allowance(address _owner, address _spender) public view returns (uint256) {
            return allowed[_owner][_spender];
        } 
      
    }