EthereumCommonwealth / Auditing

Ethereum Commonwealth Security Department conducted over 400 security audits since 2018. Not even a single contract that we audited was hacked. You can access our audit reports in the ISSUES of this repo. We are accepting new audit requests.
https://audits.callisto.network/
GNU General Public License v3.0
131 stars 34 forks source link

W12 platform #67

Closed yuriy77k closed 6 years ago

yuriy77k commented 6 years ago

Audit request

A service has been developed for the release and sale of ICO tokens and for charity projects (ERC-20 on Ethereum). The project has the ability to sell all or only part of the issued tokens using the W12 platform. The main goal of the service is to increase transparency, increase trust between the parties and reduce risks arising from the financing of projects. After the end of each stage of the roadmap, the buyer of the tokens can take advantage of the opportunity to return their funds remaining in the project fund (if it considers that the project does not fulfill its obligations). The project funds are issued in parts after the end of the roadmap stage and the time allotted for the return of funds by the buyers of the tokens. Detailed description https://docs.google.com/document/d/1tEMEhHRREhJVKLYn-K2_83hLe2KQYvJUb2gA6r361JY/edit?usp=sharing Bounty W12 (code audit) https://w12.io/bounty-w12/section/5/

Source code

https://github.com/w12-platform/W12-Product-Blockchain-Protocol

Disclosure policy

andrey@w12.io

Platform

ETH

Complexity

High

yuriy77k commented 6 years ago

You could follow the audit queue there: https://github.com/EthereumCommonwealth/Auditing/blob/master/queue.md

RideSolo commented 6 years ago

Auditing time: ~ 7 days.

yuriy77k commented 6 years ago

@RideSolo assigned.

gorbunovperm commented 6 years ago

Estimated auditing time is 7 days.

yuriy77k commented 6 years ago

@gorbunovperm assigned

MrCrambo commented 6 years ago

Auditing time 7 days.

yuriy77k commented 6 years ago

@MrCrambo assigned

gorbunovperm commented 6 years ago

My report is finished.

yuriy77k commented 6 years ago

The contract contains high severity security issue. The report was sent to the developer.

yuriy77k commented 6 years ago

@MrCrambo Notes about you report:

yuriy77k commented 5 years ago

1. Summary

W12 Project security audit report performed by Callisto Security Audit Department

2. In scope

3. Findings

12 issues were reported including:

3.1. Refund Logic

Severity: High

Description

Without correction of the Refund logic any user will be able to be refunded a higher amount of ether than what he bought, making the last investors to call refund, lose their ether.

Each call to getRefundAmount will recalculate the average price of the tokens bought by the investor (following the ether left in the contract since tranche can withdraw some ether after every milestone reached) and multiply it by the amount of tokens to be refunded.

getRefundAmount function description do not match the implemented code (if this is not corrected the investor will be refunded more than what is expected), as shown below c is first multiplied by a than divided by b but the implemented code show the opposite:

    /**
        a = address(this).balance
        b = totalFunded
        c = buyers[buyer].totalFunded
        d = buyers[buyer].totalBought
        e = wtokensToRefund

        ( ( c * (a / b) ) / d ) * e = (refund amount)
    */
    uint allowedFund = buyers[buyer].totalFunded.mul(totalFunded).div(address(this).balance);

If the above issue is taken into consideration and changed, investors should be aware that the refund function is dependent on the remaining ether balance of the contract. In other terms the transactions order of investors calling refund or if tranche is called by the owner will impact the refund value of every investor.

The formula present a ratio of the total ethereum invested by a user divided by the total ethereum collected at the moment of the call of the function multiplied by the contract balance, since the contract balance will change after every call, the refund value of a user that will call refund after will be affected. Please note that the same issue can be applied to tranche function.

Another remark is with this logic the contract if the ICO fail and all users call refund, the contract will always have ether stuck in it.

The dependence can be easily avoided if the developers set a fixed amount to be redistributed to the investors and not use address(this).balance.

Code snippet

https://github.com/w12-platform/W12-Product-Blockchain-Protocol/blob/master/contracts/W12Fund.sol#L92#L115

https://github.com/w12-platform/W12-Product-Blockchain-Protocol/blob/master/contracts/W12Fund.sol#L192#L217

3.2. Tranche Requirement

Severity: low

Description

The white paper describe tranche function to allow the project to receive funds for each stage of the Roadmap, before the start of the sale of tokens:

"The project receives installments at the end of each stage of the Roadmap. For each stage of the Roadmap, before the start of the sale of tokens, the project specifies the% of the funds that it can receive, and the date from which it is possible to request these funds."

However tranche function is allowed to execute following the milestones not the stages.

Code snippet

https://github.com/w12-platform/W12-Product-Blockchain-Protocol/blob/master/contracts/W12Fund.sol#L230#L241

3.3. Token Exchanger

Severity: medium

Description

