2
2
pragma solidity 0.8.6 ;
3
3
4
4
/*
5
- * ApeSwapFinance
5
+ ______ ______
6
+ / \ / \
7
+ | ▓▓▓▓▓▓\ ______ ______ | ▓▓▓▓▓▓\__ __ __ ______ ______
8
+ | ▓▓__| ▓▓/ \ / \| ▓▓___\▓▓ \ | \ | \| \ / \
9
+ | ▓▓ ▓▓ ▓▓▓▓▓▓\ ▓▓▓▓▓▓\\▓▓ \| ▓▓ | ▓▓ | ▓▓ \▓▓▓▓▓▓\ ▓▓▓▓▓▓\
10
+ | ▓▓▓▓▓▓▓▓ ▓▓ | ▓▓ ▓▓ ▓▓_\▓▓▓▓▓▓\ ▓▓ | ▓▓ | ▓▓/ ▓▓ ▓▓ | ▓▓
11
+ | ▓▓ | ▓▓ ▓▓__/ ▓▓ ▓▓▓▓▓▓▓▓ \__| ▓▓ ▓▓_/ ▓▓_/ ▓▓ ▓▓▓▓▓▓▓ ▓▓__/ ▓▓
12
+ | ▓▓ | ▓▓ ▓▓ ▓▓\▓▓ \\▓▓ ▓▓\▓▓ ▓▓ ▓▓\▓▓ ▓▓ ▓▓ ▓▓
13
+ \▓▓ \▓▓ ▓▓▓▓▓▓▓ \▓▓▓▓▓▓▓ \▓▓▓▓▓▓ \▓▓▓▓▓\▓▓▓▓ \▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓
14
+ | ▓▓ | ▓▓
15
+ | ▓▓ | ▓▓
16
+ \▓▓ \▓▓
17
+
6
18
* App: https://apeswap.finance
7
19
* Medium: https://ape-swap.medium.com
8
20
* Twitter: https://twitter.com/ape_swap
21
+ * Discord: https://discord.com/invite/apeswap
9
22
* Telegram: https://t.me/ape_swap
10
23
* Announcements: https://t.me/ape_swap_news
11
24
* GitHub: https://github.com/ApeSwapFinance
12
25
*/
13
26
14
- import "@openzeppelin/contracts/proxy/utils/Initializable.sol " ;
15
27
import '@openzeppelin/contracts/token/ERC20/IERC20.sol ' ;
16
28
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol ' ;
17
- import '@openzeppelin/contracts/security/ReentrancyGuard .sol ' ;
29
+ import '@openzeppelin/contracts-upgradeable /security/ReentrancyGuardUpgradeable .sol ' ;
18
30
19
- contract IAO is ReentrancyGuard , Initializable {
31
+ /// @title Harvest Period based Initial Ape Offering
32
+ /// @notice safeTransferStakeInternal uses a fixed gas limit for native transfers which should be evaluated when deploying to new networks.
33
+ contract IAO is ReentrancyGuardUpgradeable {
20
34
using SafeERC20 for IERC20 ;
21
35
22
36
uint256 constant public HARVEST_PERIODS = 4 ;
@@ -61,6 +75,9 @@ contract IAO is ReentrancyGuard, Initializable {
61
75
uint256 offeringAmount ,
62
76
uint256 excessAmount
63
77
);
78
+ event UpdateOfferingAmount (uint256 previousOfferingAmount , uint256 newOfferingAmount );
79
+ event UpdateRaisingAmount (uint256 previousRaisingAmount , uint256 newRaisingAmount );
80
+ event AdminFinalWithdraw (uint256 stakeTokenAmount , uint256 offerAmount );
64
81
event EmergencySweepWithdraw (address indexed receiver , address indexed token , uint256 balance );
65
82
66
83
@@ -91,6 +108,7 @@ contract IAO is ReentrancyGuard, Initializable {
91
108
raisingAmount = _raisingAmount;
92
109
totalAmount = 0 ;
93
110
adminAddress = _adminAddress;
111
+ __ReentrancyGuard_init ();
94
112
}
95
113
96
114
modifier onlyAdmin () {
@@ -106,26 +124,28 @@ contract IAO is ReentrancyGuard, Initializable {
106
124
_;
107
125
}
108
126
109
- function setOfferingAmount (uint256 _offerAmount ) public onlyAdmin {
127
+ function setOfferingAmount (uint256 _offerAmount ) external onlyAdmin {
110
128
require (block .number < startBlock, "cannot update during active iao " );
129
+ emit UpdateOfferingAmount (offeringAmount, _offerAmount);
111
130
offeringAmount = _offerAmount;
112
131
}
113
132
114
- function setRaisingAmount (uint256 _raisingAmount ) public onlyAdmin {
133
+ function setRaisingAmount (uint256 _raisingAmount ) external onlyAdmin {
115
134
require (block .number < startBlock, "cannot update during active iao " );
135
+ emit UpdateRaisingAmount (raisingAmount, _raisingAmount);
116
136
raisingAmount = _raisingAmount;
117
137
}
118
138
119
139
/// @notice Deposits native EVM tokens into the IAO contract as per the value sent
120
140
/// in the transaction.
121
- function depositNative () external payable onlyActiveIAO {
141
+ function depositNative () external payable onlyActiveIAO nonReentrant {
122
142
require (isNativeTokenStaking, 'stake token is not native EVM token ' );
123
143
require (msg .value > 0 , 'value not > 0 ' );
124
144
depositInternal (msg .value );
125
145
}
126
146
127
147
/// @dev Deposit ERC20 tokens with support for reflect tokens
128
- function deposit (uint256 _amount ) external onlyActiveIAO {
148
+ function deposit (uint256 _amount ) external onlyActiveIAO nonReentrant {
129
149
require (! isNativeTokenStaking, "stake token is native token, deposit through 'depositNative' " );
130
150
require (_amount > 0 , "_amount not > 0 " );
131
151
uint256 pre = getTotalStakeTokenBalance ();
@@ -135,6 +155,7 @@ contract IAO is ReentrancyGuard, Initializable {
135
155
_amount
136
156
);
137
157
uint256 finalDepositAmount = getTotalStakeTokenBalance () - pre;
158
+ require (finalDepositAmount > 0 , 'final deposit amount is zero ' );
138
159
depositInternal (finalDepositAmount);
139
160
}
140
161
@@ -163,14 +184,15 @@ contract IAO is ReentrancyGuard, Initializable {
163
184
safeTransferStakeInternal (msg .sender , refundingTokenAmount);
164
185
}
165
186
166
- uint256 offeringTokenAmountPerPeriod = getOfferingAmountPerPeriod (msg .sender );
167
- offeringToken.safeTransfer (msg .sender , offeringTokenAmountPerPeriod);
168
-
169
187
userInfo[msg .sender ].claimed[harvestPeriod] = true ;
170
188
// Subtract user debt after refund on initial harvest
171
189
if (harvestPeriod == 0 ) {
172
190
totalDebt -= userInfo[msg .sender ].amount;
173
191
}
192
+
193
+ uint256 offeringTokenAmountPerPeriod = getOfferingAmountPerPeriod (msg .sender );
194
+ offeringToken.safeTransfer (msg .sender , offeringTokenAmountPerPeriod);
195
+
174
196
emit Harvest (msg .sender , offeringTokenAmountPerPeriod, refundingTokenAmount);
175
197
}
176
198
@@ -181,16 +203,17 @@ contract IAO is ReentrancyGuard, Initializable {
181
203
/// @notice Calculate a users allocation based on the total amount deposited. This is done
182
204
/// by first scaling the deposited amount and dividing by the total amount.
183
205
/// @param _user Address of the user allocation to look up
184
- function getUserAllocation (address _user ) public view returns (uint256 ) {
206
+ /// @notice This function has been deprecated, but leaving in the contract for backwards compatibility.
207
+ function getUserAllocation (address _user ) external view returns (uint256 ) {
185
208
// avoid division by zero
186
209
if (totalAmount == 0 ) {
187
210
return 0 ;
188
211
}
189
212
190
213
// allocation:
191
- // 1e6 = 100%
192
- // 1e4 = 1%
193
- // 1 = 0.0001 %
214
+ // 1e12 = 100%
215
+ // 1e10 = 1%
216
+ // 1e8 = 0.01 %
194
217
return (userInfo[_user].amount * 1e12 / totalAmount);
195
218
}
196
219
@@ -205,11 +228,10 @@ contract IAO is ReentrancyGuard, Initializable {
205
228
206
229
/// @notice Calculate a user's offering amount to be received by multiplying the offering amount by
207
230
/// the user allocation percentage.
208
- /// @dev User allocation is scaled up by the ALLOCATION_PRECISION which is scaled down before returning a value.
209
231
/// @param _user Address of the user allocation to look up
210
232
function getOfferingAmount (address _user ) public view returns (uint256 ) {
211
233
if (totalAmount > raisingAmount) {
212
- return (offeringAmount * getUserAllocation (_user)) / 1e12 ;
234
+ return (userInfo[_user].amount * offeringAmount) / totalAmount ;
213
235
} else {
214
236
// Return an offering amount equal to a proportion of the raising amount
215
237
return (userInfo[_user].amount * offeringAmount) / raisingAmount;
@@ -223,19 +245,20 @@ contract IAO is ReentrancyGuard, Initializable {
223
245
224
246
/// @notice Calculate a user's refunding amount to be received by multiplying the raising amount by
225
247
/// the user allocation percentage.
226
- /// @dev User allocation is scaled up by the ALLOCATION_PRECISION which is scaled down before returning a value.
227
248
/// @param _user Address of the user allocation to look up
228
249
function getRefundingAmount (address _user ) public view returns (uint256 ) {
229
250
// Users are able to obtain their refund on the first harvest only
230
251
if (totalAmount <= raisingAmount || userInfo[_user].refunded == true ) {
231
252
return 0 ;
232
253
}
233
- uint256 payAmount = (raisingAmount * getUserAllocation (_user)) / 1e12 ;
234
- return userInfo[_user].amount - payAmount;
254
+ uint256 userAmount = userInfo[_user].amount;
255
+ uint256 payAmount = (userAmount * raisingAmount) / totalAmount;
256
+ return userAmount - payAmount;
235
257
}
236
258
237
259
/// @notice Get the amount of tokens a user is eligible to receive based on current state.
238
260
/// @param _user address of user to obtain token status
261
+ /// @notice offeringTokensVested should be named offeringTokensVesting. Leaving for backward compatibility
239
262
function userTokenStatus (address _user )
240
263
public
241
264
view
@@ -280,6 +303,7 @@ contract IAO is ReentrancyGuard, Initializable {
280
303
);
281
304
safeTransferStakeInternal (msg .sender , _stakeTokenAmount);
282
305
offeringToken.safeTransfer (msg .sender , _offerAmount);
306
+ emit AdminFinalWithdraw (_stakeTokenAmount, _offerAmount);
283
307
}
284
308
285
309
/// @notice Internal function to handle stake token transfers. Depending on the stake
@@ -298,7 +322,7 @@ contract IAO is ReentrancyGuard, Initializable {
298
322
require (success, "TransferHelper: NATIVE_TRANSFER_FAILED " );
299
323
} else {
300
324
// Transfer ERC20 to address
301
- IERC20 ( stakeToken) .safeTransfer (_to, _amount);
325
+ stakeToken.safeTransfer (_to, _amount);
302
326
}
303
327
}
304
328
0 commit comments