> Feedback: If these docs are stale, missing, or confusing, post sanitized feedback to `https://docs.tempo.xyz/api/feedback` with `source: "mcp"`, a short `message`, and any relevant `toolName`, `relatedResource`, or `client`.
# Tempo Token Rewards Specification

## Abstract

An opt-in, scalable, pro-rata reward distribution mechanism built into TIP-20 tokens. The system uses a "reward-per-token" accumulator pattern to distribute rewards proportionally to opted-in holders without requiring staking or per-holder iteration. Rewards are distributed instantly; time-based streaming distributions are planned for a future upgrade.

## Motivation

Many applications require pro-rata distribution of tokens to existing holders (incentive programs, deterministic inflation, staking rewards). Building this into TIP-20 allows efficient distribution without forcing users to stake tokens elsewhere or requiring distributors to loop over all holders.

## Specification

The rewards mechanism allows anyone to distribute token rewards to opted-in holders proportionally based on holdings. Users must opt in to receiving rewards and may delegate rewards to a recipient address.

## Tempo Token Rewards Functions

These functions are part of the [ITIP20](/docs/protocol/tip20/spec) interface:

```solidity
/// @notice Distribute rewards to opted-in token holders
/// @param amount Amount of tokens to distribute
function distributeReward(uint256 amount) external;

/// @notice Set the reward recipient for the caller (opt in/out of rewards)
/// @param newRewardRecipient Recipient address (address(0) to opt out)
function setRewardRecipient(address newRewardRecipient) external;

/// @notice Claim all pending rewards for the caller
/// @return maxAmount Amount claimed
function claimRewards() external returns (uint256 maxAmount);

/// @notice Get user reward info
function userRewardInfo(address user) external view returns (
    address rewardRecipient,
    uint256 rewardPerToken,
    uint256 rewardBalance
);

// State variables
function globalRewardPerToken() external view returns (uint256);
function optedInSupply() external view returns (uint128);
```

## Accrual Mechanism

The system uses an accumulator pattern:

* `globalRewardPerToken`: Cumulative rewards per token (scaled by 1e18)
* Each user stores a `rewardPerToken` snapshot; pending rewards = `(globalRewardPerToken - snapshot) * balance`

Instant distributions (`seconds_ == 0`) add directly to `globalRewardPerToken` as:
`deltaRPT = amount * 1e18 / optedInSupply`.

## Opt-In Model

Users must call `setRewardRecipient(recipient)` to opt in. When opted in:

* User's balance contributes to `optedInSupply`
* Rewards accrue to `rewardBalance` on balance-changing operations
* Users can delegate rewards to another address

Setting recipient to `address(0)` opts out.

`setRewardRecipient(...)` rejects [TIP-1022](https://github.com/tempoxyz/tempo/blob/main/tips/tip-1022.md) virtual addresses: reward recipients must remain canonical accounts rather than forwarding aliases, because reward assignment is not a TIP-20 forwarding path.

## TIP-403 Integration

All token movements must pass TIP-403 policy checks:

* `distributeReward`: Validates funder authorization
* `setRewardRecipient`: Validates holder and recipient
* `claimRewards`: Validates msg.sender

## Invariants

* `globalRewardPerToken` must monotonically increase
* `optedInSupply` must equal the sum of balances for all opted-in users
* All token movements must comply with TIP-403 policies
