-
Notifications
You must be signed in to change notification settings - Fork 1
/
TokenSplitter.sol
119 lines (93 loc) · 4.32 KB
/
TokenSplitter.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
111
112
113
114
115
116
117
118
119
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import {IERC20, SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
/**
* @title TokenSplitter
* @notice It splits LOOKS to team/treasury/trading volume reward accounts based on shares.
*/
contract TokenSplitter is Ownable, ReentrancyGuard {
using SafeERC20 for IERC20;
struct AccountInfo {
uint256 shares;
uint256 tokensDistributedToAccount;
}
uint256 public immutable TOTAL_SHARES;
IERC20 public immutable looksRareToken;
// Total LOOKS tokens distributed across all accounts
uint256 public totalTokensDistributed;
mapping(address => AccountInfo) public accountInfo;
event NewSharesOwner(address indexed oldRecipient, address indexed newRecipient);
event TokensTransferred(address indexed account, uint256 amount);
/**
* @notice Constructor
* @param _accounts array of accounts addresses
* @param _shares array of shares per account
* @param _looksRareToken address of the LOOKS token
*/
constructor(
address[] memory _accounts,
uint256[] memory _shares,
address _looksRareToken
) {
require(_accounts.length == _shares.length, "Splitter: Length differ");
require(_accounts.length > 0, "Splitter: Length must be > 0");
uint256 currentShares;
for (uint256 i = 0; i < _accounts.length; i++) {
require(_shares[i] > 0, "Splitter: Shares are 0");
currentShares += _shares[i];
accountInfo[_accounts[i]].shares = _shares[i];
}
TOTAL_SHARES = currentShares;
looksRareToken = IERC20(_looksRareToken);
}
/**
* @notice Release LOOKS tokens to the account
* @param account address of the account
*/
function releaseTokens(address account) external nonReentrant {
require(accountInfo[account].shares > 0, "Splitter: Account has no share");
// Calculate amount to transfer to the account
uint256 totalTokensReceived = looksRareToken.balanceOf(address(this)) + totalTokensDistributed;
uint256 pendingRewards = ((totalTokensReceived * accountInfo[account].shares) / TOTAL_SHARES) -
accountInfo[account].tokensDistributedToAccount;
// Revert if equal to 0
require(pendingRewards != 0, "Splitter: Nothing to transfer");
accountInfo[account].tokensDistributedToAccount += pendingRewards;
totalTokensDistributed += pendingRewards;
// Transfer funds to account
looksRareToken.safeTransfer(account, pendingRewards);
emit TokensTransferred(account, pendingRewards);
}
/**
* @notice Update share recipient
* @param _newRecipient address of the new recipient
* @param _currentRecipient address of the current recipient
*/
function updateSharesOwner(address _newRecipient, address _currentRecipient) external onlyOwner {
require(accountInfo[_currentRecipient].shares > 0, "Owner: Current recipient has no shares");
require(accountInfo[_newRecipient].shares == 0, "Owner: New recipient has existing shares");
// Copy shares to new recipient
accountInfo[_newRecipient].shares = accountInfo[_currentRecipient].shares;
accountInfo[_newRecipient].tokensDistributedToAccount = accountInfo[_currentRecipient]
.tokensDistributedToAccount;
// Reset existing shares
accountInfo[_currentRecipient].shares = 0;
accountInfo[_currentRecipient].tokensDistributedToAccount = 0;
emit NewSharesOwner(_currentRecipient, _newRecipient);
}
/**
* @notice Retrieve amount of LOOKS tokens that can be transferred
* @param account address of the account
*/
function calculatePendingRewards(address account) external view returns (uint256) {
if (accountInfo[account].shares == 0) {
return 0;
}
uint256 totalTokensReceived = looksRareToken.balanceOf(address(this)) + totalTokensDistributed;
uint256 pendingRewards = ((totalTokensReceived * accountInfo[account].shares) / TOTAL_SHARES) -
accountInfo[account].tokensDistributedToAccount;
return pendingRewards;
}
}