Skip to content

i made the fix to issue 204: implement escrow comment/note storage#214

Open
winnpxl wants to merge 1 commit intoOlufunbiIK:mainfrom
winnpxl:main
Open

i made the fix to issue 204: implement escrow comment/note storage#214
winnpxl wants to merge 1 commit intoOlufunbiIK:mainfrom
winnpxl:main

Conversation

@winnpxl
Copy link

@winnpxl winnpxl commented Feb 26, 2026

Hello. I saw this post on drip and I completed it. Kindly approve this pr, assign me the project and it's done. Thanks

Summary by CodeRabbit

  • New Features
    • Added note management functionality: users can now create notes when establishing splits and update/retrieve notes for existing splits
    • Notes are limited to 128 bytes maximum length
    • Added new error types for enhanced error handling and validation feedback

@coderabbitai
Copy link

coderabbitai bot commented Feb 26, 2026

📝 Walkthrough

Walkthrough

The PR extends the split-escrow contract with note management capabilities. It adds error variants to the Error enum, introduces public get_note and set_note APIs, modifies create_split to accept an optional note and deadline parameter, emits note events, stores notes in escrow records, and relocates the Error enum to a dedicated errors module.

Changes

Cohort / File(s) Summary
Error Handling
contracts/split-escrow/src/errors.rs
Added two new error variants: InvalidInput = 36 and InvalidEscrowStatus = 38 to the public Error enum.
Event Emission
contracts/split-escrow/src/events.rs
Added new public function emit_note_updated() to emit note creation/update events with split_id, note content, and ledger timestamp.
Core Contract Logic
contracts/split-escrow/src/lib.rs
Created new errors module; moved Error type; extended create_split() to accept deadline and optional note parameters with validation; added set_note() and get_note() public APIs; integrated note storage and conditional event emission into escrow lifecycle; added private validate_note_length() helper enforcing 128-byte maximum.
Type Definitions
contracts/split-escrow/src/types.rs
Added note: String field to SplitEscrow struct; introduced duplicate #[contracttype] and #[derive(Clone, Debug)] attributes immediately before struct declaration.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • PR #69: Modifies the same Error enum in contracts/split-escrow/src/errors.rs by introducing the enum structure extended in this PR.
  • PR #188: Changes create_split signature to include deadline parameter, directly related to signature extension in this PR.
  • PR #209: Adds auxiliary on-chain data to escrow records with get/update APIs and validation, following a similar pattern to note management introduced here.

Poem

🐰 A note in the escrow so neat,
With deadline and validations sweet,
Emit events as updates flow,
Notes dance in the contract's glow! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: implementing escrow comment/note storage as per issue 204, which is directly reflected in the substantial code additions across errors, events, lib, and types files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

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

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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

