mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Documentation for function call options.
This commit is contained in:
parent
893fb4d05b
commit
981ed5f773
@ -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.
|
||||
|
||||
|
@ -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
|
||||
==================================
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 <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 <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 <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 <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 <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}()
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user