Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected results using SafeMath for uint128 #1925

Closed
bh2smith opened this issue Sep 24, 2019 · 4 comments · Fixed by #1926
Closed

Unexpected results using SafeMath for uint128 #1925

bh2smith opened this issue Sep 24, 2019 · 4 comments · Fixed by #1926

Comments

@bh2smith
Copy link
Contributor

Summary

Trying to use SafeMath for uint128 should throw/ revert in situations when overflows happen! Same holds for overflows of any integer type that are not uint256

📝 Example

Contract:

pragma solidity ^0.5.0;

import "openzeppelin-solidity/contracts/math/SafeMath.sol";

contract BrokenSafeMath {
    using SafeMath for uint128;

    function unsafeAdd(uint128 a, uint128 b) public pure returns (uint128) {
        return uint128(a.add(b));
    }
}

unit test:

let res = await contract.unsafeAdd.call("340282366920938463463374607431768211455", 2)

yields a return value of x = 1 (unexpected/should have reverted).

The problem seems to be with the upcasting of everything to uint256 as seen in the following snippet.

function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}

As far as I understand, this implies that SafeMath is only really "safe" for uint256 and none of the other integer types.

💻 Environment
Not really applicable, but this appears to be the case for all versions. Particularly, I ran my examples with

    "openzeppelin-solidity": "^2.3.0",
@Skyge
Copy link
Contributor

Skyge commented Sep 24, 2019

Yeah, you are right, SafeMath is only for uint256 currently. So if you want to use it for uint128, maybe you should make corresponding changes: uint256 => uint128.

@abcoathup
Copy link
Contributor

Hi @bh2smith,

As per @Skyge, SafeMath only supports uint256.

See the following issue for a discussion on supporting other types:
#1625

@bh2smith
Copy link
Contributor Author

bh2smith commented Sep 25, 2019

Thanks for the suggestions all, these were very helpful. Will probably start looking for or working on a SafeCast library that might look as follows.

pragma solidity ^0.5.0;

library SafeCast {
    function castU128(uint a) internal pure returns (uint128) {
        require(a < 2**128, "SafeCast: downcast overflow");
        return uint128(a);
    }
}

Would this be something that should/could be included here in the openzeppelin repo?

@frangio
Copy link
Contributor

frangio commented Oct 7, 2019

function unsafeAdd(uint128 a, uint128 b) public pure returns (uint128) {
    return uint128(a.add(b));
}

To clarify, the dangerous operation here is not the SafeMath operation but the downcast to uint128. I think the casting library proposed by @bh2smith is the right way to approach this kind of thing.

Thank you for reporting and proposing a mitigation!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants