Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement ChainflipFacet [ChainflipFacet v1.0.0,IChainflip v1.0.0,ReceiverChainflip v1.0.0] #984

Draft
wants to merge 62 commits into
base: main
Choose a base branch
from

Conversation

ezynda3
Copy link
Contributor

@ezynda3 ezynda3 commented Feb 10, 2025

Which Jira task belongs to this PR?

LF-12192

Why did I implement it this way?

Checklist before requesting a review

Checklist for reviewer (DO NOT DEPLOY and contracts BEFORE CHECKING THIS!!!)

  • I have checked that any arbitrary calls to external contracts are validated and or restricted
  • I have checked that any privileged calls (i.e. storage modifications) are validated and or restricted
  • I have ensured that any new contracts have had AT A MINIMUM 1 preliminary audit conducted on by <company/auditor>

@ezynda3 ezynda3 added the WIP Work in progress label Feb 10, 2025
Copy link
Contributor

coderabbitai bot commented Feb 10, 2025

Walkthrough

These changes introduce new functionality for Chainflip bridging across multiple networks. A JSON configuration file for vault addresses is added, along with updated documentation for the Chainflip Facet. New smart contracts are implemented, including ChainflipFacet, ReceiverChainflip, and IChainflipVault. Deployment scripts are enhanced, and demo scripts for swapping exact ETH for ERC20 tokens are introduced. Extensive unit tests for the new contracts are included. Additionally, deployment configuration JSON files are modified to reflect new facet entries, version updates, and other relevant changes.

Changes

File(s) Change Summary
config/chainflip.json Introduces a new JSON configuration file defining vault addresses for mainnet and arbitrum.
docs/ChainflipFacet.md Adds documentation detailing the Chainflip Facet API, including new public methods and the ChainflipData struct.
script/demoScripts/demoChainflip.ts, script/demoScripts/utils/demoScriptHelpers.ts Adds a comprehensive demo script for Chainflip bridging and introduces a function for swapping exact ETH for ERC20 tokens on Uniswap.
script/deploy/facets/DeployChainflipFacet.s.sol, script/deploy/facets/UpdateChainflipFacet.s.sol, script/deploy/facets/DeployReceiverChainflip.s.sol Introduces deployment scripts for deploying and updating ChainflipFacet and for deploying ReceiverChainflip, including configuration reading and argument encoding.
src/Facets/ChainflipFacet.sol, src/Interfaces/IChainflip.sol, src/Periphery/ReceiverChainflip.sol Adds new smart contracts: ChainflipFacet with bridging methods, IChainflipVault interface for cross-chain operations, and ReceiverChainflip for handling token swaps and message passing.
test/solidity/Facets/ChainflipFacet.t.sol, test/solidity/Periphery/ReceiverChainflip.t.sol, test/solidity/utils/TestBase.sol Introduces unit tests for ChainflipFacet and ReceiverChainflip, and adds a helper function to read JSON configurations from file paths.
deployments/_deployments_log_file.json, deployments/arbitrum.diamond.staging.json, deployments/arbitrum.staging.json Updates deployment configuration files by adding new ChainflipFacet log entries, removing deprecated facets, updating versions, and modifying proxy addresses and facet entries.
deployments/mainnet.diamond.staging.json, deployments/mainnet.staging.json Adds new entries for ReceiverChainflip in deployment configurations, reflecting its deployment details.

Suggested labels

AuditCompleted

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • JIRA integration encountered authorization issues. Please disconnect and reconnect the integration in the CodeRabbit UI.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@lifi-action-bot lifi-action-bot marked this pull request as draft February 10, 2025 13:31
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (5)
src/Facets/ChainflipFacet.sol (2)

13-13: Remove debug import in production.

It seems you're importing the console utility (line 13) for debugging. Consider removing or wrapping it with conditional compilation for production to avoid unnecessary overhead or inadvertent log leakage.

-import { console } from "forge-std/console.sol";

100-159: Future-proof chain ID mappings.

The chain ID checks and consistent reverts for unsupported chains are well-defined. To accommodate future expansions, consider a more flexible mechanism (whitelisting, mapping, or dynamic registry) to reduce the need to modify contract code for additional chains.

script/deploy/facets/UpdateChainflipFacet.s.sol (1)

1-1: License compatibility check.

Currently the file is marked as UNLICENSED, while other contracts use MIT. This is typically fine for a deployment script, but confirm it aligns with your project’s licensing policy.

test/solidity/Facets/ChainflipFacet.t.sol (1)

74-78: Add test cases for invalid ChainflipData parameters.

The validChainflipData setup uses hardcoded values. Consider adding test cases for invalid parameters.

+    function testRevert_InvalidChainflipData() public {
+        ChainflipFacet.ChainflipData memory invalidData = ChainflipFacet.ChainflipData({
+            dstToken: 0,
+            cfParameters: ""
+        });
+        vm.expectRevert("Invalid destination token");
+        chainflipFacet.startBridgeTokensViaChainflip(bridgeData, invalidData);
+    }
docs/ChainflipFacet.md (1)

35-35: Fix typo in swap documentation.

The sentence has a grammatical error.

-Swapping is performed by a swap specific library that expects an array of calldata to can be run on various DEXs
+Swapping is performed by a swap-specific library that expects an array of calldata that can be run on various DEXs
🧰 Tools
🪛 LanguageTool

[uncategorized] ~35-~35: When ‘swap-specific’ is used as a modifier, it is usually spelled with a hyphen.
Context: ... parameter. Swapping is performed by a swap specific library that expects an array of callda...

(SPECIFIC_HYPHEN)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2cc7956 and 9870fed.

📒 Files selected for processing (8)
  • config/chainflip.json (1 hunks)
  • docs/ChainflipFacet.md (1 hunks)
  • script/demoScripts/demoChainflip.ts (1 hunks)
  • script/deploy/facets/DeployChainflipFacet.s.sol (1 hunks)
  • script/deploy/facets/UpdateChainflipFacet.s.sol (1 hunks)
  • src/Facets/ChainflipFacet.sol (1 hunks)
  • src/Interfaces/IChainflip.sol (1 hunks)
  • test/solidity/Facets/ChainflipFacet.t.sol (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • config/chainflip.json
🧰 Additional context used
🪛 LanguageTool
docs/ChainflipFacet.md

[uncategorized] ~35-~35: When ‘swap-specific’ is used as a modifier, it is usually spelled with a hyphen.
Context: ... parameter. Swapping is performed by a swap specific library that expects an array of callda...

(SPECIFIC_HYPHEN)


[uncategorized] ~47-~47: Possible missing comma found.
Context: ...alls to interact with the Facet In the following some sample calls are shown that allow ...

(AI_HYDRA_LEO_MISSING_COMMA)


[uncategorized] ~88-~88: Possible missing comma found.
Context: ...er from 30 USDT on Avalanche to USDC on Binance you can execute the following request: ...

(AI_HYDRA_LEO_MISSING_COMMA)

🪛 GitHub Actions: VersionControlAndAuditVerification
src/Interfaces/IChainflip.sol

[error] 1-1: File does not contain a version tag. Every version-controlled contract needs to have a custom:version tag in its code.

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: run-unit-tests
  • GitHub Check: enforce-min-test-coverage
🔇 Additional comments (3)
src/Facets/ChainflipFacet.sol (2)

52-72: Implementation of direct bridging logic looks consistent.

The logic for depositing assets and then calling _startBridge appears sound. Good use of existing modifiers such as nonReentrant, refundExcessNative, and the validation checks.


74-98: Implementation of swap-then-bridge flow is clear.

The approach of performing swaps first with _depositAndSwap before calling _startBridge is well-structured. The final minAmount assignment ensures correct bridging amounts. Nicely done.

script/deploy/facets/DeployChainflipFacet.s.sol (1)

24-30: Verify configuration path handling.

The path construction assumes a specific directory structure. Consider adding validation to ensure the config file exists.

✅ Verification successful

🏁 Script executed:

#!/bin/bash
# Check if the chainflip config file exists
if [ ! -f "config/chainflip.json" ]; then
  echo "Error: chainflip.json configuration file not found"
  exit 1
fi

# Validate JSON structure
jq -e '.mainnet.chainflipVault, .arbitrum.chainflipVault' config/chainflip.json > /dev/null

Length of output: 120


Configuration path handling verified.
The shell script confirms that the expected configuration file (config/chainflip.json) exists and contains valid JSON entries for both mainnet.chainflipVault and arbitrum.chainflipVault. No issues were detected with the configuration path, so additional validation in this area appears unnecessary.

@lifi-action-bot
Copy link
Collaborator

lifi-action-bot commented Feb 10, 2025

Test Coverage Report

Line Coverage: 79.00% (2104 / 2663 lines)
Function Coverage: 83.68% ( 359 / 429 functions)
Branch Coverage: 46.34% ( 247 / 533 branches)
Test coverage (79.00%) is above min threshold (76%). Check passed.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (5)
script/demoScripts/demoChainflip.ts (2)

40-41: Consider using environment variables for token addresses.

The USDC token address is hardcoded. For better flexibility and to prevent accidental deployments with incorrect addresses, consider using environment variables.

-const SRC_TOKEN_ADDRESS =
-    '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' as `0x${string}`
+if (!process.env.SRC_TOKEN_ADDRESS) {
+  throw new Error('SRC_TOKEN_ADDRESS environment variable is required')
+}
+const SRC_TOKEN_ADDRESS = process.env.SRC_TOKEN_ADDRESS as `0x${string}`

92-101: Consider adding error handling for bridge failures.

The bridge transaction could fail for various reasons (e.g., insufficient liquidity, network issues). Consider adding specific error handling and retry logic.

 await executeTransaction(
   () =>
     lifiDiamondContract.write.startBridgeTokensViaChainflip([
       bridgeData,
       chainflipData,
     ]),
   'Starting bridge tokens via Chainflip',
   publicClient,
   true
+  // Add retry options
+  {
+    maxRetries: 3,
+    retryDelay: 1000,
+    onError: (error) => {
+      console.error('Bridge failed:', error)
+      // Add specific error handling based on error type
+    }
+  }
 )
src/Facets/ChainflipFacet.sol (1)

31-39: Consider using an enum or mapping for chain IDs.

The current implementation uses constants for chain IDs. Consider using an enum or mapping for better maintainability and to prevent magic numbers.

-    uint256 private constant CHAIN_ID_ETHEREUM = 1;
-    uint256 private constant CHAIN_ID_ARBITRUM = 42161;
-    uint256 private constant CHAIN_ID_SOLANA = 1151111081099710;
-    uint256 private constant CHAIN_ID_BITCOIN = 20000000000001;
-
-    uint32 private constant CHAINFLIP_ID_ETHEREUM = 1;
-    uint32 private constant CHAINFLIP_ID_ARBITRUM = 4;
-    uint32 private constant CHAINFLIP_ID_SOLANA = 5;
-    uint32 private constant CHAINFLIP_ID_BITCOIN = 3;
+    enum ChainId {
+        ETHEREUM = 1,
+        ARBITRUM = 42161,
+        SOLANA = 1151111081099710,
+        BITCOIN = 20000000000001
+    }
+
+    mapping(ChainId => uint32) private chainflipIds = {
+        ChainId.ETHEREUM: 1,
+        ChainId.ARBITRUM: 4,
+        ChainId.SOLANA: 5,
+        ChainId.BITCOIN: 3
+    };
test/solidity/Facets/ChainflipFacet.t.sol (2)

81-85: Add test cases for different destination token IDs.

The test suite uses a fixed destination token ID of 6. Consider adding test cases for different token IDs to ensure the contract handles various scenarios correctly.

+    function test_CanBridgeTokensWithDifferentDestinationTokens() public {
+        uint32[] memory tokenIds = new uint32[](3);
+        tokenIds[0] = 6;  // USDC
+        tokenIds[1] = 1;  // Example token
+        tokenIds[2] = 2;  // Example token
+        
+        for (uint256 i = 0; i < tokenIds.length; i++) {
+            validChainflipData.dstToken = tokenIds[i];
+            vm.startPrank(USER_SENDER);
+            usdc.approve(_facetTestContractAddress, bridgeData.minAmount);
+            initiateBridgeTxWithFacet(false);
+            vm.stopPrank();
+        }
+    }

219-236: Add more edge cases for address validation.

The test only checks for empty addresses. Consider adding tests for invalid address formats and other edge cases.

+    function testRevert_WhenUsingInvalidSolanaAddress() public {
+        bridgeData.receiver = LibAsset.NON_EVM_ADDRESS;
+        bridgeData.destinationChainId = CHAIN_ID_SOLANA;
+        validChainflipData = ChainflipFacet.ChainflipData({
+            dstToken: 6,
+            nonEvmAddress: bytes32("invalid_solana_address"),
+            cfParameters: ""
+        });
+
+        vm.startPrank(USER_SENDER);
+        usdc.approve(_facetTestContractAddress, bridgeData.minAmount);
+        vm.expectRevert("Invalid Solana address format");
+        initiateBridgeTxWithFacet(false);
+        vm.stopPrank();
+    }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9870fed and ccf78b3.

📒 Files selected for processing (4)
  • script/demoScripts/demoChainflip.ts (1 hunks)
  • script/deploy/facets/UpdateChainflipFacet.s.sol (1 hunks)
  • src/Facets/ChainflipFacet.sol (1 hunks)
  • test/solidity/Facets/ChainflipFacet.t.sol (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • script/deploy/facets/UpdateChainflipFacet.s.sol
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: generate-tag
🔇 Additional comments (3)
script/demoScripts/demoChainflip.ts (1)

84-89: Verify the destination token ID.

The destination token ID is hardcoded to 6. Ensure this is the correct token ID for the destination chain.

✅ Verification successful

🏁 Script executed:

#!/bin/bash
# Search for any references to token IDs in the codebase to verify the correct value
rg -A 5 "dstToken: 6" .

Length of output: 2304


Destination Token ID Verification Confirmed

The codebase consistently sets dstToken to 6 in both the demo script and the test cases, implying that this value is intended for the destination chain. No discrepancies were found.

src/Facets/ChainflipFacet.sol (1)

153-181: Add reentrancy protection for token transfers.

While the contract inherits from ReentrancyGuard, ensure that the nonReentrant modifier is applied to all external methods that handle token transfers.

❌ Verification inconclusive

🏁 Script executed:

#!/bin/bash
# Search for external methods that handle token transfers
ast-grep --pattern 'function $name($_) external $_ {
  $$$
  transfer($_)
  $$$
}'

Length of output: 84


Action Required: Manually Verify NonReentrant Usage on External Token Transfer Methods
The initial automated search for a direct call to the transfer function did not produce any output. This suggests that token transfers may be performed indirectly (e.g., via the helper LibAsset.maxApproveERC20 or through external vault calls like xSwapNative and xSwapToken) rather than via explicit in-line transfer calls. However, the review comment raises a valid concern about ensuring that all externally callable methods that trigger token transfers are properly protected with the nonReentrant modifier.

To ensure that the contract is secure:

  • Manually inspect the external functions in src/Facets/ChainflipFacet.sol that perform token operations (such as those invoking LibAsset.maxApproveERC20, xSwapNative, or xSwapToken).
  • Confirm that each such function is indeed decorated with the nonReentrant modifier.
  • If any token transfer–handling function lacks this protection, add the modifier to mitigate potential reentrancy issues.

Since our automated search did not yield definitive evidence (likely due to abstraction of token transfers), please manually review the relevant functions to ensure robust reentrancy protection.

test/solidity/Facets/ChainflipFacet.t.sol (1)

149-183: Add validation for Solana address format.

The test uses a hardcoded Solana address. Consider adding validation to ensure the address follows the correct format.

❌ Verification inconclusive

🏁 Script executed:

#!/bin/bash
# Search for Solana address validation in the codebase
rg -A 5 "Solana.*address.*validation" .

Length of output: 41


Issue: Missing Validation for Solana Address Format

Our search confirms that there is no dedicated Solana address format validation logic anywhere in the codebase. The test in test/solidity/Facets/ChainflipFacet.t.sol is using a hardcoded Solana address without an accompanying check to ensure that the provided address conforms to expected Solana formatting guidelines. It is recommended that you add validation logic—either within the facet or before initiating the bridge transaction—to enforce the correct format for Solana addresses.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/Periphery/ReceiverChainflip.sol (1)

82-111: Catch block discards revert reason.

The try ... catch {} without capturing the revert reason helps automatically recover tokens but obscures debugging. If clarity is desired, consider catch Error(string memory reason) to log or emit the reason for easier troubleshooting.

Example:

} catch (bytes memory reason) {
+    // Optionally, decode or log the revert reason
     assetId.safeTransfer(receiver, amount);
     emit LiFiTransferRecovered(
         _transactionId,
         assetId,
         receiver,
         amount,
         block.timestamp
     );
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ccf78b3 and e20815f.

📒 Files selected for processing (2)
  • src/Periphery/ReceiverChainflip.sol (1 hunks)
  • test/solidity/Periphery/ReceiverChainflip.t.sol (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: generate-tag
🔇 Additional comments (7)
src/Periphery/ReceiverChainflip.sol (3)

19-21: Validate non-zero addresses for immutables.

Consider adding a check in the constructor to ensure that both _executor and _chainflipVault are non-zero addresses to prevent misconfiguration or accidental deployment with a null address.

Possible improvement example:

 constructor(
   address _owner,
   address _executor,
   address _chainflipVault
 ) WithdrawablePeriphery(_owner) {
+    require(_executor != address(0), "Executor address cannot be zero");
+    require(_chainflipVault != address(0), "Chainflip vault address cannot be zero");
     executor = IExecutor(_executor);
     chainflipVault = _chainflipVault;
 }

22-29: Modifier ensures restricted access.

The onlyChainflipVault modifier is concise and securely enforces access restrictions to cfReceive. This is a good approach to limit privileged calls solely to the designated Chainflip vault.


113-115: Empty fallback is acceptable.

The fallback function is correctly defined to receive native tokens. No further changes are required here.

test/solidity/Periphery/ReceiverChainflip.t.sol (4)

25-48: Initialization covers essential paths.

The setUp() function covers adequate setup steps, including reading configuration JSON files, labeling addresses for clarity, and deploying required contracts. This is well-structured and thorough.


50-59: Constructor test is simple and effective.

test_contractIsSetUpCorrectly() verifies key contract invariants (executor address, vault address). Spelling out these checks is a solid way to confirm proper deployment parameters.


112-139: Ensures privileged function is restricted.

test_revert_OnlyChainflipVaultCanCallCfReceive() properly checks that unauthorized entities cannot invoke cfReceive. This adds robust coverage for permission logic.


173-216: Recovery flow verified.

test_willReturnFundsToUserIfDstCallFails() demonstrates correct handling when a destination swap fails, ensuring user funds are returned. This thoroughly verifies error-handling and token recovery.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (7)
docs/ChainflipFacet.md (6)

13-19: Clarify Public Methods Documentation
The public methods are clearly listed along with concise descriptions. To further improve clarity, consider adding parameter-specific details or linking to corresponding implementation sections so that readers can easily cross-reference the information.


32-32: Enhance Guidance on Non-EVM Destinations
The note on setting the receiver in BridgeData for non-EVM destinations is useful. It might help to include a brief example or clarification on edge cases to further support developers using this configuration.


43-49: Improve Terminology: Use "swap-specific"
On line 47, the phrase "swap specific library" is used. For clarity and consistency with common terminology, consider using a hyphen to form "swap-specific library."

-Swapping is performed by a swap specific library that expects an array of calldata...
+Swapping is performed by a swap-specific library that expects an array of calldata...
🧰 Tools
🪛 LanguageTool

[uncategorized] ~47-~47: When ‘swap-specific’ is used as a modifier, it is usually spelled with a hyphen.
Context: ... parameter. Swapping is performed by a swap specific library that expects an array of callda...

(SPECIFIC_HYPHEN)


86-88: Enhance In-Text Explanation for the /quote Endpoint
The link to detailed documentation is helpful. To aid quick understanding, consider including a short inline summary of the key steps involved in using the /quote endpoint.


90-97: Punctuation Improvement in "Cross Only" Section
For improved readability, add a comma after "Arbitrum" in line 92.

-To get a transaction for a transfer from USDC on Ethereum to USDC on Arbitrum you can execute the following request:
+To get a transaction for a transfer from USDC on Ethereum to USDC on Arbitrum, you can execute the following request:
🧰 Tools
🪛 LanguageTool

[uncategorized] ~92-~92: Possible missing comma found.
Context: ...ansfer from USDC on Ethereum to USDC on Arbitrum you can execute the following request: ...

(AI_HYDRA_LEO_MISSING_COMMA)


98-104: Punctuation Improvement in "Swap & Cross" Section
Similarly, in line 100, consider inserting a comma after "Arbitrum" to enhance clarity.

-To get a transaction for a transfer from USDT on Ethereum to USDC on Arbitrum you can execute the following request:
+To get a transaction for a transfer from USDT on Ethereum to USDC on Arbitrum, you can execute the following request:
🧰 Tools
🪛 LanguageTool

[uncategorized] ~100-~100: Possible missing comma found.
Context: ...ansfer from USDT on Ethereum to USDC on Arbitrum you can execute the following request: ...

(AI_HYDRA_LEO_MISSING_COMMA)

script/deploy/facets/DeployReceiverChainflip.s.sol (1)

24-59: Configuration parsing is appropriate—consider validating missing or zero addresses.
The code properly reads from multiple JSON config files and returns addresses via abi.encode. Ensure the final constructor argument order matches the ReceiverChainflip contract requirements. It may be wise to guard against zero addresses if configurations are missing.

 function getConstructorArgs() internal override returns (bytes memory) {
     ...
+    require(refundWalletAddress != address(0), "Invalid refund wallet");
+    require(chainflipVault != address(0), "Invalid vault address");
+    require(executor != address(0), "Invalid executor address");
     return abi.encode(refundWalletAddress, executor, chainflipVault);
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e20815f and e30c1de.

📒 Files selected for processing (3)
  • docs/ChainflipFacet.md (1 hunks)
  • script/deploy/facets/DeployReceiverChainflip.s.sol (1 hunks)
  • script/deploy/resources/deployRequirements.json (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
script/deploy/facets/DeployReceiverChainflip.s.sol (1)
Learnt from: ezynda3
PR: lifinance/contracts#924
File: script/deploy/zksync/DeployReceiverStargateV2.s.sol:19-21
Timestamp: 2025-01-28T14:27:50.689Z
Learning: In LiFi's deployment scripts, the `deploy` method in `DeployScriptBase` handles the concatenation of constructor arguments with the contract's creation code, so child contracts don't need to concatenate the arguments explicitly.
🪛 LanguageTool
docs/ChainflipFacet.md

[uncategorized] ~47-~47: When ‘swap-specific’ is used as a modifier, it is usually spelled with a hyphen.
Context: ... parameter. Swapping is performed by a swap specific library that expects an array of callda...

(SPECIFIC_HYPHEN)


[uncategorized] ~92-~92: Possible missing comma found.
Context: ...ansfer from USDC on Ethereum to USDC on Arbitrum you can execute the following request: ...

(AI_HYDRA_LEO_MISSING_COMMA)


[uncategorized] ~100-~100: Possible missing comma found.
Context: ...ansfer from USDT on Ethereum to USDC on Arbitrum you can execute the following request: ...

(AI_HYDRA_LEO_MISSING_COMMA)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: generate-tag
🔇 Additional comments (14)
script/deploy/resources/deployRequirements.json (2)

572-581: ChainflipFacet Configuration Addition

The new "ChainflipFacet" entry follows the same structure as the existing entries. The use of "configData" with the _chainflipVault key, along with the provided "configFileName", "keyInConfigFile", and "allowToDeployWithZeroAddress": "false", is consistent with the project's configuration conventions.
Please verify that the "chainflip.json" file is properly set up and that the placeholder <NETWORK> is used consistently with other facets.


582-600: ReceiverChainflip Configuration Addition

The "ReceiverChainflip" configuration is well-formed. It correctly defines its "configData" with both the _owner (using "global.json" and ".refundWallet") and _chainflipVault keys (mirroring the settings of "ChainflipFacet"). In addition, the inclusion of the "contractAddresses" section for "Executor" with "allowToDeployWithZeroAddress": "false" aligns with the structure seen in other receiver configurations.
Ensure that these settings correctly map to the deployed contracts and that external calls to these addresses are properly validated per security best practices.

docs/ChainflipFacet.md (7)

1-6: Expand the "How it works" Section for Greater Clarity
The introduction is clear but could benefit from additional technical details. Consider elaborating on how the ChainflipFacet interacts with the ChainflipVault using DELEGATECALL and outlining the token transfer flow in more depth.


7-11: Effective Use of Mermaid Diagram
The Mermaid diagram visually explains the relationship between LiFiDiamond, ChainflipFacet, and Chainflip Vault well. As a suggestion, you might add labels or a brief legend if the diagram expands in complexity in the future.


20-30: Accurate and Informative ChainflipData Struct Documentation
The ChainflipData struct is well documented and clearly explains the purpose of each parameter. Ensure that any future changes to the contract implementation are also reflected here to maintain consistency.


34-42: Clear Overview of Supported Chains
The section on supported chains is informative. For added clarity, consider linking to external references or documentation that verifies these chain IDs.


51-55: Solid Explanation of LiFi Data Usage
The explanation regarding the BridgeData parameter and its role for analytics is clear and sufficient.


57-62: Clear Introduction to Sample Calls
The introductory text for sample calls sets the context well. It might be helpful to mention any prerequisites or assumptions briefly for developers new to the API.


63-84: Well-Structured JavaScript Example for Quote Result
The JavaScript snippet illustrating the quoteResult object is both clear and illustrative. Please ensure that if any field names change in the future, the example is updated accordingly.

script/deploy/facets/DeployReceiverChainflip.s.sol (5)

1-3: License and compiler version look fine.
These lines indicate a non-open source license and a modern Solidity compiler version, which are acceptable choices.


4-7: Imports are concise and well-structured.
All imports are relevant and appear to be aligned with the contract's deployment logic. No issues found.


8-10: Contract declaration and library usage look good.
The stdJson library is correctly applied to handle JSON parsing. No concerns here.


11-12: Constructor usage is consistent with the base class.
Passing "ReceiverChainflip" to the parent constructor follows the known pattern for DeployScriptBase.


13-22: Deploy logic appears correct but verify constructor argument handling.
Calling deploy(type(ReceiverChainflip).creationCode) without manual argument concatenation is correct because DeployScriptBase handles appending the constructor arguments internally. Confirm that the ReceiverChainflip constructor satisfies this approach.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
test/solidity/Facets/ChainflipFacet.t.sol (3)

34-86: Add error handling for config file operations.

The setup process could be more robust with proper error handling for file operations and JSON parsing.

Consider adding checks:

 string memory path = string.concat(
     vm.projectRoot(),
     "/config/chainflip.json"
 );
+require(vm.isFile(path), "Config file not found");
 string memory json = vm.readFile(path);
+require(bytes(json).length > 0, "Config file is empty");
 CHAINFLIP_VAULT = json.readAddress(".mainnet.chainflipVault");
+require(CHAINFLIP_VAULT != address(0), "Invalid vault address in config");

120-147: Add documentation for the override methods.

While the implementation is correct, adding documentation would improve maintainability.

Consider adding NatSpec documentation:

+/// @notice Initiates a bridge transaction using the ChainflipFacet
+/// @param isNative Boolean indicating if the transaction involves native tokens
+/// @dev This is an override of the TestBaseFacet method
 function initiateBridgeTxWithFacet(bool isNative) internal override {

149-217: Consider adding more edge cases to the bridging tests.

While the current tests cover the basic functionality, consider adding tests for:

  • Invalid destination token IDs
  • Malformed non-EVM addresses
  • Maximum and minimum amount boundaries
script/demoScripts/demoChainflip.ts (1)

86-91: Consider making ChainflipData values configurable.

The current implementation uses hardcoded values which could limit the script's flexibility:

  • dstToken is hardcoded to 3 (USDC)
  • nonEvmAddress is hardcoded to zero address
  • cfParameters is hardcoded to empty bytes

Consider making these values configurable through environment variables or command-line arguments for better reusability:

+const DST_TOKEN = process.env.DST_TOKEN || 3
+const NON_EVM_ADDRESS = process.env.NON_EVM_ADDRESS || '0x0000000000000000000000000000000000000000000000000000000000000000'
+const CF_PARAMETERS = process.env.CF_PARAMETERS || '0x'
 const chainflipData: ChainflipFacet.ChainflipDataStruct = {
-  dstToken: 3, // USDC
-  nonEvmAddress:
-    '0x0000000000000000000000000000000000000000000000000000000000000000',
-  cfParameters: '0x', // Empty parameters as per implementation
+  dstToken: DST_TOKEN,
+  nonEvmAddress: NON_EVM_ADDRESS,
+  cfParameters: CF_PARAMETERS,
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c8c2988 and d81478e.

📒 Files selected for processing (4)
  • deployments/_deployments_log_file.json (1 hunks)
  • script/demoScripts/demoChainflip.ts (1 hunks)
  • script/demoScripts/utils/demoScriptHelpers.ts (2 hunks)
  • test/solidity/Facets/ChainflipFacet.t.sol (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • deployments/_deployments_log_file.json
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: generate-tag
🔇 Additional comments (9)
test/solidity/Facets/ChainflipFacet.t.sol (3)

1-10: LGTM! Well-structured imports and declarations.

The file uses an appropriate Solidity version and imports all necessary dependencies.


11-22: LGTM! Well-designed test stub contract.

The TestChainflipFacet provides appropriate helper methods for testing while maintaining the core functionality of ChainflipFacet.


219-236: LGTM! Good negative test case.

The test properly verifies the contract's behavior with an empty non-EVM address.

script/demoScripts/demoChainflip.ts (4)

1-28: LGTM!

The imports and setup are well-organized with proper type safety using Narrow.


94-135: LGTM!

The swap implementation is well-structured with proper slippage handling and error checking.


137-146: LGTM!

The direct bridging implementation is clean and straightforward.


150-155: LGTM!

The error handling is appropriate with proper process exit codes.

script/demoScripts/utils/demoScriptHelpers.ts (2)

183-195: LGTM!

The refactored minAmountOut calculation is more readable and maintainable. The 1% slippage tolerance is a reasonable default.


312-312: Verify the increased slippage tolerance.

The slippage tolerance has been increased from 5% to 10%. While this provides more flexibility in volatile markets, it also increases the risk of unfavorable trades.

Please confirm if this increase is intentional and aligns with the project's risk tolerance.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
script/demoScripts/demoChainflip.ts (4)

28-34: Use constants for chain IDs and validate token addresses.

Consider these improvements:

  1. Define chain IDs as constants or enums for better maintainability
  2. Add validation for token addresses
+const MAINNET_CHAIN_ID = 1
+const ARBITRUM_CHAIN_ID = 42161

 async function main() {
   const withSwap = process.argv.includes('--with-swap')
   const srcTokenAddress = withSwap ? ADDRESS_USDT_ARB : ADDRESS_USDC_ARB
+  if (srcTokenAddress === undefined) {
+    throw new Error('Source token address is undefined')
+  }
   // === Set up environment ===
   const srcChain: SupportedChain = 'arbitrum'
-  const destinationChainId = 1 // Mainnet
+  const destinationChainId = MAINNET_CHAIN_ID

78-83: Improve ChainflipData configuration.

  1. Define constants for Chainflip token designators
  2. Document the purpose of cfParameters
  3. Use constants for zero address values
+// Chainflip token designators
+const CF_TOKEN_DESIGNATORS = {
+  USDC_ETH: 3,
+} as const

+// Constants
+const ZERO_BYTES32 = '0x' + '0'.repeat(64)

 const chainflipData: ChainflipFacet.ChainflipDataStruct = {
-  dstToken: 3, // Chainflip designator for USDC on ETH
+  dstToken: CF_TOKEN_DESIGNATORS.USDC_ETH,
   nonEvmAddress:
-    '0x0000000000000000000000000000000000000000000000000000000000000000',
+    ZERO_BYTES32,
+  // cfParameters is left empty as per Chainflip's implementation
+  // It may be used for future protocol upgrades
   cfParameters: '0x', // Empty parameters as per implementation
 }

85-137: Enhance error handling and transaction monitoring.

Consider these improvements:

  1. Add try-catch blocks for better error handling
  2. Enhance transaction status logging
  3. Extract swap data generation to a separate function
+async function generateSwapData(
+  amount: bigint,
+  lifiDiamondAddress: string
+): Promise<any> {
+  return getUniswapDataERC20toExactERC20(
+    ADDRESS_UNISWAP_ARB,
+    42161,
+    ADDRESS_USDT_ARB,
+    ADDRESS_USDC_ARB,
+    amount,
+    lifiDiamondAddress,
+    true
+  )
+}

 if (withSwap) {
+  try {
-    const swapData = await getUniswapDataERC20toExactERC20(
-      ADDRESS_UNISWAP_ARB,
-      42161,
-      ADDRESS_USDT_ARB,
-      ADDRESS_USDC_ARB,
-      amount,
-      lifiDiamondAddress,
-      true
-    )
+    const swapData = await generateSwapData(amount, lifiDiamondAddress)
     // ... rest of the code
+  } catch (error) {
+    console.error('Failed to generate swap data:', error)
+    throw error
+  }
 }

139-144: Improve error handling in the main execution.

Enhance error handling to provide more context and structured error information.

 main()
   .then(() => process.exit(0))
   .catch((error) => {
-    console.error(error)
+    console.error('Script execution failed:')
+    if (error instanceof Error) {
+      console.error('Error message:', error.message)
+      console.error('Stack trace:', error.stack)
+    } else {
+      console.error('Unknown error:', error)
+    }
     process.exit(1)
   })
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d81478e and 2b6cecb.

📒 Files selected for processing (3)
  • deployments/_deployments_log_file.json (1 hunks)
  • script/demoScripts/demoChainflip.ts (1 hunks)
  • script/demoScripts/utils/demoScriptHelpers.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • script/demoScripts/utils/demoScriptHelpers.ts
  • deployments/_deployments_log_file.json
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: protect_audit_labels
🔇 Additional comments (1)
script/demoScripts/demoChainflip.ts (1)

1-27: LGTM!

The imports and setup are well-organized with proper type safety using Narrow.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@ezynda3 ezynda3 removed the WIP Work in progress label Feb 13, 2025
@ezynda3 ezynda3 marked this pull request as ready for review February 13, 2025 08:57
@lifi-action-bot lifi-action-bot changed the title Implement ChainflipFacet Implement ChainflipFacet [ChainflipFacet v1.0.0,IChainflip v1.0.0,ReceiverChainflip v1.0.0] Feb 13, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2b6cecb and aef020a.

📒 Files selected for processing (1)
  • src/Interfaces/IChainflip.sol (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: Enforce Min Test Coverage
src/Interfaces/IChainflip.sol

[error] 12-12: Expected '(' but got identifier.


[warning] 12-12: --ir-minimum enables viaIR with minimum optimization, which can result in inaccurate source mappings.

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: run-unit-tests
🔇 Additional comments (1)
src/Interfaces/IChainflip.sol (1)

9-27: Well-structured interface design!

The interface is well-designed with:

  • Clear parameter naming
  • Appropriate use of the payable modifier for native token swaps
  • Consistent parameter ordering between methods
🧰 Tools
🪛 GitHub Actions: Enforce Min Test Coverage

[error] 12-12: Expected '(' but got identifier.


[warning] 12-12: --ir-minimum enables viaIR with minimum optimization, which can result in inaccurate source mappings.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/Periphery/ReceiverChainflip.sol (2)

28-29: Document the source of CHAINFLIP_NATIVE_ADDRESS.

Add a comment explaining why this specific address was chosen and its significance in the Chainflip protocol.

     /// @notice Chainflip's native token address representation
+    /// @dev This address is used by Chainflip protocol to represent native tokens
+    /// @dev Reference: <add_chainflip_documentation_link>
     address internal constant CHAINFLIP_NATIVE_ADDRESS =
         0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

107-165: Optimize token handling logic.

The function can be optimized by:

  1. Reducing redundant native token checks
  2. Consolidating the try-catch blocks
  3. Moving the approval reset inside the catch block
     function _swapAndCompleteBridgeTokens(
         bytes32 _transactionId,
         LibSwap.SwapData[] memory _swapData,
         address assetId,
         address payable receiver,
         uint256 amount
     ) private {
-        address actualAssetId = assetId == CHAINFLIP_NATIVE_ADDRESS
-            ? LibAsset.NATIVE_ASSETID
-            : assetId;
-        bool isNative = actualAssetId == LibAsset.NATIVE_ASSETID;
+        bool isNative = assetId == CHAINFLIP_NATIVE_ADDRESS;
+        address actualAssetId = isNative ? LibAsset.NATIVE_ASSETID : assetId;

-        if (!isNative) {
-            actualAssetId.safeApproveWithRetry(address(executor), amount);
-            try
-                executor.swapAndCompleteBridgeTokens(
-                    _transactionId,
-                    _swapData,
-                    actualAssetId,
-                    receiver
-                )
-            {
-                return;
-            } catch {
-                actualAssetId.safeTransfer(receiver, amount);
-                emit LiFiTransferRecovered(
-                    _transactionId,
-                    actualAssetId,
-                    receiver,
-                    amount,
-                    block.timestamp
-                );
-            }
-            actualAssetId.safeApprove(address(executor), 0);
-        } else {
-            try
-                executor.swapAndCompleteBridgeTokens{ value: amount }(
-                    _transactionId,
-                    _swapData,
-                    actualAssetId,
-                    receiver
-                )
-            {
-                return;
-            } catch {
-                receiver.safeTransferETH(amount);
-                emit LiFiTransferRecovered(
-                    _transactionId,
-                    actualAssetId,
-                    receiver,
-                    amount,
-                    block.timestamp
-                );
-            }
-        }
+        if (!isNative) {
+            actualAssetId.safeApproveWithRetry(address(executor), amount);
+        }
+        
+        try
+            executor.swapAndCompleteBridgeTokens{ value: isNative ? amount : 0 }(
+                _transactionId,
+                _swapData,
+                actualAssetId,
+                receiver
+            )
+        {
+            if (!isNative) {
+                actualAssetId.safeApprove(address(executor), 0);
+            }
+            return;
+        } catch {
+            if (isNative) {
+                receiver.safeTransferETH(amount);
+            } else {
+                actualAssetId.safeTransfer(receiver, amount);
+                actualAssetId.safeApprove(address(executor), 0);
+            }
+            emit LiFiTransferRecovered(
+                _transactionId,
+                actualAssetId,
+                receiver,
+                amount,
+                block.timestamp
+            );
+        }
     }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0778cc0 and 8e7722c.

📒 Files selected for processing (1)
  • src/Periphery/ReceiverChainflip.sol (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
src/Periphery/ReceiverChainflip.sol (2)
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Periphery/ReceiverChainflip.sol:49-71
Timestamp: 2025-02-13T08:56:27.487Z
Learning: The executor contract in ReceiverChainflip and other periphery contracts is a trusted component of the system, and therefore does not require additional reentrancy protection.
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Periphery/ReceiverChainflip.sol:162-162
Timestamp: 2025-02-24T06:51:03.551Z
Learning: In periphery contracts like ReceiverChainflip, the receive function can be left open without access control as it's part of the intended design.
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: enforce-min-test-coverage
🔇 Additional comments (3)
src/Periphery/ReceiverChainflip.sol (3)

35-40: LGTM!

The modifier is well-implemented with proper access control and error handling.


73-95: LGTM!

The function is well-documented, properly restricted with the onlyChainflipVault modifier, and correctly handles unused parameters.


170-170: LGTM!

The empty payable receive function is part of the intended design for periphery contracts.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/Periphery/ReceiverChainflip.sol (1)

106-164: Consider optimizing gas usage.

The function could be optimized by:

  1. Consolidating the native token checks into a single block
  2. Moving the approval reset outside the try-catch block
  3. Combining the duplicate event emission code

Here's a suggested optimization:

 function _swapAndCompleteBridgeTokens(
     bytes32 _transactionId,
     LibSwap.SwapData[] memory _swapData,
     address assetId,
     address payable receiver,
     uint256 amount
 ) private {
     address actualAssetId = assetId == CHAINFLIP_NATIVE_ADDRESS
         ? LibAsset.NATIVE_ASSETID
         : assetId;
     bool isNative = actualAssetId == LibAsset.NATIVE_ASSETID;
+    bool success;
 
     if (!isNative) {
-        // ERC20 token operations
         actualAssetId.safeApproveWithRetry(address(executor), amount);
-        try
-            executor.swapAndCompleteBridgeTokens(
-                _transactionId,
-                _swapData,
-                actualAssetId,
-                receiver
-            )
-        {
-            return;
-        } catch {
-            actualAssetId.safeTransfer(receiver, amount);
-            emit LiFiTransferRecovered(
-                _transactionId,
-                actualAssetId,
-                receiver,
-                amount,
-                block.timestamp
-            );
-        }
-        actualAssetId.safeApprove(address(executor), 0);
-    } else {
-        // Native token operations
-        try
-            executor.swapAndCompleteBridgeTokens{ value: amount }(
-                _transactionId,
-                _swapData,
-                actualAssetId,
-                receiver
-            )
-        {
-            return;
-        } catch {
-            receiver.safeTransferETH(amount);
-            emit LiFiTransferRecovered(
-                _transactionId,
-                actualAssetId,
-                receiver,
-                amount,
-                block.timestamp
-            );
-        }
     }
+
+    try
+        executor.swapAndCompleteBridgeTokens{ value: isNative ? amount : 0 }(
+            _transactionId,
+            _swapData,
+            actualAssetId,
+            receiver
+        )
+    {
+        success = true;
+    } catch {
+        if (isNative) {
+            receiver.safeTransferETH(amount);
+        } else {
+            actualAssetId.safeTransfer(receiver, amount);
+        }
+        emit LiFiTransferRecovered(
+            _transactionId,
+            actualAssetId,
+            receiver,
+            amount,
+            block.timestamp
+        );
+    }
+
+    if (!isNative && !success) {
+        actualAssetId.safeApprove(address(executor), 0);
+    }
 }
test/solidity/Periphery/ReceiverChainflip.t.sol (1)

106-246: Add more balance assertions.

Consider adding these balance checks to strengthen the tests:

  1. Verify executor balance before and after swaps
  2. Verify contract's token balance is 0 after failed swaps
  3. For native token tests, verify contract's ETH balance
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8e7722c and 31aefd8.

📒 Files selected for processing (2)
  • src/Periphery/ReceiverChainflip.sol (1 hunks)
  • test/solidity/Periphery/ReceiverChainflip.t.sol (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
test/solidity/Periphery/ReceiverChainflip.t.sol (1)
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Periphery/ReceiverChainflip.sol:48-62
Timestamp: 2025-02-24T09:35:34.908Z
Learning: Contract address validations for periphery contracts like ReceiverChainflip are handled in deployment scripts rather than in the constructor.
src/Periphery/ReceiverChainflip.sol (3)
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Periphery/ReceiverChainflip.sol:49-71
Timestamp: 2025-02-13T08:56:27.487Z
Learning: The executor contract in ReceiverChainflip and other periphery contracts is a trusted component of the system, and therefore does not require additional reentrancy protection.
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Periphery/ReceiverChainflip.sol:48-62
Timestamp: 2025-02-24T09:35:34.908Z
Learning: Contract address validations for periphery contracts like ReceiverChainflip are handled in deployment scripts rather than in the constructor.
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Periphery/ReceiverChainflip.sol:162-162
Timestamp: 2025-02-24T06:51:03.551Z
Learning: In periphery contracts like ReceiverChainflip, the receive function can be left open without access control as it's part of the intended design.
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: enforce-min-test-coverage
  • GitHub Check: run-unit-tests
  • GitHub Check: generate-tag
🔇 Additional comments (7)
src/Periphery/ReceiverChainflip.sol (3)

1-11: LGTM!

The contract structure and imports are well-organized. The use of SafeTransferLib for token transfers is a good security practice.

Also applies to: 16-19


20-61: LGTM!

The storage variables are correctly marked as immutable and the constructor includes appropriate zero address validations. As per the learnings, additional contract address validations are handled in deployment scripts.


72-94: LGTM!

The function is well-implemented with proper access control and message decoding. The execution flow is clear and follows the expected pattern.

test/solidity/Periphery/ReceiverChainflip.t.sol (4)

1-50: LGTM!

The test setup is comprehensive and well-organized, with proper initialization of all required contracts and clear labeling for debugging.


52-75: LGTM!

The constructor validation tests thoroughly check all zero address cases.


77-104: Add event parameter checks.

The test should verify event parameters using vm.expectEmit(true, true, true, true, address(receiver)) for consistency with other tests.


342-409: LGTM!

The helper functions are well-implemented and properly documented, making the tests more maintainable.

@mirooon mirooon marked this pull request as draft February 25, 2025 13:27
@mirooon mirooon marked this pull request as ready for review February 25, 2025 13:27
@lifi-action-bot
Copy link
Collaborator

lifi-action-bot commented Feb 25, 2025

🤖 GitHub Action: Security Alerts Review 🔍

🚨 Unresolved Security Alerts Found! 🚨
The following security alerts must be resolved before merging:

🔴 View Alert - File: src/Helpers/TransferrableOwnership.sol
🔹 Parameters passed to a constructor that are not validated for correct values may lead to contract creation in an undesired state. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/no-parameter-validation-in-constructor

🔴 View Alert - File: src/Helpers/WithdrawablePeriphery.sol
🔹 Parameters passed to a constructor that are not validated for correct values may lead to contract creation in an undesired state. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/no-parameter-validation-in-constructor

⚠️ Please resolve the above issues before merging.

🟢 Dismissed Security Alerts with Comments
The following alerts were dismissed with proper comments:

🟢 View Alert - File: src/Facets/ChainflipFacet.sol
🔹 Test functions fail to thoroughly test all aspects of contract constructors, potentially missing critical initialization issues. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/incomplete-constructor-tests
🔹 Dismiss Reason: Won't fix
🔹 Dismiss Comment: Fixed

🟢 View Alert - File: src/Facets/ChainflipFacet.sol
🔹 Test functions fail to assert the emission of expected events, potentially missing critical contract behaviors. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/missing-events-assertion
🔹 Dismiss Reason: False positive
🔹 Dismiss Comment: This is not a test so not sure what to assert

🟢 View Alert - File: src/Periphery/ReceiverChainflip.sol
🔹 The contract contains functions with inadequate validation of input parameters, potentially leading to unexpected behavior or vulnerabilities. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/insufficient-parameter-assertion
🔹 Dismiss Reason: False positive
🔹 Dismiss Comment: Validated through various modifiers

🟢 View Alert - File: src/Facets/ChainflipFacet.sol
🔹 The contract contains functions with inadequate validation of input parameters, potentially leading to unexpected behavior or vulnerabilities. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/insufficient-parameter-assertion
🔹 Dismiss Reason: False positive
🔹 Dismiss Comment: These are validated through various modifiers

🟢 View Alert - File: src/Facets/ChainflipFacet.sol
🔹 The contract contains functions with inadequate validation of input parameters, potentially leading to unexpected behavior or vulnerabilities. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/insufficient-parameter-assertion
🔹 Dismiss Reason: False positive
🔹 Dismiss Comment: These are validated through various modifiers

🟢 View Alert - File: src/Periphery/ReceiverChainflip.sol
🔹 Using a payable fallback (including receive) with no access control may lead to inadvertently locked funds. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/no-access-control-payable-fallback
🔹 Dismiss Reason: Won't fix
🔹 Dismiss Comment: Not gas efficient

🟢 View Alert - File: src/Periphery/ReceiverChainflip.sol
🔹 Labelling visibility explicitly can make it easier to address incorrect assumptions about variable and function access. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/default-visibility
🔹 Dismiss Reason: Won't fix
🔹 Dismiss Comment: Fixed

🟢 View Alert - File: src/Facets/ChainflipFacet.sol
🔹 Reentrant functions which emit events after making an external call may lead to out-of-order events. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/reentrancy-events
🔹 Dismiss Reason: False positive
🔹 Dismiss Comment: This is an internal function

🟢 View Alert - File: src/Periphery/ReceiverChainflip.sol
🔹 Using a payable fallback (including receive) with no explicit functionality may indicate incomplete contract logic. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/empty-payable-fallback
🔹 Dismiss Reason: Won't fix
🔹 Dismiss Comment: Not gas efficient

@lifi-action-bot lifi-action-bot marked this pull request as draft February 25, 2025 13:27
0xDEnYO
0xDEnYO previously approved these changes Feb 26, 2025
@ezynda3 ezynda3 marked this pull request as ready for review February 26, 2025 08:06
@lifi-action-bot lifi-action-bot marked this pull request as draft February 26, 2025 08:07
@ezynda3 ezynda3 marked this pull request as ready for review February 26, 2025 08:52
@lifi-action-bot lifi-action-bot marked this pull request as draft February 26, 2025 08:52
/// @custom:version 1.0.0
contract ChainflipFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {
/// Events ///
event BridgeToNonEVMChain(

Check warning

Code scanning / Olympix Integrated Security

Test functions fail to assert the emission of expected events, potentially missing critical contract behaviors. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/missing-events-assertion

Test functions fail to assert the emission of expected events, potentially missing critical contract behaviors. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/missing-events-assertion
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
script/demoScripts/demoChainflip.ts (1)

80-80: ⚠️ Potential issue

Fix scope error for lifiDiamondAddress.

The variable lifiDiamondAddress is declared within main() (line 139) and doesn’t exist in the scope of executeWithSourceSwap() at line 80. This will lead to a ReferenceError. Pass lifiDiamondAddress explicitly as a parameter or define it in a shared scope.

-  amount,
-  lifiDiamondAddress,
-  true
+  amount,
+  lifiDiamondAddressParam, // define or pass as argument
+  true
🧹 Nitpick comments (8)
docs/ChainflipFacet.md (1)

45-45: Use a hyphen for “swap-specific”.

According to the static analysis tool and standard writing conventions, “swap specific” should be spelled with a hyphen. This improves clarity and professionalism.

- Swapping is performed by a swap specific library ...
+ Swapping is performed by a swap-specific library ...
test/solidity/Facets/ChainflipFacet.t.sol (1)

467-486: Rename function to reflect actual behavior.

The test name testRevert_WhenNonEVMAddressWithEVMReceiver implies a revert, but the comment clearly states it should proceed normally for an EVM address, ignoring the nonEVMReceiver. Rename this function to accurately describe the scenario:

-function testRevert_WhenNonEVMAddressWithEVMReceiver() public {
+function test_SucceedsWithNonEVMReceiverAndEVMAddress() public {
src/Facets/ChainflipFacet.sol (6)

20-24: Add unit tests to cover the BridgeToNonEVMChain event emission.
While the event helps to identify non-EVM chain transfers, static analysis indicates that test functions may not assert its emission. Ensure your tests verify that the event is emitted with the correct parameters.

🧰 Tools
🪛 GitHub Check: Olympix Integrated Security

[warning] 20-20:
Test functions fail to assert the emission of expected events, potentially missing critical contract behaviors. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/missing-events-assertion


65-69: Validate that _chainflipVault is an actual deployed contract.
Even though you ensure _chainflipVault is non-zero, consider using a check (e.g., Address.isContract) to reduce the risk of deployment mistakes.


110-117: Consider requiring _bridgeData.minAmount to be above zero for bridging.
Although not strictly necessary, adding a require statement can help prevent pointless or accidental zero-amount bridges and enhance clarity for end users.


129-146: Refactor to eliminate redundant zero-address checks for EVM vs. non-EVM.
Since _bridgeData.receiver == LibAsset.NON_EVM_ADDRESS already funnels to a distinct code path, you might simplify the logic by merging repeated checks or using a small helper function to handle address encoding.


183-227: Consolidate xCall / xSwap logic to reduce duplication.
Both EVM and non-EVM bridging code paths share almost identical logic for native vs. token-based calls. Consider extracting these into a single internal function parameterized by a boolean for native, which can streamline maintainability.


241-250: Future-proof chain mapping to accommodate additional chains.
If more chains are integrated down the line, large if-else blocks may become cumbersome. Though mappings can’t be declared constant or immutable in Solidity, consider creating a separate registry contract with a reference to reduce potential code bloat.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 233571f and d623247.

📒 Files selected for processing (4)
  • docs/ChainflipFacet.md (1 hunks)
  • script/demoScripts/demoChainflip.ts (1 hunks)
  • src/Facets/ChainflipFacet.sol (1 hunks)
  • test/solidity/Facets/ChainflipFacet.t.sol (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
script/demoScripts/demoChainflip.ts (1)
Learnt from: ezynda3
PR: lifinance/contracts#984
File: script/demoScripts/demoChainflip.ts:89-97
Timestamp: 2025-02-17T07:35:27.790Z
Learning: Demo and test scripts can omit production safeguards like slippage protection to maintain simplicity and focus on demonstrating core functionality.
src/Facets/ChainflipFacet.sol (3)
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Facets/ChainflipFacet.sol:127-146
Timestamp: 2025-02-21T09:00:28.226Z
Learning: The `validateBridgeData` modifier in `Validatable.sol` already validates that the receiver address is not zero, making additional zero-address checks redundant in functions using this modifier.
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Facets/ChainflipFacet.sol:127-146
Timestamp: 2025-02-21T09:00:28.226Z
Learning: The `validateBridgeData` modifier in `Validatable.sol` validates that the receiver address is not zero using `LibUtil.isZeroAddress`, making additional zero-address checks redundant in functions using this modifier.
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Facets/ChainflipFacet.sol:157-179
Timestamp: 2025-02-17T07:34:42.595Z
Learning: In the Chainflip protocol, there is no way to verify or validate the gas budget for cross-chain calls at the smart contract level.
test/solidity/Facets/ChainflipFacet.t.sol (3)
Learnt from: ezynda3
PR: lifinance/contracts#984
File: test/solidity/Facets/ChainflipFacet.t.sol:81-87
Timestamp: 2025-02-21T09:09:15.973Z
Learning: The `cfParameters` field in ChainflipFacet's ChainflipData struct is not used in the current implementation and serves as a placeholder.
Learnt from: ezynda3
PR: lifinance/contracts#984
File: test/solidity/Facets/ChainflipFacet.t.sol:269-269
Timestamp: 2025-02-21T09:05:22.118Z
Learning: Fixed gas amounts in test files (e.g., ChainflipFacet.t.sol) don't require extensive documentation or configuration as they are only used for testing purposes.
Learnt from: ezynda3
PR: lifinance/contracts#984
File: test/solidity/Facets/ChainflipFacet.t.sol:154-156
Timestamp: 2025-02-21T11:39:07.847Z
Learning: Bitcoin address validation is not required in Chainflip test cases as the validation is handled elsewhere.
docs/ChainflipFacet.md (1)
Learnt from: ezynda3
PR: lifinance/contracts#984
File: docs/ChainflipFacet.md:0-0
Timestamp: 2025-02-13T08:57:00.095Z
Learning: The ChainflipData struct in ChainflipFacet has three fields:
1. uint32 dstToken - The destination token identifier in Chainflip
2. bytes32 nonEvmAddress - The non-EVM destination address
3. bytes cfParameters - Additional parameters for Chainflip protocol
🪛 GitHub Check: Olympix Integrated Security
src/Facets/ChainflipFacet.sol

[warning] 20-20:
Test functions fail to assert the emission of expected events, potentially missing critical contract behaviors. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/missing-events-assertion

🪛 LanguageTool
docs/ChainflipFacet.md

[uncategorized] ~47-~47: When ‘swap-specific’ is used as a modifier, it is usually spelled with a hyphen.
Context: ... parameter. Swapping is performed by a swap specific library that expects an array of callda...

(SPECIFIC_HYPHEN)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/Periphery/ReceiverChainflip.sol (1)

63-95: Consider emitting a success event in cfReceive.
Currently, there is only an event emitted when the swap fails (LiFiTransferRecovered). For greater traceability, consider emitting an event indicating successful bridging to help off-chain services or logs track normal process completion.

 function cfReceive(
     ...
 ) external payable onlyChainflipVault {
     ...
     _swapAndCompleteBridgeTokens(...);
+    emit LiFiTransferCompleted(transactionId, token, receiver, amount, block.timestamp);
 }
src/Facets/ChainflipFacet.sol (2)

45-50: Consider clarifying or removing the cfParameters field.
Since cfParameters is described as "Additional parameters for future features," it may be beneficial to add a short inline comment or docstring elaborating on planned usage, or remove this field if it’s not going to be used soon.


174-182: Consider reducing repeated ERC20 approvals.
Using LibAsset.maxApproveERC20 provides simplicity. However, for security and gas optimization, consider zeroing out allowances first or approving only the required amount. Proactively managing allowance can reduce risk if vault permissions ever become compromised.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d623247 and 9e1c645.

📒 Files selected for processing (2)
  • src/Facets/ChainflipFacet.sol (1 hunks)
  • src/Periphery/ReceiverChainflip.sol (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
src/Periphery/ReceiverChainflip.sol (3)
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Periphery/ReceiverChainflip.sol:49-71
Timestamp: 2025-02-13T08:56:27.487Z
Learning: The executor contract in ReceiverChainflip and other periphery contracts is a trusted component of the system, and therefore does not require additional reentrancy protection.
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Periphery/ReceiverChainflip.sol:48-62
Timestamp: 2025-02-24T09:35:34.908Z
Learning: Contract address validations for periphery contracts like ReceiverChainflip are handled in deployment scripts rather than in the constructor.
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Periphery/ReceiverChainflip.sol:162-162
Timestamp: 2025-02-24T06:51:03.551Z
Learning: In periphery contracts like ReceiverChainflip, the receive function can be left open without access control as it's part of the intended design.
src/Facets/ChainflipFacet.sol (3)
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Facets/ChainflipFacet.sol:127-146
Timestamp: 2025-02-21T09:00:28.226Z
Learning: The `validateBridgeData` modifier in `Validatable.sol` already validates that the receiver address is not zero, making additional zero-address checks redundant in functions using this modifier.
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Facets/ChainflipFacet.sol:127-146
Timestamp: 2025-02-21T09:00:28.226Z
Learning: The `validateBridgeData` modifier in `Validatable.sol` validates that the receiver address is not zero using `LibUtil.isZeroAddress`, making additional zero-address checks redundant in functions using this modifier.
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Facets/ChainflipFacet.sol:157-179
Timestamp: 2025-02-17T07:34:42.595Z
Learning: In the Chainflip protocol, there is no way to verify or validate the gas budget for cross-chain calls at the smart contract level.
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: generate-tag
🔇 Additional comments (7)
src/Periphery/ReceiverChainflip.sol (3)

1-61: Solid constructor and storage design.
The constructor correctly validates non-zero addresses, and the storage fields are well-structured with clear naming. Overall, these lines accurately implement initialization logic and immutability where needed.


98-164: Robust swap execution flow.
Using try-catch to fall back on sending tokens directly to the receiver is a practical recovery solution that minimizes user funds lock-up. Moreover, resetting approvals to zero helps prevent unintended spending on external contracts. This pattern aligns well with recognized safety best practices.


166-169: Receive function intentionally left open.
Per your retrieved learnings, this fallback pattern is purposeful and does not require additional access control. The approach is consistent with your design logic.

src/Facets/ChainflipFacet.sol (4)

60-69: Good job validating the _chainflipVault parameter.
Reverting on a zero address prevents accidental misconfiguration and aligns with best practices for secure contract setup.


134-146: Robust mismatch checks for destination calls.
The logic properly enforces consistency between _bridgeData.hasDestinationCall and _chainflipData.dstCallSwapData.length, preventing accidental or malicious misuse.


148-172: Well-structured EVM vs. non-EVM address handling.
Applying different logic for _chainflipData.nonEVMReceiver vs. EVM-based addresses is clean and straightforward. The validation for zero addresses is already enforced by validateBridgeData (and an explicit revert for _chainflipData.dstCallReceiver) ensuring safe usage.


240-251: Approach for mapping chain IDs is appropriate.
Using an if-else chain for compile-time constants is a known pattern in Solidity, since mappings cannot be declared as constant or immutable. The implementation is clear and avoids maintaining separate storage.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/Facets/ChainflipFacet.sol (2)

45-58: Clarify the use of cfParameters in the NatSpec.

Although flagged as "Additional parameters for future features," consider providing an example or more explicit guidance in the NatSpec comments on when or how this field might be used. This helps other developers and auditors better understand its purpose and potential expansion.


183-224: Consider reducing code duplication for bridging calls.

Both the "destination call" block (lines 183–206) and the "no destination call" block (lines 207–224) branch into native vs. token-based calls. Extracting these repeated patterns into a helper function could reduce boilerplate and improve maintainability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9e1c645 and c3473cb.

📒 Files selected for processing (1)
  • src/Facets/ChainflipFacet.sol (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
src/Facets/ChainflipFacet.sol (3)
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Facets/ChainflipFacet.sol:127-146
Timestamp: 2025-02-21T09:00:28.226Z
Learning: The `validateBridgeData` modifier in `Validatable.sol` already validates that the receiver address is not zero, making additional zero-address checks redundant in functions using this modifier.
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Facets/ChainflipFacet.sol:127-146
Timestamp: 2025-02-21T09:00:28.226Z
Learning: The `validateBridgeData` modifier in `Validatable.sol` validates that the receiver address is not zero using `LibUtil.isZeroAddress`, making additional zero-address checks redundant in functions using this modifier.
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Facets/ChainflipFacet.sol:157-179
Timestamp: 2025-02-17T07:34:42.595Z
Learning: In the Chainflip protocol, there is no way to verify or validate the gas budget for cross-chain calls at the smart contract level.
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: generate-tag
🔇 Additional comments (3)
src/Facets/ChainflipFacet.sol (3)

77-92: Looks good and straightforward.

The function’s flow—depositing assets before calling _startBridge—is clear and respects security best practices by validating the bridge data first.


94-117: Clean swap-then-bridge flow.

The logic here neatly updates _bridgeData.minAmount after the source swaps, ensuring an accurate bridged asset amount. No issues found with ordering or security checks.


229-247:

✅ Verification successful

Confirm test coverage for unsupported chains.

The _getChainflipChainId function reverts if destinationChainId does not match any known chain. Verify that there's at least one test case covering this revert scenario to ensure consistent behavior and maintain coverage.

You can confirm coverage by searching for “UnsupportedChainflipChainId” in the tests:


🏁 Script executed:

#!/bin/bash
rg -A 5 "UnsupportedChainflipChainId"

Length of output: 1390


Test Coverage for Unsupported Chains Confirmed!

The tests in test/solidity/Facets/ChainflipFacet.t.sol already cover the revert scenario using vm.expectRevert(ChainflipFacet.UnsupportedChainflipChainId.selector). This confirms that passing an unsupported destinationChainId correctly triggers the revert in _getChainflipChainId. No further changes are needed.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
test/solidity/Facets/ChainflipFacet.t.sol (3)

37-49: Use a helper method to fetch multiple config values.
The approach of individually retrieving the vault address from "chainflip.json" works well for a single value. However, if more configuration values are needed in the future, consider creating a reusable helper method to fetch all relevant addresses or parameters from the JSON file in one go, helping reduce potential code duplication.


81-83: Optional validation of dstToken.
Currently, validChainflipData.dstToken = 7 is set without validating if token ID 7 is a recognized Chainflip token. Although this may be intentional for flexibility, adding a quick check or a comment explaining that arbitrary token IDs are acceptable might prevent confusion for other contributors.


223-262: Consolidate duplicate assertion logic.
Multiple tests follow a similar pattern (e.g., setting up the environment, approving tokens, expecting events, etc.). Consider extracting this preparation into a shared helper method to minimize repetition and enhance readability.

src/Facets/ChainflipFacet.sol (1)

160-167: Consider resetting allowances post-bridge.
LibAsset.maxApproveERC20(...) grants the vault a large allowance to pull tokens. To minimize the attack surface after bridging completes, consider resetting the allowance to zero or using a minimal allowance pattern, if this aligns with the broader architecture.

- LibAsset.maxApproveERC20(
-     IERC20(_bridgeData.sendingAssetId),
-     address(chainflipVault),
-     _bridgeData.minAmount
- );
+ // Approve just for bridging and reset allowance
+ uint256 amount = _bridgeData.minAmount;
+ IERC20 token = IERC20(_bridgeData.sendingAssetId);
+ LibAsset.maxApproveERC20(token, address(chainflipVault), amount);
+ // ...
+ // After bridging, reset:
+ LibAsset.approveERC20(token, address(chainflipVault), 0);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c3473cb and fe2691c.

📒 Files selected for processing (2)
  • src/Facets/ChainflipFacet.sol (1 hunks)
  • test/solidity/Facets/ChainflipFacet.t.sol (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
test/solidity/Facets/ChainflipFacet.t.sol (3)
Learnt from: ezynda3
PR: lifinance/contracts#984
File: test/solidity/Facets/ChainflipFacet.t.sol:81-87
Timestamp: 2025-02-21T09:09:15.973Z
Learning: The `cfParameters` field in ChainflipFacet's ChainflipData struct is not used in the current implementation and serves as a placeholder.
Learnt from: ezynda3
PR: lifinance/contracts#984
File: test/solidity/Facets/ChainflipFacet.t.sol:269-269
Timestamp: 2025-02-21T09:05:22.118Z
Learning: Fixed gas amounts in test files (e.g., ChainflipFacet.t.sol) don't require extensive documentation or configuration as they are only used for testing purposes.
Learnt from: ezynda3
PR: lifinance/contracts#984
File: test/solidity/Facets/ChainflipFacet.t.sol:154-156
Timestamp: 2025-02-21T11:39:07.847Z
Learning: Bitcoin address validation is not required in Chainflip test cases as the validation is handled elsewhere.
src/Facets/ChainflipFacet.sol (3)
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Facets/ChainflipFacet.sol:127-146
Timestamp: 2025-02-21T09:00:28.226Z
Learning: The `validateBridgeData` modifier in `Validatable.sol` already validates that the receiver address is not zero, making additional zero-address checks redundant in functions using this modifier.
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Facets/ChainflipFacet.sol:127-146
Timestamp: 2025-02-21T09:00:28.226Z
Learning: The `validateBridgeData` modifier in `Validatable.sol` validates that the receiver address is not zero using `LibUtil.isZeroAddress`, making additional zero-address checks redundant in functions using this modifier.
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Facets/ChainflipFacet.sol:157-179
Timestamp: 2025-02-17T07:34:42.595Z
Learning: In the Chainflip protocol, there is no way to verify or validate the gas budget for cross-chain calls at the smart contract level.
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: generate-tag
🔇 Additional comments (5)
test/solidity/Facets/ChainflipFacet.t.sol (2)

85-88: Good coverage of constructor revert condition.
This test ensures the contract reverts when _chainflipVault is a zero address, satisfying security checks for constructor parameters.


316-348: Comprehensive mismatch coverage.
These tests thoroughly verify the mismatch between _bridgeData.hasDestinationCall and _chainflipData.dstCallSwapData, ensuring robust input validation. No issues found here.

src/Facets/ChainflipFacet.sol (3)

32-40: Consistent chain ID definitions.
Defining both EVM and non-EVM chain IDs as constants avoids magic numbers in the code. Ensure all referencing tests or external scripts are updated accordingly if these constants ever change.


64-69: Validating zero-address vault.
Reverting on a zero vault address in the constructor prevents accidental misconfiguration. This matches best practices for constructor parameter validation.


229-247: Readable chain ID mapping.
This straightforward if-else approach is preferable in Solidity when mapping to compile-time constants, ensuring clarity about supported networks. No further suggestion here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants