You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Build a full invoice cloning system that allows creators to duplicate an invoice with selective field overrides, tracks clone lineage (parent/child relationships), enforces a maximum clone chain depth to prevent infinite recursion, and emits a structured clone event.
CloneOverrides is a new #[contracttype] struct with optional fields: new_deadline: Option<u64>, new_amounts: Option<Vec<i128>>, new_recipients: Option<Vec<Address>>, new_overflow_behavior: Option<OverflowBehavior>
Cloned invoice copies all fields from source except: funded, status, payments, claimed, released_bps, completion_time — these reset to defaults
clone_invoice panics with "max clone depth exceeded" if the source invoice has a clone_depth >= 5
Clone depth is stored as clone_depth: u32 on InvoiceCore (new field, default 0); cloned invoice gets parent_clone_depth + 1
parent_invoice_id: Option<u64> stored on InvoiceExt for lineage tracking
get_invoice_ext returns parent_invoice_id and clone_depth
Only the original invoice.creator can clone; panics with "not invoice creator"
Emits a cloned event: (symbol_short!("cloned"), invoice_id, new_id)
Test test_clone_copies_recipients_and_amounts
Test test_clone_with_overrides_replaces_fields
Test test_clone_depth_limit_enforced — 5 deep clones succeed, 6th panics
Test test_clone_resets_payment_state
Context
InvoiceCore and InvoiceExt are in contracts/split/src/types.rs — adding clone_depth to InvoiceCore requires updating from_legacy, split(), and assemble()
_create_invoice_inner in lib.rs handles invoice creation — clone can reuse it or write a dedicated path
Adding a field to InvoiceCore will affect XDR serialization — all existing tests must still pass
Description
Build a full invoice cloning system that allows creators to duplicate an invoice with selective field overrides, tracks clone lineage (parent/child relationships), enforces a maximum clone chain depth to prevent infinite recursion, and emits a structured clone event.
Acceptance Criteria
clone_invoice(creator: Address, source_id: u64, overrides: CloneOverrides) -> u64CloneOverridesis a new#[contracttype]struct with optional fields:new_deadline: Option<u64>,new_amounts: Option<Vec<i128>>,new_recipients: Option<Vec<Address>>,new_overflow_behavior: Option<OverflowBehavior>funded,status,payments,claimed,released_bps,completion_time— these reset to defaultsclone_invoicepanics with"max clone depth exceeded"if the source invoice has aclone_depth >= 5clone_depth: u32onInvoiceCore(new field, default 0); cloned invoice getsparent_clone_depth + 1parent_invoice_id: Option<u64>stored onInvoiceExtfor lineage trackingget_invoice_extreturnsparent_invoice_idandclone_depthinvoice.creatorcan clone; panics with"not invoice creator"clonedevent:(symbol_short!("cloned"), invoice_id, new_id)test_clone_copies_recipients_and_amountstest_clone_with_overrides_replaces_fieldstest_clone_depth_limit_enforced— 5 deep clones succeed, 6th panicstest_clone_resets_payment_stateContext
InvoiceCoreandInvoiceExtare incontracts/split/src/types.rs— addingclone_depthtoInvoiceCorerequires updatingfrom_legacy,split(), andassemble()_create_invoice_innerinlib.rshandles invoice creation — clone can reuse it or write a dedicated pathInvoiceCorewill affect XDR serialization — all existing tests must still pass