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?

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.

| improve this answer | |
  • 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 Oct 7 '18 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? – Shawn Tabrizi Oct 7 '18 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. – Shawn Tabrizi Oct 7 '18 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.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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