1

I'm stuck with a very weird behaviour of my smart contract.

  uint weiDue = calculateTotalWei(winningBets[i].tokensDeposited, winningBets[i].amounts, multipliers) / totalWeiBetWinningTeam * totalWeiBetLosingTeam;

  //debugging
  weiDueEv(calculateTotalWei(winningBets[i].tokensDeposited, winningBets[i].amounts, multipliers), totalWeiBetWinningTeam, totalWeiBetLosingTeam, weiDue);

The function calculateTotalWei returns uint and both totalWeiBetWinningTeam and totalWeiBetLosingTeam are also uints.

After debugging with event it seems like

weiDue = 100 / 200 * 1700 // gives 0, should be 850

on the other hand

weiDue = 100 / 100 * 1700 // gives 1700

What is this magic behaviour and how do I fix this? It seems like 100/200 is coerced to 0 before multipling by 1700 but why?

2 Answers 2

1

Solidity does not support decimals, so when you do 100 / 200 it uses "integer division", where the floor function is used to determine the final value.

In this case .5 is reduced to 0.

3
  • How is it then if I create test function: function calc() public view returns (uint) { uint x = 100/200 * 1700; return x; } it returns 850
    – lemme
    Commented Oct 7, 2018 at 21:04
  • It is not clear what your calculateTotalWei function is doing. Can you please paste that code? Can you make sure the value returned from that is not zero? Commented Oct 7, 2018 at 21:12
  • Look at the behavior of function print(uint x) public pure returns(uint) { return x / 10 * 20; } You will see this function returns 0 for values of x less than 10. Commented Oct 7, 2018 at 21:41
1

Any integer division is 0 if the denominator (i.e. the number below in the fraction) is greater than the denominator (i.e. the other number) because any number following the decimal do not exist:

100/200 should be 0.50, but zeroing all the digit after the decimal, because they do not exist in the integer representation, it is zero.

To have proper execution the best practice is to premultiply any numerator for a big number and to divide for the same number the final result of the operation.

weiDue = 100 / 200 * 1700  is 0

but

weidue = ((100 * 1000) / 200 * 1700) / 1000 = 850

In this particular case if you change the order of the operation, multiplying all first and dividing as last operation, you have:

weidue = (100 * 1700) / 200 = 850

without further elaboration.

In general, when using integer math, you prefer to have the division as the latest operation to perform.

Remember that the natural order of execution of operation of same priority is from left to right, as encountered in the instruction, but some brackets somewhere do not cost money or gas, so use it.

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.