forked from indexed-finance/dividends
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathERC20NonTransferableRewardsOwned.sol
110 lines (80 loc) · 3.8 KB
/
ERC20NonTransferableRewardsOwned.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// SPDX-License-Identifier: MIT
pragma solidity =0.7.6;
pragma abicoder v2;
import {OwnableUpgradeable as Ownable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {AccessControlUpgradeable as AccessControl} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import {MerkleProofUpgradeable as MerkleProof} from "@openzeppelin/contracts-upgradeable/cryptography/MerkleProofUpgradeable.sol";
import {IERC20Upgradeable as IERC20} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import "./base/ERC20NonTransferableRewards.sol";
import "./libraries/TransferHelper.sol";
import "hardhat/console.sol";
contract ERC20NonTransferableRewardsOwned is ERC20NonTransferableRewards, Ownable, AccessControl {
using TransferHelper for address;
bytes32 public constant MAINTAINER_ROLE = keccak256("MAINTAINER_ROLE");
address public token;
bytes32 public participationMerkleRoot;
event ClaimedFor(uint256 amount, address indexed collector, address indexed to, bytes32[] proof);
event RewardsRedistributed(uint256 amount, address indexed account);
enum ParticipationType{ INACTIVE, YES }
modifier participationNeeded {
require(participationMerkleRoot != bytes32(0), "participationNeeded: merkle root not set");
_;
}
modifier onlyMaintainer {
require(hasRole(MAINTAINER_ROLE, _msgSender()), "onlyMaintainer: sender is not maintainer");
_;
}
function initialize(string memory name_, string memory symbol_, address token_, address maintainer_) public initializer {
require(token == address(0), "Already Initialized");
token = token_;
__Ownable_init();
__AccessControl_init();
ERC20.initialize(name_, symbol_);
_setupRole(MAINTAINER_ROLE, maintainer_);
_setupRole(DEFAULT_ADMIN_ROLE, maintainer_);
}
function mint(address to, uint256 amount) external virtual onlyOwner {
_mint(to, amount);
}
function burn(address from, uint256 amount) external virtual onlyOwner {
_burn(from, amount);
}
function claimFor(address account, bytes32[] memory proof) public {
bytes32 leaf = keccak256(abi.encodePacked(account, uint256(ParticipationType.YES)));
require(MerkleProof.verify(proof, participationMerkleRoot, leaf), "claimFor: Invalid merkle proof");
uint256 amount = _prepareCollect(account);
token.safeTransfer(account, amount);
emit ClaimedFor(amount, _msgSender(), account, proof);
}
function claim(bytes32[] calldata proof) external {
claimFor(_msgSender(), proof);
}
function redistribute(address[] calldata accounts, bytes32[][] calldata proofs) external {
require(accounts.length == proofs.length, "redistribute: Array length mismatch");
uint256 totalRedistributed = 0;
// Save some S_LOADs
bytes32 root = participationMerkleRoot;
for(uint256 i = 0; i < accounts.length; i ++) {
bytes32 leaf = keccak256(abi.encodePacked(accounts[i], uint256(ParticipationType.INACTIVE)));
if(!MerkleProof.verify(proofs[i], root, leaf)) {
// skip if proof is invalid
continue;
}
uint256 redistributedAmount = _prepareCollect(accounts[i]);
totalRedistributed += redistributedAmount;
emit RewardsRedistributed(redistributedAmount, accounts[i]);
}
require(totalRedistributed > 0, "redistribute: Nothing to redistribute");
_distributeRewards(totalRedistributed);
}
function distributeRewards(uint256 amount) external {
token.safeTransferFrom(_msgSender(), address(this), amount);
_distributeRewards(amount);
}
function getPointsCorrection(address account) external view returns (int256) {
return pointsCorrection[account];
}
function setParticipationMerkleRoot(bytes32 newParticipationMerkleRoot) external onlyMaintainer {
participationMerkleRoot = newParticipationMerkleRoot;
}
}