15
15
pragma solidity 0.6.10 ;
16
16
pragma experimental "ABIEncoderV2 " ;
17
17
18
+ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol " ;
19
+
18
20
import { AddressArrayUtils } from "../../lib/AddressArrayUtils.sol " ;
19
21
import { IClaimAdapter } from "../../interfaces/IClaimAdapter.sol " ;
20
22
import { IController } from "../../interfaces/IController.sol " ;
@@ -52,10 +54,15 @@ contract ClaimModule is ModuleBase {
52
54
event RewardClaimed (
53
55
ISetToken indexed _setToken ,
54
56
address indexed _rewardPool ,
55
- IClaimAdapter _adapter ,
57
+ IClaimAdapter indexed _adapter ,
56
58
uint256 _amount
57
59
);
58
60
61
+ event AnyoneClaimUpdated (
62
+ ISetToken indexed _setToken ,
63
+ bool _anyoneClaim
64
+ );
65
+
59
66
/* ============ Modifiers ============ */
60
67
61
68
/**
@@ -71,11 +78,16 @@ contract ClaimModule is ModuleBase {
71
78
// Indicates if any address can call claim or just the manager of the SetToken
72
79
mapping (ISetToken => bool ) public anyoneClaim;
73
80
74
- // Array of rewardPool addresses to claim rewards for the SetToken
81
+ // Map and array of rewardPool addresses to claim rewards for the SetToken
75
82
mapping (ISetToken => address []) public rewardPoolList;
83
+ // Map from set tokens to rewards pool address to isAdded boolean. Used to check if a reward pool has been added in O(1) time
84
+ mapping (ISetToken => mapping (address => bool )) public rewardPoolStatus;
76
85
77
- // Array of adapters associated to the rewardPool for the SetToken
86
+ // Map and array of adapters associated to the rewardPool for the SetToken
78
87
mapping (ISetToken => mapping (address => address [])) public claimSettings;
88
+ // Map from set tokens to rewards pool address to claim adapters to isAdded boolean. Used to check if an adapter has been added in O(1) time
89
+ mapping (ISetToken => mapping (address => mapping (address => bool ))) public claimSettingsStatus;
90
+
79
91
80
92
/* ============ Constructor ============ */
81
93
@@ -133,10 +145,10 @@ contract ClaimModule is ModuleBase {
133
145
*
134
146
* @param _setToken Address of SetToken
135
147
*/
136
- function updateAnyoneClaim (ISetToken _setToken ) external onlyManagerAndValidSet (_setToken) {
137
- anyoneClaim[_setToken] = ! anyoneClaim[_setToken];
148
+ function updateAnyoneClaim (ISetToken _setToken , bool _anyoneClaim ) external onlyManagerAndValidSet (_setToken) {
149
+ anyoneClaim[_setToken] = _anyoneClaim;
150
+ emit AnyoneClaimUpdated (_setToken, _anyoneClaim);
138
151
}
139
-
140
152
/**
141
153
* SET MANAGER ONLY. Adds a new claim integration for an existent rewardPool. If rewardPool doesn't have existing
142
154
* claims then rewardPool is added to rewardPoolLiost. The claim integration is associated to an adapter that
@@ -252,10 +264,27 @@ contract ClaimModule is ModuleBase {
252
264
function removeModule () external override {
253
265
delete anyoneClaim[ISetToken (msg .sender )];
254
266
267
+ // explicitly delete all elements for gas refund
255
268
address [] memory setTokenPoolList = rewardPoolList[ISetToken (msg .sender )];
256
269
for (uint256 i = 0 ; i < setTokenPoolList.length ; i++ ) {
270
+
271
+ address [] storage adapterList = claimSettings[ISetToken (msg .sender )][setTokenPoolList[i]];
272
+ for (uint256 j = 0 ; j < adapterList.length ; j++ ) {
273
+
274
+ address toRemove = adapterList[j];
275
+ claimSettingsStatus[ISetToken (msg .sender )][setTokenPoolList[i]][toRemove] = false ;
276
+
277
+ delete adapterList[j];
278
+ }
257
279
delete claimSettings[ISetToken (msg .sender )][setTokenPoolList[i]];
258
280
}
281
+
282
+ for (uint256 i = 0 ; i < rewardPoolList[ISetToken (msg .sender )].length ; i++ ) {
283
+ address toRemove = rewardPoolList[ISetToken (msg .sender )][i];
284
+ rewardPoolStatus[ISetToken (msg .sender )][toRemove] = false ;
285
+
286
+ delete rewardPoolList[ISetToken (msg .sender )][i];
287
+ }
259
288
delete rewardPoolList[ISetToken (msg .sender )];
260
289
}
261
290
@@ -277,7 +306,7 @@ contract ClaimModule is ModuleBase {
277
306
* @return Boolean indicating if the rewardPool is in the list for claims.
278
307
*/
279
308
function isRewardPool (ISetToken _setToken , address _rewardPool ) public view returns (bool ) {
280
- return rewardPoolList [_setToken]. contains ( _rewardPool) ;
309
+ return rewardPoolStatus [_setToken][ _rewardPool] ;
281
310
}
282
311
283
312
/**
@@ -309,7 +338,7 @@ contract ClaimModule is ModuleBase {
309
338
returns (bool )
310
339
{
311
340
address adapter = getAndValidateAdapter (_integrationName);
312
- return claimSettings [_setToken][_rewardPool]. contains ( adapter) ;
341
+ return claimSettingsStatus [_setToken][_rewardPool][ adapter] ;
313
342
}
314
343
315
344
/**
@@ -329,9 +358,8 @@ contract ClaimModule is ModuleBase {
329
358
view
330
359
returns (uint256 )
331
360
{
332
- IClaimAdapter adapter = _getAndValidateIntegrationAdapter (claimSettings[_setToken][_rewardPool], _integrationName);
333
- uint256 rewards = adapter.getRewards (address (_setToken), _rewardPool);
334
- return rewards;
361
+ IClaimAdapter adapter = _getAndValidateIntegrationAdapter (_setToken, _rewardPool, _integrationName);
362
+ return adapter.getRewardsAmount (_setToken, _rewardPool);
335
363
}
336
364
337
365
/* ============ Internal Functions ============ */
@@ -346,40 +374,45 @@ contract ClaimModule is ModuleBase {
346
374
*/
347
375
function _claim (ISetToken _setToken , address _rewardPool , string calldata _integrationName ) internal {
348
376
require (isRewardPool (_setToken, _rewardPool), "RewardPool not present " );
349
- IClaimAdapter adapter = _getAndValidateIntegrationAdapter (claimSettings[ _setToken][ _rewardPool] , _integrationName);
377
+ IClaimAdapter adapter = _getAndValidateIntegrationAdapter (_setToken, _rewardPool, _integrationName);
350
378
351
- uint256 rewards = adapter.getRewards (address (_setToken), _rewardPool);
379
+ IERC20 rewardsToken = IERC20 (adapter.getTokenAddress (_rewardPool));
380
+ uint256 initRewardsBalance = rewardsToken.balanceOf (address (_setToken));
352
381
353
382
(
354
383
address callTarget ,
355
384
uint256 callValue ,
356
385
bytes memory callByteData
357
386
) = adapter.getClaimCallData (
358
- address ( _setToken) ,
387
+ _setToken,
359
388
_rewardPool
360
389
);
361
390
362
391
_setToken.invoke (callTarget, callValue, callByteData);
363
392
364
- emit RewardClaimed (_setToken, _rewardPool, adapter, rewards);
393
+ uint256 finalRewardsBalance = rewardsToken.balanceOf (address (_setToken));
394
+
395
+ emit RewardClaimed (_setToken, _rewardPool, adapter, finalRewardsBalance.sub (initRewardsBalance));
365
396
}
366
397
367
398
/**
368
399
* Gets the adapter and validate it is associated to the list of claim integration of a rewardPool.
369
400
*
370
- * @param _rewardPoolClaimSettings List of claim integrations associated to a rewardPool
371
- * @param _integrationName ID of claim module integration (mapping on integration registry)
401
+ * @param _setToken Address of SetToken
402
+ * @param _rewardsPool Sddress of rewards pool
403
+ * @param _integrationName ID of claim module integration (mapping on integration registry)
372
404
*/
373
405
function _getAndValidateIntegrationAdapter (
374
- address [] memory _rewardPoolClaimSettings ,
406
+ ISetToken _setToken ,
407
+ address _rewardsPool ,
375
408
string calldata _integrationName
376
409
)
377
410
internal
378
411
view
379
412
returns (IClaimAdapter)
380
413
{
381
414
address adapter = getAndValidateAdapter (_integrationName);
382
- require (_rewardPoolClaimSettings. contains ( adapter) , "Adapter integration not present " );
415
+ require (claimSettingsStatus[_setToken][_rewardsPool][ adapter] , "Adapter integration not present " );
383
416
return IClaimAdapter (adapter);
384
417
}
385
418
@@ -395,11 +428,13 @@ contract ClaimModule is ModuleBase {
395
428
address adapter = getAndValidateAdapter (_integrationName);
396
429
address [] storage _rewardPoolClaimSettings = claimSettings[_setToken][_rewardPool];
397
430
398
- require (! _rewardPoolClaimSettings. contains ( adapter) , "Integration names must be unique " );
431
+ require (! claimSettingsStatus[_setToken][_rewardPool][ adapter] , "Integration names must be unique " );
399
432
_rewardPoolClaimSettings.push (adapter);
433
+ claimSettingsStatus[_setToken][_rewardPool][adapter] = true ;
400
434
401
- if (_rewardPoolClaimSettings. length == 1 ) {
435
+ if (! rewardPoolStatus[_setToken][_rewardPool] ) {
402
436
rewardPoolList[_setToken].push (_rewardPool);
437
+ rewardPoolStatus[_setToken][_rewardPool] = true ;
403
438
}
404
439
}
405
440
@@ -428,7 +463,7 @@ contract ClaimModule is ModuleBase {
428
463
}
429
464
430
465
/**
431
- * Validates and store the adapter address used to claim rewards for the passed rewardPool. If no adapters
466
+ * Validates and stores the adapter address used to claim rewards for the passed rewardPool. If no adapters
432
467
* left after removal then remove rewardPool from rewardPoolList and delete entry in claimSettings.
433
468
*
434
469
* @param _setToken Address of SetToken
@@ -437,14 +472,14 @@ contract ClaimModule is ModuleBase {
437
472
*/
438
473
function _removeClaim (ISetToken _setToken , address _rewardPool , string calldata _integrationName ) internal {
439
474
address adapter = getAndValidateAdapter (_integrationName);
440
- address [] memory _rewardPoolClaimSettings = claimSettings[_setToken][_rewardPool];
441
475
442
- require (_rewardPoolClaimSettings.contains (adapter), "Integration must be added " );
443
- claimSettings[_setToken][_rewardPool] = _rewardPoolClaimSettings.remove (adapter);
476
+ require (claimSettingsStatus[_setToken][_rewardPool][adapter], "Integration must be added " );
477
+ claimSettings[_setToken][_rewardPool].removeStorage (adapter);
478
+ claimSettingsStatus[_setToken][_rewardPool][adapter] = false ;
444
479
445
480
if (claimSettings[_setToken][_rewardPool].length == 0 ) {
446
- rewardPoolList[_setToken] = rewardPoolList[_setToken]. remove (_rewardPool);
447
- delete claimSettings [_setToken][_rewardPool];
481
+ rewardPoolList[_setToken]. removeStorage (_rewardPool);
482
+ rewardPoolStatus [_setToken][_rewardPool] = false ;
448
483
}
449
484
}
450
485
0 commit comments