Rewards
The rewards module adds the distribution of rewards from a specific community pool. Anyone can fund the pool but to change or initiate a reward distribution, a proposal needs to be passed.
Flow
Fund community pool with reward
Create and pass a proposal to create a release schedule
At the end of every block, a linear % of the reward will be forwarded for distribution
When the end time of the release is reached, all rewards will have been given away, and it will go inactive
Internal state
To properly release on time, calculate rewards, and keep track, we have a RewardReleaser with the following internal information:
type RewardReleaser struct {
// Total amount to be rewarded
TotalAmount types.Coin `protobuf:"bytes,1,opt,name=total_amount,json=totalAmount,proto3" json:"total_amount" yaml:"total_amount"`
// Amount released
ReleasedAmount types.Coin `protobuf:"bytes,2,opt,name=released_amount,json=releasedAmount,proto3" json:"released_amount" yaml:"released_amount"`
// Timestamp of end of release
EndTime time.Time `protobuf:"bytes,3,opt,name=end_time,json=endTime,proto3,stdtime" json:"end_time" yaml:"end_time"`
// Last height released
LastReleaseTime time.Time `protobuf:"bytes,5,opt,name=last_release_time,json=lastReleaseTime,proto3,stdtime" json:"last_release_time" yaml:"last_release_time"`
// If reward pool is active
Active bool `protobuf:"varint,6,opt,name=active,proto3" json:"active,omitempty" yaml:"active"`
}
At the end of each block, if the releaser is active:
It will calculate the amount to be distributed linearly across time based on the last release and the current block time.
If the amt to be distributed is zero, it goes inactive
It sends the amount from the pool to the fee collector
It increases the released amount, the last release time, and the community pool with the changes.
Messages
FundPool
Sends funds to the community pool, to be used in a future release.
message MsgFundPool {
string sender = 1 [ (gogoproto.moretags) = "yaml:\"sender\"" ];
cosmos.base.v1beta1.Coin amount = 2 [
(gogoproto.moretags) = "yaml:\"amount\"",
(amino.encoding) = "legacy_coin"
];
}
State Modifications:
The community pool funds will increase, as well as the module's balance
ChangeSchedule
Set the schedule to match what is sent. Only the governor can utilize this call, others need to pass a proposal.
message MsgChangeSchedule {
// authority is the address of the governance account.
string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];
// New information for the schedule
ReleaseSchedule schedule = 2 [ (gogoproto.nullable) = false ];
}
message ReleaseSchedule {
// Total amount to be rewarded
cosmos.base.v1beta1.Coin total_amount = 1 [
(gogoproto.moretags) = "yaml:\"total_amount\""
];
// Amount released
cosmos.base.v1beta1.Coin released_amount = 2 [
(gogoproto.moretags) = "yaml:\"released_amount\""
];
// Timestamp of end of release
google.protobuf.Timestamp end_time = 3 [
(gogoproto.stdtime) = true,
(gogoproto.moretags) = "yaml:\"end_time\""
];
// Last height released
google.protobuf.Timestamp last_release_time = 5 [
(gogoproto.stdtime) = true,
(gogoproto.moretags) = "yaml:\"last_release_time\""
];
// If reward pool is active
bool active = 6 [
(gogoproto.moretags) = "yaml:\"active\""
];
}
State Modifications:
Safety check the following
Denom of the amt must be the one being used
End time must be in the future
Funds must be available in the pool
Changes the reward release schedule to match what is sent
Update Params
Changes module params. Only the governor can utilize this call; others need to pass a proposal.
message MsgUpdateParams {
// authority is the address of the governance account.
string authority = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];
// params defines the x/rewards parameters to update.
//
// NOTE: All parameters must be supplied.
Params params = 2 [ (gogoproto.nullable) = false ];
}
message Params {
// Minimal deposit
string governance_min_deposit = 1;
// Denom used
string token_denom = 2;
}
State Modifications:
Changes the token_denom and min deposit
Other important flows
The releaser has a few edge cases that happen when it is initializing or going inactive:
First iteration
There is no previous release time, so we cannot calculate a reward distribution
Instead of calculating the reward, we just set the last release as the block time
Next iteration will cover it well
Last iteration
As the first release is delayed, so will be the last one
Once the EndTime is passed, all the remaining rewards will be distributed
The releaser will just go inactive a block after, when there is no amount to distribute
Last updated
Was this helpful?