Let’s write a smart smart contract code, see how attacks work, and understand repair techniques for repair
One of the features of Ethereum smart contracts is their ability to call and take advantage of other external code.
Contracts also usually handle the site, and as such the site is usually sent to various addresses of external users. These actions require the contractors to submit external calls. These external calls can be hijacked by attackers, who can force the contracts to execute additional code (using the fallback function), including calls back into themselves.
Attacks of this kind have been used by the infamous DAO hack.
This type of assaultK Can occur when a contract sends a site to an unknown address. An attacker could carefully construct a contract at an external address that contains malicious code in the fallback function.
Thus, when a contract sends a site to this address, it will activate the malicious code. Usually the malicious code performs a function in the vulnerable contract, and performs actions that are not expected by the developer.
The term “re-entry” comes from the fact that the external malicious contract calls a function in the vulnerable contract and the path of code execution “re-enters” it.
To clarify this, consider the simple vulnerable contract in
EtherStore.sol, Which acts as an Ethereum safe that allows depositors to withdraw only one site per week:
This contract has two public functions,
depositFunds The function simply increases the balance of the sender.
withdrawFunds The function allows the sender to specify the quantity of
This function is intended to be successful only if the requested amount for withdrawal is less than site 1 and no withdrawal has occurred in the last week.
The vulnerability is in line 17, where the contract sends the user the amount of their requested site.
Consider the validity that created the contract b
How might the exploitation occur?
First, the attacker creates the malicious contract (say at the address
0x0… 123) with the
EtherStoreThe contract address of as the sole builder parameter.
It will initialize and direct the public variable
etherStore For a contract to attack.
The attacker will then call
attackEtherStore Function, with any amount of site large or equal to 1 – let’s say 1 site for now.
In this example, let’s also assume that a number of other users have deposited a site in this contract, so its current balance is 10 sites. Then the following things will happen:
Attack.solRow 15 of: e
EtherStoreA contract will be called with a
msg.valueOf site 1 (and lots of gas). The sender (
msg.sender) Will be the malicious contract (
0x0… 123). so,
balances[0x0..123] = 1 ether.
Attack.solLine 17 of: The malicious contract will read the
EtherStoreContract with a parameter of site 1. It will pass all the requirements (lines 12–16 of
EtherStoreContract) because no previous withdrawals have been made.
EtherStore.solLine 17 of: The contract will send one site back to the malicious contract.
Attack.solLine 25 of: The payment for the malicious contract will perform the fallback function.
Attack.solRow 26 of: The total balance of
EtherStoreThe contract was 10 sites and is now 9 sites, so this statement if passes.
Attack.solLine 27 of: The fallback function calls
withdrawFundsFunctions again and ‘re-enters’ to
EtherStore.solLine 11 of: In this second call to
withdrawFunds, The current contract balance is still site 1 since line 18 has not yet been executed. Hence, we still have
balances[0x0..123] = 1 ether. This is also the case with
lastWithdrawTimevariable. Again, we pass all the requirements.
EtherStore.solRow 17 of: The valid contract attracts 1 more site.
- Repeat steps 4-8 until this is no longer the case
EtherStore.balance > 1, As dictated by the 26-inch line
Attack.solLine 26 of: Once one site (or less) is left in
EtherStoreContract, that’s if the statement fails. This will then allow lines 18 and 19 of
EtherStoreContract to be executed (for each call to
EtherStore.sol, Lines 18 and 19: balances and
lastWithdrawTimeMappings will be determined and execution will be completed.
The end result is that the attacker pulled the entire site except 1 from the site
EtherStore Contract in one transaction.
There are a number of common techniques that help avoid potential harm of re-entering into smart contracts.
The first is (whenever possible) to use built-in to convey Function when submitting a site to external contracts. The transfer function sends only 2300 gas with the external call, which is not enough for the destination address / contract to call another contract (i.e. re-enter the sending contract).
The second technique is to ensure that any logic that changes state variables occurs before ether is sent from the contract (or any external call). In the
EtherStore For example, lines 18 and 19 of
EtherStore.sol Should be placed before row 17.
It is good practice that any code that makes external calls to unknown addresses is the last action in a local function or in a code execution section. It is known as Pattern-effects-interactions pattern.
A third technique is the insertion of mutex – that is, adding a state variable that locks the contract during code execution, and prevents recurrences.
Application of all these techniques (the use of all three is unnecessary, but we do it for demonstration purposes) to
EtherStore.sol, Gives the contract without re-entry: