Skip to content

mehulgit/TokenReportCrowdsaleContractAudit

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Token Report Crowdsale Contract Audit


Summary

Token Report intends to run a crowdsale commencing in October 2017.

Token Report's white paper can be found here.

Bok Consulting Pty Ltd was commissioned to perform an audit on the Ethereum smart contracts for Token Report's token contracts.

No potential vulnerabilities have been identified in this token contract.

There are some differences in the token contract behaviour compared to the recently finalised ERC20 token standard, but none of these are significant.


Token Contract

The token contract consist of Token, Controller and Ledger contracts working together. Funds collected during the crowdsale will be used to calculate the token balances in this token contract, and the token balances will be minted in this token contract by an external program executing the Ledger.multiMint(...) function. Once the minting is completed, the Ledger.stopMinting() function is execute to prevent any further token minting.

The source code for this audit have been extracted from the verified source code on EtherScan:

Note that source code is exactly the same in each of these three source code files, as expected.

Together, the contracts provide the general functionality required of an ERC20 Token Standard token. There are some slight difference in behaviour compared to this recently (Sep 11 2017) finalised standard and these differences are listed below:

  • Token.transfer(...) returns false if there are insufficient tokens to transfer. In the recently finalised ERC20 token standard:

    The function SHOULD throw if the _from account balance does not have enough tokens to spend.

    Token.transfer(...) returns false as required under the previous un-finalised version of the ERC20 token standard

  • Token.transferFrom(...) returns false if there are insufficient tokens to transfer or insufficient tokens have been approved for transfer. In the recently finalised ERC20 token standard:

    The function SHOULD throw unless the _from account has deliberately authorized the sender of the message via some mechanism

    Token.transferFrom(...) returns false as required under the previous un-finalised version of the ERC20 token standard

  • Token.approve(...) requires that a non-0 approval limit be set to 0 before being modified to another non-0 approval limit. In the recently finalised ERC20 token standard:

    ... 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 compatilibilty with contracts deployed before

    Token.approve(...) implements the requirement to set a non-0 approval limit to 0 before modifying the limit to another non-0 approval limit that was a standard practice for ERC20 tokens before the recent ERC20 token standard was finalised

  • Token.transfer(...), Token.approve(...) and Token.transferFrom(...) all implement the onlyPayloadSize(...) check that was recently relatively common in ERC20 token contracts, but has now been generally discontinued as it was found to be ineffective. See Smart Contract Short Address Attack Mitigation Failure for further information. The version used in the Token contract checks for a minimum payload size (using the >= operator) and should not cause any problems with multisig wallets as documented in the link.

None of the differences above are significant to the workings of an ERC20 token.


Note

  • Transfers in the Token contract can be paused and un-paused by the token contract owner, at any time

  • The owner of the Token, Controller and Ledger contracts can use the setToken(...), setController(...) and setLedger(...) functions to bypass the intended permissioning in this system of contracts and execute some of the functions with irregular operations. As an example, the owner of Ledger can call setController({owner account}) and then execute burn(...) to burn the tokens of any account



Table Of Contents



Potential Vulnerabilities

No potential vulnerabilities have been identified in this token contract.



Scope

This audit is into the technical aspects of the token contract. The aim of this audit is to ensure that token balances and transfers cannot easily be attacked or stolen by third parties. This audit does not guarantee that that the code is bugfree, but intends to highlight any areas of weaknesses.



Testing

The following functions were tested using the script test/01_test1.sh with the summary results saved in test/test1results.txt and the detailed output saved in test/test1output.txt:

  • Deploy Token, Controller and Ledger contracts
  • Stitch the Token, Controller and Ledger contracts together
  • Mint tokens
  • Switch off minting
  • Execute transfer(...), approve(...) and transferFrom(...) of tokens
  • Execute invalid transfer(...), approve(...) and transferFrom(...) of tokens
  • Execute transfer(...), approve(...) and transferFrom(...) of 0 tokens


Code Review

  • code-review/Token.md
    • contract SafeMath
    • contract Owned
    • contract Pausable is Owned
    • contract Finalizable is Owned
    • contract IToken
    • contract TokenReceivable is Owned
    • contract EventDefinitions
    • contract Token is Finalizable, TokenReceivable, SafeMath, EventDefinitions, Pausable
    • contract Controller is Owned, Finalizable
    • contract Ledger is Owned, SafeMath, Finalizable

Check On Calls And Permissions

This section looks across the permissions required to execute the non-constant functions in these set of contracts.

General Functions

All three main contracts Token, Controller and Ledger are derived from Finalizable which is derived from Owned. They all implement Finalizable.finalize() that can only be called by the owner. They also implement Owned.changeOwner(...) that can only be called by owner, and Owned.acceptOwnership() that can only be called by the new intended owner.


Token Specific Functions

  • Token additionally is derived from TokenReceivable that implements TokenReceivable.claimTokens(...) and this can only be called owner

  • Token.setController(...) can only be called by owner

  • Token.controllerApprove(...) can only be called by Controller. As Controller does not have any functions to call Token.controllerApprove(...), this function is redundant


Controller Specific Functions

  • Controller has a Controller.setToken(...) and Controller.setLedger(...) that can only be called by owner

Ledger Specific Functions

  • Ledger.multiMint(...) can only be called by owner

    • -> Contoller.ledgerTransfer(...) that can only be called by Ledger
      • -> Token.controllerTransfer(...) that can only be called by Controller
  • Ledger has a Ledger.setController(...) and a Ledger.stopMinting(...) that can only be called by owner


Transfer And Other Functions That Can Be Called By Any Account

Following are the Token functions that can be executed by any account

  • Token.transfer(...)

    • -> Controller.transfer(...) that can only be called by Token
      • -> Ledger.transfer(...) that can only be called by Controller
  • Token.transferFrom(...)

    • -> Controller.transferFrom(...) that can only be called by Token
      • -> Ledger.transferFrom(...) that can only be called by Controller
  • Token.approve(...)

    • -> Controller.approve(...) that can only be called by Token
      • -> Ledger.approve(...) that can only be called by Controller
  • Token.increaseApproval(...)

    • -> Controller.increaseApproval(...) that can only be called by Token
      • -> Ledger.increaseApproval(...) that can only be called by Controller
  • Token.decreaseApproval(...)

    • -> Controller.decreaseApproval(...) that can only be called by Token
      • -> Ledger.decreaseApproval(...) that can only be called by Controller
  • Token.burn(...)

    • -> Controller.burn(...) that can only be called by Token
      • -> Ledger.burn(...) that can only be called by Controller

Each of the Token functions listed above can be executed by any account, but will only apply to the token balances the particular account has the permission to operate on.



(c) BokkyPooBah / Bok Consulting Pty Ltd for Token Report - Oct 18 2017. The MIT Licence.

About

Token Report Crowdsale Contract Audit

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Shell 56.3%
  • JavaScript 43.7%