Skip to content

Comments

Update scarb, starknet and l2 contract to latest version#111

Merged
Ugo-X merged 4 commits intoExplore-Beyond-Innovations:mainfrom
GideonBature:update_tooling
Aug 20, 2025
Merged

Update scarb, starknet and l2 contract to latest version#111
Ugo-X merged 4 commits intoExplore-Beyond-Innovations:mainfrom
GideonBature:update_tooling

Conversation

@GideonBature
Copy link
Contributor

@GideonBature GideonBature commented Aug 19, 2025

I have update the Starknet foundry, the Starknet and Scarb version and also adjusted the L2 contract to compile without any warning nor error.

Closes #109

Summary by CodeRabbit

  • Chores
    • Upgraded toolchain and dependencies for L2 contracts (including multiple version bumps).
    • Updated build manifest to also produce CASM artifacts.
    • Expanded ignore rules to exclude lock files from version control.
  • Refactor
    • Simplified vector append operations for clarity and small performance benefits.
    • Streamlined imports and enabled a feature flag to permit deprecated constants while preserving public interfaces.

@coderabbitai
Copy link

coderabbitai bot commented Aug 19, 2025

Warning

Rate limit exceeded

@JoE11-y has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 22 minutes and 21 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 56cc79f and cf0ccef.

📒 Files selected for processing (17)
  • .github/workflows/l2.yml (1 hunks)
  • contracts/L2/.tool-versions (1 hunks)
  • contracts/L2/src/core/L2Oracle.cairo (1 hunks)
  • contracts/L2/src/core/ProofRegistry.cairo (3 hunks)
  • contracts/L2/src/core/xZBERC20.cairo (1 hunks)
  • contracts/L2/src/dao/DAO.cairo (2 hunks)
  • contracts/L2/src/interfaces/IZeroXBridgeL2.cairo (1 hunks)
  • contracts/L2/src/lib.cairo (1 hunks)
  • contracts/L2/src/mocks/MockMerkleManager.cairo (4 hunks)
  • contracts/L2/src/mocks/MockOracle.cairo (1 hunks)
  • contracts/L2/src/mocks/MockRegistry.cairo (1 hunks)
  • contracts/L2/tests/test_DAO.cairo (1 hunks)
  • contracts/L2/tests/test_Dynamicrate.cairo (1 hunks)
  • contracts/L2/tests/test_L2Oracle.cairo (1 hunks)
  • contracts/L2/tests/test_MerkleManager.cairo (1 hunks)
  • contracts/L2/tests/test_ZeroXBridgeL2.cairo (1 hunks)
  • contracts/L2/tests/test_xZBERC20.cairo (0 hunks)

Walkthrough

Tooling and dependency versions bumped for L2 contracts; Scarb manifest updated to enable CASM output. Source changes replace storage Vec append().write(...) with push(...) and adjust imports/feature flags to align with newer StarkNet toolchains. .gitignore updated to ignore Scarb.lock.

Changes

Cohort / File(s) Summary
Tooling & manifest
contracts/L2/.tool-versions, contracts/L2/Scarb.toml, contracts/L2/.gitignore
Bump scarb to 2.12.0 and starknet-foundry to 0.48.x; update dependencies (starknet/assert_macros, snforge_std); add casm = true to StarkNet target; add Scarb.lock to .gitignore.
Storage Vec API updates
contracts/L2/src/.../ZeroXBridgeL2.cairo, contracts/L2/src/mocks/MockMerkleManager.cairo, contracts/L2/src/dao/Timelock.cairo
Replace append().write(...) patterns with push(...) for storage Vec insertions; control flow and signatures preserved.
Imports & feature flags
contracts/L2/src/dao/DAO.cairo, contracts/L2/src/dao/Timelock.cairo
Consolidate/adjust import paths; add #[feature("deprecated-starknet-consts")] in DAO; reorganize StarkNet/core imports.

Sequence Diagram(s)

No sequence diagram — changes are tooling/imports and local storage API adaptations; control-flow remains unchanged.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Assessment against linked issues

