Syntax Quirks

Named return values

// Named return values are supported like so.
function testReturn() public pure returns (uint256 tester) {
    tester = 3;
}

Pure functions

While Solidity protects internal code from modifying state in pure functions, it does not protect against external calls that modify state. Check this writeup for the Ethernauts “Shop” challenge to see how this can be exploited.

Hash Quirks

Blockhash of the current block

// Will always return 0x000...000 because it hasn't been mined.
bytes32 hash = blockhash(block.number);

Value Quirks

Using msg.value in loops

Be careful of using msg.value in loops. If there aren’t proper checks, a buyMany() may not work as expected.

BuggyBuy.sol
/// Buy many NFTs at once. Payable.
function buyMany(uint256[] calldata tokenIds) external payable nonReentrant {
    for (uint256 i = 0; i < tokenIds.length; i++) {
        _buyOne(tokenIds[i]);
    }
}
 
/// Buy one NFT.
function _buyOne(uint256 tokenId) private {
    uint256 priceToPay = offers[tokenId];
    // NOTE: `msg.value` is not decremented in the loop
    if (msg.value < priceToPay)
        revert InsufficientPayment();
 
    _token.safeTransferFrom(_token.ownerOf(tokenId), msg.sender, tokenId);
    payable(_token.ownerOf(tokenId)).sendValue(priceToPay);
}