flashloan-rs 0.2.1

Minimal Multicall3 Flashloan Module
Documentation
/// @title Errors
/// @notice SPDX-License-Identifier: MIT
/// @author jtriley.eth
/// @author clabby <https://github.com/clabby>
/// @notice Custom error utilities.

// https://docs.soliditylang.org/en/latest/control-structures.html?highlight=panic#panic-via-assert-and-error-via-require

// Errors
#define error Error(string)
#define error Panic(uint256)

// Constants
// Solidity Panic Codes
#define constant COMPILER_PANIC = 0x00
#define constant ASSERT_FALSE = 0x01
#define constant ARITHMETIC_OVERFLOW = 0x11
#define constant DIVIDE_BY_ZERO = 0x12
#define constant INVALID_ENUM_VALUE = 0x21
#define constant INVALID_STORAGE_BYTE_ARRAY = 0x22
#define constant EMPTY_ARRAY_POP = 0x31
#define constant ARRAY_OUT_OF_BOUNDS = 0x32
#define constant MEMORY_TOO_LARGE = 0x41
#define constant UNINITIALIZED_FUNCTION_POINTER = 0x51

/*

Solidity Require. Error `string` MUST be no greater than 32 bytes.

MEMORY LAYOUT WHEN THROWN
| sig    || message offset                                                 || message length                                                 || message "revert"                                               |
0x08c379a  0000000000000000000000000000000000000000000000000000000000000020  0000000000000000000000000000000000000000000000000000000000000006  7265766572740000000000000000000000000000000000000000000000000000

*/
#define macro REQUIRE() = takes (3) returns (0) {
    // takes:       // [condition, message_length, message]
    do_not_throw    // [do_not_throw_jumpdest, condition, message_length, message]
    jumpi           // [message_length, message]
    __ERROR(Error)  // [error_sig, , message_length, message]
    0x00            // [mem_ptr, error_sig, message_length, message]
    mstore          // [message_length, message]
    0x20            // [message_offset, message_length, message]
    0x04            // [message_offset_ptr, message_offset, message_length, message]
    mstore          // [message_length, message]
    0x24            // [message_length_ptr, message_length, message]
    mstore          // [message]
    0x44            // [message_ptr, message]
    mstore          // []
    0x80            // [size]
    0x00            // [offset, size]
    revert          // []
    do_not_throw:   // [message_length, message]
        pop         // [message]
        pop         // []
}

/*

Solidity Panic.

MEMORY LAYOUT WHEN THROWN
| sig     || panic code                                                     |
0x4e487b71  0000000000000000000000000000000000000000000000000000000000000001

*/
#define macro PANIC() = takes (1) returns (0) {
    // takes:       // [panic_code]
    __ERROR(Panic)  // [panic_sig, panic_code]
    0x00            // [panic_sig_offset, panic_sig, panic_code]
    mstore          // [panic_code]
    0x04            // [panic_code_offset, panic_code]
    mstore          // []
    0x24            // [revert_size]
    0x00            // [revert_offset, revert_size]
    revert          // []
}

/*
Solidity Assert.

MEMORY LAYOUT WHEN THROWN
| sig     || assert failed panic code                                       |
0x4e487b71  0000000000000000000000000000000000000000000000000000000000000001

*/
#define macro ASSERT() = takes (1) returns (0) {
    // takes:               // [condition]
    do_not_panic            // [do_not_panic_jumpdest, condition]
    jumpi                   // []
    [ASSERT_FALSE]          // [assert_false]
    PANIC()                 // []
    do_not_panic:           // []
}

// Assert that two stack elements are equal
#define macro ASSERT_EQ() = {
    // takes:             [a, b]
    eq                 // [a == b]
    ASSERT()           // []
}

// Assert that two stack elements are not equal
#define macro ASSERT_NOT_EQ() = {
    // takes:             [a, b]
    eq iszero          // [a != b]
    ASSERT()           // []
}

// Assert that two memory offsets contain equal words
#define macro ASSERT_MEM_EQ(ptr_a, ptr_b) = {
    // takes:             []
    <ptr_b> mload      // [b]
    <ptr_a> mload      // [a, b]
    eq                 // [a == b]
    ASSERT()           // []
}

// Assert that two memory offsets do not contain equal words
#define macro ASSERT_MEM_NOT_EQ(ptr_a, ptr_b) = {
    // takes:             []
    <ptr_b> mload      // [b]
    <ptr_a> mload      // [a, b]
    eq iszero          // [a != b]
    ASSERT()           // []
}

// Assert that two storage slots contain equal words
#define macro ASSERT_STORAGE_EQ(slot_a, slot_b) = {
    // takes:             []
    <slot_b> sload     // [b]
    <slot_a> sload     // [a, b]
    eq                 // [a == b]
    ASSERT()           // []
}

// Assert that two storage slots do not contain equal words
#define macro ASSERT_STORAGE_NOT_EQ(slot_a, slot_b) = {
    // takes:             []
    <slot_b> sload     // [b]
    <slot_a> sload     // [a, b]
    eq iszero          // [a != b]
    ASSERT()           // []
}

/* Bubbles up revert data if call failed. Call directly after `call`, `staticcall`, `delegatecall`. */
#define macro BUBBLE_UP_IF_FAILED() = takes (1) returns (0) {
    // takes:       // [call_succeeded]
    call_succeeded  // [call_succeeded_jumpdest, call_succeeded]
    jumpi           // []
    returndatasize  // [returndatasize]
    0x00            // [memory_offset, returndatasize]
    returndatasize  // [returndatasize, memory_offset, returndatasize]
    dup2            // [returndata_offset, returndatasize, memory_offset, returndatasize]
    dup3            // [memory_offset, returndata_offset, returndatasize, memory_offset, returndatasize]
    returndatacopy  // [memory_offset, returndatasize]
    revert          // []
    call_succeeded:
}