AXXA.ai Token - Smart Contract Audit Report

Summary

AXXA Token Audit Report AXXA intends to build a smart service and neural network ecosystem that runs powerful trading on cryptocurrency markets. For this audit we reviewed the project's token contract, deployed at 0x67d72156f9ee9b1a40da04021c20d54325e840ce. Further features are still in development.

Update - March 23rd, 2021 - The token has now been deployed on the Binance Smart Chain at 0xffca7c35339949f7b0af7267d00adff5f96e827e. .

Notes of the contract:
  • As of the time of the writing of this report, the circulating supply is 0 tokens. The owner of the contract has the ability to 'release' (mint) tokens up to the total supply cap of 1 billion. Only the owner has the ability to burn tokens.
  • Ownership - Some functions are protected and can only be called by the contract owner. The owner can transfer ownership to any address.
  • Ownership Protected functions release (mint) tokens up to the total supply, mark releasing finsihed (thereby preventing future minting), transfer ownership, and burn tokens.
  • The owner additonally has the ability to recover any tokens erroneously sent to the contract address.
  • Utilization of SafeMath to prevent overflows.
Audit Findings Summary
  • No serious issues from external attackers were identified.
  • Be aware of the ability of the owner to release tokens up to the total supply cap..
  • Date: December 2nd, 2020.
  • Update Date: March 23rd, 2021 - Add deployment to BSC.

We ran over 400,000 transactions interacting with this contract on a test blockchain to determine these results.
Date: December 2nd, 2020
Vulnerability CategoryNotesResult
Arbitrary Storage WriteN/APASS
Arbitrary JumpN/APASS
Delegate Call to Untrusted ContractN/APASS
Dependence on Predictable VariablesN/APASS
Deprecated OpcodesN/APASS
Ether ThiefN/APASS
ExceptionsN/APASS
External CallsN/APASS
Integer Over/UnderflowN/APASS
Multiple SendsN/APASS
SuicideN/APASS
State Change External CallsN/APass
Unchecked RetvalN/APASS
User Supplied AssertionN/APASS
Critical Solidity CompilerN/APASS
Overall Contract Safety PASS

TRC20 Token Graph

Multi-file Token


 ($) = payable function
 # = non-constant function
 
 Int = Internal
 Ext = External
 Pub = Public

 + [Lib] SafeMath 
    - [Int] mul
    - [Int] div
    - [Int] sub
    - [Int] add

 +  ERC20Basic 
    - [Pub] balanceOf
    - [Pub] transfer #

 +  ERC20 (ERC20Basic)
    - [Pub] allowance
    - [Pub] transferFrom #
    - [Pub] approve #

 +  UnknownToken 
    - [Pub] balanceOf
    - [Pub] transfer #

 + [Int] Token 
    - [Ext] release #
    - [Ext] totalSupply
    - [Ext] balanceOf

 +  AXXA (ERC20)
    - [Pub]  #
    - [Pub] transferOwnership #
       - modifiers: onlyOwner
    - [Pub] finishTokenRelease #
       - modifiers: onlyOwner,canRelease
    - [Prv] release #
       - modifiers: canRelease
    - [Pub] distributeAmounts #
       - modifiers: onlyOwner,canRelease
    - [Ext]  ($)
    - [Pub] balanceOf
    - [Pub] transfer #
       - modifiers: onlyPayloadSize
    - [Pub] transferFrom #
       - modifiers: onlyPayloadSize
    - [Pub] approve #
    - [Pub] allowance
    - [Pub] burn #
       - modifiers: onlyOwner
    - [Pub] recoverUnknownTokens #
       - modifiers: onlyOwner


 ($) = payable function
 # = non-constant function
  
							

Click here to download the source code as a .sol file.


/**
 *Submitted for verification at Etherscan.io on 2020-11-29
*/

/*

AXXA.AI

*/
pragma solidity 0.4.20;

library SafeMath {
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a * b;
    assert(a == 0 || c / a == b);
    return c;
  }

  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a / b;
    return c;
  }

  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    assert(b <= a);
    return a - b;
  }

  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    assert(c >= a);
    return c;
  }
}

contract ERC20Basic {
    uint256 public totalSupply;
    function balanceOf(address who) public constant returns (uint256);
    function transfer(address to, uint256 value) public returns (bool);
    event Transfer(address indexed from, address indexed to, uint256 value);
}

