EthSecurity – Telegram
If you see a Solidity method that has an argument of type array, always check for 3 things:

1. What if the array length is 0?
2. What if there are duplicated elements in the array?
3. What if there are zero value elements in the array?
@EthSecurity1
👍21🔥1
Seeing a potential re-entrancy exploit with the SteadyStackNFT contract.

Looks like anyone on the goldlist can re-use their signatures to mint as many NFTs as they want.

There's no supply check on this function so someone could mint out the remaining supply (limited by gas).@EthSecurity1
1👍1🔥1
coinbase.transfer()
Flashbots allows you to pay validators for your transactions through a smart contract by using block.coinbase.transfer(AMOUNT_TO_TRANSFER). This smart contract function transfers Ethereum from the contract to the address of the validator who proposes a block. The Flashbots builder will treat fees through coinbase transfers in the same way they do normal transaction fees, which is to say that 1 wei of coinbase payments is equivalent to 1 wei paid through transaction fees. This provides significant benefits to Flashbots users:

You can condition payment to the validator on some criteria being met
Related, you can only pay for successful transactions, not failures
You can pay for a transaction from account X with ETH from account Y (see: searcher sponsored transaction repo here)
Here's an example from our open source simple arbitrage bot of how paying through coinbase transfers work:

function uniswapWeth(uint256 _wethAmountToFirstMarket, uint256 _ethAmountToCoinbase, address[] memory _targets, bytes[] memory _payloads) external onlyExecutor payable {
require (_targets.length == _payloads.length);
uint256 _wethBalanceBefore = WETH.balanceOf(address(this));
WETH.transfer(_targets[0], _wethAmountToFirstMarket);
for (uint256 i = 0; i < _targets.length; i++) {
(bool _success, bytes memory _response) = _targets[i].call(_payloads[i]);
require(_success); _response;
}

uint256 _wethBalanceAfter = WETH.balanceOf(address(this));
require(_wethBalanceAfter > _wethBalanceBefore + _ethAmountToCoinbase);
if (_ethAmountToCoinbase == 0) return;

uint256 _ethBalance = address(this).balance;
if (_ethBalance < _ethAmountToCoinbase) {
WETH.withdraw(_ethAmountToCoinbase - _ethBalance);
}
block.coinbase.transfer(_ethAmountToCoinbase);
}


The above smart contract code will attempt to capitalize on arbitrage opportunities. If it does not make money doing so then the transaction will fail.

For more information on how coinbase transfers are priced see the bundle pricing page.

Managing payments to coinbase.address when it is a contract
Validators will occasionally have a smart contract listed as their block.coinbase address. This changes the expected behavior of making payments to block.coinbase. Specifically it costs more gas to transfer ETH to block.coinbase if it is a contract than if it is an EOA, and as such many searchers will underestimate their gas consumption and their bundles will fail for validators who use contracts instead.

To handle this edge case searchers can up their gas limit to accomodate the additional payment to validators and call block.coinbase in the following way:

block.coinbase.call{value: _ethAmountToCoinbase}(new bytes(0));

However, searchers should be acutely aware of the risk of reentrancy attacks, as calling coinbase in this way temporarily gives execution to a third party, and typically payments to coinbase are made after checks for profit. Moreover, searchers should be aware that supporting payments to coinbase addresses that are contracts will cause their gas consumption to go up, and as a result their bundle gas price to go down. This is a tradeoff that should be considered.@EthSecurity1
👍41
Here are some fun facts about $PEPE's contract code, including the curious case of $8M worth of coins that are locked up forever.There is blacklist functionality in the contract that blocks someone from receiving or sending @EthSecurity1 tokens.https://etherscan.io/address/0x6982508145454ce325ddbe47a25d4ec3d2311933#code
🤔2😁1🤯1🤬1
High finding from recent BlueBerry Update 1 contest: swap with no slippage & no deadline. Exposes the user to potential total loss of funds.

Combination of "No Slippage Parameter" & "No Expiration Deadline" from my Slippage Deep Dive https://dacian.me/defi-slippage-attacks @EthSecurity1
💯1
When auditing, a great way to find vulnerabilities is to ask questions. Sometimes these are concrete questions; other times, they are more abstract. Regarding reentrancy, some questions to ask oneself are:

Which functions have external calls?
On which state variables do these functions depend?
Which state variables does this change? And which other functions interact with those state variables? @EthSecurity1
🫡3
Always handle return value from functions enterMarket() and exitMarket() of Compound V2.
if market is not listed it will return MARKET_NOT_LISTED error. Every external call to other protocol should be reviewed and handled.@EthSecurity1
2
The "1 Wei Attack" is an exploitation of some DeFi platforms' vaults or liquidity pools, specifically those employing AMMs.

This attack takes advantage of the lack of slippage protection which leads to asset dilution and potential loss of funds for unsuspecting users. Suppose the following occurred:

1. The vault is empty
2. Alice deposits 1 token (1e18 units) into vault
3. Bob front-runs it, depositing 1 unit
4. Bob donates 1 token (1e18 units) into the vault using ERC20 transfer
5. Alice's deposit is executed

What happens?With an empty vault, the shares are being minted at a 1:1 rate with the amount. After Bob deposits 1 unit, the rate is 1:1 unit:shares.

Then, Bob donates another 1e18 units. This will make totalAssets = 1e18 + 1.Finally, Alice's transaction is completed and she gets:

(1e18*1) / (1e18 + 1) = 0.99999.. shares

In solidity, the decimals are truncated, and she gets 0 shares! 😲
@EthSecurity1
👍3🔥1🤯1
Find the bug #simple
I will post answer @EthSecurity1
🔥2