The Hard Cap Issue: Technical Explanation

uint256 public softCap;

uint256 public hardCap;

uint32 public capFlex;

Let us now discard the soft cap and focus purely on the problematic hard cap. We check whether the hard cap has been reached with the following method, again taken verbatim from our actual contract:

function hardCapReached() public constant returns (bool) {

return weiRaised >= hardCap.mul(1000 + capFlex).div(1000);


This particular snippet of code is fine, and is used in various parts of the contract to check whether hard cap behavior should be active. Unfortunately, there is a single line of code in the ICO contract where this perfectly functioning piece of code is not used, though for a reason.

function buyTokens(address _beneficiary) saleOpen public payable {

require(_beneficiary != address(0));

uint256 weiAmount = msg.value;

require(weiAmount > 0);

require(weiRaised.add(weiAmount) <= hardCap);

This function is the one that both direct contributors and the fast-track KYC contract use when funds are transferred into the ICO contract. As can clearly be seen on the last line, an attempt is made to check that the new contribution does not bring us above the hard cap. Incidentally, that is also why the hardCapReached() method could not be used, as it is unable to account for the newly received ETH by itself. Crucially, this check does not include the cap flex calculation that was present in the functioning method we covered earlier. In effect, the check behaves just as if the contract was operating with no cap flex at all, with a fixed hard cap of 22,500 ETH. Since the minimum portion of the hard cap is not directly modifiable, it is not possible to change the result of this check, effectively permanently locking our hard cap to 22,500 ETH.

require(weiRaised.add(weiAmount) <= hardCap);

An earlier version of the ICO contract was audited by a reputable member of the crypto community. Crucially, our implementation of the cap flex was a late game addition that was not included in the version that received the audit. Taking this shortcut was a choice that directly led to the issue and one that has caused us to disappoint our community.



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store