Skip to content

Commit

Permalink
Feat/recover-tokens (#8)
Browse files Browse the repository at this point in the history
* feat: recover tokens from strategy

* feat: check for receiver

* tests: add RecoverTokens tests
  • Loading branch information
0xtekgrinder authored Aug 27, 2024
1 parent 7c79b1a commit 476608f
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 1 deletion.
22 changes: 21 additions & 1 deletion contracts/BaseStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -576,9 +576,29 @@ abstract contract BaseStrategy is ERC4626, AccessControl {
}

/*//////////////////////////////////////////////////////////////
SWAP LOGIC
KEEPER LOGIC
//////////////////////////////////////////////////////////////*/

/**
* @notice Recover tokens from the strategy
* @param tokens array of tokens to recover
* @param receiver address to receive the tokens
* @custom:requires KEEPER_ROLE
*/
function recoverTokens(address[] calldata tokens, address receiver) public onlyRole(KEEPER_ROLE) {
if (receiver == address(0)) {
revert ZeroAddress();
}

uint256 length = tokens.length;
for (uint256 i; i < length; ++i) {
address token = tokens[i];
if (token != asset() && token != STRATEGY_ASSET) {
IERC20(token).safeTransfer(receiver, IERC20(token).balanceOf(address(this)));
}
}
}

/**
* @notice Swap tokens using the router/aggregator + vest the profit
* @param tokens array of tokens to swap
Expand Down
61 changes: 61 additions & 0 deletions test/unit/RecoverTokens.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: Unlicensed
pragma solidity 0.8.26;

import "../ERC4626StrategyTest.t.sol";

contract RecoverTokensTest is ERC4626StrategyTest {
function test_recoverTokens_Success() public {
deal(USDC, address(strategy), 10e18);

address[] memory tokens = new address[](1);
tokens[0] = USDC;

vm.prank(keeper);
strategy.recoverTokens(tokens, alice);

assertEq(IERC20(USDC).balanceOf(alice), 10e18);
}

function test_recoverTokens_IgnoreAsset() public {
deal(USDC, address(strategy), 10e18);
deal(asset, address(strategy), 10e18);

address[] memory tokens = new address[](2);
tokens[0] = USDC;
tokens[1] = asset;

vm.prank(keeper);
strategy.recoverTokens(tokens, alice);

assertEq(IERC20(USDC).balanceOf(alice), 10e18);
assertEq(IERC20(asset).balanceOf(alice), 0);
assertEq(IERC20(asset).balanceOf(address(strategy)), 10e18);
}

function test_recoverTokens_IgnoreStrategyAsset() public {
deal(USDC, address(strategy), 10e18);
deal(strategyAsset, address(strategy), 10e18);

address[] memory tokens = new address[](2);
tokens[0] = USDC;
tokens[1] = strategyAsset;

vm.prank(keeper);
strategy.recoverTokens(tokens, alice);

assertEq(IERC20(USDC).balanceOf(alice), 10e18);
assertEq(IERC20(strategyAsset).balanceOf(alice), 0);
assertEq(IERC20(strategyAsset).balanceOf(address(strategy)), 10e18);
}

function test_recoverTokens_ZeroReceiver() public {
deal(USDC, address(strategy), 10e18);

address[] memory tokens = new address[](1);
tokens[0] = USDC;

vm.expectRevert(ZeroAddress.selector);
vm.prank(keeper);
strategy.recoverTokens(tokens, address(0));
}
}

0 comments on commit 476608f

Please sign in to comment.