From 5a4c97b100cc99ad27b0bf527211e35a91c8bce5 Mon Sep 17 00:00:00 2001 From: arcantheon Date: Thu, 20 Jun 2024 00:51:58 +0530 Subject: [PATCH 1/2] fix(Rewarder): added a function to call farm.recoverRewardFunds --- contracts/interfaces/IFarm.sol | 2 ++ contracts/rewarder/Rewarder.sol | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/contracts/interfaces/IFarm.sol b/contracts/interfaces/IFarm.sol index fc26f6e6..0fe90695 100644 --- a/contracts/interfaces/IFarm.sol +++ b/contracts/interfaces/IFarm.sol @@ -8,6 +8,8 @@ interface IFarm { function setRewardRate(address _rwdToken, uint256[] memory _newRwdRates) external; + function recoverRewardFunds(address _rwdToken, uint256 _amount) external; + function rewardData(address _token) external view returns (RewardData memory); function cooldownPeriod() external view returns (uint256); diff --git a/contracts/rewarder/Rewarder.sol b/contracts/rewarder/Rewarder.sol index 8aeda817..850f6d17 100644 --- a/contracts/rewarder/Rewarder.sol +++ b/contracts/rewarder/Rewarder.sol @@ -121,9 +121,18 @@ contract Rewarder is Ownable, Initializable, ReentrancyGuard { /// @param _farm Farm's address in which the token manager is to be updated. /// @param _newManager Address of the new token manager. function updateTokenManagerOfFarm(address _farm, address _newManager) external onlyOwner { + _validateNonZeroAddr(_farm); IFarm(_farm).updateRewardData(REWARD_TOKEN, _newManager); } + /// @notice Function to recover reward funds from the farm. + /// @param _farm Farm's address from which reward funds is to be recovered. + /// @param _amount Amount which is to be recovered. + function recoverRewardFundsOfFarm(address _farm, uint256 _amount) external onlyOwner { + _validateNonZeroAddr(_farm); + IFarm(_farm).recoverRewardFunds(REWARD_TOKEN, _amount); + } + /// @notice Function to update APR. /// @param _farm Address of the farm. /// @param _apr APR in 1e8 precision. From e0e7e1f46a1f17e7aadfffccaca44661292b46ba Mon Sep 17 00:00:00 2001 From: arcantheon Date: Thu, 20 Jun 2024 00:52:37 +0530 Subject: [PATCH 2/2] Added test cases for recoverRewardFundsOfFarm of Rewarder contract --- test/rewarder/Rewarder.t.sol | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/test/rewarder/Rewarder.t.sol b/test/rewarder/Rewarder.t.sol index 4f2cfdb1..eeb6f78f 100644 --- a/test/rewarder/Rewarder.t.sol +++ b/test/rewarder/Rewarder.t.sol @@ -8,7 +8,7 @@ import {CamelotV2Farm} from "../../contracts/e721-farms/camelotV2/CamelotV2Farm. import {RewarderFactory} from "../../contracts/rewarder/RewarderFactory.sol"; import {Rewarder, IERC20, ERC20} from "../../contracts/rewarder/Rewarder.sol"; import {IOracle} from "../../contracts/interfaces/IOracle.sol"; -import {VmSafe} from "forge-std/Vm.sol"; +import {Farm} from "./../../contracts/Farm.sol"; contract RewarderTest is CamelotV2FarmTest { RewarderFactory public rewarderFactory; @@ -57,6 +57,29 @@ contract TestUpdateTokenManagerOfFarm is RewarderTest { } } +contract TestRecoverRewardFundsOfFarm is RewarderTest { + uint256 public amount; + + function test_RevertWhen_CallerIsNotTheOwner() public useKnownActor(actors[5]) { + vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, actors[5])); + rewarder.recoverRewardFundsOfFarm(lockupFarm, amount); + } + + function test_recoverRewardFundsOfFarm() public { + vm.prank(owner); + CamelotV2Farm(lockupFarm).updateRewardData(USDCe, address(rewarder)); + uint256 balanceBefore = IERC20(USDCe).balanceOf(address(rewarder)); + amount = 100 * 10 ** ERC20(USDCe).decimals(); + deal(USDCe, lockupFarm, amount); + vm.expectEmit(true, true, true, true, lockupFarm); + emit Farm.FundsRecovered(address(rewarder), USDCe, amount); + vm.prank(rewardManager); + rewarder.recoverRewardFundsOfFarm(lockupFarm, amount); + uint256 balanceAfter = IERC20(USDCe).balanceOf(address(rewarder)); + assertEq(balanceAfter - balanceBefore, amount); + } +} + contract TestUpdateAPR is RewarderTest { uint256 private APR;