Skip to content

Commit

Permalink
Merge pull request #5 from VenusProtocol/develop
Browse files Browse the repository at this point in the history
New Release
  • Loading branch information
chechu authored Nov 7, 2023
2 parents cf8fe48 + 1fcf955 commit 21b9fff
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 1 deletion.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## [1.1.0-dev.1](https://github.com/VenusProtocol/solidity-utilities/compare/v1.0.1...v1.1.0-dev.1) (2023-11-07)


### Features

* add math helpers and constants ([f1b2596](https://github.com/VenusProtocol/solidity-utilities/commit/f1b2596b8f508be48cce1bf5f4643dbe8a91467a))


### Bug Fixes

* resolve comments ([7f93845](https://github.com/VenusProtocol/solidity-utilities/commit/7f938459cad0743da83718dcb48f4678bed52c77))

## [1.0.1](https://github.com/VenusProtocol/solidity-utilities/compare/v1.0.0...v1.0.1) (2023-10-25)


Expand Down
154 changes: 154 additions & 0 deletions contracts/ExponentialNoError.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.13;

import { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from "./constants.sol";

/**
* @title Exponential module for storing fixed-precision decimals
* @author Compound
* @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.
* Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:
* `Exp({mantissa: 5100000000000000000})`.
*/
contract ExponentialNoError {
struct Exp {
uint256 mantissa;
}

struct Double {
uint256 mantissa;
}

uint256 internal constant EXP_SCALE = EXP_SCALE_;
uint256 internal constant DOUBLE_SCALE = 1e36;
uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;
uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;

/**
* @dev Truncates the given exp to a whole number value.
* For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15
*/
function truncate(Exp memory exp) internal pure returns (uint256) {
// Note: We are not using careful math here as we're performing a division that cannot fail
return exp.mantissa / EXP_SCALE;
}

/**
* @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.
*/
// solhint-disable-next-line func-name-mixedcase
function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {
Exp memory product = mul_(a, scalar);
return truncate(product);
}

/**
* @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.
*/
// solhint-disable-next-line func-name-mixedcase
function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {
Exp memory product = mul_(a, scalar);
return add_(truncate(product), addend);
}

/**
* @dev Checks if first Exp is less than second Exp.
*/
function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {
return left.mantissa < right.mantissa;
}

function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {
require(n <= type(uint224).max, errorMessage);

Check warning on line 62 in contracts/ExponentialNoError.sol

View workflow job for this annotation

GitHub Actions / Lint

Use Custom Errors instead of require statements
return uint224(n);
}

function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {
require(n <= type(uint32).max, errorMessage);

Check warning on line 67 in contracts/ExponentialNoError.sol

View workflow job for this annotation

GitHub Actions / Lint

Use Custom Errors instead of require statements
return uint32(n);
}

function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {
return Exp({ mantissa: add_(a.mantissa, b.mantissa) });
}

function add_(Double memory a, Double memory b) internal pure returns (Double memory) {
return Double({ mantissa: add_(a.mantissa, b.mantissa) });
}

function add_(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}

function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {
return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });
}

function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {
return Double({ mantissa: sub_(a.mantissa, b.mantissa) });
}

function sub_(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}

function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {
return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / EXP_SCALE });
}

function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {
return Exp({ mantissa: mul_(a.mantissa, b) });
}

function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {
return mul_(a, b.mantissa) / EXP_SCALE;
}

function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {
return Double({ mantissa: mul_(a.mantissa, b.mantissa) / DOUBLE_SCALE });
}

function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {
return Double({ mantissa: mul_(a.mantissa, b) });
}

function mul_(uint256 a, Double memory b) internal pure returns (uint256) {
return mul_(a, b.mantissa) / DOUBLE_SCALE;
}

function mul_(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}

function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {
return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });
}

function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {
return Exp({ mantissa: div_(a.mantissa, b) });
}

function div_(uint256 a, Exp memory b) internal pure returns (uint256) {
return div_(mul_(a, EXP_SCALE), b.mantissa);
}

function div_(Double memory a, Double memory b) internal pure returns (Double memory) {
return Double({ mantissa: div_(mul_(a.mantissa, DOUBLE_SCALE), b.mantissa) });
}

function div_(Double memory a, uint256 b) internal pure returns (Double memory) {
return Double({ mantissa: div_(a.mantissa, b) });
}

function div_(uint256 a, Double memory b) internal pure returns (uint256) {
return div_(mul_(a, DOUBLE_SCALE), b.mantissa);
}

function div_(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}

function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {
return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });
}
}
8 changes: 8 additions & 0 deletions contracts/constants.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.13;

/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)
uint256 constant EXP_SCALE = 1e18;

/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions
uint256 constant MANTISSA_ONE = EXP_SCALE;
14 changes: 14 additions & 0 deletions contracts/validators.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.13;

/// @notice Thrown if the supplied address is a zero address where it is not allowed
error ZeroAddressNotAllowed();

/// @notice Checks if the provided address is nonzero, reverts otherwise
/// @param address_ Address to check
/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address
function ensureNonzeroAddress(address address_) pure {
if (address_ == address(0)) {
revert ZeroAddressNotAllowed();
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@venusprotocol/solidity-utilities",
"version": "1.0.1",
"version": "1.1.0-dev.1",
"description": "Solidity code used by other Venus projects",
"files": [
"artifacts",
Expand Down

0 comments on commit 21b9fff

Please sign in to comment.