Very quick and likely easy question here. I am trying to code a crowdsale contract that accepts BNB and returns a number of tokens to the sender. My transactions keep failing because it says the BNB sent is greater than my max purchase cap of 100 BNB. I have sent increasing smaller amounts of BNB to no avail, they all get reverted by the require statement: require(_jagerAmount <= purchaseCap). After searching around, I am now aware that msg.sender takes in 18 decimals as it was set up for ether and not BNB. My question is, how to do I properly set up these functions to take in BNB and how to I account for the 18 decimals that msg.value caries?

uint256 purchaseCap = (100 * 10**8);

// Receive function to recieve BNB.
receive() external payable {

function buyTokens(address _beneficiary) public payable {
    uint256 jagerAmount = msg.value;
    _validatePurchase(_beneficiary, jagerAmount);
    _processPurchase(_beneficiary, jagerAmount);
    _transferBNB(payable(msg.sender), msg.value);

// Validation of an incoming purchase. Uses require statements to revert state when conditions are not met.
function _validatePurchase(address _beneficiary, uint256 _jagerAmount) internal view {
    require(block.timestamp >= startTime && block.timestamp <= endTime, "Crowdsale: current time is either before or after Crowdsale period.");
    require(_hasClosed == false, "Crowdsale: sale is no longer open");
    require(_beneficiary != address(0), "Crowdsale: beneficiary can not be Zero Address.");
    require(_jagerAmount != 0, "Crowdsale: amount of BNB must be greater than 0.");
    require(_jagerAmount <= purchaseCap, "Crowdsale: amount of BNB sent must lower than 100");
    require((balances[_beneficiary] + _jagerAmount) <= purchaseCap, "Crowdsale: amount of BNB entered exceeds buyers purchase cap.");
  • The contract looks fine, what code are you using to call buyTokens?
    – Ismael
    Oct 18, 2021 at 6:03
  • I intended to simply call the function from my frontend, but as of now I am testing on Binance Testnet and directly sending the contract BNB. I think my problem is msg.value. I saw on another post that msg.value is always in WEI, and therefore has 18 decimals and not the 8 decimals that BNB has. So if I send 1 BNB, am I correct in saying that msg.value shows 1 * 10^18?
    – Austin
    Oct 18, 2021 at 6:14

1 Answer 1


For those that may stumble across this later and have the same question, the answer was rather straightforward.

Even though BNB only has 8 decimals, Binance Smart Chain is a clone of Ethereum, so for all intents and purposes BNB should be treated as though it has 18 decimals (like Ethereum). Msg.value will have 18 decimals, so when calculating rates or amounts inside a Crowdsale contract, multiply or divide by 10**18.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.