Skip to content

feat: Vault leveraging aave on eth and pancake on base part 1 #340

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
May 1, 2025

Conversation

keyleu
Copy link
Contributor

@keyleu keyleu commented Apr 30, 2025

First PR for the vault that will use AAVE and PancakeV3.

Sets up the entire program and tests the following part of the flow:

  • Depositing in the vault.
  • Forwarding correctly to the bridges and AAVE.
  • Supplying and borrowing right amount of assets.
  • Trigger bridging using CCTP and Standard Bridge.

Summary by CodeRabbit

  • New Features

    • Introduced a comprehensive cross-chain vault strategy example integrating Ethereum and Base networks with PancakeSwap, including new modules for strategy orchestration, configuration, and contract deployment.
    • Added mock standard bridge relayer and enhanced CCTP relayer for simulating cross-chain token transfers in end-to-end tests.
    • Provided new configuration files and contract bindings for streamlined DeFi strategy setup.
  • Improvements

    • Expanded the maximum forwarding amount in token forwarding rules from 128-bit to 256-bit integers across contracts and configuration, allowing for larger transfers.
  • Bug Fixes

    • Corrected variable naming inconsistencies in configuration files and code.
  • Documentation

    • Updated documentation to reflect changes in forwarding configuration types.
  • Style

    • Improved formatting and alignment in TOML configuration files for better readability.
  • Chores

    • Removed obsolete example files and duplicate contract bindings to streamline the codebase.

Copy link
Contributor

coderabbitai bot commented Apr 30, 2025

Walkthrough

This set of changes introduces a comprehensive end-to-end example for a cross-chain vault strategy integrating Ethereum and Base networks, with PancakeSwap and various bridging mechanisms. New Rust modules and configuration files are added to orchestrate the deployment and setup of accounts, contracts, and relayers across both chains. The strategy logic automates vault management, lending, borrowing, and token bridging, with detailed configuration for all components. Additionally, the mock standard bridge relayer is implemented, and the CCTP relayer is enhanced with incremental block processing. Several contract and struct field types are updated from 128-bit to 256-bit integers to support larger token amounts. Minor fixes and formatting adjustments are also included.

Changes

File(s) / Path(s) Change Summary
e2e/examples/eth_to_base_vault_pancake/base.rs, e2e/examples/eth_to_base_vault_pancake/ethereum.rs New modules for Base and Ethereum setup: Add async functions to deploy and configure accounts, contracts, and libraries for the strategy on both chains.
e2e/examples/eth_to_base_vault_pancake/strategist/example_strategy.toml New TOML config: Adds a comprehensive configuration file for the cross-chain strategy, specifying RPCs, tokens, accounts, libraries, and parameters for Ethereum and Base.
e2e/examples/eth_to_base_vault_pancake/strategist/mod.rs New module declarations: Adds public modules strategy and strategy_config.
e2e/examples/eth_to_base_vault_pancake/strategist/strategy_config.rs New strategy config module: Defines typed Rust structs for all configuration aspects of the strategy, for both Ethereum and Base.
e2e/examples/eth_to_base_vault_pancake/strategist/strategy.rs New strategy logic: Implements the main Strategy struct and logic for vault management, lending, borrowing, and bridging, with async cycle and TOML config loading.
e2e/examples/eth_to_base_vault_pancake/vault.rs New example entrypoint: Orchestrates the full workflow: sets up clients, deploys contracts, funds relayers, writes config, simulates deposits, and starts the strategy.
e2e/examples/eth_to_base_vault_pancake/strategist/mod.rs, e2e/examples/eth_to_base_vault_pancake/strategist/strategy_config.rs, e2e/examples/eth_to_base_vault_pancake/strategist/strategy.rs New strategist module and configuration: Introduces modules for strategy logic and configuration.
e2e/examples/eth_cctp_vault/evm.rs Variable name fix: Corrects typo in variable name from cctp_transer_cfg to cctp_transfer_cfg.
e2e/examples/eth_cctp_vault/strategist/example_strategy.toml Whitespace/formatting: Aligns and formats TOML key-value pairs for readability.
e2e/examples/ethereum_integration_tests.rs Type update: Changes maxAmount in ForwardingConfig from integer literal to U256::from(1000).
e2e/examples/forked_anvil.rs File deleted: Removes a standalone example for forking and querying Anvil Ethereum clients.
e2e/Cargo.toml Example added: Registers the new example target for the cross-chain vault Pancake strategy.
e2e/src/utils/mocks/mod.rs Module added: Declares new standard_bridge_relayer module.
e2e/src/utils/mocks/standard_bridge_relayer.rs New mock relayer: Implements a mock standard bridge relayer for two EVM chains, handling ERC20DepositInitiated events and token transfers.
e2e/src/utils/mocks/cctp_relayer_evm_evm.rs CCTP relayer enhancement: Adds tracking of last processed blocks for incremental log querying.
e2e/src/utils/solidity_contracts.rs Contract bindings: Adds new Solidity contract bindings for CCTPTransfer, AavePositionManager, StandardBridgeTransfer, and PancakeSwapV3PositionManager; removes duplicate.
contracts/encoders/evm-encoder/src/libraries/forwarder.rs, packages/encoder-utils/src/libraries/forwarder/solidity_types.rs, solidity/src/libraries/Forwarder.sol, docs/src/libraries/evm/forwarder.md Type change: Updates max_amount/maxAmount field in ForwardingConfig from 128-bit to 256-bit integer types in Rust, Solidity, and docs.
packages/chain-client-utils/Cargo.toml Whitespace fix: Removes trailing whitespace in feature declaration.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Vault
    participant Forwarder
    participant Aave
    participant CCTPBridge
    participant StandardBridge
    participant BaseForwarder
    participant PancakeSwap

    User->>Vault: Deposit WETH
    Vault->>Forwarder: Split WETH (2/3 to Aave, 1/3 to StandardBridge)
    Forwarder->>Aave: Supply WETH
    Aave->>Aave: Borrow USDC (if health factor OK)
    Aave->>Forwarder: Forward USDC to CCTP input
    Forwarder->>CCTPBridge: Bridge USDC to Base
    Forwarder->>StandardBridge: Bridge WETH to Base
    CCTPBridge->>BaseForwarder: Receive USDC on Base
    StandardBridge->>BaseForwarder: Receive WETH on Base
    BaseForwarder->>PancakeSwap: Provide liquidity or execute swaps
