Skip to content

Instantly share code, notes, and snippets.

@yuriy77k
Last active June 1, 2018 09:22
Show Gist options
  • Save yuriy77k/dda904edb173bb2794843d13944d6846 to your computer and use it in GitHub Desktop.
Save yuriy77k/dda904edb173bb2794843d13944d6846 to your computer and use it in GitHub Desktop.
ETC TokenMint audit report

ETC TokenMint audit report.

Summary

This is the report from a security audit performed on ETC TokenMint by yuriy77k.

TokenMint is a service that offers to launch an ICO and deploy a custom token contract easily.

In scope

Smart-contracts at this repo: https://github.com/ethereumproject/TokenMint/tree/master/contracts

  1. https://github.com/ethereumproject/TokenMint/blob/master/contracts/metaTokenmint.sol (commit hash: d6409c1)
  2. https://github.com/ethereumproject/TokenMint/blob/master/contracts/registry.sol (commit hash: 32a7f1a)
  3. https://github.com/ethereumproject/TokenMint/blob/master/contracts/deployed/crowdsale.sol (commit hash: 1fe1f58)
  4. https://github.com/ethereumproject/TokenMint/blob/master/contracts/deployed/icoMachine.sol (commit hash: 035c918)
  5. https://github.com/ethereumproject/TokenMint/blob/master/contracts/deployed/manReg.sol (commit hash: 0d8d839)

Excluded

  1. https://github.com/ethereumproject/TokenMint/blob/master/contracts/deployed/ERC223.sol
  2. https://github.com/ethereumproject/TokenMint/blob/master/contracts/deployed/safeMath.sol

Findings

In total, 17 issues were reported including:

  • 6 high severity issues.

  • 6 medium severity issues.

  • 3 low severity issues.

  • 2 minor observation.

Security issues

Issues for metaTokenmint.sol.

1. Admin have not access to functions with onlyAdmin modifier.

Severity: medium

Description

The modifier onlyAdmin use an uninitialized variable aCount to enumerate adminList. In this case it always exit without execution a function code.

Recommendation

Change the implementation of onlyAdmin modifier.

2. Anyone could access to functions with onlyAdmin modifier.

Severity: high

Description

This condition run the function code all time when caller in not admin.

In case of the issue 1 this issue does not work, but it will if fix the issue 1.

Recommendation

Change the implementation to if (adminCheck == 1){_;} and move it out of for() {} body.

3. Contract owner can modify existing admin address instead of adding new.

Severity: medium

Description

The function modAdmin not correct add new admin after deleting one.

For example, there are 2 admins: adminList[1].adminAddr = 1..., adminList[2].adminAddr = 2..., adminCount = 2.

After deleting first admin, we get: adminList[2].adminAddr = 2..., adminCount = 1.

And now if add new admin with address 3..., we get: adminList[2].adminAddr = 3..., adminCount = 2.

So admin 2 was replaced with admin 3, and we get only one active admin in the list instead of two.

Recommendation

Change the implementation of modAdmin function. Notice, that delete just remove records from storage, but not make reindexing.

Issues for registry.sol.

4. Too much variables caused Remix compiler error.

Severity: minor observation

Description

The definitions of struct Token of registry.sol contract made the Remix compiler unable of generating bytecode of the contract.

This is not a security issue, but a code flaw. This can not affect a deployed contract, but this made compiler behave in unintended way. This hurts contract's reusability property as well.

Recommendation

Change the implementation of registry.sol.

5. Anyone except owner can run functions wiht onlyOwner modifier.

Severity: high

Description

Modifier onlyOwner run the function code if caller is not owner.

Recommendation

