Skip to content

Commit

Permalink
Merge pull request #99 from meTokens/feat/same-asset-migration
Browse files Browse the repository at this point in the history
Feat/same asset migration
  • Loading branch information
Carl Farterson authored Jan 21, 2022
2 parents 2b9c09d + 1e15513 commit 0744fc2
Show file tree
Hide file tree
Showing 6 changed files with 602 additions and 34 deletions.
103 changes: 103 additions & 0 deletions contracts/migrations/SameAssetTransferMigration.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "../libs/Details.sol";
import "../vaults/Vault.sol";
import "../interfaces/IMigration.sol";
import "../interfaces/ISingleAssetVault.sol";

/// @title Same asset vault migrator
/// @author Carl Farterson (@carlfarterson)
/// @notice create a vault to hold an asset if a meToken is resubscribing
/// to a different hub with the same asset
contract SameAssetTransferMigration is ReentrancyGuard, Vault, IMigration {
struct SameAssetMigration {
// if migration is active
bool isMigrating;
// if startMigration() has been triggered
bool started;
}

mapping(address => SameAssetMigration) private _sameAssetMigration;

constructor(
address _dao,
address _foundry,
IHub _hub,
IMeTokenRegistry _meTokenRegistry,
IMigrationRegistry _migrationRegistry
) Vault(_dao, _foundry, _hub, _meTokenRegistry, _migrationRegistry) {}

function initMigration(
address _meToken,
bytes memory /* _encodedArgs */
) external override {
require(msg.sender == address(meTokenRegistry), "!meTokenRegistry");

Details.MeToken memory meToken_ = meTokenRegistry.getDetails(_meToken);
Details.Hub memory hub_ = hub.getDetails(meToken_.hubId);
Details.Hub memory targetHub_ = hub.getDetails(meToken_.targetHubId);

require(hub_.asset == targetHub_.asset, "asset different");

_sameAssetMigration[_meToken].isMigrating = true;
}

function poke(address _meToken) external override nonReentrant {
SameAssetMigration storage usts_ = _sameAssetMigration[_meToken];
Details.MeToken memory meToken_ = meTokenRegistry.getDetails(_meToken);
Details.Hub memory hub_ = hub.getDetails(meToken_.hubId);
if (usts_.isMigrating && !usts_.started) {
ISingleAssetVault(hub_.vault).startMigration(_meToken);
usts_.started = true;
}
}

function finishMigration(address _meToken)
external
override
nonReentrant
returns (uint256 amountOut)
{
require(msg.sender == address(meTokenRegistry), "!meTokenRegistry");
SameAssetMigration storage usts_ = _sameAssetMigration[_meToken];
require(usts_.isMigrating, "!migrating");

Details.MeToken memory meToken_ = meTokenRegistry.getDetails(_meToken);
Details.Hub memory hub_ = hub.getDetails(meToken_.hubId);
Details.Hub memory targetHub_ = hub.getDetails(meToken_.targetHubId);

if (!usts_.started) {
ISingleAssetVault(hub_.vault).startMigration(_meToken);
usts_.started = true;
}
amountOut = meToken_.balancePooled + meToken_.balanceLocked;

// Send asset to new vault only if there's a migration vault
IERC20(targetHub_.asset).transfer(targetHub_.vault, amountOut);

// reset mappings
delete _sameAssetMigration[_meToken];
}

function getDetails(address _meToken)
external
view
returns (SameAssetMigration memory usts_)
{
usts_ = _sameAssetMigration[_meToken];
}

// Kicks off meToken warmup period
function isValid(
address _meToken,
bytes memory /* _encodedArgs */
) public view override returns (bool) {
Details.MeToken memory meToken_ = meTokenRegistry.getDetails(_meToken);
// MeToken not subscribed to a hub
if (meToken_.hubId == 0) return false;
return true;
}
}
10 changes: 1 addition & 9 deletions contracts/migrations/UniswapSingleTransferMigration.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ pragma solidity ^0.8.0;

import {ISwapRouter} from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "../libs/Details.sol";
import "../vaults/Vault.sol";
Expand All @@ -17,13 +15,7 @@ import "../interfaces/ISingleAssetVault.sol";
/// when recollateralizing to a vault with a different base token
/// @dev This contract moves the pooled/locked balances from
/// one erc20 to another
contract UniswapSingleTransferMigration is
Initializable,
Ownable,
ReentrancyGuard,
Vault,
IMigration
{
contract UniswapSingleTransferMigration is ReentrancyGuard, Vault, IMigration {
struct UniswapSingleTransfer {
// The earliest time that the swap can occur
uint256 soonest;
Expand Down
16 changes: 7 additions & 9 deletions contracts/registries/MeTokenRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,13 @@ contract MeTokenRegistry is Ownable, IMeTokenRegistry {
require(!hub_.updating, "hub updating");
require(!targetHub_.updating, "targetHub updating");

// TODO: what if asset is same? Is a migration vault needed since it'll start/end
// at the same and not change to a different asset?
require(hub_.asset != targetHub_.asset, "asset same");
require(_migration != address(0), "migration address(0)");

require(
IVault(_migration).isValid(_meToken, _encodedMigrationArgs),
"Invalid _encodedMigrationArgs"
);

// Ensure the migration we're using is approved
require(
migrationRegistry.isApproved(
Expand All @@ -147,12 +149,6 @@ contract MeTokenRegistry is Ownable, IMeTokenRegistry {
"!approved"
);

require(
IVault(_migration).isValid(_meToken, _encodedMigrationArgs),
"Invalid _encodedMigrationArgs"
);
IMigration(_migration).initMigration(_meToken, _encodedMigrationArgs);

meToken_.startTime = block.timestamp + _warmup;
meToken_.endTime = block.timestamp + _warmup + _duration;
meToken_.endCooldown =
Expand All @@ -163,6 +159,8 @@ contract MeTokenRegistry is Ownable, IMeTokenRegistry {
meToken_.targetHubId = _targetHubId;
meToken_.migration = _migration;

IMigration(_migration).initMigration(_meToken, _encodedMigrationArgs);

emit InitResubscribe(
_meToken,
_targetHubId,
Expand Down
11 changes: 4 additions & 7 deletions contracts/vaults/SingleAssetVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,10 @@ contract SingleAssetVault is Vault, ISingleAssetVault {
emit StartMigration(_meToken);
}

// solhint-disable-next-line
function isValid(address _asset, bytes memory _encodedArgs)
public
pure
override
returns (bool)
{
function isValid(
address _asset,
bytes memory /* _encodedArgs */
) public pure override returns (bool) {
if (_asset == address(0)) {
return false;
}
Expand Down
Loading

0 comments on commit 0744fc2

Please sign in to comment.