refactor SafeMath rich errors and use them in staking libs

This commit is contained in:
Michael Zhu
2019-08-23 15:49:17 -07:00
parent cd1fc6a1f0
commit 98e5b26eb7
19 changed files with 371 additions and 174 deletions

View File

@@ -16,8 +16,8 @@ library LibSafeMath {
}
uint256 c = a * b;
if (c / a != b) {
LibRichErrors.rrevert(LibSafeMathRichErrors.SafeMathError(
LibSafeMathRichErrors.SafeMathErrorCodes.UINT256_MULTIPLICATION_OVERFLOW,
LibRichErrors.rrevert(LibSafeMathRichErrors.Uint256BinopError(
LibSafeMathRichErrors.BinopErrorCodes.MULTIPLICATION_OVERFLOW,
a,
b
));
@@ -31,8 +31,8 @@ library LibSafeMath {
returns (uint256)
{
if (b == 0) {
LibRichErrors.rrevert(LibSafeMathRichErrors.SafeMathError(
LibSafeMathRichErrors.SafeMathErrorCodes.UINT256_DIVISION_BY_ZERO,
LibRichErrors.rrevert(LibSafeMathRichErrors.Uint256BinopError(
LibSafeMathRichErrors.BinopErrorCodes.DIVISION_BY_ZERO,
a,
b
));
@@ -47,8 +47,8 @@ library LibSafeMath {
returns (uint256)
{
if (b > a) {
LibRichErrors.rrevert(LibSafeMathRichErrors.SafeMathError(
LibSafeMathRichErrors.SafeMathErrorCodes.UINT256_SUBTRACTION_UNDERFLOW,
LibRichErrors.rrevert(LibSafeMathRichErrors.Uint256BinopError(
LibSafeMathRichErrors.BinopErrorCodes.SUBTRACTION_UNDERFLOW,
a,
b
));
@@ -63,8 +63,8 @@ library LibSafeMath {
{
uint256 c = a + b;
if (c < a) {
LibRichErrors.rrevert(LibSafeMathRichErrors.SafeMathError(
LibSafeMathRichErrors.SafeMathErrorCodes.UINT256_ADDITION_OVERFLOW,
LibRichErrors.rrevert(LibSafeMathRichErrors.Uint256BinopError(
LibSafeMathRichErrors.BinopErrorCodes.ADDITION_OVERFLOW,
a,
b
));

View File

@@ -3,20 +3,37 @@ pragma solidity ^0.5.9;
library LibSafeMathRichErrors {
// bytes4(keccak256("SafeMathError(uint8,uint256,uint256)"))
bytes4 internal constant SAFE_MATH_ERROR =
0x35a51a70;
// bytes4(keccak256("Uint256BinopError(uint8,uint256,uint256)"))
bytes4 internal constant UINT256_BINOP_ERROR_SELECTOR =
0x8d8e1919;
enum SafeMathErrorCodes {
UINT256_ADDITION_OVERFLOW,
UINT256_MULTIPLICATION_OVERFLOW,
UINT256_SUBTRACTION_UNDERFLOW,
UINT256_DIVISION_BY_ZERO
// bytes4(keccak256("Uint96BinopError(uint8,uint96,uint96)"))
bytes4 internal constant UINT96_BINOP_ERROR_SELECTOR =
0x224cf712;
// bytes4(keccak256("Uint64BinopError(uint8,uint64,uint64)"))
bytes4 internal constant UINT64_BINOP_ERROR_SELECTOR =
0x4e79032d;
// bytes4(keccak256("Uint256DowncastError(uint8,uint256)"))
bytes4 internal constant UINT256_DOWNCAST_ERROR_SELECTOR =
0xc996af7b;
enum BinopErrorCodes {
ADDITION_OVERFLOW,
MULTIPLICATION_OVERFLOW,
SUBTRACTION_UNDERFLOW,
DIVISION_BY_ZERO
}
enum DowncastErrorCodes {
VALUE_TOO_LARGE_TO_DOWNCAST_TO_UINT64,
VALUE_TOO_LARGE_TO_DOWNCAST_TO_UINT96
}
// solhint-disable func-name-mixedcase
function SafeMathError(
SafeMathErrorCodes errorCode,
function Uint256BinopError(
BinopErrorCodes errorCode,
uint256 a,
uint256 b
)
@@ -25,10 +42,59 @@ library LibSafeMathRichErrors {
returns (bytes memory)
{
return abi.encodeWithSelector(
SAFE_MATH_ERROR,
UINT256_BINOP_ERROR_SELECTOR,
errorCode,
a,
b
);
}
function Uint96BinopError(
BinopErrorCodes errorCode,
uint96 a,
uint96 b
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
UINT96_BINOP_ERROR_SELECTOR,
errorCode,
a,
b
);
}
function Uint64BinopError(
BinopErrorCodes errorCode,
uint64 a,
uint64 b
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
UINT64_BINOP_ERROR_SELECTOR,
errorCode,
a,
b
);
}
function Uint256DowncastError(
DowncastErrorCodes errorCode,
uint256 a
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
UINT256_DOWNCAST_ERROR_SELECTOR,
errorCode,
a
);
}
}

View File

@@ -16,8 +16,8 @@ contract SafeMath {
}
uint256 c = a * b;
if (c / a != b) {
LibRichErrors.rrevert(LibSafeMathRichErrors.SafeMathError(
LibSafeMathRichErrors.SafeMathErrorCodes.UINT256_MULTIPLICATION_OVERFLOW,
LibRichErrors.rrevert(LibSafeMathRichErrors.Uint256BinopError(
LibSafeMathRichErrors.BinopErrorCodes.MULTIPLICATION_OVERFLOW,
a,
b
));
@@ -31,8 +31,8 @@ contract SafeMath {
returns (uint256)
{
if (b == 0) {
LibRichErrors.rrevert(LibSafeMathRichErrors.SafeMathError(
LibSafeMathRichErrors.SafeMathErrorCodes.UINT256_DIVISION_BY_ZERO,
LibRichErrors.rrevert(LibSafeMathRichErrors.Uint256BinopError(
LibSafeMathRichErrors.BinopErrorCodes.DIVISION_BY_ZERO,
a,
b
));
@@ -47,8 +47,8 @@ contract SafeMath {
returns (uint256)
{
if (b > a) {
LibRichErrors.rrevert(LibSafeMathRichErrors.SafeMathError(
LibSafeMathRichErrors.SafeMathErrorCodes.UINT256_SUBTRACTION_UNDERFLOW,
LibRichErrors.rrevert(LibSafeMathRichErrors.Uint256BinopError(
LibSafeMathRichErrors.BinopErrorCodes.SUBTRACTION_UNDERFLOW,
a,
b
));
@@ -63,8 +63,8 @@ contract SafeMath {
{
uint256 c = a + b;
if (c < a) {
LibRichErrors.rrevert(LibSafeMathRichErrors.SafeMathError(
LibSafeMathRichErrors.SafeMathErrorCodes.UINT256_ADDITION_OVERFLOW,
LibRichErrors.rrevert(LibSafeMathRichErrors.Uint256BinopError(
LibSafeMathRichErrors.BinopErrorCodes.ADDITION_OVERFLOW,
a,
b
));

View File

@@ -8,8 +8,8 @@ const MAX_UINT256 = new BigNumber(2).pow(256).minus(1);
export function safeAdd(a: BigNumber, b: BigNumber): BigNumber {
const r = a.plus(b);
if (r.isGreaterThan(MAX_UINT256)) {
throw new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
throw new SafeMathRevertErrors.Uint256BinopError(
SafeMathRevertErrors.BinopErrorCodes.AdditionOverflow,
a,
b,
);
@@ -23,8 +23,8 @@ export function safeAdd(a: BigNumber, b: BigNumber): BigNumber {
export function safeSub(a: BigNumber, b: BigNumber): BigNumber {
const r = a.minus(b);
if (r.isLessThan(0)) {
throw new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256SubtractionUnderflow,
throw new SafeMathRevertErrors.Uint256BinopError(
SafeMathRevertErrors.BinopErrorCodes.SubtractionUnderflow,
a,
b,
);
@@ -38,8 +38,8 @@ export function safeSub(a: BigNumber, b: BigNumber): BigNumber {
export function safeMul(a: BigNumber, b: BigNumber): BigNumber {
const r = a.times(b);
if (r.isGreaterThan(MAX_UINT256)) {
throw new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256MultiplicationOverflow,
throw new SafeMathRevertErrors.Uint256BinopError(
SafeMathRevertErrors.BinopErrorCodes.MultiplicationOverflow,
a,
b,
);
@@ -52,8 +52,8 @@ export function safeMul(a: BigNumber, b: BigNumber): BigNumber {
*/
export function safeDiv(a: BigNumber, b: BigNumber): BigNumber {
if (b.isEqualTo(0)) {
throw new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256DivisionByZero,
throw new SafeMathRevertErrors.Uint256BinopError(
SafeMathRevertErrors.BinopErrorCodes.DivisionByZero,
a,
b,
);

View File

@@ -21,8 +21,8 @@ describe('Reference Functions', () => {
it('reverts on overflow', () => {
const a = MAX_UINT256.dividedToIntegerBy(2);
const b = MAX_UINT256.dividedToIntegerBy(2).plus(2);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
const expectedError = new SafeMathRevertErrors.Uint256BinopError(
SafeMathRevertErrors.BinopErrorCodes.AdditionOverflow,
a,
b,
);
@@ -41,8 +41,8 @@ describe('Reference Functions', () => {
it('reverts on underflow', () => {
const a = MAX_UINT256.dividedToIntegerBy(2);
const b = MAX_UINT256.dividedToIntegerBy(2).plus(2);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256SubtractionUnderflow,
const expectedError = new SafeMathRevertErrors.Uint256BinopError(
SafeMathRevertErrors.BinopErrorCodes.SubtractionUnderflow,
a,
b,
);
@@ -61,8 +61,8 @@ describe('Reference Functions', () => {
it('reverts on overflow', () => {
const a = MAX_UINT256.dividedToIntegerBy(2);
const b = MAX_UINT256.dividedToIntegerBy(2).plus(2);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256MultiplicationOverflow,
const expectedError = new SafeMathRevertErrors.Uint256BinopError(
SafeMathRevertErrors.BinopErrorCodes.MultiplicationOverflow,
a,
b,
);
@@ -81,8 +81,8 @@ describe('Reference Functions', () => {
it('reverts if denominator is zero', () => {
const a = MAX_UINT256.dividedToIntegerBy(2);
const b = ZERO_AMOUNT;
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256DivisionByZero,
const expectedError = new SafeMathRevertErrors.Uint256BinopError(
SafeMathRevertErrors.BinopErrorCodes.DivisionByZero,
a,
b,
);

View File

@@ -45,8 +45,8 @@ blockchainTests('SafeMath', env => {
it('should revert if the multiplication overflows', async () => {
const a = toBigNumber('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'); // The largest uint256 number
const b = toBigNumber(2);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256MultiplicationOverflow,
const expectedError = new SafeMathRevertErrors.Uint256BinopError(
SafeMathRevertErrors.BinopErrorCodes.MultiplicationOverflow,
a,
b,
);
@@ -91,8 +91,8 @@ blockchainTests('SafeMath', env => {
it('should revert if second argument is zero', async () => {
const a = toBigNumber(1);
const b = toBigNumber(0);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256DivisionByZero,
const expectedError = new SafeMathRevertErrors.Uint256BinopError(
SafeMathRevertErrors.BinopErrorCodes.DivisionByZero,
a,
b,
);
@@ -112,8 +112,8 @@ blockchainTests('SafeMath', env => {
it('should revert if the subtraction underflows', async () => {
const a = toBigNumber(0);
const b = toBigNumber(1);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256SubtractionUnderflow,
const expectedError = new SafeMathRevertErrors.Uint256BinopError(
SafeMathRevertErrors.BinopErrorCodes.SubtractionUnderflow,
a,
b,
);
@@ -143,8 +143,8 @@ blockchainTests('SafeMath', env => {
it('should revert if the addition overflows', async () => {
const a = toBigNumber('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'); // The largest uint256 number
const b = toBigNumber(1);
const expectedError = new SafeMathRevertErrors.SafeMathError(
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
const expectedError = new SafeMathRevertErrors.Uint256BinopError(
SafeMathRevertErrors.BinopErrorCodes.AdditionOverflow,
a,
b,
);