Change the implementation of condition to: if (msg.sender == owner) {

or change the implementation of whole modifier onlyOwner to this one.

6. Anyone can add a token to the registry when didn't pay the price.

Severity: medium

Description

The function register has the modifier costs which works in other way, as planned. It run the function code when price was not paid.

Recommendation

Change the implementation of condition in the modifier costs to:

if (msg.value < price)
    throw;
_;

7. Contract owner can modify existing admin address instead of adding new.

Severity: medium

Description

The function modAdmin not correct add new admin after deleting one.

This issue similar with issue 3.

Recommendation

Change the implementation of modAdmin function. Notice, that delete just remove records from storage, but not make reindexing.

8. Contract owner can overflow adminCount variable.

Severity: low

Description

The function modAdmin allow contract owner to overflow adminCount variable when adding more then 256 admins.

Recommendation

Change type of variable adminCount from uint8 to uint and in linked places (mapping and the variable i.

9. Anyone could access to functions with onlyAdmin modifier.

Severity: high

Description

This condition run function code when caller in not admin.

Recommendation

Change the implementation to if (adminCheck) {.

Issues for crowdsale.sol.

10. The user will not receive a full payment withdraw if he made several purchases.

Severity: high

Description

The function safeWithdrawal alow an user to make withdraw his payment when funding goal is not reached.

When user buy tokens, his original payment value stored in the array balanceOf. But when same user make more then one payment, the next payment replace previous value in that array (in functions () and buyTokens). So when user make withdraw, he withdrow only last payment, but not all the amount that he paid.

Recommendation

Change the implementation in the function () to balanceOf[msg.sender] += amount; and in the function buyTokens to balanceOf[buyer] += amount;.

11. User can withdraw his payment, but bought tokens remain in his account.

Severity: HIGH

Description

If an user call function safeWithdrawal when funding goal is not reached, he received back his payment, but bought tokens remain in his account.

Recommendation

Implement the return of tokens from the user to the crowdsale address.

12. The beneficiary will not receive money if someone has made a withdrawal before.

Severity: high

Description

When funding goal reached, the beneficiary will not receive money if someone has made a withdrawal before, because the value of variable amountRaised will be bigger then current contract balance.

Recommendation

Implement in the function safeWithdrawal decrease value of variable amountRaised on withdrawal amount. For example, add amountRaised -= amount; after this row and add amountRaised += amount; after this row.

Issues for icoMachine.sol.

13. The crowdsale address may be lost.

Severity: low

Description

If the token creator call the function createSale more then one time, it replace original crowdsale address in the Ico struct to the new crowdsale address with no tokens on it (all tokens moved only on the first crowdsale address).

Recommendation

Implement checking that crowdsale address was added. For example, add assert(tokens[msg.sender][index].saleAddress == 0x0); after this string.

Issues for manReg.sol.

14. Unused variable.

Severity: minor observation

Description

The variable choice unused in this project. This is not a security issue, but a code flaw. This can not affect a deployed contract.

Recommendation

Delete this variable.

15. Contract owner can modify existing admin address instead of adding new.

Severity: medium

Description

The function modAdmin not correct add the new admin after deleting one.

This issue similar with issue 3.

Recommendation

Change the implementation of modAdmin function. Notice, that delete just remove records from storage, but not make reindexing.

16. Contract owner can overflow adminCount variable.

Severity: low

Description

The function modAdmin allow to the contract owner to overflow adminCount variable when adding more then 256 admins.

Recommendation

Change type of the variable adminCount from uint8 to uint and argument uint8 _index to uint _index.

17. Admin have not access to functions with onlyAdmin modifier.

Severity: medium

Description

The modifier onlyAdmin use an uninitialized variable aCount to enumerate adminList. In this case it always exit without execution the function code.

Also if (adminCheck != 1){throw; _;} conditon never run function code.

Recommendation

Change the implementation of the onlyAdmin modifier.

Conclusion

This project has the several identical contracts (owned, priced) and I would recommend to write them in a separate .sol file and import it where necessary.

The functions in the files metaTokenmint.sol , registry.sol, manReg.sol are very similar, and I would recommend merging them into the one contract. Also pay attention to the variable price (registry.sol and manReg.sol). In the comments it is stated that the price is in ethers, although in the contract it is used as the price in the Wei. This can cause misunderstanding when the contract is used.

6 critical vulnerabilities were detected.

Smart-contract must be fixed before launch.

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