Skip to content

feat(channel): storage TTL extension, partial settlement, Deposit event - #24

Open
shawnmuggle wants to merge 3 commits into
stellar-experimental:mainfrom
mpprouter:feat/ttl-partial-settle-deposit-event
Open

feat(channel): storage TTL extension, partial settlement, Deposit event#24
shawnmuggle wants to merge 3 commits into
stellar-experimental:mainfrom
mpprouter:feat/ttl-partial-settle-deposit-event

Conversation

@shawnmuggle

Copy link
Copy Markdown

Closes #23.

Hardens the channel contract for long-lived metered-service channels (funder opens a channel with a deposit, then pays per-request via cumulative commitments over days/weeks):

  • Storage TTL extension: top_up, settle, close, and close_start now extend the instance storage TTL (threshold ~30 days, extend to ~60 days) as a side effect, and a new public extend() entrypoint lets anyone bump it explicitly, so an in-use channel is not archived. Documented under a new "Storage lifetime" section.
  • Partial settlement: settle/close payouts are capped at the channel balance, and WithdrawnAmount advances only by the amount actually transferred. A commitment exceeding the balance no longer panics and locks the recipient out; the shortfall stays claimable with the same commitment after a future top_up. For close the docs note this recoverability is best-effort, since close makes the channel immediately refundable.
  • Deposit event: top_up (including the constructor's initial deposit) emits Deposit { from, amount } so recipients can observe funding in real time. Direct token transfers to the contract address remain observable only via token events (doc note added).

Tests: updated test_close_amount_exceeds_balance to the new capped-payout semantics, added test_settle_partial_then_top_up and test_top_up_emits_deposit_event. All 30 tests pass locally, along with make fmt-check, make doc-check, and make readme-check (README regenerated via make readme).

🤖 Generated with Claude Code

shawnmuggle and others added 2 commits August 13, 2026 19:05
- Extend instance storage TTL as a side effect of top_up, settle, close,
  and close_start, and add a public extend() entrypoint so long-lived
  channels are not archived while in use.
- Cap settle/close payouts at the channel balance and advance
  WithdrawnAmount only by the amount actually transferred, so a
  commitment exceeding the balance no longer locks the recipient out;
  the shortfall stays claimable with the same commitment after a top up.
- Emit a Deposit event from top_up (including the constructor's initial
  deposit) so recipients can observe funding in real time.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 13, 2026 11:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens the Soroban channel contract for long-lived “metered service” usage by preventing instance-storage archival during normal operation, allowing partial settlement when commitments exceed balance, and emitting a deposit event for observability.

Changes:

  • Extend instance storage TTL on top_up, settle, close, and close_start, and add a public extend() entrypoint.
  • Implement capped (partial) payouts for settle/close, advancing WithdrawnAmount only by the amount actually transferred.
  • Emit a Deposit { from, amount } contract event on top_up (including constructor-funded deposits), and update docs/tests/snapshots accordingly.

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
README.md Document extend entrypoint, partial-settlement semantics, and storage lifetime behavior.
contracts/channel/src/lib.rs Add TTL extension logic/constants, extend() entrypoint, Deposit event emission in top_up, and capped withdrawal helper used by settle/close.
contracts/channel/src/event.rs Introduce Deposit contract event definition and documentation.
contracts/channel/src/test.rs Update/add tests for capped close/settle behavior and deposit-event emission.
contracts/channel/test_snapshots/test/test_top_up_zero.1.json Update snapshot TTL expectations (instance live_until) after TTL extension behavior.
contracts/channel/test_snapshots/test/test_top_up_emits_deposit_event.1.json New snapshot covering deposit event emission.
contracts/channel/test_snapshots/test/test_top_up_after_creation.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_settle.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_settle_partial_then_top_up.1.json New snapshot covering partial settlement followed by top-up and re-settlement.
contracts/channel/test_snapshots/test/test_settle_older_commitment_no_op.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_settle_incremental.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_settle_during_close_start.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_settle_after_close_start_effective.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_refund_twice.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_refund_too_early.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_refund_before_close_start_fails.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_refund_at_exact_effective_ledger.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_refund_after_close.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_open_zero_amount.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_invalid_signature.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_close.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_close_zero_amount.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_close_twice.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_close_start_resets_waiting_period.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_close_start_fails_after_effective.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_close_start_fails_after_close.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_close_start_and_refund.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_close_full_balance_no_refund_event.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_close_during_close_start.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_close_amount_exceeds_balance.1.json Update snapshot to reflect capped payout + WithdrawnAmount advancement semantics on close.
contracts/channel/test_snapshots/test/test_close_after_settle.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel/test_snapshots/test/test_close_after_close_start_effective.1.json Update snapshot TTL expectations after TTL extension behavior.
contracts/channel-factory/test_snapshots/test/test_open.1.json Update factory snapshot to new channel wasm hash/exports and new instance TTL expectations.
contracts/channel-factory/test_snapshots/test/test_open_zero_amount.1.json Update factory snapshot to new channel wasm hash/exports and new instance TTL expectations.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +855 to 875
/// Top up emits a Deposit event, and the constructor's initial deposit does too.
#[test]
fn test_top_up_emits_deposit_event() {
let env = Env::default();
env.mock_all_auths();

let auth_key = SigningKey::from_bytes(&[29u8; 32]);
let auth_pubkey = BytesN::from_array(&env, &auth_key.verifying_key().to_bytes());

let to = Address::generate(&env);
let funder = Address::generate(&env);

let (token_addr, _token, asset_admin) = create_token(&env);
asset_admin.mint(&funder, &1000);

let channel_id = env.register(Contract, (token_addr.clone(), funder.clone(), auth_pubkey.clone(), to.clone(), 500i128, 100u32));
let client = ContractClient::new(&env, &channel_id);

client.top_up(&200);
assert!(has_event_type(&env, &channel_id, "deposit"));
}
Comment on lines +358 to +360
pub fn extend(env: &Env) {
Self::extend_instance_ttl(env);
}
Address review feedback on PR stellar-experimental#24:
- Assert the constructor and top_up each emit their own Deposit event
  (env.events().all() holds only the last invocation's events, so each
  assertion isolates a single emitter).
- Add test_extend verifying extend() requires no auth and extends the
  instance storage TTL.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

Hardening for long-lived metered-service channels: TTL extension, partial settlement, Deposit event

2 participants