Ethereum has two common types of accounts: Externally Owned Accounts (EOA) and Smart Contract Accounts (SCA).
EOA are very similar to the electronic financial accounts we commonly use to store funds and interact with applications. For instance, users deposit fiat currency through PayPal and interact with various websites, stores, and apps for payments. DeFi miners usually store cryptos in their EOA, interact with DeFi dApps, and deposit funds into dApps for profits. Yet EOA have a feature that electronic financial accounts do not possess: users must have their control over EOA verified through ownership of private keys— not your keys, not your coins.
SCA are also an type of account that is essentially associated with a segment of executable bytecode (also known as a smart contract). The smart contract describes various business logic and serves as the backend for dApps. However, despite having more restrictions compared to traditional Turing complete development languages, quasi-Turing complete smart contracts have still been vulnerable to numerous attacks, dealing countless blows to the blockchain industry.
The most common and notorious attack is the reentrancy attack, which was responsible for the Ethereum fork that led to the creation of Ethereum Classic. In 2016, hackers executed a reentrancy attack on The DAO contract, stealing 3,600,000 ETH valued at over $150 million at the time. This attack, occurring during Ethereum’s early stages, devastated the ecosystem and shattered investor confidence, ultimately leading to a fork.
Specific Logic
Here’s an example to help you better understand the principle of the reentrancy attack. Bank B previously lent some money to Bank A. One day, Bank B initiates a transfer to Bank A, requesting the transfer of all the money back to Bank B. The normal path is as follows:
Step 1: Bank B requests fund withdrawal
Step 2: Bank A transfers the funds to Bank B
Step 3: Bank A confirms the successful transfer to Bank B
Step 4: Bank A updates Bank B’s account balance.
However, if Bank B creates a loophole after Step 2 and continues to request all the money from Bank A without confirmation in Step 3, then the account balance of Bank A at Bank B will remain unchanged. This recursive call will empty all of Bank A’s assets.
Related Smart Contracts
Bank A’s contract includes two functions:
The attack contract of Bank B mainly involves a loop that triggers the receive() callback function, which in turn calls the withdraw() function of the Bank contract to drain the assets of Bank A through a sequence of 1 deposit, 1 withdrawal, and receive() callback function calls, and finally updates B’s balance in A. It includes two functions:
Solution
Implementing a reentrancy lock
A reentrancy lock is a modifier used to prevent reentrancy, ensuring that a call must complete its execution before it can be invoked again. For example, since the attack by Bank B requires calling the withdraw() function of the Bank contract for multiple times, it will fail with the implementation of a reentrancy lock.
How to Use It
The main function of tx.origin in a smart contract is to retrieve the original account that initiated the transaction. Here, we will discuss two common variables in smart contracts: msg.sender and tx.origin. msg.sender retrieves the account directly calling the smart contract, while in the blockchain world, due to the nested and mutual calls of different smart contracts (such as DeFi Lego), tx.origin is needed to obtain the original account that initiated the transaction. A vulnerability arises when dApp developers only verify the security of tx.origin in the code, neglecting the security verification of attackers deploying intermediate contracts to bypass tx.origin and launch attacks.
Specific Logic
Here’s an example to get you deep into the common attack scenario. Bill has a smart wallet that verifies whether Bill is the initiator of a transfer. Once, Bill minted an NFT on a phishing website. That allowed the website to obtain Bill’s identity and initiate a transfer from his smart wallet using his identity, resulting in asset losses. Under normal circumstances, users are less likely to fall for this trap, but when interacting with dApps using a wallet, they often forget to check the interaction prompts. For example, if both involve the Mint() function, careless users may easily fall into a phishing trap. The business logic within the phishing website is riddled with traps, so it’s important to check interaction prompts for errors during regular interactions.
Smart Wallet Contract
The smart wallet contract includes one function:
Phishing Attack Contract
In a phishing attack contract, Mint() induces users to transfer funds to a hacker’s address. It includes one function:
Solutions
No matter how many contract calls involved (Contract A → Contract B →…→ target contract), only verify msg.sender, i.e., the direct caller, to avoid attacks caused by malicious intermediate contracts.
This method can keep malicious contracts away, but developers need to consider their own business realities as it effectively isolates all other external contract calls.
This goes back to the gambling or betting dApp trend around 2018 and 2019. Typically, developers use certain seeds in smart contracts to generate random numbers to select winners during draws. Common seeds include block.number, block.timestamp, blockhash, and keccak256. However, miners can fully control these seeds, so in some cases, malicious miners may manipulate the variables to reap benefits.
Common Dice Contracts
The Dice contract includes one function:
Miner’s Attack Contract
Miners can win as long as they precompute the winning random number and execute it in the same block. This includes one function:
Solution
Use off-chain random numbers provided by oracle projects
Through services provided by oracle projects such as Chainlink, on-chain random numbers are injected into on-chain contracts to ensure randomness and security. However, oracle projects also carry centralization risks, thus necessitating more mature oracle services.
A replay attack involves reinitiating a transaction using a previously used signature to steal funds. One of the best-known replay attacks in recent years was the theft of 20 million $OP tokens from the market maker Wintermute on Optimism, which was a cross-chain replay attack. Since Wintermute’s multi-signature wallet account was temporarily deployed on the Ethereum mainnet only, the hacker used the signature of the transaction for Wintermute’s deployment of a multi-signature address on Ethereum to re-execute the same transaction on the Optimism chain, thereby gaining control of the multi-signature wallet account on Optimism. A multi-signature wallet account is essentially a smart contract account, which also demonstrates a significant difference between SCA and EOA. For an EOA, a normal user only needs one private key to control all addresses on Ethereum and EVM-compatible chains (the address strings are exactly the same), while an SCA is effective on only one chain after being deployed.
Specific Logic
Here, we provide an example of a typical replay attack (same-chain replay attack). Bill has a smart wallet that requires him to enter his electronic signature before each transaction can be executed. Now that the hacker Lucy has stolen Bill’s electronic signature , she can initiate an unlimited number of transactions to drain Bill’s smart wallet.
Example
A contract with vulnerabilities consists of three functions:
Solution
Include nonce in the signature combination to prevent replay attacks. The principle of the parameter is as below:
The Denial of Service (DoS) attack is nothing new in the traditional Web2 world. It refers to any interference with a server, such as sending a large amount of junk or disruptive information, hampering or completely destroying availability. Similarly, smart contracts are plagued by such attacks, which essentially aim to make the smart contract malfunction.
Specific Logic
Let’s see an example. Project A is conducting a public offering for the protocol token, where all users can contribute funds to the liquidity pool (Smart Contract) to purchase quotas on a first-come, first-served basis, and the excess funds will be returned to the participants. Hacker Alice exploits the attack contract to participate in the public offering. Once the liquidity pool attempts to return funds to Alice’s attack contract, a DoS attack will be triggered, preventing the return action from ever being realized. As a result, a large amount of funds are locked in the smart contract.
Example
The public offering contract includes two functions:
DoS Attack Contract
The DoS attack contract includes one function:
Solutions
Remove require(success, “Refund Fail!”); from the above refund() function of PublicSale contract, ensuring that the refund operation can continue even if a refund to a single address fails.
In the above refund() function of PublicSale contract, allow users to claim refunds on their own rather than distributing the refunds, thereby minimizing unnecessary interactions with external contracts.
In a permit attack, Account A provides the signature for a designated party in advance, and then Account B, upon obtaining the signature, can carry out authorized token transfers to steal a certain amount of tokens. Here, we primarily discuss two common functions for token authorization in Smart Contracts: approve() and permit().
In the common ERC20 contract, Account A can call approve() to authorize a certain amount of tokens for Account B, enabling the latter to transfer those tokens from the former. Additionally, permit() was introduced into ERC20 contracts in EIP-2612, and Uniswap has released a new token authorization standard, Permit2, in November 2022.
Specific Logic
Here is an example. One day, Bill was browsing a blockchain news website when suddenly a Metamask signature popup appeared. Since many blockchain websites or applications use signatures to verify user logins, Bill didn’t think much of it and completed the signature directly. Five minutes later, his Metamask assets were drained. Bill then discovered in the blockchain explorer that an unknown address initiated a permit() transaction, followed by a transferFrom() transaction that emptied his wallet.
Example
The two functions are as below:
Solutions
Despite measures some wallets take to decode and display approve() authorization signature information, they provide almost no warning for permit() signature phishing, increasing the risk of attacks. Therefore, it is strongly recommended to rigorously inspect every unknown signature to ensure whether it is aimed at the permit() function.
This is extremely important for crypto users, especially airdrop hunters, as they interact with countless dApps or websites every day and are prone to traps. Storing only a small amount of funds in a wallet for regular interaction can keep losses within a manageable range.
In the blockchain industry, a honeypot attack refers to a type of malicious token contract deployed by project teams. The contract only grants the project team permission to sell, while regular users can only buy instead of selling, thus suffering losses.
Specific Logic
Here is an example. In an announcement on Telegram, Project A informs users that the token has been deployed on the mainnet and is available for trading. As the token can only be bought and cannot be sold, the price kept surging at first, and users who fear missing out keep buying. After sometime when users find it unable to sell, the project team seizes the opportunity and dumps the tokens, causing the price to plummet.
Example
Core function:
Solution
Use security scanning tools
Avoid trading tokens with low scores.
Front-running originally emerged in traditional financial markets, where information asymmetry allowed financial intermediaries to gain profits by taking swift actions based on specific industry information. In the blockchain industry, front-running mainly stems from on-chain front-running, which involves manipulating miners to prioritize packing one’s own transactions onto the chain to gain profits.
In the blockchain field, miners can profit by manipulating the transactions they pack into blocks, e.g. excluding certain transactions and reordering transactions. Such profit can be measured with Miner Extractable Value (MEV). Before a user’s transaction is added to the Ethereum mainnet, the majority of transactions are aggregated in the mempool. Miners search for transactions with higher gas prices in this mempool and prioritize packing them to maximize their gains. Generally, transactions with higher gas prices are more easily packed by miners. Meanwhile, some MEV bots also scour the mempool for transactions with profitability.
Specific Logic
Below is an example. Bill discovers a new hot token with significant price fluctuations. To ensure the success of token transactions on Uniswap, Bill sets an exceptionally wide slippage range. Unfortunately, Alice’s MEV bot detects this transaction in the mempool and promptly increases the gas fee, initiating a buy transaction before Bill’s and inserting a sell transaction after Bill’s within the same block. After block confirmation, this causes significant slippage losses for Bill, while Alice profits from an arbitrage operation of buying low and selling high.
Example
The function is as below:
Process:
Solution
The three major functions are as below:
Process:
In commitSolution(), Bill submits an encrypted string, keeping the plaintext data submitted only to himself. In this step, the submission block time commitTime is also recorded. Next, in revealSolution(), the block time is checked to prevent front-running within the same block. Since calling revealSolution() requires the submission of the plaintext answer, this step aims to prevent others from bypassing commitSolution() and directly calling revealSolution(). After successful verification, the reward will be distributed if the answer is checked correct.
Smart contracts play a crucial role in blockchain technology and offer numerous advantages. Firstly, they enable decentralized, automated execution, ensuring transaction security and reliability without third parties. Secondly, smart contracts reduce intermediary steps and costs, enhancing transaction efficiency.
Despite so many benefits, smart contracts also face the risk of attacks that incur financial losses to users. As such, some habits are essential for on-chain users. Firstly, users should always carefully choose dApps for interaction and thoroughly review the contract code and related rules. Additionally, they should regularly update and use secure wallets and contract interaction tools to mitigate the risk of hacker attacks. Furthermore, it’s advisable to store their funds in multiple addresses to minimize potential losses from contract attacks.
For industry players, ensuring the security and stability of smart contracts is of equal importance. The first priority should be strengthening the auditing of smart contracts to identify and rectify potential vulnerabilities and security risks. Secondly, industry players should stay informed about the latest blockchain developments related to contract attacks and take security measures accordingly. Last but not least, they should also enhance user education and security awareness in terms of the correct use of smart contracts.
In conclusion, with the concerted efforts of both users and industry players, the security risks posed by smart contracts can be significantly mitigated. Users should always carefully select contracts and safeguard personal assets, while industry players should intensify contract auditing, stay abreast of technological advancements, and enhance user education and security awareness. Together, we will drive the secure and reliable development of smart contracts.
Solidity by Example
https://solidity-by-example.org/
Blockchain Know-how of SlowMist
Chainlink – Top 10 DeFi Security Best Practices
https://blog.chain.link/defi-security-best-practices/#post-title
WTF – Solidity 104 Contract Security
https://www.wtf.academy/solidity-104/
Vulnerabilities in DeFi Smart Contracts in 4 Categories with 38 Scenarios
https://www.weiyangx.com/381670.html
OpenZeppelin
https://github.com/OpenZeppelin/
Established in 2017, CoinEx is a global cryptocurrency exchange committed to making trading easier. The platform provides a range of services, including spot and margin trading, futures, swaps, automated market maker (AMM), and financial management services for over 5 million users across 200+ countries and regions. Since its establishment, CoinEx has steadfastly adhered to a “user-first” service principle. With the sincere intention of nurturing an equitable, respectful and secure crypto trading environment, CoinEx enables individuals with varying levels of experience to effortlessly access the world of cryptocurrency by offering easy-to-use products.