/// @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:
}