Skip to content

Conversation

@ezynda3
Copy link
Contributor

@ezynda3 ezynda3 commented Aug 14, 2025

Which Jira task belongs to this PR?

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>

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 14, 2025

Walkthrough

Adds EcoFacet and IEcoPortal, docs, tests, deploy/update scripts, a TypeScript demo and helper constants, deployment metadata/log entries, a devDependency, and updates config/eco.json to set portal addresses for ten networks to 0x399Dbd5DF04f83103F77A58cBa2B7c4d3cdede97. No other runtime modules modified. (50 words)

Changes

Cohort / File(s) Summary of changes
Facet & Interface
src/Facets/EcoFacet.sol, src/Interfaces/IEcoPortal.sol
New EcoFacet implementation and IEcoPortal interface: PORTAL immutable and constructor, startBridgeTokensViaEco & swapAndStartBridgeTokensViaEco entrypoints, EcoData/Route/Call structs, TokenAmount/Reward types, reward building, deposit/approval logic, encoded-route and receiver validation, and calls to publishAndFund.
Tests
test/solidity/Facets/EcoFacet.t.sol
New comprehensive Solidity test suite and TestEcoFacet harness covering native/ERC20 bridge & swap flows, Solana/TRON/non‑EVM routing validation, ABI‑decode edge cases, chainId boundary checks, and test helpers/dispatchers.
Deploy & Update Scripts
script/deploy/facets/DeployEcoFacet.s.sol, script/deploy/facets/UpdateEcoFacet.s.sol
New Foundry deploy and update scripts. DeployEcoFacet reads network portal from config/eco.json via .portal and encodes constructor args; UpdateEcoFacet exposes an update run for the facet.
Config
config/eco.json
Updated network entries (optimism, base, arbitrum, celo, mainnet, ink, polygon, unichain, sonic, tron) setting each network's portal field to 0x399Dbd5DF04f83103F77A58cBa2B7c4d3cdede97.
Documentation
docs/EcoFacet.md
Added documentation describing EcoFacet workflow, public methods, EcoData struct fields, routing/receiver rules for EVM/Solana/TRON, encodedRoute usage, example quote/transaction payloads and sample calls.
Demo Script & Helpers (TS)
script/demoScripts/demoEco.ts, script/demoScripts/utils/demoScriptHelpers.ts
Added demoEco.ts full demo (Eco quote flow, Solana recipient/ATA derivation, encodedRoute handling). Minor helper edits: trimmed trailing space in ADDRESS_WMATIC_POL and added ADDRESS_WETH_BASE, ADDRESS_USDC_BASE, ADDRESS_UNISWAP_BASE.
Deployments Metadata & Log
deployments/optimism.staging.json, deployments/optimism.diamond.staging.json, deployments/_deployments_log_file.json
Added EcoFacet entries/addresses to Optimism deployment JSONs; multiple facet adds/updates in diamond staging file; appended an EcoFacet deployment record to deployments log.
Package
package.json
Added devDependency @solana/spl-token ^0.4.9.
Audit Log
audit/auditLog.json
Added audit20251001 entry and associated EcoFacet and IEcoPortal to auditedContracts.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

AuditCompleted

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The description follows the repository’s template structure but leaves critical sections empty—specifically the Jira task identifier and the rationale for the implementation—and the checkboxes for adding tests and updating documentation remain unchecked, making the description incomplete. Please fill in the “Which Jira task belongs to this PR?” and “Why did I implement it this way?” sections with the appropriate ticket number and rationale, complete the tests and documentation additions, and update the corresponding checklist items before requesting a review.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title “Implement EcoFacet [EcoFacet v1.0.0,IEcoPortal v1.0.0]” clearly summarizes the main change by indicating the addition of the EcoFacet and its interface at version 1.0.0 and is directly related to the changeset.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch LF-14918-Eco-Facet

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

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

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

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@lifi-action-bot lifi-action-bot marked this pull request as draft August 14, 2025 07:39
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

🔭 Outside diff range comments (1)
flake.nix (1)

1-44: PR title mismatch — "Implement EcoFacet" but no EcoFacet added; only devShell change (flake.nix)

Verified findings (checked HEAD on branch coderabbit_1324):

  • HEAD commit: "fix missing packages for nix"
  • Files changed in this PR: flake.nix (only)
  • No occurrences of "EcoFacet" in the repository (search returned nothing)
  • src/Facets/ exists and contains many facets, but no EcoFacet

Action required — please do one of the following:

  • Add the EcoFacet contract (src/Facets/EcoFacet.sol) plus tests/docs, following the project's Diamond conventions (name must include "Facet"), or
  • Retitle the PR to reflect the actual change, e.g. "DevShell: add jq/bc/gum/mongosh"
🧹 Nitpick comments (2)
flake.nix (2)

26-29: Useful tooling additions; consider splitting optional/heavy tools into a separate devShell to keep default lean

jq/bc are lightweight and commonly used in scripts; gum and especially mongosh tend to be optional and significantly increase the initial download/activation cost for all contributors. Recommend moving gum and mongosh into a secondary dev shell (e.g., .#tools) so default stays fast.

Apply this diff to keep default minimal:

-            jq
-            bc
-            gum
-            mongosh
+            jq
+            bc

Add this new dev shell (outside the selected lines) to offer the extras on demand:

devShells.tools = pkgs.mkShell {
  buildInputs = with pkgs; [
    gum
    mongosh
  ];
};

Developers who need these can run: nix develop .#tools


22-30: mkShell best practice: prefer packages over buildInputs for readability

In mkShell, packages is the modern, clearer attribute for PATH-population. Functionally similar here, but improves intent and consistency.

-          buildInputs = with pkgs; [
+          packages = with pkgs; [
             bun
             foundry
             stdenv.cc.cc.lib
             jq
             bc
             gum
             mongosh
           ];
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 697eb59 and 21601b2.

📒 Files selected for processing (1)
  • flake.nix (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to src/Facets/*Facet.sol : Facet contracts must reside in `src/Facets/` and names must include "Facet".
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: run-unit-tests
🔇 Additional comments (1)
flake.nix (1)

26-29: Confirm: mongosh & gum available on nixpkgs-unstable; mongosh licensed Apache-2.0

Both mongosh and gum are packaged on nixpkgs-unstable for Linux and macOS (x86_64-linux / x86_64-darwin). The MongoDB Shell (mongosh) is released under Apache-2.0. No blocking license or portability issues found.

  • Files to note: flake.nix — lines 26–29 (jq, bc, gum, mongosh) — leave as-is.

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: 3

♻️ Duplicate comments (1)
src/Facets/EcoFacet.sol (1)

178-181: Consider checking the return value of publishAndFund.

The static analysis hint indicates that the return value from publishAndFund is not being used. While this might be intentional, consider whether the returned intent ID should be logged or used for tracking purposes.

#!/bin/bash
# Description: Check how other facets handle return values from bridge protocols

# Search for similar external bridge calls in other facets
ast-grep --pattern '$_($$$).$METHOD{value: $_}($$$)'

# Check if other facets capture and use return values
rg -A 2 -B 2 'returns \(bytes32\)' src/Interfaces/

If the return value contains important information like an intent ID, consider capturing and emitting it in an event for better observability:

-        IEco(_ecoData.intentSource).publishAndFund{ value: nativeValue }(
-            intent,
-            _ecoData.allowPartial
-        );
+        bytes32 intentId = IEco(_ecoData.intentSource).publishAndFund{ value: nativeValue }(
+            intent,
+            _ecoData.allowPartial
+        );
+        // Consider emitting the intentId if needed for tracking
🧹 Nitpick comments (4)
src/Facets/EcoFacet.sol (1)

46-47: Consider reusing existing error types.

The InvalidDeadline error is already defined in GenericErrors.sol according to the AI summary. Consider importing and reusing it instead of redefining it here.

-error InvalidProver();
-error InvalidDeadline();
+import { InvalidDeadline, InvalidProver } from "../Errors/GenericErrors.sol";

Then remove the error definitions on lines 46-47.

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

160-170: Test assertion could be more specific.

The test only checks for event emission but doesn't verify that the DEFAULT_PROVER is actually used in the intent. Consider enhancing the test to decode and verify the event data.

     function test_EcoFacet_UsesDefaultProverWhenNotProvided() public {
         // validEcoData already has prover set to address(0)
         // Should use DEFAULT_PROVER from constructor
 
-        vm.expectEmit(false, false, false, true, address(mockIntentSource));
-
-        // We expect the intent to have DEFAULT_PROVER
-        // The actual event checking would require decoding the Intent struct
+        // Expect the MockIntentSource to emit with the correct prover
+        vm.expectEmit(true, true, true, true, address(mockIntentSource));
+        
+        // Construct expected intent with DEFAULT_PROVER
+        IEco.Intent memory expectedIntent = IEco.Intent({
+            route: IEco.Route({
+                source: address(ecoFacet),
+                destination: bridgeData.destinationChainId,
+                data: validEcoData.routeData
+            }),
+            reward: IEco.Reward({
+                prover: DEFAULT_PROVER,
+                tokens: _createTokenArray(bridgeData.sendingAssetId),
+                amounts: _createAmountArray(bridgeData.minAmount),
+                deadline: validEcoData.deadline,
+                nonce: validEcoData.nonce
+            })
+        });
+        
+        emit MockIntentSource.IntentPublishedAndFunded(expectedIntent, false, 0);
 
         ecoFacet.startBridgeTokensViaEco(bridgeData, validEcoData);
     }
+    
+    function _createTokenArray(address token) private pure returns (address[] memory) {
+        address[] memory tokens = new address[](1);
+        tokens[0] = token;
+        return tokens;
+    }
+    
+    function _createAmountArray(uint256 amount) private pure returns (uint256[] memory) {
+        uint256[] memory amounts = new uint256[](1);
+        amounts[0] = amount;
+        return amounts;
+    }

172-179: Consider adding assertion for custom prover usage.

Similar to the default prover test, this test should verify that the custom prover is actually used in the intent.

Add event verification to ensure the custom prover is used:

     function test_EcoFacet_UsesProvidedProverWhenSet() public {
         address customProver = address(0x9999);
         EcoFacet.EcoData memory customData = validEcoData;
         customData.prover = customProver;
 
+        // Expect the event with custom prover
+        vm.expectEmit(true, true, true, true, address(mockIntentSource));
+        
+        // Construct expected intent with custom prover
+        IEco.Intent memory expectedIntent = IEco.Intent({
+            route: IEco.Route({
+                source: address(ecoFacet),
+                destination: bridgeData.destinationChainId,
+                data: customData.routeData
+            }),
+            reward: IEco.Reward({
+                prover: customProver,
+                tokens: _createTokenArray(bridgeData.sendingAssetId),
+                amounts: _createAmountArray(bridgeData.minAmount),
+                deadline: customData.deadline,
+                nonce: customData.nonce
+            })
+        });
+        
+        emit MockIntentSource.IntentPublishedAndFunded(expectedIntent, false, 0);
+
         // Should use the provided prover instead of default
         ecoFacet.startBridgeTokensViaEco(bridgeData, customData);
     }

140-179: Consider adding more test coverage.

While the test suite covers basic functionality, consider adding tests for:

  1. Native token bridging scenarios (with msg.value)
  2. Swap and bridge functionality
  3. Partial fulfillment scenarios (allowPartial = true)
  4. Edge cases around deadline (e.g., deadline == block.timestamp)

Would you like me to generate additional test cases to improve coverage for these scenarios?

📜 Review details

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

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 21601b2 and d792e89.

📒 Files selected for processing (9)
  • config/eco.json (1 hunks)
  • docs/EcoFacet.md (1 hunks)
  • script/demoScripts/demoEco.ts (1 hunks)
  • script/deploy/facets/DeployEcoFacet.s.sol (1 hunks)
  • script/deploy/facets/UpdateEcoFacet.s.sol (1 hunks)
  • src/Errors/GenericErrors.sol (1 hunks)
  • src/Facets/EcoFacet.sol (1 hunks)
  • src/Interfaces/IEco.sol (1 hunks)
  • test/solidity/Facets/EcoFacet.t.sol (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • docs/EcoFacet.md
  • config/eco.json
🧰 Additional context used
📓 Path-based instructions (9)
{src/**/*.sol,test/solidity/**/*.sol,script/**/*.sol}

📄 CodeRabbit Inference Engine (conventions.md)

All our own Solidity files must use the LGPL-3.0 license identifier. This applies to all contracts in src/, all test files in test/solidity/, and all deployment and task scripts in script/.

Files:

  • script/deploy/facets/UpdateEcoFacet.s.sol
  • src/Interfaces/IEco.sol
  • src/Facets/EcoFacet.sol
  • src/Errors/GenericErrors.sol
  • script/deploy/facets/DeployEcoFacet.s.sol
  • test/solidity/Facets/EcoFacet.t.sol
**/*.sol

📄 CodeRabbit Inference Engine (conventions.md)

**/*.sol: Use custom error types rather than generic revert() statements.
Do not define interfaces in the same file as their implementation.
Every contract MUST have the following NatSpec tags in this order: @title, @author, @notice, @Custom:version.
The @author tag MUST always be "LI.FI (https://li.fi)" in contract NatSpec.
The @Custom:version MUST follow semantic versioning (X.Y.Z format) in contract NatSpec.
Every public/external function must have NatSpec comments describing the function, parameters, and return values.
All Solidity files must follow the rules defined in .solhint.json.
All Solidity files must use the EVM and Solidity version defined in foundry.toml unless networks require lower versions.

Files:

  • script/deploy/facets/UpdateEcoFacet.s.sol
  • src/Interfaces/IEco.sol
  • src/Facets/EcoFacet.sol
  • src/Errors/GenericErrors.sol
  • script/deploy/facets/DeployEcoFacet.s.sol
  • test/solidity/Facets/EcoFacet.t.sol
{script/deploy/facets/*.sol,script/deploy/zksync/*.sol}

📄 CodeRabbit Inference Engine (conventions.md)

{script/deploy/facets/*.sol,script/deploy/zksync/*.sol}: Deployment scripts must reside in script/deploy/facets/ for base deployments and script/deploy/zksync/ for ZKSync-specific scripts.
Deployment scripts must inherit DeployScriptBase and use JSON config with stdJson.
Update scripts must inherit UpdateScriptBase and use update("{ContractName}").

Files:

  • script/deploy/facets/UpdateEcoFacet.s.sol
  • script/deploy/facets/DeployEcoFacet.s.sol
src/Interfaces/*.sol

📄 CodeRabbit Inference Engine (conventions.md)

src/Interfaces/*.sol: All interfaces must start with I prefix (e.g., ILiFi, IStargate).
All interfaces must be placed in separate files in the src/Interfaces directory.
Every interface MUST have the following NatSpec tags in this order: @title, @notice, @author, @Custom:version.

Files:

  • src/Interfaces/IEco.sol
src/Interfaces/I*.sol

📄 CodeRabbit Inference Engine (conventions.md)

All interfaces must be placed in separate files in the src/Interfaces directory and start with I.

Files:

  • src/Interfaces/IEco.sol
src/Facets/*Facet.sol

📄 CodeRabbit Inference Engine (conventions.md)

Facet contracts must reside in src/Facets/ and names must include "Facet".

Files:

  • src/Facets/EcoFacet.sol
script/**/*.ts

📄 CodeRabbit Inference Engine (conventions.md)

script/**/*.ts: All scripts must follow the rules defined in .eslintrc.cjs.
Use async/await for asynchronous operations in TypeScript scripts.
Handle errors appropriately with try/catch blocks in TypeScript scripts.
Include proper logging for debugging and monitoring in TypeScript scripts.
Use environment variables for configuration in TypeScript scripts.
All scripts must use citty for CLI argument parsing.
Use consola for consistent logging across TypeScript scripts.
Environment variables should be validated using getEnvVar() helper in TypeScript scripts.
Scripts should exit with appropriate exit codes (0 for success, 1 for error) in TypeScript scripts.

Files:

  • script/demoScripts/demoEco.ts
src/Errors/GenericErrors.sol

📄 CodeRabbit Inference Engine (conventions.md)

src/Errors/GenericErrors.sol: All custom errors must be defined in src/Errors/GenericErrors.sol.
Error names should be descriptive and follow PascalCase.
Errors should not include error messages (for gas optimization).
All custom errors should be defined in src/Errors/GenericErrors.sol and not include error messages.

Files:

  • src/Errors/GenericErrors.sol
test/solidity/**/*.t.sol

📄 CodeRabbit Inference Engine (conventions.md)

test/solidity/**/*.t.sol: Test files must have a .t.sol extension.
All tests that verify a successful execution must be prefixed with: test_.
All tests that verify a failure case must be prefixed with: testRevert_.
For base or inherited tests, prefix with testBase_.
Every test contract must include a setUp() function.
Any contract inheriting from TestBase.sol must call initTestBase() in setUp().
Use assertEq() for checking equality of values in tests.
Use vm.expectRevert() to verify specific revert reasons in failure test cases.
Use vm.expectEmit(true, true, true, true, <contractAddress>) for event testing.
All Solidity test files must be organized mirroring the src/ structure.
All Solidity test files must use Foundry.

Files:

  • test/solidity/Facets/EcoFacet.t.sol
🧠 Learnings (19)
📓 Common learnings
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to src/Facets/*Facet.sol : Facet contracts must reside in `src/Facets/` and names must include "Facet".
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to {script/deploy/facets/*.sol,script/deploy/zksync/*.sol} : Update scripts must inherit `UpdateScriptBase` and use `update("{ContractName}")`.

Applied to files:

  • script/deploy/facets/UpdateEcoFacet.s.sol
  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to {script/deploy/facets/*.sol,script/deploy/zksync/*.sol} : Deployment scripts must inherit `DeployScriptBase` and use JSON config with `stdJson`.

Applied to files:

  • script/deploy/facets/UpdateEcoFacet.s.sol
  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to {script/deploy/facets/*.sol,script/deploy/zksync/*.sol} : Deployment scripts must reside in `script/deploy/facets/` for base deployments and `script/deploy/zksync/` for ZKSync-specific scripts.

Applied to files:

  • script/deploy/facets/UpdateEcoFacet.s.sol
  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-01-28T14:27:50.689Z
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.

Applied to files:

  • script/deploy/facets/UpdateEcoFacet.s.sol
  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-07-16T01:04:55.857Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1275
File: src/Facets/AllBridgeFacet.sol:186-188
Timestamp: 2025-07-16T01:04:55.857Z
Learning: In LiFi facet contracts, when public entry point functions have `nonReentrant` modifier protection, internal functions like `_startBridge` that they call benefit from this reentrancy protection, making event emission order after external calls acceptable from a security perspective.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2024-11-25T09:04:55.880Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: script/deploy/_targetState.json:143-143
Timestamp: 2024-11-25T09:04:55.880Z
Learning: Errors about the missing `OpBNBBridgeFacet` contract are expected when it is referenced in the target state but not yet merged into the main branch.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to src/Facets/*Facet.sol : Facet contracts must reside in `src/Facets/` and names must include "Facet".

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to src/Errors/GenericErrors.sol : All custom errors must be defined in `src/Errors/GenericErrors.sol`.

Applied to files:

  • src/Errors/GenericErrors.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to src/Errors/GenericErrors.sol : All custom errors should be defined in `src/Errors/GenericErrors.sol` and not include error messages.

Applied to files:

  • src/Errors/GenericErrors.sol
📚 Learning: 2024-09-23T01:42:03.075Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: script/deploy/facets/DeployGasZipFacet.s.sol:22-35
Timestamp: 2024-09-23T01:42:03.075Z
Learning: In deployment scripts like `DeployGasZipFacet.s.sol`, do not report issues suggesting adding error handling for missing configuration files or unexpected JSON structures, as the script will fail if the file is missing.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-06-13T08:30:28.665Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1207
File: script/deploy/facets/DeployPioneerFacet.s.sol:17-27
Timestamp: 2025-06-13T08:30:28.665Z
Learning: Deployment scripts rely on external automation (pre-script checks) to validate constructor arguments such as non-zero addresses, so adding explicit `require` guards inside the Foundry deployment scripts is generally unnecessary.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2024-10-31T09:07:36.301Z
Learnt from: ezynda3
PR: lifinance/contracts#843
File: script/deploy/facets/DeployRelayFacet.s.sol:0-0
Timestamp: 2024-10-31T09:07:36.301Z
Learning: In `script/deploy/facets/DeployRelayFacet.s.sol`, additional validation for the configuration file existence and address validity is unnecessary because the code will already fail appropriately if the configuration file is missing or the addresses are invalid.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2024-11-25T13:49:40.464Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: script/deploy/zksync/DeployPermit2Proxy.s.sol:22-61
Timestamp: 2024-11-25T13:49:40.464Z
Learning: In the deploy scripts (e.g., `script/deploy/zksync/DeployPermit2Proxy.s.sol`), complex error handling and address validation are not necessary. The team prefers to keep deploy scripts simple without extensive error handling.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-01-20T04:21:41.973Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#931
File: script/deploy/facets/DeployCBridgeFacetPacked.s.sol:27-29
Timestamp: 2025-01-20T04:21:41.973Z
Learning: In deployment scripts, validation of deployerAddress is not needed as it's guaranteed to be available through the deploy script's context.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-06-05T10:00:01.583Z
Learnt from: mirooon
PR: lifinance/contracts#1145
File: script/tasks/diamondSyncWhitelistedAddresses.sh:208-209
Timestamp: 2025-06-05T10:00:01.583Z
Learning: Task scripts in script/tasks/ directory (like diamondSyncWhitelistedAddresses.sh) define functions that are sourced by deployAllContracts.sh and called from there, rather than executing directly. They don't need to call their own functions at the end of the file.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-07-23T08:12:29.064Z
Learnt from: mirooon
PR: lifinance/contracts#1193
File: script/deploy/facets/UpdateWhitelistManagerFacet.s.sol:1-1
Timestamp: 2025-07-23T08:12:29.064Z
Learning: Deployment scripts in script/deploy/ should not use the LGPL-3.0 license identifier, contrary to other Solidity files. Scripts can use UNLICENSED or other appropriate license identifiers.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-07-11T09:43:22.393Z
Learnt from: mirooon
PR: lifinance/contracts#1193
File: test/solidity/Facets/AllowListMigratorFacet.t.sol:39-52
Timestamp: 2025-07-11T09:43:22.393Z
Learning: For fork-based tests like AllowListMigratorFacet.t.sol that work with existing deployed contracts (mainnet diamond), initTestBase() is intentionally omitted since the standard test initialization is not needed.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-01-22T12:36:12.699Z
Learnt from: mirooon
PR: lifinance/contracts#945
File: test/solidity/Facets/GlacisFacet.t.sol:214-262
Timestamp: 2025-01-22T12:36:12.699Z
Learning: The GlacisFacet test suite inherits from TestBaseFacet which already covers various failure scenarios including invalid receiver address, invalid amounts, same chain bridging, and insufficient funds, making additional failure scenario tests redundant.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
🪛 GitHub Check: Olympix Integrated Security
src/Facets/EcoFacet.sol

[warning] 178-178:
Calling a function without checking the return value may lead to silent failures. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/unused-return-function-call

🔇 Additional comments (19)
src/Errors/GenericErrors.sol (1)

20-25: New errors are well-scoped, centralized, and convention-compliant

Both InvalidDeadline() and InvalidProver() follow our error conventions (PascalCase, no messages) and are correctly added to GenericErrors for reuse across the codebase.

script/deploy/facets/UpdateEcoFacet.s.sol (2)

10-15: Update script pattern looks correct

Inherits UpdateScriptBase and delegates via update("EcoFacet"). This aligns with our deployment/update workflow.


1-1: Confirm SPDX identifier policy for deployment scripts

There’s an org-level nuance: coding guidelines say scripts use LGPL-3.0, while team learnings (PR #1193) indicate deploy scripts should use UNLICENSED. Please confirm which to follow for consistency across this repo before merging.

If UNLICENSED is preferred, apply:

-// SPDX-License-Identifier: LGPL-3.0-only
+// SPDX-License-Identifier: UNLICENSED
script/deploy/facets/DeployEcoFacet.s.sol (1)

1-1: Confirm SPDX identifier policy for deployment scripts

Same nuance as the update script: guidelines vs. team practice differ. Please confirm before merge.

If UNLICENSED is preferred:

-// SPDX-License-Identifier: LGPL-3.0-only
+// SPDX-License-Identifier: UNLICENSED
src/Interfaces/IEco.sol (1)

5-58: Interface conforms to repo standards and is well-documented

  • Correct location and I-prefixed name.
  • Required NatSpec headers present and in the correct order.
  • Function NatSpec with params/returns provided.
  • Structs capture the needed fields for the Eco intent system.

Looks good.

src/Facets/EcoFacet.sol (10)

14-17: LGTM! Contract metadata is properly documented.

The NatSpec documentation follows the required format with all mandatory tags (@title, @author, @notice, @custom:version) in the correct order.


53-56: LGTM! Constructor properly validates the default prover.

The constructor correctly validates that the default prover is not the zero address, preventing misconfiguration.


60-80: LGTM! Entry point is properly protected and validated.

The function has appropriate modifiers for reentrancy protection, validation, and excess native refund. It correctly deposits assets before initiating the bridge.


86-106: LGTM! Swap and bridge function is well-structured.

The function correctly performs swaps before bridging with proper validation and protection modifiers. The updated minAmount from swaps is correctly passed to the bridge.


117-120: LGTM! Intent source validation is correct.

The function properly validates that the intent source address is not zero before proceeding with the bridge operation.


123-125: LGTM! Deadline validation prevents expired intents.

The validation correctly ensures the deadline is in the future by checking it's greater than the current block timestamp.


141-143: LGTM! Prover selection logic is correct.

The ternary operator correctly uses the provided prover if non-zero, otherwise falls back to the DEFAULT_PROVER.


159-165: LGTM! Token approval logic is correct.

The function correctly checks if the asset is native before attempting to approve the ERC20 token to the intent source.


174-175: LGTM! Event emission follows best practices.

The LiFiTransferStarted event is correctly emitted before the external call, which is safe due to the nonReentrant modifier protection on the entry points.


128-132: No change required — address(this) is correct (it will be the diamond address at runtime)

The facet is invoked via the diamond (delegatecall), so address(this) inside the facet resolves to the diamond address. Tests demonstrate this usage.

  • src/Facets/EcoFacet.sol — IEco.Route { source: address(this), ... } (snapshot around lines 128–132).
  • test/solidity/Facets/EcoFacet.t.sol — setUp adds the facet to the diamond and then does ecoFacet = TestEcoFacet(address(diamond));, confirming calls run through the diamond.

Likely an incorrect or invalid review comment.

test/solidity/Facets/EcoFacet.t.sol (4)

11-37: LGTM! Mock implementation is well-structured.

The mock Intent Source correctly implements the IEco interface for testing purposes with appropriate event emission and deterministic return values.


40-50: LGTM! Test wrapper provides necessary access to internal functions.

The test wrapper correctly exposes LibAllowList functionality needed for test setup.


58-110: LGTM! Test setup is comprehensive and well-organized.

The setup correctly:

  • Initializes the test base
  • Deploys mock contracts
  • Configures the diamond with the facet
  • Sets up DEX allowlists
  • Creates valid test data

149-158: LGTM! Deadline validation test is correct.

The test properly validates that expired deadlines are rejected with the correct error selector.

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: 3

♻️ Duplicate comments (1)
test/solidity/Facets/EcoFacet.t.sol (1)

140-151: Use a specific revert selector and follow failure test naming convention

  • Replace the generic vm.expectRevert() with the specific InvalidContract selector per our guidelines.
  • Rename the test to start with testRevert_ to comply with our test naming convention for failure cases.

Apply within this hunk:

-function test_EcoFacet_RevertWhenIntentSourceNotProvided() public {
+function testRevert_EcoFacet_WhenIntentSourceNotProvided() public {
   vm.startPrank(USER_SENDER);

   // approval
   usdc.approve(_facetTestContractAddress, bridgeData.minAmount);

   EcoFacet.EcoData memory invalidData = validEcoData;
   invalidData.intentSource = address(0);

-  vm.expectRevert();
+  vm.expectRevert(abi.encodeWithSelector(InvalidContract.selector));
   ecoFacet.startBridgeTokensViaEco(bridgeData, invalidData);

   vm.stopPrank();
}

Additionally add the missing import at the top of the file:

import { InvalidContract } from "../../../src/Errors/GenericErrors.sol";
📜 Review details

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

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d792e89 and a058afc.

📒 Files selected for processing (1)
  • test/solidity/Facets/EcoFacet.t.sol (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
{src/**/*.sol,test/solidity/**/*.sol,script/**/*.sol}

📄 CodeRabbit Inference Engine (conventions.md)

All our own Solidity files must use the LGPL-3.0 license identifier. This applies to all contracts in src/, all test files in test/solidity/, and all deployment and task scripts in script/.

Files:

  • test/solidity/Facets/EcoFacet.t.sol
**/*.sol

📄 CodeRabbit Inference Engine (conventions.md)

**/*.sol: Use custom error types rather than generic revert() statements.
Do not define interfaces in the same file as their implementation.
Every contract MUST have the following NatSpec tags in this order: @title, @author, @notice, @Custom:version.
The @author tag MUST always be "LI.FI (https://li.fi)" in contract NatSpec.
The @Custom:version MUST follow semantic versioning (X.Y.Z format) in contract NatSpec.
Every public/external function must have NatSpec comments describing the function, parameters, and return values.
All Solidity files must follow the rules defined in .solhint.json.
All Solidity files must use the EVM and Solidity version defined in foundry.toml unless networks require lower versions.

Files:

  • test/solidity/Facets/EcoFacet.t.sol
test/solidity/**/*.t.sol

📄 CodeRabbit Inference Engine (conventions.md)

test/solidity/**/*.t.sol: Test files must have a .t.sol extension.
All tests that verify a successful execution must be prefixed with: test_.
All tests that verify a failure case must be prefixed with: testRevert_.
For base or inherited tests, prefix with testBase_.
Every test contract must include a setUp() function.
Any contract inheriting from TestBase.sol must call initTestBase() in setUp().
Use assertEq() for checking equality of values in tests.
Use vm.expectRevert() to verify specific revert reasons in failure test cases.
Use vm.expectEmit(true, true, true, true, <contractAddress>) for event testing.
All Solidity test files must be organized mirroring the src/ structure.
All Solidity test files must use Foundry.

Files:

  • test/solidity/Facets/EcoFacet.t.sol
🧠 Learnings (9)
📚 Learning: 2025-07-11T09:43:22.393Z
Learnt from: mirooon
PR: lifinance/contracts#1193
File: test/solidity/Facets/AllowListMigratorFacet.t.sol:39-52
Timestamp: 2025-07-11T09:43:22.393Z
Learning: For fork-based tests like AllowListMigratorFacet.t.sol that work with existing deployed contracts (mainnet diamond), initTestBase() is intentionally omitted since the standard test initialization is not needed.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to src/Facets/*Facet.sol : Facet contracts must reside in `src/Facets/` and names must include "Facet".

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-22T03:16:28.754Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: test/solidity/Facets/GasZipFacet.t.sol:212-213
Timestamp: 2024-10-22T03:16:28.754Z
Learning: In the `GasZipFacetTest`, for the test case `testBase_Revert_SwapAndBridgeWithInvalidSwapData()`, a generic revert is expected, so `vm.expectRevert();` without specifying the expected error is appropriate.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-10T03:26:23.793Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: test/solidity/Helpers/WithdrawablePeriphery.t.sol:79-80
Timestamp: 2024-10-10T03:26:23.793Z
Learning: In Solidity tests, it's acceptable to use `UnAuthorized.selector` in `vm.expectRevert()`; avoid suggesting changing it to string messages.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : Use `vm.expectRevert()` to verify specific revert reasons in failure test cases.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-22T03:24:24.705Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: test/solidity/Facets/GasZipFacet.t.sol:337-339
Timestamp: 2024-10-22T03:24:24.705Z
Learning: In `GasZipFacet` tests, when expecting a failure due to insufficient balance for sending value, the test should expect a generic revert without specifying a specific error.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : All tests that verify a failure case must be prefixed with: `testRevert_`.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : Use `vm.expectEmit(true, true, true, true, <contractAddress>)` for event testing.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-01-22T12:36:12.699Z
Learnt from: mirooon
PR: lifinance/contracts#945
File: test/solidity/Facets/GlacisFacet.t.sol:214-262
Timestamp: 2025-01-22T12:36:12.699Z
Learning: The GlacisFacet test suite inherits from TestBaseFacet which already covers various failure scenarios including invalid receiver address, invalid amounts, same chain bridging, and insufficient funds, making additional failure scenario tests redundant.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
🔇 Additional comments (1)
test/solidity/Facets/EcoFacet.t.sol (1)

68-81: LGTM: Facet registration into the diamond is correct

Properly collecting function selectors and re-binding the facet handle to the diamond address is aligned with our diamond test pattern. This ensures subsequent calls go through the diamond.

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

♻️ Duplicate comments (3)
src/Facets/EcoFacet.sol (1)

189-195: Unused return value from IEco.fund() call

The fund function returns an intentHash value that is not captured or used. While this doesn't affect functionality, capturing the return value would enable better traceability and could be useful for debugging or future enhancements.

Consider capturing the return value:

        // Fund the intent (publish is optional for solver discovery)
-       IEco(_ecoData.portal).fund{ value: nativeValue }(
+       bytes32 intentHash = IEco(_ecoData.portal).fund{ value: nativeValue }(
            uint64(_bridgeData.destinationChainId),
            routeHash,
            reward,
            _ecoData.allowPartial
        );
test/solidity/Facets/EcoFacet.t.sol (2)

195-215: Test doesn't verify that custom prover is actually used

The test sets a custom prover but doesn't verify that it's actually used in the fund call. The test only checks event emission.

Add verification that the custom prover was used:

 function test_CanBridgeNativeTokensWithCustomProver() public {
     EcoFacet.EcoData memory ecoData = getDefaultEcoData();
     ecoData.prover = address(0x999);
     vm.label(ecoData.prover, "CustomProver");

     // Set up for native token bridging
     bridgeData.sendingAssetId = address(0);
     bridgeData.minAmount = 1 ether;

     vm.expectEmit(true, true, true, true, _facetTestContractAddress);
     emit LiFiTransferStarted(bridgeData);
+
+    // Expect the mock portal to receive the fund call with the custom prover in reward
+    vm.expectEmit(true, true, true, true, address(mockPortal));
+    emit MockPortal.IntentFunded(
+        uint64(bridgeData.destinationChainId),
+        keccak256(abi.encode(/* expected route */)),
+        IEco.Reward({
+            deadline: ecoData.rewardDeadline,
+            creator: USER_SENDER,
+            prover: address(0x999), // Custom prover
+            nativeAmount: 0,
+            tokens: new IEco.TokenAmount[](0)
+        }),
+        ecoData.allowPartial,
+        bridgeData.minAmount
+    );

     vm.startPrank(USER_SENDER);

     ecoFacet.startBridgeTokensViaEco{ value: bridgeData.minAmount }(
         bridgeData,
         ecoData
     );

     vm.stopPrank();
 }

