Skip to content

Commit

Permalink
implement reward cap and commission cap
Browse files Browse the repository at this point in the history
  • Loading branch information
ianhe8x committed Apr 21, 2024
1 parent 402d9da commit 7e644b2
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 14 deletions.
63 changes: 49 additions & 14 deletions contracts/RewardsDistributor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ contract RewardsDistributor is IRewardsDistributor, Initializable, OwnableUpgrad
/// @notice Reward information: runner => RewardInfo
mapping(address => RewardInfo) private info;

/// @notice perMill, <max commission> = <selfStake> * <maxCommissionFactor>
/// 0: disabled
uint256 maxCommissionFactor;

/// @notice perMill, <max pool reward> = <totalStake> * <maxRewardFactor>
/// 0: disabled
uint256 maxRewardFactor;

/// @dev ### EVENTS
/// @notice Emitted when rewards are distributed for the earliest pending distributed Era.
event DistributeRewards(
Expand All @@ -98,6 +106,8 @@ contract RewardsDistributor is IRewardsDistributor, Initializable, OwnableUpgrad
event InstantRewards(address indexed runner, uint256 indexed eraIdx, uint256 token);
/// @notice Emitted when rewards arrive via increaseAgreementRewards()
event AgreementRewards(address indexed runner, uint256 agreementId, uint256 token);
/// @notice Emitted when rewards return to treasury due to exceed reward cap
event ReturnRewards(address indexed runner, uint256 token, uint256 commission);

modifier onlyRewardsStaking() {
require(msg.sender == settings.getContractAddress(SQContracts.RewardsStaking), 'G014');
Expand All @@ -119,6 +129,14 @@ contract RewardsDistributor is IRewardsDistributor, Initializable, OwnableUpgrad
settings = _settings;
}

function setMaxCommissionFactor(uint256 _maxCommissionFactor) external onlyOwner {
maxCommissionFactor = _maxCommissionFactor;
}

function setMaxRewardFactor(uint256 _maxRewardFactor) external onlyOwner {
maxRewardFactor = _maxRewardFactor;
}

/**
* @notice Initialize the runner first last claim era.
* Only RewardsStaking can call.
Expand Down Expand Up @@ -347,36 +365,53 @@ contract RewardsDistributor is IRewardsDistributor, Initializable, OwnableUpgrad
delete rewardInfo.eraRewardRemoveTable[rewardInfo.lastClaimEra];
if (rewardInfo.eraReward != 0) {
uint256 totalStake = rewardsStaking.getTotalStakingAmount(runner);
uint256 selfStake = rewardsStaking.getDelegationAmount(runner, runner);
require(totalStake > 0, 'RD006');

uint256 commissionRate = IIndexerRegistry(
settings.getContractAddress(SQContracts.IndexerRegistry)
).getCommissionRate(runner);
uint256 commission = MathUtil.mulDiv(commissionRate, rewardInfo.eraReward, PER_MILL);

info[runner].accSQTPerStake += MathUtil.mulDiv(
rewardInfo.eraReward - commission,
uint256 commission = commissionRate.mulDiv(rewardInfo.eraReward, PER_MILL);

// 1. total reward can not greater than factor2 * total_stake
// 2. commission can not greater than factor * self_stake
uint256 cappedReward = maxRewardFactor > 0
? MathUtil.min(rewardInfo.eraReward, totalStake.mulDiv(maxRewardFactor, PER_MILL))
: rewardInfo.eraReward;
uint256 cappedCommission = maxCommissionFactor > 0
? MathUtil.min(commission, selfStake.mulDiv(maxCommissionFactor, PER_MILL))
: commission;
info[runner].accSQTPerStake += cappedReward.sub(cappedCommission).mulDiv(
PER_TRILL,
totalStake
);
if (commission > 0) {
IERC20 SQToken = IERC20(settings.getContractAddress(SQContracts.SQToken));
if (cappedCommission > 0) {
// add commission to unbonding request
IERC20(settings.getContractAddress(SQContracts.SQToken)).safeTransfer(
SQToken.safeTransfer(
settings.getContractAddress(SQContracts.Staking),
commission
cappedCommission
);
IStaking(settings.getContractAddress(SQContracts.Staking)).unbondCommission(
runner,
commission
cappedCommission
);
}

emit DistributeRewards(
runner,
rewardInfo.lastClaimEra,
rewardInfo.eraReward,
commission
);
emit DistributeRewards(runner, rewardInfo.lastClaimEra, cappedReward, cappedCommission);

if (rewardInfo.eraReward - cappedReward > 0 || commission - cappedCommission > 0) {
uint256 rewardsReturn;
rewardsReturn += rewardInfo.eraReward - cappedReward;
rewardsReturn += commission - cappedCommission;
address treasury = ISettings(settings).getContractAddress(SQContracts.Treasury);
SQToken.safeTransfer(treasury, rewardsReturn);
emit ReturnRewards(
runner,
rewardInfo.eraReward - cappedReward,
commission - cappedCommission
);
}
}
return rewardInfo.lastClaimEra;
}
Expand Down
51 changes: 51 additions & 0 deletions publish/ABI/RewardsDistributor.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,31 @@
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "runner",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "token",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "commission",
"type": "uint256"
}
],
"name": "ReturnRewards",
"type": "event"
},
{
"anonymous": false,
"inputs": [
Expand Down Expand Up @@ -460,6 +485,32 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_maxCommissionFactor",
"type": "uint256"
}
],
"name": "setMaxCommissionFactor",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_maxRewardFactor",
"type": "uint256"
}
],
"name": "setMaxRewardFactor",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
Expand Down

0 comments on commit 7e644b2

Please sign in to comment.