diff --git a/docs/contracts/functions.rst b/docs/contracts/functions.rst index 717961b7c..661663028 100644 --- a/docs/contracts/functions.rst +++ b/docs/contracts/functions.rst @@ -335,7 +335,7 @@ operations as long as there is enough gas passed on to it. :: - pragma solidity ^0.6.0; + pragma solidity >0.6.1 <0.7.0; contract Test { // This function is called for all messages sent to @@ -382,7 +382,7 @@ operations as long as there is enough gas passed on to it. (bool success,) = address(test).call(abi.encodeWithSignature("nonExistingFunction()")); require(success); // results in test.x becoming == 1 and test.y becoming 0. - (success,) = address(test).call.value(1)(abi.encodeWithSignature("nonExistingFunction()")); + (success,) = address(test).call{value: 1}(abi.encodeWithSignature("nonExistingFunction()")); require(success); // results in test.x becoming == 1 and test.y becoming 1. diff --git a/docs/control-structures.rst b/docs/control-structures.rst index d962a4e26..46e0da366 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -75,9 +75,10 @@ all function arguments have to be copied to memory. it is a message call as part of the overall transaction. When calling functions of other contracts, you can specify the amount of Wei or -gas sent with the call with the special options ``.value()`` and ``.gas()``, -respectively. Any Wei you send to the contract is added to the total balance -of the contract: +gas sent with the call with the special options ``{value: 10, gas: 10000}``. +Note that it is discouraged to specify gas values explicitly, since the gas costs +of opcodes can change in the future. Any Wei you send to the contract is added +to the total balance of that contract: :: @@ -90,14 +91,14 @@ of the contract: contract Consumer { InfoFeed feed; function setFeed(InfoFeed addr) public { feed = addr; } - function callFeed() public { feed.info.value(10).gas(800)(); } + function callFeed() public { feed.info{value: 10, gas: 800}(); } } You need to use the modifier ``payable`` with the ``info`` function because -otherwise, the ``.value()`` option would not be available. +otherwise, the ``value`` option would not be available. .. warning:: - Be careful that ``feed.info.value(10).gas(800)`` only locally sets the + Be careful that ``feed.info{value: 10, gas: 800}`` only locally sets the ``value`` and amount of ``gas`` sent with the function call, and the parentheses at the end perform the actual call. So in this case, the function is not called and the ``value`` and ``gas`` settings are lost. @@ -121,6 +122,11 @@ throws an exception or goes out of gas. external functions happen after any changes to state variables in your contract so your contract is not vulnerable to a reentrancy exploit. +.. note:: + Before Solidity 0.6.2, the recommended way to specify the value and gas + was to use ``f.value(x).gas(g)()``. This is still possible but deprecated + and will be removed with Solidity 0.7.0. + Named Calls and Anonymous Function Parameters --------------------------------------------- @@ -196,17 +202,81 @@ is compiled so recursive creation-dependencies are not possible. function createAndEndowD(uint arg, uint amount) public payable { // Send ether along with the creation - D newD = (new D).value(amount)(arg); + D newD = new D{value: amount}(arg); newD.x(); } } As seen in the example, it is possible to send Ether while creating -an instance of ``D`` using the ``.value()`` option, but it is not possible +an instance of ``D`` using the ``value`` option, but it is not possible to limit the amount of gas. If the creation fails (due to out-of-stack, not enough balance or other problems), an exception is thrown. +Salted contract creations / create2 +----------------------------------- + +When creating a contract, the address of the contract is computed from +the address of the creating contract and a counter that is increased with +each contract creation. + +If you specify the option ``salt`` (a bytes32 value), then contract creation will +use a different mechanism to come up with the address of the new contract: + +It will compute the address from the address of the creating contract, +the given salt value, the (creation) bytecode of the created contract and the constructor +arguments. + +In particular, the counter ("nonce") is not used. This allows for more flexibility +in creating contracts: You are able to derive the address of the +new contract before it is created. Furthermore, you can rely on this address +also in case the creating +contracts creates other contracts in the meantime. + +The main use-case here is contracts that act as judges for off-chain interactions, +which only need to be created if there is a dispute. + +:: + + pragma solidity >0.6.1 <0.7.0; + + contract D { + uint public x; + constructor(uint a) public { + x = a; + } + } + + contract C { + function createDSalted(bytes32 salt, uint arg) public { + /// This complicated expression just tells you how the address + /// can be pre-computed. It is just there for illustration. + /// You actually only need ``new D{salt: salt}(arg)``. + address predictedAddress = address(bytes20(keccak256(abi.encodePacked( + byte(0xff), + address(this), + salt, + keccak256(abi.encodePacked( + type(D).creationCode, + arg + )) + )))); + + D d = new D{salt: salt}(arg); + require(address(d) == predictedAddress); + } + } + +.. warning:: + There are some peculiarities in relation to salted creation. A contract can be + re-created at the same address after having been destroyed. Yet, it is possible + for that newly created contract to have a different deployed bytecode even + though the creation bytecode has been the same (which is a requirement because + otherwise the address would change). This is due to the fact that the compiler + can query external state that might have changed between the two creations + and incorporate that into the deployed bytecode before it is stored. + + Order of Evaluation of Expressions ================================== diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index 96187403b..ebf54b3a4 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -89,7 +89,7 @@ as it uses ``call`` which forwards all remaining gas by default: mapping(address => uint) shares; /// Withdraw your share. function withdraw() public { - (bool success,) = msg.sender.call.value(shares[msg.sender])(""); + (bool success,) = msg.sender.call{value: shares[msg.sender]}(""); if (success) shares[msg.sender] = 0; } @@ -149,7 +149,7 @@ Sending and Receiving Ether (for example in the "details" section in Remix). - There is a way to forward more gas to the receiving contract using - ``addr.call.value(x)("")``. This is essentially the same as ``addr.transfer(x)``, + ``addr.call{value: x}("")``. This is essentially the same as ``addr.transfer(x)``, only that it forwards all remaining gas and opens up the ability for the recipient to perform more expensive actions (and it returns a failure code instead of automatically propagating the error). This might include calling back diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index be7ca1d6e..9dae37912 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -276,17 +276,17 @@ Example:: arbitrary arguments and would also handle a first argument of type ``bytes4`` differently. These edge cases were removed in version 0.5.0. -It is possible to adjust the supplied gas with the ``.gas()`` modifier:: +It is possible to adjust the supplied gas with the ``gas`` modifier:: - address(nameReg).call.gas(1000000)(abi.encodeWithSignature("register(string)", "MyName")); + address(nameReg).call{gas: 1000000}(abi.encodeWithSignature("register(string)", "MyName")); Similarly, the supplied Ether value can be controlled too:: - address(nameReg).call.value(1 ether)(abi.encodeWithSignature("register(string)", "MyName")); + address(nameReg).call{value: 1 ether}(abi.encodeWithSignature("register(string)", "MyName")); Lastly, these modifiers can be combined. Their order does not matter:: - address(nameReg).call.gas(1000000).value(1 ether)(abi.encodeWithSignature("register(string)", "MyName")); + address(nameReg).call{gas: 1000000, value: 1 ether}(abi.encodeWithSignature("register(string)", "MyName")); In a similar way, the function ``delegatecall`` can be used: the difference is that only the code of the given address is used, all other aspects (storage, balance, ...) are taken from the current contract. The purpose of ``delegatecall`` is to use library code which is stored in another contract. The user has to ensure that the layout of storage in both contracts is suitable for delegatecall to be used. @@ -297,7 +297,8 @@ Since byzantium ``staticcall`` can be used as well. This is basically the same a All three functions ``call``, ``delegatecall`` and ``staticcall`` are very low-level functions and should only be used as a *last resort* as they break the type-safety of Solidity. -The ``.gas()`` option is available on all three methods, while the ``.value()`` option is not supported for ``delegatecall``. +The ``gas`` option is available on all three methods, while the ``value`` option is not +supported for ``delegatecall``. .. note:: All contracts can be converted to ``address`` type, so it is possible to query the balance of the @@ -635,8 +636,12 @@ External (or public) functions have the following members: * ``.address`` returns the address of the contract of the function. * ``.selector`` returns the :ref:`ABI function selector ` -* ``.gas(uint)`` returns a callable function object which, when called, will send the specified amount of gas to the target function. See :ref:`External Function Calls ` for more information. -* ``.value(uint)`` returns a callable function object which, when called, will send the specified amount of wei to the target function. See :ref:`External Function Calls ` for more information. +* ``.gas(uint)`` returns a callable function object which, when called, will send + the specified amount of gas to the target function. Deprecated - use ``{gas: ...}`` instead. + See :ref:`External Function Calls ` for more information. +* ``.value(uint)`` returns a callable function object which, when called, will + send the specified amount of wei to the target function. Deprecated - use ``{value: ...}`` instead. + See :ref:`External Function Calls ` for more information. Example that shows how to use the members:: @@ -651,6 +656,8 @@ Example that shows how to use the members:: function g() public { this.f.gas(10).value(800)(); + // New syntax: + // this.f{gas: 10, value: 800}() } }