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 }