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

Improve zap #152

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
13 changes: 9 additions & 4 deletions contracts/Erc20PiptSwap.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ contract Erc20PiptSwap is EthPiptSwap {
address _swapToken,
uint256 _swapAmount,
uint256 _slippage,
uint256 _minPoolAmount,
uint256 _minPoolAmountOut,
uint256 _diffPercent
) external payable returns (uint256 poolAmountOut) {
IERC20(_swapToken).safeTransferFrom(msg.sender, address(this), _swapAmount);
Expand All @@ -56,18 +56,23 @@ contract Erc20PiptSwap is EthPiptSwap {
uint256 wrapperFee = getWrapFee(tokens);
(, uint256 ethSwapAmount) = calcEthFee(ethAmount, wrapperFee);
(, ethInUniswap, poolAmountOut) = calcSwapEthToPiptInputs(ethSwapAmount, tokens, _slippage);
require(poolAmountOut >= _minPoolAmount, "MIN_POOL_AMOUNT_OUT");
require(poolAmountOut >= _minPoolAmountOut, "MIN_POOL_AMOUNT_OUT");
require(_diffPercent >= getMaxDiffPercent(ethInUniswap), "MAX_DIFF_PERCENT");

(poolAmountOut, ) = _swapWethToPiptByPoolOut(ethAmount, poolAmountOut, tokens, wrapperFee);

emit Erc20ToPiptSwap(msg.sender, _swapToken, _swapAmount, ethAmount, poolAmountOut);
}

function swapPiptToErc20(address _swapToken, uint256 _poolAmountIn) external payable returns (uint256 erc20Out) {
uint256 ethOut = _swapPiptToWeth(_poolAmountIn);
function swapPiptToErc20(
address _swapToken,
uint256 _poolAmountIn,
uint256 _minErc20Out
) external payable returns (uint256 erc20Out) {
uint256 ethOut = _swapPiptToWeth(_poolAmountIn, 0);

erc20Out = _swapWethForTokenOut(_swapToken, ethOut);
require(erc20Out >= _minErc20Out, "MIN_ERC20_AMOUNT_OUT");

IERC20(_swapToken).safeTransfer(msg.sender, erc20Out);

Expand Down
81 changes: 40 additions & 41 deletions contracts/Erc20VaultPoolSwap.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import "./interfaces/ICurvePoolRegistry.sol";
import "./interfaces/IErc20PiptSwap.sol";
import "./interfaces/IErc20VaultPoolSwap.sol";
import "./traits/ProgressiveFee.sol";
import "hardhat/console.sol";

contract Erc20VaultPoolSwap is ProgressiveFee, IErc20VaultPoolSwap {
using SafeERC20 for IERC20;
Expand Down Expand Up @@ -75,45 +76,22 @@ contract Erc20VaultPoolSwap is ProgressiveFee, IErc20VaultPoolSwap {
usdc = IERC20(_usdc);
}

function setVaultConfigs(
address[] memory _tokens,
address[] memory _depositors,
uint8[] memory _depositorTypes,
uint8[] memory _depositorAmountLength,
uint8[] memory _depositorIndexes,
address[] memory _lpTokens,
address[] memory _curvePoolRegistries
) external onlyOwner {
function setVaultConfigs(address[] memory _tokens, VaultConfig[] memory _vaultConfigs) external onlyOwner {
uint256 len = _tokens.length;
require(
len == _depositors.length &&
len == _depositorAmountLength.length &&
len == _depositorIndexes.length &&
len == _depositorTypes.length &&
len == _lpTokens.length &&
len == _curvePoolRegistries.length,
"L"
);
require(len == _vaultConfigs.length, "L");
for (uint256 i = 0; i < len; i++) {
vaultConfig[_tokens[i]] = VaultConfig(
_depositorAmountLength[i],
_depositorIndexes[i],
_depositorTypes[i],
_depositors[i],
_lpTokens[i],
_curvePoolRegistries[i]
);
vaultConfig[_tokens[i]] = _vaultConfigs[i];

usdc.approve(_depositors[i], uint256(-1));
IERC20(_lpTokens[i]).approve(_tokens[i], uint256(-1));
IERC20(_lpTokens[i]).approve(_depositors[i], uint256(-1));
usdc.approve(_vaultConfigs[i].depositor, uint256(-1));
IERC20(_vaultConfigs[i].lpToken).approve(_tokens[i], uint256(-1));
IERC20(_vaultConfigs[i].lpToken).approve(_vaultConfigs[i].depositor, uint256(-1));
emit SetVaultConfig(
_tokens[i],
_depositors[i],
_depositorAmountLength[i],
_depositorIndexes[i],
_lpTokens[i],
_curvePoolRegistries[i]
_vaultConfigs[i].depositor,
_vaultConfigs[i].depositorLength,
_vaultConfigs[i].depositorIndex,
_vaultConfigs[i].lpToken,
_vaultConfigs[i].curvePoolRegistry
);
}
}
Expand All @@ -139,7 +117,8 @@ contract Erc20VaultPoolSwap is ProgressiveFee, IErc20VaultPoolSwap {
function swapErc20ToVaultPool(
address _pool,
address _swapToken,
uint256 _swapAmount
uint256 _swapAmount,
uint256 _poolAmountOutMin
) external override returns (uint256 poolAmountOut) {
require(_swapToken == address(usdc), "ONLY_USDC");
usdc.safeTransferFrom(msg.sender, address(this), _swapAmount);
Expand All @@ -151,7 +130,9 @@ contract Erc20VaultPoolSwap is ProgressiveFee, IErc20VaultPoolSwap {

PowerIndexPoolInterface(_pool).joinPool(poolAmountOut, tokensInPipt);
(, uint256 communityFee, , ) = PowerIndexPoolInterface(_pool).getCommunityFee();
poolAmountOut = poolAmountOut.sub(poolAmountOut.mul(communityFee).div(1 ether)) - 1;
// subtract 1 wei from poolAmountOut to avoid insufficient balance error due to rounding
poolAmountOut = poolAmountOut.sub(poolAmountOut.mul(communityFee).div(1 ether)).sub(1);
require(poolAmountOut >= _poolAmountOutMin, "POOL_AMOUNT_OUT_MIN");

IERC20(_pool).safeTransfer(msg.sender, poolAmountOut);

Expand All @@ -161,14 +142,16 @@ contract Erc20VaultPoolSwap is ProgressiveFee, IErc20VaultPoolSwap {
function swapVaultPoolToErc20(
address _pool,
uint256 _poolAmountIn,
address _swapToken
address _swapToken,
uint256 _erc20AmountOutMin
) external override returns (uint256 erc20Out) {
require(_swapToken == address(usdc), "ONLY_USDC");
IERC20(_pool).safeTransferFrom(msg.sender, address(this), _poolAmountIn);

(, uint256 _poolAmountInWithFee) = calcFee(_poolAmountIn, 0);

erc20Out = _redeemPooledVault(_pool, _poolAmountInWithFee);
require(erc20Out >= _erc20AmountOutMin, "ERC20_AMOUNT_OUT_MIN");

usdc.safeTransfer(msg.sender, erc20Out);

Expand Down Expand Up @@ -243,15 +226,17 @@ contract Erc20VaultPoolSwap is ProgressiveFee, IErc20VaultPoolSwap {
uint256 piptTotalSupply = p.totalSupply();

(VaultCalc[] memory vc, uint256 restInput, uint256 totalCorrectInput) =
getVaultCalcsForSupply(_pool, piptTotalSupply, _usdcIn);
_getVaultCalcsForSupply(_pool, piptTotalSupply, _usdcIn);

uint256[] memory tokensInPipt = new uint256[](len);
for (uint256 i = 0; i < len; i++) {
uint256 share = vc[i].correctInput.mul(1 ether).div(totalCorrectInput);
// subtract 100 wei from input to avoid rounding errors on share calculation
vc[i].correctInput = vc[i].correctInput.add(restInput.mul(share).div(1 ether)).sub(100);

tokensInPipt[i] = calcVaultOutByUsdc(vc[i].token, vc[i].correctInput);

// subtract 1e12 wei from tokensInPipt to make expected poolOut smaller to avoid LIMIT_IN error on joinPool
uint256 poolOutByToken = tokensInPipt[i].sub(1e12).mul(piptTotalSupply).div(vc[i].tokenBalance);
if (poolOutByToken < amountOut || amountOut == 0) {
amountOut = poolOutByToken;
Expand Down Expand Up @@ -297,12 +282,24 @@ contract Erc20VaultPoolSwap is ProgressiveFee, IErc20VaultPoolSwap {
}
}

function getVaultCalcsForSupply(
function getVaultCalcs(address _pool, uint256 totalInputAmount)
public
view
returns (
VaultCalc[] memory vc,
uint256 restInput,
uint256 totalCorrectInput
)
{
return _getVaultCalcsForSupply(_pool, PowerIndexPoolInterface(_pool).totalSupply(), totalInputAmount);
}

function _getVaultCalcsForSupply(
address _pool,
uint256 piptTotalSupply,
uint256 totalInputAmount
)
public
internal
view
returns (
VaultCalc[] memory vc,
Expand Down Expand Up @@ -348,17 +345,19 @@ contract Erc20VaultPoolSwap is ProgressiveFee, IErc20VaultPoolSwap {
uint256 piptTotalSupply = PowerIndexPoolInterface(_pool).totalSupply();

(VaultCalc[] memory vc, uint256 restInput, uint256 totalCorrectInput) =
getVaultCalcsForSupply(_pool, piptTotalSupply, _totalInputAmount);
_getVaultCalcsForSupply(_pool, piptTotalSupply, _totalInputAmount);

tokensInPipt = new uint256[](len);
for (uint256 i = 0; i < len; i++) {
uint256 share = vc[i].correctInput.mul(1 ether).div(totalCorrectInput);
// subtract 100 wei from input to avoid rounding errors on share calculation
vc[i].correctInput = vc[i].correctInput.add(restInput.mul(share).div(1 ether)).sub(100);

uint256 balanceBefore = IVault(vc[i].token).balanceOf(address(this));
IVault(vc[i].token).deposit(_addYearnLpTokenLiquidity(vaultConfig[vc[i].token], vc[i].correctInput));
tokensInPipt[i] = IVault(vc[i].token).balanceOf(address(this)).sub(balanceBefore);

// subtract 1e12 wei from tokensInPipt to make expected poolOut smaller to avoid LIMIT_IN error on joinPool
uint256 poolOutByToken = tokensInPipt[i].sub(1e12).mul(piptTotalSupply).div(vc[i].tokenBalance);
if (poolOutByToken < poolAmountOut || poolAmountOut == 0) {
poolAmountOut = poolOutByToken;
Expand Down
34 changes: 20 additions & 14 deletions contracts/EthPiptSwap.sol
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,12 @@ contract EthPiptSwap is ProgressiveFee {
return _swapWethToPiptByPoolOut(msg.value, _poolAmountOut, tokens, getWrapFee(tokens));
}

function swapPiptToEth(uint256 _poolAmountIn) external payable returns (uint256 ethOutAmount) {
ethOutAmount = _swapPiptToWeth(_poolAmountIn);
function swapPiptToEth(uint256 _poolAmountIn, uint256 _minEthAmountOut)
external
payable
returns (uint256 ethOutAmount)
{
ethOutAmount = _swapPiptToWeth(_poolAmountIn, _minEthAmountOut);

weth.withdraw(ethOutAmount);
Address.sendValue(msg.sender, ethOutAmount);
Expand Down Expand Up @@ -206,12 +210,7 @@ contract EthPiptSwap is ProgressiveFee {

uint256 totalEthRequired = 0;
{
uint256 piptTotalSupply = pipt.totalSupply();
// get pool out for 1 ether as 100% for calculate shares
// poolOut by 1 ether first token join = piptTotalSupply.mul(1 ether).div(getPiptTokenBalance(_tokens[0]))
// poolRatio = poolOut/totalSupply
uint256 poolRatio =
piptTotalSupply.mul(1 ether).div(getPiptTokenBalance(_tokens[0])).mul(1 ether).div(piptTotalSupply);
uint256 poolRatio = uint256(1e36).div(getPiptTokenBalance(_tokens[0]));

for (uint256 i = 0; i < _tokens.length; i++) {
// token share relatively 1 ether of first token
Expand Down Expand Up @@ -269,7 +268,7 @@ contract EthPiptSwap is ProgressiveFee {
}

function calcNeedEthToPoolOut(uint256 _poolAmountOut, uint256 _slippage) public view returns (uint256) {
uint256 ratio = _poolAmountOut.mul(1 ether).div(pipt.totalSupply()).add(100);
uint256 ratio = calcRatioToJoin(_poolAmountOut, pipt.totalSupply());

address[] memory tokens = getPiptTokens();
uint256 len = tokens.length;
Expand All @@ -285,6 +284,12 @@ contract EthPiptSwap is ProgressiveFee {
return totalEthSwap.add(totalEthSwap.mul(_slippage).div(1 ether));
}

function calcRatioToJoin(uint256 _poolAmountOut, uint256 _totalSupply) public view returns (uint256) {
// add 100 wei to ratio to make tokensInPipt values bigger as well as totalEthSwap
// to avoid LIMIT_IN errors on joinPool
return _poolAmountOut.mul(1 ether).div(_totalSupply).add(100);
}

function calcEthFee(uint256 ethAmount, uint256 wrapperFee) public view returns (uint256 ethFee, uint256 ethAfterFee) {
return calcFee(ethAmount, wrapperFee);
}
Expand Down Expand Up @@ -378,7 +383,7 @@ contract EthPiptSwap is ProgressiveFee {
}
}

(uint256 feeAmount, uint256 swapAmount) = calcEthFee(_wethAmount, wrapperFee);
(uint256 ethFeeAmount, uint256 swapAmount) = calcEthFee(_wethAmount, wrapperFee);
(uint256[] memory tokensInPipt, uint256 totalEthSwap) = _prepareTokensForJoin(tokens, _poolAmountOut);

{
Expand All @@ -390,7 +395,7 @@ contract EthPiptSwap is ProgressiveFee {
address(this)
);

emit EthToPiptSwap(msg.sender, swapAmount, feeAmount, _poolAmountOut, poolAmountOutFee);
emit EthToPiptSwap(msg.sender, swapAmount, ethFeeAmount, _poolAmountOut, poolAmountOutFee);
}

_joinPool(_poolAmountOut, tokensInPipt, wrapperFee);
Expand All @@ -411,7 +416,7 @@ contract EthPiptSwap is ProgressiveFee {
{
uint256 len = _tokens.length;
tokensInPipt = new uint256[](len);
uint256 ratio = _poolAmountOut.mul(1 ether).div(pipt.totalSupply()).add(100);
uint256 ratio = calcRatioToJoin(_poolAmountOut, pipt.totalSupply());
for (uint256 i = 0; i < len; i++) {
tokensInPipt[i] = ratio.mul(getPiptTokenBalance(_tokens[i])).div(1 ether);
totalEthSwap = totalEthSwap.add(_swapWethForTokenIn(_tokens[i], tokensInPipt[i]));
Expand All @@ -424,7 +429,7 @@ contract EthPiptSwap is ProgressiveFee {
}
}

function _swapPiptToWeth(uint256 _poolAmountIn) internal returns (uint256) {
function _swapPiptToWeth(uint256 _poolAmountIn, uint256 _minEthAmountOut) internal returns (uint256) {
address[] memory tokens = getPiptTokens();
uint256 len = tokens.length;

Expand All @@ -436,6 +441,7 @@ contract EthPiptSwap is ProgressiveFee {
uint256 wrapperFee = getWrapFee(tokens);

(uint256 ethFeeAmount, uint256 ethOutAmount) = calcEthFee(totalEthOut, wrapperFee);
require(ethOutAmount >= _minEthAmountOut, "MIN_ETH_AMOUNT_OUT");

_exitPool(_poolAmountIn, tokensOutPipt, wrapperFee);

Expand All @@ -459,7 +465,7 @@ contract EthPiptSwap is ProgressiveFee {
pipt.joinPool(_poolAmountOut, _maxAmountsIn);
} else {
if (address(this).balance < _wrapperFee) {
weth.withdraw(_wrapperFee);
weth.withdraw(_wrapperFee.sub(address(this).balance));
}
piptWrapper.joinPool{ value: _wrapperFee }(_poolAmountOut, _maxAmountsIn);
}
Expand Down
Loading