Difference between Reward() and ClaimEarnings()

In the first weeks of the Livepeer network being live, one thing that has constantly confused users of the protocol is the difference between the reward() transaction and the claimEarnings() transaction.


From explorer.livepeer.org/me/delegating


TLDR Summary

  • If you’re a transcoder, make sure to call reward() once per round. Don’t miss this.
  • Everyone who stakes needs to eventually call claimEarnings() to calculate how much token and fees they generated each round, but there is no rush to invoke this proactively. It happens behind the scenes when you change bonding status (unbonding, bonding more, or changing who you are bonded to). Unclaimed earnings are counted as “Bonded” so you are earning inflation on them.


reward() is a transaction that only transcoders need to invoke. When they invoke reward(), it generates newly minted LPT that gets split amongst them and their delegators.

  • Only transcoders invoke reward
  • They can only do this 1x/round (once per day)
  • If they fail to invoke reward() during a round, then they miss out on the newly minted LPT, and so do their delegators. It is very bad to not call reward, as it’s a big missed opportunity. that does not come back. Delegators will not be happy.
  • The newly generated LPT are automatically credited to the total delegated stake for the transcoder, and the delegated stake for each delegator. So they count towards stake for election in the next round’s active set.
  • The livepeer node should call reward() automatically at the very start of a round. But sometimes a shaky connection to an Ethereum node, or high gas prices, can cause this txn to not be submitted. Transcoders should always check if they called reward(), and call it manually via the CLI if they have not seen their txn get confirmed yet. The --gasPrice flag to the livepeer node can also help to get the txn through.


claimEarnings() is more of an accounting necessity than something that’s useful or valuable to a user as far as LPT is concerned. As mentioned above, when a transcoder calls reward() the newly generated token sit in a pool that’s credited towards their total stake. Each delegator is entitled to some of this token. How much they’re owed needs to be calculated on a round-by-round basis and credited to their account. Hence, when they call claimEarnings() they are paying for this calculation to take place on the blockchain, and the token to move from sitting in a big pool, to being allocated towards them individually.

Fees that a transcoder earns in ETH, are immediately distributed into a delegator’s account when they call claimEarnings() however.

While delegators do need to do this calculation for every single round (day), one call to claimEarnings() can do the calculation for 100 rounds.

  • Delegators or transcoders call claimEarnings() whenever they want to change their delegation status: unbond, bond towards another transcoder, bond more.
  • One call to claimEarnings() can update their status for up to 100 rounds. So if it’s been longer than 100 rounds since the last update, you may have to call claimEarnings() multiple times.
  • If it’s been less than 100 rounds, this happens in the background when you bond or unbond, you don’t need to proactively call claimEarnings().
  • If you are not changing your bond, the most effective strategy is to just call claimEarnings() once every 100 rounds. Or you can just wait and not do anything, and then call it, say 3 times if it’s been 300 rounds.
  • There’s no benefit to calling claimEarnings() more frequently if you aren’t changing bonding status, unless you prefer the ETH fees to be sitting in your account instead of in the Livepeer contract.
  • CAUTION: After you call claimEarnings() for a round, you can not call it again for that round. That means that if the transcoder earns more fees or calls reward() later in that round, you can not access those rewards or fees. To really optimize, change your bonding status late in the round after most of the fees have been collected and reward() has been called.

Update on 12/20, that you can now claim up to 100 rounds in one claim call, rather than only 20.

I’ve recently started transcoding and have been unable to ClaimEarnings via the cli. My last claim round is listed as 0 and my start round is 1265. When I invoke “Claim” (option 10), I’ve tried a variety of end rounds: 1270, 1265, 1277, but my result is always the same:

Invoking transaction: “claimEarnings”. Params: [20]
livepeer-transcoder[19589]: Transaction Failed: failed to estimate gas needed: gas required exceeds allowance or always failing transaction

I’m wondering if I need to be active for 20 rounds prior to claiming rewards? I know that other transcoders see the actual round they are claiming i.e. Params: [1278]

You should not be required to be active for 20 rounds before you can call claimEarnings. I think this one sounds like a bug that may need to be tracked through Github with as much info as you can provide to help us debug and reproduce. Mind filing here https://github.com/livepeer/go-livepeer/issues

In the meantime, you can try invoking claimEarnings via myCrypto if it is important to you to claim them at this time.