---
# System prepended metadata

title: 'MEP-05: Reward Calculation Contract'

---

# MEP-05: Reward Calculation Contract

**Created**: 2023-04-19

## Simple Summary

Specification for the reward calculation formula. Based on this one, a application creator can specify custom rules for rewarding sensor owners that submit data to the platform.

## Abstract


## Motivation


## Terminology

- Reward Pools
- Reward Cycle - period delimitated by start and end block in which users can submit data to get rewards; a cycle can be one day, one week, one month, etc.
- Daily Amount


## Specification

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

Every MEP-05 compliant contract must implement the following interface:
```solidity=
pragma solidity ^0.4.20;

/// @title MEP-05 Reward Calculation Contract
interface IMEP05 {
    event RegisterReward(uint256 indexed tokenId, uint256 dataEfficiency, uint256 pool);
    
    event Payout(uint256 startBlock, uint256 endBlock, uint256 numberOfRewards);
    
    /// @notice Registers a reward entry for a single sensor.
    /// @dev This method should store the tokenId from MEP-02, 
    ///  it's data efficiency and the pool selected; afterwards 
    ///  when the payout of a cycle is done, the method needs
    ///  to calculate the total contributions
    ///
    /// @param _tokenId The tokenId of the sensor
    /// @param _dataEfficiency The address of the sensor
    /// @param _pool The address of the sensor
    /// @return Fuel tank in decimals
    function registerReward(uint256 _tokenId, uint256 _dataEfficiency, uint256 _pool) external;

    function payout(uint256 _startBlock, uint256 _endBlock) external;
}
```


## Rationale


### Contract dependencies

In order for MEP05 to issue rewards, check fuel tank and device validity, it needs a link to:
- MEP02 - checking the validity of the sensor using `isValid`
- MEP04 - calling the `reward` method and getting the sensor's fuel tank

In practice, this is mostly done inside the constructor:
```solidity
constructor(address provisioningContract,
            address rewardTokenContract)
```

In order to authorize an external entity (EOA) to call the `payout` method, there needs to be an authorized account with a `onlyPayout` modifier.

This can go also inside of the constructor, so that we have:
```solidity=
public address authorizedAddress;

modifier onlyPayout() {
    require(msg.sender == authorizedAddress);
    _;
}

constructor(address provisioningContract,
            address rewardTokenContract,
            address payoutAddress) {
    this.authorizedAddress = payoutAddress;
}

function payout(uint256 startBlock, uint256 endBlock) external onlyPayout
{...};

```

### Pools

With each contract deployed, there exists a pool allocation of 3 pools. Each pool has N tokens supplied for a reward cycle.

In one reward cycle the reward entries compete in a pool which is selected with the calculation formula.

Example:

3 pools with 1000 tokens

One cycle could have the following reward distribution:
- 5 entries in pool 1
- 10 entries in pool 2
- 7 entries in pool 3

Each pool is independant and rewards in one pool don't affect the rewarded amount in another pool.

### Reward Formula

The reward formula calculates the data efficiency of each sensor and also the pool where it is selected.

For each cycle, the `totalContribution` needs to be calculated. The `totalContribution` is the sum of all data efficiences * fuel tanks * sensor validity.

`totalContribution = sum(dataEfficiency * fuelTank * isValid)`

Afterwards, the `payout` method needs to calculate each reward inside of the pools with the amount of tokens based on the following formula:

`reward[address] = dataEfficiency[sensor] * fuelTank[address] * isValid[sensor] / totalContribution`