mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #8009 from ethereum/docs_security
Docs security considerations
This commit is contained in:
		
						commit
						bd91c0d5c3
					
				| @ -20,14 +20,12 @@ to take too much care, but if you manage your bank account using that web servic | ||||
| you should be more careful. | ||||
| 
 | ||||
| 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 | ||||
| smart contract code is bug-free, the compiler or the platform itself might | ||||
| have a bug. A list of some publicly known security-relevant bugs of the compiler | ||||
| can be found in the | ||||
| :ref:`list of known bugs<known_bugs>`, which is also machine-readable. Note | ||||
| that there is a bug bounty program that covers the code generator of the | ||||
| Solidity compiler. | ||||
| 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 have a | ||||
| bug. A list of some publicly known security-relevant bugs of the compiler can | ||||
| be found in the :ref:`list of known bugs<known_bugs>`, which is also | ||||
| machine-readable. Note that there is a bug bounty program that covers the code | ||||
| generator of the Solidity compiler. | ||||
| 
 | ||||
| As always, with open source documentation, please help us extend this section | ||||
| (especially, some examples would not hurt)! | ||||
| @ -138,12 +136,16 @@ Sending and Receiving Ether | ||||
|   to move Ether without creating a message call. One way is to simply "mine to" | ||||
|   the contract address and the second way is using ``selfdestruct(x)``. | ||||
| 
 | ||||
| - If a contract receives Ether (without a function being called), the fallback function is executed. | ||||
|   If it does not have a fallback function, the Ether will be rejected (by throwing an exception). | ||||
|   During the execution of the fallback function, the contract can only rely | ||||
|   on the "gas stipend" it is passed (2300 gas) being available to it at that time. This stipend is not enough to modify storage | ||||
|   (do not take this for granted though, the stipend might change with future hard forks). | ||||
|   To be sure that your contract can receive Ether in that way, check the gas requirements of the fallback function | ||||
| - If a contract receives Ether (without a function being called), | ||||
|   either the :ref:`receive Ether <receive-ether-function>` | ||||
|   or the :ref:`fallback <fallback-function>` function is executed. | ||||
|   If it does not have a receive nor a fallback function, the Ether will be | ||||
|   rejected (by throwing an exception). During the execution of one of these | ||||
|   functions, the contract can only rely on the "gas stipend" it is passed (2300 | ||||
|   gas) being available to it at that time. This stipend is not enough to modify | ||||
|   storage (do not take this for granted though, the stipend might change with | ||||
|   future hard forks). To be sure that your contract can receive Ether in that | ||||
|   way, check the gas requirements of the receive and fallback functions | ||||
|   (for example in the "details" section in Remix). | ||||
| 
 | ||||
| - There is a way to forward more gas to the receiving contract using | ||||
| @ -159,17 +161,22 @@ Sending and Receiving Ether | ||||
| 
 | ||||
| - If you want to send Ether using ``address.transfer``, 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 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 | ||||
|      depth, they can force the transfer to fail; take this possibility into account or use ``send`` and make sure to always check its return value. Better yet, | ||||
|      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 | ||||
|      requires more than the allotted amount of gas (explicitly by using ``require``, | ||||
|      ``assert``, ``revert``, ``throw`` or | ||||
|      because the operation is just too expensive) - it "runs out of gas" (OOG). | ||||
|      If you use ``transfer`` or ``send`` with a return value check, this might provide a | ||||
|      means for the recipient to block progress in the sending contract. Again, the best practice here is to use | ||||
|      a :ref:`"withdraw" pattern instead of a "send" pattern <withdrawal_pattern>`. | ||||
|   1. If the recipient is a contract, it causes its receive or 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 depth, they can force the | ||||
|      transfer to fail; take this possibility into account or use ``send`` and | ||||
|      make sure to always check its return value. Better yet, 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 requires more than the allotted amount of gas (explicitly by | ||||
|      using :ref:`require <assert-and-require>`, :ref:`assert <assert-and-require>`, | ||||
|      :ref:`revert <assert-and-require>` or because the | ||||
|      operation is too expensive) - it "runs out of gas" (OOG).  If you | ||||
|      use ``transfer`` or ``send`` with a return value check, this might | ||||
|      provide a means for the recipient to block progress in the sending | ||||
|      contract. Again, the best practice here is to use a :ref:`"withdraw" | ||||
|      pattern instead of a "send" pattern <withdrawal_pattern>`. | ||||
| 
 | ||||