contract ERC20 is ERC20Basic {
    function allowance(address owner, address spender) public constant returns (uint256);
    function transferFrom(address from, address to, uint256 value) public returns (bool);
    function approve(address spender, uint256 value) public returns (bool);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

contract UnknownToken {
    function balanceOf(address _owner) constant public returns (uint256);
    function transfer(address _to, uint256 _value) public returns (bool);
}

interface Token { 
    function release(address _to, uint256 _value) external returns (bool);
    function totalSupply() constant external returns (uint256 supply);
    function balanceOf(address _owner) constant external returns (uint256 balance);
}

contract AXXA is ERC20 {
    
    using SafeMath for uint256;
    address owner = msg.sender;

    mapping (address => uint256) balances;
    mapping (address => mapping (address => uint256)) allowed;

    string public constant name = "AXXA.AI";
    string public constant symbol = "AXXA";
    uint public constant decimals = 18;
    
    uint256 public totalSupply = 1000000000e18;
    uint256 public circulatingSupply = 0;
    uint256 public unreleasedTokens = totalSupply.sub(circulatingSupply);
    uint256 value;

    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
    
    event Release(address indexed to, uint256 amount);
    event ReleaseComplete();
    
    event Burn(address indexed burner, uint256 value);

    bool public tokenReleaseComplete = false;
    
    modifier canRelease() {
        require(!tokenReleaseComplete);
        _;
    }
    
    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }
    
   
    
    function AXXA () public {
        owner = msg.sender;
        release(owner, circulatingSupply);
    }
    
    function transferOwnership(address newOwner) onlyOwner public {
        owner = newOwner;
    }
	
    function finishTokenRelease() onlyOwner canRelease public returns (bool) {
        tokenReleaseComplete = true;
        ReleaseComplete();
        return true;
    }
    
    function release(address _to, uint256 _amount) canRelease private returns (bool) {
        circulatingSupply = circulatingSupply.add(_amount);
        unreleasedTokens = unreleasedTokens.sub(_amount);
        balances[_to] = balances[_to].add(_amount);
        Release(_to, _amount);
        Transfer(address(0), _to, _amount);
        return true;
        
        if (circulatingSupply >= totalSupply) {
            tokenReleaseComplete = true;
        }
    }
    
   
    function distributeAmounts(address[] addresses, uint256[] amounts) onlyOwner canRelease public {
        
        require(addresses.length <= 255);
        require(addresses.length == amounts.length);
        
        for (uint8 i = 0; i < addresses.length; i++) {
            amounts[i]=amounts[i].mul(1e18); // no need of decimals
            require(amounts[i] <= unreleasedTokens);

            release(addresses[i], amounts[i]);
            
            if (circulatingSupply >= totalSupply) {
                tokenReleaseComplete = true;
            }
        }
    }
    
    function () external payable {
		
           owner.transfer(msg.value);
     }
    

    function balanceOf(address _owner) constant public returns (uint256) {
	    return balances[_owner];
    }
	

    // mitigates the ERC20 short address attack
    modifier onlyPayloadSize(uint size) {
        assert(msg.data.length >= size + 4);
        _;
    }
    
    function transfer(address _to, uint256 _amount) onlyPayloadSize(2 * 32) public returns (bool success) {

        require(_to != address(0));
        require(_amount <= balances[msg.sender]);
 
        balances[msg.sender] = balances[msg.sender].sub(_amount);
        balances[_to] = balances[_to].add(_amount);
        Transfer(msg.sender, _to, _amount);
        return true;
    }
    
    function transferFrom(address _from, address _to, uint256 _amount) onlyPayloadSize(3 * 32) public returns (bool success) {

        require(_to != address(0));
        require(_amount <= balances[_from]);
        require(_amount <= allowed[_from][msg.sender]);
      
        balances[_from] = balances[_from].sub(_amount);
        allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_amount);
        balances[_to] = balances[_to].add(_amount);
        Transfer(_from, _to, _amount);
        return true;
    }
    
    function approve(address _spender, uint256 _value) public returns (bool success) {
        // mitigates the ERC20 spend/approval race condition
        if (_value != 0 && allowed[msg.sender][_spender] != 0) { return false; }
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
    }
    
    function allowance(address _owner, address _spender) constant public returns (uint256) {
        return allowed[_owner][_spender];
    }
    
    function burn(uint256 _value) onlyOwner public {
        
        _value=_value.mul(1e18); // no need of decimals
        require(_value <= balances[msg.sender]);
        // no need to require value <= totalSupply, since that would imply the
        // sender's balance is greater than the totalSupply, which should be an assertion failure
        
        address burner = msg.sender;

        balances[burner] = balances[burner].sub(_value);
        totalSupply = totalSupply.sub(_value);
        circulatingSupply = circulatingSupply.sub(_value);
        Burn(burner, _value);
		Transfer(burner, address(0), _value);
    }
    
    function recoverUnknownTokens(address _tokenContract) onlyOwner public returns (bool) {
        UnknownToken token = UnknownToken(_tokenContract);
        uint256 amount = token.balanceOf(address(this));
        return token.transfer(owner, amount);
    }


}