@venusprotocol/protocol-reserve 1.0.0-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +69 -0
- package/artifacts/@openzeppelin/contracts/access/IAccessControl.sol/IAccessControl.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/access/IAccessControl.sol/IAccessControl.json +183 -0
- package/artifacts/@openzeppelin/contracts/token/ERC20/ERC20.sol/ERC20.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/token/ERC20/ERC20.sol/ERC20.json +297 -0
- package/artifacts/@openzeppelin/contracts/token/ERC20/IERC20.sol/IERC20.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/token/ERC20/IERC20.sol/IERC20.json +194 -0
- package/artifacts/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol/IERC20Metadata.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol/IERC20Metadata.json +233 -0
- package/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts/utils/Context.sol/Context.json +10 -0
- package/artifacts/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol/Ownable2StepUpgradeable.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol/Ownable2StepUpgradeable.json +115 -0
- package/artifacts/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol/OwnableUpgradeable.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol/OwnableUpgradeable.json +76 -0
- package/artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol/Initializable.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol/Initializable.json +24 -0
- package/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol/IERC20Upgradeable.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol/IERC20Upgradeable.json +194 -0
- package/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol/IERC20PermitUpgradeable.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol/IERC20PermitUpgradeable.json +86 -0
- package/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol/SafeERC20Upgradeable.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol/SafeERC20Upgradeable.json +10 -0
- package/artifacts/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol/AddressUpgradeable.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol/AddressUpgradeable.json +10 -0
- package/artifacts/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol/ContextUpgradeable.dbg.json +4 -0
- package/artifacts/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol/ContextUpgradeable.json +24 -0
- package/artifacts/@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol/AccessControlledV8.dbg.json +4 -0
- package/artifacts/@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol/AccessControlledV8.json +181 -0
- package/artifacts/@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol/IAccessControlManagerV8.dbg.json +4 -0
- package/artifacts/@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol/IAccessControlManagerV8.json +282 -0
- package/artifacts/build-info/c112788394311939ef4c47b76cde5898.json +1 -0
- package/artifacts/contracts/Interfaces/ComptrollerInterface.sol/ComptrollerInterface.dbg.json +4 -0
- package/artifacts/contracts/Interfaces/ComptrollerInterface.sol/ComptrollerInterface.json +24 -0
- package/artifacts/contracts/Interfaces/IIncomeDestination.sol/IIncomeDestination.dbg.json +4 -0
- package/artifacts/contracts/Interfaces/IIncomeDestination.sol/IIncomeDestination.json +29 -0
- package/artifacts/contracts/Interfaces/IPrime.sol/IPrime.dbg.json +4 -0
- package/artifacts/contracts/Interfaces/IPrime.sol/IPrime.json +74 -0
- package/artifacts/contracts/Interfaces/IProtocolShareReserve.sol/IProtocolShareReserve.dbg.json +4 -0
- package/artifacts/contracts/Interfaces/IProtocolShareReserve.sol/IProtocolShareReserve.json +34 -0
- package/artifacts/contracts/Interfaces/IVToken.sol/IVToken.dbg.json +4 -0
- package/artifacts/contracts/Interfaces/IVToken.sol/IVToken.json +24 -0
- package/artifacts/contracts/Interfaces/PoolRegistryInterface.sol/PoolRegistryInterface.dbg.json +4 -0
- package/artifacts/contracts/Interfaces/PoolRegistryInterface.sol/PoolRegistryInterface.json +35 -0
- package/artifacts/contracts/ProtocolReserve/ProtocolShareReserve.sol/ProtocolShareReserve.dbg.json +4 -0
- package/artifacts/contracts/ProtocolReserve/ProtocolShareReserve.sol/ProtocolShareReserve.json +741 -0
- package/artifacts/contracts/Test/Mocks/MockToken.sol/MockToken.dbg.json +4 -0
- package/artifacts/contracts/Test/Mocks/MockToken.sol/MockToken.json +315 -0
- package/contracts/Interfaces/ComptrollerInterface.sol +6 -0
- package/contracts/Interfaces/IIncomeDestination.sol +6 -0
- package/contracts/Interfaces/IPrime.sol +12 -0
- package/contracts/Interfaces/IProtocolShareReserve.sol +12 -0
- package/contracts/Interfaces/IVToken.sol +6 -0
- package/contracts/Interfaces/PoolRegistryInterface.sol +7 -0
- package/contracts/ProtocolReserve/ProtocolShareReserve.sol +378 -0
- package/contracts/Test/Mocks/MockToken.sol +22 -0
- package/contracts/interfaces/ComptrollerInterface.sol +6 -0
- package/contracts/interfaces/IProtocolShareReserve.sol +12 -0
- package/contracts/interfaces/PoolRegistryInterface.sol +7 -0
- package/contracts/test/Mocks/MockToken.sol +22 -0
- package/package.json +116 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
pragma solidity 0.8.13;
|
|
3
|
+
|
|
4
|
+
import { SafeERC20Upgradeable, IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
|
|
5
|
+
import { AccessControlledV8 } from "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol";
|
|
6
|
+
|
|
7
|
+
import { IProtocolShareReserve } from "../Interfaces/IProtocolShareReserve.sol";
|
|
8
|
+
import { ComptrollerInterface } from "../Interfaces/ComptrollerInterface.sol";
|
|
9
|
+
import { PoolRegistryInterface } from "../Interfaces/PoolRegistryInterface.sol";
|
|
10
|
+
import { IPrime } from "../Interfaces/IPrime.sol";
|
|
11
|
+
import { IVToken } from "../Interfaces/IVToken.sol";
|
|
12
|
+
import { IIncomeDestination } from "../Interfaces/IIncomeDestination.sol";
|
|
13
|
+
|
|
14
|
+
error InvalidAddress();
|
|
15
|
+
error UnsupportedAsset();
|
|
16
|
+
error InvalidTotalPercentage();
|
|
17
|
+
|
|
18
|
+
contract ProtocolShareReserve is AccessControlledV8, IProtocolShareReserve {
|
|
19
|
+
using SafeERC20Upgradeable for IERC20Upgradeable;
|
|
20
|
+
|
|
21
|
+
/// @notice protocol income is categorized into two schemas.
|
|
22
|
+
/// The first schema is for spread income from prime markets in core protocol
|
|
23
|
+
/// The second schema is for all other sources and types of income
|
|
24
|
+
enum Schema {
|
|
25
|
+
DEFAULT,
|
|
26
|
+
SPREAD_PRIME_CORE
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
struct DistributionConfig {
|
|
30
|
+
Schema schema;
|
|
31
|
+
/// @dev percenatge is represented without any scale
|
|
32
|
+
uint256 percentage;
|
|
33
|
+
address destination;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/// @notice address of core pool comptroller contract
|
|
37
|
+
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
|
|
38
|
+
address public immutable CORE_POOL_COMPTROLLER;
|
|
39
|
+
|
|
40
|
+
/// @notice address of WBNB contract
|
|
41
|
+
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
|
|
42
|
+
address public immutable WBNB;
|
|
43
|
+
|
|
44
|
+
/// @notice address of vBNB contract
|
|
45
|
+
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
|
|
46
|
+
address public immutable vBNB;
|
|
47
|
+
|
|
48
|
+
/// @notice address of Prime contract
|
|
49
|
+
address public prime;
|
|
50
|
+
|
|
51
|
+
/// @notice address of pool registry contract
|
|
52
|
+
address public poolRegistry;
|
|
53
|
+
|
|
54
|
+
uint256 private constant MAX_PERCENT = 100;
|
|
55
|
+
|
|
56
|
+
/// @notice comptroller => asset => schema => balance
|
|
57
|
+
mapping(address => mapping(address => mapping(Schema => uint256))) public assetsReserves;
|
|
58
|
+
|
|
59
|
+
/// @notice asset => balance
|
|
60
|
+
mapping(address => uint256) public totalAssetReserve;
|
|
61
|
+
|
|
62
|
+
/// @notice configuration for different income distribution targets
|
|
63
|
+
DistributionConfig[] public distributionTargets;
|
|
64
|
+
|
|
65
|
+
/// @notice Emitted when pool registry address is updated
|
|
66
|
+
event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);
|
|
67
|
+
|
|
68
|
+
/// @notice Emitted when prime address is updated
|
|
69
|
+
event PrimeUpdated(address indexed oldPrime, address indexed newPrime);
|
|
70
|
+
|
|
71
|
+
/// @notice Event emitted after the updation of the assets reserves.
|
|
72
|
+
event AssetsReservesUpdated(
|
|
73
|
+
address indexed comptroller,
|
|
74
|
+
address indexed asset,
|
|
75
|
+
uint256 amount,
|
|
76
|
+
IncomeType incomeType,
|
|
77
|
+
Schema schema
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
/// @notice Event emitted after a income distribution target is configured
|
|
81
|
+
event DestinationConfigured(address indexed destination, uint percent, Schema schema);
|
|
82
|
+
|
|
83
|
+
/// @notice Event emitted when an asset is released to a target
|
|
84
|
+
event AssetReleased(
|
|
85
|
+
address indexed destination,
|
|
86
|
+
address indexed asset,
|
|
87
|
+
Schema schema,
|
|
88
|
+
uint256 percent,
|
|
89
|
+
uint256 amount
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
/// @notice Event emitted when asset reserves state is updated
|
|
93
|
+
event ReservesUpdated(
|
|
94
|
+
address indexed comptroller,
|
|
95
|
+
address indexed asset,
|
|
96
|
+
Schema schema,
|
|
97
|
+
uint256 oldBalance,
|
|
98
|
+
uint256 newBalance
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
/// @notice Event emitted when distribution configuration is updated
|
|
102
|
+
event DistributionConfigUpdated(
|
|
103
|
+
address indexed destination,
|
|
104
|
+
uint256 oldPercentage,
|
|
105
|
+
uint256 newPercentage,
|
|
106
|
+
Schema schema
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
/// @notice Event emitted when distribution configuration is added
|
|
110
|
+
event DistributionConfigAdded(address indexed destination, uint256 percentage, Schema schema);
|
|
111
|
+
|
|
112
|
+
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
113
|
+
constructor(address _corePoolComptroller, address _wbnb, address _vbnb) {
|
|
114
|
+
if (_corePoolComptroller == address(0)) revert InvalidAddress();
|
|
115
|
+
if (_wbnb == address(0)) revert InvalidAddress();
|
|
116
|
+
if (_vbnb == address(0)) revert InvalidAddress();
|
|
117
|
+
|
|
118
|
+
CORE_POOL_COMPTROLLER = _corePoolComptroller;
|
|
119
|
+
WBNB = _wbnb;
|
|
120
|
+
vBNB = _vbnb;
|
|
121
|
+
|
|
122
|
+
// Note that the contract is upgradeable. Use initialize() or reinitializers
|
|
123
|
+
// to set the state variables.
|
|
124
|
+
_disableInitializers();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @dev Initializes the deployer to owner.
|
|
129
|
+
* @param _accessControlManager The address of ACM contract
|
|
130
|
+
*/
|
|
131
|
+
function initialize(address _accessControlManager) external initializer {
|
|
132
|
+
__AccessControlled_init(_accessControlManager);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* @dev Pool registry setter.
|
|
137
|
+
* @param _poolRegistry Address of the pool registry
|
|
138
|
+
*/
|
|
139
|
+
function setPoolRegistry(address _poolRegistry) external {
|
|
140
|
+
_checkAccessAllowed("setPoolRegistry(address)");
|
|
141
|
+
if (_poolRegistry == address(0)) revert InvalidAddress();
|
|
142
|
+
address oldPoolRegistry = poolRegistry;
|
|
143
|
+
poolRegistry = _poolRegistry;
|
|
144
|
+
emit PoolRegistryUpdated(oldPoolRegistry, poolRegistry);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* @dev Prime contract address setter.
|
|
149
|
+
* @param _prime Address of the prime contract
|
|
150
|
+
*/
|
|
151
|
+
function setPrime(address _prime) external {
|
|
152
|
+
_checkAccessAllowed("setPrime(address)");
|
|
153
|
+
if (_prime == address(0)) revert InvalidAddress();
|
|
154
|
+
address oldPrime = prime;
|
|
155
|
+
prime = _prime;
|
|
156
|
+
emit PrimeUpdated(oldPrime, prime);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* @dev Add or update destination targets based on destination address
|
|
161
|
+
* @param configs configurations of the destinations.
|
|
162
|
+
*/
|
|
163
|
+
function addOrUpdateDistributionConfigs(DistributionConfig[] memory configs) external {
|
|
164
|
+
_checkAccessAllowed("addOrUpdateDistributionConfigs(DistributionConfig)");
|
|
165
|
+
|
|
166
|
+
//we need to accrue and release funds to prime before updating the distribution configuration
|
|
167
|
+
//because prime relies on getUnreleasedFunds and its return value may change after config update
|
|
168
|
+
_accrueAndReleaseFundsToPrime();
|
|
169
|
+
|
|
170
|
+
for (uint i = 0; i < configs.length; ++i) {
|
|
171
|
+
DistributionConfig memory _config = configs[i];
|
|
172
|
+
require(_config.destination != address(0), "ProtocolShareReserve: Destination address invalid");
|
|
173
|
+
|
|
174
|
+
bool updated = false;
|
|
175
|
+
for (uint j = 0; j < distributionTargets.length; ++j) {
|
|
176
|
+
DistributionConfig storage config = distributionTargets[j];
|
|
177
|
+
|
|
178
|
+
if (_config.schema == config.schema && config.destination == _config.destination) {
|
|
179
|
+
emit DistributionConfigUpdated(
|
|
180
|
+
config.destination,
|
|
181
|
+
config.percentage,
|
|
182
|
+
_config.percentage,
|
|
183
|
+
config.schema
|
|
184
|
+
);
|
|
185
|
+
config.percentage = _config.percentage;
|
|
186
|
+
updated = true;
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (!updated) {
|
|
192
|
+
distributionTargets.push(_config);
|
|
193
|
+
emit DistributionConfigAdded(_config.destination, _config.percentage, _config.schema);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
_ensurePercentages();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* @dev Release funds
|
|
202
|
+
* @param assets assets to be released to distribution targets
|
|
203
|
+
*/
|
|
204
|
+
function releaseFunds(address comptroller, address[] memory assets) external {
|
|
205
|
+
_accruePrimeInterest();
|
|
206
|
+
|
|
207
|
+
for (uint i = 0; i < assets.length; ++i) {
|
|
208
|
+
_releaseFund(comptroller, assets[i]);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* @dev Used to find out the amount of funds that's going to be released when release funds is called.
|
|
214
|
+
* @param comptroller the comptroller address of the pool
|
|
215
|
+
* @param schema the schema of the distribution target
|
|
216
|
+
* @param destination the destination address of the distribution target
|
|
217
|
+
* @param asset the asset address which will be released
|
|
218
|
+
*/
|
|
219
|
+
function getUnreleasedFunds(
|
|
220
|
+
address comptroller,
|
|
221
|
+
Schema schema,
|
|
222
|
+
address destination,
|
|
223
|
+
address asset
|
|
224
|
+
) external view returns (uint256) {
|
|
225
|
+
for (uint i = 0; i < distributionTargets.length; ++i) {
|
|
226
|
+
DistributionConfig storage _config = distributionTargets[i];
|
|
227
|
+
if (_config.schema == schema && _config.destination == destination) {
|
|
228
|
+
uint256 total = assetsReserves[comptroller][asset][schema];
|
|
229
|
+
return (total * _config.percentage) / MAX_PERCENT;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* @dev Returns the total number of distribution targets
|
|
236
|
+
*/
|
|
237
|
+
function totalDistributions() external view returns (uint256) {
|
|
238
|
+
return distributionTargets.length;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* @dev Update the reserve of the asset for the specific pool after transferring to the protocol share reserve.
|
|
243
|
+
* @param comptroller Comptroller address(pool)
|
|
244
|
+
* @param asset Asset address.
|
|
245
|
+
*/
|
|
246
|
+
function updateAssetsState(
|
|
247
|
+
address comptroller,
|
|
248
|
+
address asset,
|
|
249
|
+
IncomeType incomeType
|
|
250
|
+
) public override(IProtocolShareReserve) {
|
|
251
|
+
if (!ComptrollerInterface(comptroller).isComptroller()) revert InvalidAddress();
|
|
252
|
+
if (asset == address(0)) revert InvalidAddress();
|
|
253
|
+
if (
|
|
254
|
+
comptroller != CORE_POOL_COMPTROLLER &&
|
|
255
|
+
PoolRegistryInterface(poolRegistry).getVTokenForAsset(comptroller, asset) == address(0)
|
|
256
|
+
) revert InvalidAddress();
|
|
257
|
+
|
|
258
|
+
Schema schema = getSchema(comptroller, asset, incomeType);
|
|
259
|
+
uint256 currentBalance = IERC20Upgradeable(asset).balanceOf(address(this));
|
|
260
|
+
uint256 assetReserve = totalAssetReserve[asset];
|
|
261
|
+
|
|
262
|
+
if (currentBalance > assetReserve) {
|
|
263
|
+
uint256 balanceDifference;
|
|
264
|
+
unchecked {
|
|
265
|
+
balanceDifference = currentBalance - assetReserve;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
assetsReserves[comptroller][asset][schema] += balanceDifference;
|
|
269
|
+
totalAssetReserve[asset] += balanceDifference;
|
|
270
|
+
emit AssetsReservesUpdated(comptroller, asset, balanceDifference, incomeType, schema);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* @dev Fetches the list of prime markets and then accrues interest and
|
|
276
|
+
* releases the funds to prime for each market
|
|
277
|
+
*/
|
|
278
|
+
function _accrueAndReleaseFundsToPrime() internal {
|
|
279
|
+
address[] memory markets = IPrime(prime).allMarkets();
|
|
280
|
+
for (uint i = 0; i < markets.length; ++i) {
|
|
281
|
+
address market = markets[i];
|
|
282
|
+
IPrime(prime).accrueInterest(market);
|
|
283
|
+
_releaseFund(CORE_POOL_COMPTROLLER, _getUnderlying(market));
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* @dev Fetches the list of prime markets and then accrues interest
|
|
289
|
+
* to prime for each market
|
|
290
|
+
*/
|
|
291
|
+
function _accruePrimeInterest() internal {
|
|
292
|
+
address[] memory markets = IPrime(prime).allMarkets();
|
|
293
|
+
for (uint i = 0; i < markets.length; ++i) {
|
|
294
|
+
address market = markets[i];
|
|
295
|
+
IPrime(prime).accrueInterest(market);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function _releaseFund(address comptroller, address asset) internal {
|
|
300
|
+
uint256 totalSchemas = uint256(type(Schema).max) + 1;
|
|
301
|
+
uint[] memory schemaBalances = new uint[](totalSchemas);
|
|
302
|
+
uint256 totalBalance;
|
|
303
|
+
|
|
304
|
+
for (uint schemaValue; schemaValue < totalSchemas; ++schemaValue) {
|
|
305
|
+
schemaBalances[schemaValue] = assetsReserves[comptroller][asset][Schema(schemaValue)];
|
|
306
|
+
totalBalance += schemaBalances[schemaValue];
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (totalBalance == 0) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
uint[] memory totalTransferAmounts = new uint[](totalSchemas);
|
|
314
|
+
|
|
315
|
+
for (uint i = 0; i < distributionTargets.length; ++i) {
|
|
316
|
+
DistributionConfig memory _config = distributionTargets[i];
|
|
317
|
+
|
|
318
|
+
uint256 transferAmount = (schemaBalances[uint256(_config.schema)] * _config.percentage) / MAX_PERCENT;
|
|
319
|
+
totalTransferAmounts[uint256(_config.schema)] += transferAmount;
|
|
320
|
+
|
|
321
|
+
IERC20Upgradeable(asset).safeTransfer(_config.destination, transferAmount);
|
|
322
|
+
IIncomeDestination(_config.destination).updateAssetsState(comptroller, asset);
|
|
323
|
+
|
|
324
|
+
emit AssetReleased(_config.destination, asset, _config.schema, _config.percentage, transferAmount);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
uint[] memory newSchemaBalances = new uint[](totalSchemas);
|
|
328
|
+
for (uint schemaValue = 0; schemaValue < totalSchemas; ++schemaValue) {
|
|
329
|
+
newSchemaBalances[schemaValue] = schemaBalances[schemaValue] - totalTransferAmounts[schemaValue];
|
|
330
|
+
assetsReserves[comptroller][asset][Schema(schemaValue)] = newSchemaBalances[schemaValue];
|
|
331
|
+
totalAssetReserve[asset] = totalAssetReserve[asset] - totalTransferAmounts[schemaValue];
|
|
332
|
+
|
|
333
|
+
emit ReservesUpdated(
|
|
334
|
+
comptroller,
|
|
335
|
+
asset,
|
|
336
|
+
Schema(schemaValue),
|
|
337
|
+
schemaBalances[schemaValue],
|
|
338
|
+
newSchemaBalances[schemaValue]
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function getSchema(
|
|
344
|
+
address comptroller,
|
|
345
|
+
address asset,
|
|
346
|
+
IncomeType incomeType
|
|
347
|
+
) internal view returns (Schema schema) {
|
|
348
|
+
schema = Schema.DEFAULT;
|
|
349
|
+
address vToken = IPrime(prime).vTokenForAsset(asset);
|
|
350
|
+
|
|
351
|
+
if (vToken != address(0) && comptroller == CORE_POOL_COMPTROLLER && incomeType == IncomeType.SPREAD) {
|
|
352
|
+
schema = Schema.SPREAD_PRIME_CORE;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function _ensurePercentages() internal view {
|
|
357
|
+
uint256 totalSchemas = uint256(type(Schema).max) + 1;
|
|
358
|
+
uint[] memory totalPercentages = new uint[](totalSchemas);
|
|
359
|
+
|
|
360
|
+
for (uint i = 0; i < distributionTargets.length; ++i) {
|
|
361
|
+
DistributionConfig memory config = distributionTargets[i];
|
|
362
|
+
totalPercentages[uint256(config.schema)] += config.percentage;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
for (uint schemaValue = 0; schemaValue <= totalSchemas - 1; ++schemaValue) {
|
|
366
|
+
if (totalPercentages[schemaValue] != MAX_PERCENT && totalPercentages[schemaValue] != 0)
|
|
367
|
+
revert InvalidTotalPercentage();
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function _getUnderlying(address vToken) internal view returns (address) {
|
|
372
|
+
if (vToken == vBNB) {
|
|
373
|
+
return WBNB;
|
|
374
|
+
} else {
|
|
375
|
+
return IVToken(vToken).underlying();
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)
|
|
3
|
+
|
|
4
|
+
pragma solidity ^0.8.0;
|
|
5
|
+
|
|
6
|
+
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
7
|
+
|
|
8
|
+
contract MockToken is ERC20 {
|
|
9
|
+
uint8 private immutable _decimals;
|
|
10
|
+
|
|
11
|
+
constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) {
|
|
12
|
+
_decimals = decimals_;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function faucet(uint256 amount) external {
|
|
16
|
+
_mint(msg.sender, amount);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function decimals() public view virtual override returns (uint8) {
|
|
20
|
+
return _decimals;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BSD-3-Clause
|
|
2
|
+
pragma solidity 0.8.13;
|
|
3
|
+
|
|
4
|
+
interface IProtocolShareReserve {
|
|
5
|
+
/// @notice it represents the type of vToken income
|
|
6
|
+
enum IncomeType {
|
|
7
|
+
SPREAD,
|
|
8
|
+
LIQUIDATION
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;
|
|
12
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)
|
|
3
|
+
|
|
4
|
+
pragma solidity ^0.8.0;
|
|
5
|
+
|
|
6
|
+
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
7
|
+
|
|
8
|
+
contract MockToken is ERC20 {
|
|
9
|
+
uint8 private immutable _decimals;
|
|
10
|
+
|
|
11
|
+
constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) {
|
|
12
|
+
_decimals = decimals_;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function faucet(uint256 amount) external {
|
|
16
|
+
_mint(msg.sender, amount);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function decimals() public view virtual override returns (uint8) {
|
|
20
|
+
return _decimals;
|
|
21
|
+
}
|
|
22
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@venusprotocol/protocol-reserve",
|
|
3
|
+
"description": "",
|
|
4
|
+
"version": "1.0.0-dev.1",
|
|
5
|
+
"author": "",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=18.0.0"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"artifacts",
|
|
11
|
+
"deploy",
|
|
12
|
+
"deployments",
|
|
13
|
+
"contracts"
|
|
14
|
+
],
|
|
15
|
+
"keywords": [
|
|
16
|
+
"blockchain",
|
|
17
|
+
"ethers",
|
|
18
|
+
"ethereum",
|
|
19
|
+
"hardhat",
|
|
20
|
+
"smart-contracts",
|
|
21
|
+
"solidity",
|
|
22
|
+
"template",
|
|
23
|
+
"typescript",
|
|
24
|
+
"typechain"
|
|
25
|
+
],
|
|
26
|
+
"exports": {
|
|
27
|
+
"deploy": "./dist/deploy",
|
|
28
|
+
"artifacts": "./artifacts",
|
|
29
|
+
"contracts": "./contracts",
|
|
30
|
+
"deployments": "./deployments"
|
|
31
|
+
},
|
|
32
|
+
"packageManager": "yarn@3.2.0",
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"compile": "hardhat compile",
|
|
38
|
+
"test": "hardhat test",
|
|
39
|
+
"build": "rm -rf dist && tsc --declaration && hardhat compile",
|
|
40
|
+
"publish:dist": "yarn build && cd dist && yarn publish --access public",
|
|
41
|
+
"lint": "yarn lint:ts && yarn lint:sol && yarn prettier:check",
|
|
42
|
+
"lint:ts": "eslint --ignore-path ./.eslintignore --ext .js,.ts .",
|
|
43
|
+
"lint:sol": "solhint \"contracts/**/*.sol\"",
|
|
44
|
+
"lint:sol:fix": "prettier --write \"contracts/**/*.sol\"",
|
|
45
|
+
"prettier": "prettier --write \"**/*.{js,json,md,ts,yaml,yml,sol}\"",
|
|
46
|
+
"prettier:check": "prettier --check \"**/*.{js,json,md,ts,yaml,yml,sol}\"",
|
|
47
|
+
"docgen": "hardhat docgen"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@commitlint/cli": "^17.4.4",
|
|
51
|
+
"@commitlint/config-conventional": "^17.4.4",
|
|
52
|
+
"@defi-wonderland/smock": "^2.3.4",
|
|
53
|
+
"@ethersproject/abi": "^5.7.0",
|
|
54
|
+
"@ethersproject/abstract-signer": "^5.7.0",
|
|
55
|
+
"@ethersproject/bignumber": "^5.7.0",
|
|
56
|
+
"@ethersproject/bytes": "^5.7.0",
|
|
57
|
+
"@ethersproject/providers": "^5.7.2",
|
|
58
|
+
"@nomicfoundation/hardhat-chai-matchers": "^1.0.4",
|
|
59
|
+
"@nomicfoundation/hardhat-network-helpers": "^1.0.6",
|
|
60
|
+
"@nomicfoundation/hardhat-toolbox": "^2.0.0",
|
|
61
|
+
"@nomiclabs/hardhat-ethers": "^2.2.1",
|
|
62
|
+
"@nomiclabs/hardhat-etherscan": "^3.1.2",
|
|
63
|
+
"@openzeppelin/contracts": "^4.8.2",
|
|
64
|
+
"@openzeppelin/contracts-upgradeable": "^4.8.2",
|
|
65
|
+
"@openzeppelin/hardhat-upgrades": "^1.22.1",
|
|
66
|
+
"@semantic-release/changelog": "^6.0.2",
|
|
67
|
+
"@semantic-release/git": "^10.0.1",
|
|
68
|
+
"@trivago/prettier-plugin-sort-imports": "^4.0.0",
|
|
69
|
+
"@typechain/ethers-v5": "^10.1.1",
|
|
70
|
+
"@typechain/hardhat": "^6.1.4",
|
|
71
|
+
"@types/chai": "^4.3.4",
|
|
72
|
+
"@types/fs-extra": "^9.0.13",
|
|
73
|
+
"@types/mocha": "^10.0.0",
|
|
74
|
+
"@types/node": "^18.16.3",
|
|
75
|
+
"@typescript-eslint/eslint-plugin": "^5.44.0",
|
|
76
|
+
"@typescript-eslint/parser": "^5.44.0",
|
|
77
|
+
"@venusprotocol/oracle": "^1.6.11-dev.7",
|
|
78
|
+
"@venusprotocol/venus-protocol": "^0.7.0",
|
|
79
|
+
"bignumber.js": "^9.1.1",
|
|
80
|
+
"chai": "^4.3.7",
|
|
81
|
+
"commitizen": "^4.2.5",
|
|
82
|
+
"cross-env": "^7.0.3",
|
|
83
|
+
"cz-conventional-changelog": "^3.3.0",
|
|
84
|
+
"dotenv": "^16.0.3",
|
|
85
|
+
"eslint": "^8.28.0",
|
|
86
|
+
"eslint-config-prettier": "^8.5.0",
|
|
87
|
+
"ethers": "^5.7.2",
|
|
88
|
+
"fs-extra": "^10.1.0",
|
|
89
|
+
"hardhat": "^2.16.1",
|
|
90
|
+
"hardhat-dependency-compiler": "^1.1.3",
|
|
91
|
+
"hardhat-deploy": "^0.11.23",
|
|
92
|
+
"hardhat-docgen": "^1.3.0",
|
|
93
|
+
"hardhat-gas-reporter": "^1.0.9",
|
|
94
|
+
"husky": "^8.0.3",
|
|
95
|
+
"lint-staged": "^13.0.4",
|
|
96
|
+
"lodash": "^4.17.21",
|
|
97
|
+
"mocha": "^10.1.0",
|
|
98
|
+
"pinst": "^3.0.0",
|
|
99
|
+
"prettier": "^2.8.4",
|
|
100
|
+
"prettier-plugin-solidity": "^1.1.2",
|
|
101
|
+
"semantic-release": "^19.0.3",
|
|
102
|
+
"shx": "^0.3.4",
|
|
103
|
+
"solhint": "^3.4.0",
|
|
104
|
+
"solhint-plugin-prettier": "^0.0.5",
|
|
105
|
+
"solidity-coverage": "^0.8.4",
|
|
106
|
+
"solidity-docgen": "^0.6.0-beta.34",
|
|
107
|
+
"ts-generator": "^0.1.1",
|
|
108
|
+
"ts-node": "^10.9.1",
|
|
109
|
+
"tsconfig-paths": "^4.1.2",
|
|
110
|
+
"typechain": "^8.1.1",
|
|
111
|
+
"typescript": "^4.9.3"
|
|
112
|
+
},
|
|
113
|
+
"dependencies": {
|
|
114
|
+
"@venusprotocol/isolated-pools": "^0.1.0-develop.3"
|
|
115
|
+
}
|
|
116
|
+
}
|