The reason you are getting that error is because num
is of type uint8
, and the sub()
function of SafeMath is looking for type uint256
. Additionally you declare using SafeMath for uint;
, which confirms that it only works with uint256
(as uint
is an alias for uint256
).
There are two ways to fix it:
1) Make num
a uint256
type. Your code would look as follows:
pragma solidity ^0.5.1;
library SafeMath {
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
}
contract Underflow1 {
using SafeMath for uint;
uint256 num= 0;
function testf2() public returns (uint256){
//val--;
num = num.sub(1);
return num;
}
}
2) (Not preferred) Allow SafeMath to handle type uint8
. Your code would look as follows:
pragma solidity ^0.5.1;
library SafeMath {
function sub(uint8 a, uint8 b) internal pure returns (uint8) {
assert(b <= a);
return a - b;
}
}
contract Underflow1 {
using SafeMath for uint8;
uint8 num= 0;
function testf2() public returns (uint8){
//val--;
num = num.sub(1);
return num;
}
}
The Solidity v0.8.0 Breaking Changes Docs says:
Checks for overflow are very common, so we made them the default to increase readability of code, even if it comes at a slight increase of gas costs.
And Checking the GitHub commits for SafeMath.sol I found this commit made on February 2021 were they added the comment:
NOTE: SafeMath is no longer needed starting with Solidity 0.8. The compiler now has built in overflow checking.
The comment was later Reviewed in this other commit, with the title Review wording of SafeMath need in Solidity 0.8, and changed to:
NOTE: SafeMath is generally not needed starting with Solidity 0.8, since the compiler now has built in overflow checking.
Checking the first commit linked, we can also see a comment made in the SignedSafeMath.sol contract that said:
Signed math operations that revert on error.
I think that's like saying they are checking for overflows.
Also, the wording changes seems to be aligned with the other answer here, noticing that you may reuse safemath as library to improve operation cost for example, as the default one is more expensive now according to the docs, or to improve the ** operator for bases different to 2 or 10.
But it does seems that SafeMath is indeed generally not needed starting with Solidity 0.8
Also the top comment in the safemath library now says:
CAUTION
This version of SafeMath should only be used with Solidity 0.8 or later, because it relies on the compiler's built in overflow checks.
Now the add function is :
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
And an earlier implementation was:
function add(uint a, uint b) internal pure returns (uint) {
uint c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
Best Answer
You can get that on openzepplins github. Just navigate to Github then Openzeeplin-contracts. Go to the branches and check a lower branch.