Skip to content

Spike 1: Add Soroban Events for Indexer#69

Open
codebestia wants to merge 8 commits intoTrustless-Work:single-release-developfrom
codebestia:spike1-add-soroban-events
Open

Spike 1: Add Soroban Events for Indexer#69
codebestia wants to merge 8 commits intoTrustless-Work:single-release-developfrom
codebestia:spike1-add-soroban-events

Conversation

@codebestia
Copy link

@codebestia codebestia commented Jul 25, 2025

CLR-S (2)

Pull Request | Trustless Work

1. Issue Link


2. Brief Description of the Issue

This PR is focused on implementing comprehensive Soroban events for the Trustless Work Smart Escrow contract to enable better indexing and monitoring capabilities. The implementation adds structured events for all major contract operations including escrow creation, funding, milestone management, dispute handling, and fund releases.


3. Changes Made

  • Created a new folder for my change (Contract-Events-for-Indexer)
  • Copied the escrow contract into the new folder
  • Added event publishing to major write actions
  • Document the changes in a new readme file

4. Evidence After Solution


5. Important Notes

Ongoing local test of event emission

Summary by CodeRabbit

  • New Features

    • Introduced a comprehensive escrow smart contract with support for escrow creation, funding, milestone management, dispute handling, and fund release.
    • Added event publishing for all major contract operations to enhance indexing and monitoring.
    • Implemented fee calculation and safe arithmetic operations for secure fund management.
  • Bug Fixes

    • Extensive unit tests added to verify correct handling of escrow lifecycle, milestones, disputes, fund distribution, and authorization checks.
  • Documentation

    • Added detailed README outlining contract event implementation, assumptions, and recommendations for best practices.
  • Chores

    • Added project manifest and structured modules for maintainability and clarity.

@coderabbitai
Copy link

coderabbitai bot commented Jul 25, 2025

Walkthrough

A new Rust-based smart contract module, "Contract-Events-for-Indexer," has been introduced to manage escrow workflows with Soroban event publishing for indexer integration. The implementation covers escrow initialization, funding, milestone management, dispute handling, and fund release, with comprehensive event emission, error handling, validation, fee calculation, storage structures, and extensive unit tests.

Changes

File(s) Change Summary
Cargo.toml, README.md Added new manifest and documentation for the contract event indexer module.
src/contract.rs Introduced main contract struct and methods for escrow lifecycle, emitting events for all major state transitions.
src/core/dispute.rs Added dispute management logic with event emission and token transfer for dispute lifecycle.
src/core/escrow.rs Implemented escrow management: initialization, funding, release, property changes, and balance queries.
src/core/milestone.rs Added milestone management: status and approval flag changes with event emission.
src/core/validators/dispute.rs Introduced validation functions for dispute resolution and flag changes.
src/core/validators/escrow.rs Added validation for escrow release, property changes, and initialization.
src/core/validators/milestone.rs Provided validation for milestone status and approval flag changes.
src/error.rs Defined comprehensive contract error enum and display implementation.
src/events/handler.rs Added event handler for publishing escrow state by contract ID.
src/lib.rs Organized module structure and re-exported public contract struct.
src/modules/fee/calculator.rs Implemented fee calculation logic for standard and dispute flows.
src/modules/math/basic.rs, src/modules/math/safe.rs Added safe arithmetic modules for overflow/underflow-checked math operations.
src/storage/types.rs Defined storage types: Escrow, Milestone, Roles, Flags, Trustline, AddressBalance, DataKey.
src/tests/test.rs Added comprehensive unit tests for all contract operations, events, and error scenarios.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Contract
    participant Token
    participant Indexer

    User->>Contract: initialize_escrow(escrow_props)
    Contract->>Contract: validate & store escrow
    Contract-->>Indexer: emit Event (escrow, created)
    
    User->>Contract: fund_escrow(signer, amount)
    Contract->>Token: transfer(signer -> contract, amount)
    Contract-->>Indexer: emit Event (escrow, funded)
    
    User->>Contract: change_milestone_status(index, status, evidence)
    Contract->>Contract: update milestone
    Contract-->>Indexer: emit Event (escrow, milestone_marked)
    
    User->>Contract: approve_milestone(index, flag)
    Contract->>Contract: update milestone approval
    Contract-->>Indexer: emit Event (escrow, milestone_approved)
    
    User->>Contract: release_funds(signer)
    Contract->>Contract: validate & calculate fees
    Contract->>Token: distribute funds
    Contract-->>Indexer: emit Event (escrow, released)
    
    User->>Contract: dispute_escrow(signer)
    Contract->>Contract: set disputed flag
    Contract-->>Indexer: emit Event (escrow, dispute_raised)
    
    User->>Contract: resolve_dispute(resolver, splits)
    Contract->>Contract: validate & distribute funds
    Contract->>Token: distribute funds
    Contract-->>Indexer: emit Event (escrow, dispute_resolved)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

In the ledger's warren, events now hop,
Each escrow's story, a carrot on top!
Milestones are marked, disputes resolved with flair,
Burrows of logic, with contracts to spare.
Indexers rejoice, for the signals are clear—
🥕 The rabbit devs have brought events here!

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

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

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 generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Documentation and Community

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

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

🧹 Nitpick comments (21)
contracts/Contract-Events-for-Indexer/src/storage/types.rs (4)

18-25: Consider using an enum for milestone status instead of String.

Using String for the status field reduces type safety and could lead to inconsistent status values. Consider defining a MilestoneStatus enum with variants like Pending, InProgress, Completed, Rejected.

+#[contracttype]
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum MilestoneStatus {
+    Pending,
+    InProgress,
+    Completed,
+    Rejected,
+}

 #[contracttype]
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub struct Milestone {
     pub description: String,
-    pub status: String,
+    pub status: MilestoneStatus,
     pub evidence: String,
     pub approved: bool,
 }

