-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy pathBondPoolLibV1.sol
More file actions
262 lines (219 loc) · 9.57 KB
/
BondPoolLibV1.sol
File metadata and controls
262 lines (219 loc) · 9.57 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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
// Neptune Mutual Protocol (https://neptunemutual.com)
// SPDX-License-Identifier: BUSL-1.1
/* solhint-disable ordering */
pragma solidity ^0.8.0;
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "../interfaces/IProtocol.sol";
import "../interfaces/IPausable.sol";
import "./NTransferUtilV2.sol";
import "./ValidationLibV1.sol";
library BondPoolLibV1 {
using NTransferUtilV2 for IERC20;
using PriceLibV1 for IStore;
using ProtoUtilV1 for IStore;
using StoreKeyUtil for IStore;
using ValidationLibV1 for IStore;
bytes32 public constant NS_BOND_TO_CLAIM = "ns:pool:bond:to:claim";
bytes32 public constant NS_BOND_CONTRIBUTION = "ns:pool:bond:contribution";
bytes32 public constant NS_BOND_LP_TOKEN = "ns:pool:bond:lq:pair:token";
bytes32 public constant NS_LQ_TREASURY = "ns:pool:bond:lq:treasury";
bytes32 public constant NS_BOND_DISCOUNT_RATE = "ns:pool:bond:discount";
bytes32 public constant NS_BOND_MAX_UNIT = "ns:pool:bond:max:unit";
bytes32 public constant NS_BOND_VESTING_TERM = "ns:pool:bond:vesting:term";
bytes32 public constant NS_BOND_UNLOCK_DATE = "ns:pool:bond:unlock:date";
bytes32 public constant NS_BOND_TOTAL_NPM_ALLOCATED = "ns:pool:bond:total:npm:alloc";
bytes32 public constant NS_BOND_TOTAL_NPM_DISTRIBUTED = "ns:pool:bond:total:npm:distrib";
/**
* @dev Calculates the discounted NPM token to be given
* for the NPM/Stablecoin Uniswap v2 LP token units.
*
* @param s Specify store instance
* @param lpTokens Enter the NPM/Stablecoin Uniswap v2 LP token units
*
*/
function calculateTokensForLpInternal(IStore s, uint256 lpTokens) public view returns (uint256) {
uint256 dollarValue = s.convertNpmLpUnitsToStabelcoinInternal(lpTokens);
uint256 npmPrice = s.getNpmPriceInternal(1 ether);
uint256 discount = _getDiscountRate(s);
uint256 discountedNpmPrice = (npmPrice * (ProtoUtilV1.MULTIPLIER - discount)) / ProtoUtilV1.MULTIPLIER;
uint256 npmForContribution = (dollarValue * 1 ether) / discountedNpmPrice;
return npmForContribution;
}
/**
* @dev Gets the bond pool information
*
* @param s Provide a store instance
*
*/
function getBondPoolInfoInternal(IStore s, address you) external view returns (IBondPool.BondPoolInfoType memory info) {
info.lpToken = _getLpTokenAddress(s);
info.marketPrice = s.getNpmPriceInternal(1 ether);
info.discountRate = _getDiscountRate(s);
info.vestingTerm = _getVestingTerm(s);
info.maxBond = _getMaxBondInUnit(s);
info.totalNpmAllocated = _getTotalNpmAllocated(s);
info.totalNpmDistributed = _getTotalNpmDistributed(s);
info.npmAvailable = IERC20(s.getNpmTokenInstanceInternal()).balanceOf(address(this));
info.bondContribution = _getYourBondContribution(s, you); // total lp tokens contributed by you
info.claimable = _getYourBondClaimable(s, you); // your total claimable NPM tokens at the end of the vesting period or "unlock date"
info.unlockDate = _getYourBondUnlockDate(s, you); // your vesting period end or "unlock date"
}
/**
* @dev Gets the NPM/Stablecoin Uniswap v2 LP token address
*/
function _getLpTokenAddress(IStore s) private view returns (address) {
return s.getAddressByKey(BondPoolLibV1.NS_BOND_LP_TOKEN);
}
/**
* @dev Gets your unsettled bond contribution amount.
*/
function _getYourBondContribution(IStore s, address you) private view returns (uint256) {
return s.getUintByKey(keccak256(abi.encodePacked(BondPoolLibV1.NS_BOND_CONTRIBUTION, you)));
}
/**
* @dev Gets your claimable discounted NPM bond amount.
*/
function _getYourBondClaimable(IStore s, address you) private view returns (uint256) {
return s.getUintByKey(keccak256(abi.encodePacked(BondPoolLibV1.NS_BOND_TO_CLAIM, you)));
}
/**
* @dev Returns the date when your discounted NPM token bond is unlocked
* for claim.
*/
function _getYourBondUnlockDate(IStore s, address you) private view returns (uint256) {
return s.getUintByKey(keccak256(abi.encodePacked(BondPoolLibV1.NS_BOND_UNLOCK_DATE, you)));
}
/**
* @dev Returns the NPM token bond discount rate
*/
function _getDiscountRate(IStore s) private view returns (uint256) {
return s.getUintByKey(NS_BOND_DISCOUNT_RATE);
}
/**
* @dev Returns the bond vesting term
*/
function _getVestingTerm(IStore s) private view returns (uint256) {
return s.getUintByKey(NS_BOND_VESTING_TERM);
}
/**
* @dev Returns the maximum NPM token units that can be bonded at a time
*/
function _getMaxBondInUnit(IStore s) private view returns (uint256) {
return s.getUintByKey(NS_BOND_MAX_UNIT);
}
/**
* @dev Returns the total NPM tokens allocated for the bond
*/
function _getTotalNpmAllocated(IStore s) private view returns (uint256) {
return s.getUintByKey(NS_BOND_TOTAL_NPM_ALLOCATED);
}
/**
* @dev Returns the total bonded NPM tokens distributed till date.
*/
function _getTotalNpmDistributed(IStore s) private view returns (uint256) {
return s.getUintByKey(NS_BOND_TOTAL_NPM_DISTRIBUTED);
}
/**
* @dev Create a new NPM/stablecoin LP token bond
*
* @custom:suppress-malicious-erc The token `BondPoolLibV1.NS_BOND_LP_TOKEN` can't be manipulated via user input
*
* @param s Specify store instance
* @param lpTokens Enter the total units of NPM/Stablecoin Uniswap v2 tokens to be bonded
* @param minNpmDesired Enter the minimum NPM tokens you desire for the given LP tokens.
* This transaction will revert if the final NPM bond is less than your specified value.
*
*/
function createBondInternal(
IStore s,
uint256 lpTokens,
uint256 minNpmDesired
) external returns (uint256 npmToVest, uint256 unlockDate) {
s.mustNotBePaused();
npmToVest = calculateTokensForLpInternal(s, lpTokens);
require(npmToVest <= _getMaxBondInUnit(s), "Bond too big");
require(npmToVest >= minNpmDesired, "Min bond `minNpmDesired` failed");
require(_getNpmBalance(s) >= npmToVest + _getBondCommitment(s), "NPM balance insufficient to bond");
// Pull the tokens from the requester's account
IERC20(s.getAddressByKey(BondPoolLibV1.NS_BOND_LP_TOKEN)).ensureTransferFrom(msg.sender, s.getAddressByKey(BondPoolLibV1.NS_LQ_TREASURY), lpTokens);
// Commitment: Total NPM to reserve for bond claims
s.addUintByKey(BondPoolLibV1.NS_BOND_TO_CLAIM, npmToVest);
// Your bond to claim later
bytes32 k = keccak256(abi.encodePacked(BondPoolLibV1.NS_BOND_TO_CLAIM, msg.sender));
s.addUintByKey(k, npmToVest);
// Amount contributed
k = keccak256(abi.encodePacked(BondPoolLibV1.NS_BOND_CONTRIBUTION, msg.sender));
s.addUintByKey(k, lpTokens);
// unlock date
unlockDate = block.timestamp + _getVestingTerm(s); // solhint-disable-line
// Unlock date
k = keccak256(abi.encodePacked(BondPoolLibV1.NS_BOND_UNLOCK_DATE, msg.sender));
s.setUintByKey(k, unlockDate);
}
/**
* @dev Gets the NPM token balance of this contract.
*
* Please also see `_getBondCommitment` to check
* the total NPM tokens already allocated to the bonders
* to be claimed later.
*
* @param s Specify store instance
*/
function _getNpmBalance(IStore s) private view returns (uint256) {
return IERC20(s.getNpmTokenInstanceInternal()).balanceOf(address(this));
}
/**
* @dev Returns the bond commitment amount.
*/
function _getBondCommitment(IStore s) private view returns (uint256) {
return s.getUintByKey(BondPoolLibV1.NS_BOND_TO_CLAIM);
}
/**
* @dev Enables the caller to claim their bond after the lockup period.
*
* @custom:suppress-malicious-erc The token `s.getNpmTokenInstanceInternal()` can't be manipulated via user input
*
*/
function claimBondInternal(IStore s) external returns (uint256 npmToTransfer) {
s.mustNotBePaused();
npmToTransfer = _getYourBondClaimable(s, msg.sender); // npmToTransfer
// Commitment: Reduce NPM reserved for claims
s.subtractUintByKey(BondPoolLibV1.NS_BOND_TO_CLAIM, npmToTransfer);
// Clear the claim amount
s.deleteUintByKey(keccak256(abi.encodePacked(BondPoolLibV1.NS_BOND_TO_CLAIM, msg.sender)));
uint256 unlocksOn = _getYourBondUnlockDate(s, msg.sender);
// Clear the unlock date
s.deleteUintByKey(keccak256(abi.encodePacked(BondPoolLibV1.NS_BOND_UNLOCK_DATE, msg.sender)));
require(block.timestamp >= unlocksOn, "Still vesting"); // solhint-disable-line
require(npmToTransfer > 0, "Nothing to claim");
s.addUintByKey(BondPoolLibV1.NS_BOND_TOTAL_NPM_DISTRIBUTED, npmToTransfer);
IERC20(s.getNpmTokenInstanceInternal()).ensureTransfer(msg.sender, npmToTransfer);
}
/**
* @dev Sets up the bond pool
*
* @custom:suppress-malicious-erc The token `s.getNpmTokenInstanceInternal()` can't be manipulated via user input
*
*/
function setupBondPoolInternal(IStore s, IBondPool.SetupBondPoolArgs calldata args) external {
if (args.lpToken != address(0)) {
s.setAddressByKey(BondPoolLibV1.NS_BOND_LP_TOKEN, args.lpToken);
}
if (args.treasury != address(0)) {
s.setAddressByKey(BondPoolLibV1.NS_LQ_TREASURY, args.treasury);
}
if (args.bondDiscountRate > 0) {
s.setUintByKey(BondPoolLibV1.NS_BOND_DISCOUNT_RATE, args.bondDiscountRate);
}
if (args.maxBondAmount > 0) {
s.setUintByKey(BondPoolLibV1.NS_BOND_MAX_UNIT, args.maxBondAmount);
}
if (args.vestingTerm > 0) {
s.setUintByKey(BondPoolLibV1.NS_BOND_VESTING_TERM, args.vestingTerm);
}
if (args.npmToTopUpNow > 0) {
IERC20(s.getNpmTokenInstanceInternal()).ensureTransferFrom(msg.sender, address(this), args.npmToTopUpNow);
s.addUintByKey(BondPoolLibV1.NS_BOND_TOTAL_NPM_ALLOCATED, args.npmToTopUpNow);
}
}
}