yAxis contest - jonah1005's results

The trusted #DeFi platform to earn reliable returns on digital assets.

General Information

Platform: Code4rena

Start Date: 09/09/2021

Pot Size: $60,000 USDC

Total HM: 24

Participants: 12

Period: 7 days

Judge: GalloDaSballo

Total Solo HM: 14

Id: 30

League: ETH

yAxis

Findings Distribution

Researcher Performance

Rank: 2/12

Findings: 12

Award: $8,039.91

🌟 Selected for report: 10

🚀 Solo Findings: 3

Findings Information

🌟 Selected for report: jonah1005

Also found by: 0xsanson

Labels

bug
3 (High Risk)
sponsor acknowledged
sponsor confirmed

Awards

209.319 YAXIS - $816.34

External Links

Handle

jonah1005

Vulnerability details

Impact

In controller.sol's function setCap, the contract wrongly handles _vaultDetails[_vault].balance. While the balance should be decreased by the difference of strategies balance, it subtracts the remaining balance of the strategy. Controller.sol#L262-L278 _vaultDetails[_vault].balance = _vaultDetails[_vault].balance.sub(_balance);

This would result in vaultDetails[_vault].balance being far smaller than the strategy's value. A user would trigger the assertion at Contreller.sol#475 and the fund would be locked in the strategy.

Though setCap is a permission function that only the operator can call, it's likely to be called and the fund would be locked in the contract. I consider this a high severity issue.

Proof of Concept

We can trigger the issue by setting the cap 1 wei smaller than the strategy's balance.

strategy_balance = strategy.functions.balanceOf().call()
controller.functions.setCap(vault.address, strategy.address, strategy_balance - 1, dai.address).transact()

## this would be reverted
vault.functions.withdrawAll(dai.address).transact()

Controller.sol#L262-L278

Tools Used

Hardhat

I believe the dev would spot the issue in the test if _vaultDetails[_vault].balance is a public variable.

One possile fix is to subtract the difference of the balance.

uint previousBalance = IStrategy(_strategy).balanceOf();
_vaultDetails[_vault].balance.sub(previousBalance.sub(_amount));

#0 - transferAndCall

2021-09-12T15:39:34Z

Please review https://github.com/code-423n4/2021-09-yaxis/pull/1 to verify resolution.

#1 - GalloDaSballo

2021-10-12T23:31:17Z

High risk vulnerability due to incorrect logic which can impact protocol functionality

Sponsor has mitigated

Findings Information

🌟 Selected for report: jonah1005

Also found by: 0xRajeev, hrkrshnn

Labels

bug
3 (High Risk)
sponsor acknowledged
sponsor confirmed

Awards

125.5914 YAXIS - $489.81

External Links

Handle

jonah1005

Vulnerability details

Impact

There's no safety check in Manager.sol addToken. There are two possible cases that might happen.

  1. One token being added twice in a Vault. Token would be counted doubly in the vault. Ref: Vault.sol#L293-L303. There would be two item in the array when querying manager.getTokens(address(this));.

  2. A token first being added to two vaults. The value calculation of the first vault would be broken. As vaults[_token] = _vault; would point to the other vault.

Permission keys should always be treated cautiously. However, calling the same initialize function twice should not be able to destroy the vault. Also, as the protocol develops, there's likely that one token is supported in two vaults. The DAO may mistakenly add the same token twice. I consider this a high-risk issue.

Proof of Concept

Adding same token twice would not raise any error here.

manager.functions.addToken(vault.address, dai.address).transact() manager.functions.addToken(vault.address, dai.address).transact()

Tools Used

Hardhat

I recommend to add two checks

require(vaults[_token] == address(0));
bool notFound = True;
for(uint256 i; i < tokens[_vault].length; i++) {
    if (tokens[_vault] == _token) {
        notFound = False;
    }
}
require(notFound, "duplicate token");

#0 - transferAndCall

2021-09-12T16:15:56Z

Please review https://github.com/code-423n4/2021-09-yaxis/pull/2 to verify resolution.

#1 - GalloDaSballo

2021-10-13T23:23:20Z

Lack of check for duplicates can cause undefined behaviour, sponsor mitigated by adding a require check

Findings Information

🌟 Selected for report: jonah1005

Also found by: 0xRajeev, WatchPug

Labels

bug
3 (High Risk)
sponsor acknowledged

Awards

125.5914 YAXIS - $489.81

External Links