❤️ Share

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

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@contracts/split-escrow/src/lib.rs`:
- Around line 304-322: The set_note path currently only checks
EscrowStatus::Active but must also block updates past the escrow deadline; add a
timestamp check using the contract env (e.g., env.ledger().timestamp() or
env.now()) after fetching escrow (from storage::get_escrow) and before allowing
the update: if the current timestamp is greater than escrow.deadline return an
error (introduce or use an appropriate Error variant such as
Error::EscrowExpired), then continue with escrow.creator.require_auth() and the
existing status check/validate_note_length calls.
- Around line 73-75: The create_split function currently accepts any deadline
(u64) including past timestamps; add validation in create_split to reject
deadlines <= current block timestamp by retrieving the current time (e.g.,
env::block_timestamp() or equivalent) and returning an Err or panicking with a
clear message when deadline is not in the future; specifically check the
deadline parameter early in create_split (before constructing the Split/escrow)
and ensure tests/handlers that call create_split reflect the new error behavior.
- Around line 9-17: The Error enum in errors.rs is missing 12 variants
referenced elsewhere; add the following variants to the Error enum:
SplitNotFound, SplitCancelled, NoFundsAvailable, EscrowNotRefundable,
InvalidBridgeStatus, OracleNotAuthorized, VerificationNotFound, BridgeNotFound,
PriceSubmissionInvalid, ProofInvalid, SplitNotFunded, and SplitReleased, each
with unique discriminant values (continue the existing sequence used in
errors.rs to avoid collisions) so references to Error::SplitNotFound etc.
resolve; update the enum declaration in errors.rs (the Error type) to include
these discriminants and run a compile to ensure no duplicate values.
- Around line 134-150: The escrow keys were migrated to String but several
functions still use or reference u64/undefined split_id variables; update the
access paths to consistently use String keys: add a helper
split_id_key(split_id: u64) -> String (or accept String inputs) and use it
wherever escrows are stored or fetched (storage::set_escrow, storage::get_escrow
calls); in particular change deposit() to convert its u64 split_id param to a
String key before lookup, make release_funds() use its split_id_str parameter
everywhere (remove references to undefined split_id), and modify
release_funds_internal() to accept a String key (or convert the incoming String
to the expected key type) so callers pass the String split_id_str; ensure all
lookups/sets use the same String key variable (split_id_str or
split_id_key(...)) to fix the type/undefined errors.

In `@contracts/split-escrow/src/types.rs`:
- Around line 459-460: Remove the duplicate attributes by keeping a single
#[contracttype] and a single #[derive(Clone, Debug)] on the SplitEscrow struct
declaration (remove the redundant repeated attributes), and in the create_escrow
function initialize the newly added note: String field when constructing
SplitEscrow (set note to the appropriate value, e.g., an empty string or the
passed-in note variable) so the struct literal in create_escrow includes note
and the code compiles.
- Around line 492-493: Several SplitEscrow struct literals are missing the new
required field note: String; update every construction site (notably the
create_escrow() function and the test cases in test.rs) to include a note value
(e.g., an empty string or context-appropriate text) when instantiating
SplitEscrow, matching how lib.rs already supplies note; ensure all SplitEscrow
{...} literals include note and re-run compilation/tests.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c237ec2 and 47f0075.

📒 Files selected for processing (4)
  • contracts/split-escrow/src/errors.rs
  • contracts/split-escrow/src/events.rs
  • contracts/split-escrow/src/lib.rs
  • contracts/split-escrow/src/types.rs

Comment on lines +9 to +17
mod errors;

#[cfg(test)]
mod test;

use crate::types::{
SplitEscrow, EscrowParticipant, EscrowStatus, Error,
SplitEscrow, EscrowParticipant, EscrowStatus,
};
use crate::errors::Error;
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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, check if the files exist and examine the error enum definition
echo "=== Checking errors.rs ===" 
if [ -f "contracts/split-escrow/src/errors.rs" ]; then
  cat "contracts/split-escrow/src/errors.rs"
else
  echo "File not found: contracts/split-escrow/src/errors.rs"
fi

Repository: OlufunbiIK/StellarSplit

Length of output: 482


🏁 Script executed:

#!/bin/bash
# Check lib.rs imports and sample error references
echo "=== Checking lib.rs lines 1-50 ===" 
if [ -f "contracts/split-escrow/src/lib.rs" ]; then
  head -50 "contracts/split-escrow/src/lib.rs" | cat -n
else
  echo "File not found"
fi

Repository: OlufunbiIK/StellarSplit

Length of output: 1914


🏁 Script executed:

#!/bin/bash
# Run the verification script from the review comment
python - <<'PY'
import re
from pathlib import Path

root = Path("contracts/split-escrow/src")
lib = (root / "lib.rs").read_text()
errs = (root / "errors.rs").read_text()

refs = set(re.findall(r'Error::([A-Za-z_][A-Za-z0-9_]*)', lib))
decl = set(re.findall(r'^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=', errs, re.M))

missing = sorted(refs - decl)
print("Referenced in lib.rs:", len(refs))
print("Declared in errors.rs:", len(decl))
print("\nReferenced variants:", sorted(refs))
print("\nDeclared variants:", sorted(decl))
print("\nMissing variants from errors.rs:", missing)
PY

Repository: OlufunbiIK/StellarSplit

Length of output: 946


🏁 Script executed:

#!/bin/bash
python - <<'PY'
import re
from pathlib import Path

lib = Path("contracts/split-escrow/src/lib.rs").read_text()

# Find all Error:: usages with line numbers
lines = lib.split('\n')
for i, line in enumerate(lines, 1):
    if 'Error::' in line:
        print(f"Line {i}: {line.strip()}")
PY

Repository: OlufunbiIK/StellarSplit

Length of output: 1120


🏁 Script executed:

#!/bin/bash
# Count how many functions would be affected
echo "=== Functions returning Err(Error::...) ===" 
rg "Error::(SplitNotFound|SplitCancelled|NoFundsAvailable|BridgeNotFound|SplitNotFunded|SplitReleased|VerificationNotFound|InvalidBridgeStatus|EscrowNotRefundable|OracleNotAuthorized|PriceSubmissionInvalid|ProofInvalid)" contracts/split-escrow/src/lib.rs -B 5 | head -100

Repository: OlufunbiIK/StellarSplit

Length of output: 3637


Add 12 missing Error enum variants to compile successfully.

The contract references Error::SplitNotFound, Error::SplitCancelled, Error::NoFundsAvailable, Error::EscrowNotRefundable, Error::InvalidBridgeStatus, Error::OracleNotAuthorized, Error::VerificationNotFound, Error::BridgeNotFound, Error::PriceSubmissionInvalid, Error::ProofInvalid, Error::SplitNotFunded, and Error::SplitReleased at 23 locations across multiple functions, but contracts/split-escrow/src/errors.rs does not define these variants. Add all 12 missing variants to the Error enum with appropriate discriminant values.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/split-escrow/src/lib.rs` around lines 9 - 17, The Error enum in
errors.rs is missing 12 variants referenced elsewhere; add the following
variants to the Error enum: SplitNotFound, SplitCancelled, NoFundsAvailable,
EscrowNotRefundable, InvalidBridgeStatus, OracleNotAuthorized,
VerificationNotFound, BridgeNotFound, PriceSubmissionInvalid, ProofInvalid,
SplitNotFunded, and SplitReleased, each with unique discriminant values
(continue the existing sequence used in errors.rs to avoid collisions) so
references to Error::SplitNotFound etc. resolve; update the enum declaration in
errors.rs (the Error type) to include these discriminants and run a compile to
ensure no duplicate values.

