This document is a follow-up report about the Bancor protocol crowdsale contracts, which have been audited by Martin Holst Swende on behalf of Dyno Security AB. During the development process, there have been three preliminary reports with potential issues, which have been addressed during the course of development, and a final report, available here.
This is the fifth document, to follow up on changes since the final report.
Based on the audit, we estimate the risk level of the Bancor crowdsale contract(s) to be Low. The security of all funds reside heavily on the security surrounding the beneficiary account, which is outside the scope of the audit, and is assumed to be a very secure multisig wallet.
This follow-up report covers the contracts central to the Bancor crowdsale, and is part of a larger audit covering all Bancor contracts. This follow-report was performed on commit hash 715bdde572c540297ce4fc6b46b1ed2b85f55bdc of the contracts on https://github.com/bancorprotocol/contracts .
This security audit has focused on vulnerabilities which could have a negative impact on crowdsale beneficiaries and users interacting with the crowdsale.
Since the last report, the crowdsale is inheritance structure has been modified. The following are the central contracts for the crowdsale:
- CrowdsaleController
- is SmartTokenController
- is TokenHolder
- is Owned
- is IOwned
- is Owned
- is TokenHolder
- is SafeMath
- is SmartTokenController
The CrowdsaleController is the main contract responsible for crowdsale. The purpose is to accept payments in various pre-specified assets, issue tokens and track contributions.
The EtherToken has been removed from the crowdsale, since the last report. Ether is now directly transferred to the beneficiary. This reduces the overall complexity of the crowdsale implementation.
- SmartToken
- is ISmartToken
- is ITokenHolder
- is IERC20Token
- is ERC20Token
- is IERC20Token
- is SafeMath
- is Owned
- is IOwned
- is TokenHolder
- is Owned
- is IOwned
- is Owned
- is ISmartToken
The SmartToken is a somewhat special ERC20Token implementation, which destroys tokens sent to itself. This is the 'native' tokens issued by the crowdsale.
The tokenOwner has high privileges within both contracts (CrowdsaleController/SmartToken). If the ownership of SmartToken can be subverted or lost, impact would be high. Risks are mitigated through
ownerOnlycan set anewOwner, which is not effectual untilnewOwnerperforms a call toacceptOwnership()
After these two steps, it is certain that the old owner initiated the transfer, and that someone holds a key that can perform contract invocations from the new address.
Since the last report, the controller has been removed, and there's now only the concept of owner.
Only the token owner can call the following CrowdsaleController methods
CrowdsaleController.enableRealCapSmartTokenController.transferTokenOwnershipSmartTokenController.acceptTokenOwnershipSmartTokenController.disableTokenTransfersSmartTokenController.issueTokensSmartTokenController.destroyTokensSmartTokenController.withdrawFromTokenTokenHolder.withdrawTokens
These findings were submitted in previous reports
- Medium: Possibility for lost funds (SmartToken/EtherToken)
- Fixed via
TokenHolderparent
- Fixed via
- Medium: Missing protection against user errors
- Fixed via modifier
isValidAddressin ERC20Token.sol
- Fixed via modifier
- Low:: SmartToken - possible to issue to
this- Fixed
- Low: Potential uninitailized variable (CrowdSaleChanger)
- fixed
- Low: Not possible to unset
changer(BancorChanger, CrowdsaleChanger)- fixed
- Info: ERC20Token, EtherToken, BancorToken,SmartToken - Interface ambiguity
- Fixed via updated documentation
- Info: BancorToken - missing reserve cap
- N/A (BancorToken removed)
- Info: BancorToken - withdraw
- N/A (BancorToken removed)
- Info: BancorToken - CRR configuration not changeable during setup
- N/A (BancorToken removed)
- Info: SmartToken - central point of ownership
- feature - still present
- Info: Returnvalus not used
- fixed
- Info:
constantmethods accessingmsg.sender(BancorChanger)- fixed
- Info : Unused code
- fixed, code removed
- Info : Hidden cap
- Not a security issue - not obligatory to reveal hidden cap