VidPool - Flat Payments: Percentage-based payment engine

Unlike the main implementation that makes payments based on worker activity (processed chunks), this payment engine pays rewards based on flat percent.


Unit of time

Payment will be made per time span from the time delegation was made. For example, if a delegation was made 10 days ago, we will pay for 10 days. The caller of this application will have to provide the rate to the engine, and the engine will calculate per block rate based on the time passed.



After we got rate per block we need to convert this rate to coins, this needs to be done in a way that reflects changes in delegation ratios that were made during this time.

For the start we need to obtain the state of the delegations at the starting block, we do it either by traversing Locked/Unlocked events of the StakingManager or by recovering snapshot (as an optimization).

Delegation state will be stored in the following struct:

type DelegationState struct {
     // Start is a block when this delegation state became valid.
     // If there was a previous DelegationState then current Start is equal
     // to previous End+1
     Start *big.Int
     // End is the last block when this delegation was valid.
     End *big.Int
     // Amount is a total amount of all delegations.
     Amount *big.Int
     // List of delegation for each delegator.
     Delegations []Delegation

type Delegation struct {
     Address common.Address
     Amount *big.Int

Delegation state is completed when the start and end are both not nil. The end may become not nil either if this is the last block in the span for which we are running payments workflow, or if delegation state changed.

Next, we need to iterate over all delegation states and accumulate payments. For each delegation in the delegation state, we get the share.


  • Delegation state: Start: 10 End: 12 Amount: 100 Delegations:

    • Address: 0x01 Amount: 40

    • Address: 0x02 Amount: 60


Transactions will be made on mainnet, using the transfer method of the ERC20 interface. The application will provide crash-recovery by dumping transactions on disk before sending them to the network. Once the application confirmed that transactions were mined those transactions will be removed from disk.

If the application fails in the process or interrupted by the user, the next start application will recover pending transactions and check the state on the blockchain. If they are not found application will resend them, otherwise remove transactions from recovery-log.

How to use


See the configuration file. EscrowAddress and TokenAddress are the same that we are using in other applications.

Worker account must have ether on goerli network and ERC20 tokens if it will be used for real transactions.

Use Rate struct to adjust payment rate to the required value, Unit is a unit of time, can be one of the month, year, day, or hour.

"Rate": {
  "Decimal": 0.1,
  "Unit": "month"


Use any convenient method to delegate some tokens to the worker. I am using seth in the following way:

amount=$(seth --to-wei 100 ether)

seth send $erc20 "increaseApproval(address,uint256)" $escrow $amount
seth send $escrow "transfer(address,uint256)" $worker $amount


Once something is staked application will be able to discover that stake and make correct payments.

./build/vidpool -c _assets/erc20.json flat

| DELEGATOR                                  | TRANSACTION URL                                                                                   | AMOUNT           |
| 0x218431C2e6B7A8d6aF5eF18F3Ad63B23c614889F | | 2392313546420000 |

Last updated