Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vault): test with yearn token #153

Merged
merged 7 commits into from
May 2, 2022
Merged
Show file tree
Hide file tree
Changes from 5 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
4 changes: 4 additions & 0 deletions contracts/interfaces/IMigration.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ pragma solidity 0.8.9;
/// @title Generic migration vault interface
/// @author Carter Carlson (@cartercarlson)
interface IMigration {
/// @notice Method returns true is the migration has started
/// @param meToken Address of meToken
function isStarted(address meToken) external view returns (bool);

/// @notice Method to trigger actions from the migration vault if needed
/// @param meToken Address of meToken
function poke(address meToken) external;
Expand Down
180 changes: 122 additions & 58 deletions contracts/libs/LibFoundry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -53,38 +53,42 @@ library LibFoundry {
address sender = LibMeta.msgSender();
MeTokenInfo memory meTokenInfo = s.meTokens[meToken];
HubInfo memory hubInfo = s.hubs[meTokenInfo.hubId];

// Handling changes
if (hubInfo.updating && block.timestamp > hubInfo.endTime) {
LibHub.finishUpdate(meTokenInfo.hubId);
} else if (meTokenInfo.targetHubId != 0) {
if (block.timestamp > meTokenInfo.endTime) {
hubInfo = s.hubs[meTokenInfo.targetHubId];
meTokenInfo = LibMeToken.finishResubscribe(meToken);
} else if (block.timestamp > meTokenInfo.startTime) {
// Handle migration actions if needed
IMigration(meTokenInfo.migration).poke(meToken);
meTokenInfo = s.meTokens[meToken];
}
}
uint256[3] memory amounts;
amounts[1] = (assetsDeposited * s.mintFee) / s.PRECISION; // fee
amounts[2] = assetsDeposited - amounts[1]; //assetsDepositedAfterFees

amounts[0] = _calculateMeTokensMinted(meToken, amounts[2]); // meTokensMinted
IVault vault = IVault(hubInfo.vault);
address asset = hubInfo.asset;

// Check if meToken is using a migration vault and in the active stage of resubscribing.
// Sometimes a meToken may be resubscribing to a hub w/ the same asset,
// in which case a migration vault isn't needed
if (
meTokenInfo.migration != address(0) &&
block.timestamp > meTokenInfo.startTime
block.timestamp > meTokenInfo.startTime &&
IMigration(meTokenInfo.migration).isStarted(meToken)
) {
// Use meToken address to get the asset address from the migration vault
vault = IVault(meTokenInfo.migration);
asset = s.hubs[meTokenInfo.targetHubId].asset;
}
vault.handleDeposit(sender, asset, assetsDeposited, amounts[1]);
LibMeToken.updateBalancePooled(true, meToken, amounts[2]);

// Handling changes
if (hubInfo.updating && block.timestamp > hubInfo.endTime) {
LibHub.finishUpdate(meTokenInfo.hubId);
} else if (meTokenInfo.targetHubId != 0) {
if (block.timestamp > meTokenInfo.endTime) {
//hubInfo = s.hubs[meTokenInfo.targetHubId];
LibMeToken.finishResubscribe(meToken);
} else if (block.timestamp > meTokenInfo.startTime) {
// Handle migration actions if needed
IMigration(meTokenInfo.migration).poke(meToken);
}
}

return (vault, asset, sender, amounts);
}

Expand All @@ -94,14 +98,12 @@ library LibFoundry {
address recipient
) internal {
(
IVault vault,
,
address asset,
address sender,
uint256[3] memory amounts // 0-meTokensMinted 1-fee 2-assetsDepositedAfterFees
) = handleMint(meToken, assetsDeposited);
vault.handleDeposit(sender, asset, assetsDeposited, amounts[1]);

LibMeToken.updateBalancePooled(true, meToken, amounts[2]);
// Mint meToken to user
IMeToken(meToken).mint(recipient, amounts[0]);
emit Mint(
Expand All @@ -119,28 +121,24 @@ library LibFoundry {
uint256 assetsDeposited,
address recipient,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
uint8 vSig,
bytes32 rSig,
bytes32 sSig
) internal {
(
IVault vault,
address asset,
address sender,
uint256[3] memory amounts // 0-meTokensMinted 1-fee 2-assetsDepositedAfterFees
) = handleMint(meToken, assetsDeposited);
vault.handleDepositWithPermit(
sender,
asset,
assetsDeposited,
amounts[1],
deadline,
v,
r,
s
);
uint256[2] memory amounts // 0-meTokensMinted 1-assetsDepositedAfterFees
) = _handleMintWithPermit(
meToken,
assetsDeposited,
deadline,
vSig,
rSig,
sSig
);

LibMeToken.updateBalancePooled(true, meToken, amounts[2]);
LibMeToken.updateBalancePooled(true, meToken, amounts[1]);
// Mint meToken to user
IMeToken(meToken).mint(recipient, amounts[0]);
emit Mint(
Expand All @@ -166,15 +164,12 @@ library LibFoundry {
// Handling changes
if (hubInfo.updating && block.timestamp > hubInfo.endTime) {
LibHub.finishUpdate(meTokenInfo.hubId);
} else if (meTokenInfo.targetHubId != 0) {
if (block.timestamp > meTokenInfo.endTime) {
hubInfo = s.hubs[meTokenInfo.targetHubId];
meTokenInfo = LibMeToken.finishResubscribe(meToken);
} else if (block.timestamp > meTokenInfo.startTime) {
// Handle migration actions if needed
IMigration(meTokenInfo.migration).poke(meToken);
meTokenInfo = s.meTokens[meToken];
}
} else if (
meTokenInfo.targetHubId != 0 &&
block.timestamp > meTokenInfo.endTime
) {
hubInfo = s.hubs[meTokenInfo.targetHubId];
meTokenInfo = LibMeToken.finishResubscribe(meToken);
}
// Calculate how many tokens are returned
uint256 rawAssetsReturned = _calculateRawAssetsReturned(
Expand Down Expand Up @@ -218,6 +213,7 @@ library LibFoundry {
rawAssetsReturned - assetsReturned
);
}

_vaultWithdrawal(
sender,
recipient,
Expand All @@ -228,29 +224,97 @@ library LibFoundry {
assetsReturned,
feeRate
);
/* uint256 fee = (assetsReturned * feeRate) / s.PRECISION;
assetsReturned = assetsReturned - fee;
}

function _handleMintWithPermit(
address meToken,
uint256 assetsDeposited,
uint256 deadline,
uint8 vSig,
bytes32 rSig,
bytes32 sSig
)
private
returns (
address asset,
address sender,
uint256[2] memory amounts
)
{
AppStorage storage s = LibAppStorage.diamondStorage();
// 0-meTokensMinted 1-fee 2-assetsDepositedAfterFees

MeTokenInfo memory meTokenInfo = s.meTokens[meToken];
HubInfo memory hubInfo = s.hubs[meTokenInfo.hubId];

// uint256[2] memory amounts;
// amounts[1] = (assetsDeposited * s.mintFee) / s.PRECISION; // fee
amounts[1] =
assetsDeposited -
((assetsDeposited * s.mintFee) / s.PRECISION); //assetsDepositedAfterFees

amounts[0] = _calculateMeTokensMinted(meToken, amounts[1]); // meTokensMinted

asset = _handlingChangesWithPermit(
amounts[1],
meToken,
meTokenInfo,
hubInfo,
assetsDeposited,
deadline,
vSig,
rSig,
sSig
);
return (asset, sender, amounts);
}

function _handlingChangesWithPermit(
uint256 assetsDepositedAfterFees,
address meToken,
MeTokenInfo memory meTokenInfo,
HubInfo memory hubInfo,
uint256 assetsDeposited,
uint256 deadline,
uint8 vSig,
bytes32 rSig,
bytes32 sSig
) private returns (address asset) {
AppStorage storage s = LibAppStorage.diamondStorage();
address sender = LibMeta.msgSender();
IVault vault = IVault(hubInfo.vault);
address asset = hubInfo.asset;
asset = hubInfo.asset;

if (
meTokenInfo.migration != address(0) &&
block.timestamp > meTokenInfo.startTime
block.timestamp > meTokenInfo.startTime &&
IMigration(meTokenInfo.migration).isStarted(meToken)
) {
// Use meToken address to get the asset address from the migration vault
vault = IVault(meTokenInfo.migration);
asset = s.hubs[meTokenInfo.targetHubId].asset;
}

vault.handleWithdrawal(recipient, asset, assetsReturned, fee);

emit Burn(
meToken,
asset,
vault.handleDepositWithPermit(
sender,
recipient,
meTokensBurned,
assetsReturned
); */
asset,
assetsDeposited,
(assetsDeposited * s.mintFee) / s.PRECISION,
deadline,
vSig,
rSig,
sSig
);
LibMeToken.updateBalancePooled(true, meToken, assetsDepositedAfterFees);
if (hubInfo.updating && block.timestamp > hubInfo.endTime) {
LibHub.finishUpdate(meTokenInfo.hubId);
} else if (meTokenInfo.targetHubId != 0) {
if (block.timestamp > meTokenInfo.endTime) {
LibMeToken.finishResubscribe(meToken);
} else if (block.timestamp > meTokenInfo.startTime) {
// Handle migration actions if needed
IMigration(meTokenInfo.migration).poke(meToken);
}
}
}

function _vaultWithdrawal(
Expand Down
5 changes: 5 additions & 0 deletions contracts/migrations/SameAssetTransferMigration.sol
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ contract SameAssetTransferMigration is ReentrancyGuard, Vault, IMigration {
delete _sameAssetMigration[meToken];
}

/// @inheritdoc IMigration
function isStarted(address meToken) external view override returns (bool) {
return _sameAssetMigration[meToken].started;
}

function getDetails(address meToken)
external
view
Expand Down
16 changes: 9 additions & 7 deletions contracts/migrations/UniswapSingleTransferMigration.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {IHubFacet} from "../interfaces/IHubFacet.sol";
import {IMeTokenRegistryFacet} from "../interfaces/IMeTokenRegistryFacet.sol";
import {IMigration} from "../interfaces/IMigration.sol";
import {ISingleAssetVault} from "../interfaces/ISingleAssetVault.sol";
import {ISwapRouter} from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import {IV3SwapRouter} from "@uniswap/swap-router-contracts/contracts/interfaces/IV3SwapRouter.sol";
import {HubInfo} from "../libs/LibHub.sol";
import {MeTokenInfo} from "../libs/LibMeToken.sol";
import {Vault} from "../vaults/Vault.sol";
Expand All @@ -33,8 +33,8 @@ contract UniswapSingleTransferMigration is ReentrancyGuard, Vault, IMigration {

// NOTE: this can be found at
// github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/interfaces/ISwapRouter.sol
ISwapRouter private immutable _router =
ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);
IV3SwapRouter private immutable _router =
IV3SwapRouter(0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45);

// args for uniswap router
uint24 public constant MINFEE = 500; // 0.05%
Expand All @@ -56,7 +56,6 @@ contract UniswapSingleTransferMigration is ReentrancyGuard, Vault, IMigration {
{
MeTokenInfo memory meTokenInfo = IMeTokenRegistryFacet(diamond)
.getMeTokenInfo(meToken);

require(
IHubFacet(diamond).getHubInfo(meTokenInfo.hubId).asset !=
IHubFacet(diamond).getHubInfo(meTokenInfo.targetHubId).asset,
Expand Down Expand Up @@ -100,7 +99,6 @@ contract UniswapSingleTransferMigration is ReentrancyGuard, Vault, IMigration {
HubInfo memory targetHubInfo = IHubFacet(diamond).getHubInfo(
meTokenInfo.targetHubId
);

uint256 amountOut;
if (!_uniswapSingleTransfers[meToken].started) {
ISingleAssetVault(
Expand All @@ -122,6 +120,11 @@ contract UniswapSingleTransferMigration is ReentrancyGuard, Vault, IMigration {
delete _uniswapSingleTransfers[meToken];
}

/// @inheritdoc IMigration
function isStarted(address meToken) external view override returns (bool) {
return _uniswapSingleTransfers[meToken].started;
}

function getDetails(address meToken)
external
view
Expand Down Expand Up @@ -191,13 +194,12 @@ contract UniswapSingleTransferMigration is ReentrancyGuard, Vault, IMigration {
IERC20(hubInfo.asset).safeApprove(address(_router), amountIn);

// https://docs.uniswap.org/protocol/guides/swaps/single-swaps
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter
IV3SwapRouter.ExactInputSingleParams memory params = IV3SwapRouter
.ExactInputSingleParams({
tokenIn: hubInfo.asset,
tokenOut: targetHubInfo.asset,
fee: usts.fee,
recipient: address(this),
deadline: block.timestamp,
amountIn: amountIn,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0
Expand Down
7 changes: 5 additions & 2 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,12 @@ const config: HardhatUserConfig = {
},
mocha: {
delay: true,
timeout: 60000, // Here is 2min but can be whatever timeout is suitable for you.
timeout: 120000, // Here is 2min but can be whatever timeout is suitable for you.
},
namedAccounts: {
SwapRouter: "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
Quoter: "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6",
UNIV3Factory: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
DAI: {
default: "0x6B175474E89094C44Da98b954EedeAC495271d0F", // here this will by default take the first account as deployer
1: "0x6B175474E89094C44Da98b954EedeAC495271d0F", // similarly on mainnet it will take the first account as deployer. Note though that depending on how hardhat network are configured, the account 0 on one network can be different than on another
Expand All @@ -108,7 +111,7 @@ const config: HardhatUserConfig = {
forking: {
url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_API_KEY}`,
accounts,
blockNumber: 13310410,
blockNumber: 14448329,
},
gas: "auto",
timeout: 1800000,
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@openzeppelin/contracts": "^4.5.0",
"@uniswap/sdk-core": "^3.0.1",
"@uniswap/v3-core": "^1.0.0",
"@uniswap/smart-order-router": "^2.5.22",
"@uniswap/v3-periphery": "^1.4.1",
"@uniswap/v3-sdk": "^3.8.1",
"yarn": "^1.22.18"
Expand Down
Loading