github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/src/libraries/Clone.sol (about)

     1  // SPDX-License-Identifier: BSD
     2  pragma solidity ^0.8.15;
     3  
     4  /// @title Clone
     5  /// @author zefram.eth, Saw-mon & Natalie, clabby
     6  /// @notice Provides helper functions for reading immutable args from calldata
     7  /// @dev Original:
     8  ///      https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args/
     9  ///      blob/105efee1b9127ed7f6fedf139e1fc796ce8791f2/src/Clone.sol
    10  /// @dev MODIFICATIONS:
    11  ///      - Added `_getArgDynBytes` function.
    12  contract Clone {
    13      uint256 private constant ONE_WORD = 0x20;
    14  
    15      /// @notice Reads an immutable arg with type address
    16      /// @param argOffset The offset of the arg in the packed data
    17      /// @return arg The arg value
    18      function _getArgAddress(uint256 argOffset) internal pure returns (address arg) {
    19          uint256 offset = _getImmutableArgsOffset();
    20          assembly {
    21              arg := shr(0x60, calldataload(add(offset, argOffset)))
    22          }
    23      }
    24  
    25      /// @notice Reads an immutable arg with type uint256
    26      /// @param argOffset The offset of the arg in the packed data
    27      /// @return arg The arg value
    28      function _getArgUint256(uint256 argOffset) internal pure returns (uint256 arg) {
    29          uint256 offset = _getImmutableArgsOffset();
    30          assembly {
    31              arg := calldataload(add(offset, argOffset))
    32          }
    33      }
    34  
    35      /// @notice Reads an immutable arg with type bytes32
    36      /// @param argOffset The offset of the arg in the packed data
    37      /// @return arg The arg value
    38      function _getArgFixedBytes(uint256 argOffset) internal pure returns (bytes32 arg) {
    39          uint256 offset = _getImmutableArgsOffset();
    40          assembly {
    41              arg := calldataload(add(offset, argOffset))
    42          }
    43      }
    44  
    45      /// @notice Reads a uint256 array stored in the immutable args.
    46      /// @param argOffset The offset of the arg in the packed data
    47      /// @param arrLen Number of elements in the array
    48      /// @return arr The array
    49      function _getArgUint256Array(uint256 argOffset, uint64 arrLen) internal pure returns (uint256[] memory arr) {
    50          uint256 offset = _getImmutableArgsOffset() + argOffset;
    51          arr = new uint256[](arrLen);
    52  
    53          assembly {
    54              calldatacopy(add(arr, ONE_WORD), offset, shl(5, arrLen))
    55          }
    56      }
    57  
    58      /// @notice Reads a dynamic bytes array stored in the immutable args.
    59      /// @param argOffset The offset of the arg in the packed data
    60      /// @param arrLen Number of elements in the array
    61      /// @return arr The array
    62      function _getArgDynBytes(uint256 argOffset, uint64 arrLen) internal pure returns (bytes memory arr) {
    63          uint256 offset = _getImmutableArgsOffset() + argOffset;
    64          arr = new bytes(arrLen);
    65  
    66          assembly {
    67              calldatacopy(add(arr, ONE_WORD), offset, arrLen)
    68          }
    69      }
    70  
    71      /// @notice Reads an immutable arg with type uint64
    72      /// @param argOffset The offset of the arg in the packed data
    73      /// @return arg The arg value
    74      function _getArgUint64(uint256 argOffset) internal pure returns (uint64 arg) {
    75          uint256 offset = _getImmutableArgsOffset();
    76          assembly {
    77              arg := shr(0xc0, calldataload(add(offset, argOffset)))
    78          }
    79      }
    80  
    81      /// @notice Reads an immutable arg with type uint8
    82      /// @param argOffset The offset of the arg in the packed data
    83      /// @return arg The arg value
    84      function _getArgUint8(uint256 argOffset) internal pure returns (uint8 arg) {
    85          uint256 offset = _getImmutableArgsOffset();
    86          assembly {
    87              arg := shr(0xf8, calldataload(add(offset, argOffset)))
    88          }
    89      }
    90  
    91      /// @return offset The offset of the packed immutable args in calldata
    92      function _getImmutableArgsOffset() internal pure returns (uint256 offset) {
    93          assembly {
    94              offset := sub(calldatasize(), shr(0xf0, calldataload(sub(calldatasize(), 2))))
    95          }
    96      }
    97  }