Summary
The function to redeem winning tickets (redeemWinningTicket) on the TicketBroker contract can settle for less than the ticket’s face value or even 0 payout while consuming the ticket.
While this might look unexpected, it’s actually clearly documented in the specification, so the Orchestrator’s client should always ensure sufficient Broadcaster’s deposits and reserves before taking on a job, as the protocol doesn’t enforce that.
Root cause
The redeemWinningTicket function first ensures that the broadcaster’s deposit and reserve are greater than the face value, while using remainingReserve for the reserve calculation. However, later, the payout is calculated using a different function claimableReserve which is that recipient's own share of the reserve for the round. The ticket is marked as used before that payout is computed, and nothing checks that the amount paid actually matches the face value.
Since anyone can top up the sender's balances (as fundDepositAndReserveFor doesn’t restrict it), a third party can add just enough ETH to satisfy the check, and the ticket can be consumed for a “partial payout” or even zero payment. The recipient can also reach the same outcome by redeeming its own ticket while its claimable reserve is short or completely exhausted in that specific round.
Why this is expected
- The code follows the specification, which documents known edge cases under which a partial or full face value can be lost:
- Precondition A: Deposit short, reserve allocation covers part of the remainder. Outcome: Partial payment, ticket consumed.
- Precondition B: Deposit short; reserve allocation already spent this round for another ticket. Outcome: Partial payout from the deposit only; ticket consumed.
- Precondition C: Zero deposit, reserve allocation already spent this round. Outcome: Zero payment, ticket consumed.
- The client that follows the same specification has to protect against possible attacks. The protocol doesn’t enforce that the Broadcaster holds enough ETH to cover all tickets that they sign.
Out of scope for the bug bounty
Reports describing a winning ticket settling below its face value in TicketBroker.redeemWinningTicket, including variants driven by the ticket broadcaster, by a third-party deposit top-up, or by no attacker at all, will be deemed invalid and are not eligible for rewards under the Livepeer Immunefi bug bounty program, unless the report shows how the severity can be escalated beyond what is described above.
References
Summary
The function to redeem winning tickets (redeemWinningTicket) on the
TicketBrokercontract can settle for less than the ticket’s face value or even 0 payout while consuming the ticket.While this might look unexpected, it’s actually clearly documented in the specification, so the Orchestrator’s client should always ensure sufficient Broadcaster’s deposits and reserves before taking on a job, as the protocol doesn’t enforce that.
Root cause
The redeemWinningTicket function first ensures that the broadcaster’s deposit and reserve are greater than the face value, while using
remainingReservefor the reserve calculation. However, later, the payout is calculated using a different functionclaimableReservewhich is that recipient's own share of the reserve for the round. The ticket is marked as used before that payout is computed, and nothing checks that the amount paid actually matches the face value.Since anyone can top up the sender's balances (as fundDepositAndReserveFor doesn’t restrict it), a third party can add just enough ETH to satisfy the check, and the ticket can be consumed for a “partial payout” or even zero payment. The recipient can also reach the same outcome by redeeming its own ticket while its claimable reserve is short or completely exhausted in that specific round.
Why this is expected
Out of scope for the bug bounty
Reports describing a winning ticket settling below its face value in
TicketBroker.redeemWinningTicket, including variants driven by the ticket broadcaster, by a third-party deposit top-up, or by no attacker at all, will be deemed invalid and are not eligible for rewards under the Livepeer Immunefi bug bounty program, unless the report shows how the severity can be escalated beyond what is described above.References
TicketBrokerproxy address on Arbitrum One.