Specifications of a contract
- A flat pricing with ETH: USD - $0.02 per token (50 tokens to 1 USD)
- Coin rate should be $0.02 (can just use the live feed from www.oraclize.it or similar)
- Token supply: 1 billion, selling 150 million e.g. $3M cap.
- Token: 8 decimals
- Multisig wallet for the proceeds, as per gnosis (as that doesn't seem to have had any issues vs. parity)
- Ensure tokens are reserved and allocated by a certain date when they unlock to subscribers
- No ETH cap: Anyone can buy as many tokens as they like until all tokens are sold
- Sale ends when 150m tokens (out of 1bn) allocated to contract run out or a certain date is reached
- Ideally the smart contract should verify in etherscan and fit into the token tracker
- There will be no whitelisting of investors and no hard/soft cap.
- There will be no refund
Crowdsale code is audited against above specifications. AllocatedCrowdsale.sol is considered as a root for the crowdsale so audit covers only following files:
Few contracts are imported from zeppline-solidity so commit
8e01dd1of zeppelin is used in audit.
1. Unit tests
No unit test are provided which is a big red flag. I will recommend to write unit test and use of truffle.
2. Redundant code
Some unnecessary code is found that is not required according the specs so I will recommend to remove this to minimizing the contract size.
- No Time Period for crowdsale
Crowdsale will be open until all the tokens are not sold and their is no ether cap so following line of codes are unnecessary.
- No refund
There will be no refund in the crowdsale so following lines are unnecessary.
- No whitelisting
Anonymous investments will be acceptable so following lines of code can be removed.
- Unused variables
- Remove unused variables from
- Remove unused variables from
After removing redundant code following corrections are required:
_baseEthCapfrom constructor parameter list of Crowdsale.sol and AllocatedCrowdsale.sol.
investInternal(address receiver, uint128 customerId)to
buy(address receiver)and make it public
event Invested(address investor, uint weiAmount, uint tokenAmount, uint128 customerId)to
event Invested(address investor, uint weiAmount, uint tokenAmount)
PreFundingState from the Crowdsale.sol
- Modify check condition of
State.Successin Crowdsale.sol:538 to depends upon amount of token sold instead of minimum funding.
4. Calculation Error
calculatePrice() in FlatPricing does not calculate right price because of invalid
multiplier value. Total decimal points in ether are 18 so we have to devide by
10 ** 10 instead of
10 ** 8.
5. Following preconditions and sanity checks are missing
- At Crowdsale.sol constructor parameter
- At AllocatedCrowdsale.sol constructor parameter
- Restrict accessibility to external for the following functions
- Use of wallet
Software wallets have pretty bad history so I would recommend hardware wallet. Multisig is secure until there is no bug in code but hardware wallet will always require physical interaction to initiate transaction.
One critical issue found regarding calculation mentioned in section 4. Crowdsale can go into invalid state or even unrecoverable state due to the absence of sanity checks at function arguments explained in section 5. Redundant code found that increases size of the contract so its a waste of gas(ethers). Right now contract is not complete according to the specs so after implementation of above changes please test it again.