Handle

jonah1005

Vulnerability details

Impact

When a user tries to withdraw the token from the vault, the vault would withdraw the token from the controller if there's insufficient liquidity in the vault. However, the controller does not raise an error when there's insufficient liquidity in the controller/ strategies. The user would lose his shares while getting nothing.

An MEV searcher could apply this attack on any withdrawal. When an attacker found an unconfirmed tx that tries to withdraw 1M dai, he can do such sandwich attack.

  1. Deposits USDC into the vault.
  2. Withdraw all dai left in the vault/controller/strategy.
  3. Place the vitims tx here. The victim would get zero dai while burning 1 M share. This would pump the share price.
  4. Withdraw all liquidity.

All users would be vulnerable to MEV attackers. I consider this is a high-risk issue.

Proof of Concept

Here's web3.py script to reproduce the issue.

deposit_amount = 100000 * 10**18
user = w3.eth.accounts[0]
get_token(dai, user, deposit_amount)
dai.functions.approve(vault.address, deposit_amount + margin_deposit).transact()
vault.functions.deposit(dai.address, deposit_amount).transact()
vault.functions.withdrawAll(usdt.address).transact()

#
print("usdt amount: ", usdt.functions.balanceOf(user).call())

Tools Used

None

There are two issues involved. First, users pay the slippage when they try to withdraw. I do not find this fair. Users have to pay extra gas to withdraw liquidity from strategy, convert the token, and still paying the slippage. I recommend writing a view function for the frontend to display how much slippage the user has to pay. Controler.sol#L448-L479

Second, the controller does not revert the transaction there's insufficient liquidity. Controller.sol#L577-L622 Recommend to revert the transaction when _amount is not equal to zero after the loop finish.

#0 - GalloDaSballo

2021-10-14T13:58:01Z

Agree with warden finding, this shows the path for an attack that is based on the Vault treating all tokens equally Since the finding shows a specific attack, the finding is unique

Recommend the sponsor mitigates Single Sided Exposure risks to avoid this attack

Findings Information

🌟 Selected for report: jonah1005

Also found by: cmichel, itsmeSTYJ

Labels

bug
3 (High Risk)
sponsor acknowledged

Awards

125.5914 YAXIS - $489.81

External Links

Handle

jonah1005

Vulnerability details

Impact

The v3 vault treats all valid tokens exactly the same. Depositing 1M DAI would get the same share as depositing 1M USDT. User can withdraw their share in another token. Though there's withdrawalProtectionFee (0.1 percent), the vault is still a no slippage stable coin exchange.

Also, I notice that 3crv_token is added to the vault in the test. Treating 3crv_token and all other stable coins the same would make the vault vulnerable to flashloan attack. 3crv_token is an lp token and at the point of writing, the price of it is 1.01. The arbitrage space is about 0.8 percent and makes the vault vulnerable to flashloan attacks.

Though the team may not add crv_token and dai to the same vault, its design makes the vault vulnerable. Strategies need to be designed with super caution or the vault would be vulnerable to attackers.

Given the possibility of flashloan attack, I consider this a high-risk issue.

Proof of Concept

The issue locates at the deposit function. Vault.sol#L147-L180

The share is mint according to the calculation here

            _shares = _shares.add(_amount);

The share is burned at Vault.sol#L217

uint256 _amount = (balance().mul(_shares)).div(totalSupply());

Here's a sample exploit in web3.py.

deposit_amount = 100000 * 10**6
user = w3.eth.accounts[0]
get_token(usdt, user, deposit_amount)
usdt.functions.approve(vault.address, deposit_amount).transact()
vault.functions.deposit(usdt.address, deposit_amount).transact()
vault.functions.withdrawAll(t3crv.address).transact()
# user can remove liquiditiy and get the profit.

Tools Used

Hardhat

Given the protocols' scenario, I feel like we can take iearn token's architect as a Ref. yDdai

yDai handles multiple tokens (cDai/ aDai/ dydx/ fulcrum). Though four tokens are pretty much the same, the contract still needs to calculate the price of each token.

Or, create a vault for each token might be an easier quick fix.

#0 - transferAndCall

2021-09-12T15:44:35Z

The design of the v3 vaults is to intentionally assume that all allowed tokens are of equal value. I do not see us enabling the 3CRV token in our Vault test, though if we did, that doesn't mean we would in reality. Using a separate vault per token is an architecture we want to avoid.