Loading

Suggested reviewers

  • vlopes11
  • bekauz

Poem

In fields of code where bridges grow,
A rabbit hops from chain to chain—
Vaults and swaps and tokens flow,
Strategies spun with clever brain.
Now numbers stretch from small to grand,
With 256 bits at hand!
Cross-chain dreams, a bunny’s delight,
All systems go—deploy tonight!

((\
( -.-)
o_(")(")

✨ Finishing Touches
  • 📝 Generate Docstrings

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

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

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

CodeRabbit Commands (Invoked using PR comments)

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

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Documentation and Community

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

@keyleu keyleu requested a review from bekauz April 30, 2025 18:56
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: 10

🧹 Nitpick comments (11)
e2e/examples/eth_to_base_vault_pancake/strategist/example_strategy.toml (1)

25-27: min_aave_health_factor representation is ambiguous

The value "12" is later commented as “Represents 1.2”. Persisting scaled numbers as plain strings is brittle and invites off-by-ten-fold errors.

Recommend:

min_aave_health_factor = { value = 120, decimals = 2 }  # 1.20

or store the raw 1.2 and convert to ray‐units in code.

e2e/examples/eth_to_base_vault_pancake/vault.rs (1)

303-307: strategy.start() fire-and-forget can drop tasks

If start() spawns background tasks without being await-ed or returning a JoinHandle, those tasks may be dropped when main exits after the 120 s sleep.
Consider returning a handle and join!-ing it, or make start() blocking.

e2e/examples/eth_to_base_vault_pancake/ethereum.rs (1)

260-274: Manual 64-byte padding is error-prone

Instead of:

let mint_recipient_hex = mint_recipient_string.strip_prefix("0x").unwrap_or_default();
let padded_hex = format!("{:0>64}", mint_recipient_hex);
let mintRecipient = FixedBytes::<32>::from_hex(padded_hex)?;

just use mint_recipient.to_fixed_bytes() (or equivalent) and avoid the string gymnastics.

e2e/examples/eth_to_base_vault_pancake/base.rs (2)

291-304: Incorrect chain label in log message creates debugging confusion

set_up_forwarder_pancake_output_to_input (and the two similar helpers below) print “on Ethereum” although they are deploying to Base (base_client).
This can be very misleading when grepping logs from multi-chain tests.

-    info!("Setting up Forwarder Pancake Output to Input on Ethereum");
+    info!("Setting up Forwarder Pancake Output to Input on Base");

Please update the other two helpers as well.


150-170: Redundant to_string()Address::from_str(..) round-trips

The config objects repeatedly call
input_account.to_string()Address::from_str(..)
which allocates and parses hex strings dozens of times.

All encoder helpers accept alloy_primitives::Address directly; pass the value without serialising first:

-        inputAccount: alloy_primitives_encoder::Address::from_str(
-            input_account.to_string().as_str(),
-        )?,
+        inputAccount: input_account.into(),

This shaves deployment time and avoids accidental checksum/prefix bugs.

e2e/examples/eth_to_base_vault_pancake/strategist/strategy_config.rs (1)

52-55: Consider numeric types for threshold parameters

min_aave_health_factor is stored as String and later parsed into U256 each cycle.
Storing it as Decimal/U256 in the config struct would avoid repeated parsing and catch format errors at deserialisation time.

e2e/src/utils/mocks/standard_bridge_relayer.rs (5)

44-66: Consider using environment variables for sensitive information.

While this is a mock implementation for testing, it's still a good practice to avoid hardcoding mnemonic phrases directly in the source code, even in test environments.

-            .phrase("test test test test test test test test test test test junk")
+            .phrase(std::env::var("TEST_MNEMONIC").unwrap_or_else(|_| "test test test test test test test test test test test junk".to_string()))

79-100: Consider implementing parallel chain polling.

The current implementation polls chains sequentially, which is simpler but less efficient. For better performance, especially with slow-responding nodes, consider polling both chains concurrently.

     async fn cycle(&mut self) -> Result<(), Box<dyn Error + Send + Sync>> {
         let worker_name = self.get_name();
 
-        if let Err(e) = self.poll_evm_a().await {
-            warn!("{worker_name}: Evm A polling error: {:?}", e);
-        }
-
-        if let Err(e) = self.poll_evm_b().await {
-            warn!("{worker_name}: Evm B polling error: {:?}", e);
-        }
+        let poll_a = self.poll_evm_a();
+        let poll_b = self.poll_evm_b();
+        
+        let (a_result, b_result) = tokio::join!(poll_a, poll_b);
+        
+        if let Err(e) = a_result {
+            warn!("{worker_name}: Evm A polling error: {:?}", e);
+        }
+        
+        if let Err(e) = b_result {
+            warn!("{worker_name}: Evm B polling error: {:?}", e);
+        }
 
         tokio::time::sleep(POLLING_PERIOD).await;
 
         Ok(())
     }

169-208: Consolidate duplicate code between send_on_evm_a and send_on_evm_b methods.

Both methods implement nearly identical logic, differing only in which EVM client they use. Consider refactoring to reduce code duplication.

+    async fn send_tokens(&self, client: &EthereumClient, destination_erc20: Address, amount: U256, recipient: Address, chain_name: &str) -> Result<(), Box<dyn Error>> {
+        let rp = client
+            .get_request_provider()
+            .await
+            .expect(&format!("failed to get {chain_name} request provider"));
+
+        let erc20 = ERC20::new(destination_erc20, &rp);
+
+        let pre_send_balance = client
+            .query(erc20.balanceOf(recipient))
+            .await
+            .expect(&format!("failed to query {chain_name} balance"));
+
+        let send_tx = client
+            .execute_tx(erc20.transfer(recipient, amount).into_transaction_request())
+            .await
+            .expect(&format!("failed to send tokens on {chain_name}"));
+
+        let _ = rp
+            .get_transaction_receipt(send_tx.transaction_hash)
+            .await;
+
+        let post_send_balance = client
+            .query(erc20.balanceOf(recipient))
+            .await
+            .expect(&format!("failed to query {chain_name} balance"));
+
+        let delta = post_send_balance._0 - pre_send_balance._0;
+        info!("[Standard Bridge] successfully sent {delta} tokens to {chain_name} address {recipient}");
+
+        Ok(())
+    }
+
     async fn send_on_evm_b(&self, amount: U256, recipient: Address) -> Result<(), Box<dyn Error>> {
-        let evm_b_rp = self
-            .runtime
-            .evm_client_b
-            .get_request_provider()
-            .await
-            .expect("failed to get evm B request provider");
-
-        let erc20 = ERC20::new(self.state.evm_b_destination_erc20, &evm_b_rp);
-
-        let pre_send_balance = self
-            .runtime
-            .evm_client_b
-            .query(erc20.balanceOf(recipient))
-            .await
-            .expect("failed to query evm B balance");
-
-        let send_tx = self
-            .runtime
-            .evm_client_b
-            .execute_tx(erc20.transfer(recipient, amount).into_transaction_request())
-            .await
-            .expect("failed to send tokens on evm B");
-
-        let _ = evm_b_rp
-            .get_transaction_receipt(send_tx.transaction_hash)
-            .await;
-
-        let post_send_balance = self
-            .runtime
-            .evm_client_b
-            .query(erc20.balanceOf(recipient))
-            .await
-            .expect("failed to query evm B balance");
-
-        let delta = post_send_balance._0 - pre_send_balance._0;
-        info!("[Standard Bridge] successfully sent {delta} tokens to evm B address {recipient}");
-
-        Ok(())
+        self.send_tokens(&self.runtime.evm_client_b, self.state.evm_b_destination_erc20, amount, recipient, "evm B")
     }

     async fn send_on_evm_a(&self, amount: U256, recipient: Address) -> Result<(), Box<dyn Error>> {
-        let evm_a_rp = self
-            .runtime
-            .evm_client_a
-            .get_request_provider()
-            .await
-            .expect("failed to get evm A request provider");
-
-        let erc20 = ERC20::new(self.state.evm_a_destination_erc20, &evm_a_rp);
-
-        let pre_send_balance = self
-            .runtime
-            .evm_client_a
-            .query(erc20.balanceOf(recipient))
-            .await
-            .expect("failed to query evm A balance");
-
-        let send_tx = self
-            .runtime
-            .evm_client_a
-            .execute_tx(erc20.transfer(recipient, amount).into_transaction_request())
-            .await
-            .expect("failed to send tokens on evm A");
-
-        let _ = evm_a_rp
-            .get_transaction_receipt(send_tx.transaction_hash)
-            .await;
-
-        let post_send_balance = self
-            .runtime
-            .evm_client_a
-            .query(erc20.balanceOf(recipient))
-            .await
-            .expect("failed to query evm A balance");
-
-        let delta = post_send_balance._0 - pre_send_balance._0;
-        info!("[Standard Bridge] successfully sent {delta} tokens to evm A address {recipient}");
-
-        Ok(())
+        self.send_tokens(&self.runtime.evm_client_a, self.state.evm_a_destination_erc20, amount, recipient, "evm A")
     }

210-304: Consider extracting common logic from poll_evm_a and poll_evm_b.

Both polling methods contain nearly identical logic, differing only in which chain they poll and which method they call to process events. Consider refactoring to reduce code duplication.

You could create a helper method that takes the necessary parameters to handle both polling scenarios:

async fn poll_chain(
    &mut self,
    client: &EthereumClient,
    filter: &Filter,
    last_block_processed: &mut Option<u64>,
    processed_events: &mut HashSet<Vec<u8>>,
    send_handler: impl Fn(U256, Address) -> Result<(), Box<dyn Error>>,
) -> Result<(), Box<dyn Error>> {
    let provider = client.get_request_provider().await.expect("could not get provider");
    
    let current_block = provider.get_block_number().await?;
    let last_block = last_block_processed.unwrap_or(current_block.saturating_sub(1));
    
    // Handle potential chain reorganizations
    if current_block <= last_block {
        return Ok(());
    }
    
    let filter = filter.clone()
        .from_block(BlockNumberOrTag::Number(last_block))
        .to_block(BlockNumberOrTag::Number(current_block));
    
    // fetch the logs
    let logs = provider.get_logs(&filter).await?;
    
    for log in logs.iter() {
        let event_id = log
            .transaction_hash
            .expect("failed to find tx hash in logs")
            .to_vec();
        if processed_events.insert(event_id) {
            let alloy_log =
                Log::new(log.address(), log.topics().into(), log.data().clone().data)
                    .unwrap_or_default();
            
            let erc20_deposit_initiated_log =
                ERC20DepositInitiated::decode_log(&alloy_log, false)?;
            
            // send tokens using the provided handler
            send_handler(
                erc20_deposit_initiated_log.amount,
                erc20_deposit_initiated_log.to,
            )?;
        }
    }
    
    // update the last block processed
    *last_block_processed = Some(current_block);
    
    Ok(())
}

Then update the poll_evm_a and poll_evm_b methods to use this helper method.


1-305: Add documentation for public methods and structs.

The code would benefit from more comprehensive documentation, particularly for public methods and structs. Consider adding documentation comments to explain the purpose and expected behavior of each component.

For example:

+/// A mock implementation of a standard bridge relayer that forwards tokens between two EVM chains
+/// based on deposit events. This is intended for testing purposes only.
 pub struct MockStandardBridgeRelayer {
     pub state: RelayerState,
     pub runtime: RelayerRuntime,
 }

+/// Runtime components needed for the relayer to operate, including connections to both EVM chains.
 pub struct RelayerRuntime {
     pub evm_client_a: EthereumClient,
     pub evm_client_b: EthereumClient,
 }

+/// State information tracked by the relayer to ensure events are processed only once
+/// and to track the latest blocks that have been processed on each chain.
 pub struct RelayerState {
     evm_a_last_block_processed: Option<u64>,
     evm_a_processed_events: HashSet<Vec<u8>>,
     evm_a_filter: Filter,
     evm_a_destination_erc20: Address,
     evm_b_last_block_processed: Option<u64>,
     evm_b_processed_events: HashSet<Vec<u8>>,
     evm_b_filter: Filter,
     evm_b_destination_erc20: Address,
 }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6d97dc7 and 28d7885.

📒 Files selected for processing (21)
  • contracts/encoders/evm-encoder/src/libraries/forwarder.rs (3 hunks)
  • docs/src/libraries/evm/forwarder.md (1 hunks)
  • e2e/Cargo.toml (1 hunks)
  • e2e/examples/eth_cctp_vault/evm.rs (2 hunks)
  • e2e/examples/eth_cctp_vault/strategist/example_strategy.toml (1 hunks)
  • e2e/examples/eth_to_base_vault_pancake/base.rs (1 hunks)
  • e2e/examples/eth_to_base_vault_pancake/ethereum.rs (1 hunks)
  • e2e/examples/eth_to_base_vault_pancake/strategist/example_strategy.toml (1 hunks)
  • e2e/examples/eth_to_base_vault_pancake/strategist/mod.rs (1 hunks)
  • e2e/examples/eth_to_base_vault_pancake/strategist/strategy.rs (1 hunks)
  • e2e/examples/eth_to_base_vault_pancake/strategist/strategy_config.rs (1 hunks)
  • e2e/examples/eth_to_base_vault_pancake/vault.rs (1 hunks)
  • e2e/examples/ethereum_integration_tests.rs (2 hunks)
  • e2e/examples/forked_anvil.rs (0 hunks)
  • e2e/src/utils/mocks/cctp_relayer_evm_evm.rs (7 hunks)
  • e2e/src/utils/mocks/mod.rs (1 hunks)
  • e2e/src/utils/mocks/standard_bridge_relayer.rs (1 hunks)
  • e2e/src/utils/solidity_contracts.rs (1 hunks)
  • packages/chain-client-utils/Cargo.toml (1 hunks)
  • packages/encoder-utils/src/libraries/forwarder/solidity_types.rs (1 hunks)
  • solidity/src/libraries/Forwarder.sol (1 hunks)
💤 Files with no reviewable changes (1)
  • e2e/examples/forked_anvil.rs
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: build
  • GitHub Check: build-and-deploy
  • GitHub Check: setup-local-ic
🔇 Additional comments (31)
packages/chain-client-utils/Cargo.toml (1)

11-11: Approve trivial formatting update
Removed trailing whitespace on the test-utils feature declaration. No functional impact.

e2e/examples/eth_cctp_vault/strategist/example_strategy.toml (1)

2-56: Formatting improvements enhance readability

The changes in this file are purely formatting adjustments that align the equals signs across configuration blocks. This improves visual consistency and makes the configuration easier to read without changing any functionality.

e2e/src/utils/mocks/mod.rs (1)

3-3: New standard bridge relayer module added

The addition of the standard bridge relayer module complements the existing CCTP relayer modules. This is in line with the PR objective of implementing bridging operations using both CCTP and the Standard Bridge.

e2e/examples/eth_cctp_vault/evm.rs (2)

174-174: Fixed variable name typo

The variable name has been corrected from cctp_transer_cfg to cctp_transfer_cfg, fixing a spelling error.


193-193: Fixed variable name typo

The variable name has been updated to use the corrected cctp_transfer_cfg instead of cctp_transer_cfg, maintaining consistency with the earlier fix.

packages/encoder-utils/src/libraries/forwarder/solidity_types.rs (1)

6-6:

✅ Verification successful

Enhanced token amount capacity

Changed maxAmount field type from uint128 to uint256 to support larger token amounts in forwarding configurations. This change aligns with updates in Solidity contracts and other Rust encoders in the codebase.

Let's verify this change is consistent with other related files:


🏁 Script executed:

#!/bin/bash
# Check for related maxAmount type changes in other files
rg -t rust "max.?[aA]mount.*[uU](128|256)|[uU](128|256).*max.?[aA]mount" --no-heading

Length of output: 1442


Enhanced token amount capacity confirmed

All EVM‐related code now consistently uses a 256-bit amount:

  • packages/encoder-utils/src/libraries/forwarder/solidity_types.rs declares uint256 maxAmount.
  • The EVM encoder (contracts/encoders/evm-encoder/src/libraries/forwarder.rs) serializes cfg.max_amount as U256.
  • End-to-end tests (e2e/examples/ethereum_integration_tests.rs and Pancake integration) use U256 for maxAmount.
  • No other EVM files reference a 128-bit maxAmount.

No further updates needed—approving the change.

e2e/examples/ethereum_integration_tests.rs (2)

322-322: Type change from integer literal to explicit U256

The change from 1000 to U256::from(1000) aligns with the broader update in the codebase where the max_amount field type in ForwardingConfig struct was changed from u128 to Uint256. This ensures type consistency throughout the system.


348-348: Type change from integer literal to explicit U256

Similarly to the previous change, this explicit U256 type construction ensures consistency with the updated field type in the ForwardingConfig struct. This is part of the system-wide enhancement to support larger token forwarding amounts.

solidity/src/libraries/Forwarder.sol (1)

20-20: Enhanced token amount support

The field type change from uint128 to uint256 for maxAmount increases the maximum representable token forwarding amount. This aligns with the corresponding changes in the Rust encoder libraries and provides better support for tokens with large supplies or values.

The change is well-integrated with related updates across the codebase, particularly in the encoder utilities and Rust libraries that interact with this Solidity struct.

e2e/examples/eth_to_base_vault_pancake/strategist/mod.rs (1)

1-2: New modules for cross-chain vault strategy

These new modules establish the foundation for the cross-chain vault strategy between Ethereum and Base networks with PancakeSwap integration. The strategy module will contain the implementation logic while strategy_config will handle configuration structures.

This modular approach maintains good separation of concerns, keeping the strategy logic separate from its configuration.

e2e/Cargo.toml (1)

16-18: New example target for cross-chain vault strategy

This addition registers the new end-to-end example for a vault strategy that leverages AAVE on Ethereum and PancakeV3 on Base. The example will demonstrate the deployment and operation of cross-chain DeFi integrations.

The example target is correctly configured and points to the appropriate entry file at examples/eth_to_base_vault_pancake/vault.rs.

docs/src/libraries/evm/forwarder.md (1)

43-43: LGTM! Expanded maxAmount field capacity.

The type change from uint128 to uint256 for the maxAmount field increases the maximum token value that can be forwarded, which is appropriate for financial operations that may involve large amounts.

contracts/encoders/evm-encoder/src/libraries/forwarder.rs (3)

3-3: LGTM! Added Uint256 import.

Added import for Uint256 from cosmwasm_std to support the type change in ForwardingConfig.


34-34: LGTM! Updated max_amount field type.

Changed the field type from u128 to Uint256 to support larger token amounts for forwarding, which aligns with the changes in the Solidity contract and documentation.


68-68: LGTM! Updated encoding logic for Uint256.

Updated the encoding logic to correctly convert the Uint256 value to U256 using its big-endian byte representation, ensuring compatibility with the Solidity library.

e2e/src/utils/solidity_contracts.rs (4)

55-61: LGTM! Added enhanced CCTPTransfer binding.

Properly defines the CCTPTransfer contract binding with RPC support and useful debugging traits.


63-69: LGTM! Added AavePositionManager binding.

Added new contract binding for AavePositionManager with appropriate annotations for RPC interaction and debugging, which is needed for the vault strategy on Ethereum.


71-77: LGTM! Added StandardBridgeTransfer binding.

Added new contract binding for StandardBridgeTransfer with RPC support, which is required for the cross-chain bridging functionality.


79-85: LGTM! Added PancakeSwapV3PositionManager binding.

Added new contract binding for PancakeSwapV3PositionManager with RPC support, which is needed for the vault strategy on Base.

e2e/src/utils/mocks/cctp_relayer_evm_evm.rs (7)

4-4: LGTM! Added BlockNumberOrTag import.

Added import to support block range filtering in event log queries.


60-60: LGTM! Added block tracking fields.

Added fields to track the last processed block for both EVM chains, enabling incremental log processing.

Also applies to: 64-64


107-107: LGTM! Initialized block tracking fields.

Properly initialized the new last block processed fields to None in the constructor.

Also applies to: 111-111


209-220: LGTM! Implemented incremental log processing for EVM A.

Enhanced the log retrieval process to only fetch logs from the last processed block to the current block, which improves efficiency and prevents duplicate processing.


243-244: LGTM! Added state update for EVM A.

Properly updates the last processed block after handling logs to maintain incremental processing state.


257-269: LGTM! Implemented incremental log processing for EVM B.

Similar to EVM A, improved the log retrieval process to only fetch logs from the last processed block to the current block.


291-292: LGTM! Added state update for EVM B.

Properly updates the last processed block after handling logs to maintain incremental processing state.

e2e/examples/eth_to_base_vault_pancake/strategist/strategy.rs (2)

157-166: Integer division silently drops remainder – verify rounding rules

let weth_to_supply = balance / 3 * 2; let weth_to_bridge = balance / 3
Any remainder (balance % 3) is ignored, which may cause drift in accounting.
Confirm this is intentional; otherwise use precise proportional splits (e.g. (balance * 2) / 3).


316-360: ⚠️ Potential issue

Compilation fails: floating-point literals used for U256 constants

U256::from(1e8), U256::from(1e17), U256::from(1e6) (lines ~318, 342, 359) are f64 literals; U256::from expects an integer type, causing a hard compile error:

expected integer, found floating-point number

Fix by using string or integer literals:

- U256::from(1e8)
+ U256::from_dec_str("100000000")?

Apply the same pattern for the other two occurrences (1e17"100000000000000000", 1e6"1000000").

Also applies to: 341-344

⛔ Skipped due to learnings
Learnt from: keyleu
PR: timewave-computer/valence-protocol#334
File: e2e/examples/eth_to_base_vault_pancake/ethereum.rs:226-227
Timestamp: 2025-04-25T22:11:33.974Z
Learning: In the Valence protocol codebase, `U256::from(1e6)` is valid syntax that compiles successfully despite 1e6 being written as a floating-point literal. This is used in multiple places within the project, particularly when setting token precision values.
Learnt from: keyleu
PR: timewave-computer/valence-protocol#334
File: e2e/examples/eth_to_base_vault_pancake/ethereum.rs:226-227
Timestamp: 2025-04-25T22:11:33.974Z
Learning: In the context of the Valence protocol, `U256::from(1e6)` is valid syntax and compiles successfully despite 1e6 being a floating-point literal in Rust.
e2e/src/utils/mocks/standard_bridge_relayer.rs (3)

1-21: Properly organized imports and constants.

The imports are well-structured, separating standard library components, external crates, and internal modules. The POLLING_PERIOD constant is appropriately defined at the top level for easy configuration.


23-32: Good use of sol! macro for event definition.

The Solidity event definition is well-structured and properly typed, following best practices for cross-chain event handling. The indexed parameters help with efficient event filtering.


34-77: Clean struct organization with clear responsibility separation.

The code follows good design principles by separating the relayer's state from its runtime components. This makes the code more maintainable and easier to test.

Copy link
Contributor

@bekauz bekauz left a comment

Choose a reason for hiding this comment

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

on a high level this looks really nice so far! It's hard to pinpoint any errors in this so approving it. If anything comes up then it will surface during the full e2e flow

@keyleu keyleu merged commit f086ef1 into main May 1, 2025
19 checks passed
@keyleu keyleu deleted the keyne/strategist-vault branch May 1, 2025 19:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants