Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions contracts/helpers/StrategyMigrator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;

import "../lib/Ownable.sol";
import "../lib/SafeERC20.sol";
import "./../interfaces/ISimpleRouter.sol";
import "./../interfaces/IYakStrategy.sol";
import "./../interfaces/IWGAS.sol";

contract StrategyMigrator is Ownable {
using SafeERC20 for IERC20;

address immutable WGAS;

event Recovered(address token, uint256 amount);

constructor(address _wgas) {
WGAS = _wgas;
}

function migrate(address _fromStrategy, address _toStrategy, uint256 _fromShares, uint256 _minDepositTokenAmount)
external
{
address fromDepositToken = IYakStrategy(_fromStrategy).depositToken();
address toDepositToken = IYakStrategy(_toStrategy).depositToken();
bool migrateFromNative = fromDepositToken == address(0);
require(
(migrateFromNative && toDepositToken == WGAS) || fromDepositToken == toDepositToken,
"StrategyMigrator::Migration impossible"
);
// Transfer shares
require(
IERC20(_fromStrategy).transferFrom(msg.sender, address(this), _fromShares),
"StrategyMigrator::transferFrom failed"
);

// Withdraw
uint256 balanceBefore =
migrateFromNative ? address(this).balance : IERC20(fromDepositToken).balanceOf(address(this));
IYakStrategy(_fromStrategy).withdraw(_fromShares);
uint256 balanceAfter =
migrateFromNative ? address(this).balance : IERC20(fromDepositToken).balanceOf(address(this));
uint256 amountOut = balanceAfter - balanceBefore;
require(amountOut >= _minDepositTokenAmount, "StrategyMigrator::amountOut too low");

// Deposit
if (migrateFromNative) {
IWGAS(WGAS).deposit{value: amountOut}();
}
IERC20(toDepositToken).approve(_toStrategy, amountOut);
IYakStrategy(_toStrategy).depositFor(msg.sender, amountOut);
require(
IYakStrategy(_toStrategy).getDepositTokensForShares(IERC20(_toStrategy).balanceOf(msg.sender))
>= _minDepositTokenAmount,
"StrategyMigrator::migrated deposit token amount too low"
);
}

receive() external payable {}

/**
* @notice Recover ERC20 from contract
* @param tokenAddress token address
* @param tokenAmount amount to recover
*/
function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyOwner {
require(tokenAmount > 0);
IERC20(tokenAddress).safeTransfer(msg.sender, tokenAmount);
emit Recovered(tokenAddress, tokenAmount);
}

/**
* @notice Recover GAS from contract
* @param amount amount
*/
function recoverGas(uint256 amount) external onlyOwner {
require(amount > 0);
payable(msg.sender).transfer(amount);
emit Recovered(address(0), amount);
}
}
4 changes: 4 additions & 0 deletions contracts/interfaces/IYakStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ interface IYakStrategy {
function depositToken() external view returns (address);

function depositFor(address account, uint256 amount) external;

function withdraw(uint256 _amount) external;

function getDepositTokensForShares(uint256 amount) external view returns (uint256);
}