# Contract scan report

> **Automated scan, not an audit. Findings may be false positives; absence of findings does not mean the code is safe.**

- Scan id: `7068b4ee-bedc-425f-8b12-cf72712ed18e`
- Status: **ok**
- Input: source, 1 file(s), 26 nSLOC, sha256 `765d7f5132127401...`
- Compiler: solc 0.8.37
- Duration: 0.9 s

## Summary

| High | Medium | Low | Info |
|---|---|---|---|
| 1 | 2 | 1 | 0 |

## Findings

### F-001 [HIGH] ERC4626-style vault without virtual shares (first-depositor inflation)

`erc4626-inflation` (custom) · confidence medium · `erc4626_inflation.sol:22`

```solidity
    function convertToShares(uint256 assets) public view returns (uint256) {
        uint256 supply = totalSupply;
        return supply == 0 ? assets : assets * supply / totalAssets();
    }
```

SimpleVault.convertToShares(uint256) (erc4626_inflation.sol#22-25) converts assets to shares without virtual shares/offset (vault SimpleVault (erc4626_inflation.sol#9-33)) while totalAssets() uses the token balance

**Why it matters:** The vault converts assets to shares with a plain ratio of totalSupply to totalAssets(), where totalAssets() comes from the vault's token balance, and has no virtual shares, virtual assets or decimals offset. The first depositor can mint 1 wei of shares and then donate a large amount of the asset directly to the vault, inflating the share price so that later deposits round down to zero (or very few) shares; the attacker then redeems and captures the victims' deposits. This is the classic ERC4626 inflation (donation) attack.

**Fix:** Use OpenZeppelin ERC4626 v4.9+ (virtual shares and assets via _decimalsOffset), add a virtual offset to the conversion math, track deposited assets internally instead of using balanceOf, or seed the vault with dead shares at deployment.

### F-002 [MEDIUM] ERC20 transfer/transferFrom/approve called without SafeERC20

`erc20-unsafe-transfer` (custom) · confidence medium · `erc4626_inflation.sol:29`

```solidity
        require(asset.transferFrom(msg.sender, address(this), assets), "transfer");
```

SimpleVault.deposit(uint256,address) (erc4626_inflation.sol#27-32) checks the return value of a raw ERC20 `transferFrom` (reverts for tokens that return nothing, e.g. USDT): require(bool,string)(asset.transferFrom(msg.sender,address(this),assets),transfer) (erc4626_inflation.sol#29)

**Why it matters:** The contract calls transfer, transferFrom or approve directly on an ERC20 token instead of going through SafeERC20 (or an equivalent low-level wrapper). When the boolean return value is ignored, a token that signals failure by returning false (rather than reverting) lets the call 'succeed' silently, so balances are credited for tokens that never moved. When the return value is checked through the interface, tokens that return nothing at all (USDT, BNB, OMG and others) make the ABI decoder revert, so every call fails and funds can be locked. Severity is high when the return value is ignored and medium when it is checked.

**Fix:** Use OpenZeppelin SafeERC20 (safeTransfer, safeTransferFrom, forceApprove) or Solady SafeTransferLib for every interaction with an arbitrary ERC20 token.

### F-003 [MEDIUM] Reentrancy vulnerabilities

`reentrancy-no-eth` (slither) · confidence medium · `erc4626_inflation.sol:29`

```solidity
        require(asset.transferFrom(msg.sender, address(this), assets), "transfer");
```

Reentrancy in SimpleVault.deposit(uint256,address) (erc4626_inflation.sol#27-32):
	External calls:
	- require(bool,string)(asset.transferFrom(msg.sender,address(this),assets),transfer) (erc4626_inflation.sol#29)
	State variables written after the call(s):
	- totalSupply += shares (erc4626_inflation.sol#30)
	SimpleVault.totalSupply (erc4626_inflation.sol#11) can be used in cross function reentrancies:
	- SimpleVault.convertToShares(uint256) (erc4626_inflation.sol#22-25)
	- SimpleVault.deposit(uint256,address) (erc4626_inflation.sol#27-32)
	- SimpleVault.totalSupply (erc4626_inflation.sol#11)

**Why it matters:** 
Detection of the [reentrancy bug](https://github.com/trailofbits/not-so-smart-contracts/tree/master/reentrancy).
Do not report reentrancies that involve Ether (see `reentrancy-eth`).

**Fix:** Apply the [`check-effects-interactions` pattern](http://solidity.readthedocs.io/en/v0.4.21/security-considerations.html#re-entrancy).

### F-004 [LOW] Dangerous strict equalities

`incorrect-equality` (slither) · confidence high · `erc4626_inflation.sol:24`

```solidity
        return supply == 0 ? assets : assets * supply / totalAssets();
```

SimpleVault.convertToShares(uint256) (erc4626_inflation.sol#22-25) uses a dangerous strict equality:
	- supply == 0 (erc4626_inflation.sol#24)

**Why it matters:** Use of strict equalities that can be easily manipulated by an attacker.

**Fix:** Don't use strict equality to determine if an account has enough Ether or tokens.
