Different blockchains have different settings and quirks that lead to various items. For instance, the average block time, timestamp and many others. This talk is inspired by a
this Github repository about the same thing as well. Many of the chains have documentation on
how it differs from Ethereum as well.
The average block on Ethereum is about 12 seconds since the proof of stake merge. On Polygon, this is 6 seconds.
block.number may not reflect proper timing on other chains. On Arbitrum, this represents the Layer 1 block number and is updated once per minute. This means it can jump from 1000 to 1004. In some cases, calculations can be wrong, especially when using this as a time reference.
An L2 sequencer is a method of the transactions going from L2 to L1. If the sequencer is down then updates from things like Chainlink will not work. For things like pricing oracles, it's important to ensure these are up-to-date. Otherwise, unfair liquidation or oracle manipulations could occur. An additional chainlink feature is checking the price feed address, as it may differ between other chains or may not exist entirely.
On Uniswap, the token order matters. Typically, this is sorted by address. On different chains, the addresses may vary, changing the ordering on the call. This is true of the ordering on Chainlink as well.
Modified opcodes. Some chains may have an older version of EVM, such as not having PUSH0 or difficulty being removed in the proof of stake update being changed. tx.origin and msg.sender on the L2 have slightly different meanings. precompiles can be different as well.
Modified opcodes. Some chains may have an older version of EVM, such as not having PUSH0 or difficulty being removed in the proof of stake update being changed. tx.origin and msg.sender on the L2 have slightly different meanings. precompiles can be different as well.
Frontrunning is weird on L2s. Optimism has a private mempool, making frontrunning infeasible. However, this may be decentralized in the future, resulting in the ability to frontrun.
Frontrunning is weird on L2s. Optimism has a private mempool, making frontrunning infeasible. However, this may be decentralized in the future, resulting in the ability to frontrun.
Various tokens are different. Decimals, such USDC and USDT are 6 on Ethereum but 18 on BSC. Harcode coded addresses of tokens, such as WETH. Contract interfaces may be different, such as USDT on Ethereum missing the return value but this isn't the case on Polygon.
From the reports being read, it's fairly common that projects only test on a single blockchain. Considering all of the issues mentioned above, simply running the code on a different chain or reviewing these issues will net you some findings on occasion.