Comment on lines +73 to 75
deadline: u64,
note: Option<String>,
) -> u64 {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Validate deadline at split creation.

create_split accepts any deadline, including timestamps in the past, which can create immediately expired escrows.

Proposed fix
 pub fn create_split(
@@
     note: Option<String>,
 ) -> u64 {
     // Verify the creator is authorizing this call
     creator.require_auth();
@@
     if storage::is_paused(&env) {
         panic!("Contract is paused");
     }
+
+    if deadline <= env.ledger().timestamp() {
+        panic!("Deadline must be in the future");
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/split-escrow/src/lib.rs` around lines 73 - 75, The create_split
function currently accepts any deadline (u64) including past timestamps; add
validation in create_split to reject deadlines <= current block timestamp by
retrieving the current time (e.g., env::block_timestamp() or equivalent) and
returning an Err or panicking with a clear message when deadline is not in the
future; specifically check the deadline parameter early in create_split (before
constructing the Split/escrow) and ensure tests/handlers that call create_split
reflect the new error behavior.

Comment on lines +134 to +150
let split_id_str = String::from_str(&env, &split_id.to_string());

let escrow = SplitEscrow {
split_id: split_id.clone(),
split_id: split_id_str.clone(),
creator: creator.clone(),
requester: creator.clone(),
description: description.clone(),
total_amount,
amount_collected: 0,
participants,
status: EscrowStatus::Active,
deadline: deadline,
deadline,
created_at: env.ledger().timestamp(),
note: note_value.clone(),
};

storage::set_escrow(&env, &split_id, &escrow);
storage::set_escrow(&env, &split_id_str, &escrow);
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

🧩 Analysis chain

🏁 Script executed:

# First, let's find the file and check its structure
git ls-files | grep -E "(split-escrow|lib\.rs)"

Repository: OlufunbiIK/StellarSplit

Length of output: 1557


🏁 Script executed:

# Let's examine the file and count total lines
wc -l contracts/split-escrow/src/lib.rs

Repository: OlufunbiIK/StellarSplit

Length of output: 104


🏁 Script executed:

# Now inspect the split_id usage patterns as suggested
rg -n -C2 'String::from_str\(&env, &split_id.to_string\(\)\)|pub fn deposit\(|split_id: u64|get_escrow\(&env, &split_id_str\)|set_escrow\(&env, &split_id_str' contracts/split-escrow/src/lib.rs

Repository: OlufunbiIK/StellarSplit

Length of output: 3929


🏁 Script executed:

# Also search more broadly for split_id usage in the file
rg -n 'split_id' contracts/split-escrow/src/lib.rs | head -40

Repository: OlufunbiIK/StellarSplit

Length of output: 2805


Fix undefined variable and type mismatches in split_id key migration.

The code stores escrows with String keys (line 150) but the deposit() function tries to access them using the undefined variable split_id_str (line 174), which doesn't exist in that function's scope. Additionally, at line 242, split_id_str (a String) is passed to release_funds_internal() which expects a u64, causing a type mismatch. Similarly, release_funds() receives split_id_str as a parameter but line 256 references undefined split_id.

This breaks compilation. Convert all escrow access paths to consistently use the String key form:

  • In deposit(): convert the u64 split_id parameter to String before accessing escrows
  • In release_funds(): use the split_id_str parameter consistently instead of undefined split_id
  • In release_funds_internal(): accept String keys or convert them appropriately for escrow lookups

A helper function like the suggested split_id_key() would prevent this drift across all access paths.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/split-escrow/src/lib.rs` around lines 134 - 150, The escrow keys
were migrated to String but several functions still use or reference
u64/undefined split_id variables; update the access paths to consistently use
String keys: add a helper split_id_key(split_id: u64) -> String (or accept
String inputs) and use it wherever escrows are stored or fetched
(storage::set_escrow, storage::get_escrow calls); in particular change deposit()
to convert its u64 split_id param to a String key before lookup, make
release_funds() use its split_id_str parameter everywhere (remove references to
undefined split_id), and modify release_funds_internal() to accept a String key
(or convert the incoming String to the expected key type) so callers pass the
String split_id_str; ensure all lookups/sets use the same String key variable
(split_id_str or split_id_key(...)) to fix the type/undefined errors.

Comment on lines +304 to +322
pub fn set_note(env: Env, split_id: String, note: String) -> Result<(), Error> {
if storage::is_paused(&env) {
panic!("Contract is paused");
}

// Validate note length
Self::validate_note_length(&note)?;

// Get escrow
let mut escrow = storage::get_escrow(&env, &split_id)
.ok_or(Error::EscrowNotFound)?;

// Verify caller is the creator
escrow.creator.require_auth();

// Check escrow status is Active
if escrow.status != EscrowStatus::Active {
return Err(Error::InvalidEscrowStatus);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

set_note should reject updates after deadline, not only by status.

If EscrowStatus is still Active past deadline (lazy state update), note edits are still allowed. Add a timestamp check before permitting update.

Proposed fix
 pub fn set_note(env: Env, split_id: String, note: String) -> Result<(), Error> {
@@
     let mut escrow = storage::get_escrow(&env, &split_id)
         .ok_or(Error::EscrowNotFound)?;
@@
     // Verify caller is the creator
     escrow.creator.require_auth();
+
+    if env.ledger().timestamp() > escrow.deadline {
+        escrow.status = EscrowStatus::Expired;
+        storage::set_escrow(&env, &split_id, &escrow);
+        return Err(Error::EscrowExpired);
+    }
 
     // Check escrow status is Active
     if escrow.status != EscrowStatus::Active {
         return Err(Error::InvalidEscrowStatus);
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/split-escrow/src/lib.rs` around lines 304 - 322, The set_note path
currently only checks EscrowStatus::Active but must also block updates past the
escrow deadline; add a timestamp check using the contract env (e.g.,
env.ledger().timestamp() or env.now()) after fetching escrow (from
storage::get_escrow) and before allowing the update: if the current timestamp is
greater than escrow.deadline return an error (introduce or use an appropriate
Error variant such as Error::EscrowExpired), then continue with
escrow.creator.require_auth() and the existing status check/validate_note_length
calls.

Comment on lines +459 to +460
#[contracttype]
#[derive(Clone, Debug)]
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

🧩 Analysis chain

🏁 Script executed:

cat -n contracts/split-escrow/src/types.rs | sed -n '455,500p'

Repository: OlufunbiIK/StellarSplit

Length of output: 1669


🏁 Script executed:

rg -n 'fn create_escrow' contracts/split-escrow/src/types.rs -A 30

Repository: OlufunbiIK/StellarSplit

Length of output: 978


Remove duplicate #[contracttype] and #[derive(Clone, Debug)] attributes on SplitEscrow, and initialize the note field in create_escrow.

Lines 459–460 have duplicate attributes that will cause conflicting trait implementations and fail compilation. Additionally, the note: String field added at line 493 is not initialized in the create_escrow function (line 629–640), which will cause a compilation error for missing required struct field.

Proposed fixes

Remove duplicate attributes at lines 459–460:

 #[contracttype]
 #[derive(Clone, Debug)]
-#[contracttype]
-#[derive(Clone, Debug)]
 pub struct SplitEscrow {

Add note field initialization in create_escrow function:

     SplitEscrow {
         split_id,
         creator: creator.clone(),
         description,
         total_amount,
         amount_collected: 0,
         participants,
         requester: creator.clone(),
         status: EscrowStatus::Active,
         deadline,
         created_at: env.ledger().timestamp(),
+        note: String::new(),
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/split-escrow/src/types.rs` around lines 459 - 460, Remove the
duplicate attributes by keeping a single #[contracttype] and a single
#[derive(Clone, Debug)] on the SplitEscrow struct declaration (remove the
redundant repeated attributes), and in the create_escrow function initialize the
newly added note: String field when constructing SplitEscrow (set note to the
appropriate value, e.g., an empty string or the passed-in note variable) so the
struct literal in create_escrow includes note and the code compiles.

Comment on lines +492 to +493
/// Optional note/comment attached to the escrow (max 128 bytes)
pub note: String,
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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for SplitEscrow struct definition and create_escrow function
rg -n -A 30 'pub struct SplitEscrow' contracts/split-escrow/src/types.rs | head -50

Repository: OlufunbiIK/StellarSplit

Length of output: 1055


🏁 Script executed:

#!/bin/bash
# Read the struct definition to see if `note` field exists
sed -n '461,510p' contracts/split-escrow/src/types.rs

Repository: OlufunbiIK/StellarSplit

Length of output: 1556


🏁 Script executed:

#!/bin/bash
# Find the create_escrow function
rg -n -A 25 'pub fn create_escrow' contracts/split-escrow/src/types.rs

Repository: OlufunbiIK/StellarSplit

Length of output: 832


🏁 Script executed:

#!/bin/bash
# Find all places where SplitEscrow struct literal is constructed
rg -n 'SplitEscrow \{' contracts/split-escrow/src/types.rs

Repository: OlufunbiIK/StellarSplit

Length of output: 163


🏁 Script executed:

#!/bin/bash
# Find all Rust files in split-escrow and search for SplitEscrow struct construction
find contracts/split-escrow/src -name "*.rs" -type f | while read file; do
  rg -l 'SplitEscrow \{' "$file" 2>/dev/null
done

Repository: OlufunbiIK/StellarSplit

Length of output: 171


🏁 Script executed:

#!/bin/bash
# Find all SplitEscrow struct literal constructions in lib.rs and test.rs
echo "=== lib.rs ===" && rg -n -B2 -A15 'SplitEscrow \{' contracts/split-escrow/src/lib.rs
echo "=== test.rs ===" && rg -n -B2 -A15 'SplitEscrow \{' contracts/split-escrow/src/test.rs

Repository: OlufunbiIK/StellarSplit

Length of output: 4301


Initialize the note field in all SplitEscrow struct literals.

The SplitEscrow struct now requires a note: String field (line 493), but several construction sites are missing it:

  • create_escrow() function (types.rs, line 629–640)
  • Multiple test cases (test.rs): lines 521, 535, 556, 583, 598

The field is already correctly initialized in lib.rs (line 147), but the remaining locations must be updated to compile.

Example fix for types.rs
 pub fn create_escrow(
     env: &Env,
     split_id: String,
@@
 ) -> SplitEscrow {
     SplitEscrow {
         split_id,
         creator: creator.clone(),
@@
         status: EscrowStatus::Active,
         deadline,
         created_at: env.ledger().timestamp(),
+        note: String::from_str(env, ""),
     }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@contracts/split-escrow/src/types.rs` around lines 492 - 493, Several
SplitEscrow struct literals are missing the new required field note: String;
update every construction site (notably the create_escrow() function and the
test cases in test.rs) to include a note value (e.g., an empty string or
context-appropriate text) when instantiating SplitEscrow, matching how lib.rs
already supplies note; ensure all SplitEscrow {...} literals include note and
re-run compilation/tests.

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.

1 participant