Oddbean new post about | logout

Notes by CryptoAudit | export

 Hi, I just got acquainted with nostr.  Are there people interested in reading about defi and smart contracts and the bugs that occur in it, as well as identifying scam projects in that space, I think there are most people interested in Bitcoin here.
Thanks  
 The before-after pattern is used to check the vault balance before and after the deposit, to determine exactly how much the vault has received.

While the first deposit is ongoing, what will happen if we can make the second deposit?

For example, suppose you deposit 10 tokens, but before you get to the 'after' you deposit another 10 tokens.

The second deposit will see an amount of 10 in the before-after as nothing else occurred here. However, the first deposit sees the increase of its own 10 tokens but also those 10 tokens of the second deposit. The vault therefore thinks it received another 20 tokens.

This mistake leads to reentrancy.

```
function depositFor(address token, uint256 _amount, address user) public{
  ...
  uint256 _pool = balance();
  IERC20(token).safeTransferFrrom(msg.sender, address(this), _amount);
  earn();
  uint256 _after = balance();
  ...  
}
```

You can easily write a rule for this pattern with the @semgrep tool and find all similar cases. 
 In this contract, attacker by buying 112 USDT and then buying 101 TCR using USDT and selling 101 TCR, the hacker obtained 600K USDT.

https://etherscan.io/tx/0x81e9918e248d14d78ff7b697355fd9f456c6d7881486ed14fdfb69db16631154
https://etherscan.io/token/0xe38b72d6595fd3885d1d2f770aa23e94757f91a1#code#L159

The root cause of this problem is in the burnFrom function. This implementation allows any account A to burn tokens from any other account B if account A approves that number of tokens to B.

Hacker Approved huge amount of tokens to Uniswap pool. In the next step, he buys 101 TCR. Then he uses this bug to burn TCR owned by the pool and as a result the price of TCR increases. In the end, he sells the TCRs he bought.

```
require(_allowance[msg.sender][from] >= amount, ERROR_ATL);
```

You can easily write a rule for this pattern with the @semgrep tool and find all similar cases. 
 Sometimes a smart contract uses several oracle price feeds to track the prices of several assets.
Since different feeds can have different heartbeats, it is wrong to assume that the same time interval heartbeat can be used as a staleness check.

```
(, rawPrice, , updatedAt, ) = IChainlink(chainlink).latestRoundData();

(, int256 USDCPrice,, uint256 USDCUpdatedAt,) = IChainlink(USDCSource).latestRoundData();

require(block.timestamp - updatedAt <= heartbeatInterval,"ORACLE_HEARTBEAT_FAILED");

require(block.timestamp - USDCUpdatedAt <= heartbeatInterval, "USDC_ORACLE_HEARTBEAT_FAILED");
``` 
 Due to the huge use of Chainlink to request off-chain pricing data, we must check that the pricing data is not stale. Because if this happens, the prices will not reflect the current pricing and this will cause loss of funds for the user or the platform.
```
(, int256 price, , , ) = priceFeedDAIETH.latestRoundData();
``` 
 If you have worked with Solidity, you are familiar with the ecrecover function. If signature is not valid, this function returns signing address or 0. Therefore, the output of this function should always be checked.

You can easily write a rule for this pattern with the @semgrep tool and find all the cases that are not like this. 
 An important point about the ecrecover function is that in some cases when the signature is not valid, this function returns a random address instead of returning address 0.
Both cases can be seen in the code below and you can easily write a rule for it with the @semgrep tool.

```solidity
    address signer = ecrecover(hash, v, r, s);
    require(signer == owner, "MyFunction: invalid signature");
    require(signer != address(0), "ECDSA: invalid signature");
```
nostr:nevent1qqsd9p4lk64f7deejltaca8nvhj2k5pd96k8yqg6dhxwpgcvc7l92rqpzpmhxue69uhkummnw3ezumt0d5hsygx67l6vew85z2wsj0zmwtv5gg7clamt39xu7fufjvd2vt8598545cpsgqqqqqqsh9kc82 
 Finding bugs  in solidity language, smart contracts and static code analysis is divided into 2 periods for me.

Before familiarizing with the @semgrep tool and after that.

Before that, I used to choose Linux tools and commands and by chaining them, I found the pattern I was looking for, which sometimes became difficult. 

But after getting familiar with this excellent tool, the work became much easier, and by writing a rule and taking some points into consideration, it is possible to reduce the false positive a lot.

I intend to publish some information about this tool and the bugs I found with it. 
 I want to talk here about some bugs in the field of web3, defi, ..., similar examples of some interesting and controversial bugs, also dealing with some projects after receiving a vulnerability report.