27-36: Consider consolidating roles to reduce complexity.

The Roles struct defines 6 different address roles, which may increase gas costs and complexity. Consider whether some roles could be combined or if all are necessary for the escrow functionality.


54-59: Missing PartialEq and Eq traits for AddressBalance.

The AddressBalance struct is missing PartialEq and Eq derive traits, which are present on other structs and may be needed for comparisons and testing.

 #[contracttype]
-#[derive(Clone)]
+#[derive(Clone, PartialEq, Eq)]
 pub struct AddressBalance {

61-66: DataKey enum may need expansion for comprehensive storage.

The DataKey enum currently only has Admin and Escrow variants. As the contract grows, you may need additional keys for storing milestones, disputes, or other entities separately.

Consider adding variants like:

 #[derive(Clone)]
 #[contracttype]
 pub enum DataKey {
     Admin,
     Escrow,
+    Milestone(String), // milestone_id
+    Dispute(String),   // dispute_id
+    UserEscrows(Address), // user-specific escrow lists
 }
contracts/Contract-Events-for-Indexer/Cargo.toml (1)

1-16: Well-configured Cargo.toml for Soroban smart contract development.

The manifest is properly structured with correct crate type, workspace dependencies, and development features. The configuration is appropriate for a smart contract spike.

Consider adding metadata for better documentation:

 [package]
 name = "Contract-Events-for-Indexer"
 version = "0.0.0"
 edition = "2021"
 publish = false
+authors = ["Trustless Work Team"]
+description = "Soroban escrow contract with comprehensive event indexing"
contracts/Contract-Events-for-Indexer/src/events/handler.rs (1)

5-13: Event publishing implementation is correct but needs documentation.

The event publishing logic is implemented correctly using Soroban's event system. The conversion to Val types and payload construction follows best practices.

However, consider the following improvements:

  1. Document the cryptic event topic: The topic "p_by_spdr" is unclear. Add documentation explaining what this represents.

  2. Add function documentation:

+/// Publishes an escrow event for indexing purposes.
+/// 
+/// # Arguments
+/// * `e` - The contract environment
+/// * `escrow_id` - Unique identifier for the escrow
+/// * `escrow` - The escrow data structure to be indexed
 pub fn escrows_by_contract_id(e: &Env, escrow_id: String, escrow: Escrow) {
  1. Consider more descriptive event topic:
-    let topics = (symbol_short!("p_by_spdr"),);
+    let topics = (symbol_short!("escrow_upd"),); // or "esc_update"
contracts/Contract-Events-for-Indexer/src/lib.rs (1)

39-42: Remove or update the "Work In Progress" comment.

The storage module appears to be complete with comprehensive type definitions. The WIP comment may be outdated and could confuse future maintainers.

-/// This module is currently Work In Progress.
+/// Storage types and data structures for the escrow contract.
 mod storage {
     pub mod types;
 }
contracts/Contract-Events-for-Indexer/src/modules/math/basic.rs (1)

10-18: Excellent use of checked arithmetic for financial safety.

The implementation correctly uses Rust's checked_add and checked_sub methods to prevent overflow and underflow, which is critical for financial operations in smart contracts. The error handling prevents silent arithmetic failures.

Consider adding documentation to explain the safety guarantees:

 impl BasicArithmetic for BasicMath {
+    /// Safely adds two i128 values, returning an error on overflow.
     fn safe_add(a: i128, b: i128) -> Result<i128, ContractError> {
         a.checked_add(b).ok_or(ContractError::Overflow)
     }

+    /// Safely subtracts two i128 values, returning an error on underflow.
     fn safe_sub(a: i128, b: i128) -> Result<i128, ContractError> {
         a.checked_sub(b).ok_or(ContractError::Underflow)
     }
 }
contracts/Contract-Events-for-Indexer/src/modules/math/safe.rs (1)

10-16: Consider adding input validation for divisor.

While the implementation handles division by zero through checked_div, consider adding explicit validation for divisor == 0 at the beginning of the function for clearer error messaging and early return.

 fn safe_mul_div(amount: i128, multiplier: i128, divisor: i128) -> Result<i128, ContractError> {
+    if divisor == 0 {
+        return Err(ContractError::DivisionError);
+    }
+    
     amount
         .checked_mul(multiplier)
         .ok_or(ContractError::Overflow)?
         .checked_div(divisor)
         .ok_or(ContractError::DivisionError)
 }
contracts/Contract-Events-for-Indexer/README.md (1)

22-26: Consider adding concrete examples and implementation details.

The recommendations are valuable, but the documentation would benefit from including:

  • Specific event structure examples with data types
  • Code snippets showing event emission patterns
  • Testing strategy beyond basic event publishing
  • Performance benchmarks for event publishing costs
contracts/Contract-Events-for-Indexer/src/core/validators/milestone.rs (1)

19-21: Consider refactoring duplicate bounds checking logic.

Both validation functions contain identical bounds checking logic. Consider extracting this into a helper function to reduce code duplication.

+fn validate_milestone_index(escrow: &Escrow, milestone_index: i128) -> Result<(), ContractError> {
+    if escrow.milestones.is_empty() {
+        return Err(ContractError::NoMileStoneDefined);
+    }
+    
+    if milestone_index < 0 || milestone_index >= escrow.milestones.len() as i128 {
+        return Err(ContractError::InvalidMileStoneIndex);
+    }
+    
+    Ok(())
+}

Also applies to: 40-42

contracts/Contract-Events-for-Indexer/src/core/validators/escrow.rs (2)

69-72: Consider using reference instead of taking ownership.

The escrow_properties parameter is only used for reading values, so it should take a reference instead of ownership for better performance and API design.

 pub fn validate_initialize_escrow_conditions(
     e: Env,
-    escrow_properties: Escrow,
+    escrow_properties: &Escrow,
 ) -> Result<(), ContractError> {

81-83: Consider making milestone limit configurable.

The hardcoded limit of 10 milestones should be made configurable or defined as a constant to improve maintainability.

+const MAX_MILESTONES: usize = 10;
+
 pub fn validate_initialize_escrow_conditions(
     // ... parameters
 ) -> Result<(), ContractError> {
     // ... other validations
     
-    if escrow_properties.milestones.len() > 10 {
+    if escrow_properties.milestones.len() > MAX_MILESTONES {
         return Err(ContractError::TooManyMilestones);
     }
contracts/Contract-Events-for-Indexer/src/core/milestone.rs (3)

30-33: Remove redundant milestone index validation

The milestone index is already validated in validate_milestone_status_change_conditions at line 24-28. The .ok_or() check here is redundant since the validation ensures the index is valid.

-let mut milestone_to_update = existing_escrow
-    .milestones
-    .get(milestone_index as u32)
-    .ok_or(ContractError::InvalidMileStoneIndex)?;
+let mut milestone_to_update = existing_escrow
+    .milestones
+    .get(milestone_index as u32)
+    .unwrap();

38-38: Remove trailing whitespace

-        
+

62-65: Remove redundant milestone index validation

Same as the previous method, the milestone index is already validated in validate_milestone_flag_change_conditions. The .ok_or() check is redundant.

-let mut milestone_to_update = existing_escrow
-    .milestones
-    .get(milestone_index as u32)
-    .ok_or(ContractError::InvalidMileStoneIndex)?;
+let mut milestone_to_update = existing_escrow
+    .milestones
+    .get(milestone_index as u32)
+    .unwrap();
contracts/Contract-Events-for-Indexer/src/core/dispute.rs (1)

35-37: Consider removing redundant balance check

This balance check appears redundant since validate_dispute_resolution_conditions at line 47 also validates funds against the current balance.

contracts/Contract-Events-for-Indexer/src/tests/test.rs (4)

13-13: Remove commented out import

This commented import is not being used and should be removed to keep the code clean.

-// use test_token::token::{Token, TokenClient};

528-528: Consider extracting hardcoded commission value

The trustless work commission calculation uses a hardcoded value of 30 (basis points). Consider extracting this to a constant to ensure it matches the contract's actual commission rate.

+    const TRUSTLESS_WORK_COMMISSION_BPS: i128 = 30; // 0.3%
     let total_amount = amount as i128;
-    let trustless_work_commission = ((total_amount * 30) / 10000) as i128;
+    let trustless_work_commission = ((total_amount * TRUSTLESS_WORK_COMMISSION_BPS) / 10000) as i128;

788-788: Consider extracting hardcoded commission value

The trustless work commission calculation uses a hardcoded value of 30 (basis points). Consider extracting this to a constant for consistency.

+    const TRUSTLESS_WORK_COMMISSION_BPS: i128 = 30; // 0.3%
     let total_amount = amount as i128;
-    let trustless_work_commission = ((total_amount * 30) / 10000) as i128;
+    let trustless_work_commission = ((total_amount * TRUSTLESS_WORK_COMMISSION_BPS) / 10000) as i128;

1132-1132: Consider extracting hardcoded commission value

The trustless work commission calculation uses a hardcoded value of 30 (basis points). Consider extracting this to a constant for consistency across all tests.

+    const TRUSTLESS_WORK_COMMISSION_BPS: i128 = 30; // 0.3%
     let total_amount = amount as i128;
-    let trustless_work_commission = ((total_amount * 30) / 10000) as i128;
+    let trustless_work_commission = ((total_amount * TRUSTLESS_WORK_COMMISSION_BPS) / 10000) as i128;
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5d4669d and cd94687.

⛔ Files ignored due to path filters (2)
  • .DS_Store is excluded by !**/.DS_Store
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (17)
  • contracts/Contract-Events-for-Indexer/Cargo.toml (1 hunks)
  • contracts/Contract-Events-for-Indexer/README.md (1 hunks)
  • contracts/Contract-Events-for-Indexer/src/contract.rs (1 hunks)
  • contracts/Contract-Events-for-Indexer/src/core/dispute.rs (1 hunks)
  • contracts/Contract-Events-for-Indexer/src/core/escrow.rs (1 hunks)
  • contracts/Contract-Events-for-Indexer/src/core/milestone.rs (1 hunks)
  • contracts/Contract-Events-for-Indexer/src/core/validators/dispute.rs (1 hunks)
  • contracts/Contract-Events-for-Indexer/src/core/validators/escrow.rs (1 hunks)
  • contracts/Contract-Events-for-Indexer/src/core/validators/milestone.rs (1 hunks)
  • contracts/Contract-Events-for-Indexer/src/error.rs (1 hunks)
  • contracts/Contract-Events-for-Indexer/src/events/handler.rs (1 hunks)
  • contracts/Contract-Events-for-Indexer/src/lib.rs (1 hunks)
  • contracts/Contract-Events-for-Indexer/src/modules/fee/calculator.rs (1 hunks)
  • contracts/Contract-Events-for-Indexer/src/modules/math/basic.rs (1 hunks)
  • contracts/Contract-Events-for-Indexer/src/modules/math/safe.rs (1 hunks)
  • contracts/Contract-Events-for-Indexer/src/storage/types.rs (1 hunks)
  • contracts/Contract-Events-for-Indexer/src/tests/test.rs (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (5)
contracts/Contract-Events-for-Indexer/src/lib.rs (1)
contracts/Contract-Events-for-Indexer/src/events/handler.rs (1)
  • escrows_by_contract_id (5-13)
contracts/Contract-Events-for-Indexer/src/core/milestone.rs (3)
contracts/Contract-Events-for-Indexer/src/events/handler.rs (1)
  • escrows_by_contract_id (5-13)
contracts/Contract-Events-for-Indexer/src/core/validators/milestone.rs (2)
  • validate_milestone_flag_change_conditions (27-45)
  • validate_milestone_status_change_conditions (6-24)
contracts/Contract-Events-for-Indexer/src/core/escrow.rs (2)
  • e (126-126)
  • get_escrow (129-134)
contracts/Contract-Events-for-Indexer/src/core/dispute.rs (6)
contracts/Contract-Events-for-Indexer/src/events/handler.rs (1)
  • escrows_by_contract_id (5-13)
contracts/Contract-Events-for-Indexer/src/core/validators/dispute.rs (2)
  • validate_dispute_flag_change_conditions (43-72)
  • validate_dispute_resolution_conditions (10-40)
contracts/Contract-Events-for-Indexer/src/contract.rs (3)
  • resolve_dispute (164-184)
  • get_escrow (101-103)
  • dispute_escrow (186-194)
contracts/Contract-Events-for-Indexer/src/core/escrow.rs (3)
  • e (126-126)
  • get_escrow (129-134)
  • get_receiver (16-22)
contracts/Contract-Events-for-Indexer/src/modules/math/basic.rs (2)
  • safe_add (6-6)
  • safe_add (11-13)
contracts/Contract-Events-for-Indexer/src/modules/fee/calculator.rs (2)
  • calculate_dispute_fees (33-38)
  • calculate_dispute_fees (67-107)
contracts/Contract-Events-for-Indexer/src/modules/fee/calculator.rs (2)
contracts/Contract-Events-for-Indexer/src/modules/math/safe.rs (2)
  • safe_mul_div (6-6)
  • safe_mul_div (10-16)
contracts/Contract-Events-for-Indexer/src/modules/math/basic.rs (4)
  • safe_sub (7-7)
  • safe_sub (15-17)
  • safe_add (6-6)
  • safe_add (11-13)
contracts/Contract-Events-for-Indexer/src/core/escrow.rs (3)
contracts/Contract-Events-for-Indexer/src/core/validators/escrow.rs (3)
  • validate_escrow_property_change_conditions (41-66)
  • validate_initialize_escrow_conditions (69-86)
  • validate_release_conditions (9-38)
contracts/Contract-Events-for-Indexer/src/contract.rs (6)
  • initialize_escrow (44-53)
  • fund_escrow (55-67)
  • get_escrow (101-103)
  • release_funds (69-85)
  • get_multiple_escrow_balances (112-118)
  • get_escrow_by_contract_id (105-110)
contracts/Contract-Events-for-Indexer/src/modules/fee/calculator.rs (2)
  • calculate_standard_fees (28-31)
  • calculate_standard_fees (45-65)
🔇 Additional comments (17)
contracts/Contract-Events-for-Indexer/src/storage/types.rs (1)

3-16: Well-structured core escrow entity with comprehensive fields.

The Escrow struct effectively captures all necessary escrow data. The field organization is logical and the use of #[contracttype] with appropriate derive traits is correct for Soroban contracts.

contracts/Contract-Events-for-Indexer/src/lib.rs (3)

1-16: Excellent module organization with proper separation of concerns.

The module structure is well-designed with logical groupings for core business logic, validators, events, and utilities. The re-exports provide a clean API surface.


18-21: Appropriate visibility for event handler re-export.

The use of pub(crate) for the event handler re-export is correct, keeping event publishing internal to the contract while making it accessible across modules.


48-48: EscrowContract implementation verified

The EscrowContract struct is defined with #[contract] and has a #[contractimpl] block in contracts/Contract-Events-for-Indexer/src/contract.rs (and similarly in the escrow crate). All required Soroban methods are present. No changes needed.

contracts/Contract-Events-for-Indexer/src/modules/math/basic.rs (2)

3-8: Well-designed trait-based approach for safe arithmetic.

The trait abstraction allows for different implementations and the method signatures are appropriate for safe arithmetic operations in financial contracts.


15-17: ContractError::Underflow is defined and correctly used

The Underflow variant is declared in contracts/Contract-Events-for-Indexer/src/error.rs (line 39) with a matching Display implementation (“This operation can cause an Underflow”). Its semantics align with checked_sub failing on out‐of‐bounds subtraction. No changes needed here.

contracts/Contract-Events-for-Indexer/src/modules/math/safe.rs (1)

1-17: Well-implemented safe arithmetic module with proper overflow protection.

The implementation correctly uses Rust's checked_mul and checked_div to prevent arithmetic overflow and division by zero errors. The error handling is appropriate and integrates well with the contract's error system.

contracts/Contract-Events-for-Indexer/README.md (1)

1-26: Comprehensive documentation with clear structure and practical insights.

The README effectively documents the spike findings and provides valuable context for the Soroban events implementation. The structure covering overview, findings, assumptions, and recommendations is well-organized.

contracts/Contract-Events-for-Indexer/src/error.rs (1)

4-52: Comprehensive error handling system with good coverage.

The error enum provides excellent coverage of all contract operations with unique error codes and descriptive variants. The integration with Soroban SDK through the contracterror attribute is appropriate.

contracts/Contract-Events-for-Indexer/src/core/validators/escrow.rs (2)

8-38: Solid release validation logic with comprehensive checks.

The validation correctly checks all necessary conditions for fund release: authorization, completion status, milestone approval, and dispute state. The logic flow is appropriate and follows fail-fast principles.


21-23: All milestone-related error variant usages match definitions in error.rs

I’ve confirmed that each ContractError variant used in the milestone and escrow validators (e.g. NoMileStoneDefined, InvalidMileStoneIndex, OnlyServiceProviderChangeMilstoneStatus, OnlyApproverChangeMilstoneFlag) exactly matches the enum entries in src/error.rs. There are no reference mismatches in these validator files.

If the goal is to correct the spelling of “Milstone” to “Milestone,” that should be done in error.rs (and then propagated here). As-is, no changes are required in the validator code.

contracts/Contract-Events-for-Indexer/src/core/validators/dispute.rs (2)

43-72: Well-structured authorization validation

The validation logic correctly checks for duplicate disputes and comprehensively validates all authorized roles.


31-37: Fix incorrect fund validation logic

The validation conditions appear to be inverted. You're checking if the input funds are less than the net funds (after fees), but the net funds should always be less than the input funds since fees are deducted.

-if approver_funds < fee_result.net_approver_funds {
-    return Err(ContractError::InsufficientApproverFundsForCommissions);
-}
-
-if receiver_funds < fee_result.net_receiver_funds {
-    return Err(ContractError::InsufficientServiceProviderFundsForCommissions);
-}
+if fee_result.net_approver_funds > approver_funds {
+    return Err(ContractError::InsufficientApproverFundsForCommissions);
+}
+
+if fee_result.net_receiver_funds > receiver_funds {
+    return Err(ContractError::InsufficientReceiverFundsForCommissions);
+}

Also note that the error message on line 36 mentions "ServiceProviderFunds" but should be "ReceiverFunds" for consistency.

Likely an incorrect or invalid review comment.

contracts/Contract-Events-for-Indexer/src/modules/fee/calculator.rs (2)

45-65: Correct fee calculation implementation

The standard fee calculation correctly uses safe arithmetic and properly deducts fees in sequence to avoid negative values.


67-107: Well-implemented proportional fee distribution

The dispute fee calculation correctly:

  • Handles the edge case of zero total funds
  • Distributes fees proportionally based on each party's share
  • Uses safe arithmetic to prevent overflow/underflow
contracts/Contract-Events-for-Indexer/src/core/dispute.rs (2)

78-89: Clean dispute flagging implementation

The method correctly follows the pattern of authentication, validation, state update, and event emission.


57-67: Ensure token transfer failures are handled explicitly

Before finalizing, please confirm whether TokenClient::transfer returns a Result<_, _> or panics on failure. If it returns a Result, propagate errors with ? or handle them; if it panics, consider matching its return value (if any) or wrapping the call in a recoverable construct. In resolve_dispute (contracts/Contract-Events-for-Indexer/src/core/dispute.rs), each of these calls needs explicit error handling:

  • Line 57:
    token_client.transfer(&contract_address, &trustless_work_address, &fee_result.trustless_work_fee);
  • Line 58:
    token_client.transfer(&contract_address, &escrow.roles.platform_address, &fee_result.platform_fee);
  • Line 61 (inside if net_approver_funds > 0):
    token_client.transfer(&contract_address, &escrow.roles.approver, &fee_result.net_approver_funds);
  • Line 65 (inside if net_receiver_funds > 0):
    token_client.transfer(&contract_address, &receiver, &fee_result.net_receiver_funds);

Suggested patterns:

- token_client.transfer(...);
+ token_client.transfer(...)?; // propagate error

or

if let Err(e) = token_client.transfer(...) {
    return Err(ContractError::TokenTransferFailed);
}

Comment on lines +87 to +99
pub fn update_escrow(
e: Env,
plataform_address: Address,
escrow_properties: Escrow,
) -> Result<Escrow, ContractError> {
let updated_escrow = EscrowManager::change_escrow_properties(
e.clone(),
plataform_address.clone(),
escrow_properties.clone(),
)?;

Ok(updated_escrow)
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add event emission for escrow updates

The update_escrow function modifies escrow state but doesn't emit an event. For consistency with other state-changing functions and to support proper indexing, an event should be emitted.

     pub fn update_escrow(
         e: Env,
-        plataform_address: Address,
+        platform_address: Address,
         escrow_properties: Escrow,
     ) -> Result<Escrow, ContractError> {
         let updated_escrow = EscrowManager::change_escrow_properties(
             e.clone(),
-            plataform_address.clone(),
+            platform_address.clone(),
             escrow_properties.clone(),
         )?;
+        e.events().publish(
+            (symbol_short!("escrow"), symbol_short!("updated")),
+            (updated_escrow.engagement_id.clone(), platform_address)
+        );
         
         Ok(updated_escrow)
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pub fn update_escrow(
e: Env,
plataform_address: Address,
escrow_properties: Escrow,
) -> Result<Escrow, ContractError> {
let updated_escrow = EscrowManager::change_escrow_properties(
e.clone(),
plataform_address.clone(),
escrow_properties.clone(),
)?;
Ok(updated_escrow)
}
pub fn update_escrow(
e: Env,
platform_address: Address,
escrow_properties: Escrow,
) -> Result<Escrow, ContractError> {
let updated_escrow = EscrowManager::change_escrow_properties(
e.clone(),
platform_address.clone(),
escrow_properties.clone(),
)?;
e.events().publish(
(symbol_short!("escrow"), symbol_short!("updated")),
(updated_escrow.engagement_id.clone(), platform_address)
);
Ok(updated_escrow)
}
🤖 Prompt for AI Agents
In contracts/Contract-Events-for-Indexer/src/contract.rs around lines 87 to 99,
the update_escrow function updates escrow state but does not emit an event.
Modify the function to emit an event after successfully updating the escrow by
calling the appropriate event emission method with relevant escrow update
details. This will ensure consistency with other state-changing functions and
support proper indexing.


pub fn update_escrow(
e: Env,
plataform_address: Address,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix typo in parameter name

The parameter name contains a typo: "plataform_address" should be "platform_address".

-        plataform_address: Address,
+        platform_address: Address,

Also update the usage on line 94:

-            plataform_address.clone(),
+            platform_address.clone(),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
plataform_address: Address,
pub fn update_escrow(
env: Env,
engagement_id: u64,
- plataform_address: Address,
+ platform_address: Address,
arbiter_address: Address,
dispute_resolution_address: Address,
) -> Result<(), Error> {
// Delegate to manager with updated properties
EscrowManager::change_escrow_properties(
env,
engagement_id,
- plataform_address.clone(),
+ platform_address.clone(),
arbiter_address.clone(),
dispute_resolution_address.clone(),
)?;
Ok(())
}
🤖 Prompt for AI Agents
In contracts/Contract-Events-for-Indexer/src/contract.rs at line 89, correct the
typo in the parameter name from "plataform_address" to "platform_address". Also,
update all usages of this parameter, including the one at line 94, to use the
corrected name "platform_address" to maintain consistency and avoid errors.

Comment on lines +32 to +42
pub fn fund_escrow(
e: Env,
signer: Address,
amount_to_deposit: i128,
) -> Result<(), ContractError> {
signer.require_auth();
let escrow = Self::get_escrow(e.clone())?;
let token_client = TokenClient::new(&e, &escrow.trustline.address);
token_client.transfer(&signer, &e.current_contract_address(), &amount_to_deposit);
Ok(())
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add amount validation and error handling

The method should validate that amount_to_deposit is positive and handle potential transfer failures.

 pub fn fund_escrow(
     e: Env,
     signer: Address,
     amount_to_deposit: i128,
 ) -> Result<(), ContractError> {
     signer.require_auth();
+    if amount_to_deposit <= 0 {
+        return Err(ContractError::AmountCannotBeZero);
+    }
     let escrow = Self::get_escrow(e.clone())?;
     let token_client = TokenClient::new(&e, &escrow.trustline.address);
     token_client.transfer(&signer, &e.current_contract_address(), &amount_to_deposit);
     Ok(())
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pub fn fund_escrow(
e: Env,
signer: Address,
amount_to_deposit: i128,
) -> Result<(), ContractError> {
signer.require_auth();
let escrow = Self::get_escrow(e.clone())?;
let token_client = TokenClient::new(&e, &escrow.trustline.address);
token_client.transfer(&signer, &e.current_contract_address(), &amount_to_deposit);
Ok(())
}
pub fn fund_escrow(
e: Env,
signer: Address,
amount_to_deposit: i128,
) -> Result<(), ContractError> {
signer.require_auth();
if amount_to_deposit <= 0 {
return Err(ContractError::AmountCannotBeZero);
}
let escrow = Self::get_escrow(e.clone())?;
let token_client = TokenClient::new(&e, &escrow.trustline.address);
token_client.transfer(&signer, &e.current_contract_address(), &amount_to_deposit);
Ok(())
}
🤖 Prompt for AI Agents
In contracts/Contract-Events-for-Indexer/src/core/escrow.rs around lines 32 to
42, the fund_escrow function lacks validation for the amount_to_deposit and does
not handle transfer errors. Add a check to ensure amount_to_deposit is positive,
returning an appropriate ContractError if not. Also, modify the
token_client.transfer call to handle its Result return value, propagating any
errors instead of ignoring them.

Comment on lines +53 to +70
escrow.flags.released = true;
e.storage().instance().set(&DataKey::Escrow, &escrow);

let contract_address = e.current_contract_address();
let token_client = TokenClient::new(&e, &escrow.trustline.address);

if token_client.balance(&contract_address) < escrow.amount {
return Err(ContractError::EscrowBalanceNotEnoughToSendEarnings);
}

let fee_result =
FeeCalculator::calculate_standard_fees(escrow.amount as i128, escrow.platform_fee as i128)?;

token_client.transfer(&contract_address, &trustless_work_address, &fee_result.trustless_work_fee);
token_client.transfer(&contract_address, &escrow.roles.platform_address, &fee_result.platform_fee);

let receiver = Self::get_receiver(&escrow);
token_client.transfer(&contract_address, &receiver, &fee_result.receiver_amount);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Critical: Update state after successful transfers

The escrow state is marked as released before the token transfers occur. If any transfer fails, the escrow will be in an inconsistent state (marked as released but funds not distributed).

 validate_release_conditions(&escrow, &release_signer)?;
 
-escrow.flags.released = true;
-e.storage().instance().set(&DataKey::Escrow, &escrow);
-
 let contract_address = e.current_contract_address();
 let token_client = TokenClient::new(&e, &escrow.trustline.address);
 
 if token_client.balance(&contract_address) < escrow.amount {
     return Err(ContractError::EscrowBalanceNotEnoughToSendEarnings);
 }
 
 let fee_result =
     FeeCalculator::calculate_standard_fees(escrow.amount as i128, escrow.platform_fee as i128)?;
 
 token_client.transfer(&contract_address, &trustless_work_address, &fee_result.trustless_work_fee);
 token_client.transfer(&contract_address, &escrow.roles.platform_address, &fee_result.platform_fee);
 
 let receiver = Self::get_receiver(&escrow);
 token_client.transfer(&contract_address, &receiver, &fee_result.receiver_amount);
+
+escrow.flags.released = true;
+e.storage().instance().set(&DataKey::Escrow, &escrow);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
escrow.flags.released = true;
e.storage().instance().set(&DataKey::Escrow, &escrow);
let contract_address = e.current_contract_address();
let token_client = TokenClient::new(&e, &escrow.trustline.address);
if token_client.balance(&contract_address) < escrow.amount {
return Err(ContractError::EscrowBalanceNotEnoughToSendEarnings);
}
let fee_result =
FeeCalculator::calculate_standard_fees(escrow.amount as i128, escrow.platform_fee as i128)?;
token_client.transfer(&contract_address, &trustless_work_address, &fee_result.trustless_work_fee);
token_client.transfer(&contract_address, &escrow.roles.platform_address, &fee_result.platform_fee);
let receiver = Self::get_receiver(&escrow);
token_client.transfer(&contract_address, &receiver, &fee_result.receiver_amount);
validate_release_conditions(&escrow, &release_signer)?;
let contract_address = e.current_contract_address();
let token_client = TokenClient::new(&e, &escrow.trustline.address);
if token_client.balance(&contract_address) < escrow.amount {
return Err(ContractError::EscrowBalanceNotEnoughToSendEarnings);
}
let fee_result =
FeeCalculator::calculate_standard_fees(escrow.amount as i128, escrow.platform_fee as i128)?;
token_client.transfer(&contract_address, &trustless_work_address, &fee_result.trustless_work_fee);
token_client.transfer(&contract_address, &escrow.roles.platform_address, &fee_result.platform_fee);
let receiver = Self::get_receiver(&escrow);
token_client.transfer(&contract_address, &receiver, &fee_result.receiver_amount);
escrow.flags.released = true;
e.storage().instance().set(&DataKey::Escrow, &escrow);
🤖 Prompt for AI Agents
In contracts/Contract-Events-for-Indexer/src/core/escrow.rs around lines 53 to
70, the escrow state is set to released before the token transfers, risking
inconsistent state if a transfer fails. To fix this, move the line setting
escrow.flags.released = true and the subsequent state update to after all token
transfers have successfully completed, ensuring the state only updates once all
transfers succeed.

Comment on lines +97 to +120
pub fn get_multiple_escrow_balances(
e: Env,
signer: Address,
addresses: Vec<Address>,
) -> Result<Vec<AddressBalance>, ContractError> {
signer.require_auth();
const MAX_ESCROWS: u32 = 20;
if addresses.len() > MAX_ESCROWS {
return Err(ContractError::TooManyEscrowsRequested);
}

let mut balances: Vec<AddressBalance> = Vec::new(&e);
for address in addresses.iter() {
let escrow = Self::get_escrow_by_contract_id(e.clone(), &address)?;
let token_client = TokenClient::new(&e, &escrow.trustline.address);
let balance = token_client.balance(&address);
balances.push_back(AddressBalance {
address: address.clone(),
balance,
trustline_decimals: escrow.trustline.decimals,
});
}
Ok(balances)
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Handle cross-contract call failures and consider performance

The method makes multiple cross-contract calls in a loop which could fail and may have performance implications.

Consider:

  1. Wrapping the cross-contract call in error handling to continue on failure
  2. Implementing batch operations if the number of queries is frequently high
  3. Documenting the gas cost implications of multiple cross-contract calls
 for address in addresses.iter() {
-    let escrow = Self::get_escrow_by_contract_id(e.clone(), &address)?;
-    let token_client = TokenClient::new(&e, &escrow.trustline.address);
-    let balance = token_client.balance(&address);
-    balances.push_back(AddressBalance {
-        address: address.clone(),
-        balance,
-        trustline_decimals: escrow.trustline.decimals,
-    });
+    match Self::get_escrow_by_contract_id(e.clone(), &address) {
+        Ok(escrow) => {
+            let token_client = TokenClient::new(&e, &escrow.trustline.address);
+            let balance = token_client.balance(&address);
+            balances.push_back(AddressBalance {
+                address: address.clone(),
+                balance,
+                trustline_decimals: escrow.trustline.decimals,
+            });
+        }
+        Err(_) => {
+            // Skip failed contract calls or add default entry
+            continue;
+        }
+    }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pub fn get_multiple_escrow_balances(
e: Env,
signer: Address,
addresses: Vec<Address>,
) -> Result<Vec<AddressBalance>, ContractError> {
signer.require_auth();
const MAX_ESCROWS: u32 = 20;
if addresses.len() > MAX_ESCROWS {
return Err(ContractError::TooManyEscrowsRequested);
}
let mut balances: Vec<AddressBalance> = Vec::new(&e);
for address in addresses.iter() {
let escrow = Self::get_escrow_by_contract_id(e.clone(), &address)?;
let token_client = TokenClient::new(&e, &escrow.trustline.address);
let balance = token_client.balance(&address);
balances.push_back(AddressBalance {
address: address.clone(),
balance,
trustline_decimals: escrow.trustline.decimals,
});
}
Ok(balances)
}
pub fn get_multiple_escrow_balances(
e: Env,
signer: Address,
addresses: Vec<Address>,
) -> Result<Vec<AddressBalance>, ContractError> {
signer.require_auth();
const MAX_ESCROWS: u32 = 20;
if addresses.len() > MAX_ESCROWS {
return Err(ContractError::TooManyEscrowsRequested);
}
let mut balances: Vec<AddressBalance> = Vec::new(&e);
for address in addresses.iter() {
match Self::get_escrow_by_contract_id(e.clone(), &address) {
Ok(escrow) => {
let token_client = TokenClient::new(&e, &escrow.trustline.address);
let balance = token_client.balance(&address);
balances.push_back(AddressBalance {
address: address.clone(),
balance,
trustline_decimals: escrow.trustline.decimals,
});
}
Err(_) => {
// Skip failed contract lookups; optionally record defaults or log
continue;
}
}
}
Ok(balances)
}
🤖 Prompt for AI Agents
In contracts/Contract-Events-for-Indexer/src/core/escrow.rs around lines 97 to
120, the get_multiple_escrow_balances function makes multiple cross-contract
calls inside a loop without error handling, which can cause the entire call to
fail if one call fails and may impact performance. Modify the code to wrap each
cross-contract call in error handling so that failures for individual addresses
do not abort the entire process, allowing the function to continue processing
other addresses. Additionally, consider implementing batch operations if
frequent high-volume queries occur to optimize performance. Finally, add
documentation comments explaining the gas cost implications of making multiple
cross-contract calls in this method.

Comment on lines +103 to +110
ContractError::OnlyServiceProviderChangeMilstoneStatus => {
write!(f, "Only the service provider can change milestone status")
}
ContractError::NoMileStoneDefined => write!(f, "Escrow initialized without milestone"),
ContractError::InvalidMileStoneIndex => write!(f, "Invalid milestone index"),
ContractError::OnlyApproverChangeMilstoneFlag => {
write!(f, "Only the approver can change milestone flag")
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Update Display implementation to match corrected error variants.

The Display implementation needs to be updated to match the corrected error variant names.

-            ContractError::OnlyServiceProviderChangeMilstoneStatus => {
+            ContractError::OnlyServiceProviderChangeMilestoneStatus => {
                 write!(f, "Only the service provider can change milestone status")
             }
-            ContractError::NoMileStoneDefined => write!(f, "Escrow initialized without milestone"),
-            ContractError::InvalidMileStoneIndex => write!(f, "Invalid milestone index"),
-            ContractError::OnlyApproverChangeMilstoneFlag => {
+            ContractError::NoMilestoneDefined => write!(f, "Escrow initialized without milestone"),
+            ContractError::InvalidMilestoneIndex => write!(f, "Invalid milestone index"),
+            ContractError::OnlyApproverChangeMilestoneFlag => {
                 write!(f, "Only the approver can change milestone flag")
             }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ContractError::OnlyServiceProviderChangeMilstoneStatus => {
write!(f, "Only the service provider can change milestone status")
}
ContractError::NoMileStoneDefined => write!(f, "Escrow initialized without milestone"),
ContractError::InvalidMileStoneIndex => write!(f, "Invalid milestone index"),
ContractError::OnlyApproverChangeMilstoneFlag => {
write!(f, "Only the approver can change milestone flag")
}
ContractError::OnlyServiceProviderChangeMilestoneStatus => {
write!(f, "Only the service provider can change milestone status")
}
ContractError::NoMilestoneDefined => write!(f, "Escrow initialized without milestone"),
ContractError::InvalidMilestoneIndex => write!(f, "Invalid milestone index"),
ContractError::OnlyApproverChangeMilestoneFlag => {
write!(f, "Only the approver can change milestone flag")
}
🤖 Prompt for AI Agents
In contracts/Contract-Events-for-Indexer/src/error.rs around lines 103 to 110,
the Display implementation uses outdated or incorrect error variant names.
Review the current enum variant names for ContractError and update all
references in the Display match arms to use the corrected variant names exactly
as defined, ensuring consistency and correctness in error message handling.

Comment on lines +123 to +125
ContractError::AmountToDepositGreatherThanEscrowAmount => {
write!(f, "Amount to deposit is greater than the escrow amount")
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix typo in error variant name.

There's a spelling error in the error variant name.

-    AmountToDepositGreatherThanEscrowAmount => {
-        write!(f, "Amount to deposit is greater than the escrow amount")
+    AmountToDepositGreaterThanEscrowAmount => {
+        write!(f, "Amount to deposit is greater than the escrow amount")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ContractError::AmountToDepositGreatherThanEscrowAmount => {
write!(f, "Amount to deposit is greater than the escrow amount")
}
ContractError::AmountToDepositGreaterThanEscrowAmount => {
write!(f, "Amount to deposit is greater than the escrow amount")
}
🤖 Prompt for AI Agents
In contracts/Contract-Events-for-Indexer/src/error.rs around lines 123 to 125,
the error variant name "AmountToDepositGreatherThanEscrowAmount" contains a
typo. Rename the variant to "AmountToDepositGreaterThanEscrowAmount" to correct
the spelling of "Greather" to "Greater" consistently in the codebase.

}

#[test]
fn test_initialize_excrow() {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix typo in test function name

The function name contains a typo: "excrow" should be "escrow".

-fn test_initialize_excrow() {
+fn test_initialize_escrow() {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fn test_initialize_excrow() {
fn test_initialize_escrow() {
🤖 Prompt for AI Agents
In contracts/Contract-Events-for-Indexer/src/tests/test.rs at line 46, the test
function name has a typo: "test_initialize_excrow" should be corrected to
"test_initialize_escrow". Rename the function to fix the spelling mistake.

let _receiver_address = Address::generate(&env);

let amount: i128 = 100_000_000;
let platform_fee = (0.3 * 10i128.pow(18) as f64) as i128;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid floating-point arithmetic for fee calculations

Using floating-point arithmetic for financial calculations can lead to precision issues. Consider using integer arithmetic instead.

-    let platform_fee = (0.3 * 10i128.pow(18) as f64) as i128;
+    let platform_fee = 3 * 10i128.pow(17); // 0.3 * 10^18
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let platform_fee = (0.3 * 10i128.pow(18) as f64) as i128;
let platform_fee = 3 * 10i128.pow(17); // 0.3 * 10^18
🤖 Prompt for AI Agents
In contracts/Contract-Events-for-Indexer/src/tests/test.rs at line 160, the
calculation of platform_fee uses floating-point arithmetic which can cause
precision errors in financial calculations. Replace the floating-point operation
with integer arithmetic by directly computing the fee as an integer, for example
by multiplying the base unit (10^18) by the fee numerator and dividing by the
denominator, to maintain precision without using floats.

let release_signer_address = Address::generate(&env);
let dispute_resolver_address = Address::generate(&env);
let amount: i128 = 100_000_000;
let platform_fee = (0.3 * 10i128.pow(18) as f64) as i128;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid floating-point arithmetic for fee calculations

Using floating-point arithmetic for financial calculations can lead to precision issues. Consider using integer arithmetic instead.

-    let platform_fee = (0.3 * 10i128.pow(18) as f64) as i128;
+    let platform_fee = 3 * 10i128.pow(17); // 0.3 * 10^18
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let platform_fee = (0.3 * 10i128.pow(18) as f64) as i128;
let platform_fee = 3 * 10i128.pow(17); // 0.3 * 10^18
🤖 Prompt for AI Agents
In contracts/Contract-Events-for-Indexer/src/tests/test.rs at line 303, the
calculation of platform_fee uses floating-point arithmetic which can cause
precision errors in financial calculations. Replace the floating-point operation
with integer arithmetic by expressing the fee as a fraction or using integer
multiplication and division to maintain precision without floating-point
numbers.

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.

Spike 1: Add Soroban Events to Smart Contract for Indexer Integration

1 participant

Comments