-
Notifications
You must be signed in to change notification settings - Fork 5
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
[New Operator] - Beefy LP Vault #114
Conversation
Co-authored-by: Leo <[email protected]>
refactor: update function names and comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1st review:
Left to review:
- private functions from
contracts/operators/Beefy/BeefyZapBiswapLPVaultOperator.sol
in details - Unit tests
- Optimal amount computation
// Deploy ParaswapOperator | ||
const paraswapOperator = await paraswapOperatorFactory.deploy(tokenTransferProxy, augustusSwapper); | ||
await paraswapOperator.deployed(); | ||
console.log | ||
console.log; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💅
/// Note: "Zap" means that we are converting an asset for the LP Token by | ||
/// swapping and adding liquidity. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Who is we
?
💅 It's better to phrase comments with impersonal type as the deployed contracts are standalone pieces of code. We just happen to deploy and maintain them.
/// Note: "Zap" means that we are converting an asset for the LP Token by | |
/// swapping and adding liquidity. | |
/// Note: "Zapping" means that the asset is converted for the LP Token by | |
/// swapping and adding liquidity. |
/// @param underlying The underlying token address or zapper | ||
event VaultAdded(address vault, address underlying); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💅 underlying
is not explicit enough imo
I even prefer the explicit namingtokenOrZapper
if there's no other way to describe the variable
contracts/operators/Beefy/README.md
Outdated
|
||
To solve the problem of remaining dust after adding liquidity in a uniswap like liquidity pool, we need to perform a calculation to minimize the amount of unused token by the uniswap like router. | ||
|
||
> For this exemple, we will use an WBNB-USDT Uniswap luqidity pool, and we have 1 WBNB as a total investment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
> For this exemple, we will use an WBNB-USDT Uniswap luqidity pool, and we have 1 WBNB as a total investment. | |
> For this example, we will use a WBNB-USDT Uniswap liquidity pool, and we have 1 WBNB as a total investment. |
contracts/operators/Beefy/README.md
Outdated
|
||
## Optimal swap amount | ||
|
||
To solve the problem of remaining dust after adding liquidity in a uniswap like liquidity pool, we need to perform a calculation to minimize the amount of unused token by the uniswap like router. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To solve the problem of remaining dust after adding liquidity in a uniswap like liquidity pool, we need to perform a calculation to minimize the amount of unused token by the uniswap like router. | |
To solve the problem of remaining dust after adding liquidity in a Uniswap-like liquidity pool, we need to perform a calculation to minimize the amount of unused tokens by the Uniswap-like router. |
contracts/operators/Beefy/README.md
Outdated
After the swap, the ratio between **A** and **B** in the liquidity pool is: | ||
$${A+s \over B-b} = {a-s \over b}$$ | ||
|
||
From this equation we can solve for s as using [b espression](#find-b) as follow: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From this equation we can solve for s as using [b espression](#find-b) as follow: | |
From this equation we can solve for s using [b espression](#find-b) as follow: |
contracts/operators/Beefy/README.md
Outdated
|
||
b = B(1 - f)s / (A + (1 - f)s) | ||
|
||
##### Replace b by his value expressed in terms of s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
##### Replace b by his value expressed in terms of s | |
##### Replace b with the value expressed in terms of s |
|
||
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; | ||
|
||
interface IBiswapRouter02 is IUniswapV2Router02 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since IBiswapRouter02 is IUniswapV2Router02
:
I believe that the functions getAmountOut
and getAmountIn
are overloaded, not overridden. This would allow us to use IBiswapRouter02
instead of IUniswapV2Router02
in the uniswapLPVaultOperator and allow factorization of the two contracts, for better legibility and maintenance
The biswapLPVaultOperator would use the same code as uniswapLpvault but override the only two functions whose implementation is different.
} | ||
|
||
/// @notice Perform a vault token withdraw (moo) from Beefy, and | ||
/// transfer the rest as one of the paired token.abi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❔ token.abi
? Not sure I get what you mean here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the .abi
uint256 amount, | ||
address token | ||
) private { | ||
IBiswapRouter02 biswapRouter = IBiswapRouter02(router); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔧 This can be declared further down in the scope to save gas fees if the execution reverts
// LP Tokens needs to be sent back to the pair address to be burned | ||
IERC20(pair).safeTransfer(pair, IERC20(pair).balanceOf(address(this))); | ||
|
||
// We are removing liquidity by burning the LP Token and not |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💅 Same comment: refrain from using "we" which does not translate well in English in this context
require(token0 == token || token1 == token, "BLVO: INVALID_TOKEN"); | ||
|
||
// LP Tokens needs to be sent back to the pair address to be burned | ||
IERC20(pair).safeTransfer(pair, IERC20(pair).balanceOf(address(this))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❔ Not sure I understand why balanceOf
is chained after the transfer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are transferring the received LP Tokens to the LP Token address to burn the LP tokens... This mechanism a little bit weird, but correct. However we must compute the balance before/after withdrawing to send the right amount, i'm fixing this issue.
|
||
/// @dev Zap one of the paired tokens for the LP Token, deposit the | ||
/// asset in the Beefy vault and receive the vault token (moo) | ||
/// @param router The uniswap v2 router address to use for swaping and adding liquidity |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// @param router The uniswap v2 router address to use for swaping and adding liquidity | |
/// @param router The Uniswap v2 router address to use for swapping and adding liquidity |
1, | ||
path, | ||
address(this), | ||
block.timestamp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❔ Why is the interface expecting the block timestamp for a swap? Please enlighten me, I am not very familiar with the Biswap router
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can specify the unix timestamp after which the transaction will revert (for e.g I want to execute my transaction and i need my tokens to be swapped in 1 min max).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// @dev Calculate the optimal amount of tokenA to swap in order | ||
/// to obtain the same market value of tokenB after the trade | ||
/// in order to add as many tokensA and tokensB as possible | ||
/// to the liquidity so that as few as possible remain. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// @dev Calculate the optimal amount of tokenA to swap in order | |
/// to obtain the same market value of tokenB after the trade | |
/// in order to add as many tokensA and tokensB as possible | |
/// to the liquidity so that as few as possible remain. | |
/// @dev Calculate the optimal amount of tokenA to swap to obtain | |
/// the same market value of tokenB after the trade. | |
/// This allows to add as many tokensA and tokensB as possible | |
/// to the liquidity to minimize the remaining amount. |
Context
On the Beefy app, we can find two types of vaults : LPs and Single Assets
![image](https://user-images.githubusercontent.com/22816913/166662324-8f2b0cc8-9126-44fd-9941-8815ec9971c9.png)
The first Beefy Operator is focused on Single Asset Vaults, see PR : #107.
But now, we need a new operator for the LPs vaults.
How the operator works :
There are two steps :
The protocols takes one of the paired tokens.
![image](https://user-images.githubusercontent.com/22816913/166662791-f87291e8-88f3-4d6f-b478-6c50d4031817.png)
For example, in the BTCB-ETH LP vault, we can deposit BTCB or ETH and withdraw BTCB or ETH. The users is not managing Beefy vault tokens or LP Tokens.
Deposit (steps)
Withdraw (steps)
You can get more details in the README.md file for the price calculation (operator folder).
1 Operator = 1 Router Type
Since that the operator is interacting directly with the AMM router to swap and add/remove liquidity, we need to be aware of the router interface. Some AMMs does not have the same interface.
We created an operator for Biswap (where one function needed the fee parameter) and one for the classic UniswapV2 router.
One Operator will list all the supported routers with the same interface. If we need an other router interface, we need an other operator. Supporting Biswap and UniswapV2, will cover a lot of beefy vaults.