Skip to content

Commit

Permalink
⚡️ Memory safe assembly (#333)
Browse files Browse the repository at this point in the history
  • Loading branch information
axic authored Oct 27, 2022
1 parent c2594bf commit f2833c7
Show file tree
Hide file tree
Showing 7 changed files with 27 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/utils/CREATE3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ library CREATE3 {
bytes memory proxyChildBytecode = PROXY_BYTECODE;

address proxy;
/// @solidity memory-safe-assembly
assembly {
// Deploy a new contract with our pre-made bytecode via CREATE2.
// We start 32 bytes into the code to avoid copying the byte length.
Expand Down
7 changes: 7 additions & 0 deletions src/utils/FixedPointMathLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ library FixedPointMathLib {
uint256 y,
uint256 denominator
) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
Expand All @@ -54,6 +55,7 @@ library FixedPointMathLib {
uint256 y,
uint256 denominator
) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
Expand All @@ -71,6 +73,7 @@ library FixedPointMathLib {
uint256 n,
uint256 scalar
) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
switch x
case 0 {
Expand Down Expand Up @@ -159,6 +162,7 @@ library FixedPointMathLib {
//////////////////////////////////////////////////////////////*/

function sqrt(uint256 x) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
let y := x // We start y at x, which will help us make our initial estimate.

Expand Down Expand Up @@ -223,6 +227,7 @@ library FixedPointMathLib {
}

function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Mod x by y. Note this will return
// 0 instead of reverting if y is zero.
Expand All @@ -231,6 +236,7 @@ library FixedPointMathLib {
}

function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {
/// @solidity memory-safe-assembly
assembly {
// Divide x by y. Note this will return
// 0 instead of reverting if y is zero.
Expand All @@ -239,6 +245,7 @@ library FixedPointMathLib {
}

function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Add 1 to x * y if x % y > 0. Note this will
// return 0 instead of reverting if y is zero.
Expand Down
1 change: 1 addition & 0 deletions src/utils/LibString.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pragma solidity >=0.8.0;
/// @author Modified from Solady (https://github.com/Vectorized/solady/blob/main/src/utils/LibString.sol)
library LibString {
function toString(uint256 value) internal pure returns (string memory str) {
/// @solidity memory-safe-assembly
assembly {
// The maximum value of a uint256 contains 78 digits (1 byte per digit), but we allocate 160 bytes
// to keep the free memory pointer word aligned. We'll need 1 word for the length, 1 word for the
Expand Down
1 change: 1 addition & 0 deletions src/utils/MerkleProofLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ library MerkleProofLib {
bytes32 root,
bytes32 leaf
) internal pure returns (bool isValid) {
/// @solidity memory-safe-assembly
assembly {
if proof.length {
// Left shifting by 5 is like multiplying by 32.
Expand Down
2 changes: 2 additions & 0 deletions src/utils/SSTORE2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ library SSTORE2 {
runtimeCode // The bytecode we want the contract to have after deployment. Capped at 1 byte less than the code size limit.
);

/// @solidity memory-safe-assembly
assembly {
// Deploy a new contract with the generated creation code.
// We start 32 bytes into the code to avoid copying the byte length.
Expand Down Expand Up @@ -79,6 +80,7 @@ library SSTORE2 {
uint256 start,
uint256 size
) private view returns (bytes memory data) {
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
data := mload(0x40)
Expand Down
4 changes: 4 additions & 0 deletions src/utils/SafeTransferLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ library SafeTransferLib {
function safeTransferETH(address to, uint256 amount) internal {
bool success;

/// @solidity memory-safe-assembly
assembly {
// Transfer the ETH and store if it succeeded or not.
success := call(gas(), to, amount, 0, 0, 0, 0)
Expand All @@ -35,6 +36,7 @@ library SafeTransferLib {
) internal {
bool success;

/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
Expand Down Expand Up @@ -67,6 +69,7 @@ library SafeTransferLib {
) internal {
bool success;

/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
Expand Down Expand Up @@ -98,6 +101,7 @@ library SafeTransferLib {
) internal {
bool success;

/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
Expand Down
11 changes: 11 additions & 0 deletions src/utils/SignedWadMath.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pragma solidity >=0.8.0;

/// @dev Will not revert on overflow, only use where overflow is not possible.
function toWadUnsafe(uint256 x) pure returns (int256 r) {
/// @solidity memory-safe-assembly
assembly {
// Multiply x by 1e18.
r := mul(x, 1000000000000000000)
Expand All @@ -17,6 +18,7 @@ function toWadUnsafe(uint256 x) pure returns (int256 r) {
/// @dev Will not revert on overflow, only use where overflow is not possible.
/// @dev Not meant for negative second amounts, it assumes x is positive.
function toDaysWadUnsafe(uint256 x) pure returns (int256 r) {
/// @solidity memory-safe-assembly
assembly {
// Multiply x by 1e18 and then divide it by 86400.
r := div(mul(x, 1000000000000000000), 86400)
Expand All @@ -27,6 +29,7 @@ function toDaysWadUnsafe(uint256 x) pure returns (int256 r) {
/// @dev Will not revert on overflow, only use where overflow is not possible.
/// @dev Not meant for negative day amounts, it assumes x is positive.
function fromDaysWadUnsafe(int256 x) pure returns (uint256 r) {
/// @solidity memory-safe-assembly
assembly {
// Multiply x by 86400 and then divide it by 1e18.
r := div(mul(x, 86400), 1000000000000000000)
Expand All @@ -35,6 +38,7 @@ function fromDaysWadUnsafe(int256 x) pure returns (uint256 r) {

/// @dev Will not revert on overflow, only use where overflow is not possible.
function unsafeWadMul(int256 x, int256 y) pure returns (int256 r) {
/// @solidity memory-safe-assembly
assembly {
// Multiply x by y and divide by 1e18.
r := sdiv(mul(x, y), 1000000000000000000)
Expand All @@ -44,13 +48,15 @@ function unsafeWadMul(int256 x, int256 y) pure returns (int256 r) {
/// @dev Will return 0 instead of reverting if y is zero and will
/// not revert on overflow, only use where overflow is not possible.
function unsafeWadDiv(int256 x, int256 y) pure returns (int256 r) {
/// @solidity memory-safe-assembly
assembly {
// Multiply x by 1e18 and divide it by y.
r := sdiv(mul(x, 1000000000000000000), y)
}
}

function wadMul(int256 x, int256 y) pure returns (int256 r) {
/// @solidity memory-safe-assembly
assembly {
// Store x * y in r for now.
r := mul(x, y)
Expand All @@ -66,6 +72,7 @@ function wadMul(int256 x, int256 y) pure returns (int256 r) {
}

function wadDiv(int256 x, int256 y) pure returns (int256 r) {
/// @solidity memory-safe-assembly
assembly {
// Store x * 1e18 in r for now.
r := mul(x, 1000000000000000000)
Expand Down Expand Up @@ -119,6 +126,7 @@ function wadExp(int256 x) pure returns (int256 r) {
q = ((q * x) >> 96) - 14423608567350463180887372962807573;
q = ((q * x) >> 96) + 26449188498355588339934803723976023;

/// @solidity memory-safe-assembly
assembly {
// Div in assembly because solidity adds a zero check despite the unchecked.
// The q polynomial won't have zeros in the domain as all its roots are complex.
Expand Down Expand Up @@ -147,6 +155,7 @@ function wadLn(int256 x) pure returns (int256 r) {
// ln(x * C) = ln(x) + ln(C), we can simply do nothing here
// and add ln(2**96 / 10**18) at the end.

/// @solidity memory-safe-assembly
assembly {
r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
Expand Down Expand Up @@ -183,6 +192,7 @@ function wadLn(int256 x) pure returns (int256 r) {
q = ((q * x) >> 96) + 204048457590392012362485061816622;
q = ((q * x) >> 96) + 31853899698501571402653359427138;
q = ((q * x) >> 96) + 909429971244387300277376558375;
/// @solidity memory-safe-assembly
assembly {
// Div in assembly because solidity adds a zero check despite the unchecked.
// The q polynomial is known not to have zeros in the domain.
Expand Down Expand Up @@ -211,6 +221,7 @@ function wadLn(int256 x) pure returns (int256 r) {

/// @dev Will return 0 instead of reverting if y is zero.
function unsafeDiv(int256 x, int256 y) pure returns (int256 r) {
/// @solidity memory-safe-assembly
assembly {
// Divide x by y.
r := sdiv(x, y)
Expand Down

0 comments on commit f2833c7

Please sign in to comment.