flashloan-rs 0.2.1

Minimal Multicall3 Flashloan Module
Documentation
/// @title HuffCloneLib
/// @notice SPDX-License-Identifier: MIT
/// @notice Clones with Immutable Args Library
/// @author wighawag <https://github.com/wighawag>
/// @author zefram <https://github.com/boredGenius>
/// @author hari <https://github.com/hrkrshnn>
/// @author z0r0z <https://github.com/z0r0z>
/// @author clabby <https://github.com/clabby>
/// @notice Adapted from wighawag (https://github.com/wighawag/clones-with-immutable-args/blob/master/src/ClonesWithImmutableArgs.sol)

/// @notice Creates a clone proxy of the implementation contract, with immutable args
/// @dev data cannot exceed 65535 bytes, since 2 bytes are used to store the data length
/// @param err       The jumpdest to jump to if an error occurs
/// @param dest_ptr  The memory pointer to store the creation code of the clone at
/// @param impl_addr The address of the implementation contract to clone
/// @param data_ptr  Pointer to beginning of encoded immutable args in memory
/// @return instance The address of the created clone
#define macro CLONE(err, dest_ptr) = takes(2) returns (1) {
    // Input Stack:        [impl_addr, data_ptr]
    dup2 mload          // [data_len, impl_addr, data_ptr]
    dup1 0x02 add       // [extra_len, data_len, impl_addr, data_ptr]
    dup1 0x41 add       // [creation_size, extra_len, data_len, impl_addr, data_ptr]
    0x0A dup2 sub       // [run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]

    __RIGHTPAD(0x61)    // [0x61..., run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    <dest_ptr> mstore   // [run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    dup1 0xF0 shl       // [run_size << 0xF0, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    <dest_ptr> 0x01 add // [dest_ptr + 0x01, run_size << 0xF0, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    mstore              // [run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]

    __RIGHTPAD(0x3d81600a3d39f33d3d3d3d363d3d3761)
    <dest_ptr> 0x03 add // [dest_ptr + 0x03, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    mstore              // [run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    dup3 0xF0 shl       // [extra_len << 0xF0, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    <dest_ptr> 0x13 add // [dest_ptr + 0x13, extra_len << 0xF0, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    mstore              // [run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]

    __RIGHTPAD(0x603736393661)
    <dest_ptr> 0x15 add // [dest_ptr + 0x15, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    mstore              // [run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    dup3 0xF0 shl       // [extra_len << 0xF0, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    <dest_ptr> 0x1B add // [dest_ptr + 0x1B, extra_len << 0xF0, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    mstore              // [run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]

    __RIGHTPAD(0x013d73)
    <dest_ptr> 0x1D add // [dest_ptr + 0x1D, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    mstore              // [run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    dup5 0x60 shl       // [impl_addr << 0x60, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    <dest_ptr> 0x20 add // [dest_ptr + 0x20, impl_addr << 0x60, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    mstore              // [run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]

    __RIGHTPAD(0x5af43d3d93803e603557fd5bf3)
    <dest_ptr> 0x34 add // [dest_ptr + 0x34, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    mstore              // [run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]

    ////////////////////////////////
    //       APPENDED DATA        //
    ////////////////////////////////

    // Subtract 0x02 from extra_len
    0x02 dup4 sub       // [extra_len - 0x02, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    swap3 pop           // [run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]

    // copy_ptr = data_ptr + 0x41
    <dest_ptr> 0x41 add // [copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]

    // Increase data_ptr by 0x20
    swap6 0x20 add      // [data_ptr + 0x20, run_size, creation_size, extra_len, data_len, impl_addr, copy_ptr]
    swap6               // [copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]

    // counter = extra_len
    dup4                // [counter, copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
    memcopy_loop:
        dup8 mload      // [data, counter, copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
        dup3 mstore     // [counter, copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]

        swap1 0x20 add  // [copy_ptr + 0x20, counter, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
        swap1           // [counter, copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
        swap7 0x20 add  // [data_ptr + 0x20, copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, counter]
        swap7           // [counter, copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]

        0x20 swap1 sub  // [counter, copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]

        dup1 0x20 gt    // [0x20 > counter, counter, copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
        iszero memcopy_loop jumpi
    post_loop:
        dup1            // [counter, counter, copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
        0x01            // [0x01, counter, counter, copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
        swap1           // [counter, 0x01, counter, copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
        0x20 sub        // [0x20 - counter, 0x01, counter, copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
        0x100 exp       // [0x100 ** (0x20 - counter), 0x01, counter, copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
        sub not         // [mask, counter, copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]

        dup9 mload and  // [data & mask, counter, copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
        dup3 mstore     // [counter, copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]

        add             // [copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
        dup4 0xF0 shl   // [extra_len << 0xF0, copy_ptr, run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]
        swap1 mstore    // [run_size, creation_size, extra_len, data_len, impl_addr, data_ptr]

        pop <dest_ptr>  // [dest_ptr, creation_size, extra_len, data_len, impl_addr, data_ptr]
        0x00 create     // [instance, extra_len, data_len, impl_addr, run_size]

        // Revert if deployment failed
        dup1 iszero err jumpi

        // Clean stack:
        swap4           // [run_size, extra_len, data_len, impl_addr, instance]
        pop pop pop pop // [instance]

    // Return stack:       [instance]
}