I'm in the process of developing a smart contract that allows users to purchase tokens. However, I'm encountering an issue with the price calculation:

  1. The token I'm selling (let's call it "SellToken") has 18 decimals.
  2. The token being used for purchase (e.g., USDC) has 6 decimals.

Here's the relevant function from my smart contract:

function purchaseTokens(address inputToken, uint256 lockDuration, uint256 amount, uint256 price) external {
    require(acceptedTokens[inputToken], "Token not accepted");
    require(price == priceByLockDuration[lockDuration], "Invalid price");

    IERC20 paymentToken = IERC20(inputToken);

    uint256 totalPrice = price.mul(amount);
    console.log('totalPrice', totalPrice);
    console.log('amount', amount);
    require(paymentToken.balanceOf(msg.sender) >= totalPrice, "Insufficient balance");
    require(totalTokensForSale.sub(totalTokensSold) >= amount, "Insufficient sale tokens for sale");
    require(paymentToken.transferFrom(msg.sender, address(this), totalPrice), "Payment transfer failed");

    Purchase memory newPurchase;
    newPurchase.amount = amount;
    newPurchase.unlockTime = block.timestamp.add(lockDuration);
    newPurchase.claimed = false;

    purchaseCount[msg.sender] = purchaseCount[msg.sender].add(1);
    totalTokensSold = totalTokensSold.add(amount);

When I set the price as follows:

const price = ethers.parseUnits('0.1', USDCdecimals)
const amount = 1


The result is that when a user spends 0.1 USDC, they only receive 0.000000000000000001 SellToken.

How can I adjust the price calculation so that spending 0.1 USDC will give the user 1 SellToken?

1 Answer 1


It is the good old Cross-Multiplication trick.

For example let's say 1 usdc = 10 tokens, then for 0.23 usdc you have 10 tokens * 0.23 usdc / 1 usdc = 2.3 tokens.

For convinience you could store the price as a fraction.

uint256 priceNumerator = 10*10**18;  // in tokens units
uint256 priceDenominator = 1*10**6;  // in USDC units

If you paid amountUSDC in USDC then

uint256 amountTokens = priceNumerator * amountUSDC / priceDenominator;

Going back to the example you paid 0.23 USDC, that will be amountUSDC = 230000.

amountTokens = 10 *10**18 * 230000 / 10**6;

After doing the math you get amountTokens = 2.3 * 10**18, o 2.3 tokens as expected.

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.