Skip to content

TicketBroker: allow unlocking deposit separately from reserve #659

Description

@eliteprox

Summary

Gateways (ticket senders) currently must unlock and withdraw deposit and reserve together. Gateways that want to reclaim idle deposit while keeping reserve funded for ticket coverage cannot do so without also unlocking (and eventually withdrawing) their reserve.

At minimum, TicketBroker should support unlocking / withdrawing deposit funds separately from reserve. Optionally, deposit withdrawal could skip (or use a shorter) unlock period, since reserve is what covers winning tickets claimed during the unlock / following-round window.

Current behavior

In MixinTicketBrokerCore:

  • Sender has a single withdrawRound shared by deposit + reserve.
  • unlock() starts one unlock that applies to both balances.
  • withdraw() always clears both sender.deposit and the sender's reserve (clearReserve), then transfers the sum.
  • Ticket redemption requires the sender to be locked (isLocked), and pays from deposit first, then reserve when face value exceeds deposit.
// withdraw() — deposit and reserve are inseparable today
sender.deposit = 0;
clearReserve(msg.sender);
withdrawTransfer(payable(msg.sender), deposit.add(reserve));

Funding paths already treat deposit and reserve independently (fundDeposit, fundReserve, fundDepositAndReserve), but unlock/withdraw do not.

Motivation

  1. Capital efficiency for gateways — A gateway may hold more deposit than needed for day-to-day ticket face values while keeping reserve sized for worst-case / following-round claims. Today, reclaiming excess deposit forces unlocking reserve too, which either:
    • blocks further ticket redemptions once the unlock completes (sender is unlocked), or
    • requires cancelling unlock / re-funding to stay operational.
  2. Reserve already covers the lock-period risk — The unlock period exists so tickets created before unlock can still be redeemed afterward. Reserve is the mechanism that covers claims when deposit is exhausted during that window (and for the following round). If reserve remains locked and funded, withdrawing deposit does not remove that safety net.
  3. Symmetric with funding API — Deposit and reserve can already be funded independently; unlock/withdraw should match that model.

Proposed requirements

Minimum (required)

  • Support unlocking / withdrawing deposit only, without clearing or unlocking reserve.
  • Reserve-only unlock/withdraw can remain as today, or stay coupled only when the sender explicitly unlocks both.
  • Preserve existing security invariants for reserve:
    • Reserve still subject to unlock period before withdrawal.
    • Sender remains locked for ticket redemption as long as reserve (and any remaining deposit policy) requires it — exact locking rules to be specified in design.
  • Events / getter updates so indexers and UIs can distinguish deposit vs reserve unlock/withdraw.

Stretch / discuss

  • Allow immediate (or shorter-period) deposit withdrawal while reserve stays locked, on the rationale that reserve covers tickets claimed in the unlock / following round.
  • If deposit can be withdrawn without a lock period, document how redemption behaves when deposit is zero but reserve is still locked and funded (already partially supported: redemption allows deposit == 0 if remainingReserve > 0).

Design questions

  1. API shape — e.g. unlockDeposit() / withdrawDeposit() vs parameterized unlock(UnlockTarget) / withdraw(WithdrawTarget)?
  2. Locking semantics — If deposit is withdrawn but reserve remains, should isLocked stay true solely based on reserve state (likely yes, so tickets remain redeemable)?
  3. Partial deposit withdraw — Withdraw full deposit only, or allow withdrawing an amount up to sender.deposit?
  4. Self-funding cancel behavior — Today, funding deposit/reserve as the sender cancels an in-progress unlock. How should that interact with separate deposit vs reserve unlocks?
  5. Upgrade path — Proxy upgrade of TicketBroker target; any storage layout changes for separate withdraw rounds?

Acceptance criteria

  • Gateway can withdraw deposit without withdrawing or unlocking reserve.
  • Reserve remains available for winning ticket claims under the existing reserve claim rules while still locked.
  • Existing unlock / withdraw behavior is either preserved (both) or clearly migrated with tests.
  • Unit + integration tests covering: deposit-only unlock/withdraw, reserve still claimable, redemption with zero deposit + non-zero reserve, and no regression on full unlock/withdraw.
  • Docs / comments updated for gateway operators on when to use deposit-only vs full unlock.

References

  • contracts/pm/mixins/MixinTicketBrokerCore.solunlock, withdraw, redeemWinningTicket, Sender
  • contracts/pm/mixins/MixinReserve.sol — reserve claim / clear semantics
  • Repo: https://github.com/livepeer/protocol

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions