-
Notifications
You must be signed in to change notification settings - Fork 11.9k
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
SafeMath for uint32 and all other variations #1625
Comments
Hi @cedricwalter. Thank you for opening an issue prior to contributing a PR. 😊 Please see my response here: #1484 (comment).
Could you share your motivation for working with 32 bit integers? If it involves gas costs, please include code to measure them. Given that Solidity emulates 32 bit arithmetic with masks, shifting, and "manual" overflow detection, I'm not convinced that using 32 bit integers is actually cheaper than integers of the native size (256 bit). |
Hi. 😊 I've noticed that the types effects to gas costs in case of numbers in inside of structs. 💡 Details are in the CryptZombies tutorial below:
With the sample code below, I've measured that how much of gas cost difference between Sample code (GasCosts.sol)pragma solidity >=0.4.21 <0.6.0;
contract GasCosts {
StructA public structA;
struct StructA {
uint a;
uint b;
uint c;
}
StructB public structB;
struct StructB {
uint8 a;
uint8 b;
uint8 c;
}
function saveStructAtoStorage() public {
structA = StructA(1, 2, 3);
}
function saveStructBtoStorage() public {
structB = StructB(1, 2, 3);
}
} Operations on truffle consoleStructA (
|
This repository also demonstrates measurable savings in gas costs, showing that the use of 256-bit arithmetic adds an inefficiency cost of about 1/3 compared to using 32-bit integers, in a setting where 32-bit integers suffice. To reproduce, clone that repo and run |
Hm, I wonder how those numbers would change in more dynamic scenarios (e.g. the values are received as parameters instead of being hardcoded, and some math is done on them). |
Tagging this for 2.3 so that we keep track of it and continue the discussion, but this doesn't necessarily mean that we will include support in that version. |
@nventuro I'm not sure what you mean. In the example repo the uint values are received by EVM as parameters; the actual values being stored are randomly generated in Javascript. |
Sorry @wbt, I had only looked at the example @ackintosh provided. Your example should indeed trigger some of Solidity's masking code, since you're both storing packed That said, it does seem to serve as a good estimate of an upper bound in gas savings, since it compares four values packed into a single slot as opposed to four full slots, with functions that only read/write said slots. |
@nventuro Yes, I believe packing is the primary gas-savings motivation for using smaller ints. |
I've added a function "turnUpHeat" in the example repo which does some math on what the contract is receiving as dynamic variables. Also, I think you'd have to be using |
@wbt I played around with your migrations script for a bit, adding calls to That said, there are cases where savings can be quite large (~30%), so providing support may make sense. My main issue is regarding a lack of language support in this regards (no generics, in particular): we'd have to maintain multiple |
I agree, which is why "everybody always use uint256 or don't use OpenZeppelin's safemath" doesn't seem appropriate. Code autogeneration seems like it'd be relatively easy, or copy-paste-modify for those where it's requested (or maybe starting with the powers of 2, 8-256). I would recommend dropping "Bytes" from the suggested name, and have N match the bit count (e. g. "SafeMath32"), so the naming convention matches how uints are named. |
#1926 added
Arithmetic will be performed on 256 types (which is often useful since it allows for intermediate steps in a calculation to go over smaller types, e.g. when multiplying multiple numbers before dividing), and the final downcast will assert that the result fits in the intended type. |
🧐 Motivation
📝 Details
I need safe math operations on uint32, i could do a PR but there is a lot of type to support (uint8 to uint256 in steps of 8 (unsigned of 8 up to 256 bits) ) and before jumping in, i want to know what this PR could/should contains
The text was updated successfully, but these errors were encountered: