Skip to content

Instantly share code, notes, and snippets.

@PaulRBerg
Created August 14, 2020 21:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PaulRBerg/4d7cb0873ed99dcd34df50fffb54dbb2 to your computer and use it in GitHub Desktop.
Save PaulRBerg/4d7cb0873ed99dcd34df50fffb54dbb2 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.6.10+commit.00c0fcaf.js&optimize=true&gist=
/* SPDX-License-Identifier: LGPL-3.0-or-later */
pragma solidity ^0.6.10;
/**
* @title CarefulMath
* @author Compound
* @notice Exponential module for storing fixed-precision decimals.
* @dev Derived from OpenZeppelin's SafeMath library
*/
abstract contract CarefulMath {
/**
* @notice Possible error codes that can be returned.
*/
enum MathError { NO_ERROR, DIVISION_BY_ZERO, INTEGER_OVERFLOW, INTEGER_UNDERFLOW, MODULO_BY_ZERO }
/**
* @notice Adds two numbers, returns an error on overflow.
*/
function addUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) {
uint256 c = a + b;
if (c >= a) {
return (MathError.NO_ERROR, c);
} else {
return (MathError.INTEGER_OVERFLOW, 0);
}
}
/**
* @notice Add `a` and `b` and then subtract `c`.
*/
function addThenSubUInt(
uint256 a,
uint256 b,
uint256 c
) internal pure returns (MathError, uint256) {
(MathError err0, uint256 sum) = addUInt(a, b);
if (err0 != MathError.NO_ERROR) {
return (err0, 0);
}
return subUInt(sum, c);
}
/**
* @notice Integer division of two numbers, truncating the quotient.
*/
function divUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) {
if (b == 0) {
return (MathError.DIVISION_BY_ZERO, 0);
}
return (MathError.NO_ERROR, a / b);
}
/**
* @notice Returns the remainder of dividing two numbers.
* @dev Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*/
function modUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) {
if (b == 0) {
return (MathError.MODULO_BY_ZERO, 0);
}
return (MathError.NO_ERROR, a % b);
}
/**
* @notice Multiplies two numbers, returns an error on overflow.
*/
function mulUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) {
if (a == 0) {
return (MathError.NO_ERROR, 0);
}
uint256 c = a * b;
if (c / a != b) {
return (MathError.INTEGER_OVERFLOW, 0);
} else {
return (MathError.NO_ERROR, c);
}
}
/**
* @notice Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).
*/
function subUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) {
if (b <= a) {
return (MathError.NO_ERROR, a - b);
} else {
return (MathError.INTEGER_UNDERFLOW, 0);
}
}
}
/* SPDX-License-Identifier: LGPL-3.0-or-later */
pragma solidity ^0.6.10;
import "./CarefulMath.sol";
contract CarefulMathShowcase is CarefulMath {
function doMath(uint256 a, uint256 b) external pure returns (uint256) {
MathError mathErr;
uint256 result;
(mathErr, result) = addUInt(a, b);
require(mathErr == MathError.NO_ERROR, "BESPOKE_MATH_ERROR");
return result;
}
}
/* SPDX-License-Identifier: LGPL-3.0-or-later */
pragma solidity ^0.6.10;
/**
* @title Erc20
* @author OpenZeppelin
* @notice Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
/* SPDX-License-Identifier: LGPL-3.0-or-later */
pragma solidity ^0.6.10;
import "./SafeMath.sol";
contract SafeMathShowcase {
using SafeMath for uint256;
function doMath(uint256 a, uint256 b) external pure returns (uint256) {
uint256 result = a.add(b);
return result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment