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

Open
wants to merge 25 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

This pull request introduces support for the Chainflip protocol by adding a configuration file, new documentation, demo scripts, deployment and update scripts, a smart contract implementation for the Chainflip facet, a related interface, and comprehensive tests. The changes define vault addresses per network, document public methods and data structures, and provide scripts to deploy and update the facet. Additionally, the implementation of the ChainflipFacet contract enables bridging and swapping tokens according to the Chainflip protocol requirements.

Changes

File(s) Change Summary
config/chainflip.json Added a JSON configuration file defining the chainflipVault addresses for mainnet and arbitrum.
docs/ChainflipFacet.md Introduced documentation for the Chainflip Facet detailing its functionality, public methods, data structures, and API examples.
script/demoScripts/demoChainflip.ts Added a demo script that sets up the environment and executes token bridging using the Chainflip protocol via the startBridgeTokensViaChainflip method.
script/deploy/facets/DeployChainflipFacet.s.sol
script/deploy/facets/UpdateChainflipFacet.s.sol
Added Solidity deployment and update scripts for the ChainflipFacet contract, including configuration reading and setup of constructor parameters or update call data.
src/Facets/ChainflipFacet.sol Introduced the ChainflipFacet contract implementing bridging operations with methods for direct bridging and swap followed by bridging, including necessary validations, asset handling, and event emission.
src/Interfaces/IChainflip.sol Added the IChainflipVault interface defining functions for native and ERC20 token cross-chain swaps.
test/solidity/Facets/ChainflipFacet.t.sol Added new Solidity test contracts for the ChainflipFacet, including a stub (TestChainflipFacet) and tests (ChainflipFacetTest) to validate bridging and swap functionalities.
src/Periphery/ReceiverChainflip.sol Implemented the ReceiverChainflip contract for handling cross-chain swaps and message passing, including functions for receiving messages and executing swaps.
test/solidity/Periphery/ReceiverChainflip.t.sol Introduced tests for the ReceiverChainflip contract to validate setup, withdrawal operations, error handling, and payload processing.
script/deploy/facets/DeployReceiverChainflip.s.sol Added a deployment script for the ReceiverChainflip contract, including configuration reading for constructor arguments.
script/deploy/resources/deployRequirements.json Updated the deployment requirements JSON to include ChainflipFacet and ReceiverChainflip entities with their respective configuration data.
deployments/_deployments_log_file.json Added a new section for the "ChainflipFacet" in the deployments log file, detailing its deployment information for the "arbitrum" network.
deployments/arbitrum.diamond.staging.json Updated the facets and their versions in the diamond deployment configuration, adding ChainflipFacet and replacing an empty entry with DeBridgeDlnFacet.
deployments/arbitrum.staging.json Removed the "MayanFacet" entry and added a new entry for "ChainflipFacet" in the staging deployment configuration.

Suggested reviewers

  • 0xDEnYO

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.
✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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. (Beta)
  • @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.

src/Interfaces/IChainflip.sol Show resolved Hide resolved
script/demoScripts/demoChainflip.ts Outdated Show resolved Hide resolved
script/demoScripts/demoChainflip.ts Outdated Show resolved Hide resolved
docs/ChainflipFacet.md Outdated Show resolved Hide resolved
docs/ChainflipFacet.md Outdated Show resolved Hide resolved
@lifi-action-bot
Copy link
Collaborator

Test Coverage Report

Line Coverage: 78.64% (2257 / 2870 lines)
Function Coverage: 84.84% ( 392 / 462 functions)
Branch Coverage: 39.26% ( 223 / 568 branches)
Test coverage (78.64%) is above min threshold (78%). 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.

src/Facets/ChainflipFacet.sol Outdated Show resolved Hide resolved
src/Facets/ChainflipFacet.sol Outdated Show resolved Hide resolved
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.

src/Periphery/ReceiverChainflip.sol Show resolved Hide resolved
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.

src/Interfaces/IChainflip.sol Outdated Show resolved Hide resolved
src/Interfaces/IChainflip.sol Outdated Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick / optional:

If there is only one value I would suggest to simplify/revert the structure, e.g.

{
"chainflipVault": {
"mainnet": "...",
"arbitrum": "...",
"optimism": "..."
}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated


/// @custom:version 1.0.0
interface IChainflipVault {
function xSwapNative(
Copy link
Contributor

Choose a reason for hiding this comment

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

this line is erroneous

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

Copy link
Contributor

Choose a reason for hiding this comment

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

how did you test the custom receiver without a deployment?

```solidity
struct ChainflipData {
uint32 dstToken; // Token identifier on the destination chain
bytes32 nonEvmAddress; // Destination address for non-EVM chains (Solana, Bitcoin)
Copy link
Contributor

Choose a reason for hiding this comment

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

would suggest to rename this to nonEVMReceiver (like in MayanFacet) and move it to first position (as described in the new facet checklist)


The facet supports the following chains with their respective IDs:

- Ethereum (1)
Copy link
Contributor

Choose a reason for hiding this comment

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

Could this change in the future? If yes, could we link to some resource instead that shows which networks are supported so our docs do not get outdated easily?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

});
}

// All facet test files inherit from `utils/TestBaseFacet.sol` and require the following method overrides:
Copy link
Contributor

Choose a reason for hiding this comment

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

this should be removed

Copy link
Contributor

Choose a reason for hiding this comment

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

please add test cases for destination calls, too

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

assertEq(receiver.chainflipVault() == chainflipVault, true);
}

function test_OwnerCanPullERC20Token() public {
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm...not sure if we need to test this in every contract that inherits from WithdrawablePeriphery as this is already tested there....maybe only if some functions are overwritten or what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes sense. Will remove.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

payload,
ADDRESS_USDC,
defaultUSDCAmount
);
Copy link
Contributor

Choose a reason for hiding this comment

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

please also check here if funds were transferred / balances changed as expected
same below

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

Copy link
Contributor

Choose a reason for hiding this comment

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

could you please add a demo for a destination call in there, too?

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 (1)

159-181: Consider specifying a gas budget or clarifying zero value usage.

In both the native-token (lines 161-172) and ERC20 (lines 193-203 or 204-212) flows, you're passing 0 as the gas budget parameter. If different budgets will eventually be required, consider exposing a parameter or providing a comment to explain that zero is intentional.

Also applies to: 193-213

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

1-301: Optional additional test scenarios.

You may want to add coverage for:

  • Bridging with an extremely large dstToken, testing boundary conditions.
  • Bridging with no _bridgeData.minAmount (zero) to confirm expected behavior.
  • Attempting a native token transfer while passing a non-zero allowance for an ERC20.
📜 Review details

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

📥 Commits

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

📒 Files selected for processing (3)
  • src/Facets/ChainflipFacet.sol (1 hunks)
  • src/Interfaces/IChainflip.sol (1 hunks)
  • test/solidity/Facets/ChainflipFacet.t.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.

🪛 GitHub Actions: Types Bindings
src/Interfaces/IChainflip.sol

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

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

6-8: Remove duplicate SPDX license identifier and pragma statements.

These lines replicate the license and pragma already declared at lines 1-3, causing unnecessary duplication. Removing them will keep the header clean and help avoid pipeline warnings or failures.

Apply this diff to remove the duplicates:

-// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.17;

11-12: Fix duplicate function declaration for xSwapNative.

Line 11 and line 12 define the same function xSwapNative, resulting in a syntax error (the pipeline logs show “Expected '(' but got identifier” at line 12). Removing the second declaration resolves the error.

Apply this diff to remove the unintentional duplication:

 function xSwapNative(
-function xSwapNative(
     uint32 dstChain,
🧰 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.

🪛 GitHub Actions: Types Bindings

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


9-9: License and version tag.

The custom version tag on line 9 is helpful for tracking contract versions and meets compliance with your pipeline checks. No issues here.

src/Facets/ChainflipFacet.sol (2)

119-129: Acknowledge if-else logic for chain ID mapping.

Your if-else approach for mapping _bridgeData.destinationChainId to dstChain is valid, given Solidity’s current limitations on constant or immutable mappings. This pattern ensures clarity on which chains are supported.


153-157: Validation of destination call vs. Chainflip parameters is good.

The check _bridgeData.hasDestinationCall != (_chainflipData.cfParameters.length > 0) helps prevent mismatches between user intent and actual bridging data. Nice to see thorough validation here.

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

35-48: Config-based vault address lookup is well-structured.

Reading the chainflipVault from config/chainflip.json is clean and flexible. Ensure the config file is consistently maintained in different environments (test, staging, production) or handle missing/invalid file reads gracefully.

Would you like me to generate a script to confirm the file’s presence in all relevant deployment contexts?


257-299: Test coverage for destination calls is thorough.

Your test_CanBridgeTokensWithDestinationCall() covers bridging tokens with a message (cfParameters) for the Chainflip bridging logic. This is excellent for end-to-end coverage of cross-chain messaging.


224-236: Good coverage for unsupported destination chain.

The test verifies the revert condition for polygon chain ID (137), ensuring your ChainflipFacet properly rejects unsupported destinations.

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)
docs/ChainflipFacet.md (4)

24-30: Consider renaming nonEvmAddress to nonEVMReceiver.

For consistency with other facets (like MayanFacet), consider renaming the parameter and moving it to the first position in the struct.

 struct ChainflipData {
+  bytes32 nonEVMReceiver; // Destination address for non-EVM chains (Solana, Bitcoin)
   uint32 dstToken; // Token identifier on the destination chain
-  bytes32 nonEvmAddress; // Destination address for non-EVM chains (Solana, Bitcoin)
   bytes cfParameters; // Additional parameters for future features
 }

36-43: Consider relying on external documentation for supported chains.

To prevent the documentation from becoming outdated, consider removing the explicit chain list and relying solely on the external reference link, which is already provided.

-The facet supports the following chains with their respective IDs:
-
-- Ethereum (1)
-- Arbitrum (42161)
-- Solana (1151111081099710)
-- Bitcoin (20000000000001)
-
-[Reference](https://docs.chainflip.io/swapping/integrations/advanced/vault-swaps#supported-chains)
+For the latest list of supported chains and their respective IDs, please refer to the [Chainflip documentation](https://docs.chainflip.io/swapping/integrations/advanced/vault-swaps#supported-chains).

61-61: Fix grammatical issues in the text.

Add missing commas for better readability:

-In the following some sample calls are shown that allow you to retrieve
+In the following, some sample calls are shown that allow you to retrieve
-To get a transaction for a transfer from USDT on Ethereum to USDC on Arbitrum you can execute
+To get a transaction for a transfer from USDT on Ethereum to USDC on Arbitrum, you can execute

Also applies to: 102-102

🧰 Tools
🪛 LanguageTool

[uncategorized] ~61-~61: 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)


90-90: Add a security note about wallet addresses.

Consider adding a security reminder about not sharing private keys or using test wallets for examples.

-**Hint**: Don't forget to replace `{YOUR_WALLET_ADDRESS}` with your real wallet address in the examples.
+**Hint**: Don't forget to replace `{YOUR_WALLET_ADDRESS}` with your real wallet address in the examples. For testing purposes, always use a test wallet and never share your private keys.
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between aa8b393 and c353f90.

📒 Files selected for processing (2)
  • docs/ChainflipFacet.md (1 hunks)
  • src/Interfaces/IChainflip.sol (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Interfaces/IChainflip.sol
🧰 Additional context used
🧠 Learnings (1)
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
🪛 LanguageTool
docs/ChainflipFacet.md

[uncategorized] ~49-~49: 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] ~61-~61: 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] ~102-~102: 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: run-unit-tests
  • GitHub Check: generate-tag
🔇 Additional comments (1)
docs/ChainflipFacet.md (1)

1-12: LGTM! Clear introduction with helpful visualization.

The introduction effectively explains the facet's purpose and includes a clear mermaid diagram showing the interaction flow.

const amount = parseUnits('10', Number(srcTokenDecimals))

console.info(
`\nBridge ${amount} ${srcTokenName} (${srcTokenSymbol}) from ${srcChain} --> Arbitrum`
Copy link
Contributor

Choose a reason for hiding this comment

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

-> Mainnet ?

Comment on lines 28 to 29
error EmptyNonEvmAddress();
address public immutable chainflipVault;
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick:blank line between these two lines

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated


/// @dev Parameters specific to Chainflip bridge
/// @param dstToken Token to be received on the destination chain (uint32)
/// @param cfParameters Additional metadata for future features (currently unused)
Copy link
Contributor

Choose a reason for hiding this comment

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

missing description for nonEvmAddress param

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated


/// @dev Parameters specific to Chainflip bridge
/// @param dstToken Token to be received on the destination chain (uint32)
/// @param cfParameters Additional metadata for future features (currently unused)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think that part for future features (currently unused) could be removed and added to Third party integration notion page with explanation that this param is unused and can be used in the future. Wdyt?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

/// @notice Constructor for the contract.
/// @param _chainflipVault Address of the Chainflip vault contract
constructor(address _chainflipVault) {
chainflipVault = _chainflipVault;
Copy link
Contributor

Choose a reason for hiding this comment

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

In my opinion would be better to replace this line:
address public immutable chainflipVault;
to this
IChainflipVault public immutable chainflipVault;

where constructor would also accept IChainflipVault _chainflipVault param and adjust the rest of the code accordingly

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

Comment on lines 228 to 229
vm.expectRevert("ChainflipFacet: Unsupported destination chain");
initiateBridgeTxWithFacet(false);
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: blank lines between these two lines

vm.label(address(erc20Proxy), "ERC20Proxy");
}

function test_contractIsSetUpCorrectly() public {
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: to keep test naming consistent start with capital character test_ContractIsSetUpCorrectly. similar cases below

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

);
}

function test_revert_WithdrawTokenNonOwner() public {
Copy link
Contributor

Choose a reason for hiding this comment

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

start with: testRevert_

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated

@@ -530,5 +533,18 @@ abstract contract TestBase is Test, DiamondTest, ILiFi {
uint256 targetBlock = block.number + numBlocks;
vm.roll(targetBlock);
}

function getConfigAddressFromPath(
Copy link
Contributor

Choose a reason for hiding this comment

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

that's what we needed! 🚀

Comment on lines +1 to +6
{
"chainflipVault": {
"mainnet": "0xF5e10380213880111522dd0efD3dbb45b9f62Bcc",
"arbitrum": "0x79001a5e762f3bEFC8e5871b42F6734e00498920"
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

instead of using the following json structure. I propose organizing our config files using a structure that maps networks to their elements like:

{
  "mainnet": {
    "chainflipVault": "0xF5e10380213880111522dd0efD3dbb45b9f62Bcc"
  },
  "arbitrum": {
    "chainflipVault": "0x79001a5e762f3bEFC8e5871b42F6734e00498920"
  }
}

This approach will align with our template demo script which has the following code:

// If you need to retrieve a specific address from your config file 
// based on the chain and element name, use this helper function.
//
// First, ensure you import the relevant config file:
// import config from '../../config/{{camelCase name}}.json'
//
// Then, retrieve the address:
// const EXAMPLE_ADDRESS = getConfigElement(config, srcChain, 'example');

https://github.com/lifinance/contracts/blob/main/templates/facetDemoScript.template.hbs#L37-L45

getConfigElement function first checks for the specified network and element after the network.
https://github.com/lifinance/contracts/blob/main/script/demoScripts/utils/demoScriptHelpers.ts#L606-L618

I understand that more complex structures exist in our repository but in most cases the format described above will be sufficient. It’s better to keep it clear from the beginning.

always open for discussion

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@0xDEnYO I reverted it as you suggested but this approach makes sense in that it keeps everything in a format that our helpers expect even if it requires a bit more repetition.

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 (2)
test/solidity/utils/TestBase.sol (1)

537-548: LGTM! Well-structured configuration reader.

The getConfigAddressFromPath function provides a clean way to read network-specific addresses from JSON configuration files. The implementation:

  • Safely constructs the file path using string.concat
  • Uses foundry's vm.projectRoot() for reliable path resolution
  • Leverages vm.readFile for file I/O during tests
  • Returns parsed address using the JSON path

Consider adding error handling for:

  • Non-existent configuration files
  • Invalid JSON paths
  • Invalid address formats
test/solidity/Facets/ChainflipFacet.t.sol (1)

35-85: Remove console log before merging.

The setup function is well-structured, but the console log should be removed.

Apply this diff:

-        console.log("Chainflip Vault Address:", CHAINFLIP_VAULT);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c353f90 and 8a152f4.

📒 Files selected for processing (10)
  • config/chainflip.json (1 hunks)
  • script/demoScripts/demoChainflip.ts (1 hunks)
  • script/deploy/facets/DeployChainflipFacet.s.sol (1 hunks)
  • script/deploy/facets/DeployReceiverChainflip.s.sol (1 hunks)
  • script/deploy/resources/deployRequirements.json (1 hunks)
  • src/Facets/ChainflipFacet.sol (1 hunks)
  • src/Periphery/ReceiverChainflip.sol (1 hunks)
  • test/solidity/Facets/ChainflipFacet.t.sol (1 hunks)
  • test/solidity/Periphery/ReceiverChainflip.t.sol (1 hunks)
  • test/solidity/utils/TestBase.sol (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • script/deploy/facets/DeployChainflipFacet.s.sol
  • script/deploy/facets/DeployReceiverChainflip.s.sol
  • config/chainflip.json
🧰 Additional context used
🧠 Learnings (1)
src/Periphery/ReceiverChainflip.sol (1)
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.
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: run-unit-tests
  • GitHub Check: enforce-min-test-coverage
  • GitHub Check: generate-tag
🔇 Additional comments (24)
test/solidity/utils/TestBase.sol (1)

20-22: LGTM! Adding JSON parsing capabilities.

The addition of stdJson from forge-std enables reading and parsing JSON configuration files during testing, which is a good practice for managing network-specific addresses and other configuration data.

script/demoScripts/demoChainflip.ts (3)

1-27: LGTM!

The imports and configuration setup are well-organized and properly typed.


28-61: LGTM!

The main function setup is comprehensive, with proper handling of command-line arguments and environment initialization.


85-136: Add destination call example.

The script demonstrates basic bridging and swap+bridge scenarios but lacks an example of destination calls. Consider adding a demo for destination calls to showcase this feature.

src/Periphery/ReceiverChainflip.sol (4)

1-18: LGTM!

The imports and contract declaration are well-organized with appropriate inheritance.


19-35: LGTM!

The storage variables and access control modifier are properly implemented.


61-83: LGTM!

The cfReceive function is well-implemented with proper access control and message handling.


101-140: LGTM!

The _swapAndCompleteBridgeTokens function handles both token types correctly with proper error handling and approval management.

src/Facets/ChainflipFacet.sol (3)

47-51: Add validation for ChainflipData struct.

Consider adding validation for the ChainflipData struct fields to prevent potential issues:

  • dstToken: Validate supported token IDs
  • nonEvmAddress: Validate non-zero value for non-EVM chains
  • cfParameters: Validate length constraints

66-107: LGTM!

The bridging functions are well-implemented with proper access control and validation.


115-227: LGTM!

The internal methods are well-implemented with proper error handling and chain ID mapping.

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

1-86: LGTM!

The setup and basic tests are comprehensive, properly verifying contract initialization and access control.


88-132: LGTM!

The ERC20 swap tests are thorough, verifying both successful execution and balance changes.


134-224: LGTM!

The failure handling and native token tests provide good coverage of edge cases and native token functionality.


227-296: LGTM!

The helper functions are well-implemented, providing comprehensive test data generation for both token types.

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

11-23: LGTM!

The stub contract is well-structured with appropriate helper functions for testing.


116-148: LGTM!

The test case thoroughly validates the bridging functionality to Solana with appropriate balance assertions.


150-180: LGTM!

The test case thoroughly validates the bridging functionality to Bitcoin with appropriate balance assertions.


182-216: LGTM!

The test case thoroughly validates the bridging functionality to Ethereum with appropriate balance assertions and chain-specific setup.


218-231: LGTM!

The test case correctly validates the error handling for unsupported chains.


233-251: LGTM!

The test case correctly validates the error handling for empty non-EVM addresses.


253-295: LGTM!

The test case thoroughly validates the bridging functionality with destination call and appropriate balance assertions.

script/deploy/resources/deployRequirements.json (2)

573-581: LGTM!

The ChainflipFacet configuration follows the established pattern and correctly references the chainflip.json file.


582-599: LGTM!

The ReceiverChainflip configuration follows the established pattern and correctly references the required configuration files.

script/demoScripts/demoChainflip.ts Outdated Show resolved Hide resolved
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 (11)
src/Interfaces/IChainflip.sol (2)

6-8: Move @custom:version tag above pragma statement.

Based on the project's standard practice mentioned in past review comments, the version tag should be placed above the pragma statement.

Apply this diff to align with the project's conventions:

 // SPDX-License-Identifier: MIT
+/// @custom:version 1.0.0
 pragma solidity ^0.8.17;
 
 import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
 
 /// @title Interface for Chainflip Vault contract
-/// @custom:version 1.0.0
 interface IChainflipVault {
🧰 Tools
🪛 GitHub Actions: SC Core Dev Approval Check

[warning] 6-8: Remove duplicate SPDX license identifier and pragma statements.


9-71:

❓ Verification inconclusive

Enhance NatSpec documentation for better clarity.

The NatSpec comments could be improved by:

  1. Adding descriptions for nonEvmAddress parameter in xSwapNative and xSwapToken functions.
  2. Clarifying the format and constraints for cfParameters.

🌐 Web query:

What is the format and constraints for cfParameters in Chainflip protocol?

💡 Result:

The Chainflip protocol's cfParameters encompass various configuration settings and constraints that govern swap execution, liquidity provisioning, and validator operations. Key components include:

DCA (Dollar Cost Averaging) Parameters

  • Chunk count: Set by brokers but subject to protocol limits[1]
  • Minimum chunk size: Protocol-defined floor per asset (e.g., 1k USDC)[1]
  • Automatic adjustment: Protocol reduces chunks if (total_amount / chunk_size) < requested_chunks[1]

Swap Execution Parameters

type ExecuteSwapParams = {
  srcChain: Chain;
  srcAsset: Asset;
  destChain: Chain;
  destAsset: Asset;
  destAddress: string;
  amount: string; // Base units (e.g., wei)
  ccmParams?: {
    gasBudget: string; // Base units
    message: `0x${string}`; // Hex-encoded <10kB
  };
};

Constraints:

  • ERC-20 token allowances must cover swap amounts[4]
  • Message payloads limited to <10kB[4]
  • Gas budgets specified in source asset base units[4]

Cryptographic Constraints

  • FROST threshold signatures require parameter validation:
    • Generated values must lie in [1,q) range for EdDSA/Schnorr operations[7][10]
    • Strict bounds checking during secret sharing ceremonies[10]

Liquidity Provisioning Parameters

  • Requires State Chain account with staked FLIP[10]
  • Deterministic address generation rules:
    • Bitcoin: HD wallet addresses[10]
    • EVM chains: CREATE2 addresses[10]

Cross-Chain Messaging (CCM)

Receiver interface requirements:

// EVM
function cfReceive(
  uint32 srcChain,
  bytes calldata srcAddress,
  bytes calldata message,
  address token,
  uint256 amount
) external payable;

// Solana
pub fn cf_receive_token(
  source_chain: u32,
  source_address: Vec<u8>,
  message: Vec<u8>,
  amount: u64
) -> Result<()>;

Parameters must match these function signatures exactly[4].

These parameters are enforced through protocol-level validation in both on-chain components (State Chain) and off-chain validator operations[6][7]. Developers can query current parameter values via the cf_environment RPC method[1].

Citations:


Enhance NatSpec Documentation for cfParameters and Non-EVM Address Handling

  • cfParameters: Update the NatSpec for both xSwapNative and xSwapToken to clearly explain that the cfParameters argument encapsulates multiple configuration settings. This includes parameters for dollar cost averaging (e.g., chunk count, minimum chunk size), swap execution details (such as gas budget in source-asset base units and a hex-encoded message limited to less than 10kB), cryptographic constraints (e.g., bounds for threshold signature validation), liquidity provisioning rules, and cross-chain messaging requirements. Referencing the Chainflip protocol documents can provide developers with the necessary context on these expected formats and constraints.

  • Non-EVM Address Clarification: The current NatSpec does not mention a nonEvmAddress parameter—even though the review requested descriptions for it. If the dstAddress parameter is intended to also support non-EVM chain address formats, please clarify this in the documentation by indicating:

    • The expected format for non-EVM addresses.
    • Any differences or additional validations required when dealing with addresses on non-EVM chains.

This enhanced documentation will ensure that developers correctly interpret the parameters and adhere to protocol-level validations.

🧰 Tools
🪛 GitHub Actions: SC Core Dev Approval Check

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


[error] 11-12: Duplicate function declaration for 'xSwapNative'.


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


[error] 11-12: Duplicate function declaration for 'xSwapNative'.

script/demoScripts/demoChainflip.ts (1)

77-77: Consider using constants for chain IDs.

The hardcoded chain ID could be replaced with a constant for better maintainability.

Apply this diff to use the constant:

-        bridgeData.destinationChainId = 42161; // Arbitrum chain ID
+        bridgeData.destinationChainId = CHAIN_ID_ARBITRUM;
test/solidity/Facets/ChainflipFacet.t.sol (2)

45-45: Remove debug logging in production code.

Console logging should be removed before deployment.

-        console.log("Chainflip Vault Address:", CHAINFLIP_VAULT);

118-307: Add missing test scenarios.

The test suite could be enhanced with additional scenarios:

  1. Test for maximum message length
  2. Test for various gas amounts in destination calls
  3. Test for token ID validation

Would you like me to generate the additional test cases?

docs/ChainflipFacet.md (6)

13-19: Enhance method documentation with parameter descriptions.

Consider adding parameter descriptions to make the documentation more comprehensive:

 - `function startBridgeTokensViaChainflip(BridgeData calldata _bridgeData, ChainflipData calldata _chainflipData)`
-  - Bridges tokens using Chainflip without performing any swaps
+  - Bridges tokens using Chainflip without performing any swaps
+  - Parameters:
+    - `_bridgeData`: Contains bridge configuration and analytics data
+    - `_chainflipData`: Contains Chainflip-specific parameters for the transfer

 - `swapAndStartBridgeTokensViaChainflip(BridgeData memory _bridgeData, LibSwap.SwapData[] calldata _swapData, ChainflipData memory _chainflipData)`
-  - Performs swap(s) before bridging tokens using Chainflip
+  - Performs swap(s) before bridging tokens using Chainflip
+  - Parameters:
+    - `_bridgeData`: Contains bridge configuration and analytics data
+    - `_swapData`: Array of swap operations to perform before bridging
+    - `_chainflipData`: Contains Chainflip-specific parameters for the transfer

20-35: Add usage examples for ChainflipData parameters.

Consider adding examples to illustrate how to properly format the parameters:

 }
+
+### Examples
+
+```javascript
+const chainflipData = {
+  // For Bitcoin destination
+  nonEVMReceiver: "0x1234...5678", // Bitcoin address encoded as bytes32
+  dstToken: 20000000000001, // Bitcoin chain ID
+  message: "0x", // Empty for Bitcoin
+  gasAmount: 0, // Not used for Bitcoin
+  cfParameters: "0x" // Empty if no additional parameters
+};
+
+// For Solana destination
+const chainflipData = {
+  nonEVMReceiver: "0x9abc...def0", // Solana address encoded as bytes32
+  dstToken: 1151111081099710, // Solana chain ID
+  message: "0x...", // Optional message data
+  gasAmount: 1000000, // Gas budget for Solana
+  cfParameters: "0x..." // Additional parameters if needed
+};
+```

36-46: Make chain support documentation more maintainable.

Instead of listing specific chains, consider referencing Chainflip's documentation directly:

 ## Supported Chains
 
-The facet supports the following chains with their respective IDs:
+The facet supports various EVM and non-EVM chains. For the most up-to-date list of supported chains and their respective IDs, please refer to:
 
-Ethereum (1)
-Arbitrum (42161)
-Solana (1151111081099710)
-Bitcoin (20000000000001)
-
-[Reference](https://docs.chainflip.io/swapping/integrations/advanced/vault-swaps#supported-chains)
+- [Chainflip Supported Chains Documentation](https://docs.chainflip.io/swapping/integrations/advanced/vault-swaps#supported-chains)
+
+This ensures you always have access to the latest information about supported chains and their IDs.

47-60: Fix grammatical issues in the documentation.

Minor grammatical improvements needed:

-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] ~51-~51: 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)


61-93: Improve readability of the API documentation.

Add proper punctuation and clarify the explanation:

-In the following some sample calls are shown that allow you to retrieve a populated transaction
+In the following section, sample calls are shown that allow you to retrieve a populated transaction
🧰 Tools
🪛 LanguageTool

[uncategorized] ~63-~63: A comma might be missing here.
Context: ...alls to interact with the Facet In the following some sample calls are shown that allow ...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


94-108: Add example responses for API calls.

Consider adding example responses to help users understand what to expect:

 curl 'https://li.quest/v1/quote?fromChain=ETH&fromAmount=1000000&fromToken=USDT&toChain=ARB&toToken=USDC&slippage=0.03&allowBridges=chainflip&fromAddress={YOUR_WALLET_ADDRESS}'

+Example response:
+```json
+{

  • "id": "0x...",
  • "type": "lifi",
  • "tool": "chainflip",
  • "action": {
  • "fromChainId": 1,
  • "toChainId": 42161,
  • "fromToken": "USDT",
  • "toToken": "USDC",
  • "fromAmount": "1000000",
  • "slippage": "0.03"
  • },
  • "estimate": {
  • "toAmount": "998500",
  • "executionDuration": 300
  • }
    +}
    +```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

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

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between ed037ce0ceb55e43a8393466eee8c5df6e816b0d and 6d22b49c290a632969ae30a9ef75a5c7e6f27391.

</details>

<details>
<summary>📒 Files selected for processing (5)</summary>

* `docs/ChainflipFacet.md` (1 hunks)
* `script/demoScripts/demoChainflip.ts` (1 hunks)
* `src/Facets/ChainflipFacet.sol` (1 hunks)
* `src/Interfaces/IChainflip.sol` (1 hunks)
* `test/solidity/Facets/ChainflipFacet.t.sol` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧠 Learnings (1)</summary>

<details>
<summary>docs/ChainflipFacet.md (1)</summary>

Learnt from: ezynda3
PR: #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

</details>

</details><details>
<summary>🪛 LanguageTool</summary>

<details>
<summary>docs/ChainflipFacet.md</summary>

[uncategorized] ~51-~51: 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] ~63-~63: A comma might be missing here.
Context: ...alls to interact with the Facet  In the following some sample calls are shown that allow ...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)

</details>

</details>
<details>
<summary>🪛 GitHub Actions: SC Core Dev Approval Check</summary>

<details>
<summary>test/solidity/Facets/ChainflipFacet.t.sol</summary>

[warning] 1-301: Optional additional test scenarios recommended.

</details>
<details>
<summary>src/Interfaces/IChainflip.sol</summary>

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

---

[error] 11-12: Duplicate function declaration for 'xSwapNative'.

---

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

---

[warning] 6-8: Remove duplicate SPDX license identifier and pragma statements.

---

[error] 11-12: Duplicate function declaration for 'xSwapNative'.

</details>
<details>
<summary>src/Facets/ChainflipFacet.sol</summary>

[warning] 159-181: Consider specifying a gas budget or clarifying zero value usage.

---

[warning] 47-51: Add validation for ChainflipData struct.

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (4)</summary>

* GitHub Check: audit-verification
* GitHub Check: run-unit-tests
* GitHub Check: enforce-min-test-coverage
* GitHub Check: generate-tag

</details>

<details>
<summary>🔇 Additional comments (5)</summary><blockquote>

<details>
<summary>src/Interfaces/IChainflip.sol (1)</summary>

`1-4`: **LGTM!**

The license, pragma, and import statements are correctly defined.

</details>
<details>
<summary>script/demoScripts/demoChainflip.ts (2)</summary>

`1-27`: **LGTM!**

The imports and setup code are well-structured and correctly implemented.

---

`82-82`: <details>
<summary>✅ Verification successful</summary>

**Verify the destination token ID.**

The hardcoded token ID `7` should be verified for correctness.

---

🏁 Script executed:

```shell
#!/bin/bash
# Search for token ID definitions or mappings
rg -A 5 "dstToken.*7" .

Length of output: 982


Token ID Verification: Confirm USDC on Arbitrum Mapping

The test files indicate that the destination token ID is consistently hardcoded as 7—with comments (e.g., in test/solidity/Facets/ChainflipFacet.t.sol) specifying it represents USDC on Arbitrum. Please ensure that this mapping is intentional for the production flow. If this value is correct, consider linking it to a centralized configuration or adding documentation to prevent future ambiguity.

src/Facets/ChainflipFacet.sol (1)

220-234: Consider using a mapping for chain ID conversion.

While the if-else chain works, it could be refactored for better readability.

Based on past review comments and learnings, using if-else with constants is the preferred approach in Solidity since mappings cannot be constant or immutable.

docs/ChainflipFacet.md (1)

3-11: LGTM! Clear and effective explanation.

The overview and diagram effectively communicate how the Chainflip Facet integrates with the LiFiDiamond contract and interacts with the Chainflip Vault.

src/Facets/ChainflipFacet.sol Outdated Show resolved Hide resolved
src/Facets/ChainflipFacet.sol Show resolved Hide resolved
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)
script/demoScripts/demoChainflip.ts (1)

77-84: Consider documenting the Chainflip parameters.

The chainflipData struct contains hardcoded values that might not be immediately clear to users.

Add comments explaining:

  • Why nonEVMReceiver is set to zero bytes32
  • What the dstToken value 3 represents (USDC on ETH)
  • The purpose of empty message and cfParameters
src/Facets/ChainflipFacet.sol (1)

149-154: Consider improving error message for destination call mismatch.

The current error message InformationMismatch is generic and might not help users understand the specific issue.

-            revert InformationMismatch();
+            revert("ChainflipFacet: hasDestinationCall must match message presence");
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6d22b49 and 6d39d19.

📒 Files selected for processing (5)
  • deployments/_deployments_log_file.json (1 hunks)
  • deployments/arbitrum.diamond.staging.json (2 hunks)
  • deployments/arbitrum.staging.json (1 hunks)
  • script/demoScripts/demoChainflip.ts (1 hunks)
  • src/Facets/ChainflipFacet.sol (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • deployments/_deployments_log_file.json
  • deployments/arbitrum.staging.json
  • deployments/arbitrum.diamond.staging.json
⏰ 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 (4)
script/demoScripts/demoChainflip.ts (2)

1-17: LGTM! Clean and well-organized imports.

The imports are logically grouped and include all necessary dependencies for the demo script.


140-145: LGTM! Proper error handling.

The script includes appropriate error handling and process exit codes.

src/Facets/ChainflipFacet.sol (2)

50-56: LGTM! Well-documented struct.

The ChainflipData struct is well-documented with clear parameter descriptions.


220-234: LGTM! Clear chain ID conversion logic.

The chain ID conversion is implemented using if-else statements as recommended, with clear error handling.

Comment on lines +89 to +97
const swapData = await getUniswapDataERC20toExactERC20(
ADDRESS_UNISWAP_ARB, // Uniswap router address on Arbitrum
42161, // Arbitrum chain id
ADDRESS_USDT_ARB, // Swap from USDT
ADDRESS_USDC_ARB, // Swap to USDC
amount, // The exact output amount we want in USDC
lifiDiamondAddress, // Receiver for the swapped tokens (the diamond)
true // requiresDeposit flag
)
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Consider adding slippage protection for the swap.

The swap data is generated without explicit slippage parameters, which could lead to unfavorable rates.


🏁 Script executed:

#!/bin/bash
# Check if getUniswapDataERC20toExactERC20 includes slippage protection
rg -A 5 "getUniswapDataERC20toExactERC20" ./script/demoScripts/utils/

Length of output: 540


Action Required: Add explicit slippage protection to the swap

It appears that the function getUniswapDataERC20toExactERC20—as currently implemented in script/demoScripts/utils/demoScriptHelpers.ts—does not include any parameter or logic for specifying a slippage tolerance. Given that the swap data is generated without explicit slippage parameters, this might expose the swap to unfavorable rate fluctuations.

  • Location: script/demoScripts/demoChainflip.ts (lines 89–97)
  • Verification: The search output for getUniswapDataERC20toExactERC20 confirmed that the function signature accepts the uniswap router address, chain ID, sending and receiving asset IDs, and the exact output amount—but no slippage parameter is present.

Please consider enhancing the function to incorporate slippage protection, either by adding a new parameter or integrating a mechanism that adjusts the swap to guard against price volatility.

Comment on lines +157 to +179
if (_bridgeData.sendingAssetId == address(0)) {
if (_bridgeData.hasDestinationCall) {
IChainflipVault(chainflipVault).xCallNative{
value: _bridgeData.minAmount
}(
dstChain,
encodedDstAddress,
_chainflipData.dstToken,
_chainflipData.message,
_chainflipData.gasAmount,
_chainflipData.cfParameters
);
} else {
IChainflipVault(chainflipVault).xSwapNative{
value: _bridgeData.minAmount
}(
dstChain,
encodedDstAddress,
_chainflipData.dstToken,
_chainflipData.cfParameters
);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Consider adding gas budget validation for cross-chain calls.

The contract forwards native value without validating the gas budget, which could lead to failed transactions on the destination chain.


🌐 Web query:

What is the recommended gas budget for Chainflip cross-chain calls?

💡 Result:

The recommended gas budget for Chainflip cross-chain calls depends on the specific blockchain involved and transaction type. Based on available data:

For Ethereum deposits:

  • Typical gas usage is ~31k gas[5], costing significantly less than standard swaps (about 1/3 of Uniswap v3 trade costs)[1].
  • Batching reduces costs further for destination-chain transfers[5].

General guidelines:

  1. Destination-chain variability:
    • Gas budgets should account for real-time network conditions on the target chain (e.g., Solana/NEAR typically cost $2k-$10k daily)[4].
    • Use Symbiosis-like logic where calldata includes stablecoin-equivalent gas estimates for S-chain and destination-chain steps[2].

Key optimization factors:

  • Chainflip's app-chain architecture minimizes external computation costs by handling logic internally[1][9].
  • Batching combines multiple egress transactions into single broadcasts to reduce per-transaction overhead[5].
  • Protocol automatically deducts estimated gas fees from swap outputs during broadcast[5].

For developers:

  • Use Symbiosis-style simulations to verify calldata executability before setting budgets[2].
  • Refer to Chainflip's SDK/API tools for real-time fee estimations[2][5].

While exact figures vary by chain, Ethereum-based swaps generally require budgeting ~31k gas plus destination-chain fees adjusted through batching optimizations[1][5].

Citations:


Gas Budget Validation for Cross-Chain Calls

In src/Facets/ChainflipFacet.sol (lines 157–179), the contract currently forwards native value without verifying that the provided gas budget (i.e., _chainflipData.gasAmount) is sufficient for execution on the destination chain. Based on Chainflip guidance, for Ethereum-based swaps a typical gas budget is around ~31k gas (plus additional destination-chain fees when applicable), though exact requirements depend on real-time network conditions.

  • Action Required:
    Add a check to validate that _chainflipData.gasAmount meets or exceeds an expected threshold (for example, at least ~31k gas for Ethereum) before initiating a cross-chain call. Consider using Chainflip’s SDK/API or Symbiosis-style simulation logic to determine the appropriate gas amount dynamically.

  • Rationale:
    Without this validation, insufficient gas could lead to failed transactions on the destination chain.

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