#1 - GalloDaSballo

2021-10-13T15:50:32Z

Anecdotal example from warden makes sense.

Assuming that 3CRV is worth the same as a stablecoin is in principle very similar to assuming that a swap between each stable on curve will yield a balanced trade

This reminds me of the Single Sided Exposure Exploit that Yearn Suffered, and would recommend mitigating by checking the virtual_price on the 3CRV token

#2 - GalloDaSballo

2021-10-13T15:50:52Z

TODO: Review and check duplicates, need to read yaxis vault code and use cases before can judge this

#3 - GalloDaSballo

2021-10-14T14:33:36Z

After reviewing the code and the submissions, I have to agree that the vault creates arbitrage opportunities, since it heavily relies on 3CRV you may want to use it's virtual_price as a way to mitigate potential exploits, alternatively you can roll your own pricing oracle solution

Not mitigating this opportunity means that an attacker will exploit it at the detriment of the depositors

Findings Information

🌟 Selected for report: jonah1005

Labels

bug
3 (High Risk)
sponsor acknowledged

Awards

465.1532 YAXIS - $1,814.10

External Links

Handle

jonah1005

Vulnerability details

Impact

For a dai vault that pairs with NativeStrategyCurve3Crv, every time earn() is called, shareholders would lose money. (about 2%)

There're two issues involved. The Vault contract and the controller contract doesn't handle the price difference between the want token and other tokens.

Vault.sol#L293 When a vault calculates its value, it sums up all tokens balance. Controller.sol#L410-L436 However, when the controller calculates vaults' value, it only adds the amount of strategy.want it received. (in this case, it's t3crv).

Under the current design, users who deposit dai to the vault would not get yield. Instead, they would keep losing money. I consider this a high-risk issue

Proof of Concept

I trigger the bug with the following web3.py script:

previous_price = vault.functions.getPricePerFullShare().call()
vault.functions.available(dai.address).call()
vault.functions.earn(dai.address, strategy.address).transact()
current_price = vault.functions.getPricePerFullShare().call()
print(previous_price)
print(current_price)

Tools Used

Hardhat

The protocol should decide what the balance sheet in each contract stands for and make it consistent in all cases. Take, for example, if _vaultDetails[_vault].balance; stands for the amount of 'want' token the vault owns, there shouldn't exist two different want in all the strategies the vault has. Also, when the vault queries controllers function balanceOf(), they should always multiply it by the price.

#0 - gpersoon

2021-09-30T11:50:57Z

I think this is also related to the underlying problem that all coins are assumed to have the same value. See also #2, #8 and #158

#1 - GalloDaSballo

2021-10-14T15:53:10Z

Agree with wardens finding and acknowledge it's similitude with other issues

Personally this is a different vulnerability that can be solved by solving the same underlying problem

Marking this as unique finding as it's a specific exploit the protocol could face

Findings Information

🌟 Selected for report: cmichel

Also found by: hickuphh3, jonah1005

Labels

bug
duplicate
3 (High Risk)

Awards

125.5914 YAXIS - $489.81

External Links

Handle

jonah1005

Vulnerability details

Impact

The vault does not normalize decimals when a user withdraws the token. When a user has 100e18 shares, he can withdraw all usdc/ usdt from the token.

The liquidity of USDC/USDC would be drained. I consider this is a high-risk issue.

Proof of Concept

Vault.sol#L232-L261

This is the web3.py script to drain all usdt from the vault.

usdt_balance = usdt.functions.balanceOf(vault.address).call()
print('previous usdt:', usdt_balance)
# We deposit some margin dai to drain all liquidity.
deposit_amount = usdt_balance + usdt_balance
dai.functions.approve(vault.address, deposit_amount).transact()
vault.functions.deposit(dai.address, deposit_amount).transact()
print('amount of share:', vault.functions.balanceOf(user).call())
vault.functions.withdrawAll(usdt.address).transact()

## usdt would left zero
print('usdt left:', usdt.functions.balanceOf(vault.address).call())

Tools Used

None

Normalize decimals on withdrawing.

#0 - gpersoon

2021-09-30T13:01:36Z

Seems duplicate of #73

#1 - GalloDaSballo

2021-10-14T16:52:49Z

Duplicate of #131

Findings Information

🌟 Selected for report: jonah1005

Labels

bug
3 (High Risk)
sponsor acknowledged
sponsor confirmed

Awards

465.1532 YAXIS - $1,814.10

External Links

Handle

jonah1005

Vulnerability details

removeToken would break the vault.

Impact

There's no safety check in Manager.sol's removeToken. Manager.sol#L454-L487

  1. The token would be locked in the original vault. Given the current design, the vault would keep a ratio of total amount to save the gas. Once the token is removed at manager contract, these token would lost.
  2. Controller's balanceOf would no longer reflects the real value. Controller.sol#L488-L495 While _vaultDetails[msg.sender].balance; remains the same, user can nolonger withdraw those amount.
  3. Share price in the vault would decrease drastically. The share price is calculated as totalValue / totalSupply Vault.sol#L217. While the totalSupply of the share remains the same, the total balance has drastically decreased.

Calling removeToken way would almost break the whole protocol if the vault has already started. I consider this is a high-risk issue.

Proof of Concept

We can see how the vault would be affected with below web3.py script.

print(vault.functions.balanceOfThis().call())
print(vault.functions.totalSupply().call())
manager.functions.removeToken(vault.address, dai.address).transact()
print(vault.functions.balanceOfThis().call())
print(vault.functions.totalSupply().call())

output

100000000000000000000000 100000000000000000000000 0 100000000000000000000000

Tools Used

Hardhat

Remove tokens from a vault would be a really critical job. I recommend the team cover all possible cases and check all components' states (all vault/ strategy/ controller's state) in the test.

Some steps that I try to come up with that is required to remove TokenA from a vault.

  1. Withdraw all tokenA from all strategies (and handle it correctly in the controller).
  2. Withdraw all tokenA from the vault.
  3. Convert all tokenA that's collected in the previous step into tokenB.
  4. Transfer tokenB to the vault and compensate the transaction fee/slippage cost to the vault.

#0 - transferAndCall

2021-09-12T17:25:11Z

Removing a token is understood as a critical (and possibly nuclear) operation within this architecture. We knew we would have to first withdraw all of the identified token from strategies, but what was missed was converting that token to another (without withdrawing, as that would be too much centralization).

Proposed method of resolution:

  • Withdraw all tokenA from all strategies (this sends it to the vault)
  • Swap tokenA for tokenB in the vault (requires implementing a new function to be called by the strategist)
  • Remove the token via the Manager function

#1 - transferAndCall

2021-09-12T19:23:35Z

Please review https://github.com/code-423n4/2021-09-yaxis/pull/5 to check resolution.

#2 - GalloDaSballo

2021-10-14T16:27:15Z

Removing a token can cause accounting errors, stuck funds and break some of the functionality

Adding additional checks to prevent removing the token until all tokens have been migrated may be the simplest path forward

Sponsor has mitigated by adding custom functionality, however it is up to them to enforce that the vault has no token left before removing it, adding a couple extra checks may provide a guarantee against admin privileged abuses

Findings Information

🌟 Selected for report: WatchPug

Also found by: cmichel, jonah1005

Labels

bug
duplicate
3 (High Risk)
sponsor acknowledged

Awards

125.5914 YAXIS - $489.81

External Links

Handle

jonah1005

Vulnerability details

Impact

The Controller's function withdraw(address _token, uint256 _amount) should return whatever amount of the token user/vault asks. However, it tries to withdraw strategy.want token and convert it.

Take for example, when a user/vault calls withdraw(dai, 100), the controller should transfer 100 dai to the user/vault; instead, it withdraw 100 t3crv from the strategy, convert it to dai, and transfer the converted amount to the user. In this case, the user would get about 101 dai. (1 t3crv = 1.01 dai).

1 percent of arbitrage space is enough to cause painful results. Also, the arbitrage space really depends on the strategy. Strategy should be able to have whatever want token, e.g., ETH, CRV,.... Vault users would definetly lose their money if the price not being handled properly.

I consider this a high-risk issue.

Proof of Concept

Controller.sol#L446-L477

We can trigger the bug with following web3.py script.

  1. Two users deposit to the vault.
  2. Admin call earn
  3. Two users withdraw all from the vault.
deposit_amount = 100000 * 10**18
user = w3.eth.accounts[0]
get_token(dai, user, deposit_amount)
dai.functions.approve(vault.address, deposit_amount).transact()
vault.functions.deposit(dai.address, deposit_amount).transact()

