Skip to content

Commit

Permalink
Fix/rewards (#184)
Browse files Browse the repository at this point in the history
* onchain rewards

* one more test

* onchain voting

* refactor

* typo

* removed min

* Update contracts/libs/gov/gov-pool/GovPoolMicropool.sol

Co-authored-by: Artem Chystiakov <47551140+Arvolear@users.noreply.github.com>

* Update contracts/libs/gov/gov-pool/GovPoolRewards.sol

Co-authored-by: Artem Chystiakov <47551140+Arvolear@users.noreply.github.com>

* Update contracts/libs/gov/gov-pool/GovPoolRewards.sol

Co-authored-by: Artem Chystiakov <47551140+Arvolear@users.noreply.github.com>

* Update contracts/libs/gov/gov-pool/GovPoolRewards.sol

Co-authored-by: Artem Chystiakov <47551140+Arvolear@users.noreply.github.com>

* Update contracts/libs/utils/TokenBalance.sol

Co-authored-by: Artem Chystiakov <47551140+Arvolear@users.noreply.github.com>

* Update test/gov/GovPool.test.js

Co-authored-by: Artem Chystiakov <47551140+Arvolear@users.noreply.github.com>

* Update test/gov/GovPool.test.js

Co-authored-by: Artem Chystiakov <47551140+Arvolear@users.noreply.github.com>

* Update test/gov/GovPool.test.js

Co-authored-by: Artem Chystiakov <47551140+Arvolear@users.noreply.github.com>

* Update test/gov/GovPool.test.js

Co-authored-by: Artem Chystiakov <47551140+Arvolear@users.noreply.github.com>

* removed commented lines

---------

Co-authored-by: Artem Chystiakov <47551140+Arvolear@users.noreply.github.com>
  • Loading branch information
todesstille and Arvolear authored Feb 15, 2024
1 parent 2e7ba47 commit 08764c0
Show file tree
Hide file tree
Showing 5 changed files with 338 additions and 24 deletions.
1 change: 1 addition & 0 deletions contracts/interfaces/gov/IGovPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ interface IGovPool {
uint256[] delegationTimes;
uint256[] delegationPowers;
mapping(uint256 => bool) isClaimed;
mapping(uint256 => uint256) partiallyClaimed;
}

/// @notice The struct that holds reward properties (only for internal needs)
Expand Down
25 changes: 18 additions & 7 deletions contracts/libs/gov/gov-pool/GovPoolMicropool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,22 @@ library GovPoolMicropool {

require(reward != 0, "Gov: no micropool rewards");

userInfos[delegatee].delegatorInfos[delegator].isClaimed[proposalId] = true;
IGovPool.DelegatorInfo storage delegatorInfo = userInfos[delegatee].delegatorInfos[
delegator
];

delegatorInfo.isClaimed[proposalId] = true;

address rewardToken = proposals[proposalId].core.settings.rewardsInfo.rewardToken;

rewardToken.sendFunds(delegator, reward, TokenBalance.TransferType.TryMint);
uint256 paid = rewardToken.sendFunds(delegator, reward, TokenBalance.TransferType.TryMint);

if (paid < reward) {
delegatorInfo.isClaimed[proposalId] = false;
delegatorInfo.partiallyClaimed[proposalId] += paid;
}

emit DelegatorRewardsClaimed(proposalId, delegator, delegatee, rewardToken, reward);
emit DelegatorRewardsClaimed(proposalId, delegator, delegatee, rewardToken, paid);
}

function getDelegatorRewards(
Expand Down Expand Up @@ -151,9 +160,11 @@ library GovPoolMicropool {

uint256 totalVoted = micropoolRawVote.totalVoted;

return
delegatorsRewards.ratio(delegatorInfo.delegationPowers[index], totalVoted).min(
totalVoted
);
uint256 reward = delegatorsRewards.ratio(
delegatorInfo.delegationPowers[index],
totalVoted
);

return reward - delegatorInfo.partiallyClaimed[proposalId];
}
}
95 changes: 81 additions & 14 deletions contracts/libs/gov/gov-pool/GovPoolRewards.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";

import "../../../interfaces/core/ICoreProperties.sol";

Expand All @@ -15,6 +16,7 @@ library GovPoolRewards {
using EnumerableSet for EnumerableSet.AddressSet;
using TokenBalance for address;
using MathHelper for uint256;
using Math for uint256;

event RewardClaimed(uint256 proposalId, address sender, address token, uint256 rewards);
event VotingRewardClaimed(
Expand Down Expand Up @@ -102,25 +104,40 @@ library GovPoolRewards {

require(core.executed, "Gov: proposal is not executed");

uint256 staticRewards = userRewards.staticRewards[proposalId];
IGovPool.VotingRewards memory votingRewards = userRewards.votingRewards[proposalId];
uint256 staticRewardsToPay = userRewards.staticRewards[proposalId];
uint256 staticRewardsPaid;

IGovPool.VotingRewards memory votingRewardsToPay = userRewards.votingRewards[
proposalId
];
IGovPool.VotingRewards memory votingRewardsPaid;

delete userRewards.staticRewards[proposalId];
delete userRewards.votingRewards[proposalId];

address rewardToken = core.settings.rewardsInfo.rewardToken;

_sendRewards(
uint256 rewardsPaid = _sendRewards(
user,
core.settings.rewardsInfo.rewardToken,
staticRewards +
votingRewards.personal +
votingRewards.micropool +
votingRewards.treasury
staticRewardsToPay +
votingRewardsToPay.personal +
votingRewardsToPay.micropool +
votingRewardsToPay.treasury
);

(staticRewardsToPay, staticRewardsPaid) = _recalculateAllRewards(
rewardsPaid,
staticRewardsToPay,
votingRewardsPaid,
votingRewardsToPay
);

emit RewardClaimed(proposalId, user, rewardToken, staticRewards);
emit VotingRewardClaimed(proposalId, user, rewardToken, votingRewards);
userRewards.staticRewards[proposalId] = staticRewardsToPay;
userRewards.votingRewards[proposalId] = votingRewardsToPay;

emit RewardClaimed(proposalId, user, rewardToken, staticRewardsPaid);
emit VotingRewardClaimed(proposalId, user, rewardToken, votingRewardsPaid);
} else {
EnumerableSet.AddressSet storage offchainTokens = userRewards.offchainTokens;
mapping(address => uint256) storage offchainRewards = userRewards.offchainRewards;
Expand All @@ -132,11 +149,16 @@ library GovPoolRewards {
uint256 rewards = offchainRewards[rewardToken];

delete offchainRewards[rewardToken];
offchainTokens.remove(rewardToken);

_sendRewards(user, rewardToken, rewards);
uint256 paid = _sendRewards(user, rewardToken, rewards);

if (paid < rewards) {
offchainRewards[rewardToken] = rewards - paid;
} else {
offchainTokens.remove(rewardToken);
}

emit RewardClaimed(0, user, rewardToken, rewards);
emit RewardClaimed(0, user, rewardToken, paid);
}
}
}
Expand Down Expand Up @@ -189,11 +211,15 @@ library GovPoolRewards {
}
}

function _sendRewards(address receiver, address rewardToken, uint256 rewards) internal {
function _sendRewards(
address receiver,
address rewardToken,
uint256 rewards
) internal returns (uint256) {
require(rewardToken != address(0), "Gov: rewards are off");
require(rewards != 0, "Gov: zero rewards");

rewardToken.sendFunds(receiver, rewards, TokenBalance.TransferType.TryMint);
return rewardToken.sendFunds(receiver, rewards, TokenBalance.TransferType.TryMint);
}

function _getMultipliedRewards(address user, uint256 amount) internal view returns (uint256) {
Expand Down Expand Up @@ -282,4 +308,45 @@ library GovPoolRewards {

votingRewards.micropool -= delegatorsRewards;
}

function _recalculateReward(
uint256 rewardsPaid,
uint256 rewardsToPay
) private pure returns (uint256, uint256, uint256) {
uint256 amountMin = rewardsPaid.min(rewardsToPay);

return (rewardsPaid - amountMin, amountMin, rewardsToPay - amountMin);
}

function _recalculateAllRewards(
uint256 rewardsPaid,
uint256 staticRewardsToPay,
IGovPool.VotingRewards memory votingRewardsPaid,
IGovPool.VotingRewards memory votingRewardsToPay
) private pure returns (uint256, uint256) {
uint256 staticRewardsPaid;

(rewardsPaid, staticRewardsPaid, staticRewardsToPay) = _recalculateReward(
rewardsPaid,
staticRewardsToPay
);

(
rewardsPaid,
votingRewardsPaid.personal,
votingRewardsToPay.personal
) = _recalculateReward(rewardsPaid, votingRewardsToPay.personal);
(
rewardsPaid,
votingRewardsPaid.micropool,
votingRewardsToPay.micropool
) = _recalculateReward(rewardsPaid, votingRewardsToPay.micropool);
(
rewardsPaid,
votingRewardsPaid.treasury,
votingRewardsToPay.treasury
) = _recalculateReward(rewardsPaid, votingRewardsToPay.treasury);

return (staticRewardsToPay, staticRewardsPaid);
}
}
7 changes: 5 additions & 2 deletions contracts/libs/utils/TokenBalance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ library TokenBalance {
address receiver,
uint256 amount,
TransferType transferType
) internal {
) internal returns (uint256) {
uint256 balance = normThisBalance(token);

require(balance >= amount || transferType == TransferType.TryMint, "Insufficient funds");

if (token == ETHEREUM_ADDRESS) {
(bool status, ) = payable(receiver).call{value: amount.min(balance)}("");
amount = amount.min(balance);
(bool status, ) = payable(receiver).call{value: amount}("");

require(status, "Failed to send eth");
} else {
Expand All @@ -47,6 +48,8 @@ library TokenBalance {

IERC20(token).safeTransfer(receiver, amount.from18(token));
}

return amount;
}

function sendFunds(address token, address receiver, uint256 amount) internal {
Expand Down
Loading

0 comments on commit 08764c0

Please sign in to comment.