| Callstack Depth | ||||
| =============== | ||||
| @ -181,8 +188,7 @@ before they interact with your contract. | ||||
| 
 | ||||
| Note that ``.send()`` does **not** throw an exception if the call stack is | ||||
| depleted but rather returns ``false`` in that case. The low-level functions | ||||
| ``.call()``, ``.callcode()``, ``.delegatecall()`` and ``.staticcall()`` behave | ||||
| in the same way. | ||||
| ``.call()``, ``.delegatecall()`` and ``.staticcall()`` behave in the same way. | ||||
| 
 | ||||
| tx.origin | ||||
| ========= | ||||
| @ -207,7 +213,7 @@ Never use tx.origin for authorization. Let's say you have a wallet contract like | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| Now someone tricks you into sending ether to the address of this attack wallet: | ||||
| Now someone tricks you into sending Ether to the address of this attack wallet: | ||||
| 
 | ||||
| :: | ||||
| 
 | ||||
| @ -224,7 +230,7 @@ Now someone tricks you into sending ether to the address of this attack wallet: | ||||
|             owner = msg.sender; | ||||
|         } | ||||
| 
 | ||||
|         fallback() external { | ||||
|         receive() external payable { | ||||
|             TxUserWallet(msg.sender).transferTo(owner, msg.sender.balance); | ||||
|         } | ||||
|     } | ||||
| @ -247,8 +253,7 @@ In general, read about the limits of two's complement representation, which even | ||||
| more special edge cases for signed numbers. | ||||
| 
 | ||||
| Try to use ``require`` to limit the size of inputs to a reasonable range and use the | ||||
| :ref:`SMT checker<smt_checker>` to find potential overflows, or | ||||
| use a library like | ||||
| :ref:`SMT checker<smt_checker>` to find potential overflows, or use a library like | ||||
| `SafeMath <https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol>`_ | ||||
| if you want all overflows to cause a revert. | ||||
| 
 | ||||
| @ -259,16 +264,16 @@ Code such as ``require((balanceOf[_to] + _value) >= balanceOf[_to])`` can also h | ||||
| Clearing Mappings | ||||
| ================= | ||||
| 
 | ||||
| The Solidity type ``mapping`` (see :ref:`mapping-types`) is a storage-only key-value data structure that | ||||
| does not keep track of the keys that were assigned a non-zero value. | ||||
| Because of that, cleaning a mapping without extra information about the written | ||||
| keys is not possible. | ||||
| The Solidity type ``mapping`` (see :ref:`mapping-types`) is a storage-only | ||||
| key-value data structure that does not keep track of the keys that were | ||||
| assigned a non-zero value.  Because of that, cleaning a mapping without extra | ||||
| information about the written keys is not possible. | ||||
| If a ``mapping`` is used as the base type of a dynamic storage array, deleting | ||||
| or popping the array will have no effect over the ``mapping`` elements. | ||||
| The same happens, for example, if a ``mapping`` is used as the type of a member | ||||
| field of a ``struct`` that is the base type of a dynamic storage array. | ||||
| The ``mapping`` is also ignored in assignments of structs or arrays containing | ||||
| a ``mapping``. | ||||
| or popping the array will have no effect over the ``mapping`` elements.  The | ||||
| same happens, for example, if a ``mapping`` is used as the type of a member | ||||
| field of a ``struct`` that is the base type of a dynamic storage array.  The | ||||
| ``mapping`` is also ignored in assignments of structs or arrays containing a | ||||
| ``mapping``. | ||||
| 
 | ||||
| :: | ||||
| 
 | ||||
| @ -307,8 +312,7 @@ another call to ``writeMap``. | ||||
| 
 | ||||
| If your ``mapping`` information must be deleted, consider using a library similar to | ||||
| `iterable mapping <https://github.com/ethereum/dapp-bin/blob/master/library/iterable_mapping.sol>`_, | ||||
| allowing you to traverse the keys and delete their values in the appropriate | ||||
| ``mapping``. | ||||
| allowing you to traverse the keys and delete their values in the appropriate ``mapping``. | ||||
| 
 | ||||
| Minor Details | ||||
| ============= | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user