Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save yuriy77k/05b3feee64c2b73be4fdbac74d4421d4 to your computer and use it in GitHub Desktop.
Save yuriy77k/05b3feee64c2b73be4fdbac74d4421d4 to your computer and use it in GitHub Desktop.

UNUS SED LEO audit report.

1. Summary

This document is a security audit report performed by danbogd, where UNUS SED LEO has been reviewed.

2. In scope

Сommit hash .

or

3. Findings

In total, 7 issues were reported including:

  • 1 medium severity issues
  • 3 low severity issues
  • 3 owner privileges (ability of owner to manipulate contract, may be risky for investors)..
  • 0 notes.

No critical security issues were found.

3.1 Out of Gas

Severity: medium

Description

Even if a view function does not need ether for execution when it is called externaly, developers should think about implementing loops inside such functions. Still, such functions may be called by other function as part of on-chain operations and stall those.

In this implementation if the value of checkpoints.length of the function getValueAt will be very large the transfer functions can lead to "Out of Gas" error or to "Block Gas Limit".

Code snippet

LEO_token.sol, line 508.

    function getValueAt(Checkpoint[] storage checkpoints, uint _block
    ) view internal returns (uint) {
    if (checkpoints.length == 0) return 0;

    // Shortcut for the actual value
    if (_block >= checkpoints[checkpoints.length-1].fromBlock)
        return checkpoints[checkpoints.length-1].value;
    if (_block < checkpoints[0].fromBlock) return 0;

    // Binary search of the value in the array
    uint min = 0;
    uint max = checkpoints.length-1;
    uint mid = 0;
    while (max > min) {
        mid = (max + min + 1)/ 2;
        if (checkpoints[mid].fromBlock<=_block) {
            min = mid;
        } else {
            max = mid-1;
        }
    }
    return checkpoints[min].value;
    }

3.2. Allowance Approval

Severity: low

Description

Following ERC-20 final description:

"NOTE: To prevent attack vectors like the one described here and discussed here, clients SHOULD make sure to create user interfaces in such a way that they set the allowance first to 0 before setting it to another value for the same spender. THOUGH The contract itself shouldn't enforce it, to allow backwards compatibility with contracts deployed before.

Do not throw in case if the following condition is true require((_amount == 0) || (_allowances[msg.sender][spender] == 0)) and return false, users might not notice that the changes didn't occur, and external contract calls to this function will highlight many other issues.

Code snippet

LEO_token.sol, line 302.

    function approve(address _spender, uint256 _amount) public returns (bool success) {
    require(transfersEnabled);

    require((_amount == 0) || (allowed[msg.sender][_spender] == 0));

    if (isContract(controller)) {
    require(TokenController(controller).onApprove(msg.sender, _spender, _amount));
    }

    allowed[msg.sender][_spender] = _amount;
    emit Approval(msg.sender, _spender, _amount);
    return true;
    }

3.3. No checking for zero address

Severity: low

Description

Incoming addresses should be checked for an empty value(0x0 address) to avoid loss of funds or blocking some functionality.

Code snippet

LEO_token.sol, line 76.

    function changeController(address _newController) public onlyController {
    emit ControlTransferred(controller, _newController);
    controller = _newController;
    }

3.4. Known vulnerabilities of ERC-20 token

Severity: low

Description

  1. It is possible to double withdrawal attack. More details here.

  2. Lack of transaction handling mechanism issue. WARNING! This is a very common issue and it already caused millions of dollars losses for lots of token users! More details here.

Recommendation

Add into a function transfer(address _to, ... ) following code:

require( _to != address(this) );

3.5. Owner Privileges

Severity: owner previliges

Description

Contract owner allow himself to:

enable/disable transfer, transferFrom, approve functions

LEO_token.sol, line 496. function enableTransfers(bool _transfersEnabled) public onlyController { transfersEnabled = _transfersEnabled; }

  • upgrade contract and implement any logic in the new contract. And even if the new contract will be audited, at any time possible to change the address of the new contract again to not audited and insecure.

LEO_token.sol, line 698.

    function upgradeController(address _newControllerAddress) public onlyOwner {
    tokenContract.changeController(_newControllerAddress);
    emit UpgradedController(_newControllerAddress);
}
  • evacuate all users tokens on owner account.

LEO_token.sol, line 719.

    function claimLostTokens(address payable _token) public onlyOwner {
    LEO token = LEO(_token);
    uint balance = token.balanceOf(address(this));
    token.transfer(owner, balance);
    emit ClaimedTokens(_token, owner, balance);
    }

4. Conclusion

The review did not show any critical issues, some of medium and low severity issues were found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment