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.

Design

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.

Example:

Param Value
Rate 0.1 per month
Time span 10 days
Total rate per span .033 = ~0.1/3

Shares

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.

Example:

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

    • Address: 0x01 Amount: 40

    • Address: 0x02 Amount: 60

Param Value
Time between End and Start 2 month
Montly rate 0.1
Rate per delegation state (End - Start)*0.1 = (12 - 10) * 0.1 = 0.2
Tokens amount 0.2 * Staked amount
Tokens for 0x01 0.2 * 40 = 8
Tokens for 0x02 0.2 * 60 = 12

Transactions

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

Setup

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"
}


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

erc20=0xc35550282b2a7F2148dD4513c70f9dAA1AFA277C
escrow=0x6bB9DF55B2c7DE181DB2F953B3f5e15baC7e1523
worker=0xa919396182bd6c536456abe056420308d53bdcc5
amount=$(seth --to-wei 100 ether)

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

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

Payments

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 | https://goerli.etherscan.io/tx/0x0ea28b977604c88ed2ea7a72eab3027e285fd7d563376bf765da354ad1f75cff | 2392313546420000 |

+--------------------------------------------+-----------------------------