deposit_amount = 100000 * 10**18
user2 = w3.eth.accounts[1]
get_token(dai, user2, deposit_amount)
dai.functions.approve(vault.address, deposit_amount).transact({'from': user2})
vault.functions.deposit(dai.address, deposit_amount).transact({'from': user2})
vault.functions.earn(dai.address, strategy.address).transact()
vault.functions.withdrawAll(dai.address).transact({'from': user})
## raise error here
vault.functions.withdrawAll(dai.address).transact({'from': user2})

Since the first user gets more tokens than he should have, user2 would not be able to withdraw all the shares.

Tools Used

None

#0 - gpersoon

2021-09-30T11:47:21Z

I think this is related to the underlying problem that all coins are assumed to have the same value. See also #2 and #158

#1 - GalloDaSballo

2021-10-14T16:48:36Z

Duplicate of #77

Findings Information

🌟 Selected for report: cmichel

Also found by: defsec, jonah1005, tensors

Labels

bug
duplicate
2 (Med Risk)
sponsor acknowledged
sponsor confirmed

Awards

37.6774 YAXIS - $146.94

External Links

Handle

jonah1005

Vulnerability details

manager does not use safe transfer

Impact

Manager contract does not use safeTransfer in function recoverToken. Mansger.sol#L442-L452 Manager contract would not be able to transfer non-standard ERC20 tokens.

Given the manager is not designed to hold the token, I consider this a low-risk issue.

Proof of Concept

Mansger.sol#L442-L452

Tools Used

None

I recommend using safeERC20 as other contracts do.

#0 - transferAndCall

2021-09-12T16:29:51Z

Please review https://github.com/code-423n4/2021-09-yaxis/pull/3 and verify resolution.

#1 - GalloDaSballo

2021-10-13T23:04:39Z

Duplicate of #114

Raising to Med severity

Findings Information

🌟 Selected for report: jonah1005

Labels

bug
2 (Med Risk)
sponsor acknowledged

Awards

139.546 YAXIS - $544.23

External Links

Handle

jonah1005

Vulnerability details

Impact

The protocol frequently interacts with crv a lot. However, the contract doesn't specify the minimum return amount. Given the fact that there's a lot of MEV searchers, calling swap without specifying the minimum return amount really puts user funds in danger.

For example, controller's withdrawAll is designed to transfer all the funds in a strategy.Controller.sol#L360 The arbitrage space is enough for a searcher to sandwich this trade.

Proof of Concept

Mansger.sol#L442-L452

Controller.sol#L273

Tools Used

None

Always calculates an estimated return when calling to crv.

#0 - GalloDaSballo

2021-10-14T00:31:14Z

Agree with finding, agree with severity as this allows to "leak value"

Findings Information

🌟 Selected for report: jonah1005

Labels

bug
1 (Low Risk)
sponsor acknowledged
sponsor confirmed

Awards

46.5153 YAXIS - $181.41

External Links

Handle

jonah1005

Vulnerability details

Impact

There's no safety check in controller's addStrategy. When the same strategy is added to a vault twice, the protocol breakdowns in several ways.

  1. Removing that strategy would always raise errors.
  2. _vaultDetails[_vault].balances[_strategy] would not track strategy's balance correctly; getBestStrategyWithdraw would have a wrong answer and makes withdrawing from the strategy to raise error in certain scenarios.

I consider this a low-risk issue.

Proof of Concept

This is the web3.py script:

controller.functions.addStrategy(vault.address, strategy.address, cap, 0).transact()
controller.functions.addStrategy(vault.address, strategy.address, cap, 0).transact()

# would not be able to removestrategy
controller.functions.removeStrategy(vault.address, strategy.address, 0).transact()

Tools Used

Hardhat

The controller should raise an error if the strategy has been added to the protocol(any vault). As adding the same strategy to two different vaults would have worse results, the controller can maintain a map to record each strategy's status.

#0 - Haz077

2021-09-20T19:12:43Z

Edits are added in code-423n4/2021-09-yaxis#10

#1 - GalloDaSballo

2021-10-14T00:15:25Z

Sponsor agreed and mitigated, ensuring that a strategy is added only once avoids undefined logic errors

Findings Information

🌟 Selected for report: jonah1005

Also found by: pauliax

Labels

bug
1 (Low Risk)

Awards

20.9319 YAXIS - $81.63

External Links

Handle

jonah1005

Vulnerability details

vault cap's at totalSupply would behave unexpectedly

Impact

