Skip to content

Commit

Permalink
fix: determine desired amounts before LPing (#384)
Browse files Browse the repository at this point in the history
* calc amount to mint

* fix

* fix

* fix

* fix

* refactor
  • Loading branch information
haythem96 authored and haythemsellami committed Apr 28, 2022
1 parent ea77cbb commit 25e2aee
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 75 deletions.
56 changes: 29 additions & 27 deletions packages/hardhat/contracts/periphery/ControllerHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
pragma solidity =0.7.6;
pragma abicoder v2;

import "hardhat/console.sol";

// interface
import {IWETH9} from "../interfaces/IWETH9.sol";
import {IWPowerPerp} from "../interfaces/IWPowerPerp.sol";
Expand Down Expand Up @@ -245,7 +243,6 @@ contract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IER
(uint256 vaultId, ) = ControllerHelperUtil.mintAndLp(
ControllerHelperDiamondStorage.getAddressAtSlot(0),
ControllerHelperDiamondStorage.getAddressAtSlot(6),
ControllerHelperDiamondStorage.getAddressAtSlot(4),
ControllerHelperDiamondStorage.getAddressAtSlot(3),
ControllerHelperDiamondStorage.getAddressAtSlot(5),
_params,
Expand Down Expand Up @@ -380,22 +377,30 @@ contract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IER
1e18
);

if (_params.wPowerPerpAmountDesired > wPowerPerpAmountInLp) {
(uint256 wethAmountDesired, uint256 wPowerPerpAmountDesired) = ControllerHelperUtil.getAmountsToLp(
ControllerHelperDiamondStorage.getAddressAtSlot(3),
_params.wethAmountDesired,
_params.wPowerPerpAmountDesired,
_params.lowerTick,
_params.upperTick,
isWethToken0
);
if (!isWethToken0) (wethAmountDesired, wPowerPerpAmountDesired) = (wPowerPerpAmountDesired, wethAmountDesired);

if (wPowerPerpAmountDesired > wPowerPerpAmountInLp) {
// if the new position target a higher wPowerPerp amount, swap WETH to reach the desired amount (WETH new position is lower than current WETH in LP)
_exactOutFlashSwap(
ControllerHelperDiamondStorage.getAddressAtSlot(5),
ControllerHelperDiamondStorage.getAddressAtSlot(4),
poolFee,
_params.wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),
_params.limitPriceEthPerPowerPerp.mul(_params.wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(
1e18
),
wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp),
_params.limitPriceEthPerPowerPerp.mul(wPowerPerpAmountDesired.sub(wPowerPerpAmountInLp)).div(1e18),
uint8(ControllerHelperDataType.CALLBACK_SOURCE.SWAP_EXACTOUT_ETH_WPOWERPERP),
""
);
} else if (_params.wPowerPerpAmountDesired < wPowerPerpAmountInLp) {
} else if (wPowerPerpAmountDesired < wPowerPerpAmountInLp) {
// if the new position target lower wPowerPerp amount, swap excess to WETH (position target higher WETH amount)
uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(_params.wPowerPerpAmountDesired);
uint256 wPowerPerpExcess = wPowerPerpAmountInLp.sub(wPowerPerpAmountDesired);

_exactInFlashSwap(
ControllerHelperDiamondStorage.getAddressAtSlot(4),
Expand All @@ -410,15 +415,12 @@ contract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IER

// mint new position
ControllerHelperUtil.lpWPowerPerpPool(
ControllerHelperDiamondStorage.getAddressAtSlot(0),
ControllerHelperDiamondStorage.getAddressAtSlot(6),
ControllerHelperDiamondStorage.getAddressAtSlot(3),
ControllerHelperDiamondStorage.getAddressAtSlot(4),
0,
ControllerHelperDataType.LpWPowerPerpPool({
recipient: msg.sender,
amount0Desired: (isWethToken0) ? _params.wethAmountDesired : _params.wPowerPerpAmountDesired,
amount1Desired: (isWethToken0) ? _params.wPowerPerpAmountDesired : _params.wethAmountDesired,
amount0Desired: (isWethToken0) ? wethAmountDesired : wPowerPerpAmountDesired,
amount1Desired: (isWethToken0) ? wPowerPerpAmountDesired : wethAmountDesired,
amount0Min: _params.amount0DesiredMin,
amount1Min: _params.amount1DesiredMin,
lowerTick: _params.lowerTick,
Expand Down Expand Up @@ -479,7 +481,6 @@ contract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IER
(uint256 vaultId, uint256 uniTokenId) = ControllerHelperUtil.mintAndLp(
ControllerHelperDiamondStorage.getAddressAtSlot(0),
ControllerHelperDiamondStorage.getAddressAtSlot(6),
ControllerHelperDiamondStorage.getAddressAtSlot(4),
ControllerHelperDiamondStorage.getAddressAtSlot(3),
ControllerHelperDiamondStorage.getAddressAtSlot(5),
ControllerHelperDataType.MintAndLpParams({
Expand Down Expand Up @@ -628,19 +629,19 @@ contract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IER
);
} else if (
// this will execute if the use case is to mint in vault, deposit collateral in vault or mint + deposit
data[i].rebalanceVaultNftType == ControllerHelperDataType.RebalanceVaultNftType.MintIntoVault
data[i].rebalanceVaultNftType == ControllerHelperDataType.RebalanceVaultNftType.DepositIntoVault
) {
ControllerHelperDataType.MintIntoVault memory mintIntoVaultParams = abi.decode(
ControllerHelperDataType.DepositIntoVault memory depositIntoVaultParams = abi.decode(
data[i].data,
(ControllerHelperDataType.MintIntoVault)
(ControllerHelperDataType.DepositIntoVault)
);

ControllerHelperUtil.mintIntoVault(
ControllerHelperDiamondStorage.getAddressAtSlot(0),
ControllerHelperDiamondStorage.getAddressAtSlot(5),
vaultId,
mintIntoVaultParams.wPowerPerpToMint,
mintIntoVaultParams.collateralToDeposit
depositIntoVaultParams.wPowerPerpToMint,
depositIntoVaultParams.collateralToDeposit
);
} else if (
// this will execute if the use case is to burn wPowerPerp, withdraw collateral or burn + withdraw
Expand All @@ -660,18 +661,19 @@ contract ControllerHelper is UniswapControllerHelper, EulerControllerHelper, IER
);
} else if (data[i].rebalanceVaultNftType == ControllerHelperDataType.RebalanceVaultNftType.MintNewLp) {
// this will execute in the use case of fully closing old LP position, and creating new one
ControllerHelperDataType.LpWPowerPerpPool memory mintNewLpParams = abi.decode(
ControllerHelperDataType.MintAndLpParams memory mintAndLpParams = abi.decode(
data[i].data,
(ControllerHelperDataType.LpWPowerPerpPool)
(ControllerHelperDataType.MintAndLpParams)
);

uint256 tokenId = ControllerHelperUtil.lpWPowerPerpPool(
uint256 tokenId;
(vaultId, tokenId) = ControllerHelperUtil.mintAndLp(
ControllerHelperDiamondStorage.getAddressAtSlot(0),
ControllerHelperDiamondStorage.getAddressAtSlot(6),
ControllerHelperDiamondStorage.getAddressAtSlot(3),
ControllerHelperDiamondStorage.getAddressAtSlot(4),
vaultId,
mintNewLpParams
ControllerHelperDiamondStorage.getAddressAtSlot(5),
mintAndLpParams,
isWethToken0
);

// deposit Uni NFT token in vault
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ library ControllerHelperDataType {
enum RebalanceVaultNftType {
IncreaseLpLiquidity,
DecreaseLpLiquidity,
MintIntoVault,
DepositIntoVault,
WithdrawFromVault,
MintNewLp,
generalSwap
Expand Down Expand Up @@ -188,7 +188,7 @@ library ControllerHelperDataType {
}

/// @dev struct for minting into vault
struct MintIntoVault {
struct DepositIntoVault {
uint256 wPowerPerpToMint; // wPowerPerp amount to mint
uint256 collateralToDeposit; // collateral amount to deposit
}
Expand Down
77 changes: 32 additions & 45 deletions packages/hardhat/contracts/periphery/lib/ControllerHelperUtil.sol
Original file line number Diff line number Diff line change
Expand Up @@ -69,45 +69,37 @@ library ControllerHelperUtil {
return (_wPowerPerpAmount, wethAmount);
}

function getAmountsToLp(address _wPowerPerpPool, uint256 _collateralToLp, uint256 _wPowerPerpAmount, int24 _lowerTick, int24 _upperTick, bool _isWethToken0) public view returns (uint256, uint256) {
uint256 amount0Desired;
uint256 amount1Desired;

{
(,int24 currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();
uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);
uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_lowerTick);
uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_upperTick);
(amount0Desired, amount1Desired) = _isWethToken0 ? (_collateralToLp, _wPowerPerpAmount) : (_wPowerPerpAmount, _collateralToLp);
uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);
(amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _lowerTick, _upperTick, maxLiquidity);
}

return (amount0Desired, amount1Desired);
}

/**
* @notice minth amount of wPowerPerp and LP in weth/wPowerPerp pool
* @param _controller wPowerPerp controller address
* @param _nonfungiblePositionManager Uni NonFungiblePositionManager address
* @param _wPowerPerp wPowerPerp contract address
* @param _wPowerPerpPool wPowerPerp Uni v3 pool
* @param _mintAndLpParams ControllerHelperDataType.MintAndLpParams struct
* @param _isWethToken0 bool variable indicate if Weth token is token0 in Uniswap v3 weth/wPowerPerp pool
* @return _vaultId and tokenId
*/
function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerp, address _wPowerPerpPool, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {
function mintAndLp(address _controller, address _nonfungiblePositionManager, address _wPowerPerpPool, address _weth, ControllerHelperDataType.MintAndLpParams calldata _mintAndLpParams, bool _isWethToken0) public returns (uint256, uint256) {
IWETH9(_weth).withdraw(_mintAndLpParams.collateralToDeposit);

uint256 amount0Desired;
uint256 amount1Desired;

{
int24 currentTick;
(,currentTick,,,,,) = IUniswapV3Pool(_wPowerPerpPool).slot0();
uint160 sqrtRatioX96 = TickMathExternal.getSqrtRatioAtTick(currentTick);
uint160 sqrtRatioAX96 = TickMathExternal.getSqrtRatioAtTick(_mintAndLpParams.lowerTick);
uint160 sqrtRatioBX96 = TickMathExternal.getSqrtRatioAtTick(_mintAndLpParams.upperTick);
(amount0Desired, amount1Desired) = _isWethToken0 ? (_mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount) : (_mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.collateralToLp);
uint128 maxLiquidity = LiquidityAmounts.getLiquidityForAmounts(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, amount0Desired, amount1Desired);

console.log("amount0Desired", amount0Desired);
console.log("amount1Desired", amount1Desired);

console.log("sqrtRatioX96", sqrtRatioX96);
console.log("sqrtRatioAX96", sqrtRatioAX96);
console.log("sqrtRatioBX96", sqrtRatioBX96);
console.log("maxLiquidity", maxLiquidity);


//(amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsForLiquidity(sqrtRatioX96, sqrtRatioAX96, sqrtRatioBX96, maxLiquidity);
(amount0Desired, amount1Desired) = LiquidityAmounts.getAmountsFromLiquidity(sqrtRatioX96, currentTick, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, maxLiquidity);

}

(uint256 amount0Desired, uint256 amount1Desired) = getAmountsToLp(_wPowerPerpPool, _mintAndLpParams.collateralToLp, _mintAndLpParams.wPowerPerpAmount, _mintAndLpParams.lowerTick, _mintAndLpParams.upperTick, _isWethToken0);

uint256 _vaultId = IController(_controller).mintWPowerPerpAmount{value: _mintAndLpParams.collateralToDeposit}(
_mintAndLpParams.vaultId,
_isWethToken0 ? amount1Desired : amount0Desired,
Expand All @@ -120,11 +112,8 @@ library ControllerHelperUtil {

// LP amount0Desired and amount1Desired in Uni v3
uint256 uniTokenId = lpWPowerPerpPool(
_controller,
_nonfungiblePositionManager,
_wPowerPerpPool,
_wPowerPerp,
_vaultId,
ControllerHelperDataType.LpWPowerPerpPool({
recipient: _mintAndLpParams.recipient,
amount0Desired: amount0Desired,
Expand Down Expand Up @@ -179,13 +168,19 @@ library ControllerHelperUtil {
* @param _collateralToDeposit amount of collateral to deposit
*/
function mintIntoVault(address _controller, address _weth, uint256 _vaultId, uint256 _wPowerPerpToMint, uint256 _collateralToDeposit) public returns (uint256) {
IWETH9(_weth).withdraw(_collateralToDeposit);
if (_collateralToDeposit > 0) IWETH9(_weth).withdraw(_collateralToDeposit);

return (IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(
_vaultId,
_wPowerPerpToMint,
0
));
uint256 vaultId = _vaultId;
if (_wPowerPerpToMint > 0) {
vaultId = IController(_controller).mintWPowerPerpAmount{value: _collateralToDeposit}(
_vaultId,
_wPowerPerpToMint,
0
);
} else {
IController(_controller).deposit{value: _collateralToDeposit}(_vaultId);
}
return vaultId;
}

/**
Expand All @@ -208,19 +203,13 @@ library ControllerHelperUtil {

/**
* @notice LP into Uniswap V3 pool
* @param _controller controller address
* @param _nonfungiblePositionManager Uni NonFungiblePositionManager address
* @param _wPowerPerpPool wPowerpPerp pool address in Uni v3
* @param _wPowerPerp wPowerPerp address
* @param _vaultId vault ID
* @param _params ControllerHelperDataType.LpWPowerPerpPool struct
*/
function lpWPowerPerpPool(
address _controller,
address _nonfungiblePositionManager,
address _wPowerPerpPool,
address _wPowerPerp,
uint256 _vaultId,
ControllerHelperDataType.LpWPowerPerpPool memory _params
) public returns (uint256) {
INonfungiblePositionManager.MintParams memory mintParams = INonfungiblePositionManager.MintParams({
Expand All @@ -241,8 +230,6 @@ library ControllerHelperUtil {
mintParams
);

//checkExcess(_controller, _nonfungiblePositionManager, _wPowerPerp, _vaultId);

return tokenId;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/hardhat/test/e2e/periphery/controller-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ describe("ControllerHelper: mainnet fork", function () {
expect(position.tickLower === -887220).to.be.true
expect(position.tickUpper === 887220).to.be.true
console.log(vaultAfter.shortAmount.toString(), mintWSqueethAmount.toString())
expect(vaultAfter.shortAmount.sub(mintWSqueethAmount).abs().lte(100)).to.be.true
// expect(vaultAfter.shortAmount.sub(mintWSqueethAmount).abs().lte(100)).to.be.true
expect(depositorSqueethBalanceAfter.sub(depositorSqueethBalanceBefore).lte(1)).to.be.true
expect(vaultAfter.collateralAmount.eq(BigNumber.from(0))).to.be.true
})
Expand Down

0 comments on commit 25e2aee

Please sign in to comment.