Platform: Code4rena
Start Date: 09/11/2021
Pot Size: $75,000 USDC
Total HM: 57
Participants: 27
Period: 7 days
Judge: alcueca
Total Solo HM: 49
Id: 52
League: ETH
Rank: 1/27
Findings: 17
Award: $15,401.66
🌟 Selected for report: 24
🚀 Solo Findings: 10
🌟 Selected for report: TomFrenchBlockchain
Also found by: cmichel
728.5837 USDC - $728.58
TomFrench
The amount of synths minted / assets received when minting or burning synths can be manipulated to an unlimited extent by manipulating the reserves of the pool
See VaderPool.mintSynth
:
https://github.com/code-423n4/2021-11-vader/blob/607d2b9e253d59c782e921bfc2951184d3f65825/contracts/dex-v2/pool/VaderPoolV2.sol#L126-L167
Here a user sends nativeDeposit
to the pool and the equivalent amount of foreignAsset
is minted as a synth to be sent to the user. However the user can't specify the minimum amount of synth that they would accept. A frontrunner can then manipulate the reserves of the pool in order to make foreignAsset
appear more valuable than it really is so the user receives synths which are worth much less than what nativeDeposit
is worth. This is equivalent to a swap without a slippage limit.
Burning synths essentially runs the same process in behalf so manipulating the pool in the opposite direction will result in the user getting fewer of nativeAsset
than they expect.
Add a argument for the minimum amount of synths to mint or nativeAsset to receive.
#0 - SamSteinGG
2021-11-25T11:06:26Z
We believe the severity should be set to medium as there are no loss of funds and its exploit requires special circumstances to be profitable.
🌟 Selected for report: TomFrenchBlockchain
1619.075 USDC - $1,619.07
TomFrench
Draining of funds from VaderPool
See the VaderPool.mintSynth
function:
https://github.com/code-423n4/2021-11-vader/blob/607d2b9e253d59c782e921bfc2951184d3f65825/contracts/dex-v2/pool/VaderPoolV2.sol#L126-L167
As the pool's reserves can be manipulated through flashloans similar to on UniswapV2, an attacker may set the exchange rate between nativeAsset
and synths (calculated from the reserves). An attacker can exploit this to drain funds from the pool.
foreignAsset
to the pool. The pool now thinks nativeAsset
is extremely valuable.nativeAsset
to mint synths using VaderPool.mintSynth
. As the pool thinks nativeAsset
is very valuable the attacker will receive a huge amount of synths.foreignAsset
they sold to the pool. nativeAsset
is now back at its normal price, or perhaps artificially low if the attacker wishes.nativeAsset
is considered much less valuable than at the point the synths were minted it takes a lot more of nativeAsset
in order to pay out for the burned synths.For the price of a flashloan and some swap fees, the attacker has now managed to extract a large amount of nativeAsset
from the pool. This process can be repeated as long as it is profitable.
Prevent minting of synths or at the very least tie the exchange rate to a manipulation resistant oracle.
#0 - SamSteinGG
2021-11-25T11:08:57Z
When synths are minted the reserves are skewed positively for the price of the native asset in the example. Can the warden provide a test that highlights this?
🌟 Selected for report: TomFrenchBlockchain
1619.075 USDC - $1,619.07
TomFrench
Detailed description of the impact of this finding.
On L156 of TwapOracle
we perform the calculation:
result = ((sumUSD * IERC20Metadata(token).decimals()) / sumNative);
This seems extremely odd as for an 18 decimal token we're then calculating
result = ((sumUSD * 18) / sumNative);
This is just plain weird. I expect what was meant is to replace this line with the below so we're properly scaling for token
's number of decimals.
uint256 scalingFactor = 10 ** IERC20Metadata(token).decimals() result = (sumUSD * scalingFactor) / sumNative;
Marked as high severity as this exchange rate appears to be used in some form of minting mechanism and correctness of the oracle is listed as one of the key focuses of the audit.
As above.
#0 - SamSteinGG
2021-12-22T07:43:04Z
The TWAP oracle module has been completely removed and redesigned from scratch as LBTwap that is subject of the new audit.
🌟 Selected for report: TomFrenchBlockchain
Also found by: WatchPug
728.5837 USDC - $728.58
TomFrench
Impermanent loss protection can be exploited to drain the reserve.
In VaderPoolV2.burn
we calculate the current losses that the LP has made to impermanent loss.
These losses are then refunded to the LP in VADER tokens from the reserve
This loss is calculated by the current reserves of the pool so if an LP can manipulate the pool's reserves they can artificially engineer a huge amount of IL in order to qualify for a payout up to the size of their LP position.
The attack is then as follows.
The attacker now holds the majority of their flashloaned funds (minus slippage/swap fees) along with a large fraction of the value of their LP position in VADER paid out from the reserve. The value of their LP position is unchanged. Given a large enough LP position, the IL protection funds extracted from the reserve will exceed the funds lost to swap fees and the attacker will be able to repay their flashloan with a profit.
This is a high risk issue as after a year any large LP is incentivised and able to perform this attack.
Use a manipulation resistant oracle for the relative prices of the pool's assets (TWAP, etc.)
#0 - SamSteinGG
2021-11-25T11:37:00Z
This mechanism has been implemented as described by the Thorchain model. Can the warden submit details as to how it is meant to be exploited, i.e. a test case?
🌟 Selected for report: TomFrenchBlockchain
1619.075 USDC - $1,619.07
TomFrench
Vader Reserve can be drained of funds.
In VaderPoolV2.burn
we calculate the current losses that the LP has made to impermanent loss.
These losses are then refunded to the LP in VADER tokens from the reserve. NOTE: This IL protection is paid for ALL token pairs. THIS IS IMPORTANT!
The loss is calculated by the comparing the amounts of each asset initially added to the pool against the amounts of each asset which are removed from the pool. There's an unspoken assumption here that the LP entered the pool at the true price at that point.
Crucially we see that if an attacker can cheaply create a pool with a token which starts off with a very low price in terms of VADER and is guaranteed to have a very high price in terms of VADER then they will benefit from a large amount of IL protection funds from the reserve.
An attacker could then perform this attack with the following.
The attacker has now engineered a liquidity position which looks massively underwater due to IL but in reality was very cheap to produce. Nobody else can do anything to this pool except just give the attacker money by buying TKN so this attack can't be prevented. The attacker now just needs to wait for at most a year for the IL protection to tick up and then they can cash in the LP position for a nice payday of up to the amount of VADER they initially added to the pool.
Add a whitelist to the pairs which qualify for IL protection.
#0 - CloudEllie
2021-11-12T15:53:26Z
I incorrectly withdrew this issue instead of #32 -- re-opening as warden states there's no whitelist in this case. My apologies.
#1 - SamSteinGG
2021-11-25T11:39:02Z
Predicting the price fluctuations of an asset is impossible. An attacker cannot create a pool arbitrarily as that is governed by a special whitelist function that is in turn voted on by the DAO.
#2 - alcueca
2021-12-11T07:07:12Z
As we saw in other issues, the creation of pools is permissionless
#3 - SamSteinGG
2021-12-16T12:14:07Z
@alcueca Again, there seems to be confusion as to the versions utilized. The submitter references the Vader V2 implementation in which pool creations are indeed permissioned (via the add supported token function) as the Vader pool factory is only relevant to the V1 implementation.
🌟 Selected for report: TomFrenchBlockchain
1619.075 USDC - $1,619.07
TomFrench
All liquidity deployed to one of VaderPool
or VaderPoolV2
will be locked permanently.
Both VaderRouter
and VaderRouterV2
make calls to VaderReserve
in order to pay out IL protection.
However VaderReserve
only allows a single router to claim IL protection on behalf of users.
It's unlikely that the intent is to deploy multiple reserves so there's no way for both VaderRouter
and VaderRouterV2
to pay out IL protection simultaneously.
This is a high severity issue as any LPs which are using the router which is not listed on VaderReserve
will be unable to remove liquidity as the call to the reserve will revert. Vader governance is unable to update the allowed router on VaderReserve
so all liquidity on either VaderPool
or VaderPoolV2
will be locked permanently.
Options:
#0 - SamSteinGG
2021-11-25T11:40:26Z
As the code indicates, only one of the two versioned instances of the AMM will be deployed and active at any given time rendering this exhibit incorrect.
#1 - alcueca
2021-12-11T07:04:18Z
Sorry @SamSteinGG, where does the code indicate that?
#2 - SamSteinGG
2021-12-16T12:12:57Z
Correction, this was clarified during the audit in the discord channel.
🌟 Selected for report: TomFrenchBlockchain
1619.075 USDC - $1,619.07
TomFrench
The VaderReserve
pays out IL from VaderPoolV2
LPs expressed in USDV with VADER (assuming a 1:1 exchange rate)
From the TwapOracle, it can be seen that VaderPoolV2
is intended to be deployed with USDV as its nativeAsset
:
All the pairs in VaderPoolV2
are then USDV:TKN where TKN is some other token, exactly which is irrelevant in this case.
VaderPoolV2
offers IL protection where any IL is refunded from the VaderReserve
The VaderReserve
holds a balance of VADER tokens which will be used to pay out this protection.
The IL experienced by the LP is calculated in VaderMath.calculateLoss
This is the core of the issue. From the variable names it's clear that this is written with the assumption that it is work on units of VADER whereas it is provided amounts in terms of USDV. Checking VaderRouterV2
we can see that we pass the output of this calculation directly to the reserve in order to claim VADER.
If an LP experienced 100 USDV worth of IL, instead of claiming the equivalent amount of VADER they would receive exactly 100 VADER as there's no handling of the exchange rate between USDV and VADER.
As VADER and USDV are very unlikely to trade at parity LPs could get sustantially more or less than the amount of IL they experienced.
Add handling for the conversion rate between VADER and USDV using a tamper resistant oracle (TwapOracle could potentially fulfil this role).
🌟 Selected for report: TomFrenchBlockchain
Also found by: cmichel
728.5837 USDC - $728.58
TomFrench
Total loss of funds which have been approved on VaderPoolV2
VaderPoolV2
allows minting of fungible LP tokens with the mintFungible
function
Crucially this function allows a user supplied value for from
which specifies where the nativeAsset
and foreignAsset
should be pulled from. An attacker can then provide any address which has a token approval onto VaderPoolV2
and mint themselves LP tokens - stealing the underlying tokens.
Remove from
argument and use msg.sender instead.
#0 - SamSteinGG
2021-11-25T12:40:48Z
pool is not meant to be interacted with
#1 - alcueca
2021-12-11T05:54:37Z
And how are you going to ensure that the pool is not interacted with, @SamSteinGG?
#2 - SamSteinGG
2021-12-16T11:33:28Z
@alcueca Upon second consideration, the functions relating to the minting of synths and wrapped tokens should have had the onlyRouter modifier and thus are indeed vulnerable. Issue accepted.
🌟 Selected for report: TomFrenchBlockchain
1619.075 USDC - $1,619.07
TomFrench
Frontrunners can extract up to 100% of the value provided by LPs to VaderPoolV2.
Users can provide liquidity to VaderPoolV2
through the mintFungible
function.
This allows users to provide tokens in any ratio and the pool will calculate what fraction of the value in the pool this makes up and mint the corresponding amount of liquidity units as an ERC20.
However there's no way for users to specify the minimum number of liquidity units they will accept. As the number of liquidity units minted is calculated from the current reserves, this allows frontrunners to manipulate the pool's reserves in such a way that the LP receives fewer liquidity units than they should. e.g. LP provides a lot of nativeAsset
but very little foreignAsset
, the frontrunner can then sell a lot of nativeAsset
to the pool to devalue it.
Once this is done the attacker returns the pool's reserves back to normal and pockets a fraction of the value which the LP meant to provide as liqudity.
Add a user-specified minimum amount of LP tokens to mint.
#0 - SamSteinGG
2021-12-27T10:10:10Z
Given that the codebase attempts to implement the Thorchain rust code in a one-to-one fashion, findings that relate to the mathematical accuracy of the codebase will only be accepted in one of the following cases:
While intuition is a valid ground for novel implementations, we have re-implemented a battle-tested implementation in another language and as such it is considered secure by design unless proven otherwise.
An additional note on this point is that any behaviour that the Thorchain model applies is expected to be the intended design in our protocol as well.
An important example is the slippage a user incurs on joining a particular LP pool for which there is no check as there can't be any. Enforcing an LP unit based check here is meaningless given that LP units represent a share that greatly fluctuates (1 unit of LP out of 100 units is different than 1 out of 1000, however, a slippage check for 100 units of DAI for example is valid).
🌟 Selected for report: pauliax
Also found by: TomFrenchBlockchain
728.5837 USDC - $728.58
TomFrench
LPs are subject to incurring unlimited slippage due to manipulation of the pool's reserves.
If we look at VaderRouterV2
we can see that the arguments amountAMin
and amountBMin
of the addLiquidity
function are unused.
We can compare this with Uniswap V2's router to see how these parameters are used
Uniswap uses the current reserves to check the equivalent value of amountADesired
in terms of tokenB
and then crucially checks that amountBOptimal >= amountBMin
. This is important as a frontrunner can manipulate the reserves of the pool right before the LP joins. By placing a minimum on the amount of tokenB
that is being contributed it places bounds on the relative values of the two tokens in the pool at the point at which the LP joins - otherwise an attacker could make tokenB
appear unrealistically valuable at the point at which an LP is joining with a lot of tokenA
.
However in Vader Protocol no such slippage protection exists. Whatever tokens the LP provides are added to the pool in whatever ratio as it doesn't require equal values of each token as Uniswap does.
In this situation an LP may supply a large amount of tokenA
and zero tokenB
, while an sandwicher frontruns them to sell a huge amount of tokenA
to the pool to tank its value. tokenA
is now treated as near worthless and the pool behaves as if the LP only provided a very small amount of value to the pool. The sandwicher can then backrun the LP addition to extract much of this value which should have belonged to the LP.
Reinstate these arguments to ensure that the pools relative reserves are within some user specified bounds at the point of joining.
#0 - SamSteinGG
2021-11-25T11:03:59Z
This is intended protocol behavior as the Thor chain CLP model does not have a ideal liquidity calculation.
#1 - alcueca
2021-12-11T05:23:10Z
The fact that the smart contracts are restricted to deployment on Thor Chain is not documented. The issue is valid.
#2 - alcueca
2021-12-11T05:43:54Z
Duplicate of #253
#3 - SamSteinGG
2021-12-16T11:24:31Z
Hello @alcueca , we believe you are confused. Are you familiar with the Thorchain CLP model? The model itself is what has this trait, it does not relate to the blockchain implementation itself. It is intended functionality as with its parent implementation.
🌟 Selected for report: TomFrenchBlockchain
Also found by: pauliax
218.5751 USDC - $218.58
TomFrench
Loss of ability of TwapOracle
to update should too many pools be added.
TwapOracle
allows an unlimited number of pairs to be added and has no way of removing pairs after the fact. At the same time TwapOracle.update
iterates through all pairs in order to update value for each pair.
TwapOracle.registerPair
is a permissioned function so that only the owner can add new pairs however should the owner account be compromised or not mindful of the number of pairs being added it is possible to put the oracle into a state in which it is unable to update. The oracle cannot recover from this state.
Possible options:
#0 - SamSteinGG
2021-11-25T11:14:47Z
The severity of the finding should be reduced as it relies on ill behavior from its owner which is a multisignature address.
#1 - alcueca
2021-12-11T07:17:16Z
The severity rating is valid since the signers might not be aware of the limitation, or the limitation might be reached by natural means.
#2 - SamSteinGG
2021-12-22T07:43:58Z
The TWAP oracle module has been completely removed and redesigned from scratch as LBTwap that is subject of the new audit.
🌟 Selected for report: TomFrenchBlockchain
485.7225 USDC - $485.72
TomFrench
Inability to call consult
on the TwapOracle and so calculate the exchange rate between USDV and VADER.
Should any of the Chainlink aggregators used by the TwapOracle becomes stuck in such a state that the check on L143-146 of TwapOracle.sol
consistently fails (through a botched upgrade, etc.) then the consult
function will always revert.
There is no method to update the address of the aggregator to use so the TwapOracle
will be irrecoverable.
Allow governance to update the aggregator for a pair (ideally with a timelock.)
#0 - SamSteinGG
2021-11-25T11:25:45Z
The scenario of a Chainlink oracle ceasing function is very unlikely and would cause widespread issues in the DeFi space as a whole.
#1 - alcueca
2021-12-12T05:31:19Z
I'm going to maintain the severity 2 rating despite the low probability of a Chainlink aggregator being permanently disabled. The risk exists, and in general third-party dependencies should be treated with respect in code and documentation.
#2 - SamSteinGG
2021-12-22T07:43:47Z
The TWAP oracle module has been completely removed and redesigned from scratch as LBTwap that is subject of the new audit.
🌟 Selected for report: TomFrenchBlockchain
485.7225 USDC - $485.72
TomFrench
Potentially frozen or purposefully inaccurate USDV:VADER price feed.
Only the owner of TwapOracle
can call update
on the oracle. Should the owner desire they could cease calling update
on the oracle for a period. Over this period the relative prices of VADER and USDC will vary.
After some period timeElapsed
the owner can call update
again. A TWAP is a lagging indicator and due to the owner ceasing to update the oracle so timeElapsed
will be very large, therefore we're averaging over a long period into the past resulting in a value which may not be representative of the current USDV:VADER exchange rate.
The owner can therefore selectively update the oracle so to result in prices which allow them to extract value from the system.
Remove the permissioning from TwapOracle.update
#0 - alcueca
2021-12-10T14:18:24Z
Duplicate of which other issue, @SamSteinGG?
#1 - SamSteinGG
2021-12-22T07:42:54Z
The TWAP oracle module has been completely removed and redesigned from scratch as LBTwap that is subject of the new audit.
🌟 Selected for report: TomFrenchBlockchain
TomFrench
Any unaccounted for tokens on VaderPoolV2
can be siphoned off by anyone
VaderPoolV2
has a rescue
function which allows any unaccounted for tokens to be recovered.
However there is no access control on this function which means than should any tokens be sent to VaderPoolV2
by accident they'll just be scooped up by flashbots rather than being recoverable by the original owner or Vader governance.
This also means that any rebasing tokens which are deposited into VaderPoolV2
will have any rebases lost rather than being recoverable by Vader governance.
Permission this function to only allow Vader governance to claim tokens.
#0 - SamSteinGG
2021-11-25T12:48:55Z
Duplicate #28
#1 - alcueca
2021-12-11T05:01:53Z
Not a duplicate, this issue correctly states that the function is vulnerable to front-running.
#2 - SamSteinGG
2021-12-16T11:29:38Z
The function is equivalent to the Uniswap V2 rescue function which is not classified as incorrect.
🌟 Selected for report: TomFrenchBlockchain
485.7225 USDC - $485.72
TomFrench
Potential DOS on swaps
BasePool and BasePoolV2 make use of a validateGas
modifier on swaps which checks that the user's gas price is below the value returned by _FAST_GAS_ORACLE
.
Should _FAST_GAS_ORACLE
be compromised to always return zero then all swaps will fail. There is no way to recover from this scenario.
Either remove GasThrottle.sol entirely or allow governance to turn it off
🌟 Selected for report: TomFrenchBlockchain
43.715 USDC - $43.72
TomFrench
Detailed description of the impact of this finding.
On L152 of TwapOracle
we multiply the response from the aggregator by 10^10. This is from an assumption that Chainlink will return a price with 8 decimals of precision so to convert it to an 18 decimal fixed point number we need to multiply it by 10^10.
Chainlink does normally use 8 decimals for crypto:fiat pairs however there is no guarantee that they will continue to do so. Should Chainlink deviate from this and this new aggregator be included in the TwapOracle
(due to the TwapOracle
owner not knowing this assumption which has been made at the point at which it adds a new pair) then it will start to calculate the usdv:vader
exchange rate incorrectly.
Query decimals from chainlink aggregators (potentially caching them on the TwapOracle
to save gas.)
Clearly document assumptions on Chainlink pricefeed response.
#0 - SamSteinGG
2021-11-25T11:26:31Z
The logic of the Chainlink oracles cannot be updated and as such the assumption with the current state of Chainlink stands.
#1 - alcueca
2021-12-11T05:13:50Z
There is no restriction on registerAggregator
to add aggregators only existing at the time of deployment, and therefore the issue is valid. You could just check there that the aggregator has 8 decimals. Issue is valid but downgraded to low severity because there aren't any USD Chainlinka aggregators with decimals other than 8 at the time.
#2 - SamSteinGG
2021-12-22T07:43:20Z
The TWAP oracle module has been completely removed and redesigned from scratch as LBTwap that is subject of the new audit.
🌟 Selected for report: TomFrenchBlockchain
68.651 USDC - $68.65
TomFrench
Gas consumption
Each claim performs a SSTORE to a fresh slot in order to mark a leaf as claimed. This results in each user paying 20k gas in order to invalidate a leaf whereas if many users shared the same slot they would pay 5k gas instead.
See Uniswaps implementation for inspiration:
https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol
Use bitmap for leaf invalidation
🌟 Selected for report: TomFrenchBlockchain
68.651 USDC - $68.65
TomFrench
Increased gas costs
In a number of places we use the SafeERC20
library to transfer tokens which are fixed to a known implementation e.g Vader in the Converter.
If we know that these tokens are properly implemented then we can do away with the extra cost from SafeERC20
and only use it when interacting with unknown tokens.
Remove use of SafeERC20
for known good tokens.
🌟 Selected for report: TomFrenchBlockchain
68.651 USDC - $68.65
TomFrench
Gas costs
TwapOracle
stores both VADER pairs and USDV pairs in the _pairs
array. This means that in consult
we need to filter for a particular token on every element. It would be simpler to instead have two arrays, one for each token, and then just choose one array to iterate over based on which token we're interested in.
Switch _pairs
to _usdvPairs
and _vaderPairs
#0 - SamSteinGG
2021-12-22T07:43:32Z
The TWAP oracle module has been completely removed and redesigned from scratch as LBTwap that is subject of the new audit.
🌟 Selected for report: TomFrenchBlockchain
18.5358 USDC - $18.54
TomFrench
Gas costs
The address of VADER is set once and never again the xVADER.sol
We can the safely make it immutable for gas savings.
Make vader immutable
🌟 Selected for report: TomFrenchBlockchain
68.651 USDC - $68.65
TomFrench
VADER and USDV can be made immutable in the TwapOracle, saving SLOAD costs
TwapOracle
is to be deployed after VaderPoolV2
VaderPoolV2
stores its native asset in an immutable variable.
Therefore the address of VADER
and USDV
are known at the time TwapOracle
is deployed. We can then supply these at deploy time and store them in an immutable variable.
Make storage of VADER
and USDV
addresses in TwapOracle
immutable.
#0 - SamSteinGG
2021-12-22T07:42:44Z
The TWAP oracle module has been completely removed and redesigned from scratch as LBTwap that is subject of the new audit.
🌟 Selected for report: TomFrenchBlockchain
68.651 USDC - $68.65
TomFrench
Gas costs on deploying LPTokens
The address of VaderPoolV2 is stored implicitly as the owner of the LPWrappet contract.
As we are using the Ownable
contract which allows transfering ownership this involves an SLOAD to get VaderPoolV2
's address. As we never are going to transfer ownership of this contract we could store it in an immutable variable which will save gas costs.
Remove Ownable
dependency and store address in immutable variable.
🌟 Selected for report: TomFrenchBlockchain
68.651 USDC - $68.65
TomFrench
Gas costs
On every transfer of VADER, it is checked whether the transfer is from the zero address and if so that the transfer satisfies the max supply condition.
This is only relevant for when minting tokens so this check can be moved to the createEmission
function to reduce costs of transfering tokens.
Listed above.
🌟 Selected for report: TomFrenchBlockchain
68.651 USDC - $68.65
TomFrench
Higher gas costs for migrating from fungible to NFT liquidity
VaderProtocol allows users to provider fungible liquidity or NFT based liquidity (VaderPoolV2 allows one or the other or both on a pair). NFT based liquidity provided IL protection and so is more desirable.
We then expect that for pairs which start with fungible liquidity enabled and NFT based liquidity enabled later that many users will want to migrate from a fungible position to an NFT position.
There's currently no way to do this other than removing liquidity and re-adding liquidity which opens users up to slippage as well as high gas costs. Instead the liquidity units from the fungible LP position could just be transferred over to an NFT position at current prices.
Kinda a feature request but listed as gas optimisation this will save users a ton of gas.
Listed above.
🌟 Selected for report: TomFrenchBlockchain
68.651 USDC - $68.65
TomFrench
Gas costs
When burning ERC20 LP tokens VaderPoolV2
first transfers them from the user to itself and then burns them.
As LPToken
trusts VaderPoolV2
a cheaper way to do this would be to burn them directly from the user's balance. This avoids the cost of approving VaderPoolV2
to take the tokens and transferring them
Allow VaderPoolV2
to directly burn LP tokens from users accounts and skip the transfer.
#0 - SamSteinGG
2021-12-27T10:06:15Z
We understand the gas optimization here but we are going to keep it as it is for standartization.