312-333: Test name doesn't accurately reflect what's being tested

The test is named test_UsesDefaultProverWhenNotProvided but it only verifies that the DEFAULT_PROVER getter returns the expected value, not that it's actually used in the fund call.

Either rename the test to reflect what it actually tests or add verification that the default prover is used:

-function test_UsesDefaultProverWhenNotProvided() public {
+function test_DefaultProverGetterReturnsCorrectValue() public {
     EcoFacet.EcoData memory ecoData = getDefaultEcoData();
     ecoData.prover = address(0);

     // Set up for native token bridging
     bridgeData.sendingAssetId = address(0);
     bridgeData.minAmount = 1 ether;

     vm.expectEmit(true, true, true, true, _facetTestContractAddress);
     emit LiFiTransferStarted(bridgeData);

     vm.startPrank(USER_SENDER);

     ecoFacet.startBridgeTokensViaEco{ value: bridgeData.minAmount }(
         bridgeData,
         ecoData
     );

     vm.stopPrank();

     assertEq(ecoFacet.DEFAULT_PROVER(), defaultProver);
 }

Or add proper verification:

 function test_UsesDefaultProverWhenNotProvided() public {
     EcoFacet.EcoData memory ecoData = getDefaultEcoData();
     ecoData.prover = address(0);

     // Set up for native token bridging
     bridgeData.sendingAssetId = address(0);
     bridgeData.minAmount = 1 ether;

     vm.expectEmit(true, true, true, true, _facetTestContractAddress);
     emit LiFiTransferStarted(bridgeData);
+
+    // Verify that DEFAULT_PROVER is used in the fund call
+    vm.expectEmit(true, true, true, true, address(mockPortal));
+    emit MockPortal.IntentFunded(
+        uint64(bridgeData.destinationChainId),
+        keccak256(abi.encode(/* expected route */)),
+        IEco.Reward({
+            deadline: ecoData.rewardDeadline,
+            creator: USER_SENDER,
+            prover: defaultProver, // Should use DEFAULT_PROVER
+            nativeAmount: 0,
+            tokens: new IEco.TokenAmount[](0)
+        }),
+        ecoData.allowPartial,
+        bridgeData.minAmount
+    );

     vm.startPrank(USER_SENDER);

     ecoFacet.startBridgeTokensViaEco{ value: bridgeData.minAmount }(
         bridgeData,
         ecoData
     );

     vm.stopPrank();

     assertEq(ecoFacet.DEFAULT_PROVER(), defaultProver);
 }
📜 Review details

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

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a058afc and ba1cb12.

📒 Files selected for processing (3)
  • src/Facets/EcoFacet.sol (1 hunks)
  • src/Interfaces/IEco.sol (1 hunks)
  • test/solidity/Facets/EcoFacet.t.sol (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
{src/**/*.sol,test/solidity/**/*.sol,script/**/*.sol}

📄 CodeRabbit Inference Engine (conventions.md)

All our own Solidity files must use the LGPL-3.0 license identifier. This applies to all contracts in src/, all test files in test/solidity/, and all deployment and task scripts in script/.

Files:

  • src/Interfaces/IEco.sol
  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
**/*.sol

📄 CodeRabbit Inference Engine (conventions.md)

**/*.sol: Use custom error types rather than generic revert() statements.
Do not define interfaces in the same file as their implementation.
Every contract MUST have the following NatSpec tags in this order: @title, @author, @notice, @Custom:version.
The @author tag MUST always be "LI.FI (https://li.fi)" in contract NatSpec.
The @Custom:version MUST follow semantic versioning (X.Y.Z format) in contract NatSpec.
Every public/external function must have NatSpec comments describing the function, parameters, and return values.
All Solidity files must follow the rules defined in .solhint.json.
All Solidity files must use the EVM and Solidity version defined in foundry.toml unless networks require lower versions.

Files:

  • src/Interfaces/IEco.sol
  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
src/Interfaces/*.sol

📄 CodeRabbit Inference Engine (conventions.md)

src/Interfaces/*.sol: All interfaces must start with I prefix (e.g., ILiFi, IStargate).
All interfaces must be placed in separate files in the src/Interfaces directory.
Every interface MUST have the following NatSpec tags in this order: @title, @notice, @author, @Custom:version.

Files:

  • src/Interfaces/IEco.sol
src/Interfaces/I*.sol

📄 CodeRabbit Inference Engine (conventions.md)

All interfaces must be placed in separate files in the src/Interfaces directory and start with I.

Files:

  • src/Interfaces/IEco.sol
src/Facets/*Facet.sol

📄 CodeRabbit Inference Engine (conventions.md)

Facet contracts must reside in src/Facets/ and names must include "Facet".

Files:

  • src/Facets/EcoFacet.sol
test/solidity/**/*.t.sol

📄 CodeRabbit Inference Engine (conventions.md)

test/solidity/**/*.t.sol: Test files must have a .t.sol extension.
All tests that verify a successful execution must be prefixed with: test_.
All tests that verify a failure case must be prefixed with: testRevert_.
For base or inherited tests, prefix with testBase_.
Every test contract must include a setUp() function.
Any contract inheriting from TestBase.sol must call initTestBase() in setUp().
Use assertEq() for checking equality of values in tests.
Use vm.expectRevert() to verify specific revert reasons in failure test cases.
Use vm.expectEmit(true, true, true, true, <contractAddress>) for event testing.
All Solidity test files must be organized mirroring the src/ structure.
All Solidity test files must use Foundry.

Files:

  • test/solidity/Facets/EcoFacet.t.sol
🧠 Learnings (12)
📚 Learning: 2025-07-16T01:04:55.857Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1275
File: src/Facets/AllBridgeFacet.sol:186-188
Timestamp: 2025-07-16T01:04:55.857Z
Learning: In LiFi facet contracts, when public entry point functions have `nonReentrant` modifier protection, internal functions like `_startBridge` that they call benefit from this reentrancy protection, making event emission order after external calls acceptable from a security perspective.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-07-16T01:03:08.106Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1275
File: src/Facets/AllBridgeFacet.sol:164-164
Timestamp: 2025-07-16T01:03:08.106Z
Learning: In src/Facets/AllBridgeFacet.sol, the team has decided that explicit validation for address downcasting from `_bridgeData.sendingAssetId` to `bytes32(uint256(uint160(_bridgeData.sendingAssetId)))` is not required, accepting the potential risk of silent overflow from unsafe downcasting.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-07-11T09:43:22.393Z
Learnt from: mirooon
PR: lifinance/contracts#1193
File: test/solidity/Facets/AllowListMigratorFacet.t.sol:39-52
Timestamp: 2025-07-11T09:43:22.393Z
Learning: For fork-based tests like AllowListMigratorFacet.t.sol that work with existing deployed contracts (mainnet diamond), initTestBase() is intentionally omitted since the standard test initialization is not needed.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-01-22T12:36:12.699Z
Learnt from: mirooon
PR: lifinance/contracts#945
File: test/solidity/Facets/GlacisFacet.t.sol:214-262
Timestamp: 2025-01-22T12:36:12.699Z
Learning: The GlacisFacet test suite inherits from TestBaseFacet which already covers various failure scenarios including invalid receiver address, invalid amounts, same chain bridging, and insufficient funds, making additional failure scenario tests redundant.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-22T03:16:28.754Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: test/solidity/Facets/GasZipFacet.t.sol:212-213
Timestamp: 2024-10-22T03:16:28.754Z
Learning: In the `GasZipFacetTest`, for the test case `testBase_Revert_SwapAndBridgeWithInvalidSwapData()`, a generic revert is expected, so `vm.expectRevert();` without specifying the expected error is appropriate.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-10T03:26:23.793Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: test/solidity/Helpers/WithdrawablePeriphery.t.sol:79-80
Timestamp: 2024-10-10T03:26:23.793Z
Learning: In Solidity tests, it's acceptable to use `UnAuthorized.selector` in `vm.expectRevert()`; avoid suggesting changing it to string messages.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : Use `vm.expectRevert()` to verify specific revert reasons in failure test cases.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-22T03:24:24.705Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: test/solidity/Facets/GasZipFacet.t.sol:337-339
Timestamp: 2024-10-22T03:24:24.705Z
Learning: In `GasZipFacet` tests, when expecting a failure due to insufficient balance for sending value, the test should expect a generic revert without specifying a specific error.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : All tests that verify a failure case must be prefixed with: `testRevert_`.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : Use `vm.expectEmit(true, true, true, true, <contractAddress>)` for event testing.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : All tests that verify a successful execution must be prefixed with: `test_`.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-01-28T11:29:09.566Z
Learnt from: mirooon
PR: lifinance/contracts#945
File: test/solidity/Facets/GlacisFacet.t.sol:0-0
Timestamp: 2025-01-28T11:29:09.566Z
Learning: Empty test methods with explanatory comments are acceptable in test classes when the feature being tested (e.g., native token bridging) is not supported by the implementation.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
🪛 GitHub Check: Olympix Integrated Security
src/Facets/EcoFacet.sol

[failure] 130-130:
The contract is vulnerable to signature replay attacks, potentially allowing malicious actors to reuse valid signatures. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/signature-replay-attacks


[warning] 190-190:
Calling a function without checking the return value may lead to silent failures. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/unused-return-function-call

🔇 Additional comments (3)
src/Interfaces/IEco.sol (1)

1-117: LGTM!

The interface is well-structured with comprehensive NatSpec documentation, properly defined structs, and clear function signatures that align with the cross-chain intent system architecture.

src/Facets/EcoFacet.sol (1)

151-151: No replay vulnerability — routeHash is the route component; intent uniqueness & replay protection are enforced elsewhere

Short: EcoFacet deliberately computes routeHash = keccak256(abi.encode(route)) as the route component and passes (destination, routeHash, reward) to the portal. The intent identity and replay protection are provided by the portal/prover layer (intentHash is built from destination + routeHash + reward; reward.creator is set to msg.sender in EcoFacet), and the protocol tracks proven/fulfilled intents to prevent replays.

Relevant locations:

  • src/Facets/EcoFacet.sol — computes routeHash (bytes32 routeHash = keccak256(abi.encode(route))); builds Reward with creator = msg.sender; calls IEco(...).fund(...)
  • src/Interfaces/IEco.sol — Route/Reward/Intent structs and fund/publish signatures (intent includes destination, routeHash, reward)
  • test/solidity/Facets/EcoFacet.t.sol — MockPortal.publish / fund compute intentHash using destination + keccak(route) + keccak(reward) and emit IntentFunded (demonstrates expected behaviour)

Conclusion: no code change required in this facet — replay protection is provided by the Eco contracts and the reward/destination combination used when funding intents.

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

9-9: Fix incorrect import statement

The import statement incorrectly imports InvalidProver and InvalidDeadline from GenericErrors.sol, but these errors are defined in EcoFacet.sol according to the implementation.

Apply this diff to fix the import:

-import { InvalidContract, InvalidProver, InvalidDeadline } from "../../../src/Errors/GenericErrors.sol";
+import { InvalidContract } from "../../../src/Errors/GenericErrors.sol";
⛔ Skipped due to learnings
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to src/Errors/GenericErrors.sol : All custom errors must be defined in `src/Errors/GenericErrors.sol`.
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to src/Errors/GenericErrors.sol : All custom errors should be defined in `src/Errors/GenericErrors.sol` and not include error messages.
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to src/Errors/GenericErrors.sol : Errors should not include error messages (for gas optimization).
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to src/Errors/GenericErrors.sol : Error names should be descriptive and follow PascalCase.

@ezynda3 ezynda3 added the WIP Work in progress label Aug 18, 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: 0

♻️ Duplicate comments (2)
src/Facets/EcoFacet.sol (2)

130-174: Signature replay vulnerability flagged by static analysis needs investigation

The static analysis tool has flagged a potential signature replay attack vulnerability at line 130. However, upon reviewing the code, this appears to be a false positive since:

  1. The function doesn't handle signatures directly
  2. The route hash is computed from the entire route struct including salt and deadline
  3. The salt parameter in EcoData provides replay protection
  4. The deadline parameters provide time-bound protection

Let me verify the signature handling in the broader codebase:

#!/bin/bash
# Description: Search for signature-related functionality in the Eco integration
# to understand if there are any actual signature replay vulnerabilities

echo "=== Searching for signature handling in Eco-related files ==="
rg -n -A5 -B5 'signature|ecrecover|recover' --type=sol src/Interfaces/IEco.sol src/Facets/EcoFacet.sol || echo "No signature handling found"

echo -e "\n=== Checking for nonce or replay protection mechanisms ==="
rg -n -A3 -B3 'nonce|salt|replay|deadline' --type=sol src/Interfaces/IEco.sol src/Facets/EcoFacet.sol

echo -e "\n=== Examining the route hash computation ==="
rg -n -A10 'keccak256.*encode' --type=sol src/Facets/EcoFacet.sol

196-201: Unchecked return value from external call

The call to IEco(_ecoData.portal).fund() doesn't check the return value, which could lead to silent failures as flagged by static analysis.

Based on the retrieved learnings, when public entry point functions have nonReentrant modifier protection, the event emission order after external calls is acceptable from a security perspective. However, we should still consider checking the return value for better error handling:

-        // Fund the intent (publish is optional for solver discovery)
-        IEco(_ecoData.portal).fund{ value: nativeValue }(
-            uint64(_bridgeData.destinationChainId),
-            routeHash,
-            reward,
-            _ecoData.allowPartial
-        );
+        // Fund the intent (publish is optional for solver discovery)
+        bytes32 intentId = IEco(_ecoData.portal).fund{ value: nativeValue }(
+            uint64(_bridgeData.destinationChainId),
+            routeHash,
+            reward,
+            _ecoData.allowPartial
+        );
+        
+        // Optional: emit intentId for tracking purposes
+        // emit IntentCreated(intentId, _bridgeData.transactionId);
🧹 Nitpick comments (1)
test/solidity/Facets/EcoFacet.t.sol (1)

252-255: Consider adding swap test with mock setup

While the swap test is appropriately commented out due to Optimism DEX complexity, consider adding a simplified version using mocks to test the swap functionality without requiring complex DEX setup.

You could add a simple mock-based swap test:

function test_CanSwapAndBridgeWithMockDex() public {
    // Create mock swap data that will succeed
    LibSwap.SwapData[] memory mockSwapData = new LibSwap.SwapData[](1);
    mockSwapData[0] = LibSwap.SwapData({
        callTo: address(this), // Use test contract as mock DEX
        approveTo: address(this),
        sendingAssetId: ADDRESS_USDC,
        receivingAssetId: ADDRESS_USDC, // Same asset for simplicity
        fromAmount: 100 * 10**6,
        callData: "", // Empty call data
        requiresDeposit: true
    });

    // Setup test with mock data
    EcoFacet.EcoData memory ecoData = getDefaultEcoData();
    // ... rest of test implementation
}
📜 Review details

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

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ba1cb12 and 0e0aa63.

📒 Files selected for processing (3)
  • src/Facets/EcoFacet.sol (1 hunks)
  • src/Interfaces/IEco.sol (1 hunks)
  • test/solidity/Facets/EcoFacet.t.sol (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Interfaces/IEco.sol
🧰 Additional context used
📓 Path-based instructions (4)
{src/**/*.sol,test/solidity/**/*.sol,script/**/*.sol}

📄 CodeRabbit Inference Engine (conventions.md)

All our own Solidity files must use the LGPL-3.0 license identifier. This applies to all contracts in src/, all test files in test/solidity/, and all deployment and task scripts in script/.

Files:

  • test/solidity/Facets/EcoFacet.t.sol
  • src/Facets/EcoFacet.sol
**/*.sol

📄 CodeRabbit Inference Engine (conventions.md)

**/*.sol: Use custom error types rather than generic revert() statements.
Do not define interfaces in the same file as their implementation.
Every contract MUST have the following NatSpec tags in this order: @title, @author, @notice, @Custom:version.
The @author tag MUST always be "LI.FI (https://li.fi)" in contract NatSpec.
The @Custom:version MUST follow semantic versioning (X.Y.Z format) in contract NatSpec.
Every public/external function must have NatSpec comments describing the function, parameters, and return values.
All Solidity files must follow the rules defined in .solhint.json.
All Solidity files must use the EVM and Solidity version defined in foundry.toml unless networks require lower versions.

Files:

  • test/solidity/Facets/EcoFacet.t.sol
  • src/Facets/EcoFacet.sol
test/solidity/**/*.t.sol

📄 CodeRabbit Inference Engine (conventions.md)

test/solidity/**/*.t.sol: Test files must have a .t.sol extension.
All tests that verify a successful execution must be prefixed with: test_.
All tests that verify a failure case must be prefixed with: testRevert_.
For base or inherited tests, prefix with testBase_.
Every test contract must include a setUp() function.
Any contract inheriting from TestBase.sol must call initTestBase() in setUp().
Use assertEq() for checking equality of values in tests.
Use vm.expectRevert() to verify specific revert reasons in failure test cases.
Use vm.expectEmit(true, true, true, true, <contractAddress>) for event testing.
All Solidity test files must be organized mirroring the src/ structure.
All Solidity test files must use Foundry.

Files:

  • test/solidity/Facets/EcoFacet.t.sol
src/Facets/*Facet.sol

📄 CodeRabbit Inference Engine (conventions.md)

Facet contracts must reside in src/Facets/ and names must include "Facet".

Files:

  • src/Facets/EcoFacet.sol
🧠 Learnings (13)
📓 Common learnings
Learnt from: mirooon
PR: lifinance/contracts#945
File: src/Facets/GlacisFacet.sol:1-3
Timestamp: 2025-01-28T11:28:16.225Z
Learning: The GlacisFacet contract audit will be conducted and added to the audit log in later stages of development. This is acceptable during the initial development phase.
📚 Learning: 2024-10-22T03:16:28.754Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: test/solidity/Facets/GasZipFacet.t.sol:212-213
Timestamp: 2024-10-22T03:16:28.754Z
Learning: In the `GasZipFacetTest`, for the test case `testBase_Revert_SwapAndBridgeWithInvalidSwapData()`, a generic revert is expected, so `vm.expectRevert();` without specifying the expected error is appropriate.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-10T03:26:23.793Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: test/solidity/Helpers/WithdrawablePeriphery.t.sol:79-80
Timestamp: 2024-10-10T03:26:23.793Z
Learning: In Solidity tests, it's acceptable to use `UnAuthorized.selector` in `vm.expectRevert()`; avoid suggesting changing it to string messages.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-22T03:24:24.705Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: test/solidity/Facets/GasZipFacet.t.sol:337-339
Timestamp: 2024-10-22T03:24:24.705Z
Learning: In `GasZipFacet` tests, when expecting a failure due to insufficient balance for sending value, the test should expect a generic revert without specifying a specific error.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : Use `vm.expectRevert()` to verify specific revert reasons in failure test cases.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : All tests that verify a failure case must be prefixed with: `testRevert_`.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : Use `vm.expectEmit(true, true, true, true, <contractAddress>)` for event testing.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : All tests that verify a successful execution must be prefixed with: `test_`.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-11T09:43:22.393Z
Learnt from: mirooon
PR: lifinance/contracts#1193
File: test/solidity/Facets/AllowListMigratorFacet.t.sol:39-52
Timestamp: 2025-07-11T09:43:22.393Z
Learning: For fork-based tests like AllowListMigratorFacet.t.sol that work with existing deployed contracts (mainnet diamond), initTestBase() is intentionally omitted since the standard test initialization is not needed.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-01-22T12:36:12.699Z
Learnt from: mirooon
PR: lifinance/contracts#945
File: test/solidity/Facets/GlacisFacet.t.sol:214-262
Timestamp: 2025-01-22T12:36:12.699Z
Learning: The GlacisFacet test suite inherits from TestBaseFacet which already covers various failure scenarios including invalid receiver address, invalid amounts, same chain bridging, and insufficient funds, making additional failure scenario tests redundant.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-01-28T11:29:09.566Z
Learnt from: mirooon
PR: lifinance/contracts#945
File: test/solidity/Facets/GlacisFacet.t.sol:0-0
Timestamp: 2025-01-28T11:29:09.566Z
Learning: Empty test methods with explanatory comments are acceptable in test classes when the feature being tested (e.g., native token bridging) is not supported by the implementation.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-16T01:04:55.857Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1275
File: src/Facets/AllBridgeFacet.sol:186-188
Timestamp: 2025-07-16T01:04:55.857Z
Learning: In LiFi facet contracts, when public entry point functions have `nonReentrant` modifier protection, internal functions like `_startBridge` that they call benefit from this reentrancy protection, making event emission order after external calls acceptable from a security perspective.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-07-16T01:03:08.106Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1275
File: src/Facets/AllBridgeFacet.sol:164-164
Timestamp: 2025-07-16T01:03:08.106Z
Learning: In src/Facets/AllBridgeFacet.sol, the team has decided that explicit validation for address downcasting from `_bridgeData.sendingAssetId` to `bytes32(uint256(uint160(_bridgeData.sendingAssetId)))` is not required, accepting the potential risk of silent overflow from unsafe downcasting.

Applied to files:

  • src/Facets/EcoFacet.sol
🪛 GitHub Check: Olympix Integrated Security
src/Facets/EcoFacet.sol

[failure] 130-130:
The contract is vulnerable to signature replay attacks, potentially allowing malicious actors to reuse valid signatures. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/signature-replay-attacks


[warning] 196-196:
Calling a function without checking the return value may lead to silent failures. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/unused-return-function-call

🔇 Additional comments (24)
src/Facets/EcoFacet.sol (10)

1-17: LGTM - Proper license and imports

The contract follows the required LGPL-3.0 license and has proper imports for the EcoFacet functionality.


18-22: LGTM - Contract structure follows LiFi patterns

The contract properly inherits from required base contracts and follows the established LiFi facet architecture with immutable default prover setup.


35-44: LGTM - Well-documented EcoData struct

The struct is properly documented with comprehensive NatSpec comments explaining each parameter's purpose and usage.


48-49: Custom errors properly defined

The custom errors InvalidProver and InvalidDeadline follow the coding guidelines for using custom error types instead of generic reverts.


53-62: LGTM - Comprehensive validation in modifier

The validateEcoData modifier properly validates both the portal address and deadline constraints with appropriate custom errors.


68-71: LGTM - Constructor validation

The constructor properly validates the default prover address and uses the custom InvalidProver error as required.


78-96: LGTM - Entry point follows LiFi patterns

The startBridgeTokensViaEco function properly implements the LiFi facet pattern with appropriate modifiers for reentrancy protection, validation, and asset handling.


102-123: LGTM - Swap and bridge entry point

The swapAndStartBridgeTokensViaEco function correctly implements the swap-then-bridge pattern with proper validation modifiers and follows established LiFi conventions.


175-183: LGTM - Proper token approval handling

The code correctly handles token approvals only for non-native assets and uses the established LibAsset.maxApproveERC20 pattern.


192-194: LGTM - Event emission follows established pattern

The LiFiTransferStarted event is properly emitted before the external call, following the established LiFi pattern and retrieved learnings about event emission order in protected functions.

test/solidity/Facets/EcoFacet.t.sol (14)

1-11: LGTM - Proper test file setup

The test file follows the required conventions with proper license, imports, and error imports from the correct locations.


13-23: LGTM - Test wrapper contract

The TestEcoFacet wrapper properly extends the main facet and exposes necessary functions for testing setup.


35-96: LGTM - Comprehensive test setup

The setUp function properly configures the test environment with:

  • Fork configuration for Optimism
  • Facet deployment and diamond integration
  • DEX and function selector approvals
  • Proper labeling for debugging

99-126: LGTM - Override functions for Optimism fork

The override functions properly handle the complexity of swap data setup on Optimism fork, providing reasonable alternatives for testing.

Also applies to: 130-146


148-168: LGTM - Helper function for test data

The getDefaultEcoData helper function creates properly structured test data with reasonable defaults.


170-197: LGTM - Override hooks follow base class pattern

The override functions properly implement the required interface for base class test execution with native and non-native token handling.


200-206: LGTM - Appropriate test skipping

The overridden swap tests are appropriately skipped with clear comments explaining the reason (Optimism DEX setup complexity).


210-230: LGTM - Native token bridging test

The test properly verifies native token bridging with a custom prover and follows the established testing patterns with proper event emission verification.


232-250: LGTM - Default prover test

The test correctly verifies bridging with the default prover when no custom prover is provided, including proper token setup and approval.


257-271: LGTM - Zero portal validation test

The test properly verifies the InvalidContract revert when portal address is zero, following the testRevert_ naming convention.


273-287: LGTM - Deadline validation tests

Both deadline validation tests properly verify the InvalidDeadline error for expired route and reward deadlines, following the correct naming convention.

Also applies to: 289-303


305-309: LGTM - Constructor validation test

The test properly verifies that the constructor reverts with InvalidProver when given a zero address for the default prover.


311-332: LGTM - Default prover usage verification

The test correctly verifies that the default prover is used when none is provided and includes an assertion to confirm the DEFAULT_PROVER value.


334-359: LGTM - Calls data test

The test properly verifies that the facet can handle EcoData with calls array, demonstrating the full functionality of the bridge system.

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

♻️ Duplicate comments (2)
test/solidity/Facets/EcoFacet.t.sol (2)

214-234: Strengthen: assert the custom prover was actually used

As in prior reviews, assert behavioral outcomes, not just event emission. This is easiest with a mock portal that records the prover used.

Option A (preferred): Use a minimal mock IEco portal in this test file that records prover on fund() and expose a getter/event. Then add:

         ecoFacet.startBridgeTokensViaEco{ value: bridgeData.minAmount }(
             bridgeData,
             ecoData
         );
 
         vm.stopPrank();
+
+        // Assert the provided custom prover was used
+        assertEq(mockPortal.lastProver(), ecoData.prover, "should use provided prover");

Option B: If you must stick to an Optimism fork, add an event in EcoFacet emitted with the effective prover and assert it here via vm.expectEmit.


315-336: Strengthen: assert default prover path

Mirror the custom-prover assertion to verify fallback to DEFAULT_PROVER at execution time (not only the getter).

         ecoFacet.startBridgeTokensViaEco{ value: bridgeData.minAmount }(
             bridgeData,
             ecoData
         );
 
         vm.stopPrank();
 
-        assertEq(ecoFacet.DEFAULT_PROVER(), OPTIMISM_DEFAULT_PROVER);
+        assertEq(ecoFacet.DEFAULT_PROVER(), OPTIMISM_DEFAULT_PROVER);
+        // If using a mock portal:
+        // assertEq(mockPortal.lastProver(), OPTIMISM_DEFAULT_PROVER, "should use default prover");
🧹 Nitpick comments (11)
docs/EcoFacet.md (2)

60-66: Fix parameter type and clarify wording for swap input

  • The function takes an array of swaps, not a single swap.
  • Tighten grammar.
-Some methods accept a `SwapData _swapData` parameter.
+Some methods accept a `LibSwap.SwapData[] calldata _swapData` parameter.
@@
-Swapping is performed by a swap specific library that expects an array of calldata to can be run on various DEXs (i.e. Uniswap) to make one or multiple swaps before performing another action.
+Swapping is performed by a swap-specific library that expects an array of calldata that can be executed on various DEXs (e.g., Uniswap) to make one or multiple swaps before performing another action.

28-33: Document deadline semantics to match revert behavior

Tests expect InvalidDeadline when deadline <= block.timestamp. Suggest clarifying this in the docs to help integrators avoid off-by-one issues.

 /// @param routeDeadline The deadline for route execution (timestamp)
-/// @param rewardDeadline The deadline for claiming rewards (timestamp)
+/// @param rewardDeadline The deadline for claiming rewards (timestamp)
+/// Note: Both deadlines must be strictly greater than the current block timestamp
+/// at the time of execution (deadline > block.timestamp).
@@
-This parameter is strictly for analytics purposes. It's used to emit events that we can later track and index in our subgraphs and provide data on how our contracts are being used. `BridgeData` and the events we can emit can be found [here](../src/Interfaces/ILiFi.sol).
+This parameter is strictly for analytics purposes. It's used to emit events that we can later track and index in our subgraphs and provide data on how our contracts are being used. `BridgeData` and the events we can emit can be found [here](../src/Interfaces/ILiFi.sol). Ensure your deadlines are set safely in the future to avoid reverts.

Also applies to: 66-71

src/Interfaces/IEco.sol (2)

11-14: Add per-field NatSpec on TokenAmount for consistency

Minor doc polish to match the level of detail given in Call.

     struct TokenAmount {
-        address token;
-        uint256 amount;
+        /// @notice ERC20 token address (use address(0) for native, if applicable)
+        address token;
+        /// @notice Amount of the token
+        uint256 amount;
     }

33-39: Add per-field NatSpec on Reward fields

Improves generated docs and consumer clarity.

     struct Reward {
-        uint64 deadline;
-        address creator;
-        address prover;
-        uint256 nativeAmount;
-        TokenAmount[] tokens;
+        /// @notice Reward claim deadline on the destination chain
+        uint64 deadline;
+        /// @notice Address that created the intent (credited as creator)
+        address creator;
+        /// @notice Address authorized to prove the route
+        address prover;
+        /// @notice Amount of native token escrowed as incentive
+        uint256 nativeAmount;
+        /// @notice Additional ERC20 token incentives
+        TokenAmount[] tokens;
     }
test/solidity/Facets/EcoFacet.t.sol (7)

5-11: Import EcoFacet errors instead of re-declaring them later

Avoids drift if the contract error names change and keeps selectors authoritative.

 import { EcoFacet } from "../../../src/Facets/EcoFacet.sol";
 import { IEco } from "../../../src/Interfaces/IEco.sol";
 import { InvalidContract } from "../../../src/Errors/GenericErrors.sol";
+import { InvalidProver, InvalidDeadline } from "../../../src/Facets/EcoFacet.sol";

12-15: Remove locally re-declared errors (use imported ones)

Locally shadowing custom errors invites selector drift and maintenance issues.

-// Errors from EcoFacet
-error InvalidProver();
-error InvalidDeadline();
+// Errors from EcoFacet are imported above

31-35: Replace hardcoded DEFAULT_PROVER with config-driven value

The TODO indicates this should be synced with deployment config. Load from config/eco.json to ensure tests track deploys.

-    address internal constant OPTIMISM_DEFAULT_PROVER =
-        0x1234567890123456789012345678901234567890; // TODO: Replace with actual prover address from Eco Protocol
+    address internal OPTIMISM_DEFAULT_PROVER;

Then in setUp (see next comment) parse config. Confirm JSON shape (e.g., .optimism.defaultProver) before applying.


39-48: Initialize DEFAULT_PROVER from config/eco.json

Keeps tests aligned with deployment parameters.

     function setUp() public {
         // Setup Optimism fork at block 139757044
         customBlockNumberForForking = 139757044;
         customRpcUrlForForking = "ETH_NODE_URI_OPTIMISM";
         initTestBase();
 
-        // Deploy contracts with actual prover address
-        ecoFacet = new TestEcoFacet(OPTIMISM_DEFAULT_PROVER);
+        // Load default prover from config
+        // Requires: import "forge-std/StdJson.sol"; and `using stdJson for string;` at top
+        string memory ecoCfg = vm.readFile("config/eco.json");
+        OPTIMISM_DEFAULT_PROVER = vm.parseJsonAddress(ecoCfg, ".optimism.defaultProver");
+
+        // Deploy contracts with actual prover address
+        ecoFacet = new TestEcoFacet(OPTIMISM_DEFAULT_PROVER);
         portal = IEco(OPTIMISM_PORTAL);

If stdJson is not already used in this test suite, add:

import "forge-std/StdJson.sol";
using stdJson for string;

Please verify the JSON path matches config/eco.json.


36-38: Remove unused state variable portal

portal is assigned but never read in this file.

-    IEco internal portal;

64-70: Allowlist clarity: avoid labeling portal as a DEX

Nit: addDex(OPTIMISM_PORTAL) conceptually allows an external contract, not a DEX. Consider renaming helper in TestEcoFacet to a more neutral name (e.g., addAllowedContract) for readability, or add a comment clarifying its purpose.


133-150: Stubbed swap data with empty calldata can mask issues

This keeps array access safe, but it silently ensures no swap occurs. Consider gating tests that depend on swaps behind feature flags or using a dedicated mock that always succeeds to keep swap-and-bridge flows covered.

📜 Review details

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

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0e0aa63 and 9f6d871.

📒 Files selected for processing (3)
  • docs/EcoFacet.md (1 hunks)
  • src/Interfaces/IEco.sol (1 hunks)
  • test/solidity/Facets/EcoFacet.t.sol (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
{src/**/*.sol,test/solidity/**/*.sol,script/**/*.sol}

📄 CodeRabbit inference engine (conventions.md)

All our own Solidity files must use the LGPL-3.0 license identifier. This applies to all contracts in src/, all test files in test/solidity/, and all deployment and task scripts in script/.

Files:

  • src/Interfaces/IEco.sol
  • test/solidity/Facets/EcoFacet.t.sol
**/*.sol

📄 CodeRabbit inference engine (conventions.md)

**/*.sol: Use custom error types rather than generic revert() statements.
Do not define interfaces in the same file as their implementation.
Every contract MUST have the following NatSpec tags in this order: @title, @author, @notice, @Custom:version.
The @author tag MUST always be "LI.FI (https://li.fi)" in contract NatSpec.
The @Custom:version MUST follow semantic versioning (X.Y.Z format) in contract NatSpec.
Every public/external function must have NatSpec comments describing the function, parameters, and return values.
All Solidity files must follow the rules defined in .solhint.json.
All Solidity files must use the EVM and Solidity version defined in foundry.toml unless networks require lower versions.

Files:

  • src/Interfaces/IEco.sol
  • test/solidity/Facets/EcoFacet.t.sol
src/Interfaces/*.sol

📄 CodeRabbit inference engine (conventions.md)

src/Interfaces/*.sol: All interfaces must start with I prefix (e.g., ILiFi, IStargate).
All interfaces must be placed in separate files in the src/Interfaces directory.
Every interface MUST have the following NatSpec tags in this order: @title, @notice, @author, @Custom:version.

Files:

  • src/Interfaces/IEco.sol
src/Interfaces/I*.sol

📄 CodeRabbit inference engine (conventions.md)

All interfaces must be placed in separate files in the src/Interfaces directory and start with I.

Files:

  • src/Interfaces/IEco.sol
test/solidity/**/*.t.sol

📄 CodeRabbit inference engine (conventions.md)

test/solidity/**/*.t.sol: Test files must have a .t.sol extension.
All tests that verify a successful execution must be prefixed with: test_.
All tests that verify a failure case must be prefixed with: testRevert_.
For base or inherited tests, prefix with testBase_.
Every test contract must include a setUp() function.
Any contract inheriting from TestBase.sol must call initTestBase() in setUp().
Use assertEq() for checking equality of values in tests.
Use vm.expectRevert() to verify specific revert reasons in failure test cases.
Use vm.expectEmit(true, true, true, true, <contractAddress>) for event testing.
All Solidity test files must be organized mirroring the src/ structure.
All Solidity test files must use Foundry.

Files:

  • test/solidity/Facets/EcoFacet.t.sol
🧠 Learnings (12)
📓 Common learnings
Learnt from: mirooon
PR: lifinance/contracts#945
File: src/Facets/GlacisFacet.sol:1-3
Timestamp: 2025-01-28T11:28:16.225Z
Learning: The GlacisFacet contract audit will be conducted and added to the audit log in later stages of development. This is acceptable during the initial development phase.
📚 Learning: 2024-10-31T09:09:38.568Z
Learnt from: ezynda3
PR: lifinance/contracts#843
File: src/Facets/RelayFacet.sol:165-170
Timestamp: 2024-10-31T09:09:38.568Z
Learning: In the `RelayFacet` contract (`src/Facets/RelayFacet.sol`), within the `_startBridge` function, low-level `call` is intentionally used to transfer tokens so that extra bytes can be added to the calldata, as required for integrating with Relay Protocol.

Applied to files:

  • docs/EcoFacet.md
📚 Learning: 2024-10-22T03:16:28.754Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: test/solidity/Facets/GasZipFacet.t.sol:212-213
Timestamp: 2024-10-22T03:16:28.754Z
Learning: In the `GasZipFacetTest`, for the test case `testBase_Revert_SwapAndBridgeWithInvalidSwapData()`, a generic revert is expected, so `vm.expectRevert();` without specifying the expected error is appropriate.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-10T03:26:23.793Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: test/solidity/Helpers/WithdrawablePeriphery.t.sol:79-80
Timestamp: 2024-10-10T03:26:23.793Z
Learning: In Solidity tests, it's acceptable to use `UnAuthorized.selector` in `vm.expectRevert()`; avoid suggesting changing it to string messages.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-22T03:24:24.705Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: test/solidity/Facets/GasZipFacet.t.sol:337-339
Timestamp: 2024-10-22T03:24:24.705Z
Learning: In `GasZipFacet` tests, when expecting a failure due to insufficient balance for sending value, the test should expect a generic revert without specifying a specific error.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : Use `vm.expectRevert()` to verify specific revert reasons in failure test cases.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : All tests that verify a failure case must be prefixed with: `testRevert_`.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : Use `vm.expectEmit(true, true, true, true, <contractAddress>)` for event testing.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : All tests that verify a successful execution must be prefixed with: `test_`.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-11T09:43:22.393Z
Learnt from: mirooon
PR: lifinance/contracts#1193
File: test/solidity/Facets/AllowListMigratorFacet.t.sol:39-52
Timestamp: 2025-07-11T09:43:22.393Z
Learning: For fork-based tests like AllowListMigratorFacet.t.sol that work with existing deployed contracts (mainnet diamond), initTestBase() is intentionally omitted since the standard test initialization is not needed.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-01-22T12:36:12.699Z
Learnt from: mirooon
PR: lifinance/contracts#945
File: test/solidity/Facets/GlacisFacet.t.sol:214-262
Timestamp: 2025-01-22T12:36:12.699Z
Learning: The GlacisFacet test suite inherits from TestBaseFacet which already covers various failure scenarios including invalid receiver address, invalid amounts, same chain bridging, and insufficient funds, making additional failure scenario tests redundant.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-01-28T11:29:09.566Z
Learnt from: mirooon
PR: lifinance/contracts#945
File: test/solidity/Facets/GlacisFacet.t.sol:0-0
Timestamp: 2025-01-28T11:29:09.566Z
Learning: Empty test methods with explanatory comments are acceptable in test classes when the feature being tested (e.g., native token bridging) is not supported by the implementation.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
🔇 Additional comments (1)
src/Interfaces/IEco.sol (1)

1-53: Interface looks correct and policy-compliant

  • SPDX is LGPL-3.0-only (matches policy).
  • NatSpec present with required tags and order.
  • Interface is in src/Interfaces and prefixed with I.
  • Public function has complete NatSpec.

@ezynda3 ezynda3 force-pushed the LF-14918-Eco-Facet branch from 9f6d871 to 38e383f Compare August 27, 2025 03:00
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

♻️ Duplicate comments (1)
script/deploy/facets/DeployEcoFacet.s.sol (1)

20-21: Double-encoding issue resolved — good fix

Passing only creationCode relies on DeployScriptBase to append constructor args once. Matches repo pattern.

🧹 Nitpick comments (6)
script/deploy/facets/UpdateEcoFacet.s.sol (1)

7-14: Missing NatSpec on contract and run()

Add minimal NatSpec to satisfy repo rules and solhint.

-contract DeployScript is UpdateScriptBase {
+/// @title UpdateEcoFacet Script
+/// @author LI.FI (https://li.fi)
+/// @notice Updates EcoFacet on existing diamonds
+/// @custom:version 1.0.0
+contract DeployScript is UpdateScriptBase {
-    function run()
+    /// @notice Executes the EcoFacet update cut.
+    /// @return facets The facet addresses involved in the cut.
+    /// @return cutData Encoded diamond cut data.
+    function run()
         public
         returns (address[] memory facets, bytes memory cutData)
     {
         return update("EcoFacet");
     }
 }
script/deploy/facets/DeployEcoFacet.s.sol (3)

1-1: License header for deploy scripts — align with team convention

Switch to UNLICENSED to match deploy script practice.

-// SPDX-License-Identifier: LGPL-3.0-only
+// SPDX-License-Identifier: UNLICENSED

9-21: Add NatSpec and consider explicit return for clarity

Docs are required; explicit return is optional but clearer.

-contract DeployScript is DeployScriptBase {
+/// @title DeployEcoFacet Script
+/// @author LI.FI (https://li.fi)
+/// @notice Deploys EcoFacet using config/eco.json
+/// @custom:version 1.0.0
+contract DeployScript is DeployScriptBase {
@@
-    function run()
+    /// @notice Deploy EcoFacet.
+    /// @return deployed The deployed EcoFacet instance.
+    /// @return constructorArgs ABI-encoded constructor args used.
+    function run()
         public
         returns (EcoFacet deployed, bytes memory constructorArgs)
     {
         constructorArgs = getConstructorArgs();
 
         deployed = EcoFacet(deploy(type(EcoFacet).creationCode));
+        return (deployed, constructorArgs);
     }

23-33: NatSpec missing on getConstructorArgs()

Add brief docs.

-    function getConstructorArgs() internal override returns (bytes memory) {
+    /// @notice Builds constructor args from config/eco.json.
+    /// @return ABI-encoded IEcoPortal address.
+    function getConstructorArgs() internal override returns (bytes memory) {
src/Facets/EcoFacet.sol (2)

142-167: Add validation for destination portal address.

Prevent malformed intents by rejecting zero destinationPortal.

     ) private pure {
@@
         if (
             _bridgeData.receiver == NON_EVM_ADDRESS &&
             _ecoData.nonEVMReceiver.length == 0
         ) {
             revert InvalidReceiver();
         }
+        if (_ecoData.destinationPortal == address(0)) {
+            revert InvalidConfig();
+        }

253-276: Return value intentionally unused; document to appease scanners.

publishAndFund likely returns an intent id. If we’re not using it, add a short comment to clarify intent and silence “unused return” warnings.

-            intentSource.publishAndFund{
+            // Intentionally ignore returned intent id; tracking is handled off-chain/by portal
+            intentSource.publishAndFund{
                 value: _bridgeData.minAmount + _ecoData.solverReward
             }(intent, false);
@@
-            intentSource.publishAndFund{ value: _ecoData.solverReward }(
+            // Intentionally ignore returned intent id
+            intentSource.publishAndFund{ value: _ecoData.solverReward }(
                 intent,
                 false
             );
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9f6d871 and 38e383f.

📒 Files selected for processing (8)
  • config/dexs.json (12 hunks)
  • config/eco.json (1 hunks)
  • docs/EcoFacet.md (1 hunks)
  • script/deploy/facets/DeployEcoFacet.s.sol (1 hunks)
  • script/deploy/facets/UpdateEcoFacet.s.sol (1 hunks)
  • src/Facets/EcoFacet.sol (1 hunks)
  • src/Interfaces/IEcoPortal.sol (1 hunks)
  • test/solidity/Facets/EcoFacet.t.sol (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/EcoFacet.md
🧰 Additional context used
📓 Path-based instructions (7)
{src/**/*.sol,test/solidity/**/*.sol,script/**/*.sol}

📄 CodeRabbit inference engine (conventions.md)

All our own Solidity files must use the LGPL-3.0 license identifier. This applies to all contracts in src/, all test files in test/solidity/, and all deployment and task scripts in script/.

Files:

  • script/deploy/facets/DeployEcoFacet.s.sol
  • src/Interfaces/IEcoPortal.sol
  • script/deploy/facets/UpdateEcoFacet.s.sol
  • test/solidity/Facets/EcoFacet.t.sol
  • src/Facets/EcoFacet.sol
**/*.sol

📄 CodeRabbit inference engine (conventions.md)

**/*.sol: Use custom error types rather than generic revert() statements.
Do not define interfaces in the same file as their implementation.
Every contract MUST have the following NatSpec tags in this order: @title, @author, @notice, @Custom:version.
The @author tag MUST always be "LI.FI (https://li.fi)" in contract NatSpec.
The @Custom:version MUST follow semantic versioning (X.Y.Z format) in contract NatSpec.
Every public/external function must have NatSpec comments describing the function, parameters, and return values.
All Solidity files must follow the rules defined in .solhint.json.
All Solidity files must use the EVM and Solidity version defined in foundry.toml unless networks require lower versions.

Files:

  • script/deploy/facets/DeployEcoFacet.s.sol
  • src/Interfaces/IEcoPortal.sol
  • script/deploy/facets/UpdateEcoFacet.s.sol
  • test/solidity/Facets/EcoFacet.t.sol
  • src/Facets/EcoFacet.sol
{script/deploy/facets/*.sol,script/deploy/zksync/*.sol}

📄 CodeRabbit inference engine (conventions.md)

{script/deploy/facets/*.sol,script/deploy/zksync/*.sol}: Deployment scripts must reside in script/deploy/facets/ for base deployments and script/deploy/zksync/ for ZKSync-specific scripts.
Deployment scripts must inherit DeployScriptBase and use JSON config with stdJson.
Update scripts must inherit UpdateScriptBase and use update("{ContractName}").

Files:

  • script/deploy/facets/DeployEcoFacet.s.sol
  • script/deploy/facets/UpdateEcoFacet.s.sol
src/Interfaces/*.sol

📄 CodeRabbit inference engine (conventions.md)

src/Interfaces/*.sol: All interfaces must start with I prefix (e.g., ILiFi, IStargate).
All interfaces must be placed in separate files in the src/Interfaces directory.
Every interface MUST have the following NatSpec tags in this order: @title, @notice, @author, @Custom:version.

Files:

  • src/Interfaces/IEcoPortal.sol
src/Interfaces/I*.sol

📄 CodeRabbit inference engine (conventions.md)

All interfaces must be placed in separate files in the src/Interfaces directory and start with I.

Files:

  • src/Interfaces/IEcoPortal.sol
test/solidity/**/*.t.sol

📄 CodeRabbit inference engine (conventions.md)

test/solidity/**/*.t.sol: Test files must have a .t.sol extension.
All tests that verify a successful execution must be prefixed with: test_.
All tests that verify a failure case must be prefixed with: testRevert_.
For base or inherited tests, prefix with testBase_.
Every test contract must include a setUp() function.
Any contract inheriting from TestBase.sol must call initTestBase() in setUp().
Use assertEq() for checking equality of values in tests.
Use vm.expectRevert() to verify specific revert reasons in failure test cases.
Use vm.expectEmit(true, true, true, true, <contractAddress>) for event testing.
All Solidity test files must be organized mirroring the src/ structure.
All Solidity test files must use Foundry.

Files:

  • test/solidity/Facets/EcoFacet.t.sol
src/Facets/*Facet.sol

📄 CodeRabbit inference engine (conventions.md)

Facet contracts must reside in src/Facets/ and names must include "Facet".

Files:

  • src/Facets/EcoFacet.sol
🧠 Learnings (33)
📓 Common learnings
Learnt from: mirooon
PR: lifinance/contracts#945
File: src/Facets/GlacisFacet.sol:1-3
Timestamp: 2025-01-28T11:28:16.225Z
Learning: The GlacisFacet contract audit will be conducted and added to the audit log in later stages of development. This is acceptable during the initial development phase.
📚 Learning: 2025-08-26T15:19:07.775Z
Learnt from: mirooon
PR: lifinance/contracts#1328
File: script/deploy/facets/LDA/DeployAlgebraFacet.s.sol:4-4
Timestamp: 2025-08-26T15:19:07.775Z
Learning: DeployScriptBase.sol is located at script/deploy/facets/utils/DeployScriptBase.sol, not script/deploy/utils/DeployScriptBase.sol. Import paths from script/deploy/facets/LDA/ should use "../utils/DeployScriptBase.sol" to reference it correctly.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
  • script/deploy/facets/UpdateEcoFacet.s.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to {script/deploy/facets/*.sol,script/deploy/zksync/*.sol} : Deployment scripts must reside in `script/deploy/facets/` for base deployments and `script/deploy/zksync/` for ZKSync-specific scripts.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
  • script/deploy/facets/UpdateEcoFacet.s.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to {script/deploy/facets/*.sol,script/deploy/zksync/*.sol} : Deployment scripts must inherit `DeployScriptBase` and use JSON config with `stdJson`.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
  • script/deploy/facets/UpdateEcoFacet.s.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to {script/deploy/facets/*.sol,script/deploy/zksync/*.sol} : Update scripts must inherit `UpdateScriptBase` and use `update("{ContractName}")`.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
  • script/deploy/facets/UpdateEcoFacet.s.sol
📚 Learning: 2024-09-23T01:42:03.075Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: script/deploy/facets/DeployGasZipFacet.s.sol:22-35
Timestamp: 2024-09-23T01:42:03.075Z
Learning: In deployment scripts like `DeployGasZipFacet.s.sol`, do not report issues suggesting adding error handling for missing configuration files or unexpected JSON structures, as the script will fail if the file is missing.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-01-28T14:27:50.689Z
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.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-06-13T08:30:28.665Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1207
File: script/deploy/facets/DeployPioneerFacet.s.sol:17-27
Timestamp: 2025-06-13T08:30:28.665Z
Learning: Deployment scripts rely on external automation (pre-script checks) to validate constructor arguments such as non-zero addresses, so adding explicit `require` guards inside the Foundry deployment scripts is generally unnecessary.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2024-10-04T09:21:59.708Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#819
File: deployments/polygon.json:0-0
Timestamp: 2024-10-04T09:21:59.708Z
Learning: Ensure that scripts used for codebase verification produce valid and accurate results before reporting issues, especially when checking Ethereum address checksums in `deployments/polygon.json`.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-04-21T03:17:53.443Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1109
File: deployments/worldchain.json:28-28
Timestamp: 2025-04-21T03:17:53.443Z
Learning: For deployment PRs updating contract addresses (like RelayFacet on Worldchain), verify the presence of entries in all relevant files (worldchain.json, worldchain.diamond.json, _deployments_log_file.json) before reporting inconsistencies. The RelayFacet entry exists in all required deployment files with the correct address.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2024-11-25T13:49:40.464Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: script/deploy/zksync/DeployPermit2Proxy.s.sol:22-61
Timestamp: 2024-11-25T13:49:40.464Z
Learning: In the deploy scripts (e.g., `script/deploy/zksync/DeployPermit2Proxy.s.sol`), complex error handling and address validation are not necessary. The team prefers to keep deploy scripts simple without extensive error handling.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-07-04T08:59:08.108Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1256
File: deployments/zksync.diamond.json:81-87
Timestamp: 2025-07-04T08:59:08.108Z
Learning: When analyzing deployment PRs in the lifinance/contracts repository, carefully verify that target state configuration files (like script/deploy/_targetState.json) have been updated before flagging missing entries. The AI summary section should be consulted to understand all file changes, as manual searches might miss entries due to formatting differences or search limitations.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2024-10-14T00:50:53.603Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: script/deploy/facets/DeployPermit2Proxy.s.sol:17-20
Timestamp: 2024-10-14T00:50:53.603Z
Learning: In `DeployScriptBase`, `getConstructorArgs()` is called and constructor arguments are handled, so child deploy scripts do not need to pass constructor arguments explicitly to the `deploy` function.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-07-23T08:12:29.064Z
Learnt from: mirooon
PR: lifinance/contracts#1193
File: script/deploy/facets/UpdateWhitelistManagerFacet.s.sol:1-1
Timestamp: 2025-07-23T08:12:29.064Z
Learning: Deployment scripts in script/deploy/ should not use the LGPL-3.0 license identifier, contrary to other Solidity files. Scripts can use UNLICENSED or other appropriate license identifiers.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-07-11T09:43:22.393Z
Learnt from: mirooon
PR: lifinance/contracts#1193
File: test/solidity/Facets/AllowListMigratorFacet.t.sol:39-52
Timestamp: 2025-07-11T09:43:22.393Z
Learning: For fork-based tests like AllowListMigratorFacet.t.sol that work with existing deployed contracts (mainnet diamond), initTestBase() is intentionally omitted since the standard test initialization is not needed.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to src/Facets/*Facet.sol : Facet contracts must reside in `src/Facets/` and names must include "Facet".

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-01-22T12:36:12.699Z
Learnt from: mirooon
PR: lifinance/contracts#945
File: test/solidity/Facets/GlacisFacet.t.sol:214-262
Timestamp: 2025-01-22T12:36:12.699Z
Learning: The GlacisFacet test suite inherits from TestBaseFacet which already covers various failure scenarios including invalid receiver address, invalid amounts, same chain bridging, and insufficient funds, making additional failure scenario tests redundant.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-22T03:16:28.754Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: test/solidity/Facets/GasZipFacet.t.sol:212-213
Timestamp: 2024-10-22T03:16:28.754Z
Learning: In the `GasZipFacetTest`, for the test case `testBase_Revert_SwapAndBridgeWithInvalidSwapData()`, a generic revert is expected, so `vm.expectRevert();` without specifying the expected error is appropriate.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-10T03:26:23.793Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: test/solidity/Helpers/WithdrawablePeriphery.t.sol:79-80
Timestamp: 2024-10-10T03:26:23.793Z
Learning: In Solidity tests, it's acceptable to use `UnAuthorized.selector` in `vm.expectRevert()`; avoid suggesting changing it to string messages.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-22T03:24:24.705Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: test/solidity/Facets/GasZipFacet.t.sol:337-339
Timestamp: 2024-10-22T03:24:24.705Z
Learning: In `GasZipFacet` tests, when expecting a failure due to insufficient balance for sending value, the test should expect a generic revert without specifying a specific error.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : Use `vm.expectRevert()` to verify specific revert reasons in failure test cases.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : All tests that verify a failure case must be prefixed with: `testRevert_`.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : Use `vm.expectEmit(true, true, true, true, <contractAddress>)` for event testing.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : All tests that verify a successful execution must be prefixed with: `test_`.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-01-28T14:29:00.823Z
Learnt from: ezynda3
PR: lifinance/contracts#924
File: script/deploy/zksync/utils/UpdateScriptBase.sol:112-178
Timestamp: 2025-01-28T14:29:00.823Z
Learning: The suggestion to modify `buildDiamondCut` function in `UpdateScriptBase.sol` to handle selectors from multiple old facets differently was deemed unnecessary by the maintainer.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-05-06T09:09:38.108Z
Learnt from: mirooon
PR: lifinance/contracts#1117
File: test/solidity/Periphery/LiFiDEXAggregator.t.sol:111-127
Timestamp: 2025-05-06T09:09:38.108Z
Learning: The `setupApechain()` function in LiFiDEXAggregator tests intentionally avoids calling `initTestBase()` to prevent needing to define standard contracts (like ADDRESS_USDC_PROXY and Uniswap) that aren't needed for Apechain-specific tests.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-31T09:10:16.115Z
Learnt from: ezynda3
PR: lifinance/contracts#843
File: test/solidity/Facets/RelayFacet.t.sol:0-0
Timestamp: 2024-10-31T09:10:16.115Z
Learning: In the `signData` function within `RelayFacetTest` in `test/solidity/Facets/RelayFacet.t.sol`, the use of the EIP-712 standard for hashing and signing is not required.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-11-21T08:39:29.530Z
Learnt from: ezynda3
PR: lifinance/contracts#861
File: config/dexs.json:748-752
Timestamp: 2024-11-21T08:39:29.530Z
Learning: In the 'worldchain' network, the addresses `0x50D5a8aCFAe13Dceb217E9a071F6c6Bd5bDB4155`, `0x8f023b4193a6b18C227B4a755f8e28B3D30Ef9a1`, and `0x603a538477d44064eA5A5d8C345b4Ff6fca1142a` are used as DEXs and should be included in `config/dexs.json`.

Applied to files:

  • config/dexs.json
📚 Learning: 2024-11-04T02:25:07.478Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#846
File: config/dexs.json:296-300
Timestamp: 2024-11-04T02:25:07.478Z
Learning: In `config/dexs.json`, it's expected that some addresses appear multiple times across different networks.

Applied to files:

  • config/dexs.json
📚 Learning: 2024-10-21T01:27:47.808Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#836
File: config/dexs.json:396-397
Timestamp: 2024-10-21T01:27:47.808Z
Learning: In `config/dexs.json`, it's acceptable for a whitelisted DEX address to be the same across multiple networks.

Applied to files:

  • config/dexs.json
📚 Learning: 2025-06-11T08:55:44.396Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1201
File: config/dexs.json:536-537
Timestamp: 2025-06-11T08:55:44.396Z
Learning: In lifinance/contracts, the addresses stored in config/dexs.json are handled case-insensitively, so they do not need to be written in EIP-55 checksummed format.

Applied to files:

  • config/dexs.json
📚 Learning: 2025-07-16T01:04:55.857Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1275
File: src/Facets/AllBridgeFacet.sol:186-188
Timestamp: 2025-07-16T01:04:55.857Z
Learning: In LiFi facet contracts, when public entry point functions have `nonReentrant` modifier protection, internal functions like `_startBridge` that they call benefit from this reentrancy protection, making event emission order after external calls acceptable from a security perspective.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2024-10-31T09:09:38.568Z
Learnt from: ezynda3
PR: lifinance/contracts#843
File: src/Facets/RelayFacet.sol:165-170
Timestamp: 2024-10-31T09:09:38.568Z
Learning: In the `RelayFacet` contract (`src/Facets/RelayFacet.sol`), within the `_startBridge` function, low-level `call` is intentionally used to transfer tokens so that extra bytes can be added to the calldata, as required for integrating with Relay Protocol.

Applied to files:

  • src/Facets/EcoFacet.sol
🪛 GitHub Check: Olympix Integrated Security
src/Facets/EcoFacet.sol

[notice] 114-114:
Reentrant functions which emit events after making an external call may lead to out-of-order events. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/reentrancy-events


[warning] 261-261:
Calling a function without checking the return value may lead to silent failures. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/unused-return-function-call


[warning] 271-271:
Calling a function without checking the return value may lead to silent failures. For more information, visit: http://detectors.olympixdevsectools.com/article/web3-vulnerability/unused-return-function-call

🔇 Additional comments (7)
script/deploy/facets/UpdateEcoFacet.s.sol (1)

1-1: License header for deploy scripts — align with team convention

Our deploy/update scripts use UNLICENSED (per team learnings), not LGPL.

[ suggest_nitpick ]

-// SPDX-License-Identifier: LGPL-3.0-only
+// SPDX-License-Identifier: UNLICENSED
test/solidity/Facets/EcoFacet.t.sol (3)

1-3: License and pragma look good.

LGPL-3.0 identifier and Solidity pragma present per guidelines.


30-79: Solid test harness wiring.

Fork setup, liquidity seeding, facet attachment, and allowlist configuration align with our testing conventions.


138-141: Good negative test for zero portal config.

Accurately expects InvalidConfig on constructor with address(0).

src/Facets/EcoFacet.sol (3)

278-291: Event emission after external call is acceptable here.

Protected by nonReentrant in the public entrypoints; ordering is fine per prior practice. Referencing our earlier learnings.


1-20: NatSpec and licensing comply.

LGPL-3.0 license, required NatSpec tags (title/author/notice/version), and facet placement look correct.


3-3: Confirm compiler version matches foundry.toml.

Ensure 0.8.17 matches the repo’s configured Solidity/EVM version.

Would you like a quick script to parse foundry.toml and check pragma consistency?

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: 4

♻️ Duplicate comments (3)
script/deploy/facets/DeployEcoFacet.s.sol (1)

20-21: Fix deployment call to follow DeployScriptBase patterns.

Based on past review comments, DeployScriptBase.deploy already handles concatenating constructor arguments with creation code. Passing pre-concatenated code causes double-encoding of constructor arguments.

Apply this diff:

-        deployed = EcoFacet(deploy(type(EcoFacet).creationCode));
+        deployed = EcoFacet(deploy(type(EcoFacet).creationCode));

The getConstructorArgs() override already handles returning abi.encode(portal), so the deploy call only needs the creation code.

src/Facets/EcoFacet.sol (2)

208-210: Fix route tokens logic to use receiving asset type.

The current implementation uses sendingAssetId to determine if route tokens are needed, but should use receivingAssetId since route tokens represent what gets delivered on the destination chain.

Apply this diff:

-        if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {
+        if (LibAsset.isNativeAsset(_ecoData.receivingAssetId)) {
             return new IEcoPortal.TokenAmount[](0);
         }

228-250: Fix native amount calculation logic and remove double-counting.

The intent construction has two issues:

  1. Uses sending asset to determine native amounts but should use receiving asset
  2. Double-counts minAmount in the reward, causing underfunding

Apply this diff:

-        bool isNative = LibAsset.isNativeAsset(_bridgeData.sendingAssetId);
+        bool receiveNative = LibAsset.isNativeAsset(_ecoData.receivingAssetId);

         return
             IEcoPortal.Intent({
                 destination: uint64(_bridgeData.destinationChainId),
                 route: IEcoPortal.Route({
                     salt: _ecoData.salt,
                     deadline: _ecoData.routeDeadline,
                     portal: _ecoData.destinationPortal,
-                    nativeAmount: isNative ? _bridgeData.minAmount : 0,
+                    nativeAmount: receiveNative ? _bridgeData.minAmount : 0,
                     tokens: routeTokens,
                     calls: routeCalls
                 }),
                 reward: IEcoPortal.Reward({
                     deadline: _ecoData.rewardDeadline,
                     creator: msg.sender,
                     prover: _ecoData.prover,
-                    nativeAmount: isNative
-                        ? _ecoData.solverReward + _bridgeData.minAmount
-                        : _ecoData.solverReward,
+                    nativeAmount: _ecoData.solverReward,
                     tokens: new IEcoPortal.TokenAmount[](0)
                 })
             });
🧹 Nitpick comments (5)
deployments/_deployments_log_file.json (1)

39136-39141: Timestamp/verification housekeeping (non-blocking).

If verification completes, remember to flip VERIFIED to "true". Ensure timestamp convention (UTC vs local) matches prior entries before merging.

script/demoScripts/demoEco.ts (4)

27-30: Avoid hardcoding portal/prover; load from config by chain/environment.

Hardcoded addresses risk drift across staging/prod. Prefer reading from config/eco.json (and/or env) keyed by src/dst chain.
If helpful, I can wire this to getEnvVar() and config/eco.json in a follow-up.


42-44: Use consola for consistent logging.

Replace console.info/log/error with consola.info/log/error to align with script conventions.

-  console.info(`Bridge 5 USDC from ${srcChain} --> Base`)
-  console.info(`Connected wallet address: ${signerAddress}`)
+  consola.info(`Bridge 5 USDC from ${srcChain} --> Base`)
+  consola.info(`Connected wallet address: ${signerAddress}`)

93-120: Simplify ERC20 wrappers by using viem getContract.

You can instantiate an ERC20 contract once and reuse read/write calls; it reduces boilerplate and improves readability.

-  const tokenContract = {
-    read: { allowance: async (args: [`0x${string}`, `0x${string}`]): Promise<bigint> => {
-      return (await publicClient.readContract({ address: SRC_TOKEN_ADDRESS, abi: erc20Abi, functionName: 'allowance', args })) as bigint
-    }},
-    write: { approve: async (args: [`0x${string}`, bigint]): Promise<`0x${string}`> => {
-      return walletClient.writeContract({ address: SRC_TOKEN_ADDRESS, abi: erc20Abi, functionName: 'approve', args } as any)
-    }},
-  }
+  const tokenContract = getContract({
+    address: SRC_TOKEN_ADDRESS,
+    abi: erc20Abi,
+    client: { public: publicClient, wallet: walletClient },
+  })

This remains compatible with ensureAllowance’s read/write usage.


129-147: Standardize logging and confirmed executeTransaction flag semantics

  • Verified that executeTransaction is defined as
    export const executeTransaction = async <T>(
      transaction: () => Promise<T>,
      transactionDescription: string,
      publicClient?: any,
      validateReceipt = false
    ) => {  }
    So the fourth boolean argument (true) correctly enables receipt validation—no change required there.
  • For consistency with the rest of the demo scripts (which use consola.info, consola.error, etc.), consider:
    • Importing consola in demoEco.ts.
    • Replacing the existing console.log(…) calls around line 129 with consola.info(…).
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 38e383f and 12b2a21.

📒 Files selected for processing (8)
  • config/eco.json (1 hunks)
  • deployments/_deployments_log_file.json (1 hunks)
  • deployments/optimism.diamond.staging.json (4 hunks)
  • deployments/optimism.staging.json (1 hunks)
  • script/demoScripts/demoEco.ts (1 hunks)
  • script/deploy/facets/DeployEcoFacet.s.sol (1 hunks)
  • src/Facets/EcoFacet.sol (1 hunks)
  • test/solidity/Facets/EcoFacet.t.sol (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • config/eco.json
🧰 Additional context used
📓 Path-based instructions (6)
script/**/*.ts

📄 CodeRabbit inference engine (conventions.md)

script/**/*.ts: All scripts must follow the rules defined in .eslintrc.cjs.
Use async/await for asynchronous operations in TypeScript scripts.
Handle errors appropriately with try/catch blocks in TypeScript scripts.
Include proper logging for debugging and monitoring in TypeScript scripts.
Use environment variables for configuration in TypeScript scripts.
All scripts must use citty for CLI argument parsing.
Use consola for consistent logging across TypeScript scripts.
Environment variables should be validated using getEnvVar() helper in TypeScript scripts.
Scripts should exit with appropriate exit codes (0 for success, 1 for error) in TypeScript scripts.

Files:

  • script/demoScripts/demoEco.ts
{src/**/*.sol,test/solidity/**/*.sol,script/**/*.sol}

📄 CodeRabbit inference engine (conventions.md)

All our own Solidity files must use the LGPL-3.0 license identifier. This applies to all contracts in src/, all test files in test/solidity/, and all deployment and task scripts in script/.

Files:

  • script/deploy/facets/DeployEcoFacet.s.sol
  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
**/*.sol

📄 CodeRabbit inference engine (conventions.md)

**/*.sol: Use custom error types rather than generic revert() statements.
Do not define interfaces in the same file as their implementation.
Every contract MUST have the following NatSpec tags in this order: @title, @author, @notice, @Custom:version.
The @author tag MUST always be "LI.FI (https://li.fi)" in contract NatSpec.
The @Custom:version MUST follow semantic versioning (X.Y.Z format) in contract NatSpec.
Every public/external function must have NatSpec comments describing the function, parameters, and return values.
All Solidity files must follow the rules defined in .solhint.json.
All Solidity files must use the EVM and Solidity version defined in foundry.toml unless networks require lower versions.

Files:

  • script/deploy/facets/DeployEcoFacet.s.sol
  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
{script/deploy/facets/*.sol,script/deploy/zksync/*.sol}

📄 CodeRabbit inference engine (conventions.md)

{script/deploy/facets/*.sol,script/deploy/zksync/*.sol}: Deployment scripts must reside in script/deploy/facets/ for base deployments and script/deploy/zksync/ for ZKSync-specific scripts.
Deployment scripts must inherit DeployScriptBase and use JSON config with stdJson.
Update scripts must inherit UpdateScriptBase and use update("{ContractName}").

Files:

  • script/deploy/facets/DeployEcoFacet.s.sol
src/Facets/*Facet.sol

📄 CodeRabbit inference engine (conventions.md)

Facet contracts must reside in src/Facets/ and names must include "Facet".

Files:

  • src/Facets/EcoFacet.sol
test/solidity/**/*.t.sol

📄 CodeRabbit inference engine (conventions.md)

test/solidity/**/*.t.sol: Test files must have a .t.sol extension.
All tests that verify a successful execution must be prefixed with: test_.
All tests that verify a failure case must be prefixed with: testRevert_.
For base or inherited tests, prefix with testBase_.
Every test contract must include a setUp() function.
Any contract inheriting from TestBase.sol must call initTestBase() in setUp().
Use assertEq() for checking equality of values in tests.
Use vm.expectRevert() to verify specific revert reasons in failure test cases.
Use vm.expectEmit(true, true, true, true, <contractAddress>) for event testing.
All Solidity test files must be organized mirroring the src/ structure.
All Solidity test files must use Foundry.

Files:

  • test/solidity/Facets/EcoFacet.t.sol
🧠 Learnings (48)
📓 Common learnings
Learnt from: mirooon
PR: lifinance/contracts#945
File: src/Facets/GlacisFacet.sol:1-3
Timestamp: 2025-01-28T11:28:16.225Z
Learning: The GlacisFacet contract audit will be conducted and added to the audit log in later stages of development. This is acceptable during the initial development phase.
📚 Learning: 2024-10-09T03:47:21.269Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#812
File: deployments/_deployments_log_file.json:1914-1927
Timestamp: 2024-10-09T03:47:21.269Z
Learning: Duplicate entries in `deployments/_deployments_log_file.json` that are outdated do not require changes.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2025-05-28T17:33:33.959Z
Learnt from: mirooon
PR: lifinance/contracts#1170
File: deployments/_deployments_log_file.json:28060-28072
Timestamp: 2025-05-28T17:33:33.959Z
Learning: Deployment log files like `deployments/_deployments_log_file.json` are historical records that document the actual versions deployed at specific times. They should not be updated to match current contract versions - they must accurately reflect what was deployed when the deployment occurred.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2025-01-09T04:17:46.190Z
Learnt from: ezynda3
PR: lifinance/contracts#914
File: deployments/_deployments_log_file.json:26902-26916
Timestamp: 2025-01-09T04:17:46.190Z
Learning: Updates to _deployments_log_file.json can represent backfilling of historical deployment data, not just new deployments. Such updates don't require new audits.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2025-05-28T17:33:10.529Z
Learnt from: mirooon
PR: lifinance/contracts#1170
File: deployments/_deployments_log_file.json:28706-28717
Timestamp: 2025-05-28T17:33:10.529Z
Learning: Deployment log files (like `_deployments_log_file.json`) are historical records that should not be updated to match current contract versions. They should accurately reflect the versions that were actually deployed at specific timestamps.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2024-12-04T01:59:34.045Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#832
File: deployments/_deployments_log_file.json:23712-23720
Timestamp: 2024-12-04T01:59:34.045Z
Learning: In `deployments/_deployments_log_file.json`, duplicate deployment entries for the same version and address may occur because they correspond to deployments on different networks. These entries are acceptable and should not be flagged as duplicates in future reviews.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2025-08-07T10:20:01.383Z
Learnt from: mirooon
PR: lifinance/contracts#1283
File: deployments/ronin.diamond.json:65-68
Timestamp: 2025-08-07T10:20:01.383Z
Learning: When analyzing deployment PRs in the lifinance/contracts repository, carefully verify that target state configuration files (like script/deploy/_targetState.json) and deployment log files have been updated before flagging missing entries. The AI summary section should be consulted to understand all file changes, as manual searches might miss entries due to formatting differences or search limitations.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2025-07-04T08:59:08.108Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1256
File: deployments/zksync.diamond.json:81-87
Timestamp: 2025-07-04T08:59:08.108Z
Learning: When analyzing deployment PRs in the lifinance/contracts repository, carefully verify that target state configuration files (like script/deploy/_targetState.json) have been updated before flagging missing entries. The AI summary section should be consulted to understand all file changes, as manual searches might miss entries due to formatting differences or search limitations.

Applied to files:

  • deployments/_deployments_log_file.json
  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-08-07T10:20:01.383Z
Learnt from: mirooon
PR: lifinance/contracts#1283
File: deployments/ronin.diamond.json:65-68
Timestamp: 2025-08-07T10:20:01.383Z
Learning: When analyzing deployment PRs in the lifinance/contracts repository, understand that _targetState.json tracks contract version numbers (not addresses) and _deployments_log_file.json contains deployment records with addresses that may not be organized in obvious network sections. Always verify the actual file structure before flagging missing entries.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2025-04-21T03:17:53.443Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1109
File: deployments/worldchain.json:28-28
Timestamp: 2025-04-21T03:17:53.443Z
Learning: For deployment PRs updating contract addresses (like RelayFacet on Worldchain), verify the presence of entries in all relevant files (worldchain.json, worldchain.diamond.json, _deployments_log_file.json) before reporting inconsistencies. The RelayFacet entry exists in all required deployment files with the correct address.

Applied to files:

  • deployments/_deployments_log_file.json
  • script/deploy/facets/DeployEcoFacet.s.sol
  • deployments/optimism.staging.json
  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-11-25T09:04:55.880Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: script/deploy/_targetState.json:143-143
Timestamp: 2024-11-25T09:04:55.880Z
Learning: Errors about the missing `OpBNBBridgeFacet` contract are expected when it is referenced in the target state but not yet merged into the main branch.

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2024-11-25T06:25:01.232Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: script/deploy/_targetState.json:143-143
Timestamp: 2024-11-25T06:25:01.232Z
Learning: Contracts like `OpBNBBridgeFacet` may be in development and only available in feature branches, resulting in missing source files in the main branch. Before flagging such missing contracts, check for open PRs that might include them.

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2025-08-26T15:19:07.775Z
Learnt from: mirooon
PR: lifinance/contracts#1328
File: script/deploy/facets/LDA/DeployAlgebraFacet.s.sol:4-4
Timestamp: 2025-08-26T15:19:07.775Z
Learning: DeployScriptBase.sol is located at script/deploy/facets/utils/DeployScriptBase.sol, not script/deploy/utils/DeployScriptBase.sol. Import paths from script/deploy/facets/LDA/ should use "../utils/DeployScriptBase.sol" to reference it correctly.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to {script/deploy/facets/*.sol,script/deploy/zksync/*.sol} : Deployment scripts must reside in `script/deploy/facets/` for base deployments and `script/deploy/zksync/` for ZKSync-specific scripts.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to {script/deploy/facets/*.sol,script/deploy/zksync/*.sol} : Deployment scripts must inherit `DeployScriptBase` and use JSON config with `stdJson`.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to {script/deploy/facets/*.sol,script/deploy/zksync/*.sol} : Update scripts must inherit `UpdateScriptBase` and use `update("{ContractName}")`.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2024-09-23T01:42:03.075Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: script/deploy/facets/DeployGasZipFacet.s.sol:22-35
Timestamp: 2024-09-23T01:42:03.075Z
Learning: In deployment scripts like `DeployGasZipFacet.s.sol`, do not report issues suggesting adding error handling for missing configuration files or unexpected JSON structures, as the script will fail if the file is missing.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-01-28T14:27:50.689Z
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.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-06-13T08:30:28.665Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1207
File: script/deploy/facets/DeployPioneerFacet.s.sol:17-27
Timestamp: 2025-06-13T08:30:28.665Z
Learning: Deployment scripts rely on external automation (pre-script checks) to validate constructor arguments such as non-zero addresses, so adding explicit `require` guards inside the Foundry deployment scripts is generally unnecessary.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2024-10-04T09:21:59.708Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#819
File: deployments/polygon.json:0-0
Timestamp: 2024-10-04T09:21:59.708Z
Learning: Ensure that scripts used for codebase verification produce valid and accurate results before reporting issues, especially when checking Ethereum address checksums in `deployments/polygon.json`.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2024-11-25T13:49:40.464Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: script/deploy/zksync/DeployPermit2Proxy.s.sol:22-61
Timestamp: 2024-11-25T13:49:40.464Z
Learning: In the deploy scripts (e.g., `script/deploy/zksync/DeployPermit2Proxy.s.sol`), complex error handling and address validation are not necessary. The team prefers to keep deploy scripts simple without extensive error handling.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2024-10-14T00:50:53.603Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: script/deploy/facets/DeployPermit2Proxy.s.sol:17-20
Timestamp: 2024-10-14T00:50:53.603Z
Learning: In `DeployScriptBase`, `getConstructorArgs()` is called and constructor arguments are handled, so child deploy scripts do not need to pass constructor arguments explicitly to the `deploy` function.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-07-23T08:12:29.064Z
Learnt from: mirooon
PR: lifinance/contracts#1193
File: script/deploy/facets/UpdateWhitelistManagerFacet.s.sol:1-1
Timestamp: 2025-07-23T08:12:29.064Z
Learning: Deployment scripts in script/deploy/ should not use the LGPL-3.0 license identifier, contrary to other Solidity files. Scripts can use UNLICENSED or other appropriate license identifiers.

Applied to files:

  • script/deploy/facets/DeployEcoFacet.s.sol
📚 Learning: 2025-04-21T03:17:53.443Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1109
File: deployments/worldchain.json:28-28
Timestamp: 2025-04-21T03:17:53.443Z
Learning: For deployment PRs involving address updates like the RelayFacet to Worldchain, verify the actual presence of entries in files before reporting issues. The RelayFacet exists in the diamond log file and the PR diff already contains the necessary address change.

Applied to files:

  • deployments/optimism.staging.json
  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-10-09T03:47:21.269Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: deployments/bsc.diamond.staging.json:4-7
Timestamp: 2024-10-09T03:47:21.269Z
Learning: In files with "staging" in their filename, such as `deployments/bsc.diamond.staging.json`, it is acceptable for facets to have empty "Name" and "Version" fields. Do not flag missing facet information in such files during reviews.

Applied to files:

  • deployments/optimism.staging.json
  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-09-27T07:10:15.586Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#812
File: deployments/polygon.diamond.json:4-11
Timestamp: 2024-09-27T07:10:15.586Z
Learning: In `deployments/polygon.diamond.json`, it's acceptable for certain facets to have empty names and versions when specified by the developer.

Applied to files:

  • deployments/optimism.staging.json
  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-10-24T06:17:25.211Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: deployments/bsc.diamond.staging.json:100-101
Timestamp: 2024-10-24T06:17:25.211Z
Learning: In `deployments/bsc.diamond.staging.json`, the trailing comma after the last property in the `Periphery` object is acceptable and should not be flagged as a JSON formatting error.

Applied to files:

  • deployments/optimism.staging.json
📚 Learning: 2024-11-01T11:53:57.162Z
Learnt from: ezynda3
PR: lifinance/contracts#846
File: deployments/cronos.diamond.json:28-31
Timestamp: 2024-11-01T11:53:57.162Z
Learning: In `deployments/cronos.diamond.json`, both `GenericSwapFacet` and `GenericSwapFacetV3` are distinct facets that should be included together, as they serve different purposes.

Applied to files:

  • deployments/optimism.staging.json
  • deployments/optimism.diamond.staging.json
📚 Learning: 2025-07-16T01:04:55.857Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1275
File: src/Facets/AllBridgeFacet.sol:186-188
Timestamp: 2025-07-16T01:04:55.857Z
Learning: In LiFi facet contracts, when public entry point functions have `nonReentrant` modifier protection, internal functions like `_startBridge` that they call benefit from this reentrancy protection, making event emission order after external calls acceptable from a security perspective.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2024-10-31T09:09:38.568Z
Learnt from: ezynda3
PR: lifinance/contracts#843
File: src/Facets/RelayFacet.sol:165-170
Timestamp: 2024-10-31T09:09:38.568Z
Learning: In the `RelayFacet` contract (`src/Facets/RelayFacet.sol`), within the `_startBridge` function, low-level `call` is intentionally used to transfer tokens so that extra bytes can be added to the calldata, as required for integrating with Relay Protocol.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-07-11T09:43:22.393Z
Learnt from: mirooon
PR: lifinance/contracts#1193
File: test/solidity/Facets/AllowListMigratorFacet.t.sol:39-52
Timestamp: 2025-07-11T09:43:22.393Z
Learning: For fork-based tests like AllowListMigratorFacet.t.sol that work with existing deployed contracts (mainnet diamond), initTestBase() is intentionally omitted since the standard test initialization is not needed.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to src/Facets/*Facet.sol : Facet contracts must reside in `src/Facets/` and names must include "Facet".

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
  • deployments/optimism.diamond.staging.json
📚 Learning: 2025-01-22T12:36:12.699Z
Learnt from: mirooon
PR: lifinance/contracts#945
File: test/solidity/Facets/GlacisFacet.t.sol:214-262
Timestamp: 2025-01-22T12:36:12.699Z
Learning: The GlacisFacet test suite inherits from TestBaseFacet which already covers various failure scenarios including invalid receiver address, invalid amounts, same chain bridging, and insufficient funds, making additional failure scenario tests redundant.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-22T03:16:28.754Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: test/solidity/Facets/GasZipFacet.t.sol:212-213
Timestamp: 2024-10-22T03:16:28.754Z
Learning: In the `GasZipFacetTest`, for the test case `testBase_Revert_SwapAndBridgeWithInvalidSwapData()`, a generic revert is expected, so `vm.expectRevert();` without specifying the expected error is appropriate.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-10T03:26:23.793Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: test/solidity/Helpers/WithdrawablePeriphery.t.sol:79-80
Timestamp: 2024-10-10T03:26:23.793Z
Learning: In Solidity tests, it's acceptable to use `UnAuthorized.selector` in `vm.expectRevert()`; avoid suggesting changing it to string messages.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-22T03:24:24.705Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: test/solidity/Facets/GasZipFacet.t.sol:337-339
Timestamp: 2024-10-22T03:24:24.705Z
Learning: In `GasZipFacet` tests, when expecting a failure due to insufficient balance for sending value, the test should expect a generic revert without specifying a specific error.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : Use `vm.expectRevert()` to verify specific revert reasons in failure test cases.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : All tests that verify a failure case must be prefixed with: `testRevert_`.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : Use `vm.expectEmit(true, true, true, true, <contractAddress>)` for event testing.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : All tests that verify a successful execution must be prefixed with: `test_`.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-01-28T14:29:00.823Z
Learnt from: ezynda3
PR: lifinance/contracts#924
File: script/deploy/zksync/utils/UpdateScriptBase.sol:112-178
Timestamp: 2025-01-28T14:29:00.823Z
Learning: The suggestion to modify `buildDiamondCut` function in `UpdateScriptBase.sol` to handle selectors from multiple old facets differently was deemed unnecessary by the maintainer.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-31T09:10:16.115Z
Learnt from: ezynda3
PR: lifinance/contracts#843
File: test/solidity/Facets/RelayFacet.t.sol:0-0
Timestamp: 2024-10-31T09:10:16.115Z
Learning: In the `signData` function within `RelayFacetTest` in `test/solidity/Facets/RelayFacet.t.sol`, the use of the EIP-712 standard for hashing and signing is not required.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-05-06T09:09:38.108Z
Learnt from: mirooon
PR: lifinance/contracts#1117
File: test/solidity/Periphery/LiFiDEXAggregator.t.sol:111-127
Timestamp: 2025-05-06T09:09:38.108Z
Learning: The `setupApechain()` function in LiFiDEXAggregator tests intentionally avoids calling `initTestBase()` to prevent needing to define standard contracts (like ADDRESS_USDC_PROXY and Uniswap) that aren't needed for Apechain-specific tests.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-11-26T01:04:16.637Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: deployments/fantom.diamond.json:92-94
Timestamp: 2024-11-26T01:04:16.637Z
Learning: In `deployments/*.diamond.json` files, it's acceptable for facets to have empty `Name` and `Version` fields, and these should not be flagged as issues.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-11-26T01:01:18.499Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: deployments/arbitrum.diamond.json:148-150
Timestamp: 2024-11-26T01:01:18.499Z
Learning: In `deployments/*.diamond.json` configuration files, facets that are part of an open PR and not yet merged into the main branch may have missing `Name` and `Version` fields.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-11-26T01:14:58.163Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: deployments/worldchain.diamond.json:5-63
Timestamp: 2024-11-26T01:14:58.163Z
Learning: When facet versions are set to empty strings in `deployments/*.diamond.json` files, do not report this issue, as it is already known and will be addressed separately.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2025-02-12T09:44:12.961Z
Learnt from: mirooon
PR: lifinance/contracts#985
File: script/deploy/_targetState.json:0-0
Timestamp: 2025-02-12T09:44:12.961Z
Learning: The bsca network intentionally maintains different facet versions between staging and production environments, specifically:
1. CalldataVerificationFacet: v1.1.1 in staging vs v1.1.2 in production
2. EmergencyPauseFacet: present only in production
3. Permit2Proxy: present only in production

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2025-04-21T03:15:12.236Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1109
File: deployments/worldchain.diamond.json:84-85
Timestamp: 2025-04-21T03:15:12.236Z
Learning: In deployment JSON files that contain "diamond" in their filename (located in the deployments folder), periphery contracts may have empty string values for their addresses. This indicates that the contract is not deployed on that particular chain and should not be flagged as an issue during code reviews.

Applied to files:

  • deployments/optimism.diamond.staging.json
🧬 Code graph analysis (1)
script/demoScripts/demoEco.ts (2)
script/common/types.ts (1)
  • SupportedChain (3-3)
script/demoScripts/utils/demoScriptHelpers.ts (4)
  • setupEnvironment (636-688)
  • ADDRESS_USDC_OPT (61-61)
  • ensureBalance (827-848)
  • ensureAllowance (853-887)
🔇 Additional comments (16)
deployments/optimism.staging.json (1)

48-49: Cross-file consistency confirmed – manual checksum verification required

All automated consistency checks passed:

  • deployments/optimism.staging.json defines
    “EcoFacet”: 0x26B5c627471C1c057020aCFC06DF4Bd08e7207e6
  • deployments/optimism.diamond.staging.json contains the same
    Name (“EcoFacet”) and matching address
  • _deployments_log_file.json includes an EcoFacet.optimism.staging entry with the identical address

Eth_utils was unavailable in the sandbox, so the EIP-55 checksum couldn’t be automatically validated. Please manually confirm that 0x26B5c627471C1c057020aCFC06DF4Bd08e7207e6 is correctly checksummed before merging.

deployments/_deployments_log_file.json (1)

39128-39144: ✅ Verified: EcoFacet.optimism.staging deployment entry is fully consistent

All checks passed with the provided script:

  • JSON integrity confirmed (jq . deployments/_deployments_log_file.json succeeded).
  • Constructor argument decodes to portal 0x90f0c8acc1e083bcb4f487f84fc349ae8d5e28d7, matching the value in config/eco.json (case-insensitive match).
  • Facet address 0x26B5c627471C1c057020aCFC06DF4Bd08e7207e6 appears in both deployments/optimism.staging.json and deployments/optimism.diamond.staging.json.
  • No CREATE2/CREATE3 or SALT usage detected in script/deploy/facets/DeployEcoFacet.s.sol.

Everything aligns with our logging conventions and the “historical record” rule.

deployments/optimism.diamond.staging.json (1)

88-91: LGTM! New EcoFacet deployment and staging placeholders are properly configured.

The new EcoFacet entry at 0x26B5c627471C1c057020aCFC06DF4Bd08e7207e6 with version 1.0.0 is properly added. The empty Name/Version fields for staging facets and the new Patcher periphery placeholder are acceptable in staging deployment files.

Also applies to: 148-151, 160-167, 180-180

test/solidity/Facets/EcoFacet.t.sol (5)

12-22: LGTM! TestEcoFacet wrapper provides necessary access controls.

The public wrapper methods addDex and setFunctionApprovalBySignature correctly expose the LibAllowList functionality needed for testing the facet's allowlist-based restrictions.


30-79: LGTM! Comprehensive test setup with proper diamond integration.

The setup correctly:

  • Forks testnet state and adds liquidity
  • Deploys TestEcoFacet with portal configuration
  • Attaches facet to diamond with all required selectors
  • Configures allowlist for Uniswap DEX and required function selectors
  • Sets appropriate test constants for bridge data and solver rewards

81-101: LGTM! Valid EcoData construction with proper test values.

The getValidEcoData() helper constructs realistic EcoData with appropriate defaults for testing, including proper deadline calculations and empty destination calls array.


103-136: LGTM! Correct implementation of TestBaseFacet overrides.

Both bridge methods correctly handle native vs ERC20 flows by sending appropriate msg.value (bridge amount + solver reward for native, only solver reward for ERC20 tokens).


138-141: LGTM! Proper invalid config test with correct error expectation.

The test correctly verifies that EcoFacet construction with a zero address portal reverts with InvalidConfig.selector.

src/Facets/EcoFacet.sol (6)

1-19: LGTM! Proper contract header with all required NatSpec tags.

The contract follows LiFi standards with:


54-59: LGTM! Proper constructor validation with appropriate error handling.

The constructor correctly validates the portal address and reverts with InvalidConfig for zero addresses, ensuring the immutable portal is always valid.


63-83: LGTM! Well-structured public entry points with proper modifiers.

Both functions correctly:

  • Apply all necessary modifiers (nonReentrant, refundExcessNative, validateBridgeData, source swap validation)
  • Handle asset deposits appropriately (direct deposit vs swap+deposit)
  • Delegate to internal _startBridge for core logic

Also applies to: 85-110


142-167: LGTM! Comprehensive bridge data validation.

The validation correctly ensures:

  • Consistency between destination calls and hasDestinationCall flag
  • Proper receiver address matching for non-destination-call scenarios
  • Non-EVM receiver validation when targeting non-EVM chains

169-202: LGTM! Smart route call construction based on context.

The logic appropriately handles different scenarios:

  • Uses provided destination calls when available
  • Returns empty calls for non-EVM receivers
  • Constructs appropriate transfer calls (ERC20 transfer vs native value transfer) based on asset type

278-291: LGTM! Appropriate event emissions for different bridge scenarios.

The function correctly emits BridgeToNonEVMChain for non-EVM destinations and always emits LiFiTransferStarted for tracking purposes.

script/demoScripts/demoEco.ts (2)

21-25: Good fix: ABI source is now well-typed and local.

Switching to the compiled artifact and Narrow typing resolves the earlier undefined ABI issue and avoids runtime mismatches.


8-8: Please verify the TypeChain output directory and import path for ILiFi
I wasn’t able to locate a typechain or typechain-types folder in the repo, so the import in script/demoScripts/demoEco.ts will likely fail to resolve. Please confirm where your generated TypeChain definitions live (and that they’re committed), then update the import accordingly.

• Check your TypeChain configuration (e.g., in hardhat.config.ts or typechain.config.ts) to see the output directory
• Ensure the generated types folder (commonly typechain or typechain-types) exists at the project root
• Adjust the import in script/demoScripts/demoEco.ts to point at the correct relative path for ILiFi

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

♻️ Duplicate comments (6)
script/demoScripts/demoEco.ts (3)

105-131: Consider using the createContractObject helper for consistency.

Similar to the previous suggestion, the tokenContract creation duplicates logic that could be handled by the helper.

-  const tokenContract = {
-    read: {
-      allowance: async (
-        args: [`0x${string}`, `0x${string}`]
-      ): Promise<bigint> => {
-        return (await publicClient.readContract({
-          address: SRC_TOKEN_ADDRESS,
-          abi: erc20Abi,
-          functionName: 'allowance',
-          args,
-        })) as bigint
-      },
-    },
-    write: {
-      approve: async (
-        args: [`0x${string}`, bigint]
-      ): Promise<`0x${string}`> => {
-        return walletClient.writeContract({
-          address: SRC_TOKEN_ADDRESS,
-          abi: erc20Abi,
-          functionName: 'approve',
-          args,
-        } as any)
-      },
-    },
-  }
+  const tokenContract = createContractObject(
+    SRC_TOKEN_ADDRESS,
+    erc20Abi,
+    publicClient,
+    walletClient
+  )

100-100: Clarify the inconsistent comment about the fee amount.

The comment states "0.25 USDC fee" but the code uses the feeAmount variable which is set to 0.015 USDC. This creates confusion about the actual fee amount.

-    solverReward: feeAmount, // 0.25 USDC fee instead of ETH
+    solverReward: feeAmount, // 0.015 USDC fee

77-88: Verify destinationChainId type: should be bigint for ILiFi.BridgeDataStruct.

The ILiFi.BridgeDataStruct expects destinationChainId as a bigint (uint256), but the current implementation uses a number type which may cause TypeScript compilation errors.

   const bridgeData: ILiFi.BridgeDataStruct = {
     transactionId: `0x${randomBytes(32).toString('hex')}`,
     bridge: 'eco',
     integrator: 'demoScript',
     referrer: zeroAddress,
     sendingAssetId: SRC_TOKEN_ADDRESS,
     receiver: signerAddress, // Receiver on destination chain (same as signer)
-    destinationChainId: args.dstChain === 'base' ? 8453 : 8453, // Default to Base for now
+    destinationChainId: BigInt(args.dstChain === 'base' ? 8453 : 8453), // Default to Base for now
     minAmount: amount,
     hasSourceSwaps: false,
     hasDestinationCall: false,
   }
src/Facets/EcoFacet.sol (3)

227-243: Route tokens should be based on the receiving asset, not the sending asset.

The function currently checks if the sending asset is native to determine route tokens, but route tokens represent what will be delivered on the destination chain. This should be based on the receiving asset instead.

 function _buildRouteTokens(
     ILiFi.BridgeData memory _bridgeData,
     EcoData calldata _ecoData
 ) private pure returns (IEcoPortal.TokenAmount[] memory) {
-    if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {
+    if (LibAsset.isNativeAsset(_ecoData.receivingAssetId)) {
         return new IEcoPortal.TokenAmount[](0);
     }

     IEcoPortal.TokenAmount[]
         memory routeTokens = new IEcoPortal.TokenAmount[](1);
     routeTokens[0] = IEcoPortal.TokenAmount({
         token: _ecoData.receivingAssetId,
         amount: _bridgeData.minAmount
     });

     return routeTokens;
 }

280-282: Reward native amount includes minAmount unnecessarily.

For native token transfers, the reward's native amount currently includes both the solver reward and the bridge amount. The bridge amount is already accounted for in the route, so including it in the reward causes double-counting and may lead to incorrect funding.

                 nativeAmount: isNative
-                    ? _ecoData.solverReward + _bridgeData.minAmount
-                    : 0, // No native amount for ERC20
+                    ? _ecoData.solverReward
+                    : 0, // Only solver reward, not bridge amount

272-272: Route native amount should be based on the receiving asset.

The route's native amount represents what needs to be delivered on the destination chain. This should be determined by whether the receiving asset is native, not the sending asset.

-                nativeAmount: isNative ? _bridgeData.minAmount : 0,
+                nativeAmount: LibAsset.isNativeAsset(_ecoData.receivingAssetId) ? _bridgeData.minAmount : 0,
🧹 Nitpick comments (6)
script/demoScripts/demoEco.ts (1)

61-73: Consider using the createContractObject helper for consistency.

The current manual creation of the usdcContract object duplicates logic from the existing createContractObject helper. Consider using the helper to reduce code duplication and ensure consistent error handling.

-  const usdcContract = {
-    read: {
-      balanceOf: async (args: [`0x${string}`]): Promise<bigint> => {
-        return (await publicClient.readContract({
-          address: SRC_TOKEN_ADDRESS,
-          abi: erc20Abi,
-          functionName: 'balanceOf',
-          args,
-        })) as bigint
-      },
-    },
-  } as const
+  const usdcContract = createContractObject(
+    SRC_TOKEN_ADDRESS,
+    erc20Abi,
+    publicClient,
+    walletClient
+  )

You'll need to import the helper:

import { createContractObject } from './utils/demoScriptHelpers'
deployments/optimism.diamond.staging.json (4)

88-91: Missing facet metadata for CelerIMFacetMutable.

The CelerIMFacetMutable facet at address 0x2Af20933E5886aFe275c0EEE4A2e65daA4E8b169 has empty Name and Version fields. While this is acceptable for staging environments, consider adding the metadata for better traceability.


120-123: Missing facet metadata for two unidentified facets.

The facets at addresses 0xa137Fe4C41A2E04ca34578DC9023ad45cC194389 and 0x6124C65B6264bE13f059b7C3A891a5b77DA8Bd95 have empty Name and Version fields. Consider documenting what these facets are for better maintainability.


148-151: Missing facet metadata for multiple facets.

Several facets have empty Name and Version fields:

  • 0x91559A75bd9045681265C77922b3cAeDB3D5120d (lines 149-150)
  • 0x8962d191Ba0f2Bc29b949ACA222f8251B241190b (lines 153-154)
  • 0x0f4D0D8890bAF9036D3895315559a6F0d573e2EC (lines 161-162)
  • 0x59A1Bcaa32EdB1a233fEF945857529BBD6df247f (lines 165-166)

While acceptable for staging, documenting these facets would improve maintainability.

Also applies to: 152-155, 160-163, 164-167


180-180: Empty Patcher address in periphery.

The Patcher periphery contract has an empty address. If this contract is not needed for the staging environment, consider documenting why it's empty or removing the entry entirely.

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

71-72: Add the missing SwapRouter02 exactInput function selector.

For completeness and to support Uniswap V3 SwapRouter02 operations, consider adding the exactInput function selector approval. Based on web search results, the correct signature for SwapRouter02's exactInput uses a 5-field tuple.

   ecoFacet.setFunctionApprovalBySignature(
     uniswap.swapETHForExactTokens.selector
   );
+  // Approve SwapRouter02.exactInput(ExactInputParams) selector
+  // ExactInputParams: (bytes path, address recipient, uint256 deadline, uint256 amountIn, uint256 amountOutMinimum)
+  ecoFacet.setFunctionApprovalBySignature(
+    bytes4(keccak256("exactInput((bytes,address,uint256,uint256,uint256))"))
+  );
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9265a47 and acd28da.

📒 Files selected for processing (7)
  • deployments/_deployments_log_file.json (1 hunks)
  • deployments/optimism.diamond.staging.json (4 hunks)
  • deployments/optimism.staging.json (1 hunks)
  • script/demoScripts/demoEco.ts (1 hunks)
  • script/demoScripts/utils/demoScriptHelpers.ts (1 hunks)
  • src/Facets/EcoFacet.sol (1 hunks)
  • test/solidity/Facets/EcoFacet.t.sol (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • deployments/_deployments_log_file.json
  • deployments/optimism.staging.json
🧰 Additional context used
📓 Path-based instructions (5)
{src/**/*.sol,test/solidity/**/*.sol,script/**/*.sol}

📄 CodeRabbit inference engine (conventions.md)

All our own Solidity files must use the LGPL-3.0 license identifier. This applies to all contracts in src/, all test files in test/solidity/, and all deployment and task scripts in script/.

Files:

  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
**/*.sol

📄 CodeRabbit inference engine (conventions.md)

**/*.sol: Use custom error types rather than generic revert() statements.
Do not define interfaces in the same file as their implementation.
Every contract MUST have the following NatSpec tags in this order: @title, @author, @notice, @Custom:version.
The @author tag MUST always be "LI.FI (https://li.fi)" in contract NatSpec.
The @Custom:version MUST follow semantic versioning (X.Y.Z format) in contract NatSpec.
Every public/external function must have NatSpec comments describing the function, parameters, and return values.
All Solidity files must follow the rules defined in .solhint.json.
All Solidity files must use the EVM and Solidity version defined in foundry.toml unless networks require lower versions.

Files:

  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
src/Facets/*Facet.sol

📄 CodeRabbit inference engine (conventions.md)

Facet contracts must reside in src/Facets/ and names must include "Facet".

Files:

  • src/Facets/EcoFacet.sol
script/**/*.ts

📄 CodeRabbit inference engine (conventions.md)

script/**/*.ts: All scripts must follow the rules defined in .eslintrc.cjs.
Use async/await for asynchronous operations in TypeScript scripts.
Handle errors appropriately with try/catch blocks in TypeScript scripts.
Include proper logging for debugging and monitoring in TypeScript scripts.
Use environment variables for configuration in TypeScript scripts.
All scripts must use citty for CLI argument parsing.
Use consola for consistent logging across TypeScript scripts.
Environment variables should be validated using getEnvVar() helper in TypeScript scripts.
Scripts should exit with appropriate exit codes (0 for success, 1 for error) in TypeScript scripts.

Files:

  • script/demoScripts/utils/demoScriptHelpers.ts
  • script/demoScripts/demoEco.ts
test/solidity/**/*.t.sol

📄 CodeRabbit inference engine (conventions.md)

test/solidity/**/*.t.sol: Test files must have a .t.sol extension.
All tests that verify a successful execution must be prefixed with: test_.
All tests that verify a failure case must be prefixed with: testRevert_.
For base or inherited tests, prefix with testBase_.
Every test contract must include a setUp() function.
Any contract inheriting from TestBase.sol must call initTestBase() in setUp().
Use assertEq() for checking equality of values in tests.
Use vm.expectRevert() to verify specific revert reasons in failure test cases.
Use vm.expectEmit(true, true, true, true, <contractAddress>) for event testing.
All Solidity test files must be organized mirroring the src/ structure.
All Solidity test files must use Foundry.

Files:

  • test/solidity/Facets/EcoFacet.t.sol
🧠 Learnings (41)
📓 Common learnings
Learnt from: mirooon
PR: lifinance/contracts#945
File: src/Facets/GlacisFacet.sol:1-3
Timestamp: 2025-01-28T11:28:16.225Z
Learning: The GlacisFacet contract audit will be conducted and added to the audit log in later stages of development. This is acceptable during the initial development phase.
📚 Learning: 2025-07-16T01:04:55.857Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1275
File: src/Facets/AllBridgeFacet.sol:186-188
Timestamp: 2025-07-16T01:04:55.857Z
Learning: In LiFi facet contracts, when public entry point functions have `nonReentrant` modifier protection, internal functions like `_startBridge` that they call benefit from this reentrancy protection, making event emission order after external calls acceptable from a security perspective.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-08-27T22:23:51.247Z
Learnt from: mirooon
PR: lifinance/contracts#1328
File: src/Periphery/Lda/Facets/NativeWrapperFacet.sol:0-0
Timestamp: 2025-08-27T22:23:51.247Z
Learning: In src/Periphery/Lda/Facets/NativeWrapperFacet.sol, the wrapNative function should not validate msg.value == amountIn because CoreRouteFacet's DistributeNative command (command type 3) overrides the amountIn parameter with address(this).balance, making such validation incorrect and causing false failures.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2024-10-31T09:09:38.568Z
Learnt from: ezynda3
PR: lifinance/contracts#843
File: src/Facets/RelayFacet.sol:165-170
Timestamp: 2024-10-31T09:09:38.568Z
Learning: In the `RelayFacet` contract (`src/Facets/RelayFacet.sol`), within the `_startBridge` function, low-level `call` is intentionally used to transfer tokens so that extra bytes can be added to the calldata, as required for integrating with Relay Protocol.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-08-27T23:36:40.706Z
Learnt from: mirooon
PR: lifinance/contracts#1328
File: test/solidity/Periphery/GasZipPeriphery.t.sol:223-233
Timestamp: 2025-08-27T23:36:40.706Z
Learning: In bridge facet swap flows with requiresDeposit=false, tokens are already held by the diamond contract from previous swaps. When subsequent contracts like GasZipPeriphery call LibAsset.depositAsset, they pull tokens from msg.sender (the diamond) to themselves via transferFrom, requiring no additional approvals since the diamond already owns the tokens.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-04-04T07:21:52.878Z
Learnt from: mirooon
PR: lifinance/contracts#1086
File: test/solidity/utils/TestBase.sol:195-205
Timestamp: 2025-04-04T07:21:52.878Z
Learning: In the TestBase.sol file, the Optimism network constants are set correctly with:
- ADDRESS_UNISWAP_OPTIMISM: 0x4A7b5Da61326A6379179b40d00F57E5bbDC962c2 (Uniswap V2 Router)
- ADDRESS_USDC_OPTIMISM: 0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85 (Native USDC)
- USDC.e (bridged USDC from Ethereum) on Optimism has address 0x7f5c764cbc14f9669b88837ca1490cca17c31607

Applied to files:

  • script/demoScripts/utils/demoScriptHelpers.ts
📚 Learning: 2024-10-10T09:26:14.420Z
Learnt from: maxklenk
PR: lifinance/contracts#830
File: config/hop.json:536-582
Timestamp: 2024-10-10T09:26:14.420Z
Learning: In the `config/hop.json` file, for the `MATIC` token in the `polygon` section, having the zero address `0x0000000000000000000000000000000000000000` is acceptable because it references WMATIC.

Applied to files:

  • script/demoScripts/utils/demoScriptHelpers.ts
📚 Learning: 2024-11-21T08:39:29.530Z
Learnt from: ezynda3
PR: lifinance/contracts#861
File: config/dexs.json:748-752
Timestamp: 2024-11-21T08:39:29.530Z
Learning: In the 'worldchain' network, the addresses `0x50D5a8aCFAe13Dceb217E9a071F6c6Bd5bDB4155`, `0x8f023b4193a6b18C227B4a755f8e28B3D30Ef9a1`, and `0x603a538477d44064eA5A5d8C345b4Ff6fca1142a` are used as DEXs and should be included in `config/dexs.json`.

Applied to files:

  • script/demoScripts/utils/demoScriptHelpers.ts
📚 Learning: 2024-11-25T09:04:55.880Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: script/deploy/_targetState.json:143-143
Timestamp: 2024-11-25T09:04:55.880Z
Learning: Errors about the missing `OpBNBBridgeFacet` contract are expected when it is referenced in the target state but not yet merged into the main branch.

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2024-11-25T06:25:01.232Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: script/deploy/_targetState.json:143-143
Timestamp: 2024-11-25T06:25:01.232Z
Learning: Contracts like `OpBNBBridgeFacet` may be in development and only available in feature branches, resulting in missing source files in the main branch. Before flagging such missing contracts, check for open PRs that might include them.

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2025-08-19T05:10:12.922Z
Learnt from: ezynda3
PR: lifinance/contracts#1303
File: script/utils/network.ts:27-32
Timestamp: 2025-08-19T05:10:12.922Z
Learning: In the lifinance/contracts repository, the team decided to standardize RPC environment variable naming by converting all hyphens to underscores in network names. For example, "tron-shasta" becomes "ETH_NODE_URI_TRON_SHASTA". The getRPCEnvVarName() helper in script/utils/network.ts implements this standard and should be used consistently across the codebase instead of direct string manipulation.

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2024-11-04T03:47:47.465Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#847
File: script/tasks/fundNewWalletOnAllChains.ts:156-164
Timestamp: 2024-11-04T03:47:47.465Z
Learning: In the `fundNewWalletOnAllChains.ts` script, the gas estimation code involving `publicClient.estimateGas()` is intentionally commented out and should remain that way unless specified otherwise.

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to script/**/*.ts : All scripts must use `citty` for CLI argument parsing.

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2025-07-17T04:21:55.549Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1266
File: script/deploy/safe/execute-pending-timelock-tx.ts:334-334
Timestamp: 2025-07-17T04:21:55.549Z
Learning: In the lifinance/contracts repository, 0xDEnYO prefers to keep private key processing simple in scripts like execute-pending-timelock-tx.ts without adding format validation, prioritizing code simplicity over strict validation in controlled environments.

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2025-07-17T04:21:50.790Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1266
File: script/deploy/safe/execute-pending-timelock-tx.ts:129-129
Timestamp: 2025-07-17T04:21:50.790Z
Learning: In the lifinance/contracts repository, 0xDEnYO prefers not to add private key format validation in deployment scripts like execute-pending-timelock-tx.ts, prioritizing code simplicity over strict validation in their controlled environment.

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2025-07-16T01:03:08.106Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1275
File: src/Facets/AllBridgeFacet.sol:164-164
Timestamp: 2025-07-16T01:03:08.106Z
Learning: In src/Facets/AllBridgeFacet.sol, the team has decided that explicit validation for address downcasting from `_bridgeData.sendingAssetId` to `bytes32(uint256(uint160(_bridgeData.sendingAssetId)))` is not required, accepting the potential risk of silent overflow from unsafe downcasting.

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2025-08-22T10:03:58.794Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1299
File: script/demoScripts/demoAcrossV4.ts:728-737
Timestamp: 2025-08-22T10:03:58.794Z
Learning: Demo scripts in `script/demoScripts` are exempt from the citty CLI argument parsing requirement that applies to other TypeScript scripts. Templates for demo scripts don't use citty and this is acceptable.

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2025-07-11T09:43:22.393Z
Learnt from: mirooon
PR: lifinance/contracts#1193
File: test/solidity/Facets/AllowListMigratorFacet.t.sol:39-52
Timestamp: 2025-07-11T09:43:22.393Z
Learning: For fork-based tests like AllowListMigratorFacet.t.sol that work with existing deployed contracts (mainnet diamond), initTestBase() is intentionally omitted since the standard test initialization is not needed.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to src/Facets/*Facet.sol : Facet contracts must reside in `src/Facets/` and names must include "Facet".

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-10-22T03:16:28.754Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: test/solidity/Facets/GasZipFacet.t.sol:212-213
Timestamp: 2024-10-22T03:16:28.754Z
Learning: In the `GasZipFacetTest`, for the test case `testBase_Revert_SwapAndBridgeWithInvalidSwapData()`, a generic revert is expected, so `vm.expectRevert();` without specifying the expected error is appropriate.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-10T03:26:23.793Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: test/solidity/Helpers/WithdrawablePeriphery.t.sol:79-80
Timestamp: 2024-10-10T03:26:23.793Z
Learning: In Solidity tests, it's acceptable to use `UnAuthorized.selector` in `vm.expectRevert()`; avoid suggesting changing it to string messages.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-22T03:24:24.705Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: test/solidity/Facets/GasZipFacet.t.sol:337-339
Timestamp: 2024-10-22T03:24:24.705Z
Learning: In `GasZipFacet` tests, when expecting a failure due to insufficient balance for sending value, the test should expect a generic revert without specifying a specific error.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : Use `vm.expectRevert()` to verify specific revert reasons in failure test cases.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : All tests that verify a failure case must be prefixed with: `testRevert_`.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : Use `vm.expectEmit(true, true, true, true, <contractAddress>)` for event testing.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-28T07:54:14.853Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-07-28T07:54:14.853Z
Learning: Applies to test/solidity/**/*.t.sol : All tests that verify a successful execution must be prefixed with: `test_`.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-08-28T02:41:07.483Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1321
File: docs/RelayDepositoryFacet.md:9-10
Timestamp: 2025-08-28T02:41:07.483Z
Learning: Unit tests for RelayDepositoryFacet cannot verify fund forwarding behavior after deposits because the facet delegates to external IRelayDepository contracts. The forwarding logic is implemented in the Relay Protocol V2 Depository contracts, not in the facet itself.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-01-28T14:29:00.823Z
Learnt from: ezynda3
PR: lifinance/contracts#924
File: script/deploy/zksync/utils/UpdateScriptBase.sol:112-178
Timestamp: 2025-01-28T14:29:00.823Z
Learning: The suggestion to modify `buildDiamondCut` function in `UpdateScriptBase.sol` to handle selectors from multiple old facets differently was deemed unnecessary by the maintainer.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-01-22T12:36:12.699Z
Learnt from: mirooon
PR: lifinance/contracts#945
File: test/solidity/Facets/GlacisFacet.t.sol:214-262
Timestamp: 2025-01-22T12:36:12.699Z
Learning: The GlacisFacet test suite inherits from TestBaseFacet which already covers various failure scenarios including invalid receiver address, invalid amounts, same chain bridging, and insufficient funds, making additional failure scenario tests redundant.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-01-28T11:29:09.566Z
Learnt from: mirooon
PR: lifinance/contracts#945
File: test/solidity/Facets/GlacisFacet.t.sol:0-0
Timestamp: 2025-01-28T11:29:09.566Z
Learning: Empty test methods with explanatory comments are acceptable in test classes when the feature being tested (e.g., native token bridging) is not supported by the implementation.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-05-06T09:09:38.108Z
Learnt from: mirooon
PR: lifinance/contracts#1117
File: test/solidity/Periphery/LiFiDEXAggregator.t.sol:111-127
Timestamp: 2025-05-06T09:09:38.108Z
Learning: The `setupApechain()` function in LiFiDEXAggregator tests intentionally avoids calling `initTestBase()` to prevent needing to define standard contracts (like ADDRESS_USDC_PROXY and Uniswap) that aren't needed for Apechain-specific tests.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-09-27T07:10:15.586Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#812
File: deployments/polygon.diamond.json:4-11
Timestamp: 2024-09-27T07:10:15.586Z
Learning: In `deployments/polygon.diamond.json`, it's acceptable for certain facets to have empty names and versions when specified by the developer.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-11-26T01:01:18.499Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: deployments/arbitrum.diamond.json:148-150
Timestamp: 2024-11-26T01:01:18.499Z
Learning: In `deployments/*.diamond.json` configuration files, facets that are part of an open PR and not yet merged into the main branch may have missing `Name` and `Version` fields.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-11-01T11:53:57.162Z
Learnt from: ezynda3
PR: lifinance/contracts#846
File: deployments/cronos.diamond.json:28-31
Timestamp: 2024-11-01T11:53:57.162Z
Learning: In `deployments/cronos.diamond.json`, both `GenericSwapFacet` and `GenericSwapFacetV3` are distinct facets that should be included together, as they serve different purposes.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-11-26T01:04:16.637Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: deployments/fantom.diamond.json:92-94
Timestamp: 2024-11-26T01:04:16.637Z
Learning: In `deployments/*.diamond.json` files, it's acceptable for facets to have empty `Name` and `Version` fields, and these should not be flagged as issues.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2025-02-12T09:44:12.961Z
Learnt from: mirooon
PR: lifinance/contracts#985
File: script/deploy/_targetState.json:0-0
Timestamp: 2025-02-12T09:44:12.961Z
Learning: The bsca network intentionally maintains different facet versions between staging and production environments, specifically:
1. CalldataVerificationFacet: v1.1.1 in staging vs v1.1.2 in production
2. EmergencyPauseFacet: present only in production
3. Permit2Proxy: present only in production

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2025-04-21T03:17:53.443Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1109
File: deployments/worldchain.json:28-28
Timestamp: 2025-04-21T03:17:53.443Z
Learning: For deployment PRs involving address updates like the RelayFacet to Worldchain, verify the actual presence of entries in files before reporting issues. The RelayFacet exists in the diamond log file and the PR diff already contains the necessary address change.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-10-09T03:47:21.269Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: deployments/bsc.diamond.staging.json:4-7
Timestamp: 2024-10-09T03:47:21.269Z
Learning: In files with "staging" in their filename, such as `deployments/bsc.diamond.staging.json`, it is acceptable for facets to have empty "Name" and "Version" fields. Do not flag missing facet information in such files during reviews.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-11-26T01:14:58.163Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: deployments/worldchain.diamond.json:5-63
Timestamp: 2024-11-26T01:14:58.163Z
Learning: When facet versions are set to empty strings in `deployments/*.diamond.json` files, do not report this issue, as it is already known and will be addressed separately.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-11-26T01:16:27.721Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: deployments/worldchain.diamond.json:40-43
Timestamp: 2024-11-26T01:16:27.721Z
Learning: Version inconsistencies of 'GenericSwapFacetV3' across deployment configurations are acceptable if they are only due to differences in Solidity pragma directives.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2025-04-21T03:17:53.443Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1109
File: deployments/worldchain.json:28-28
Timestamp: 2025-04-21T03:17:53.443Z
Learning: For deployment PRs updating contract addresses (like RelayFacet on Worldchain), verify the presence of entries in all relevant files (worldchain.json, worldchain.diamond.json, _deployments_log_file.json) before reporting inconsistencies. The RelayFacet entry exists in all required deployment files with the correct address.

Applied to files:

  • deployments/optimism.diamond.staging.json
🧬 Code graph analysis (1)
script/demoScripts/demoEco.ts (2)
script/common/types.ts (1)
  • SupportedChain (3-3)
script/demoScripts/utils/demoScriptHelpers.ts (6)
  • setupEnvironment (637-689)
  • ADDRESS_USDC_OPT (61-61)
  • ensureBalance (828-849)
  • ADDRESS_USDC_BASE (71-71)
  • ensureAllowance (854-888)
  • executeTransaction (787-823)
🔇 Additional comments (9)
script/demoScripts/utils/demoScriptHelpers.ts (1)

70-71: LGTM!

The removal of the trailing space from ADDRESS_WMATIC_POL and the addition of ADDRESS_USDC_BASE are correct. These changes support the Eco bridging demo script that targets USDC on Base.

deployments/optimism.diamond.staging.json (1)

168-171: LGTM! EcoFacet properly configured.

The EcoFacet is correctly configured with:

  • Address: 0xc4884225aeFe7218f9f489A5Eb8beB504ab272AA
  • Name: "EcoFacet"
  • Version: "1.0.0"

This aligns with the semantic versioning requirements and the facet implementation.

test/solidity/Facets/EcoFacet.t.sol (4)

150-153: LGTM! Proper test for invalid configuration.

The test correctly verifies that the EcoFacet constructor reverts with InvalidConfig when passed a zero address for the portal, ensuring proper validation of the immutable portal reference.


156-182: LGTM! Correctly handles ERC20 token rewards.

The test override properly accounts for the TOKEN_SOLVER_REWARD in the balance assertions and approval amount, ensuring the EcoFacet's unique reward mechanism is properly tested.


185-213: LGTM! Fuzzed test properly validates token reward handling.

The fuzzed test correctly ensures the user has sufficient balance for both the bridge amount and the TOKEN_SOLVER_REWARD, with proper bounds checking to prevent overflow.


216-292: LGTM! Comprehensive swap and bridge test with proper reward handling.

The test correctly:

  1. Calculates the total amount needed (bridge amount + solver reward)
  2. Sets up the swap to produce the exact total amount
  3. Verifies balance changes match expectations
  4. Properly emits the expected events
src/Facets/EcoFacet.sol (3)

54-59: LGTM! Constructor properly validates portal address.

The constructor correctly reverts with InvalidConfig when the portal address is zero, ensuring the immutable portal reference is always valid.


165-190: LGTM! Comprehensive validation logic.

The _validateEcoData function properly validates:

  1. Consistency between destination calls and the hasDestinationCall flag
  2. Receiver address consistency for EVM destinations
  3. Non-empty nonEVMReceiver for non-EVM destinations

295-298: Fix msg.value calculation to avoid double-counting.

Since the reward native amount was incorrectly including the bridge amount, this publishAndFund call sends the correct total value. However, after fixing the reward native amount above, this should remain unchanged as it correctly sends the total needed (bridge amount + solver reward).

The msg.value calculation is correct and should remain as is after fixing the reward native amount calculation.

Define and use constants for:
- NATIVE_REWARD_AMOUNT (0)
- ALLOW_PARTIAL_FILL (false)
- SOLANA_ENCODED_ROUTE_LENGTH (319)
- SOLANA_RECEIVER_OFFSET (251)
- SOLANA_RECEIVER_END (283)
- SOLANA_ADDRESS_MIN_LENGTH (32)
- SOLANA_ADDRESS_MAX_LENGTH (44)

Improves code maintainability and makes the intent behind each value explicit.

Resolves audit issue #1
Remove '{ value: 0 }' from PORTAL.publishAndFund call as it's redundant
(default is 0). Simplifies code and slightly reduces bytecode size.

Resolves audit issue #8
BREAKING CHANGE: Remove receiverAddress field from EcoData struct as it
duplicates _bridgeData.receiver. The receiver is already validated from
the encodedRoute for EVM chains and through nonEVMReceiver for Solana.

This saves gas and simplifies the API by removing redundant data.

Resolves audit issue #2
Remove receiverAddress field from EcoData struct usage in demo script
to match the updated contract interface.
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: 3

♻️ Duplicate comments (2)
deployments/optimism.diamond.staging.json (1)

164-183: Remove duplicate AcrossFacet V4 entries

AcrossFacetV4 and AcrossFacetPackedV4 each appear twice (Lines 164-167 & 176-179, 148-151 & 180-183) with identical Name/Version but different addresses, reintroducing the ambiguity we previously asked to resolve. Please keep only the active deployment (or rename the inactive entry with a disambiguating suffix) so downstream tooling can map facets deterministically.

script/demoScripts/demoEco.ts (1)

521-534: Critical: Use bs58.decode() to convert Solana address, not TextEncoder.

TextEncoder encodes the base58 string characters, not the underlying 32-byte public key. This will produce incorrect bytes for the Solana recipient and cause on-chain failures or send funds to the wrong address.

Apply this diff:

+import bs58 from 'bs58'

Then replace the encoding logic:

   if (isDestinationSolana) {
     if (!privateKey)
       throw new Error('Private key required for Solana destination')
 
     const solanaAddress = deriveSolanaAddress(privateKey)
-    // Convert Solana base58 address to hex bytes for nonEVMReceiver field
-    const encoder = new TextEncoder()
-    const solanaAddressBytes = encoder.encode(solanaAddress)
-    nonEVMReceiverBytes = toHex(solanaAddressBytes)
+    // Convert Solana base58 address to raw 32-byte public key
+    const solanaAddressBytes = bs58.decode(solanaAddress)
+    if (solanaAddressBytes.length !== 32) {
+      throw new Error(`Invalid Solana address: expected 32 bytes, got ${solanaAddressBytes.length}`)
+    }
+    nonEVMReceiverBytes = toHex(solanaAddressBytes)
 
     console.log('Solana destination details:')

Note: Verify that the bs58 package is installed. If not, add it with npm install bs58 or pnpm add bs58.

🧹 Nitpick comments (2)
script/demoScripts/demoEco.ts (2)

122-135: Document that derived Solana address is demo-only; consider accepting user input.

The function derives a Solana address from an Ethereum private key, which creates an unrelated ed25519 keypair. While acceptable for demo purposes, this should either:

  1. Accept a user-provided Solana recipient address via CLI arg/env var as the primary path
  2. Clearly document in code comments that this derivation is DEMO-ONLY and unsuitable for real funds

Consider adding a CLI argument --solanaRecipient and using this function only as a fallback for demo mode. Example:

/**
 * Derives a Solana address from an Ethereum private key
 * 
 * ⚠️ DEMO ONLY: This creates an unrelated ed25519 keypair.
 * For production, use a proper Solana wallet or accept recipient via CLI.
 * 
 * Uses the Ethereum private key as a seed for Ed25519 keypair generation
 *
 * @param ethPrivateKey - Ethereum private key (with or without 0x prefix)
 * @returns Solana address in base58 format
 */

Based on learnings.


383-384: Consider using getEnvVar() for PRIVATE_KEY access.

While setupEnvironment() validates the private key internally via getPrivateKeyForEnvironment(), directly accessing process.env.PRIVATE_KEY here bypasses explicit validation and violates the guideline to use getEnvVar() consistently.

Consider:

-  const privateKey = process.env.PRIVATE_KEY
+  const privateKey = getEnvVar('PRIVATE_KEY', false)

This makes the validation explicit at the point of use. However, since setupEnvironment() already validates it, this is a minor style improvement rather than a critical fix.

Based on coding guidelines.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 967d424 and 5bc35be.

📒 Files selected for processing (4)
  • deployments/_deployments_log_file.json (1 hunks)
  • deployments/optimism.diamond.staging.json (5 hunks)
  • deployments/optimism.staging.json (1 hunks)
  • script/demoScripts/demoEco.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • deployments/optimism.staging.json
🧰 Additional context used
📓 Path-based instructions (1)
script/**/*.ts

📄 CodeRabbit inference engine (conventions.md)

script/**/*.ts: All TypeScript scripts must follow .eslintrc.cjs, use async/await, try/catch error handling, proper logging, environment variables, correct typings, use citty for CLI parsing, consola for logging, validate env vars via getEnvVar(), and exit with appropriate codes
Prefer existing helper functions over reimplementation (e.g., getDeployments, getProvider, getWalletFromPrivateKeyInDotEnv, sendTransaction, ensureBalanceAndAllowanceToDiamond, getUniswapData*)
Always use proper TypeChain types (e.g., ILiFi.BridgeDataStruct) and never use any for bridge data or contract structures
Before/after changes: verify imports and types exist, ensure typechain is generated, keep changes comprehensive and consistent, run TS compilation, remove unused imports, and ensure function signatures match usage
Scripts must execute with bunx tsx

Files:

  • script/demoScripts/demoEco.ts
🧠 Learnings (23)
📚 Learning: 2025-09-09T10:39:26.383Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1357
File: deployments/lens.diamond.json:48-51
Timestamp: 2025-09-09T10:39:26.383Z
Learning: In the lifinance/contracts repository, when deployment JSON files show address changes (like AcrossFacetV3 address updates in deployments/*.diamond.json), the corresponding _deployments_log_file.json updates may be handled in separate PRs rather than the same PR that updates the diamond configuration files.

Applied to files:

  • deployments/_deployments_log_file.json
  • deployments/optimism.diamond.staging.json
📚 Learning: 2025-09-15T12:33:51.069Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1377
File: deployments/_deployments_log_file.json:5607-5619
Timestamp: 2025-09-15T12:33:51.069Z
Learning: The deployments/_deployments_log_file.json is structured as network → environment → version → array of deployment records. Always understand the file hierarchy before attempting validation, and target specific paths rather than trying to validate all objects in the JSON.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2025-05-28T17:33:33.959Z
Learnt from: mirooon
PR: lifinance/contracts#1170
File: deployments/_deployments_log_file.json:28060-28072
Timestamp: 2025-05-28T17:33:33.959Z
Learning: Deployment log files like `deployments/_deployments_log_file.json` are historical records that document the actual versions deployed at specific times. They should not be updated to match current contract versions - they must accurately reflect what was deployed when the deployment occurred.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2025-01-09T04:17:46.190Z
Learnt from: ezynda3
PR: lifinance/contracts#914
File: deployments/_deployments_log_file.json:26902-26916
Timestamp: 2025-01-09T04:17:46.190Z
Learning: Updates to _deployments_log_file.json can represent backfilling of historical deployment data, not just new deployments. Such updates don't require new audits.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2025-01-16T00:24:10.002Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#927
File: foundry.toml:78-78
Timestamp: 2025-01-16T00:24:10.002Z
Learning: Avalanche chain (chainid=43114) is supported by Etherscan V2 API and can use the endpoint https://api.etherscan.io/v2/api?chainid=43114 instead of Snowtrace.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to script/**/*.ts : Prefer existing helper functions over reimplementation (e.g., getDeployments, getProvider, getWalletFromPrivateKeyInDotEnv, sendTransaction, ensureBalanceAndAllowanceToDiamond, getUniswapData*)

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2025-08-19T05:10:12.922Z
Learnt from: ezynda3
PR: lifinance/contracts#1303
File: script/utils/network.ts:27-32
Timestamp: 2025-08-19T05:10:12.922Z
Learning: In the lifinance/contracts repository, the team decided to standardize RPC environment variable naming by converting all hyphens to underscores in network names. For example, "tron-shasta" becomes "ETH_NODE_URI_TRON_SHASTA". The getRPCEnvVarName() helper in script/utils/network.ts implements this standard and should be used consistently across the codebase instead of direct string manipulation.

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to script/**/*.ts : Always use proper TypeChain types (e.g., ILiFi.BridgeDataStruct) and never use any for bridge data or contract structures

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2025-07-16T01:03:08.106Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1275
File: src/Facets/AllBridgeFacet.sol:164-164
Timestamp: 2025-07-16T01:03:08.106Z
Learning: In src/Facets/AllBridgeFacet.sol, the team has decided that explicit validation for address downcasting from `_bridgeData.sendingAssetId` to `bytes32(uint256(uint160(_bridgeData.sendingAssetId)))` is not required, accepting the potential risk of silent overflow from unsafe downcasting.

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2025-05-27T16:19:16.726Z
Learnt from: mirooon
PR: lifinance/contracts#1165
File: src/Facets/GnosisBridgeFacet.sol:22-22
Timestamp: 2025-05-27T16:19:16.726Z
Learning: The correct USDS token address on Ethereum mainnet is 0xdC035D45d973E3EC169d2276DDab16f1e407384F, not 0xA4Bdb11dc0a2bEC88d24A3aa1E6Bb17201112eBe.

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2025-09-25T07:47:30.735Z
Learnt from: ezynda3
PR: lifinance/contracts#1324
File: src/Facets/EcoFacet.sol:306-336
Timestamp: 2025-09-25T07:47:30.735Z
Learning: In EcoFacet (src/Facets/EcoFacet.sol), the team intentionally uses variable-length validation for nonEVMReceiver addresses (up to 44 bytes) to support cross-ecosystem bridging with different address formats, rather than enforcing fixed 32-byte raw pubkeys.

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2025-09-22T00:52:26.172Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1388
File: deployments/hyperevm.diamond.json:72-75
Timestamp: 2025-09-22T00:52:26.172Z
Learning: In diamond configuration files (deployments/*.diamond.json), it's acceptable to have multiple versions of the same facet (e.g., GlacisFacet v1.0.0 and v1.1.0) deployed at different contract addresses. This is intentional design for version coexistence, gradual migration, or backward compatibility purposes.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-09-27T07:10:15.586Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#812
File: deployments/polygon.diamond.json:4-11
Timestamp: 2024-09-27T07:10:15.586Z
Learning: In `deployments/polygon.diamond.json`, it's acceptable for certain facets to have empty names and versions when specified by the developer.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-11-01T11:53:57.162Z
Learnt from: ezynda3
PR: lifinance/contracts#846
File: deployments/cronos.diamond.json:28-31
Timestamp: 2024-11-01T11:53:57.162Z
Learning: In `deployments/cronos.diamond.json`, both `GenericSwapFacet` and `GenericSwapFacetV3` are distinct facets that should be included together, as they serve different purposes.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-11-26T01:01:18.499Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: deployments/arbitrum.diamond.json:148-150
Timestamp: 2024-11-26T01:01:18.499Z
Learning: In `deployments/*.diamond.json` configuration files, facets that are part of an open PR and not yet merged into the main branch may have missing `Name` and `Version` fields.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2025-09-16T01:39:54.099Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1381
File: deployments/arbitrum.json:65-69
Timestamp: 2025-09-16T01:39:54.099Z
Learning: When verifying facet deployments across .json and .diamond.json files, search by facet name rather than trying to cross-reference addresses between the files, as the same contract can have different addresses in different deployment files.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-11-26T01:04:16.637Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: deployments/fantom.diamond.json:92-94
Timestamp: 2024-11-26T01:04:16.637Z
Learning: In `deployments/*.diamond.json` files, it's acceptable for facets to have empty `Name` and `Version` fields, and these should not be flagged as issues.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2025-04-21T03:17:53.443Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1109
File: deployments/worldchain.json:28-28
Timestamp: 2025-04-21T03:17:53.443Z
Learning: For deployment PRs involving address updates like the RelayFacet to Worldchain, verify the actual presence of entries in files before reporting issues. The RelayFacet exists in the diamond log file and the PR diff already contains the necessary address change.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2025-04-21T03:17:53.443Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1109
File: deployments/worldchain.json:28-28
Timestamp: 2025-04-21T03:17:53.443Z
Learning: For deployment PRs updating contract addresses (like RelayFacet on Worldchain), verify the presence of entries in all relevant files (worldchain.json, worldchain.diamond.json, _deployments_log_file.json) before reporting inconsistencies. The RelayFacet entry exists in all required deployment files with the correct address.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-10-09T03:47:21.269Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#819
File: deployments/scroll.diamond.json:82-82
Timestamp: 2024-10-09T03:47:21.269Z
Learning: In the `deployments/*.diamond.json` and `deployments/*.json` files, the `LiFiDEXAggregator` contract may intentionally have the same contract address across multiple networks. This is acceptable and should not be flagged as an issue in future code reviews.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-11-26T01:14:58.163Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: deployments/worldchain.diamond.json:5-63
Timestamp: 2024-11-26T01:14:58.163Z
Learning: When facet versions are set to empty strings in `deployments/*.diamond.json` files, do not report this issue, as it is already known and will be addressed separately.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2025-04-21T03:15:12.236Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1109
File: deployments/worldchain.diamond.json:84-85
Timestamp: 2025-04-21T03:15:12.236Z
Learning: In deployment JSON files that contain "diamond" in their filename (located in the deployments folder), periphery contracts may have empty string values for their addresses. This indicates that the contract is not deployed on that particular chain and should not be flagged as an issue during code reviews.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-10-09T03:47:21.269Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: deployments/bsc.diamond.staging.json:4-7
Timestamp: 2024-10-09T03:47:21.269Z
Learning: In files with "staging" in their filename, such as `deployments/bsc.diamond.staging.json`, it is acceptable for facets to have empty "Name" and "Version" fields. Do not flag missing facet information in such files during reviews.

Applied to files:

  • deployments/optimism.diamond.staging.json
🧬 Code graph analysis (1)
script/demoScripts/demoEco.ts (2)
script/demoScripts/utils/demoScriptHelpers.ts (21)
  • ADDRESS_USDC_OPT (61-61)
  • ADDRESS_USDC_BASE (75-75)
  • ADDRESS_USDC_ARB (63-63)
  • ADDRESS_USDC_ETH (57-57)
  • ADDRESS_USDC_POL (59-59)
  • ADDRESS_USDC_SOL (67-67)
  • ADDRESS_WETH_OPT (70-70)
  • ADDRESS_WETH_BASE (73-73)
  • ADDRESS_WETH_ARB (72-72)
  • ADDRESS_WETH_ETH (69-69)
  • ADDRESS_WETH_POL (71-71)
  • ADDRESS_UNISWAP_OPT (81-81)
  • ADDRESS_UNISWAP_BASE (83-83)
  • ADDRESS_UNISWAP_ARB (82-82)
  • ADDRESS_UNISWAP_ETH (78-78)
  • ADDRESS_UNISWAP_POL (80-80)
  • setupEnvironment (653-707)
  • getUniswapDataERC20toExactERC20 (334-406)
  • ensureBalance (846-867)
  • ensureAllowance (872-906)
  • executeTransaction (805-841)
script/common/types.ts (1)
  • SupportedChain (3-3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: enforce-min-test-coverage
  • GitHub Check: run-unit-tests
🔇 Additional comments (1)
deployments/_deployments_log_file.json (1)

43054-43060: Timestamp is set in the future.

The TIMESTAMP 2025-10-06 17:59:14 post-dates this PR by ~2 months, so this log can’t reflect an executed deployment. These records must document real deployments with accurate metadata—please update after the deployment occurs or correct the timestamp now. Based on learnings

⛔ Skipped due to learnings
Learnt from: ezynda3
PR: lifinance/contracts#861
File: deployments/_deployments_log_file.json:22488-22488
Timestamp: 2024-11-22T07:19:51.143Z
Learning: In `deployments/_deployments_log_file.json`, deployment timestamps may appear to be set in the future and should not be flagged as invalid.
Learnt from: ezynda3
PR: lifinance/contracts#823
File: deployments/_deployments_log_file.json:10542-10543
Timestamp: 2024-11-21T08:17:27.878Z
Learning: When reviewing deployment timestamps in `deployments/_deployments_log_file.json`, ensure that the timestamps are accurately compared with the current date to avoid incorrectly flagging valid timestamps as future deployment dates.
Learnt from: mirooon
PR: lifinance/contracts#1170
File: deployments/_deployments_log_file.json:28060-28072
Timestamp: 2025-05-28T17:33:33.959Z
Learning: Deployment log files like `deployments/_deployments_log_file.json` are historical records that document the actual versions deployed at specific times. They should not be updated to match current contract versions - they must accurately reflect what was deployed when the deployment occurred.
Learnt from: ezynda3
PR: lifinance/contracts#914
File: deployments/_deployments_log_file.json:26902-26916
Timestamp: 2025-01-09T04:17:46.190Z
Learning: Updates to _deployments_log_file.json can represent backfilling of historical deployment data, not just new deployments. Such updates don't require new audits.
Learnt from: mirooon
PR: lifinance/contracts#1170
File: deployments/_deployments_log_file.json:28706-28717
Timestamp: 2025-05-28T17:33:10.529Z
Learning: Deployment log files (like `_deployments_log_file.json`) are historical records that should not be updated to match current contract versions. They should accurately reflect the versions that were actually deployed at specific timestamps.
Learnt from: mirooon
PR: lifinance/contracts#1283
File: deployments/ronin.diamond.json:65-68
Timestamp: 2025-08-07T10:20:01.383Z
Learning: When analyzing deployment PRs in the lifinance/contracts repository, carefully verify that target state configuration files (like script/deploy/_targetState.json) and deployment log files have been updated before flagging missing entries. The AI summary section should be consulted to understand all file changes, as manual searches might miss entries due to formatting differences or search limitations.
Learnt from: 0xDEnYO
PR: lifinance/contracts#812
File: deployments/_deployments_log_file.json:1914-1927
Timestamp: 2024-09-30T03:52:27.281Z
Learning: Duplicate entries in `deployments/_deployments_log_file.json` that are outdated do not require changes.
Learnt from: 0xDEnYO
PR: lifinance/contracts#812
File: deployments/_deployments_log_file.json:1914-1927
Timestamp: 2024-10-09T03:47:21.269Z
Learning: Duplicate entries in `deployments/_deployments_log_file.json` that are outdated do not require changes.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (3)
docs/EcoFacet.md (1)

152-154: Use unambiguous chain identifiers in /quote examples (prefer numeric IDs 10 = Optimism, 8453 = Base)

Replace non-standard slugs OPT/BAS with chain IDs to avoid drift.

-```shell
-curl 'https://li.quest/v1/quote?fromChain=OPT&fromAmount=5000000&fromToken=USDC&toChain=BAS&toToken=USDC&slippage=0.03&allowBridges=eco&fromAddress={YOUR_WALLET_ADDRESS}'
-```
+```shell
+curl 'https://li.quest/v1/quote?fromChain=10&fromAmount=5000000&fromToken=USDC&toChain=8453&toToken=USDC&slippage=0.03&allowBridges=eco&fromAddress={YOUR_WALLET_ADDRESS}'
+```
@@
-```shell
-curl 'https://li.quest/v1/quote?fromChain=OPT&fromAmount=5000000&fromToken=USDT&toChain=BAS&toToken=USDC&slippage=0.03&allowBridges=eco&fromAddress={YOUR_WALLET_ADDRESS}'
-```
+```shell
+curl 'https://li.quest/v1/quote?fromChain=10&fromAmount=5000000&fromToken=USDT&toChain=8453&toToken=USDC&slippage=0.03&allowBridges=eco&fromAddress={YOUR_WALLET_ADDRESS}'
+```

Also applies to: 160-162

deployments/_deployments_log_file.json (1)

43049-43061: Verify verification status, address/args integrity, and field types for EcoFacet record

  • VERIFIED is "false" (string). If the contract is now verified (per prior thread), flip to true and keep type consistent with the rest of this file. Also prefer consistent timestamp format across entries.
  • Sanity-check ADDRESS checksum and that CONSTRUCTOR_ARGS encodes the configured Eco portal address for optimism.
  • Confirm this address is referenced in optimism staging facet/diamond JSONs.

Run this script from repo root:

#!/bin/bash
set -euo pipefail

LOG=deployments/_deployments_log_file.json

echo "1) Extract EcoFacet optimism staging 1.0.0 record"
jq -r '.EcoFacet.optimism.staging["1.0.0"][0]' "$LOG"

echo -e "\n2) Check VERIFIED field type consistency across file"
echo "Types found for VERIFIED:"
jq -r '
  paths(strings) as $p
  | getpath($p) as $v
  | if ($p|tostring|test("VERIFIED$")) then (type) else empty end
' "$LOG" | sort -u

echo -e "\n3) Validate checksum casing of ADDRESS and constructor arg encoding"
python - << 'PY'
import json, sys, re
from pathlib import Path
try:
    from eth_utils import to_checksum_address
except ImportError:
    print("Installing eth_utils...", file=sys.stderr)
    import subprocess; subprocess.check_call([sys.executable, "-m", "pip", "install", "eth_utils"], stdout=subprocess.DEVNULL)
    from eth_utils import to_checksum_address

log = json.loads(Path("deployments/_deployments_log_file.json").read_text())
rec = log["EcoFacet"]["optimism"]["staging"]["1.0.0"][0]
addr = rec["ADDRESS"]
args = rec["CONSTRUCTOR_ARGS"]

def tail20(hexstr):
    s = hexstr.lower().removeprefix("0x")
    return "0x"+s[-40:]

ok_checksum = (addr == to_checksum_address(addr))
print(f"ADDRESS: {addr}")
print(f"Checksum valid/cased: {ok_checksum}")

# Extract last 20 bytes of constructor args
arg_tail = tail20(args)
print(f"Constructor arg tail (address-encoded): {arg_tail}")

# Try to locate the same address in config/eco.json
import subprocess, json as js
try:
    cfg = js.loads(Path("config/eco.json").read_text())
    # naive scan for values equal to arg_tail (case-insensitive)
    found = []

    def walk(o, path=""):
        if isinstance(o, dict):
            for k,v in o.items(): walk(v, f"{path}/{k}")
        elif isinstance(o, list):
            for i,v in enumerate(o): walk(v, f"{path}[{i}]")
        elif isinstance(o, str):
            if o.lower() == arg_tail.lower():
                found.append(path)
    walk(cfg)
    print(f"Portal address matches in config/eco.json at paths: {found if found else 'NOT FOUND'}")
except FileNotFoundError:
    print("config/eco.json not found; please verify manually.")
PY

echo -e "\n4) Ensure the facet address is referenced in optimism staging facet/diamond files"
echo "Matches in deployments/*optimism*staging*.json:"
rg -n -C2 -i 'EcoFacet|0xA64C0263B1a37B3241Da01046134b7707D39f00b' deployments | sed -n '1,120p'

Based on learnings

script/demoScripts/demoEco.ts (1)

519-524: Non‑EVM receiver encoding for Solana (ack prior)

The TextEncoder approach encodes base58 chars, not raw pubkey bytes. This was discussed earlier; if you revisit, consider bs58.decode for Solana only. Otherwise, current variable-length policy is acceptable here.

🧹 Nitpick comments (9)
docs/EcoFacet.md (3)

107-107: Make link text descriptive (MD059)
Replace “here” with meaningful text.

-The swap library can be found [here](../src/Libraries/LibSwap.sol).
+See the LibSwap library source (../src/Libraries/LibSwap.sol).
@@
-… can be found [here](../src/Interfaces/ILiFi.sol).
+… see ILiFi interface and events (../src/Interfaces/ILiFi.sol).
@@
-… can be found [here](https://docs.li.fi/products/more-integration-options/li.fi-api/transferring-tokens-example).
+… see Transferring tokens with the LiFi API (https://docs.li.fi/products/more-integration-options/li.fi-api/transferring-tokens-example).

Also applies to: 113-113, 144-144


75-84: Clarify native bridging vs swap-from-native
State that native token as the bridge asset is unsupported, but swapping from native to ERC20 before bridging is supported (set msg.value to swapData[0].fromAmount).

Based on learnings

-**Native Token Bridging**: The EcoFacet contract does not support native token bridging. Only ERC20 token transfers are supported. Transactions will revert if native tokens are specified as the sending asset.
+**Native Token Bridging**: Bridging a native token directly is not supported and will revert. Only ERC20 tokens can be bridged.
+However, you may swap from a native token to the ERC20 bridge token in the same transaction (set `msg.value = _swapData[0].fromAmount` when the swap input is native).

54-57: Specify Solana address encoding precisely
Use “base58-decoded 32-byte public key,” not “base58 address encoded as bytes” to avoid ambiguity.

-Provide the Solana address in `nonEVMReceiver` as bytes (base58 address encoded as bytes)
+Provide the Solana address in `nonEVMReceiver` as the base58‑decoded 32‑byte public key (bytes)
script/demoScripts/demoEco.ts (3)

106-114: Use getEnvVar() and consola for env + logging per script standards

Replace direct process.env and console.* with repo helpers/logging.

Apply:

+import consola from 'consola'
+// If your repo exposes getEnvVar, import from its utils module:
+// import { getEnvVar } from '../utils/utils' // adjust path to your utils
@@
-const ECO_API_URL = process.env.ECO_API_URL || 'https://quotes.eco.com'
-const DAPP_ID = process.env.ECO_DAPP_ID || 'lifi-demo'
+const ECO_API_URL = (typeof getEnvVar === 'function' ? getEnvVar('ECO_API_URL', false) : process.env.ECO_API_URL) || 'https://quotes.eco.com'
+const DAPP_ID = (typeof getEnvVar === 'function' ? getEnvVar('ECO_DAPP_ID', false) : process.env.ECO_DAPP_ID) || 'lifi-demo'
-
-console.log('Eco API Configuration:')
-console.log('  API URL:', ECO_API_URL)
-console.log('  DAPP ID:', DAPP_ID)
-console.log('  Set ECO_API_URL and ECO_DAPP_ID env vars to override defaults\n')
+consola.info('Eco API Configuration:')
+consola.info('  API URL:', ECO_API_URL)
+consola.info('  DAPP ID:', DAPP_ID)
+consola.info('  Set ECO_API_URL and ECO_DAPP_ID env vars to override defaults\n')

Based on coding guidelines.


311-354: Switch API-call logs to consola and keep error paths consistent

Use consola for uniform logging in scripts.

-  console.log('Fetching quote from Eco API...')
-  console.log('Quote request:', JSON.stringify(quoteRequest, null, 2))
+  consola.info('Fetching quote from Eco API...')
+  consola.info('Quote request:', JSON.stringify(quoteRequest, null, 2))
@@
-  console.log('Quote received:', JSON.stringify(data, null, 2))
+  consola.info('Quote received:', JSON.stringify(data, null, 2))
@@
-    console.error('API returned error:', data.error)
+    consola.error('API returned error:', data.error)
@@
-    console.error('Invalid quote response structure.')
-    console.error('Expected structure with data.quoteResponse, but got:', data)
+    consola.error('Invalid quote response structure.')
+    consola.error('Expected structure with data.quoteResponse, but got:', data)

Based on coding guidelines.


376-382: Replace remaining console. in main() with consola for consistency*

Use consola.info/log/error across main(); keep messages identical. This aligns with repo logging standards and avoids mixed logging sinks.

Based on coding guidelines.

Also applies to: 599-621, 632-655

src/Facets/EcoFacet.sol (2)

24-26: Prefer constant over immutable for compile-time chain IDs

These values are known at compile time; using constant slightly reduces bytecode/gas.

-    uint64 private immutable ECO_CHAIN_ID_TRON = 728126428;
-    uint64 private immutable ECO_CHAIN_ID_SOLANA = 1399811149;
+    uint64 private constant ECO_CHAIN_ID_TRON = 728126428;
+    uint64 private constant ECO_CHAIN_ID_SOLANA = 1399811149;

122-130: Clarify native-token note in docstring

Native bridging is disabled via noNativeAsset; the “Native tokens handle positive slippage...” line can confuse readers. Clarify it refers to potential future native support or swap input ETH only.

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

29-31: Use a mock IEcoPortal and assert publishAndFund inputs

Pointing PORTAL to a hard-coded address on a fork can lead to false positives (EOA/no-code calls “succeed”). Replace with a mock that records args or add vm.expectCall to assert destination, encodedRoute, reward.tokens[0], and allowPartial.

As a follow-up, I can provide a minimal MockEcoPortal that captures the last call and exposes getters for assertions.

Also applies to: 50-67, 380-387

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 68e1008 and a391b5a.

📒 Files selected for processing (8)
  • config/eco.json (1 hunks)
  • deployments/_deployments_log_file.json (1 hunks)
  • deployments/optimism.diamond.staging.json (5 hunks)
  • deployments/optimism.staging.json (1 hunks)
  • docs/EcoFacet.md (1 hunks)
  • script/demoScripts/demoEco.ts (1 hunks)
  • src/Facets/EcoFacet.sol (1 hunks)
  • test/solidity/Facets/EcoFacet.t.sol (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • deployments/optimism.staging.json
  • deployments/optimism.diamond.staging.json
🧰 Additional context used
📓 Path-based instructions (7)
{src,test/solidity,script}/**/*.sol

📄 CodeRabbit inference engine (conventions.md)

{src,test/solidity,script}/**/*.sol: All Solidity files must start with a license identifier, followed by a blank line, then the pragma statement
Use SPDX license identifier // SPDX-License-Identifier: LGPL-3.0-only for all first-party Solidity files
Error names must be descriptive PascalCase, use custom errors instead of revert() strings, and omit error messages for gas optimization
Solidity variable/function naming: state variables camelCase; function params camelCase with leading underscore; constants and immutables in CONSTANT_CASE; private/internal variables camelCase; function names camelCase

Files:

  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
src/**/*.sol

📄 CodeRabbit inference engine (conventions.md)

src/**/*.sol: Every contract must include NatSpec header in this order: @title, @author LI.FI (https://li.fi), @notice, @Custom:version X.Y.Z
All public/external functions must have NatSpec comments documenting purpose, params, and returns
Add inline comments for complex logic, optimizations, gas-saving techniques, and math steps
Emit GenericSwapCompleted after successful same-chain swap completion

Files:

  • src/Facets/EcoFacet.sol
src/Facets/**/*Facet.sol

📄 CodeRabbit inference engine (conventions.md)

src/Facets/**/*Facet.sol: Facet contracts must be located in src/Facets and include "Facet" in the contract name
Facet contracts must implement: internal _startBridge, swapAndStartBridgeTokensVia{FacetName}, and startBridgeTokensVia{FacetName}
Facet contracts must import/use: ILiFi, LibAsset, LibSwap, LibAllowList; and use security mixins ReentrancyGuard, SwapperV2, Validatable; ECDSA optional
Do not use msg.sender as refund address; require an explicit parameter for refund address
In {facetName}Data, receiverAddress must be the first field and be validated against bridgeData.receiver; verify targetChainId equals bridgeData.destinationChain for EVM-to-EVM
Apply required modifiers where appropriate: nonReentrant, refundExcessNative, validateBridgeData, doesNotContainSourceSwaps/doesContainSourceSwaps, doesNotContainDestinationCalls/doesContainDestinationCalls
Emit LiFiTransferStarted at the start of a transaction before external calls; do not emit LiFiTransferCompleted or LiFiTransferRecovered in facets
For native fees in facets, use the _depositAndSwap variant and reserve required fees before execution
For non-EVM chains: receiverAddress must be bytes (not bytes32), must not be zero, and bridgeData.receiver must equal NON_EVM_ADDRESS

Files:

  • src/Facets/EcoFacet.sol
**/*.sol

📄 CodeRabbit inference engine (conventions.md)

Follow solhint rules as configured in .solhint.json

Files:

  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
test/solidity/**/*.t.sol

📄 CodeRabbit inference engine (conventions.md)

test/solidity/**/*.t.sol: Solidity test files must use .t.sol extension; organize imports with system libraries first, then project files
Test naming: successful tests prefixed test_, failure tests prefixed testRevert_, base/inherited tests prefixed testBase_; negative tests must check specific revert reasons
Each test contract must implement setUp() that configures block numbers, initializes base contracts, sets up facets, and uses vm.label; contracts inheriting TestBase.sol must call initTestBase() in setUp()
Use vm.startPrank()/vm.stopPrank() for user simulation; maintain blank-line formatting rules for tests (expectRevert separation, assertion grouping, spacing)
Use assertEq for equality, custom assertion modifiers for balance changes, vm.expectRevert with precise reasons, and vm.expectEmit(true,true,true,true,) to verify events and parameters

Files:

  • test/solidity/Facets/EcoFacet.t.sol
script/**/*.ts

📄 CodeRabbit inference engine (conventions.md)

script/**/*.ts: All TypeScript scripts must follow .eslintrc.cjs, use async/await, try/catch error handling, proper logging, environment variables, correct typings, use citty for CLI parsing, consola for logging, validate env vars via getEnvVar(), and exit with appropriate codes
Prefer existing helper functions over reimplementation (e.g., getDeployments, getProvider, getWalletFromPrivateKeyInDotEnv, sendTransaction, ensureBalanceAndAllowanceToDiamond, getUniswapData*)
Always use proper TypeChain types (e.g., ILiFi.BridgeDataStruct) and never use any for bridge data or contract structures
Before/after changes: verify imports and types exist, ensure typechain is generated, keep changes comprehensive and consistent, run TS compilation, remove unused imports, and ensure function signatures match usage
Scripts must execute with bunx tsx

Files:

  • script/demoScripts/demoEco.ts
{README.md,Deploy.md,docs/**}

📄 CodeRabbit inference engine (conventions.md)

Keep primary documentation up to date: README.md (overview/setup), Deploy.md (deployment), and docs/ (technical docs)

Files:

  • docs/EcoFacet.md
🧠 Learnings (39)
📚 Learning: 2025-04-21T03:17:53.443Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1109
File: deployments/worldchain.json:28-28
Timestamp: 2025-04-21T03:17:53.443Z
Learning: For deployment PRs updating contract addresses (like RelayFacet on Worldchain), verify the presence of entries in all relevant files (worldchain.json, worldchain.diamond.json, _deployments_log_file.json) before reporting inconsistencies. The RelayFacet entry exists in all required deployment files with the correct address.

Applied to files:

  • config/eco.json
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to src/Facets/**/*Facet.sol : Facet contracts must implement: internal _startBridge, swapAndStartBridgeTokensVia{FacetName}, and startBridgeTokensVia{FacetName}

Applied to files:

  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
  • docs/EcoFacet.md
📚 Learning: 2025-09-25T07:47:30.735Z
Learnt from: ezynda3
PR: lifinance/contracts#1324
File: src/Facets/EcoFacet.sol:306-336
Timestamp: 2025-09-25T07:47:30.735Z
Learning: In EcoFacet (src/Facets/EcoFacet.sol), the team intentionally uses variable-length validation for nonEVMReceiver addresses (up to 44 bytes) to support cross-ecosystem bridging with different address formats, rather than enforcing fixed 32-byte raw pubkeys.

Applied to files:

  • src/Facets/EcoFacet.sol
  • script/demoScripts/demoEco.ts
📚 Learning: 2025-07-16T01:04:55.857Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1275
File: src/Facets/AllBridgeFacet.sol:186-188
Timestamp: 2025-07-16T01:04:55.857Z
Learning: In LiFi facet contracts, when public entry point functions have `nonReentrant` modifier protection, internal functions like `_startBridge` that they call benefit from this reentrancy protection, making event emission order after external calls acceptable from a security perspective.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-08-27T22:23:51.257Z
Learnt from: mirooon
PR: lifinance/contracts#1328
File: src/Periphery/Lda/Facets/NativeWrapperFacet.sol:0-0
Timestamp: 2025-08-27T22:23:51.257Z
Learning: In src/Periphery/Lda/Facets/NativeWrapperFacet.sol, the wrapNative function should not validate msg.value == amountIn because CoreRouteFacet's DistributeNative command (command type 3) overrides the amountIn parameter with address(this).balance, making such validation incorrect and causing false failures.

Applied to files:

  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-16T01:03:08.106Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1275
File: src/Facets/AllBridgeFacet.sol:164-164
Timestamp: 2025-07-16T01:03:08.106Z
Learning: In src/Facets/AllBridgeFacet.sol, the team has decided that explicit validation for address downcasting from `_bridgeData.sendingAssetId` to `bytes32(uint256(uint160(_bridgeData.sendingAssetId)))` is not required, accepting the potential risk of silent overflow from unsafe downcasting.

Applied to files:

  • src/Facets/EcoFacet.sol
  • script/demoScripts/demoEco.ts
📚 Learning: 2025-09-19T14:10:55.064Z
Learnt from: ezynda3
PR: lifinance/contracts#1324
File: src/Facets/EcoFacet.sol:68-71
Timestamp: 2025-09-19T14:10:55.064Z
Learning: In src/Facets/EcoFacet.sol, the team prefers to use msg.sender as the refund address for native tokens in the refundExcessNative modifier, contrary to the general guideline of requiring explicit refund parameters.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to src/Facets/**/*Facet.sol : Do not use msg.sender as refund address; require an explicit parameter for refund address

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to src/Facets/**/*Facet.sol : Apply required modifiers where appropriate: nonReentrant, refundExcessNative, validateBridgeData, doesNotContainSourceSwaps/doesContainSourceSwaps, doesNotContainDestinationCalls/doesContainDestinationCalls

Applied to files:

  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to src/Facets/**/*Facet.sol : In {facetName}Data, receiverAddress must be the first field and be validated against bridgeData.receiver; verify targetChainId equals bridgeData.destinationChain for EVM-to-EVM

Applied to files:

  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to src/Facets/**/*Facet.sol : For non-EVM chains: receiverAddress must be bytes (not bytes32), must not be zero, and bridgeData.receiver must equal NON_EVM_ADDRESS

Applied to files:

  • src/Facets/EcoFacet.sol
  • docs/EcoFacet.md
📚 Learning: 2025-10-02T18:10:09.934Z
Learnt from: mirooon
PR: lifinance/contracts#1406
File: src/Facets/UnitFacet.sol:75-81
Timestamp: 2025-10-02T18:10:09.934Z
Learning: In UnitFacet.sol and similar facet contracts in src/Facets/, the LiFiTransferStarted event emission should ALWAYS be at the end of the _startBridge internal function, after all validations and asset transfers have been completed successfully.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to src/Facets/**/*Facet.sol : Emit LiFiTransferStarted at the start of a transaction before external calls; do not emit LiFiTransferCompleted or LiFiTransferRecovered in facets

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2024-10-31T09:09:38.568Z
Learnt from: ezynda3
PR: lifinance/contracts#843
File: src/Facets/RelayFacet.sol:165-170
Timestamp: 2024-10-31T09:09:38.568Z
Learning: In the `RelayFacet` contract (`src/Facets/RelayFacet.sol`), within the `_startBridge` function, low-level `call` is intentionally used to transfer tokens so that extra bytes can be added to the calldata, as required for integrating with Relay Protocol.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2024-10-09T03:47:21.269Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: src/Periphery/Permit2Proxy.sol:75-108
Timestamp: 2024-10-09T03:47:21.269Z
Learning: In the `Permit2Proxy` contract (`src/Periphery/Permit2Proxy.sol`), reentrancy protection is not necessary for functions like `callDiamondWithEIP2612Signature` when calling our own trusted diamond contract (`LIFI_DIAMOND`).

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-08-27T13:51:52.704Z
Learnt from: mirooon
PR: lifinance/contracts#1328
File: src/Periphery/Lda/Facets/NativeWrapperFacet.sol:33-0
Timestamp: 2025-08-27T13:51:52.704Z
Learning: In LDA facets like NativeWrapperFacet, mirooon prefers to rely on CoreRouteFacet's upstream validation for parameters like `from` rather than adding defensive validation checks in individual facets, since CoreRouteFacet ensures only valid values (msg.sender, address(this), or INTERNAL_INPUT_SOURCE) are passed to the facets.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-09-25T00:12:58.536Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1395
File: src/Periphery/FeeForwarder.sol:78-120
Timestamp: 2025-09-25T00:12:58.536Z
Learning: In src/Periphery/FeeForwarder.sol, the team intentionally uses address(this).balance for refunding remaining native tokens because the contract is designed to never hold funds and not collect dust, making it safe to return the entire balance to the caller.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-09-25T07:48:53.243Z
Learnt from: ezynda3
PR: lifinance/contracts#1324
File: src/Facets/EcoFacet.sol:280-303
Timestamp: 2025-09-25T07:48:53.243Z
Learning: In src/Facets/EcoFacet.sol, the team prefers to allow natural Solidity reverts (array bounds, insufficient data) in route validation rather than adding explicit guards with custom errors, as the reverts achieve the same security outcome while keeping code simpler.

Applied to files:

  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to src/Facets/**/*Facet.sol : Facet contracts must import/use: ILiFi, LibAsset, LibSwap, LibAllowList; and use security mixins ReentrancyGuard, SwapperV2, Validatable; ECDSA optional

Applied to files:

  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-02-21T09:00:28.226Z
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Facets/ChainflipFacet.sol:127-146
Timestamp: 2025-02-21T09:00:28.226Z
Learning: The `validateBridgeData` modifier in `Validatable.sol` already validates that the receiver address is not zero, making additional zero-address checks redundant in functions using this modifier.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-02-21T09:00:28.226Z
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Facets/ChainflipFacet.sol:127-146
Timestamp: 2025-02-21T09:00:28.226Z
Learning: The `validateBridgeData` modifier in `Validatable.sol` validates that the receiver address is not zero using `LibUtil.isZeroAddress`, making additional zero-address checks redundant in functions using this modifier.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2024-11-22T08:49:35.205Z
Learnt from: ezynda3
PR: lifinance/contracts#827
File: src/Facets/DeBridgeDlnFacet.sol:0-0
Timestamp: 2024-11-22T08:49:35.205Z
Learning: In `DeBridgeDlnFacet.sol`, direct access to the `deBridgeChainId` mapping is acceptable, and using the `getDeBridgeChainId` function is not necessary in these instances.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-09-30T12:00:56.667Z
Learnt from: ezynda3
PR: lifinance/contracts#1324
File: src/Facets/EcoFacet.sol:1-1
Timestamp: 2025-09-30T12:00:56.667Z
Learning: In the lifinance/contracts repository, audit logging is handled manually by the team, and merging is automatically restricted until an audit has been logged. Missing audit entries in auditLog.json should not be flagged as critical blocking issues during review, as the team has process controls in place to prevent merging without proper audits.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2024-12-12T02:22:38.502Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#902
File: .github/workflows/forceMergePRBypassAudit.yml:0-0
Timestamp: 2024-12-12T02:22:38.502Z
Learning: Only the CTO and Security Architect can use the force-merge PR bypass audit action, and it will be documented and communicated to prevent unauthorized use.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-09-09T10:39:26.383Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1357
File: deployments/lens.diamond.json:48-51
Timestamp: 2025-09-09T10:39:26.383Z
Learning: In the lifinance/contracts repository, when deployment JSON files show address changes (like AcrossFacetV3 address updates in deployments/*.diamond.json), the corresponding _deployments_log_file.json updates may be handled in separate PRs rather than the same PR that updates the diamond configuration files.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2025-09-15T12:33:51.069Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1377
File: deployments/_deployments_log_file.json:5607-5619
Timestamp: 2025-09-15T12:33:51.069Z
Learning: The deployments/_deployments_log_file.json is structured as network → environment → version → array of deployment records. Always understand the file hierarchy before attempting validation, and target specific paths rather than trying to validate all objects in the JSON.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2025-01-16T00:24:10.002Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#927
File: foundry.toml:78-78
Timestamp: 2025-01-16T00:24:10.002Z
Learning: Avalanche chain (chainid=43114) is supported by Etherscan V2 API and can use the endpoint https://api.etherscan.io/v2/api?chainid=43114 instead of Snowtrace.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2024-10-22T03:16:28.754Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: test/solidity/Facets/GasZipFacet.t.sol:212-213
Timestamp: 2024-10-22T03:16:28.754Z
Learning: In the `GasZipFacetTest`, for the test case `testBase_Revert_SwapAndBridgeWithInvalidSwapData()`, a generic revert is expected, so `vm.expectRevert();` without specifying the expected error is appropriate.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-10T03:26:23.793Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: test/solidity/Helpers/WithdrawablePeriphery.t.sol:79-80
Timestamp: 2024-10-10T03:26:23.793Z
Learning: In Solidity tests, it's acceptable to use `UnAuthorized.selector` in `vm.expectRevert()`; avoid suggesting changing it to string messages.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-22T03:24:24.705Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: test/solidity/Facets/GasZipFacet.t.sol:337-339
Timestamp: 2024-10-22T03:24:24.705Z
Learning: In `GasZipFacet` tests, when expecting a failure due to insufficient balance for sending value, the test should expect a generic revert without specifying a specific error.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to test/solidity/**/*.t.sol : Test naming: successful tests prefixed test_, failure tests prefixed testRevert_, base/inherited tests prefixed testBase_; negative tests must check specific revert reasons

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-09-16T07:56:45.093Z
Learnt from: ezynda3
PR: lifinance/contracts#1324
File: test/solidity/Facets/EcoFacet.t.sol:135-141
Timestamp: 2025-09-16T07:56:45.093Z
Learning: In EcoFacet test setup, the isNative parameter in swap-and-bridge flows refers to the bridge token type (output), not the swap input type. The ERC20 branch (isNative=false) can still swap from native ETH to ERC20 tokens, requiring msg.value = swapData[0].fromAmount for the ETH input to the swap.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
  • docs/EcoFacet.md
📚 Learning: 2025-08-27T23:36:40.773Z
Learnt from: mirooon
PR: lifinance/contracts#1328
File: test/solidity/Periphery/GasZipPeriphery.t.sol:223-233
Timestamp: 2025-08-27T23:36:40.773Z
Learning: In bridge facet swap flows with requiresDeposit=false, tokens are already held by the diamond contract from previous swaps. When subsequent contracts like GasZipPeriphery call LibAsset.depositAsset, they pull tokens from msg.sender (the diamond) to themselves via transferFrom, requiring no additional approvals since the diamond already owns the tokens.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-08-29T11:07:57.743Z
Learnt from: mirooon
PR: lifinance/contracts#1328
File: src/Periphery/LDA/Facets/CurveFacet.sol:87-91
Timestamp: 2025-08-29T11:07:57.743Z
Learning: In src/Periphery/LDA/Facets/CurveFacet.sol, modern Curve pools (isV2=true, representing V2/NG pools) should reject native tokenIn by adding an early revert check when LibAsset.isNativeAsset(tokenIn) is true, since ICurveV2 exchange functions are non-payable and cannot accept native ETH.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to script/**/*.ts : Prefer existing helper functions over reimplementation (e.g., getDeployments, getProvider, getWalletFromPrivateKeyInDotEnv, sendTransaction, ensureBalanceAndAllowanceToDiamond, getUniswapData*)

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2025-08-19T05:10:12.922Z
Learnt from: ezynda3
PR: lifinance/contracts#1303
File: script/utils/network.ts:27-32
Timestamp: 2025-08-19T05:10:12.922Z
Learning: In the lifinance/contracts repository, the team decided to standardize RPC environment variable naming by converting all hyphens to underscores in network names. For example, "tron-shasta" becomes "ETH_NODE_URI_TRON_SHASTA". The getRPCEnvVarName() helper in script/utils/network.ts implements this standard and should be used consistently across the codebase instead of direct string manipulation.

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to script/**/*.ts : Always use proper TypeChain types (e.g., ILiFi.BridgeDataStruct) and never use any for bridge data or contract structures

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2025-05-27T16:19:16.726Z
Learnt from: mirooon
PR: lifinance/contracts#1165
File: src/Facets/GnosisBridgeFacet.sol:22-22
Timestamp: 2025-05-27T16:19:16.726Z
Learning: The correct USDS token address on Ethereum mainnet is 0xdC035D45d973E3EC169d2276DDab16f1e407384F, not 0xA4Bdb11dc0a2bEC88d24A3aa1E6Bb17201112eBe.

Applied to files:

  • script/demoScripts/demoEco.ts
📚 Learning: 2025-08-19T05:07:19.448Z
Learnt from: ezynda3
PR: lifinance/contracts#1303
File: script/deploy/tron/utils.ts:3-5
Timestamp: 2025-08-19T05:07:19.448Z
Learning: In the lifinance/contracts repository, consola and TronWeb should be imported as named exports: `import { consola } from 'consola'` and `import { TronWeb } from 'tronweb'`. Do not flag these as incorrect default export usage.

Applied to files:

  • script/demoScripts/demoEco.ts
🧬 Code graph analysis (1)
script/demoScripts/demoEco.ts (2)
script/demoScripts/utils/demoScriptHelpers.ts (21)
  • ADDRESS_USDC_OPT (61-61)
  • ADDRESS_USDC_BASE (75-75)
  • ADDRESS_USDC_ARB (63-63)
  • ADDRESS_USDC_ETH (57-57)
  • ADDRESS_USDC_POL (59-59)
  • ADDRESS_USDC_SOL (67-67)
  • ADDRESS_WETH_OPT (70-70)
  • ADDRESS_WETH_BASE (73-73)
  • ADDRESS_WETH_ARB (72-72)
  • ADDRESS_WETH_ETH (69-69)
  • ADDRESS_WETH_POL (71-71)
  • ADDRESS_UNISWAP_OPT (81-81)
  • ADDRESS_UNISWAP_BASE (83-83)
  • ADDRESS_UNISWAP_ARB (82-82)
  • ADDRESS_UNISWAP_ETH (78-78)
  • ADDRESS_UNISWAP_POL (80-80)
  • setupEnvironment (653-707)
  • getUniswapDataERC20toExactERC20 (334-406)
  • ensureBalance (846-867)
  • ensureAllowance (872-906)
  • executeTransaction (805-841)
script/common/types.ts (1)
  • SupportedChain (3-3)
🪛 markdownlint-cli2 (0.18.1)
docs/EcoFacet.md

107-107: Link text should be descriptive

(MD059, descriptive-link-text)


113-113: Link text should be descriptive

(MD059, descriptive-link-text)


144-144: Link text should be descriptive

(MD059, descriptive-link-text)

🔇 Additional comments (4)
config/eco.json (2)

29-31: TRON entry uses an EVM-style address — confirm intent

If TRON is only a destination (not a source chain running the facet), a portal address here may be unused. If it is used, confirm Eco Portal exists on TRON and that 0x399D…e97 is valid on TRON’s addressing scheme.


2-31: Ignore identical portal address across networks
This CREATE2 deployment yields the same portal address on each chain by design. No changes needed.

Likely an incorrect or invalid review comment.

docs/EcoFacet.md (1)

97-100: Chain ID mappings verified
Constants in EcoFacet.sol (ECO_CHAIN_ID_TRON = 728126428, ECO_CHAIN_ID_SOLANA = 1399811149) match the documentation and IEcoPortal interface usage.

src/Facets/EcoFacet.sol (1)

213-229: Event order and unused return are acceptable here

Emitting after external call and not checking publishAndFund’s return is an intentional choice with nonReentrant protection and portal semantics.

Based on learnings.

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

♻️ Duplicate comments (1)
deployments/optimism.diamond.staging.json (1)

148-187: Duplicate AcrossFacet entries remain — resolve ambiguity.

There are still duplicate facet entries with identical Name and Version at different addresses:

  1. AcrossFacetPackedV4 1.0.0:

    • 0x8962d191Ba0f2Bc29b949ACA222f8251B241190b (Line 148)
    • 0xf536ed5A4310455FF39dBf90336e17d11550E7b4 (Line 180)
  2. AcrossFacetV4 1.0.0:

    • 0xc2A0D799744536C621Af9B2933CdB4Ad959980bF (Line 164)
    • 0x91559A75bd9045681265C77922b3cAeDB3D5120d (Line 176)

Per previous feedback, EcoFacet duplicates were marked as "removed" but these AcrossFacet duplicates persist. Deployment tooling that selects facets by Name/Version cannot disambiguate between these entries.

Recommended action: For each duplicate pair, identify the correct/active deployment address and remove the obsolete entry, or suffix the Name field of inactive entries (e.g., "AcrossFacetV4_Deprecated") to disambiguate.

Based on learnings.

🧹 Nitpick comments (1)
docs/EcoFacet.md (1)

105-142: Replace “here” links with descriptive text.

Multiple instances link the word “here,” which hurts accessibility and was flagged by markdownlint (MD059). Please rewrite the link text to describe the destination (e.g., “LibSwap library”).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a391b5a and 1bc03bc.

📒 Files selected for processing (7)
  • deployments/_deployments_log_file.json (1 hunks)
  • deployments/optimism.diamond.staging.json (5 hunks)
  • deployments/optimism.staging.json (1 hunks)
  • docs/EcoFacet.md (1 hunks)
  • script/demoScripts/demoEco.ts (1 hunks)
  • src/Facets/EcoFacet.sol (1 hunks)
  • test/solidity/Facets/EcoFacet.t.sol (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • script/demoScripts/demoEco.ts
🧰 Additional context used
📓 Path-based instructions (6)
{src,test/solidity,script}/**/*.sol

📄 CodeRabbit inference engine (conventions.md)

{src,test/solidity,script}/**/*.sol: All Solidity files must start with a license identifier, followed by a blank line, then the pragma statement
Use SPDX license identifier // SPDX-License-Identifier: LGPL-3.0-only for all first-party Solidity files
Error names must be descriptive PascalCase, use custom errors instead of revert() strings, and omit error messages for gas optimization
Solidity variable/function naming: state variables camelCase; function params camelCase with leading underscore; constants and immutables in CONSTANT_CASE; private/internal variables camelCase; function names camelCase

Files:

  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
src/**/*.sol

📄 CodeRabbit inference engine (conventions.md)

src/**/*.sol: Every contract must include NatSpec header in this order: @title, @author LI.FI (https://li.fi), @notice, @Custom:version X.Y.Z
All public/external functions must have NatSpec comments documenting purpose, params, and returns
Add inline comments for complex logic, optimizations, gas-saving techniques, and math steps
Emit GenericSwapCompleted after successful same-chain swap completion

Files:

  • src/Facets/EcoFacet.sol
src/Facets/**/*Facet.sol

📄 CodeRabbit inference engine (conventions.md)

src/Facets/**/*Facet.sol: Facet contracts must be located in src/Facets and include "Facet" in the contract name
Facet contracts must implement: internal _startBridge, swapAndStartBridgeTokensVia{FacetName}, and startBridgeTokensVia{FacetName}
Facet contracts must import/use: ILiFi, LibAsset, LibSwap, LibAllowList; and use security mixins ReentrancyGuard, SwapperV2, Validatable; ECDSA optional
Do not use msg.sender as refund address; require an explicit parameter for refund address
In {facetName}Data, receiverAddress must be the first field and be validated against bridgeData.receiver; verify targetChainId equals bridgeData.destinationChain for EVM-to-EVM
Apply required modifiers where appropriate: nonReentrant, refundExcessNative, validateBridgeData, doesNotContainSourceSwaps/doesContainSourceSwaps, doesNotContainDestinationCalls/doesContainDestinationCalls
Emit LiFiTransferStarted at the start of a transaction before external calls; do not emit LiFiTransferCompleted or LiFiTransferRecovered in facets
For native fees in facets, use the _depositAndSwap variant and reserve required fees before execution
For non-EVM chains: receiverAddress must be bytes (not bytes32), must not be zero, and bridgeData.receiver must equal NON_EVM_ADDRESS

Files:

  • src/Facets/EcoFacet.sol
**/*.sol

📄 CodeRabbit inference engine (conventions.md)

Follow solhint rules as configured in .solhint.json

Files:

  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
test/solidity/**/*.t.sol

📄 CodeRabbit inference engine (conventions.md)

test/solidity/**/*.t.sol: Solidity test files must use .t.sol extension; organize imports with system libraries first, then project files
Test naming: successful tests prefixed test_, failure tests prefixed testRevert_, base/inherited tests prefixed testBase_; negative tests must check specific revert reasons
Each test contract must implement setUp() that configures block numbers, initializes base contracts, sets up facets, and uses vm.label; contracts inheriting TestBase.sol must call initTestBase() in setUp()
Use vm.startPrank()/vm.stopPrank() for user simulation; maintain blank-line formatting rules for tests (expectRevert separation, assertion grouping, spacing)
Use assertEq for equality, custom assertion modifiers for balance changes, vm.expectRevert with precise reasons, and vm.expectEmit(true,true,true,true,) to verify events and parameters

Files:

  • test/solidity/Facets/EcoFacet.t.sol
{README.md,Deploy.md,docs/**}

📄 CodeRabbit inference engine (conventions.md)

Keep primary documentation up to date: README.md (overview/setup), Deploy.md (deployment), and docs/ (technical docs)

Files:

  • docs/EcoFacet.md
🧠 Learnings (47)
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to src/Facets/**/*Facet.sol : Facet contracts must implement: internal _startBridge, swapAndStartBridgeTokensVia{FacetName}, and startBridgeTokensVia{FacetName}

Applied to files:

  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
  • docs/EcoFacet.md
📚 Learning: 2025-09-25T07:47:30.735Z
Learnt from: ezynda3
PR: lifinance/contracts#1324
File: src/Facets/EcoFacet.sol:306-336
Timestamp: 2025-09-25T07:47:30.735Z
Learning: In EcoFacet (src/Facets/EcoFacet.sol), the team intentionally uses variable-length validation for nonEVMReceiver addresses (up to 44 bytes) to support cross-ecosystem bridging with different address formats, rather than enforcing fixed 32-byte raw pubkeys.

Applied to files:

  • src/Facets/EcoFacet.sol
  • deployments/optimism.staging.json
📚 Learning: 2025-07-16T01:04:55.857Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1275
File: src/Facets/AllBridgeFacet.sol:186-188
Timestamp: 2025-07-16T01:04:55.857Z
Learning: In LiFi facet contracts, when public entry point functions have `nonReentrant` modifier protection, internal functions like `_startBridge` that they call benefit from this reentrancy protection, making event emission order after external calls acceptable from a security perspective.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-08-27T22:23:51.257Z
Learnt from: mirooon
PR: lifinance/contracts#1328
File: src/Periphery/Lda/Facets/NativeWrapperFacet.sol:0-0
Timestamp: 2025-08-27T22:23:51.257Z
Learning: In src/Periphery/Lda/Facets/NativeWrapperFacet.sol, the wrapNative function should not validate msg.value == amountIn because CoreRouteFacet's DistributeNative command (command type 3) overrides the amountIn parameter with address(this).balance, making such validation incorrect and causing false failures.

Applied to files:

  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-07-16T01:03:08.106Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1275
File: src/Facets/AllBridgeFacet.sol:164-164
Timestamp: 2025-07-16T01:03:08.106Z
Learning: In src/Facets/AllBridgeFacet.sol, the team has decided that explicit validation for address downcasting from `_bridgeData.sendingAssetId` to `bytes32(uint256(uint160(_bridgeData.sendingAssetId)))` is not required, accepting the potential risk of silent overflow from unsafe downcasting.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-09-19T14:10:55.064Z
Learnt from: ezynda3
PR: lifinance/contracts#1324
File: src/Facets/EcoFacet.sol:68-71
Timestamp: 2025-09-19T14:10:55.064Z
Learning: In src/Facets/EcoFacet.sol, the team prefers to use msg.sender as the refund address for native tokens in the refundExcessNative modifier, contrary to the general guideline of requiring explicit refund parameters.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to src/Facets/**/*Facet.sol : Do not use msg.sender as refund address; require an explicit parameter for refund address

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to src/Facets/**/*Facet.sol : Apply required modifiers where appropriate: nonReentrant, refundExcessNative, validateBridgeData, doesNotContainSourceSwaps/doesContainSourceSwaps, doesNotContainDestinationCalls/doesContainDestinationCalls

Applied to files:

  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to src/Facets/**/*Facet.sol : In {facetName}Data, receiverAddress must be the first field and be validated against bridgeData.receiver; verify targetChainId equals bridgeData.destinationChain for EVM-to-EVM

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to src/Facets/**/*Facet.sol : For non-EVM chains: receiverAddress must be bytes (not bytes32), must not be zero, and bridgeData.receiver must equal NON_EVM_ADDRESS

Applied to files:

  • src/Facets/EcoFacet.sol
  • docs/EcoFacet.md
📚 Learning: 2025-10-02T18:10:09.934Z
Learnt from: mirooon
PR: lifinance/contracts#1406
File: src/Facets/UnitFacet.sol:75-81
Timestamp: 2025-10-02T18:10:09.934Z
Learning: In UnitFacet.sol and similar facet contracts in src/Facets/, the LiFiTransferStarted event emission should ALWAYS be at the end of the _startBridge internal function, after all validations and asset transfers have been completed successfully.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to src/Facets/**/*Facet.sol : Emit LiFiTransferStarted at the start of a transaction before external calls; do not emit LiFiTransferCompleted or LiFiTransferRecovered in facets

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2024-10-31T09:09:38.568Z
Learnt from: ezynda3
PR: lifinance/contracts#843
File: src/Facets/RelayFacet.sol:165-170
Timestamp: 2024-10-31T09:09:38.568Z
Learning: In the `RelayFacet` contract (`src/Facets/RelayFacet.sol`), within the `_startBridge` function, low-level `call` is intentionally used to transfer tokens so that extra bytes can be added to the calldata, as required for integrating with Relay Protocol.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2024-10-09T03:47:21.269Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: src/Periphery/Permit2Proxy.sol:75-108
Timestamp: 2024-10-09T03:47:21.269Z
Learning: In the `Permit2Proxy` contract (`src/Periphery/Permit2Proxy.sol`), reentrancy protection is not necessary for functions like `callDiamondWithEIP2612Signature` when calling our own trusted diamond contract (`LIFI_DIAMOND`).

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-08-27T13:51:52.704Z
Learnt from: mirooon
PR: lifinance/contracts#1328
File: src/Periphery/Lda/Facets/NativeWrapperFacet.sol:33-0
Timestamp: 2025-08-27T13:51:52.704Z
Learning: In LDA facets like NativeWrapperFacet, mirooon prefers to rely on CoreRouteFacet's upstream validation for parameters like `from` rather than adding defensive validation checks in individual facets, since CoreRouteFacet ensures only valid values (msg.sender, address(this), or INTERNAL_INPUT_SOURCE) are passed to the facets.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-09-25T00:12:58.536Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1395
File: src/Periphery/FeeForwarder.sol:78-120
Timestamp: 2025-09-25T00:12:58.536Z
Learning: In src/Periphery/FeeForwarder.sol, the team intentionally uses address(this).balance for refunding remaining native tokens because the contract is designed to never hold funds and not collect dust, making it safe to return the entire balance to the caller.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-09-25T07:48:53.243Z
Learnt from: ezynda3
PR: lifinance/contracts#1324
File: src/Facets/EcoFacet.sol:280-303
Timestamp: 2025-09-25T07:48:53.243Z
Learning: In src/Facets/EcoFacet.sol, the team prefers to allow natural Solidity reverts (array bounds, insufficient data) in route validation rather than adding explicit guards with custom errors, as the reverts achieve the same security outcome while keeping code simpler.

Applied to files:

  • src/Facets/EcoFacet.sol
  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-02-21T09:00:28.226Z
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Facets/ChainflipFacet.sol:127-146
Timestamp: 2025-02-21T09:00:28.226Z
Learning: The `validateBridgeData` modifier in `Validatable.sol` already validates that the receiver address is not zero, making additional zero-address checks redundant in functions using this modifier.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-02-21T09:00:28.226Z
Learnt from: ezynda3
PR: lifinance/contracts#984
File: src/Facets/ChainflipFacet.sol:127-146
Timestamp: 2025-02-21T09:00:28.226Z
Learning: The `validateBridgeData` modifier in `Validatable.sol` validates that the receiver address is not zero using `LibUtil.isZeroAddress`, making additional zero-address checks redundant in functions using this modifier.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2024-11-22T08:49:35.205Z
Learnt from: ezynda3
PR: lifinance/contracts#827
File: src/Facets/DeBridgeDlnFacet.sol:0-0
Timestamp: 2024-11-22T08:49:35.205Z
Learning: In `DeBridgeDlnFacet.sol`, direct access to the `deBridgeChainId` mapping is acceptable, and using the `getDeBridgeChainId` function is not necessary in these instances.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-09-30T12:00:56.667Z
Learnt from: ezynda3
PR: lifinance/contracts#1324
File: src/Facets/EcoFacet.sol:1-1
Timestamp: 2025-09-30T12:00:56.667Z
Learning: In the lifinance/contracts repository, audit logging is handled manually by the team, and merging is automatically restricted until an audit has been logged. Missing audit entries in auditLog.json should not be flagged as critical blocking issues during review, as the team has process controls in place to prevent merging without proper audits.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2024-12-12T02:22:38.502Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#902
File: .github/workflows/forceMergePRBypassAudit.yml:0-0
Timestamp: 2024-12-12T02:22:38.502Z
Learning: Only the CTO and Security Architect can use the force-merge PR bypass audit action, and it will be documented and communicated to prevent unauthorized use.

Applied to files:

  • src/Facets/EcoFacet.sol
📚 Learning: 2025-04-21T03:17:53.443Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1109
File: deployments/worldchain.json:28-28
Timestamp: 2025-04-21T03:17:53.443Z
Learning: For deployment PRs involving address updates like the RelayFacet to Worldchain, verify the actual presence of entries in files before reporting issues. The RelayFacet exists in the diamond log file and the PR diff already contains the necessary address change.

Applied to files:

  • deployments/optimism.staging.json
  • deployments/optimism.diamond.staging.json
📚 Learning: 2025-09-15T12:33:51.069Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1377
File: deployments/_deployments_log_file.json:5607-5619
Timestamp: 2025-09-15T12:33:51.069Z
Learning: The deployments/_deployments_log_file.json is structured as network → environment → version → array of deployment records. Always understand the file hierarchy before attempting validation, and target specific paths rather than trying to validate all objects in the JSON.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2025-09-09T10:39:26.383Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1357
File: deployments/lens.diamond.json:48-51
Timestamp: 2025-09-09T10:39:26.383Z
Learning: In the lifinance/contracts repository, when deployment JSON files show address changes (like AcrossFacetV3 address updates in deployments/*.diamond.json), the corresponding _deployments_log_file.json updates may be handled in separate PRs rather than the same PR that updates the diamond configuration files.

Applied to files:

  • deployments/_deployments_log_file.json
  • deployments/optimism.diamond.staging.json
📚 Learning: 2025-05-28T17:33:33.959Z
Learnt from: mirooon
PR: lifinance/contracts#1170
File: deployments/_deployments_log_file.json:28060-28072
Timestamp: 2025-05-28T17:33:33.959Z
Learning: Deployment log files like `deployments/_deployments_log_file.json` are historical records that document the actual versions deployed at specific times. They should not be updated to match current contract versions - they must accurately reflect what was deployed when the deployment occurred.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2025-01-09T04:17:46.190Z
Learnt from: ezynda3
PR: lifinance/contracts#914
File: deployments/_deployments_log_file.json:26902-26916
Timestamp: 2025-01-09T04:17:46.190Z
Learning: Updates to _deployments_log_file.json can represent backfilling of historical deployment data, not just new deployments. Such updates don't require new audits.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2025-01-16T00:24:10.002Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#927
File: foundry.toml:78-78
Timestamp: 2025-01-16T00:24:10.002Z
Learning: Avalanche chain (chainid=43114) is supported by Etherscan V2 API and can use the endpoint https://api.etherscan.io/v2/api?chainid=43114 instead of Snowtrace.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2025-09-22T00:52:26.172Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1388
File: deployments/hyperevm.diamond.json:72-75
Timestamp: 2025-09-22T00:52:26.172Z
Learning: In diamond configuration files (deployments/*.diamond.json), it's acceptable to have multiple versions of the same facet (e.g., GlacisFacet v1.0.0 and v1.1.0) deployed at different contract addresses. This is intentional design for version coexistence, gradual migration, or backward compatibility purposes.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-09-27T07:10:15.586Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#812
File: deployments/polygon.diamond.json:4-11
Timestamp: 2024-09-27T07:10:15.586Z
Learning: In `deployments/polygon.diamond.json`, it's acceptable for certain facets to have empty names and versions when specified by the developer.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-11-26T01:01:18.499Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: deployments/arbitrum.diamond.json:148-150
Timestamp: 2024-11-26T01:01:18.499Z
Learning: In `deployments/*.diamond.json` configuration files, facets that are part of an open PR and not yet merged into the main branch may have missing `Name` and `Version` fields.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-11-26T01:04:16.637Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: deployments/fantom.diamond.json:92-94
Timestamp: 2024-11-26T01:04:16.637Z
Learning: In `deployments/*.diamond.json` files, it's acceptable for facets to have empty `Name` and `Version` fields, and these should not be flagged as issues.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-11-01T11:53:57.162Z
Learnt from: ezynda3
PR: lifinance/contracts#846
File: deployments/cronos.diamond.json:28-31
Timestamp: 2024-11-01T11:53:57.162Z
Learning: In `deployments/cronos.diamond.json`, both `GenericSwapFacet` and `GenericSwapFacetV3` are distinct facets that should be included together, as they serve different purposes.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2025-09-16T01:39:54.099Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1381
File: deployments/arbitrum.json:65-69
Timestamp: 2025-09-16T01:39:54.099Z
Learning: When verifying facet deployments across .json and .diamond.json files, search by facet name rather than trying to cross-reference addresses between the files, as the same contract can have different addresses in different deployment files.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2025-04-21T03:17:53.443Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1109
File: deployments/worldchain.json:28-28
Timestamp: 2025-04-21T03:17:53.443Z
Learning: For deployment PRs updating contract addresses (like RelayFacet on Worldchain), verify the presence of entries in all relevant files (worldchain.json, worldchain.diamond.json, _deployments_log_file.json) before reporting inconsistencies. The RelayFacet entry exists in all required deployment files with the correct address.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-10-09T03:47:21.269Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#819
File: deployments/scroll.diamond.json:82-82
Timestamp: 2024-10-09T03:47:21.269Z
Learning: In the `deployments/*.diamond.json` and `deployments/*.json` files, the `LiFiDEXAggregator` contract may intentionally have the same contract address across multiple networks. This is acceptable and should not be flagged as an issue in future code reviews.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-11-26T01:14:58.163Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: deployments/worldchain.diamond.json:5-63
Timestamp: 2024-11-26T01:14:58.163Z
Learning: When facet versions are set to empty strings in `deployments/*.diamond.json` files, do not report this issue, as it is already known and will be addressed separately.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2025-04-21T03:15:12.236Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1109
File: deployments/worldchain.diamond.json:84-85
Timestamp: 2025-04-21T03:15:12.236Z
Learning: In deployment JSON files that contain "diamond" in their filename (located in the deployments folder), periphery contracts may have empty string values for their addresses. This indicates that the contract is not deployed on that particular chain and should not be flagged as an issue during code reviews.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-10-09T03:47:21.269Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: deployments/bsc.diamond.staging.json:4-7
Timestamp: 2024-10-09T03:47:21.269Z
Learning: In files with "staging" in their filename, such as `deployments/bsc.diamond.staging.json`, it is acceptable for facets to have empty "Name" and "Version" fields. Do not flag missing facet information in such files during reviews.

Applied to files:

  • deployments/optimism.diamond.staging.json
📚 Learning: 2024-10-22T03:16:28.754Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: test/solidity/Facets/GasZipFacet.t.sol:212-213
Timestamp: 2024-10-22T03:16:28.754Z
Learning: In the `GasZipFacetTest`, for the test case `testBase_Revert_SwapAndBridgeWithInvalidSwapData()`, a generic revert is expected, so `vm.expectRevert();` without specifying the expected error is appropriate.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-10T03:26:23.793Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#782
File: test/solidity/Helpers/WithdrawablePeriphery.t.sol:79-80
Timestamp: 2024-10-10T03:26:23.793Z
Learning: In Solidity tests, it's acceptable to use `UnAuthorized.selector` in `vm.expectRevert()`; avoid suggesting changing it to string messages.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2024-10-22T03:24:24.705Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#807
File: test/solidity/Facets/GasZipFacet.t.sol:337-339
Timestamp: 2024-10-22T03:24:24.705Z
Learning: In `GasZipFacet` tests, when expecting a failure due to insufficient balance for sending value, the test should expect a generic revert without specifying a specific error.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to test/solidity/**/*.t.sol : Test naming: successful tests prefixed test_, failure tests prefixed testRevert_, base/inherited tests prefixed testBase_; negative tests must check specific revert reasons

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-09-16T07:56:45.093Z
Learnt from: ezynda3
PR: lifinance/contracts#1324
File: test/solidity/Facets/EcoFacet.t.sol:135-141
Timestamp: 2025-09-16T07:56:45.093Z
Learning: In EcoFacet test setup, the isNative parameter in swap-and-bridge flows refers to the bridge token type (output), not the swap input type. The ERC20 branch (isNative=false) can still swap from native ETH to ERC20 tokens, requiring msg.value = swapData[0].fromAmount for the ETH input to the swap.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
  • docs/EcoFacet.md
📚 Learning: 2025-08-27T23:36:40.773Z
Learnt from: mirooon
PR: lifinance/contracts#1328
File: test/solidity/Periphery/GasZipPeriphery.t.sol:223-233
Timestamp: 2025-08-27T23:36:40.773Z
Learning: In bridge facet swap flows with requiresDeposit=false, tokens are already held by the diamond contract from previous swaps. When subsequent contracts like GasZipPeriphery call LibAsset.depositAsset, they pull tokens from msg.sender (the diamond) to themselves via transferFrom, requiring no additional approvals since the diamond already owns the tokens.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-08-29T11:07:57.743Z
Learnt from: mirooon
PR: lifinance/contracts#1328
File: src/Periphery/LDA/Facets/CurveFacet.sol:87-91
Timestamp: 2025-08-29T11:07:57.743Z
Learning: In src/Periphery/LDA/Facets/CurveFacet.sol, modern Curve pools (isV2=true, representing V2/NG pools) should reject native tokenIn by adding an early revert check when LibAsset.isNativeAsset(tokenIn) is true, since ICurveV2 exchange functions are non-payable and cannot accept native ETH.

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to src/Facets/**/*Facet.sol : For native fees in facets, use the _depositAndSwap variant and reserve required fees before execution

Applied to files:

  • test/solidity/Facets/EcoFacet.t.sol
🪛 markdownlint-cli2 (0.18.1)
docs/EcoFacet.md

105-105: Link text should be descriptive

(MD059, descriptive-link-text)


111-111: Link text should be descriptive

(MD059, descriptive-link-text)


142-142: Link text should be descriptive

(MD059, descriptive-link-text)

🔇 Additional comments (3)
deployments/_deployments_log_file.json (1)

43049-43062: Confirm EcoFacet staging verification status.
The VERIFIED flag remains "false", but deployment logs are meant to mirror the post‑deployment state. If the contract has since been verified on Optimism staging, please update the log (and include any missing metadata like verification URL/TX if applicable); otherwise call out why verification is blocked so we have a clear audit trail.

src/Facets/EcoFacet.sol (1)

1-316: LGTM! EcoFacet implementation looks solid.

The facet follows all required conventions and guidelines:

✅ Proper license identifier and pragma
✅ Required imports (ILiFi, LibAsset, LibSwap, security mixins)
✅ Required entry points (startBridgeTokensViaEco, swapAndStartBridgeTokensViaEco)
✅ Internal _startBridge implementation
✅ Appropriate modifiers (nonReentrant, refundExcessNative, validateBridgeData, etc.)
✅ Custom errors for gas optimization
✅ Constants defined for magic numbers
✅ Comprehensive validation logic for EVM/non-EVM chains
✅ NatSpec documentation for all public functions
✅ Immutable PORTAL variable with constructor validation
✅ Consolidated validation logic (previous gas optimization feedback addressed)
✅ Proper event emissions

The implementation handles cross-chain bridging for EVM chains (including Tron), Solana, and validates receivers appropriately. The team's preference to use msg.sender for native refunds is documented in learnings.

As per learnings.

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

1-924: LGTM! Comprehensive test coverage for EcoFacet.

The test suite is well-structured and provides thorough coverage:

✅ Proper test naming conventions (testRevert_, testBase_, test_)
✅ Extends TestBaseFacet correctly
✅ Comprehensive setUp() with forked environment, liquidity, and facet wiring
✅ Helper functions (_getValidEcoData, _createEncodedRoute, initiate* dispatchers)
✅ Tests for invalid configurations and error codes
✅ Native token rejection tests (both bridge and swap flows)
✅ EVM chain bridging tests (Optimism)
✅ Tron bridging tests (EVM-compatible)
✅ Solana bridging tests with encoded routes and ATA validation
✅ Chain ID boundary tests (uint64.max, overflow)
✅ Route validation tests (empty routes, invalid ABI encoding, receiver mismatches)
✅ ATA validation tests (zero ATA, mismatched ATA)
✅ Event emission verification
✅ Balance change assertions with TOKEN_SOLVER_REWARD handling

The test coverage addresses both positive and negative scenarios, including edge cases for different chain types and validation paths.

As per learnings.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
deployments/_deployments_log_file.json (1)

43365-43376: Update EcoFacet optimism-staging deployment to verified

This new staging deployment is recorded as unverified. We normally require explorer verification for freshly deployed facets before merging deployment metadata; otherwise reviewers and integrators can't inspect the bytecode source, which is a security and ops blocker. Please complete the contract verification on Optimism and flip "VERIFIED" to "true" (with any other verification metadata, if applicable) before merging.

🧹 Nitpick comments (1)
audit/auditLog.json (1)

389-400: Restore chronological ordering for audit entries.

audit20251001 should sit before audit20251007 to keep the audits map in ascending date order like the rest of the file. Please move the block up.

-    "audit20251007": {
-      "auditCompletedOn": "07.10.2025",
-      "auditedBy": "Sujith Somraaj (individual security researcher)",
-      "auditorGitHandle": "sujithsomraaj",
-      "auditReportPath": "./audit/reports/2025.10.07_UnitFacet(v1.0.0).pdf",
-      "auditCommitHash": "626dd4a927ed84c1c8de9e6b22af66669da62356"
-    },
-    "audit20251001": {
+    "audit20251001": {
       "auditCompletedOn": "01.10.2025",
       "auditedBy": "Sujith Somraaj (individual security researcher)",
       "auditorGitHandle": "sujithsomraaj",
       "auditReportPath": "./audit/reports/2025.10.01_EcoFacet(v1.0.0).pdf",
       "auditCommitHash": "8d0e66a69c765e83c13339d7a77071ce2f26968a"
+    },
+    "audit20251007": {
+      "auditCompletedOn": "07.10.2025",
+      "auditedBy": "Sujith Somraaj (individual security researcher)",
+      "auditorGitHandle": "sujithsomraaj",
+      "auditReportPath": "./audit/reports/2025.10.07_UnitFacet(v1.0.0).pdf",
+      "auditCommitHash": "626dd4a927ed84c1c8de9e6b22af66669da62356"
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1bc03bc and f45a34a.

⛔ Files ignored due to path filters (1)
  • audit/reports/2025.10.01_EcoFacet(v1.0.0).pdf is excluded by !**/*.pdf
📒 Files selected for processing (3)
  • audit/auditLog.json (3 hunks)
  • deployments/_deployments_log_file.json (1 hunks)
  • package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json
🧰 Additional context used
📓 Path-based instructions (1)
audit/auditLog.json

📄 CodeRabbit inference engine (conventions.md)

Maintain auditLog.json with audits entries (id, dates, auditor, report path, commit) and auditedContracts mapping

Files:

  • audit/auditLog.json
🧠 Learnings (4)
📚 Learning: 2025-09-12T10:17:51.686Z
Learnt from: CR
PR: lifinance/contracts#0
File: conventions.md:0-0
Timestamp: 2025-09-12T10:17:51.686Z
Learning: Applies to audit/auditLog.json : Maintain auditLog.json with audits entries (id, dates, auditor, report path, commit) and auditedContracts mapping

Applied to files:

  • audit/auditLog.json
📚 Learning: 2025-09-15T12:33:51.069Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1377
File: deployments/_deployments_log_file.json:5607-5619
Timestamp: 2025-09-15T12:33:51.069Z
Learning: The deployments/_deployments_log_file.json is structured as network → environment → version → array of deployment records. Always understand the file hierarchy before attempting validation, and target specific paths rather than trying to validate all objects in the JSON.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2025-09-09T10:39:26.383Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#1357
File: deployments/lens.diamond.json:48-51
Timestamp: 2025-09-09T10:39:26.383Z
Learning: In the lifinance/contracts repository, when deployment JSON files show address changes (like AcrossFacetV3 address updates in deployments/*.diamond.json), the corresponding _deployments_log_file.json updates may be handled in separate PRs rather than the same PR that updates the diamond configuration files.

Applied to files:

  • deployments/_deployments_log_file.json
📚 Learning: 2025-01-16T00:24:10.002Z
Learnt from: 0xDEnYO
PR: lifinance/contracts#927
File: foundry.toml:78-78
Timestamp: 2025-01-16T00:24:10.002Z
Learning: Avalanche chain (chainid=43114) is supported by Etherscan V2 API and can use the endpoint https://api.etherscan.io/v2/api?chainid=43114 instead of Snowtrace.

Applied to files:

  • deployments/_deployments_log_file.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: enforce-min-test-coverage
  • GitHub Check: run-unit-tests

@ezynda3 ezynda3 merged commit 25a5b88 into main Oct 10, 2025
36 of 38 checks passed
@ezynda3 ezynda3 deleted the LF-14918-Eco-Facet branch October 10, 2025 14:47
@coderabbitai coderabbitai bot mentioned this pull request Oct 21, 2025
8 tasks
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.

7 participants