-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathVKatMetadata.sol
More file actions
183 lines (138 loc) · 6.27 KB
/
VKatMetadata.sol
File metadata and controls
183 lines (138 loc) · 6.27 KB
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import { DaoAuthorizableUpgradeable as DaoAuthorizable } from
"@aragon/osx-commons-contracts/src/permission/auth/DaoAuthorizableUpgradeable.sol";
import { IDAO } from "@aragon/osx-commons-contracts/src/dao/IDAO.sol";
import { IVKatMetadata } from "src/interfaces/IVKatMetadata.sol";
contract VKatMetadata is IVKatMetadata, DaoAuthorizable, UUPSUpgradeable {
using EnumerableSet for EnumerableSet.AddressSet;
/// @notice The bytes32 identifier for admin role functions.
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
/// @notice Expresses a preference to auto-compound rewards into vKat.
address public constant AUTOCOMPOUND_RESERVED_ADDRESS = address(type(uint160).max);
/// @notice The preferences per user.
mapping(address => VKatMetaDataV1) private preferences;
/// @notice The list of whitelisted tokens added by admin.
EnumerableSet.AddressSet internal rewardTokens;
/// @notice The default preferences that will be used if user hasn't set it.
VKatMetaDataV1 private defaultPreferences;
/// @notice The address of kat token.
address public kat;
constructor() {
_disableInitializers();
}
function initialize(address _dao, address _kat, address[] calldata _rewardTokens) external initializer {
__DaoAuthorizableUpgradeable_init(IDAO(_dao));
kat = _kat;
// whitelist reward tokens.
for (uint256 i = 0; i < _rewardTokens.length; i++) {
address token = _rewardTokens[i];
rewardTokens.add(token);
emit RewardTokenAdded(token);
}
// add KAT as a reward token.
rewardTokens.add(kat);
emit RewardTokenAdded(kat);
// add the reserved address for auto-compounding.
rewardTokens.add(AUTOCOMPOUND_RESERVED_ADDRESS);
emit RewardTokenAdded(AUTOCOMPOUND_RESERVED_ADDRESS);
// Set the default preferences to auto-compound into vKat.
uint16[] memory _weights = new uint16[](1);
address[] memory _tokens = new address[](1);
VKatMetaDataV1 memory _defaultPreferences =
VKatMetaDataV1({ rewardTokenWeights: _weights, rewardTokens: _tokens });
_defaultPreferences.rewardTokens[0] = AUTOCOMPOUND_RESERVED_ADDRESS;
_defaultPreferences.rewardTokenWeights[0] = 1;
_setDefaultPreferences(_defaultPreferences);
}
// ============= Admin Functions ====================
/// @inheritdoc IVKatMetadata
function addRewardToken(address _token) external auth(ADMIN_ROLE) {
if (_token == address(0)) {
revert ZeroAddress();
}
bool added = rewardTokens.add(_token);
if (!added) {
revert TokenAlreadyInWhitelist(_token);
}
emit RewardTokenAdded(_token);
}
/// @inheritdoc IVKatMetadata
function removeRewardToken(address _token) external auth(ADMIN_ROLE) {
if (_token == AUTOCOMPOUND_RESERVED_ADDRESS || _token == kat) {
revert ReservedAddressCannotBeRemoved();
}
bool removed = rewardTokens.remove(_token);
if (!removed) {
revert TokenNotInWhitelist(_token);
}
emit RewardTokenRemoved(_token);
}
/// @inheritdoc IVKatMetadata
function setDefaultPreferences(VKatMetaDataV1 memory _preferences) external auth(ADMIN_ROLE) {
_setDefaultPreferences(_preferences);
}
// ============ User Specific Functions =============
/// @inheritdoc IVKatMetadata
function setPreferences(VKatMetaDataV1 calldata _preferences) public virtual {
_validatePreferences(_preferences);
preferences[msg.sender] = _preferences;
emit PreferencesSet(msg.sender, _preferences);
}
// =========== View Functions ==============
/// @inheritdoc IVKatMetadata
function isRewardToken(address _token) public view returns (bool) {
return rewardTokens.contains(_token);
}
/// @inheritdoc IVKatMetadata
function getPreferencesOrDefault(address _account) public view returns (VKatMetaDataV1 memory) {
VKatMetaDataV1 memory preferences_ = preferences[_account];
if (preferences_.rewardTokens.length == 0) {
preferences_ = getDefaultPreferences();
}
return preferences_;
}
/// @inheritdoc IVKatMetadata
function getDefaultPreferences() public view virtual returns (VKatMetaDataV1 memory) {
return defaultPreferences;
}
/// @inheritdoc IVKatMetadata
function allowedRewardTokens() external view returns (address[] memory) {
return rewardTokens.values();
}
/// @dev Helper function to validate the new default preferences and set it.
function _setDefaultPreferences(VKatMetaDataV1 memory _preferences) internal virtual {
_validatePreferences(_preferences);
defaultPreferences = _preferences;
emit DefaultPreferencesSet(_preferences);
}
function _validatePreferences(VKatMetaDataV1 memory _preferences) internal virtual {
if (_preferences.rewardTokens.length != _preferences.rewardTokenWeights.length) {
revert LengthMismatch();
}
address[] memory tokens = _preferences.rewardTokens;
for (uint256 i = 0; i < tokens.length; i++) {
address token = tokens[i];
// Validate that reward token is already
// added by admin in a whitelist.
if (!isRewardToken(token)) {
revert TokenNotWhitelisted(token);
}
// Ensure for no duplicate addresses
for (uint256 j = i + 1; j < tokens.length; j++) {
if (tokens[j] == token) {
revert DuplicateRewardToken();
}
}
}
}
// =========== Upgrade Related Functions ===========
function _authorizeUpgrade(address) internal override auth(ADMIN_ROLE) { }
function implementation() external view returns (address) {
return _getImplementation();
}
/// @dev Reserved storage space to allow for layout changes in the future.
uint256[44] private __gap;
}