11// SPDX-License-Identifier: MIT
22pragma solidity ^ 0.8.4 ;
33
4+ import {FinalityCodec} from "./FinalityCodec.sol " ;
5+
46/// @notice Gas-optimized assembly version of ExtraArgsCodec library.
57library ExtraArgsCodec {
68 error InvalidDataLength (EncodingErrorLocation location , uint256 offset );
@@ -14,7 +16,7 @@ library ExtraArgsCodec {
1416
1517 // Base size excludes all variable-length fields (CCV addresses/args, executor address, executorArgs, tokenReceiver,
1618 // tokenArgs).
17- // Encoding order: tag(4) + gasLimit(4) + blockConfirmations (2) + ccvsLength(1) + executorLength(1) +
19+ // Encoding order: tag(4) + gasLimit(4) + finalityConfig (2) + ccvsLength(1) + executorLength(1) +
1820 // executorArgsLength(2) + tokenReceiverLength(1) + tokenArgsLength(2) = 17 bytes.
1921 uint256 public constant GENERIC_EXTRA_ARGS_V3_BASE_SIZE = 4 + 4 + 2 + 1 + 1 + 2 + 1 + 2 ;
2022 uint256 public constant GENERIC_EXTRA_ARGS_V3_STATIC_LENGTH_SIZE = 4 + 4 + 2 + 1 ;
@@ -49,7 +51,7 @@ library ExtraArgsCodec {
4951 /// Static length fields.
5052 /// bytes4 tag; Version tag.
5153 /// uint32 gasLimit; Gas limit for the callback on the destination chain.
52- /// uint16 blockConfirmations ; Number of block confirmations to wait for (0 = default finality) .
54+ /// bytes2 finalityConfig ; Finality config (see `FinalityCodec`): block depth and/or flags .
5355 /// uint8 ccvsLength; Number of cross-chain verifiers.
5456 ///
5557 /// Variable length fields (per CCV, repeated ccvsLength times).
@@ -78,12 +80,9 @@ library ExtraArgsCodec {
7880 /// There are various ways to estimate the gas required for a callback on the destination chain, depending on the
7981 /// chain family. Please refer to the documentation for each chain for more details.
8082 uint32 gasLimit;
81- /// @notice The number of block confirmations to wait for. 0 means the default finality that the CCV considers
82- /// final. Any non-zero value means a block depth. CCVs, Pools and the executor may all reject this value by
83- /// reverting the transaction on the source chain if they do not want to take on the risk of the block confirmations
84- /// specified.
83+ /// @notice The finality config, see FinalityCodec for encoding details.
8584 /// @dev May be zero to indicate waiting for finality is desired.
86- uint16 blockConfirmations ;
85+ bytes2 finalityConfig ;
8786 /// @notice An array of CCV addresses representing the cross-chain verifiers to be used for the message.
8887 /// @dev May be empty to specify the default verifier(s) should be used.
8988 address [] ccvs;
@@ -116,15 +115,15 @@ library ExtraArgsCodec {
116115 bytes tokenArgs;
117116 }
118117
119- /// @notice Creates a basic encoded GenericExtraArgsV3 with only gasLimit and blockConfirmations set.
118+ /// @notice Creates a basic encoded GenericExtraArgsV3 with only gasLimit and block-depth finality set.
120119 /// @param gasLimit The gas limit for the callback on the destination chain.
121- /// @param blockConfirmations The user requested number of block confirmations .
120+ /// @param blockDepth Block depth encoded via `FinalityCodec._encodeBlockDepth` (no upper flag bits) .
122121 /// @return encoded The encoded extra args as bytes. These are ready to be passed into CCIP functions.
123122 function _getBasicEncodedExtraArgsV3 (
124123 uint32 gasLimit ,
125- uint16 blockConfirmations
124+ uint16 blockDepth
126125 ) internal pure returns (bytes memory ) {
127- return abi.encodePacked (GENERIC_EXTRA_ARGS_V3_TAG, gasLimit, blockConfirmations , bytes7 (0 ));
126+ return abi.encodePacked (GENERIC_EXTRA_ARGS_V3_TAG, gasLimit, FinalityCodec. _encodeBlockDepth (blockDepth) , bytes7 (0 ));
128127 }
129128
130129 enum SVMTokenReceiverUsage {
@@ -395,7 +394,7 @@ library ExtraArgsCodec {
395394 );
396395
397396 bytes memory staticFields =
398- abi.encodePacked (GENERIC_EXTRA_ARGS_V3_TAG, extraArgs.gasLimit, extraArgs.blockConfirmations , uint8 (ccvsLength));
397+ abi.encodePacked (GENERIC_EXTRA_ARGS_V3_TAG, extraArgs.gasLimit, extraArgs.finalityConfig , uint8 (ccvsLength));
399398
400399 uint256 ptr;
401400 // This block is memory safe because it only writes to the allocated `encoded` bytes.
@@ -462,15 +461,17 @@ library ExtraArgsCodec {
462461 let gasLimit := calldataload (add (encoded.offset, 4 ))
463462 mstore (extraArgs, and (shr (224 , gasLimit), 0xFFFFFFFF ))
464463
465- // Read block confirmations (2 bytes).
466- let blockConfirmations := calldataload (add (encoded.offset, 8 ))
467- mstore (add (extraArgs, 32 ), and (shr (240 , blockConfirmations), 0xFFFF ))
464+ // Read finalityConfig (2 bytes).
465+ // bytes2 is left-aligned in memory, so mask the top 2 bytes of the loaded word directly
466+ // instead of shifting right (which would produce a right-aligned uint that reads back as zero).
467+ let finalityWord := calldataload (add (encoded.offset, 8 ))
468+ mstore (add (extraArgs, 32 ), and (finalityWord, shl (240 , 0xFFFF )))
468469
469470 // Read ccvs length (1 byte).
470471 ccvsLength := byte (0 , calldataload (add (encoded.offset, 10 )))
471472 }
472473
473- uint256 offset = GENERIC_EXTRA_ARGS_V3_STATIC_LENGTH_SIZE; // Skip tag, gasLimit, blockConfirmations , ccvsLength.
474+ uint256 offset = GENERIC_EXTRA_ARGS_V3_STATIC_LENGTH_SIZE; // Skip tag, gasLimit, finalityConfig , ccvsLength.
474475
475476 // Allocate arrays for CCVs.
476477 extraArgs.ccvs = new address [](ccvsLength);
0 commit comments