0

I'm making a fund manager using solidity and I'd like to calculate the percentage, however I'm wonder whether the use of safeMath is actually incorrect.

using SafeMath for uint256;
uint256 percent = 5
function managePayment(uint256 payment)
    amountToSplit = payment.mul(percent).div(100);
}

In this case, I'm limiting myself to 1/5 of the max supply otherwise multiply will throw when calculating the percent, is there a better approach to doing this, (Granted I could avoid using safe math, if I validate the percentage is less than 100) However, I'd like to avoid this approach

1 Answer 1

1

Since solidity 0.8 you dont' need safe math for that. The compiler will inject checking sequences to automatically throw if overflow occurs. (This problem was removed since OP is aware of that)

Update: According to the comment, looks like OP wants to calculate multiplying with the result larger than uint256 and then the division will take back the intermediate result down to uint256. The safeMath library or overflow prevention are not designed for that. You need to implement or use some library that can represent higher bitwidth (e.g. uint512). After searching for a while I think Openzeppellin already have similar library for you, look at function mulDiv(uint256 x, uint256 y, uint256 denominator) source code. Hence the code below will be safe to use:

pragma solidity ^0.8.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/Math.sol";
contract Test {
  uint256 percent = 10;
  function managePayment(uint256 payment) public view returns(uint256){
      return  Math.mulDiv(payment, percent, 100);
  }
}

Input: 2**255 = 57896044618658097711785492504343953926634992332820282019728792003956564819968

Output: 2**255/10 = 5789604461865809771178549250434395392663499233282028201972879200395656481996

You can also choose rounding direction : Math.mulDiv(payment, percent, 100, Math.Rounding.Up);

Output: 2**255/10 = 5789604461865809771178549250434395392663499233282028201972879200395656481997

Other Related links :

  1. https://forum.openzeppelin.com/t/best-way-to-handle-uint-256-bit/1487/3
  2. How to define 2048-bit integers on smart contracts?
  3. Synthetic uint512 out of 2 uint256
3
  • I was using a simpler representation for the percent but I uses bips usually. Again, won't this be an issue, lets say the payment is 1/2 of the Uint256.MAX, if we do payment*numerator, we're overflowing, and it will throw an error. When in reality, I want to allow unsafe overflow, because my next operation brings will always bring back into range assuming the numerator is less than the denominator
    – Ritzy Dev
    Dec 31, 2022 at 16:25
  • You have to make sure it wont happen. If you allow unsafe overflow it will be like this, for example payment = 2^255, numerator = 2 : payment*numerator = 2^256 = 0. payment*numerator/denom = 0/100 = 0; How can you get the correct result with overflow ?
    – minhhn2910
    Jan 1, 2023 at 4:14
  • You need to give real examples in number etc so people can understand more what you want.
    – minhhn2910
    Jan 1, 2023 at 4:15

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.