From 85d32827267acca05235519217d15afbde1b64c6 Mon Sep 17 00:00:00 2001 From: Entreprenerd Date: Mon, 18 Jul 2022 23:30:37 +0200 Subject: [PATCH 1/5] feat: initial set of events --- contracts/RewardsManager.sol | 47 ++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/contracts/RewardsManager.sol b/contracts/RewardsManager.sol index f34cc1c..0cef476 100644 --- a/contracts/RewardsManager.sol +++ b/contracts/RewardsManager.sol @@ -78,6 +78,14 @@ contract RewardsManager is ReentrancyGuard { mapping(uint256 => mapping(address => mapping(address => uint256))) public rewards; // rewards[epochId][vaultAddress][tokenAddress] = AMOUNT + // EpochId for Transfer is implied by block.timestamp (and can be fetched there) + event Transfer(address indexed vault, address indexed from, address indexed to, uint256 amount); + + event AddReward(uint256 indexed epochId, address indexed vault, address indexed token, uint256 amount, address sender); + + // NOTE: Massive pain in the ass to do properly + event ClaimReward(uint256 indexed epochId, address indexed vault, address indexed token, uint256 amount, address claimer); + constructor() { DEPLOY_TIME = block.timestamp; } @@ -264,6 +272,8 @@ contract RewardsManager is ReentrancyGuard { pointsWithdrawn[epochId][vault][user][token] += pointsLeft; } + emit ClaimReward(epochId, vault, token, tokensForUser, user); + // Transfer the token IERC20(token).safeTransfer(user, tokensForUser); } @@ -300,6 +310,8 @@ contract RewardsManager is ReentrancyGuard { // We checked it was zero, no need to add pointsWithdrawn[epochId][vault][user][token] = userInfo.userEpochTotalPoints; + emit ClaimReward(epochId, vault, token, tokensForUser, user); + IERC20(token).safeTransfer(user, tokensForUser); } @@ -334,6 +346,8 @@ contract RewardsManager is ReentrancyGuard { // We checked it was zero, no need to add pointsWithdrawn[epochId][vault][user][token] = userInfo.userEpochTotalPoints; + emit ClaimReward(epochId, vault, token, tokensForUser, user); + IERC20(token).safeTransfer(user, tokensForUser); } @@ -390,7 +404,10 @@ contract RewardsManager is ReentrancyGuard { uint256 totalAdditionalReward = rewards[epochId][vault][tokens[i]]; // Which means they claimed all points for that token pointsWithdrawn[epochId][vault][user][tokens[i]] = userPoints; // Can assign because we checked it's 0 above - amounts[i] += totalAdditionalReward * userPoints / (vaultTotalPoints - thisContractVaultPoints); + uint256 amount = totalAdditionalReward * userPoints / (vaultTotalPoints - thisContractVaultPoints); + amounts[i] += amount; + + emit ClaimReward(epochId, vault, tokens[i], amount, user); unchecked { ++i; } } @@ -466,7 +483,11 @@ contract RewardsManager is ReentrancyGuard { uint256 totalAdditionalReward = rewards[epochId][vault][token]; // uint256 tokensForUser = totalAdditionalReward * userPoints / (vaultTotalPoints - thisContractVaultPoints); - amounts[i] += totalAdditionalReward * userPoints / (vaultTotalPoints - thisContractVaultPoints); + uint256 amount = totalAdditionalReward * userPoints / (vaultTotalPoints - thisContractVaultPoints); + amounts[i] += amount; + + emit ClaimReward(epochId, vault, tokens[i], amount, user); + unchecked { ++i; } } @@ -533,6 +554,8 @@ contract RewardsManager is ReentrancyGuard { // Give each epoch an equal amount of reward for(uint256 epochId = startEpoch; epochId <= endEpoch; ) { + emit AddReward(epochId, vault, token, perEpoch, msg.sender); + unchecked { rewards[epochId][vault][token] += perEpoch; } @@ -574,8 +597,13 @@ contract RewardsManager is ReentrancyGuard { // Give each epoch an equal amount of reward for(uint256 epochId = startEpoch; epochId <= endEpoch; ) { + + uint256 currentAmount = amounts[epochId - startEpoch]; + + emit AddReward(epochId, vault, token, currentAmount, msg.sender); + unchecked { - rewards[epochId][vault][token] += amounts[epochId - startEpoch]; + rewards[epochId][vault][token] += currentAmount; } unchecked { @@ -625,6 +653,8 @@ contract RewardsManager is ReentrancyGuard { unchecked { rewards[epochId][vault][token] += diff; } + + emit AddReward(epochId, vault, token, diff, msg.sender); } /// **== Notify System ==** /// @@ -645,6 +675,8 @@ contract RewardsManager is ReentrancyGuard { } else { _handleTransfer(msg.sender, from, to, amount); } + + emit Transfer(msg.sender, from, to, amount); } /// @dev handles a deposit for vault, to address of amount @@ -1086,11 +1118,14 @@ contract RewardsManager is ReentrancyGuard { // To be able to use the same ratio for all tokens, we need the pointsWithdrawn to all be 0 require(pointsWithdrawn[epochId][params.vault][user][token] == 0); // dev: You already accrued during the epoch, cannot optimize - + // Use ratio to calculate tokens to send uint256 totalAdditionalReward = rewards[epochId][params.vault][token]; - + amounts[i] += totalAdditionalReward * userInfo.userEpochTotalPoints / (vaultInfo.vaultEpochTotalPoints - thisContractInfo.userEpochTotalPoints); + + emit ClaimReward(epochId, params.vault, token, totalAdditionalReward * userInfo.userEpochTotalPoints / (vaultInfo.vaultEpochTotalPoints - thisContractInfo.userEpochTotalPoints), msg.sender); + unchecked { ++i; } } @@ -1191,6 +1226,8 @@ contract RewardsManager is ReentrancyGuard { unchecked { // vaultEpochTotalPoints can't be zero if userEpochTotalPoints is > zero amounts[i] += totalAdditionalReward * userInfo.userEpochTotalPoints / vaultInfo.vaultEpochTotalPoints; + + emit ClaimReward(epochId, params.vault, token, totalAdditionalReward * userInfo.userEpochTotalPoints / vaultInfo.vaultEpochTotalPoints, user); ++i; } } From 02dcbb09b115d760321f04048001f06d95509075 Mon Sep 17 00:00:00 2001 From: Entreprenerd Date: Tue, 19 Jul 2022 02:10:32 +0200 Subject: [PATCH 2/5] chore: comment --- contracts/RewardsManager.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/RewardsManager.sol b/contracts/RewardsManager.sol index 0cef476..83fcbd2 100644 --- a/contracts/RewardsManager.sol +++ b/contracts/RewardsManager.sol @@ -83,7 +83,7 @@ contract RewardsManager is ReentrancyGuard { event AddReward(uint256 indexed epochId, address indexed vault, address indexed token, uint256 amount, address sender); - // NOTE: Massive pain in the ass to do properly + // TODO: 100k+ gas cost on bulk claims, must refactor event ClaimReward(uint256 indexed epochId, address indexed vault, address indexed token, uint256 amount, address claimer); constructor() { From f9f2c887c06f651f122d043d2d8470f538f5dc35 Mon Sep 17 00:00:00 2001 From: Entreprenerd Date: Tue, 19 Jul 2022 19:37:43 +0200 Subject: [PATCH 3/5] feat: bulkClaim event --- contracts/RewardsManager.sol | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/contracts/RewardsManager.sol b/contracts/RewardsManager.sol index 83fcbd2..3124fe6 100644 --- a/contracts/RewardsManager.sol +++ b/contracts/RewardsManager.sol @@ -81,10 +81,13 @@ contract RewardsManager is ReentrancyGuard { // EpochId for Transfer is implied by block.timestamp (and can be fetched there) event Transfer(address indexed vault, address indexed from, address indexed to, uint256 amount); - event AddReward(uint256 indexed epochId, address indexed vault, address indexed token, uint256 amount, address sender); + event AddReward(uint256 epochId, address indexed vault, address indexed token, uint256 amount, address indexed sender); - // TODO: 100k+ gas cost on bulk claims, must refactor - event ClaimReward(uint256 indexed epochId, address indexed vault, address indexed token, uint256 amount, address claimer); + // Claiming of rewards may be done in bulk, information will be incomplete, as such we `epochId` is not indexed + event ClaimReward(uint256 epochId, address indexed vault, address indexed token, uint256 amount, address indexed claimer); + + // Fired off when using bulk claim functions to save gas + event BulkClaimReward(uint256 startEpoch, uint256 endEpoch, address indexed vault, address indexed token, uint256 totalAmount, address indexed claimer); constructor() { DEPLOY_TIME = block.timestamp; @@ -404,10 +407,8 @@ contract RewardsManager is ReentrancyGuard { uint256 totalAdditionalReward = rewards[epochId][vault][tokens[i]]; // Which means they claimed all points for that token pointsWithdrawn[epochId][vault][user][tokens[i]] = userPoints; // Can assign because we checked it's 0 above - uint256 amount = totalAdditionalReward * userPoints / (vaultTotalPoints - thisContractVaultPoints); - amounts[i] += amount; - emit ClaimReward(epochId, vault, tokens[i], amount, user); + amounts[i] += totalAdditionalReward * userPoints / (vaultTotalPoints - thisContractVaultPoints); unchecked { ++i; } } @@ -417,6 +418,9 @@ contract RewardsManager is ReentrancyGuard { // Go ahead and transfer for(uint256 i; i < tokensLength; ){ + + emit BulkClaimReward(epochStart, epochEnd, vault, tokens[i], amounts[i], user); + IERC20(tokens[i]).safeTransfer(user, amounts[i]); unchecked { ++i; } @@ -519,6 +523,7 @@ contract RewardsManager is ReentrancyGuard { // Go ahead and transfer for(uint256 i; i < tokensLength; ){ + emit BulkClaimReward(epochStart, epochEnd, vault, tokens[i], amounts[i], user); IERC20(tokens[i]).safeTransfer(user, amounts[i]); unchecked { ++i; } } @@ -1124,8 +1129,6 @@ contract RewardsManager is ReentrancyGuard { amounts[i] += totalAdditionalReward * userInfo.userEpochTotalPoints / (vaultInfo.vaultEpochTotalPoints - thisContractInfo.userEpochTotalPoints); - emit ClaimReward(epochId, params.vault, token, totalAdditionalReward * userInfo.userEpochTotalPoints / (vaultInfo.vaultEpochTotalPoints - thisContractInfo.userEpochTotalPoints), msg.sender); - unchecked { ++i; } } @@ -1160,6 +1163,7 @@ contract RewardsManager is ReentrancyGuard { // Go ahead and transfer { for(uint256 i; i < tokensLength; ){ + emit BulkClaimReward(params.epochStart, params.epochEnd, params.vault, params.tokens[i], amounts[i], user); IERC20(params.tokens[i]).safeTransfer(user, amounts[i]); unchecked { ++i; } } @@ -1226,8 +1230,6 @@ contract RewardsManager is ReentrancyGuard { unchecked { // vaultEpochTotalPoints can't be zero if userEpochTotalPoints is > zero amounts[i] += totalAdditionalReward * userInfo.userEpochTotalPoints / vaultInfo.vaultEpochTotalPoints; - - emit ClaimReward(epochId, params.vault, token, totalAdditionalReward * userInfo.userEpochTotalPoints / vaultInfo.vaultEpochTotalPoints, user); ++i; } } @@ -1264,6 +1266,7 @@ contract RewardsManager is ReentrancyGuard { // Go ahead and transfer { for(uint256 i; i < tokensLength; ){ + emit BulkClaimReward(params.epochStart, params.epochEnd, params.vault, params.tokens[i], amounts[i], user); IERC20(params.tokens[i]).safeTransfer(user, amounts[i]); unchecked { ++i; } } From ad313d6625e83bff7eca6c01eff51518045c8d2a Mon Sep 17 00:00:00 2001 From: Entreprenerd Date: Tue, 19 Jul 2022 23:18:50 +0200 Subject: [PATCH 4/5] feat: bulk events idea --- contracts/RewardsManager.sol | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/contracts/RewardsManager.sol b/contracts/RewardsManager.sol index 3124fe6..a668d9a 100644 --- a/contracts/RewardsManager.sol +++ b/contracts/RewardsManager.sol @@ -87,7 +87,8 @@ contract RewardsManager is ReentrancyGuard { event ClaimReward(uint256 epochId, address indexed vault, address indexed token, uint256 amount, address indexed claimer); // Fired off when using bulk claim functions to save gas - event BulkClaimReward(uint256 startEpoch, uint256 endEpoch, address indexed vault, address indexed token, uint256 totalAmount, address indexed claimer); + // NOTE: We don't list tokens nor amounts to save gas, see events for that + event BulkClaimReward(uint256 startEpoch, uint256 endEpoch, address indexed vault, address indexed claimer); constructor() { DEPLOY_TIME = block.timestamp; @@ -416,11 +417,11 @@ contract RewardsManager is ReentrancyGuard { unchecked { ++epochId; } } + emit BulkClaimReward(epochStart, epochEnd, vault, user); + // Go ahead and transfer for(uint256 i; i < tokensLength; ){ - emit BulkClaimReward(epochStart, epochEnd, vault, tokens[i], amounts[i], user); - IERC20(tokens[i]).safeTransfer(user, amounts[i]); unchecked { ++i; } @@ -521,9 +522,10 @@ contract RewardsManager is ReentrancyGuard { // For last epoch, we don't delete the shares, but we delete the points delete points[epochEnd][vault][user]; + emit BulkClaimReward(epochStart, epochEnd, vault, user); + // Go ahead and transfer for(uint256 i; i < tokensLength; ){ - emit BulkClaimReward(epochStart, epochEnd, vault, tokens[i], amounts[i], user); IERC20(tokens[i]).safeTransfer(user, amounts[i]); unchecked { ++i; } } @@ -1162,8 +1164,10 @@ contract RewardsManager is ReentrancyGuard { // Go ahead and transfer { + + emit BulkClaimReward(params.epochStart, params.epochEnd, params.vault, user); + for(uint256 i; i < tokensLength; ){ - emit BulkClaimReward(params.epochStart, params.epochEnd, params.vault, params.tokens[i], amounts[i], user); IERC20(params.tokens[i]).safeTransfer(user, amounts[i]); unchecked { ++i; } } @@ -1265,8 +1269,10 @@ contract RewardsManager is ReentrancyGuard { // Go ahead and transfer { + + emit BulkClaimReward(params.epochStart, params.epochEnd, params.vault, user); + for(uint256 i; i < tokensLength; ){ - emit BulkClaimReward(params.epochStart, params.epochEnd, params.vault, params.tokens[i], amounts[i], user); IERC20(params.tokens[i]).safeTransfer(user, amounts[i]); unchecked { ++i; } } From 64f23b0705152a8e10f813e6912f5315a8ae134f Mon Sep 17 00:00:00 2001 From: Entreprenerd Date: Tue, 19 Jul 2022 23:57:18 +0200 Subject: [PATCH 5/5] feat: emit an event per token on bulkClaims --- contracts/RewardsManager.sol | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/contracts/RewardsManager.sol b/contracts/RewardsManager.sol index a668d9a..28b4edc 100644 --- a/contracts/RewardsManager.sol +++ b/contracts/RewardsManager.sol @@ -87,8 +87,7 @@ contract RewardsManager is ReentrancyGuard { event ClaimReward(uint256 epochId, address indexed vault, address indexed token, uint256 amount, address indexed claimer); // Fired off when using bulk claim functions to save gas - // NOTE: We don't list tokens nor amounts to save gas, see events for that - event BulkClaimReward(uint256 startEpoch, uint256 endEpoch, address indexed vault, address indexed claimer); + event BulkClaimReward(uint256 startEpoch, uint256 endEpoch, address indexed vault, address indexed token, uint256 totalAmount, address indexed claimer); constructor() { DEPLOY_TIME = block.timestamp; @@ -417,10 +416,11 @@ contract RewardsManager is ReentrancyGuard { unchecked { ++epochId; } } - emit BulkClaimReward(epochStart, epochEnd, vault, user); // Go ahead and transfer for(uint256 i; i < tokensLength; ){ + emit BulkClaimReward(epochStart, epochEnd, vault, tokens[i], amounts[i], user); + IERC20(tokens[i]).safeTransfer(user, amounts[i]); @@ -522,11 +522,12 @@ contract RewardsManager is ReentrancyGuard { // For last epoch, we don't delete the shares, but we delete the points delete points[epochEnd][vault][user]; - emit BulkClaimReward(epochStart, epochEnd, vault, user); - // Go ahead and transfer for(uint256 i; i < tokensLength; ){ + emit BulkClaimReward(epochStart, epochEnd, vault, tokens[i], amounts[i], user); + IERC20(tokens[i]).safeTransfer(user, amounts[i]); + unchecked { ++i; } } } @@ -1165,10 +1166,11 @@ contract RewardsManager is ReentrancyGuard { // Go ahead and transfer { - emit BulkClaimReward(params.epochStart, params.epochEnd, params.vault, user); - for(uint256 i; i < tokensLength; ){ + emit BulkClaimReward(params.epochStart, params.epochEnd, params.vault, params.tokens[i], amounts[i], user); + IERC20(params.tokens[i]).safeTransfer(user, amounts[i]); + unchecked { ++i; } } } @@ -1270,10 +1272,11 @@ contract RewardsManager is ReentrancyGuard { // Go ahead and transfer { - emit BulkClaimReward(params.epochStart, params.epochEnd, params.vault, user); - for(uint256 i; i < tokensLength; ){ + emit BulkClaimReward(params.epochStart, params.epochEnd, params.vault, params.tokens[i], amounts[i], user); + IERC20(params.tokens[i]).safeTransfer(user, amounts[i]); + unchecked { ++i; } } }