When a vault imposes a deposit cap check, it checks totalSupply instead of balance. This is under the assumption that the share price would be (close) 1. However, the price of shares would deviate from 1 after the vault's launch. Also, early vault users can pump share price by sending tokens to the vault.

Proof of Concept

This is the web3.py script to pump share price

deposit_amount = 100000 * 10**18
margin_deposit = 100
user = w3.eth.accounts[0]
get_token(dai, user, deposit_amount + margin_deposit)
dai.functions.approve(vault.address, deposit_amount + margin_deposit).transact()
vault.functions.deposit(dai.address, margin_deposit).transact()
dai.functions.transfer(vault.address, deposit_amount,).transact()
share_price = vault.functions.getPricePerFullShare().call()
print(share_price)

After pumping the share price, normal user can deposit beyond the vault's cap.

vault.functions.setTotalDepositCap(100*10**18).transact()
deposit_amount = 100000 * 10**18
user = w3.eth.accounts[0]
get_token(dai, user, deposit_amount)
dai.functions.approve(vault.address, deposit_amount ).transact()
vault.functions.deposit(dai.address, deposit_amount).transact()

Tools Used

Hardhat

Checks balance() instead of totalSupply

#0 - Haz077

2021-09-30T17:47:11Z

Kinda same as #26, so I chose #26 because it's more detailed and both issues are from the same handle anyway.

#1 - GalloDaSballo

2021-10-14T00:21:14Z

The warden is claiming that the vault is not enforcing depositCaps because the require check is checking for totalSupply instead of balance: https://github.com/code-423n4/2021-09-yaxis/blob/7d253085b0109f48164362aa4dfecd46685627b4/contracts/v3/Vault.sol#L200

This is a valid (and unique) finding

Findings Information

🌟 Selected for report: jonah1005

Labels

bug
1 (Low Risk)
sponsor acknowledged

Awards

46.5153 YAXIS - $181.41

External Links

Handle

jonah1005

Vulnerability details

Impact

When a user deposit tokens to the vault, the amount of share is calculated as _amount = (_amount.mul(totalSupply())).div(_balance); Vault.sol#L192. The first depositor can hijack the vault by depositing 1 wei of the token and pump the price share by sending extra token. Any new user that deposits to the vault would get zero share as totalSupply() / balance() would be rounded to zero.

Steps to exploit:

  1. deposits 1 wei dai and gets 1 share.
  2. sends 100 dai (100 * 10 ** 18) into the vault

Since permissionless user would no be able to add new vault into the protocol, I consider this a low-risk issue.

Proof of Concept

Vault.sol#L192.

This is the web3.py script to pump share price

deposit_amount = 100000 * 10**18
margin_deposit = 1
user = w3.eth.accounts[0]
get_token(dai, user, deposit_amount + margin_deposit)
dai.functions.approve(vault.address, deposit_amount + margin_deposit).transact()
vault.functions.deposit(dai.address, margin_deposit).transact()
dai.functions.transfer(vault.address, deposit_amount,).transact()
share_price = vault.functions.getPricePerFullShare().call()
print(share_price)

Tools Used

None

Common mitigation of this attack is to permanently lock some lp tokens at initialization. Ref: UniswapV2Pair.sol#L110-L131

#0 - GalloDaSballo

2021-10-13T23:06:44Z

Agree with griefing potential, would recommend making initial deposits of at least 1 * 10 ** DECIMALS of the vault token to avoid that scenario (or to make it expensive to perform)

Findings Information

🌟 Selected for report: cmichel

Also found by: hickuphh3, jonah1005, pauliax

Labels

bug
duplicate
G (Gas Optimization)
sponsor acknowledged
sponsor confirmed

Awards

2.7432 YAXIS - $10.70

External Links

Handle

jonah1005

Vulnerability details

Impact

[Vault.sol#L172] (https://github.com/code-423n4/2021-09-yaxis/blob/main/contracts/v3/Vault.sol#L172) _shares = _shares.add(_amount); _shares is always 0 before the operation

Proof of Concept

[Vault.sol#L172] (https://github.com/code-423n4/2021-09-yaxis/blob/main/contracts/v3/Vault.sol#L172)

Tools Used

_shares = _amount

#0 - transferAndCall

2021-09-12T16:34:03Z

Please review https://github.com/code-423n4/2021-09-yaxis/pull/4 to verify resolution.

#1 - GalloDaSballo

2021-10-12T22:26:16Z

Duplicate of #118

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter