mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
commit
f8d67a8ea6
@ -70,15 +70,18 @@ only (locally) sets the value and amount of gas sent with the function call and
|
|||||||
parentheses at the end perform the actual call.
|
parentheses at the end perform the actual call.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
Any interaction with another contract imposes a certain danger, especially
|
Any interaction with another contract imposes a potential danger, especially
|
||||||
if the source code of the contract is not known in advance. The current
|
if the source code of the contract is not known in advance. The current
|
||||||
contract hands over control to the called contract and that might do
|
contract hands over control to the called contract and that may potentially
|
||||||
just about anything. Be prepared that it calls into other contracts of
|
do just about anything. Even if the called contract inherits from a known parent contract,
|
||||||
your system and perhaps even back into the calling contract before your
|
the inheriting contract is only required to have a correct interface. The
|
||||||
|
implementation of the contract, however, can be completely arbitrary and thus,
|
||||||
|
pose a danger. In addition, be prepared in case it calls into other contracts of
|
||||||
|
your system or even back into the calling contract before the first
|
||||||
call returns. This means
|
call returns. This means
|
||||||
that the called contract can change state variables of the calling contract
|
that the called contract can change state variables of the calling contract
|
||||||
via its functions. Write your functions in a way that e.g. calls to
|
via its functions. Write your functions in a way that, for example, calls to
|
||||||
external functions happen after any changes to state variables in your contract,
|
external functions happen after any changes to state variables in your contract
|
||||||
so your contract is not vulnerable to a recursive call exploit.
|
so your contract is not vulnerable to a recursive call exploit.
|
||||||
|
|
||||||
Named Calls and Anonymous Function Parameters
|
Named Calls and Anonymous Function Parameters
|
||||||
|
@ -6,22 +6,23 @@ While it is usually quite easy to build software that works as expected,
|
|||||||
it is much harder to check that nobody can use it in a way that was **not** anticipated.
|
it is much harder to check that nobody can use it in a way that was **not** anticipated.
|
||||||
|
|
||||||
In Solidity, this is even more important because you can use smart contracts
|
In Solidity, this is even more important because you can use smart contracts
|
||||||
to handle tokens or even more valuable things. Furthermore, every execution of a smart
|
to handle tokens or, possibly, even more valuable things. Furthermore, every
|
||||||
contract happens in public as it is mostly open source.
|
execution of a smart contract happens in public and, in addition to that,
|
||||||
|
the source code is often available.
|
||||||
|
|
||||||
Of course you always have to consider how much is at stake:
|
Of course you always have to consider how much is at stake:
|
||||||
You can compare a smart contract with a web service that is open to the
|
You can compare a smart contract with a web service that is open to the
|
||||||
public (and thus also to malicous actors) and perhaps even open source.
|
public (and thus, also to malicous actors) and perhaps even open source.
|
||||||
If you only store your grocery list on that web service, you might not have
|
If you only store your grocery list on that web service, you might not have
|
||||||
to take too much care, but if you manage your bank account using that web service,
|
to take too much care, but if you manage your bank account using that web service,
|
||||||
you should be more careful.
|
you should be more careful.
|
||||||
|
|
||||||
This section will list some pitfalls and general security recommendations but
|
This section will list some pitfalls and general security recommendations but
|
||||||
can of course never be complete. Also keep in mind that even if your
|
can, of course, never be complete. Also, keep in mind that even if your
|
||||||
smart contract code is bug-free, the compiler or the platform itself might
|
smart contract code is bug-free, the compiler or the platform itself might
|
||||||
have a bug.
|
have a bug.
|
||||||
|
|
||||||
As always with open source documentation, please help us extend this section
|
As always, with open source documentation, please help us extend this section
|
||||||
(especially, some examples would not hurt)!
|
(especially, some examples would not hurt)!
|
||||||
|
|
||||||
********
|
********
|
||||||
@ -62,7 +63,7 @@ complete contract):
|
|||||||
The problem is not too serious here because of the limited gas as part
|
The problem is not too serious here because of the limited gas as part
|
||||||
of ``send``, but it still exposes a weakness: Ether transfer always
|
of ``send``, but it still exposes a weakness: Ether transfer always
|
||||||
includes code execution, so the recipient could be a contract that calls
|
includes code execution, so the recipient could be a contract that calls
|
||||||
back into ``withdraw``. This would enable it to get a multiple refund and
|
back into ``withdraw``. This would let it get multiple refunds and
|
||||||
basically retrieve all the Ether in the contract.
|
basically retrieve all the Ether in the contract.
|
||||||
|
|
||||||
To avoid re-entrancy, you can use the Checks-Effects-Interactions pattern as
|
To avoid re-entrancy, you can use the Checks-Effects-Interactions pattern as
|
||||||
@ -82,7 +83,6 @@ outlined further below:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Note that re-entrancy is not only an effect of Ether transfer but of any
|
Note that re-entrancy is not only an effect of Ether transfer but of any
|
||||||
function call on another contract. Furthermore, you also have to take
|
function call on another contract. Furthermore, you also have to take
|
||||||
multi-contract situations into account. A called contract could modify the
|
multi-contract situations into account. A called contract could modify the
|
||||||
@ -91,10 +91,10 @@ state of another contract you depend on.
|
|||||||
Gas Limit and Loops
|
Gas Limit and Loops
|
||||||
===================
|
===================
|
||||||
|
|
||||||
Loops that do not have a fixed number of iterations, e.g. loops that depends on storage values, have to be used carefully:
|
Loops that do not have a fixed number of iterations, for example, loops that depend on storage values, have to be used carefully:
|
||||||
Due to the block gas limit, transactions can only consume a certain amount of gas. Either explicitly or just due to
|
Due to the block gas limit, transactions can only consume a certain amount of gas. Either explicitly or just due to
|
||||||
normal operation, the number of iterations in a loop can grow beyond the block gas limit, which can cause the complete
|
normal operation, the number of iterations in a loop can grow beyond the block gas limit which can cause the complete
|
||||||
contract to be stalled at a certain point. This does not apply at full extent to ``constant`` functions that are only executed
|
contract to be stalled at a certain point. This may not apply to ``constant`` functions that are only executed
|
||||||
to read data from the blockchain. Still, such functions may be called by other contracts as part of on-chain operations
|
to read data from the blockchain. Still, such functions may be called by other contracts as part of on-chain operations
|
||||||
and stall those. Please be explicit about such cases in the documentation of your contracts.
|
and stall those. Please be explicit about such cases in the documentation of your contracts.
|
||||||
|
|
||||||
@ -113,17 +113,17 @@ Sending and Receiving Ether
|
|||||||
into the sending contract or other state changes you might not have though of.
|
into the sending contract or other state changes you might not have though of.
|
||||||
So it allows for great flexibility for honest users but also for malicious actors.
|
So it allows for great flexibility for honest users but also for malicious actors.
|
||||||
|
|
||||||
- If you want to send ether using ``address.send``, there are certain details to be aware of:
|
- If you want to send Ether using ``address.send``, there are certain details to be aware of:
|
||||||
|
|
||||||
1. If the recipient is a contract, it causes its fallback function to be executed which can in turn call back into the sending contract
|
1. If the recipient is a contract, it causes its fallback function to be executed which can, in turn, call back the sending contract.
|
||||||
2. Sending Ether can fail due to the call depth going above 1024. Since the caller is in total control of the call
|
2. Sending Ether can fail due to the call depth going above 1024. Since the caller is in total control of the call
|
||||||
depth, they can force the transfer to fail, so make sure to always check the return value of ``send``. Better yet,
|
depth, they can force the transfer to fail; make sure to always check the return value of ``send``. Better yet,
|
||||||
write your contract using a pattern where the recipient can withdraw Ether instead.
|
write your contract using a pattern where the recipient can withdraw Ether instead.
|
||||||
3. Sending Ether can also fail because the execution of the recipient contract
|
3. Sending Ether can also fail because the execution of the recipient contract
|
||||||
requires more than the allotted amount of gas (explicitly by using ``throw`` or
|
requires more than the allotted amount of gas (explicitly by using ``throw`` or
|
||||||
because the operation is just too expensive) - it "runs out of gas" (OOG).
|
because the operation is just too expensive) - it "runs out of gas" (OOG).
|
||||||
If the return value of ``send`` is checked, this might provide a
|
If the return value of ``send`` is checked, this might provide a
|
||||||
means for the recipient to block progress in the sending contract. Again, the best practise here is to use
|
means for the recipient to block progress in the sending contract. Again, the best practice here is to use
|
||||||
a "withdraw" pattern instead of a "send" pattern.
|
a "withdraw" pattern instead of a "send" pattern.
|
||||||
|
|
||||||
Callstack Depth
|
Callstack Depth
|
||||||
@ -157,7 +157,7 @@ Restrict the Amount of Ether
|
|||||||
|
|
||||||
Restrict the amount of Ether (or other tokens) that can be stored in a smart
|
Restrict the amount of Ether (or other tokens) that can be stored in a smart
|
||||||
contract. If your source code, the compiler or the platform has a bug, these
|
contract. If your source code, the compiler or the platform has a bug, these
|
||||||
funds might be gone. If you want to limit your loss, limit the amount of Ether.
|
funds may be lost. If you want to limit your loss, limit the amount of Ether.
|
||||||
|
|
||||||
Keep it Small and Modular
|
Keep it Small and Modular
|
||||||
=========================
|
=========================
|
||||||
@ -168,30 +168,30 @@ about source code quality of course apply: Limit the amount of local variables,
|
|||||||
the length of functions and so on. Document your functions so that others
|
the length of functions and so on. Document your functions so that others
|
||||||
can see what your intention was and whether it is different than what the code does.
|
can see what your intention was and whether it is different than what the code does.
|
||||||
|
|
||||||
Use the Checks-Effects-Interactions pattern
|
Use the Checks-Effects-Interactions Pattern
|
||||||
===========================================
|
===========================================
|
||||||
|
|
||||||
Most functions will first perform some checks (who called the function,
|
Most functions will first perform some checks (who called the function,
|
||||||
are the arguments in range, did they send enough Ether, does the person
|
are the arguments in range, did they send enough Ether, does the person
|
||||||
have tokens, ...). These checks should be done first.
|
have tokens, etc.). These checks should be done first.
|
||||||
|
|
||||||
As the second step, if all checks passed, effects to the state variables
|
As the second step, if all checks passed, effects to the state variables
|
||||||
of the current contract should be made. Interaction with other contracts
|
of the current contract should be made. Interaction with other contracts
|
||||||
should be the very last step in any function.
|
should be the very last step in any function.
|
||||||
|
|
||||||
Early contracts delayed some effects and waited for external function
|
Early contracts delayed some effects and waited for external function
|
||||||
calls to return in a non-error state. This is often a serious mistake,
|
calls to return in a non-error state. This is often a serious mistake
|
||||||
because of the re-entrancy problem explained above.
|
because of the re-entrancy problem explained above.
|
||||||
|
|
||||||
Note that also calls to known contracts might in turn cause calls to
|
Note that, also, calls to known contracts might in turn cause calls to
|
||||||
unknown contracts, so it is probably better to just always apply this pattern.
|
unknown contracts, so it is probably better to just always apply this pattern.
|
||||||
|
|
||||||
Include a Failsafe-Mode
|
Include a Fail-Safe Mode
|
||||||
=======================
|
========================
|
||||||
|
|
||||||
While making your system fully decentralised will remove any intermediary,
|
While making your system fully decentralised will remove any intermediary,
|
||||||
it might be a good idea, especially for new code, to include some kind
|
it might be a good idea, especially for new code, to include some kind
|
||||||
of fail-safe-mechanism:
|
of fail-safe mechanism:
|
||||||
|
|
||||||
You can add a function in your smart contract that performs some
|
You can add a function in your smart contract that performs some
|
||||||
self-checks like "Has any Ether leaked?",
|
self-checks like "Has any Ether leaked?",
|
||||||
@ -200,9 +200,9 @@ Keep in mind that you cannot use too much gas for that, so help through off-chai
|
|||||||
computations might be needed there.
|
computations might be needed there.
|
||||||
|
|
||||||
If the self-check fails, the contract automatically switches into some kind
|
If the self-check fails, the contract automatically switches into some kind
|
||||||
of "failsafe" mode, which e.g. disables most of the features, hands over
|
of "failsafe" mode, which, for example, disables most of the features, hands over
|
||||||
control to a fixed and trusted third party or just converts the contract into
|
control to a fixed and trusted third party or just converts the contract into
|
||||||
a simple "give me back my money"-contract.
|
a simple "give me back my money" contract.
|
||||||
|
|
||||||
|
|
||||||
*******************
|
*******************
|
||||||
|
Loading…
Reference in New Issue
Block a user