From 4f38fa6ef7e17cf891c86f204f7ecb4875dd9cc1 Mon Sep 17 00:00:00 2001 From: narendra_reddy Date: Sun, 18 Aug 2024 21:45:49 +0530 Subject: [PATCH] add natspec docs to evm contract Bridge.sol --- ethereum/contracts/bridge/Bridge.sol | 413 +++++++++++++++++++++++---- 1 file changed, 357 insertions(+), 56 deletions(-) diff --git a/ethereum/contracts/bridge/Bridge.sol b/ethereum/contracts/bridge/Bridge.sol index f9db91bb59..219ad3b3c4 100644 --- a/ethereum/contracts/bridge/Bridge.sol +++ b/ethereum/contracts/bridge/Bridge.sol @@ -32,9 +32,34 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { uint64 indexed sequence ); - /* - * @dev Produce a AssetMeta message for a given token - */ + /** + * @notice Attests to a token by producing an `AssetMeta` message and publishing it. + * @dev This function gathers metadata for a given ERC20 token and generates an `AssetMeta` message. + * It then publishes the message to the Wormhole network. The function supports tokens that do not + * implement the optional ERC20 methods for symbol and name by handling missing values gracefully. + * @param tokenAddress The address of the ERC20 token to attest. + * @param nonce A unique identifier for the message to prevent replay attacks. + * @return sequence The sequence number of the published message, used to track the message on the Wormhole network. + * + * The `AssetMeta` message includes: + * - `payloadID`: The identifier for the asset meta payload (set to 2). + * - `tokenAddress`: The address of the ERC20 token, encoded as a 32-byte value. + * - `tokenChain`: The chain ID where the token resides. + * - `decimals`: The number of decimals used by the token. + * - `symbol`: The symbol of the token, encoded as a 32-byte value. + * - `name`: The name of the token, encoded as a 32-byte value. + * + * Emits: + * - A message on the Wormhole network with the encoded `AssetMeta` data. + * + * Requirements: + * - The token must be a valid ERC20 token address. + * - The function must be called with enough Ether to cover the Wormhole fee. + * + * Reverts: + * - The function may revert if the token contract does not support the `decimals`, `symbol`, or `name` methods, + * or if the Wormhole message publication fails. + */ function attestToken(address tokenAddress, uint32 nonce) public payable returns (uint64 sequence) { // decimals, symbol & token are not part of the core ERC20 token standard, so we need to support contracts that dont implement them (,bytes memory queriedDecimals) = tokenAddress.staticcall(abi.encodeWithSignature("decimals()")); @@ -70,9 +95,30 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { }(nonce, encoded, finality()); } - /* - * @notice Send eth through portal by first wrapping it to WETH. - */ + /** + * @notice Sends ETH through the portal by first wrapping it into WETH. + * @dev This function wraps the ETH sent with the transaction into WETH, deducts the Wormhole fee and arbiter fee, and then logs the transfer details. + * The function handles the wrapping, fee calculation, and transfer process, and returns the sequence number of the logged transfer. + * @param recipientChain The chain ID where the recipient is located. + * @param recipient The address of the recipient on the target chain, encoded as a 32-byte value. + * @param arbiterFee The fee paid to the arbiter for processing the transfer. + * @param nonce A unique identifier for the transfer to prevent replay attacks. + * @return sequence The sequence number of the logged transfer, used to track the transfer on the Wormhole network. + * + * The function performs the following steps: + * - Calls `_wrapAndTransferETH` to wrap the ETH into WETH, deducts fees, and refunds any excess ETH (dust) to the sender. + * - Logs the transfer details using `logTransfer`, which records the transaction on the Wormhole network. + * + * Emits: + * - A log entry with the transfer details including the wrapped WETH amount, arbiter fee, and Wormhole fee. + * + * Requirements: + * - The function must be called with enough ETH to cover the Wormhole fee and arbiter fee. + * - The wrapped amount must be sufficient after deducting fees. + * + * Reverts: + * - The function may revert if the internal `_wrapAndTransferETH` call fails due to insufficient ETH or other conditions. + */ function wrapAndTransferETH( uint16 recipientChain, bytes32 recipient, @@ -93,7 +139,7 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { ); } - /* + /** * @notice Send eth through portal by first wrapping it. * * @dev This type of transfer is called a "contract-controlled transfer". @@ -124,7 +170,32 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { payload ); } - + /** + * @notice Wraps ETH into WETH and handles the transfer process. + * @dev This internal function manages the wrapping of ETH into WETH, deducts the Wormhole fee, and ensures that any excess ETH (dust) is refunded to the sender. + * It also normalizes the amounts for the transfer and arbiter fee, and tracks the token amounts using `bridgeOut`. + * @param arbiterFee The fee paid to the arbiter for processing the transfer. + * @return transferResult The result of the transfer, including the token chain, token address, normalized amount, normalized arbiter fee, and Wormhole fee. + * + * The `transferResult` structure includes: + * - `tokenChain`: The chain ID where the WETH resides (the current chain). + * - `tokenAddress`: The address of the WETH contract, encoded as a 32-byte value. + * - `normalizedAmount`: The amount of WETH, normalized for decimal places. + * - `normalizedArbiterFee`: The arbiter fee, normalized for decimal places. + * - `wormholeFee`: The fee paid for using the Wormhole, which is deducted from the total value. + * + * Requirements: + * - The function requires that the total value sent (`msg.value`) is greater than the Wormhole fee. + * - The arbiter fee must be less than or equal to the amount of ETH available after deducting the Wormhole fee. + * + * Emits: + * - WETH deposits the ETH into the WETH contract. + * - Excess ETH (dust) is refunded to the sender. + * + * Reverts: + * - If the total value sent is smaller than the Wormhole fee, the transaction will revert with "value is smaller than wormhole fee". + * - If the arbiter fee exceeds the amount available after the Wormhole fee is deducted, the transaction will revert with "fee is bigger than amount minus wormhole fee". + */ function _wrapAndTransferETH(uint256 arbiterFee) internal returns (BridgeStructs.TransferResult memory transferResult) { uint wormholeFee = wormhole().messageFee(); @@ -160,9 +231,24 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { }); } - /* - * @notice Send ERC20 token through portal. - */ + /** + * @notice Transfers ERC20 tokens through the portal. + * @dev This function facilitates the transfer of ERC20 tokens across chains using the portal. + * It involves calling an internal function to handle the token transfer and then logging the transfer details. + * @param token The address of the ERC20 token to transfer. + * @param amount The amount of tokens to transfer. + * @param recipientChain The chain ID of the recipient's chain. + * @param recipient The address of the recipient on the target chain. + * @param arbiterFee The fee paid to the arbiter for processing the transfer. + * @param nonce A unique identifier for the transfer to prevent replay attacks. + * @return sequence The sequence number of the logged transfer, used to track the transfer on the target chain. + * + * Emits: + * - Transfer details are logged using `logTransfer`. + * + * Reverts: + * - The function will revert if the internal `_transferTokens` function fails or if the transfer logging fails. + */ function transferTokens( address token, uint256 amount, @@ -188,7 +274,7 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { ); } - /* + /** * @notice Send ERC20 token through portal. * * @dev This type of transfer is called a "contract-controlled transfer". @@ -225,9 +311,29 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { ); } - /* - * @notice Initiate a transfer - */ + /** + * @notice Initiates a token transfer. + * @dev This internal function handles the transfer of ERC20 tokens, including the processing of tokens on the current chain and burning tokens on foreign chains. + * It normalizes the amount of tokens and arbiter fees based on the token's decimal places, and ensures that dust amounts that cannot be bridged are not deposited. + * @param token The address of the ERC20 token to transfer. + * @param amount The amount of tokens to transfer. + * @param arbiterFee The fee paid to the arbiter for processing the transfer. + * @return transferResult The result of the transfer, including the token chain, token address, normalized amount, normalized arbiter fee, and wormhole fee. + * + * The `transferResult` structure includes: + * - `tokenChain`: The chain ID where the token resides. + * - `tokenAddress`: The address of the token contract. + * - `normalizedAmount`: The amount of tokens, normalized for decimal places. + * - `normalizedArbiterFee`: The arbiter fee, normalized for decimal places. + * - `wormholeFee`: The fee paid for using the wormhole, which is equal to the `msg.value`. + * + * Requirements: + * - The function assumes that `msg.sender` has authorized the contract to transfer tokens on their behalf. + * - The function assumes that the `TokenImplementation` contract is properly set up and can handle the `burn` operation. + * + * Reverts: + * - The function will revert if the token transfer fails or if the balance check operations do not behave as expected. + */ function _transferTokens(address token, uint256 amount, uint256 arbiterFee) internal returns (BridgeStructs.TransferResult memory transferResult) { // determine token parameters uint16 tokenChain; @@ -334,14 +440,7 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { * @return The sequence number of the published message. */ function logTransferWithPayload( - uint16 tokenChain, - bytes32 tokenAddress, - uint256 amount, - uint16 recipientChain, - bytes32 recipient, - uint256 callValue, - uint32 nonce, - bytes memory payload + - ) internal returns (uint64 sequence) { BridgeStructs.TransferWithPayload memory transfer = BridgeStructs .TransferWithPayload({ @@ -361,7 +460,23 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { finality() ); } - + /** + * @notice Updates the wrapped token by processing the encoded VAA (Verified Action Approval) from the Wormhole bridge. + * @dev This function parses and verifies the encoded virtual machine (VM) from the Wormhole bridge. + * It ensures the validity of the VM and checks that the VM is from a legitimate emitter. + * Finally, it parses the asset metadata and updates the wrapped token. + * @param encodedVm The encoded virtual machine (VM) data from the Wormhole bridge. + * @return token The address of the updated wrapped token. + * + * Requirements: + * - The `encodedVm` must be a valid Wormhole VM. + * - The VM must be from a verified emitter (bridge). + * - The asset metadata must be successfully parsed from the VM's payload. + * - The `_updateWrapped` function will handle the actual update of the wrapped token. + * + * Reverts: + * - If the VM is invalid or the emitter is not verified, the transaction will revert with the respective error. + */ function updateWrapped(bytes memory encodedVm) external returns (address token) { (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole().parseAndVerifyVM(encodedVm); @@ -381,7 +496,23 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { return wrapped; } - + /** + * @notice Creates a new wrapped token by processing the encoded VAA (Verified Action Approval) from the Wormhole bridge. + * @dev This function parses and verifies the encoded virtual machine (VM) from the Wormhole bridge. + * It ensures the validity of the VM and checks that the VM is from a legitimate emitter. + * After parsing the asset metadata, it creates a new wrapped token. + * @param encodedVm The encoded virtual machine (VM) data from the Wormhole bridge. + * @return token The address of the newly created wrapped token. + * + * Requirements: + * - The `encodedVm` must be a valid Wormhole VM. + * - The VM must be from a verified emitter (bridge). + * - The asset metadata must be successfully parsed from the VM's payload. + * - The `_createWrapped` function will handle the actual creation of the wrapped token. + * + * Reverts: + * - If the VM is invalid or the emitter is not verified, the transaction will revert with the respective error. + */ function createWrapped(bytes memory encodedVm) external returns (address token) { (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole().parseAndVerifyVM(encodedVm); @@ -392,7 +523,25 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { return _createWrapped(meta, vm.sequence); } - // Creates a wrapped asset using AssetMeta + /** + * @notice Creates a new wrapped asset using the provided `AssetMeta` information. + * @dev This function deploys a new `BridgeToken` contract as a wrapped version of the token specified by the `AssetMeta`. + * It requires that the token to be wrapped is from a foreign chain (i.e., not the current chain). + * The function uses `create2` to deploy the `BridgeToken` contract with a unique address determined by the token's chain ID and address. + * It also initializes the `BridgeToken` contract with relevant parameters. + * @param meta The metadata for the asset to be wrapped, represented by the `BridgeStructs.AssetMeta` structure. + * @param sequence The sequence number used to initialize the `BridgeToken`. + * @return token The address of the newly created wrapped asset. + * + * Requirements: + * - The `tokenChain` in `meta` must not match the current chain ID. + * - A wrapped asset must not already exist for the given `tokenChain` and `tokenAddress`. + * + * Reverts: + * - If the token chain is the same as the current chain ID, the transaction will revert with "can only wrap tokens from foreign chains". + * - If a wrapped asset already exists for the specified token, the transaction will revert with "wrapped asset already exists". + * - If the deployment of the `BridgeToken` contract fails, the transaction will revert with no data. + */ function _createWrapped(BridgeStructs.AssetMeta memory meta, uint64 sequence) internal returns (address token) { require(meta.tokenChain != chainId(), "can only wrap tokens from foreign chains"); require(wrappedAsset(meta.tokenChain, meta.tokenAddress) == address(0), "wrapped asset already exists"); @@ -430,7 +579,7 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { setWrappedAsset(meta.tokenChain, meta.tokenAddress, token); } - /* + /** * @notice Complete a contract-controlled transfer of an ERC20 token. * * @dev The transaction can only be redeemed by the recipient, typically a @@ -444,7 +593,7 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { return _completeTransfer(encodedVm, false); } - /* + /** * @notice Complete a contract-controlled transfer of WETH, and unwrap to ETH. * * @dev The transaction can only be redeemed by the recipient, typically a @@ -458,7 +607,7 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { return _completeTransfer(encodedVm, true); } - /* + /** * @notice Complete a transfer of an ERC20 token. * * @dev The msg.sender gets paid the associated fee. @@ -469,7 +618,7 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { _completeTransfer(encodedVm, false); } - /* + /** * @notice Complete a transfer of WETH and unwrap to eth. * * @dev The msg.sender gets paid the associated fee. @@ -480,7 +629,7 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { _completeTransfer(encodedVm, true); } - /* + /** * @dev Truncate a 32 byte array to a 20 byte address. * Reverts if the array contains non-0 bytes in the first 12 bytes. * @@ -491,7 +640,41 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { return address(uint160(uint256(b))); } - // Execute a Transfer message + /** + * @notice Executes a transfer message, handling the transfer of tokens or ETH as specified by the Wormhole message. + * @dev This internal function parses and verifies the Wormhole message, processes the transfer by either + * unwrapping WETH or transferring ERC20 tokens, and manages the associated fees. It also ensures + * that the transfer is completed only once and emits a `TransferRedeemed` event. + * @param encodedVm The encoded Wormhole message to be processed. + * @param unwrapWETH A boolean indicating whether to unwrap WETH into ETH during the transfer. + * @return The payload of the Wormhole message. + * + * The function performs the following steps: + * - Parses and verifies the Wormhole message to ensure it is valid and from an authorized emitter. + * - Determines whether the transfer is of type 3 (with payload) and verifies the sender if so. + * - Checks if the transfer has already been completed to prevent double processing. + * - Emits a `TransferRedeemed` event to signal that the transfer has been processed. + * - Determines the appropriate token contract and checks if WETH needs to be unwrapped. + * - Queries the token's decimals and adjusts the amounts based on the token's decimal precision. + * - Transfers the arbiter fee to the arbiter if applicable, either unwrapping WETH or transferring ERC20 tokens. + * - Transfers the remaining amount to the recipient, handling both WETH and ERC20 tokens. + * + * Requirements: + * - The Wormhole message must be valid and from an authorized emitter. + * - The transfer must not have been completed previously. + * - If `unwrapWETH` is true, the token must be WETH. + * - The arbiter fee must be less than or equal to the transferred amount. + * - If `unwrapWETH` is true, sufficient ETH must be available to withdraw and transfer. + * + * Emits: + * - `TransferRedeemed` event indicating that the transfer has been processed. + * + * Reverts: + * - If the Wormhole message is invalid or from an unauthorized emitter. + * - If the transfer has already been completed. + * - If the arbiter fee is greater than the transferred amount. + * - If `unwrapWETH` is true and the token is not WETH. + */ function _completeTransfer(bytes memory encodedVm, bool unwrapWETH) internal returns (bytes memory) { (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole().parseAndVerifyVM(encodedVm); @@ -592,6 +775,21 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { return bridgeContracts(vm.emitterChainId) == vm.emitterAddress; } + /** + * @notice Encodes the asset metadata into a single `bytes` object. + * @dev This function takes the `AssetMeta` structure and encodes its fields into a `bytes` array. + * The fields are packed together using `abi.encodePacked`. + * @param meta The asset metadata to encode, represented by the `BridgeStructs.AssetMeta` structure. + * @return encoded The encoded asset metadata as a `bytes` array. + * + * The encoded metadata includes: + * - `payloadID`: The ID of the payload. + * - `tokenAddress`: The address of the token. + * - `tokenChain`: The chain ID where the token resides. + * - `decimals`: The number of decimals the token uses. + * - `symbol`: The symbol of the token. + * - `name`: The name of the token. + */ function encodeAssetMeta(BridgeStructs.AssetMeta memory meta) public pure returns (bytes memory encoded) { encoded = abi.encodePacked( meta.payloadID, @@ -603,6 +801,23 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { ); } + /** + * @notice Encodes the transfer data into a single `bytes` object. + * @dev This function takes the `Transfer` structure and encodes its fields into a `bytes` array. + * The fields are packed together using `abi.encodePacked`. + * @param transfer The transfer data to encode, represented by the `BridgeStructs.Transfer` structure. + * @return encoded The encoded transfer data as a `bytes` array. + * + * The encoded transfer data includes: + * - `payloadID`: The ID of the payload. + * - `amount`: The amount being transferred. + * - `tokenAddress`: The address of the token being transferred. + * - `tokenChain`: The chain ID where the token resides. + * - `to`: The recipient address. + * - `toChain`: The chain ID of the recipient. + * - `fee`: The fee associated with the transfer. + */ + function encodeTransfer(BridgeStructs.Transfer memory transfer) public pure returns (bytes memory encoded) { encoded = abi.encodePacked( transfer.payloadID, @@ -614,7 +829,23 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { transfer.fee ); } - + /** + * @notice Encodes the transfer data with an additional payload into a single `bytes` object. + * @dev This function takes the `TransferWithPayload` structure and encodes its fields into a `bytes` array. + * The fields are packed together using `abi.encodePacked`. + * @param transfer The transfer data with payload to encode, represented by the `BridgeStructs.TransferWithPayload` structure. + * @return encoded The encoded transfer data with payload as a `bytes` array. + * + * The encoded transfer data includes: + * - `payloadID`: The ID of the payload. + * - `amount`: The amount being transferred. + * - `tokenAddress`: The address of the token being transferred. + * - `tokenChain`: The chain ID where the token resides. + * - `to`: The recipient address. + * - `toChain`: The chain ID of the recipient. + * - `fromAddress`: The address of the sender. + * - `payload`: Additional payload data associated with the transfer. + */ function encodeTransferWithPayload(BridgeStructs.TransferWithPayload memory transfer) public pure returns (bytes memory encoded) { encoded = abi.encodePacked( transfer.payloadID, @@ -632,9 +863,29 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { payloadID = encoded.toUint8(0); } - /* - * @dev Parse a token metadata attestation (payload id 2) - */ + /** + * @notice Parses encoded asset metadata and returns it as an `AssetMeta` structure. + * @dev This function decodes the provided `bytes` array into an `AssetMeta` structure. + * The function sequentially extracts the fields from the encoded data and verifies the integrity of the data. + * @param encoded The encoded asset metadata as a `bytes` array. + * @return meta The parsed asset metadata represented by the `BridgeStructs.AssetMeta` structure. + * + * The decoded asset metadata includes: + * - `payloadID`: The ID of the payload (must be 2 for valid `AssetMeta`). + * - `tokenAddress`: The address of the token. + * - `tokenChain`: The chain ID where the token resides. + * - `decimals`: The number of decimals the token uses. + * - `symbol`: The symbol of the token. + * - `name`: The name of the token. + * + * Requirements: + * - The `payloadID` must be 2, indicating valid `AssetMeta` data. + * - The length of the encoded data must match the expected length after parsing. + * + * Reverts: + * - If the `payloadID` is not 2, the transaction will revert with "invalid AssetMeta". + * - If the length of the encoded data does not match the expected length after parsing, the transaction will revert with "invalid AssetMeta". + */ function parseAssetMeta(bytes memory encoded) public pure returns (BridgeStructs.AssetMeta memory meta) { uint index = 0; @@ -661,12 +912,30 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { require(encoded.length == index, "invalid AssetMeta"); } - /* - * @dev Parse a token transfer (payload id 1). - * - * @params encoded The byte array corresponding to the token transfer (not - * the whole VAA, only the payload) - */ + /** + * @notice Parses encoded transfer data and returns it as a `Transfer` structure. + * @dev This function decodes the provided `bytes` array into a `Transfer` structure. + * The function sequentially extracts the fields from the encoded data and verifies the integrity of the data. + * @param encoded The encoded transfer data as a `bytes` array. + * @return transfer The parsed transfer data represented by the `BridgeStructs.Transfer` structure. + * + * The decoded transfer data includes: + * - `payloadID`: The ID of the payload (must be 1 for valid `Transfer` data). + * - `amount`: The amount being transferred. + * - `tokenAddress`: The address of the token being transferred. + * - `tokenChain`: The chain ID where the token resides. + * - `to`: The recipient address. + * - `toChain`: The chain ID of the recipient. + * - `fee`: The fee associated with the transfer. + * + * Requirements: + * - The `payloadID` must be 1, indicating valid `Transfer` data. + * - The length of the encoded data must match the expected length after parsing. + * + * Reverts: + * - If the `payloadID` is not 1, the transaction will revert with "invalid Transfer". + * - If the length of the encoded data does not match the expected length after parsing, the transaction will revert with "invalid Transfer". + */ function parseTransfer(bytes memory encoded) public pure returns (BridgeStructs.Transfer memory transfer) { uint index = 0; @@ -696,12 +965,29 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { require(encoded.length == index, "invalid Transfer"); } - /* - * @dev Parse a token transfer with payload (payload id 3). - * - * @params encoded The byte array corresponding to the token transfer (not - * the whole VAA, only the payload) - */ + /** + * @notice Parses encoded transfer data with an additional payload and returns it as a `TransferWithPayload` structure. + * @dev This function decodes the provided `bytes` array into a `TransferWithPayload` structure. + * The function sequentially extracts the fields from the encoded data and verifies the integrity of the data. + * @param encoded The encoded transfer data with payload as a `bytes` array. + * @return transfer The parsed transfer data with payload, represented by the `BridgeStructs.TransferWithPayload` structure. + * + * The decoded transfer data includes: + * - `payloadID`: The ID of the payload (must be 3 for valid `TransferWithPayload` data). + * - `amount`: The amount being transferred. + * - `tokenAddress`: The address of the token being transferred. + * - `tokenChain`: The chain ID where the token resides. + * - `to`: The recipient address. + * - `toChain`: The chain ID of the recipient. + * - `fromAddress`: The address of the sender. + * - `payload`: Additional payload data associated with the transfer. + * + * Requirements: + * - The `payloadID` must be 3, indicating valid `TransferWithPayload` data. + * + * Reverts: + * - If the `payloadID` is not 3, the transaction will revert with "invalid Transfer". + */ function parseTransferWithPayload(bytes memory encoded) public pure returns (BridgeStructs.TransferWithPayload memory transfer) { uint index = 0; @@ -731,14 +1017,29 @@ contract Bridge is BridgeGovernance, ReentrancyGuard { transfer.payload = encoded.slice(index, encoded.length - index); } - /* - * @dev Parses either a type 1 transfer or a type 3 transfer ("transfer with - * payload") as a Transfer struct. The fee is set to 0 for type 3 - * transfers, since they have no fees associated with them. - * - * The sole purpose of this function is to get around the local - * variable count limitation in _completeTransfer. - */ + /** + * @notice Parses an encoded transfer data into a `Transfer` structure. + * @dev This function decodes either a type 1 transfer or a type 3 transfer ("transfer with payload") into a `Transfer` structure. + * For type 3 transfers, which have no fees, the fee is set to 0. + * This function helps circumvent local variable count limitations in `_completeTransfer`. + * @param encoded The encoded transfer data as a `bytes` array. + * @return transfer The parsed transfer data represented by the `BridgeStructs.Transfer` structure. + * + * The decoded transfer data includes: + * - `payloadID`: The ID of the payload (1 for type 1 transfers, 3 for type 3 transfers). + * - `amount`: The amount being transferred. + * - `tokenAddress`: The address of the token being transferred. + * - `tokenChain`: The chain ID where the token resides. + * - `to`: The recipient address. + * - `toChain`: The chain ID of the recipient. + * - `fee`: The fee associated with the transfer (set to 0 for type 3 transfers). + * + * Requirements: + * - The `payloadID` must be either 1 or 3, indicating valid transfer types. + * + * Reverts: + * - If the `payloadID` is not 1 or 3, the transaction will revert with "Invalid payload id". + */ function _parseTransferCommon(bytes memory encoded) public pure returns (BridgeStructs.Transfer memory transfer) { uint8 payloadID = parsePayloadID(encoded);