addTokenToListing member of TokenExchanger contract pairs tokens to be exchanged in a 1:1 ratio only following TokenExchanger contract logic.

If an ERC20 or WToken address is paired with different addresses, the value of listingTokenToWToken[token](if the same token address is paired more than once) and listingWTokenToToken[wToken](if the same wToken address is paired more than once) will be overwritten since hasPair(token, wToken) will return false even if one of the addresses was used before, consequences:

Code snippet

https://github.com/w12-platform/W12-Product-Blockchain-Protocol/blob/master/contracts/token/exchanger/TokenExchanger.sol#L24#L33

https://github.com/w12-platform/W12-Product-Blockchain-Protocol/blob/master/contracts/token/exchanger/TokenExchanger.sol#L35#L37

https://github.com/w12-platform/W12-Product-Blockchain-Protocol/blob/master/contracts/token/exchanger/TokenExchanger.sol#L45#L49

https://github.com/w12-platform/W12-Product-Blockchain-Protocol/blob/master/contracts/token/exchanger/TokenExchanger.sol#L45#L49

https://github.com/w12-platform/W12-Product-Blockchain-Protocol/blob/master/contracts/token/exchanger/TokenExchanger.sol#L55#L67

3.4. Pricer Removing

Severity: medium

Description

removePricer function member of PricerRole can be called by anyone and remove all addresses allowed with onlyPricer modifier, no access restriction is set. Depending in the further use of PricerRole contract, the impact can vary widely.

Code snippet

https://github.com/w12-platform/W12-Product-Blockchain-Protocol/blob/master/contracts/rates/roles/Pricer.sol#L30#L32

3.5. Symbols Contract

Severity: medium

Description

Code snippet

https://github.com/w12-platform/W12-Product-Blockchain-Protocol/blob/master/contracts/rates/Symbols.sol#L16#L22

https://github.com/w12-platform/W12-Product-Blockchain-Protocol/blob/master/contracts/rates/Symbols.sol#L32#L40

Recommendation

    function _removeSymbolByIndex(uint index) internal {
        require(index < symbolsList.length);

        if (index != symbolsList.length - 1) {
            symbolsList[index] = symbolsList[symbolsList.length - 1];
        // -- Add the following to update the index of the last symbol -- //
        symbolIndex[symbolsList[index]] = index;
        delete symbolsList[symbolsList.length - 1];
        }
    else delete symbolsList[index];
    // --------------------- END RECOMMENDATION --------------------- //

        symbolsList.length--;
    }

3.6. Zero Address

Severity: low

Description

setVersion function member of VersionsLedger contract do not require _address input parameters to be different than zero address.

Code snippet

https://github.com/w12-platform/W12-Product-Blockchain-Protocol/blob/master/contracts/versioning/VersionsLedger.sol#L15#L25

3.7. 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

Code snippet

https://github.com/w12-platform/W12-Product-Blockchain-Protocol/blob/master/contracts/token/WToken.sol

3.8. Possibility of increasing Tokens amount.

Severity: low

Description

In WhitePaper at page 48 there written, that tokens amount are limited and can not be increased, but smart contract has mint() function and trusted people can mint, also owner can add trusted people.

Code snippet

https://github.com/w12-platform/W12-Product-Blockchain-Protocol/blob/c81ef801315eb4a2535e4fc072a37b42d5b18e9d/contracts/token/WToken.sol#L164-L177

Recommendation

There should be no possibility of minting extra tokens, because in whitepaper there written that tokens amount are limited and fixed.

3.9. It is possible for trusted address to call vestingTransfer function with zero _value.

Severity: low

Code snippet

Description

The _value parameter is not checked for a zero value. In case if _value is zero the condition in line 182 will be true and a vesting time will be added to vestingTimes array each call of vestingTransfer function with zero of _value parameter. Thus, duplicate values will be accumulated in the vestingTimes array.

And if after zero value vestingTransfer will be transfer with positive value, then accountBalance function will not work correctly. For each duplicated vestingTime the balance will be subtracted.

It can happen by accident or maliciously.

Recommendation

Use check for zero value of _value parameter. Or check for duplicates in vestingTimes array.

3.10. TODO comments left.

Severity: minor observation

Description

TODO comment left in code.

3.11. Modifier has no sense.

Severity: minor observation

Description

Modifier onlyFrom allows everyone and can be deleted and not used.

3.12. No need of checking.

Severity: minor observation

Description

Checking has no sense, because SafeMath library will do it automatically.

4. Conclusion

The audited contracts contain different severity level issues that need to be fixed before deployment including a high severity.

5. Revealing audit reports

https://gist.github.com/yuriy77k/9bebeab10b57be632c6aa5592c5060af

https://gist.github.com/yuriy77k/0ac2e633c833e87abcb466807df21aec

https://gist.github.com/yuriy77k/430045c0823ecadacf952720cb62dda9