Skip links
dm token logo

DMToken Token Sale Smart Contract Audit

Coinfabrik was hired to audit the contract in terms of its security. First of all, we will analyze the code and deliver a summary of the reviewed contract. After evaluating the contract, we will write a detailed description of our discoveries and proposed changes, followed by the conclusion.

The audited contract is from the DMarket token repository at https://github.com/suntechsoft/dmarket-smartcontract.git, it was based on the commit 3211829f8d5b24098e5134e5e1a54df07c219e30, and updated to commit 48092bfa825ab92d0c6d2867776dd6f1b6b26fa7.

Summary

The audited contracts are:

  • contracts/v0.3/DMToken.sol: An ERC-20 compatible token

From their description:

Cryptocurrency for trading any virtual in-game items on any platform globally.

We found the contract well written and easy to follow. We checked it against the latest known vulnerabilities and found the contract to be adequately protected and secure.

We made a couple of suggestions not related to the security of the contract. They were enhancements for particular uses, or to mitigate user errors.

Detailed findings

Minor severity

Verification missing

The function currentPar can be called with an invalid start value of token vesting: a block number higher than the current block. This would cause it to return an erroneous value.

  function currentPart(address _address) private constant returns (uint256) {

      if (vestingMembers[_address].totalSum == 0) {

          return 0;
      }
      if (block.number >= vestingMembers[_address].end) {

          return vestingMembers[_address].totalSum.sub(vestingMembers[_address].usedAmount);
      }

      return vestingMembers[_address].totalSum

      .mul(block.number - vestingMembers[_address].start)

      .div(vestingMembers[_address].end - vestingMembers[_address].start)

      .sub(vestingMembers[_address].usedAmount);
   }

The possible impact is very minimal; only the owner can add a vesting token with an invalid start date.  We suggest to add a check and return if the start is after the current block number.

  function currentPart(address _address) private constant returns (uint256) {

      ..

      if (block.number <= vestingMembers[_address].start)  {

          return 0;

      }

This item was fixed at commit 9544d63c3a86c8ca5c60fb83a68cf11926aea22a.

Enhancements

Protection for unintended transfer of tokens

The contract DMToken will allow public interaction with any user so we suggest for it be protected for accidental transfer of tokens.

Solidity since last year has protection against unintended transfer of ether. But there’s no protection against unintentional transfer of tokens. This problem has caused serious losses because contracts were not prepared to refund arbitrary tokens leaving them inaccessible.

We recommend implementing a simple mechanism that allows the contract’s owner to refund unintentionally sent arbitrary tokens.

   function refundTokens(address _token, address _refund, uint _value) onlyOwner {

       require(_token != this);

       ERC20 token = ERC20(_token);

       token.transfer(_refund, _value);

       RefundTokens(_token, _refund, _value);

   }

Unnecessary check of balance

In the function multiTransfer, there is a check to ensure the sender has enough funds to make all the transfers. In the more common case of the sender having enough funds, it adds an unnecessary extra cost since transfer also checks if the sender has enough funds, and it will revert the whole transaction when there are not enough funds.

  function multiTransfer(address[] recipients, uint256[] amounts) public onlyOwner {
      require(recipients.length == amounts.length);
      for (i = 0; i < recipients.length; i++) {
          require(recipients[i] != address(0));
          require(transfer(recipients[i], amounts[i]));
      }
   }

Similarly the multiVesting function has an additional check that is not necessary in the more common case the sender has enough funds.

This enhancement was applied in commit 9544d63c3a86c8ca5c60fb83a68cf11926aea22a.

Observations

  • The contract uses the constant modifier, this has been deprecated in new versions of the solidity compiler for pure and view modifiers. Currently it generates a warning but the code compiles without issues.

    In future versions of the compiler this modifier will be removed. We suggest to consider using view and pure modifiers in future versions of the contract.

Conclusion

We only found a minor issue regarding an arithmetic operation that could cause problems. This issue was fixed promptly during the course of the audit.

Otherwise, the contract is secure without any known vulnerabilities.

Do you want to know what is Coinfabrik Auditing Process?

Check our A-Z Smart Contract Audit Guide or you could request a quote for your project.