Objective Addressed Explanation
Update Scarb to 2.12.0 (#109)
Update Starknet Foundry to 0.48.0 (#109) Version updated to 0.48.1 in .tool-versions (not exactly 0.48.0).
Ensure contracts compile and all tests pass with updated tools (#109) No build or test artifacts in this diff to confirm successful compilation/tests.
Document breaking changes or required code adjustments (#109) No documentation or migration notes included in this diff.

Possibly related PRs

Suggested reviewers

  • Ugo-X

Poem

I hopped through lines of code and found a tiny tweak,
Replaced append with push — a hop, a skip, no break.
Scarb’s new shoes and CASM carrots gleam in morning light,
Tooling trimmed and imports set — the garden’s looking right.
Now tests to run and carrots tasted — hop on, code takes flight! 🐇🥕

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

Copy link

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
contracts/L2/src/dao/Timelock.cairo (1)

214-226: Bug: get_pending_actions iterates numeric IDs but actions are keyed by hashed IDs.

action_id is a Poseidon-based hash (see generate_action_id), not a sequential counter. Iterating 0..action_count and probing self.actions.entry(action_id) will miss most actions and can read uninitialized storage paths. This can yield incorrect results or undefined/default reads.

Suggested approach: track action IDs in a storage Vec and iterate that when building the pending list. Minimal change:

-        fn get_pending_actions(self: @TContractState) -> Array<felt252> {
-            let mut pending = ArrayTrait::new();
-            let count = self.action_count.read();
-
-            for i in 0..count {
-                let action_id: felt252 = i.into();
-                let action_entry = self.actions.entry(action_id);
-                if action_entry.status.read() == ActionStatus::Pending {
-                    pending.append(action_id);
-                }
-            };
-            pending
-        }
+        fn get_pending_actions(self: @TContractState) -> Array<felt252> {
+            let mut pending = ArrayTrait::new();
+            let ids_len = self.pending_ids.len();
+            for i in 0..ids_len {
+                let action_id = self.pending_ids.at(i).read();
+                let entry = self.actions.entry(action_id);
+                if entry.status.read() == ActionStatus::Pending {
+                    pending.append(action_id);
+                }
+            };
+            pending
+        }

Additional changes needed outside this range:

  • Add a storage Vec to track IDs and populate it when queuing actions.
// In Storage
pending_ids: Vec<felt252>,
// In queue_action, after setting status to Pending:
self.pending_ids.push(action_id);

Optionally, you can later compact pending_ids or keep it append-only and filter by status as shown.

contracts/L2/src/dao/DAO.cairo (1)

285-289: Poll voting is effectively disabled due to incorrect phase checks.
vote_in_poll and _is_in_poll_phase both require PollPassed, but the voting phase is PollActive. As written, no one can vote during the poll.

Update _is_in_poll_phase to check PollActive and time, and (optionally) align/remove the redundant direct status assert in vote_in_poll.

Apply this diff to fix _is_in_poll_phase:

-        fn _is_in_poll_phase(self: @ContractState, proposal_id: u256) -> bool {
-            let proposal = self.proposals.read(proposal_id);
-            let current_time = get_block_timestamp();
-            proposal.status == ProposalStatus::PollPassed && current_time <= proposal.poll_end_time
-        }
+        fn _is_in_poll_phase(self: @ContractState, proposal_id: u256) -> bool {
+            let proposal = self.proposals.read(proposal_id);
+            let current_time = get_block_timestamp();
+            proposal.status == ProposalStatus::PollActive && current_time <= proposal.poll_end_time
+        }

If you prefer to keep a direct status check in vote_in_poll, change it to PollActive (or remove it, see next comment).

Also applies to: 520-524

🧹 Nitpick comments (4)
contracts/L2/.gitignore (1)

5-6: Consider committing Scarb.lock for reproducible builds.

Ignoring Scarb.lock makes dependency resolution non-deterministic across dev/CI, which is risky when upgrading toolchains. Most contract repos commit Scarb.lock to ensure consistent compilation and bytecode reproducibility.

Apply this diff to stop ignoring the lockfile:

 .tool-versions
 node_modules
-.env
-Scarb.lock
+.env

If you prefer to keep it ignored, please document the rationale in CONTRIBUTING.md and pin exact dependency versions in Scarb.toml to reduce drift.

contracts/L2/src/dao/DAO.cairo (3)

281-294: Remove duplicate asserts and single-source vote count updates.

  • assert(!self.has_voted.read(...), 'Already voted') is present twice; keep one.
  • You update vote counts both via _update_vote_counts(...) and again on the local proposal copy. This results in two RMW cycles and can be simplified to a single source of truth (prefer the internal helper).

Minimal change to deduplicate the "Already voted" assert:

         fn vote_in_poll(ref self: ContractState, proposal_id: u256, support: bool) {
             let caller = get_caller_address();
             let mut proposal = self._validate_proposal_exists(proposal_id);

             assert(self._is_in_poll_phase(proposal_id), 'Not in poll phase');
-            assert(!self.has_voted.read((proposal_id, caller)), 'Already voted');
             assert(proposal.id == proposal_id, 'Proposal does not exist');
-            assert(proposal.status == ProposalStatus::PollPassed, 'Not in poll phase');

             let current_time = get_block_timestamp();
             assert(current_time <= proposal.poll_end_time, 'Poll phase ended');
             assert(!self.has_voted.read((proposal_id, caller)), 'Already voted');
             let vote_weight = self._get_voter_weight(caller);
             assert(vote_weight > 0, 'No voting power');
             self._update_vote_counts(proposal_id, support, vote_weight);
-            if support {
-                proposal.vote_for += vote_weight;
-            } else {
-                proposal.vote_against += vote_weight;
-            }
             self.proposals.write(proposal_id, proposal);

If you want, I can follow up with a patch that keeps all counting inside _update_vote_counts and only persists non-count fields from the local proposal here.


243-245: Nit: fix assertion message grammar.
Use “Binding vote already cast” (lowercase ‘vote’, ‘cast’ vs ‘casted’).

Apply this diff:

-            assert!(binding_vote.get_vote().is_none(), "Binding Vote Already casted");
+            assert!(binding_vote.get_vote().is_none(), "Binding vote already cast");

113-115: Deprecate contract_address_const and remove the deprecated StarkNet consts feature

We’re currently relying on #[feature("deprecated-starknet-consts")] and contract_address_const in production and tests, which is a temporary workaround that will break under future toolchains. To future-proof the DAO:

• Production code

  • contracts/L2/src/dao/DAO.cairo: lines 340, 371 – both initialize executive_action_address via contract_address_const::<0x0>().

• Test suite

  • contracts/L2/tests/**: dozens of calls to contract_address_const::<'…'>() across tests (e.g. test_L2Oracle.cairo, test_xZBERC20.cairo, test_Dynamicrate.cairo, test_ZeroXBridgeL2.cairo, test_DAO.cairo).

Refactor suggestion:

  1. In your Proposal struct, change
    pub executive_action_address: ContractAddress
    to
    pub executive_action_address: Option<ContractAddress>
  2. In create_proposal / submit_proposal, set executive_action_address: None.
  3. In start_binding_vote, assign executive_action_address = Some(execute_action_address).
  4. Update all current call sites (production & tests) to pass explicit addresses instead of using contract_address_const.

This change will let you drop the deprecated feature gate and remove all contract_address_const usages. Let me know if you’d like a full patch for the struct and affected call sites.

📜 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 a1058f2 and 6ff5124.

⛔ Files ignored due to path filters (1)
  • contracts/L2/Scarb.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • contracts/L2/.gitignore (1 hunks)
  • contracts/L2/.tool-versions (1 hunks)
  • contracts/L2/Scarb.toml (1 hunks)
  • contracts/L2/src/core/ZeroXBridgeL2.cairo (1 hunks)
  • contracts/L2/src/dao/DAO.cairo (2 hunks)
  • contracts/L2/src/dao/Timelock.cairo (1 hunks)
  • contracts/L2/src/mocks/MockMerkleManager.cairo (1 hunks)
🔇 Additional comments (10)
contracts/L2/.tool-versions (1)

1-2: Version bumps align with PR goals; looks good.

Upgrading to scarb 2.12.0 and starknet-foundry 0.48.1 is consistent with the stated objectives and recent ecosystem changes.

contracts/L2/src/mocks/MockMerkleManager.cairo (1)

98-98: Correct use of storage Vec.push with newer StarkNet toolchains.

Replacing append().write(...) with push(...) for storage Vec is the right API on recent Cairo/StarkNet versions. Semantics and gas profile are appropriate.

contracts/L2/src/dao/Timelock.cairo (1)

133-137: Good modernization: storage Vec.push is the correct pattern.

Using push to copy calldata into the storage Vec is correct and clearer than append().write with the updated storage API.

contracts/L2/src/core/ZeroXBridgeL2.cairo (2)

464-466: Correct migration to storage Vec.push.

Using push for appending the tail of peaks is the proper API in updated Cairo/StarkNet. The overwrite-then-append logic remains intact.


404-410: Inconsistent semantics vs. Mock: zeros are retained here but filtered in Mock get_last_peaks.

This implementation returns all stored peaks including zeros, whereas MockMerkleManager.get_last_peaks filters out zeros before returning. If MMR.append expects only the active peaks, consider normalizing both to the same behavior to avoid subtle divergence across environments.

Would you like me to harmonize both implementations to filter non-zero peaks before passing to MMR and emitting events?

contracts/L2/src/dao/DAO.cairo (2)

1-1: Import consolidation aligns with Starknet 2.12 APIs — looks good.
Using use starknet::{ContractAddress, storage::Map}; at the file scope cleanly supports types used outside the module (e.g., Proposal/ProposalBindingData). No concerns.


119-121: Storage import path update is correct for v2.12.
Switching to starknet::storage::{...} matches current module locations in the Starknet 2.12 toolchain.

contracts/L2/Scarb.toml (3)

24-24: casm = true is a sensible addition.
Keeping both sierra = true and casm = true is recommended for deployment pipelines still consuming CASM artifacts. No action needed.


10-10: Confirm OpenZeppelin 0.20.0 compatibility
Starknet bumped to 2.12.0 as intended. Scarb.toml now includes:

• starknet = "2.12.0"
• assert_macros = "2.12.0"
• snforge_std = "0.48.0"
• openzeppelin_access/introspection/token/upgrades/utils = "0.20.0"

.tool-versions also pins scarb 2.12.0 and starknet-foundry 0.48.1.

Please verify in your local build & test matrix that all OpenZeppelin 0.20.0 crates work correctly against Starknet 2.12.0.


18-20: Dev tooling bumps validated

We’ve confirmed in contracts/L2/Scarb.toml (lines 18–20) that
• assert_macros = "2.12.0"
• snforge_std = "0.48.0"

This aligns with Starknet Foundry 0.48.x. If you pin Foundry to 0.48.1, bump snforge_std to 0.48.1 for strict symmetry; otherwise 0.48.0 is acceptable.

Please verify:

  • Your local .tool-versions (or asdf config) for the Foundry version
  • That CI’s snforge installation matches the expected version

JoE11-y
JoE11-y previously approved these changes Aug 20, 2025
Copy link
Contributor

@JoE11-y JoE11-y left a comment

Choose a reason for hiding this comment

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

Thanks for this @GideonBature

@GideonBature
Copy link
Contributor Author

You are welcome. Thank you for the opportunity to keep contributing.

JoE11-y
JoE11-y previously approved these changes Aug 20, 2025
Copy link

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
contracts/L2/src/dao/Timelock.cairo (2)

257-266: High-bit truncation bug in u256 hashing causes information loss.

Masking high with 0x0FFFFFFFFFFFFFFFF retains only 64 bits (not 124 as the comment suggests), introducing avoidable collisions when compressing a u256. Both low and high (u128 each) fit into felt252 as separate field elements and do not require truncation before hashing.

Fix: hash high and low directly without masking.

Apply this diff:

-            // Truncate the high part to 124 bits (since felt252 can hold 252 bits: 128 + 124).
-            let truncated_high = high
-                & 0x0FFFFFFFFFFFFFFFF; // Mask to retain only the lower 124 bits.
-
-            // Use Poseidon hashing to combine the truncated high part and low part into a single
-            // felt252.
-            PoseidonTrait::new()
-                .update(truncated_high.into()) // Convert truncated_high to felt252.
-                .update(low.into()) // Convert low to felt252.
-                .finalize() // Finalize the hash to produce a single felt252.
+            // Hash the (high, low) limbs directly; both fit into felt252 without truncation.
+            PoseidonTrait::new()
+                .update(high.into())
+                .update(low.into())
+                .finalize()

Optional tightening: Instead of per-element hashing via u256_to_felt252, flatten each u256 into two felts and hash the entire flattened span in generate_action_id. I can provide a small refactor if preferred.


211-223: get_pending_actions incorrectly enumerates action IDs
The current implementation loops 0..action_count, converts each integer to a felt, and treats that as an action ID—but real IDs are Poseidon hashes, so this will never find the queued actions. You must explicitly track and iterate the actual IDs.

Please update contracts/L2/src/dao/Timelock.cairo as follows:

• In the Storage struct (around line 36), add a Vec<felt252> to record IDs:

     struct Storage {
         #[starknet::storage_node]
         actions: Map<felt252, ActionNode>,
-        action_count: u64,
+        action_count: u64,
+        #[starknet::storage_node]
+        action_ids: Vec<felt252>,
         minimum_delay: u64,
         governance: ContractAddress,
     }

• In queue_action (around line 136), after writing the new entry and before incrementing action_count, push the ID:

             action_entry.status.write(ActionStatus::Pending);
+            self.action_ids.push(action_id);
             self.action_count.write(self.action_count.read() + 1);

• Rewrite get_pending_actions (lines 211–223) to iterate over action_ids instead of 0..action_count:

-   fn get_pending_actions(self: @ContractState) -> Array<felt252> {
-       let mut pending = ArrayTrait::new();
-       let count = self.action_count.read();
-
-       for i in 0..count {
-           let action_id: felt252 = i.into();
-           let action_entry = self.actions.entry(action_id);
-           if action_entry.status.read() == ActionStatus::Pending {
-               pending.append(action_id);
-           }
-       }
-       pending
-   }
+   fn get_pending_actions(self: @ContractState) -> Array<felt252> {
+       let mut pending = ArrayTrait::new();
+       let count = self.action_ids.len();
+       let mut i = 0;
+       while i < count {
+           let action_id = self.action_ids.at(i).read();
+           let action_entry = self.actions.entry(action_id);
+           if action_entry.status.read() == ActionStatus::Pending {
+               pending.append(action_id);
+           }
+           i = i + 1;
+       }
+       pending
+   }

These changes ensure you enumerate exactly the IDs you’ve queued, then filter by status.

🧹 Nitpick comments (4)
contracts/L2/src/core/ZeroXBridgeL2.cairo (3)

311-321: Consider a graceful fallback when TVL is zero to avoid reverting during bootstrap.

Currently, total TVL of zero will cause an early assert failure, blocking mint/burn paths if the oracle hasn’t reported yet. Returning the baseline PRECISION when TVL is zero avoids dividing by zero, keeps behavior consistent with the “raw_rate == 0” case, and eases network bootstrap.

Proposed change:

-            assert(total_tvl > 0, 'TVL cannot be zero');
+            // Avoid division by zero during bootstrap/initialization.
+            if total_tvl == 0 {
+                return PRECISION;
+            }

Please confirm this aligns with product expectations and oracle behavior (i.e., whether zero TVL should pause operations or allow a default rate). If zero should be a hard stop, the current assert is fine.


338-347: Remove redundant inner braces in set_rates.

Minor cleanup for readability; the extra block scopes are unnecessary.

Apply this refactor:

-            if let Option::Some(new_min) = min_rate {
-                {
-                    current_rates.min_rate = new_min;
-                }
-            }
+            if let Option::Some(new_min) = min_rate {
+                current_rates.min_rate = new_min;
+            }
-            if let Option::Some(new_max) = max_rate {
-                {
-                    current_rates.max_rate = new_max;
-                }
-            }
+            if let Option::Some(new_max) = max_rate {
+                current_rates.max_rate = new_max;
+            }

444-463: Switch to Vec.push is correct for newer storage Vec APIs; consider shrinking instead of zero-filling (optional).

  • The replacement of append().write(...) with push(...) is the right API for the current toolchain.
  • Optional: when peaks_len < last_peaks_len, zero-filling the tail preserves length. If the MMR implementation accepts a shorter peaks vector (no trailing zeros required), shrinking the storage Vec (e.g., via a truncate/pop operation if available) would:
    • reduce storage reads/writes,
    • avoid persisting trailing zeros,
    • likely save gas.

If the storage Vec API provides a safe truncate/pop_back, consider using it here. If not, the current approach is acceptable and functionally safe given downstream code constructs the peaks Array explicitly.

Can you confirm whether starknet::storage::Vec exposes truncate or pop_back in your current Cairo/StarkNet version? If so, I can propose a concrete diff to replace the zero-fill loop.

contracts/L2/src/dao/Timelock.cairo (1)

126-134: Switch to storage Vec::push is correct; consider bounding calldata length.

The .push(element) change is the right API on newer Starknet storage Vecs. As a defensive measure, consider enforcing a max calldata length to avoid excessive storage writes in one transaction.

Example guard near the top of queue_action:

const MAX_CALLDATA_LEN: usize = 1024; // tune per your use-case

let calldata_length = calldata.len();
assert!(calldata_length <= MAX_CALLDATA_LEN, "Calldata too large");
📜 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 6ff5124 and 56cc79f.

📒 Files selected for processing (2)
  • contracts/L2/src/core/ZeroXBridgeL2.cairo (6 hunks)
  • contracts/L2/src/dao/Timelock.cairo (7 hunks)
🔇 Additional comments (9)
contracts/L2/src/core/ZeroXBridgeL2.cairo (5)

3-5: Imports updated for MMR and Array/Hash traits look correct.

These align with newer Cairo/StarkNet libraries and cover the traits used below (Poseidon hashing, arrays).


8-17: Interface and OZ/Upgrades imports align with updated toolchain.

The dispatcher/component imports match usage below; no API mismatches spotted.


21-27: Storage and env imports are consistent with the Vec push/write pointer usage.

Including MutableVecTrait and StoragePointer*Access is necessary for the later .at(...).write(...) and .push(...) calls. Looks good.


400-405: get_last_peaks readback looks good.

Iterating storage Vec and building a transient Array via .append is correct and matches downstream usage.


313-313: Semantics unchanged; minor clarity improvement.

Returning PRECISION directly (instead of 1 * PRECISION) improves readability with no behavioral change.

contracts/L2/src/dao/Timelock.cairo (4)

1-4: Imports modernization and consolidation LGTM.

Switching to core::{array, hash, integer, poseidon} and consolidating starknet imports aligns with newer Cairo/Starknet APIs. poseidon_hash_span is appropriately used later for hashing arrays.

Also applies to: 6-8


30-31: Correctly importing MutableVecTrait and super::*.

MutableVecTrait is required for .push() on storage Vec; use super::* keeps the dispatcher types (IExecutorDispatcher) in scope within the module. Good update.


90-92: Enum variants converted to unit-like; double-check storage/serde compatibility.

Changing from tuple-like empty variants to unit variants should preserve discriminants and thus on-chain encoding. If this contract upgrades in place against existing state, verify no storage decoding issues for ActionStatus.

Would you like me to generate a quick script to scan for any migrations or cross-contract serialization dependencies on ActionStatus?


170-175: No functional change; array reconstruction remains correct.

Loop still reconstructs calldata into memory for the executor call. Looks good.

@Ugo-X Ugo-X merged commit 34b99e4 into Explore-Beyond-Innovations:main Aug 20, 2025
1 check passed
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.

Update L2 Contracts to use latest tooling versions

3 participants