mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Update documentation.
This commit is contained in:
parent
683bce1869
commit
e3b6c5a4bd
@ -5,7 +5,7 @@ How to update your code:
|
|||||||
* Change every ``keccak256(a, b, c)`` to ``keccak256(abi.encodePacked(a, b, c))``.
|
* Change every ``keccak256(a, b, c)`` to ``keccak256(abi.encodePacked(a, b, c))``.
|
||||||
* Add ``public`` to every function and ``external`` to every fallback or interface function that does not specify its visibility already.
|
* Add ``public`` to every function and ``external`` to every fallback or interface function that does not specify its visibility already.
|
||||||
* Make your fallback functions ``external``.
|
* Make your fallback functions ``external``.
|
||||||
* Explicitly state the storage location for local variables of struct and array types, e.g. change ``uint[] x = m_x`` to ``uint[] storage x = m_x``.
|
* Explicitly state the data location for all variables of struct, array or mapping types (including function parameters), e.g. change ``uint[] x = m_x`` to ``uint[] storage x = m_x``. Note that ``external`` functions require parameters with a data location of ``calldata``.
|
||||||
* Explicitly convert values of contract type to addresses before using an ``address`` member. Example: if ``c`` is a contract, change ``c.transfer(...)`` to ``address(c).transfer(...)``.
|
* Explicitly convert values of contract type to addresses before using an ``address`` member. Example: if ``c`` is a contract, change ``c.transfer(...)`` to ``address(c).transfer(...)``.
|
||||||
|
|
||||||
Breaking Changes:
|
Breaking Changes:
|
||||||
@ -54,6 +54,7 @@ Breaking Changes:
|
|||||||
* Type Checker: Disallow calling constructor with wrong argument count. This was already the case in the experimental 0.5.0 mode.
|
* Type Checker: Disallow calling constructor with wrong argument count. This was already the case in the experimental 0.5.0 mode.
|
||||||
* Type Checker: Disallow uninitialized storage variables. This was already the case in the experimental 0.5.0 mode.
|
* Type Checker: Disallow uninitialized storage variables. This was already the case in the experimental 0.5.0 mode.
|
||||||
* Type Checker: Detecting cyclic dependencies in variables and structs is limited in recursion to 256.
|
* Type Checker: Detecting cyclic dependencies in variables and structs is limited in recursion to 256.
|
||||||
|
* Type Checker: Require explicit data location for all variables, including function parameters. This was partly already the case in the experimental 0.5.0 mode.
|
||||||
* Type Checker: Only accept a single ``bytes`` type for ``.call()`` (and family), ``keccak256()``, ``sha256()`` and ``ripemd160()``.
|
* Type Checker: Only accept a single ``bytes`` type for ``.call()`` (and family), ``keccak256()``, ``sha256()`` and ``ripemd160()``.
|
||||||
* Type Checker: Fallback function must be external. This was already the case in the experimental 0.5.0 mode.
|
* Type Checker: Fallback function must be external. This was already the case in the experimental 0.5.0 mode.
|
||||||
* Type Checker: Interface functions must be declared external. This was already the case in the experimental 0.5.0 mode.
|
* Type Checker: Interface functions must be declared external. This was already the case in the experimental 0.5.0 mode.
|
||||||
@ -61,7 +62,7 @@ Breaking Changes:
|
|||||||
* Type Checker: Disallow "loose assembly" syntax entirely. This means that jump labels, jumps and non-functional instructions cannot be used anymore.
|
* Type Checker: Disallow "loose assembly" syntax entirely. This means that jump labels, jumps and non-functional instructions cannot be used anymore.
|
||||||
* Type System: Disallow explicit and implicit conversions from decimal literals to ``bytesXX`` types.
|
* Type System: Disallow explicit and implicit conversions from decimal literals to ``bytesXX`` types.
|
||||||
* Type System: Disallow explicit and implicit conversions from hex literals to ``bytesXX`` types of different size.
|
* Type System: Disallow explicit and implicit conversions from hex literals to ``bytesXX`` types of different size.
|
||||||
* Remove obsolete ``std`` directory from the Solidity repository. This means accessing ``https://github.com/ethereum/soldity/blob/develop/std/*.sol`` (or ``https://github.com/ethereum/solidity/std/*.sol`` in Remix) will not be possible.
|
* Remove obsolete ``std`` directory from the Solidity repository. This means accessing ``https://github.com/ethereum/solidity/blob/develop/std/*.sol`` (or ``https://github.com/ethereum/solidity/std/*.sol`` in Remix) will not be possible.
|
||||||
* References Resolver: Turn missing storage locations into an error. This was already the case in the experimental 0.5.0 mode.
|
* References Resolver: Turn missing storage locations into an error. This was already the case in the experimental 0.5.0 mode.
|
||||||
* Syntax Checker: Disallow functions without implementation to use modifiers. This was already the case in the experimental 0.5.0 mode.
|
* Syntax Checker: Disallow functions without implementation to use modifiers. This was already the case in the experimental 0.5.0 mode.
|
||||||
* Syntax Checker: Named return values in function types are an error.
|
* Syntax Checker: Named return values in function types are an error.
|
||||||
|
@ -90,7 +90,7 @@ of votes.
|
|||||||
// If the first argument of `require` evaluates
|
// If the first argument of `require` evaluates
|
||||||
// to `false`, execution terminates and all
|
// to `false`, execution terminates and all
|
||||||
// changes to the state and to Ether balances
|
// changes to the state and to Ether balances
|
||||||
// are reverted.
|
// are reverted.
|
||||||
// This used to consume all gas in old EVM versions, but
|
// This used to consume all gas in old EVM versions, but
|
||||||
// not anymore.
|
// not anymore.
|
||||||
// It is often a good idea to use `require` to check if
|
// It is often a good idea to use `require` to check if
|
||||||
@ -708,7 +708,7 @@ For a contract that fulfills payments, the signed message must include:
|
|||||||
A replay attack is when a signed message is reused to claim authorization for
|
A replay attack is when a signed message is reused to claim authorization for
|
||||||
a second action.
|
a second action.
|
||||||
To avoid replay attacks we will use the same as in Ethereum transactions
|
To avoid replay attacks we will use the same as in Ethereum transactions
|
||||||
themselves, a so-called nonce, which is the number of transactions sent by an
|
themselves, a so-called nonce, which is the number of transactions sent by an
|
||||||
account.
|
account.
|
||||||
The smart contract will check if a nonce is used multiple times.
|
The smart contract will check if a nonce is used multiple times.
|
||||||
|
|
||||||
@ -731,7 +731,7 @@ Packing arguments
|
|||||||
Now that we have identified what information to include in the
|
Now that we have identified what information to include in the
|
||||||
signed message, we are ready to put the message together, hash it,
|
signed message, we are ready to put the message together, hash it,
|
||||||
and sign it. For simplicity, we just concatenate the data.
|
and sign it. For simplicity, we just concatenate the data.
|
||||||
The
|
The
|
||||||
`ethereumjs-abi <https://github.com/ethereumjs/ethereumjs-abi>`_ library provides
|
`ethereumjs-abi <https://github.com/ethereumjs/ethereumjs-abi>`_ library provides
|
||||||
a function called ``soliditySHA3`` that mimics the behavior
|
a function called ``soliditySHA3`` that mimics the behavior
|
||||||
of Solidity's ``keccak256`` function applied to arguments encoded
|
of Solidity's ``keccak256`` function applied to arguments encoded
|
||||||
@ -750,7 +750,7 @@ creates the proper signature for the ``ReceiverPays`` example:
|
|||||||
["address", "uint256", "uint256", "address"],
|
["address", "uint256", "uint256", "address"],
|
||||||
[recipient, amount, nonce, contractAddress]
|
[recipient, amount, nonce, contractAddress]
|
||||||
).toString("hex");
|
).toString("hex");
|
||||||
|
|
||||||
web3.personal.sign(hash, web3.eth.defaultAccount, callback);
|
web3.personal.sign(hash, web3.eth.defaultAccount, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -779,7 +779,7 @@ at the end of this chapter).
|
|||||||
|
|
||||||
Computing the Message Hash
|
Computing the Message Hash
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
The smart contract needs to know exactly what parameters were signed,
|
The smart contract needs to know exactly what parameters were signed,
|
||||||
and so it must recreate the message from the parameters and use that
|
and so it must recreate the message from the parameters and use that
|
||||||
for signature verification. The functions ``prefixed`` and
|
for signature verification. The functions ``prefixed`` and
|
||||||
@ -801,7 +801,7 @@ The full contract
|
|||||||
|
|
||||||
constructor() public payable {}
|
constructor() public payable {}
|
||||||
|
|
||||||
function claimPayment(uint256 amount, uint256 nonce, bytes signature) public {
|
function claimPayment(uint256 amount, uint256 nonce, bytes memory signature) public {
|
||||||
require(!usedNonces[nonce]);
|
require(!usedNonces[nonce]);
|
||||||
usedNonces[nonce] = true;
|
usedNonces[nonce] = true;
|
||||||
|
|
||||||
@ -820,7 +820,7 @@ The full contract
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// signature methods.
|
/// signature methods.
|
||||||
function splitSignature(bytes sig)
|
function splitSignature(bytes memory sig)
|
||||||
internal
|
internal
|
||||||
pure
|
pure
|
||||||
returns (uint8 v, bytes32 r, bytes32 s)
|
returns (uint8 v, bytes32 r, bytes32 s)
|
||||||
@ -839,7 +839,7 @@ The full contract
|
|||||||
return (v, r, s);
|
return (v, r, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
function recoverSigner(bytes32 message, bytes sig)
|
function recoverSigner(bytes32 message, bytes memory sig)
|
||||||
internal
|
internal
|
||||||
pure
|
pure
|
||||||
returns (address)
|
returns (address)
|
||||||
@ -874,7 +874,7 @@ two parties (Alice and Bob). Using it involves three steps:
|
|||||||
1. Alice funds a smart contract with Ether. This "opens" the payment channel.
|
1. Alice funds a smart contract with Ether. This "opens" the payment channel.
|
||||||
2. Alice signs messages that specify how much of that Ether is owed to the recipient. This step is repeated for each payment.
|
2. Alice signs messages that specify how much of that Ether is owed to the recipient. This step is repeated for each payment.
|
||||||
3. Bob "closes" the payment channel, withdrawing their portion of the Ether and sending the remainder back to the sender.
|
3. Bob "closes" the payment channel, withdrawing their portion of the Ether and sending the remainder back to the sender.
|
||||||
|
|
||||||
Not ethat only steps 1 and 3 require Ethereum transactions, step 2 means that
|
Not ethat only steps 1 and 3 require Ethereum transactions, step 2 means that
|
||||||
the sender transmits a cryptographically signed message to the recipient via off chain ways (e.g. email).
|
the sender transmits a cryptographically signed message to the recipient via off chain ways (e.g. email).
|
||||||
This means only two transactions are required to support any number of transfers.
|
This means only two transactions are required to support any number of transfers.
|
||||||
@ -906,7 +906,7 @@ Each message includes the following information:
|
|||||||
|
|
||||||
* The smart contract's address, used to prevent cross-contract replay attacks.
|
* The smart contract's address, used to prevent cross-contract replay attacks.
|
||||||
* The total amount of Ether that is owed the recipient so far.
|
* The total amount of Ether that is owed the recipient so far.
|
||||||
|
|
||||||
A payment channel is closed just once, at the of a series of transfers.
|
A payment channel is closed just once, at the of a series of transfers.
|
||||||
Because of this, only one of the messages sent will be redeemed. This is why
|
Because of this, only one of the messages sent will be redeemed. This is why
|
||||||
each message specifies a cumulative total amount of Ether owed, rather than the
|
each message specifies a cumulative total amount of Ether owed, rather than the
|
||||||
@ -926,7 +926,7 @@ Here is the modified javascript code to cryptographically sign a message from th
|
|||||||
[contractAddress, amount]
|
[contractAddress, amount]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function signMessage(message, callback) {
|
function signMessage(message, callback) {
|
||||||
web3.personal.sign(
|
web3.personal.sign(
|
||||||
"0x" + message.toString("hex"),
|
"0x" + message.toString("hex"),
|
||||||
@ -934,10 +934,10 @@ Here is the modified javascript code to cryptographically sign a message from th
|
|||||||
callback
|
callback
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// contractAddress is used to prevent cross-contract replay attacks.
|
// contractAddress is used to prevent cross-contract replay attacks.
|
||||||
// amount, in wei, specifies how much Ether should be sent.
|
// amount, in wei, specifies how much Ether should be sent.
|
||||||
|
|
||||||
function signPayment(contractAddress, amount, callback) {
|
function signPayment(contractAddress, amount, callback) {
|
||||||
var message = constructPaymentMessage(contractAddress, amount);
|
var message = constructPaymentMessage(contractAddress, amount);
|
||||||
signMessage(message, callback);
|
signMessage(message, callback);
|
||||||
@ -1003,7 +1003,7 @@ The full contract
|
|||||||
expiration = now + duration;
|
expiration = now + duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isValidSignature(uint256 amount, bytes signature)
|
function isValidSignature(uint256 amount, bytes memory signature)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (bool)
|
returns (bool)
|
||||||
@ -1017,7 +1017,7 @@ The full contract
|
|||||||
/// the recipient can close the channel at any time by presenting a
|
/// the recipient can close the channel at any time by presenting a
|
||||||
/// signed amount from the sender. the recipient will be sent that amount,
|
/// signed amount from the sender. the recipient will be sent that amount,
|
||||||
/// and the remainder will go back to the sender
|
/// and the remainder will go back to the sender
|
||||||
function close(uint256 amount, bytes signature) public {
|
function close(uint256 amount, bytes memory signature) public {
|
||||||
require(msg.sender == recipient);
|
require(msg.sender == recipient);
|
||||||
require(isValidSignature(amount, signature));
|
require(isValidSignature(amount, signature));
|
||||||
|
|
||||||
@ -1043,7 +1043,7 @@ The full contract
|
|||||||
/// All functions below this are just taken from the chapter
|
/// All functions below this are just taken from the chapter
|
||||||
/// 'creating and verifying signatures' chapter.
|
/// 'creating and verifying signatures' chapter.
|
||||||
|
|
||||||
function splitSignature(bytes sig)
|
function splitSignature(bytes memory sig)
|
||||||
internal
|
internal
|
||||||
pure
|
pure
|
||||||
returns (uint8 v, bytes32 r, bytes32 s)
|
returns (uint8 v, bytes32 r, bytes32 s)
|
||||||
@ -1058,11 +1058,11 @@ The full contract
|
|||||||
// final byte (first byte of the next 32 bytes)
|
// final byte (first byte of the next 32 bytes)
|
||||||
v := byte(0, mload(add(sig, 96)))
|
v := byte(0, mload(add(sig, 96)))
|
||||||
}
|
}
|
||||||
|
|
||||||
return (v, r, s);
|
return (v, r, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
function recoverSigner(bytes32 message, bytes sig)
|
function recoverSigner(bytes32 message, bytes memory sig)
|
||||||
internal
|
internal
|
||||||
pure
|
pure
|
||||||
returns (address)
|
returns (address)
|
||||||
@ -1083,7 +1083,7 @@ Note: The function ``splitSignature`` is very simple and does not use all securi
|
|||||||
A real implementation should use a more rigorously tested library, such as
|
A real implementation should use a more rigorously tested library, such as
|
||||||
openzepplin's `version <https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/ECRecovery.sol>`_ of this code.
|
openzepplin's `version <https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/ECRecovery.sol>`_ of this code.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Verifying Payments
|
Verifying Payments
|
||||||
------------------
|
------------------
|
||||||
@ -1101,7 +1101,7 @@ The recipient should verify each message using the following process:
|
|||||||
2. Verify that the new total is the expected amount.
|
2. Verify that the new total is the expected amount.
|
||||||
3. Verify that the new total does not exceed the amount of Ether escrowed.
|
3. Verify that the new total does not exceed the amount of Ether escrowed.
|
||||||
4. Verify that the signature is valid and comes from the payment channel sender.
|
4. Verify that the signature is valid and comes from the payment channel sender.
|
||||||
|
|
||||||
We'll use the `ethereumjs-util <https://github.com/ethereumjs/ethereumjs-util>`_
|
We'll use the `ethereumjs-util <https://github.com/ethereumjs/ethereumjs-util>`_
|
||||||
library to write this verifications. The final step can be done a number of ways,
|
library to write this verifications. The final step can be done a number of ways,
|
||||||
but if it's being done in **JavaScript**.
|
but if it's being done in **JavaScript**.
|
||||||
@ -1117,14 +1117,14 @@ above:
|
|||||||
["\x19Ethereum Signed Message:\n32", hash]
|
["\x19Ethereum Signed Message:\n32", hash]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function recoverSigner(message, signature) {
|
function recoverSigner(message, signature) {
|
||||||
var split = ethereumjs.Util.fromRpcSig(signature);
|
var split = ethereumjs.Util.fromRpcSig(signature);
|
||||||
var publicKey = ethereumjs.Util.ecrecover(message, split.v, split.r, split.s);
|
var publicKey = ethereumjs.Util.ecrecover(message, split.v, split.r, split.s);
|
||||||
var signer = ethereumjs.Util.pubToAddress(publicKey).toString("hex");
|
var signer = ethereumjs.Util.pubToAddress(publicKey).toString("hex");
|
||||||
return signer;
|
return signer;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isValidSignature(contractAddress, amount, signature, expectedSigner) {
|
function isValidSignature(contractAddress, amount, signature, expectedSigner) {
|
||||||
var message = prefixed(constructPaymentMessage(contractAddress, amount));
|
var message = prefixed(constructPaymentMessage(contractAddress, amount));
|
||||||
var signer = recoverSigner(message, signature);
|
var signer = recoverSigner(message, signature);
|
||||||
|
@ -580,16 +580,18 @@ variables are held).
|
|||||||
Data location
|
Data location
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
Every complex type, i.e. *arrays* and *structs*, has an additional
|
|
||||||
annotation, the "data location", about whether it is stored in memory or in storage. Depending on the
|
|
||||||
context, there is always a default, but it can be overridden by appending
|
|
||||||
either ``storage`` or ``memory`` to the type. The default for function parameters (including return parameters) is ``memory``, the default for local variables is ``storage`` and the location is forced
|
|
||||||
to ``storage`` for state variables (obviously).
|
|
||||||
|
|
||||||
There is also a third data location, ``calldata``, which is a non-modifiable,
|
Every complex type, i.e. *arrays* and *structs*, has an additional
|
||||||
non-persistent area where function arguments are stored. Function parameters
|
annotation, the "data location", about where it is stored. There are three data locations:
|
||||||
(not return parameters) of external functions are forced to ``calldata`` and
|
``memory``, ``storage`` and ``calldata``. Calldata is only valid for parameters of external contract
|
||||||
behave mostly like ``memory``.
|
functions and is required for this type of parameter. Calldata is a non-modifiable,
|
||||||
|
non-persistent area where function arguments are stored, and behaves mostly like memory.
|
||||||
|
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Prior to version 0.5.0 the data location could be omitted, and would default to different locations
|
||||||
|
depending on the kind of variable, function type, etc., but all complex types must now give an explicit
|
||||||
|
data location.
|
||||||
|
|
||||||
Data locations are important because they change how assignments behave:
|
Data locations are important because they change how assignments behave:
|
||||||
assignments between storage and memory and also to a state variable (even from other state variables)
|
assignments between storage and memory and also to a state variable (even from other state variables)
|
||||||
@ -635,10 +637,6 @@ Forced data location:
|
|||||||
- parameters (not return) of external functions: calldata
|
- parameters (not return) of external functions: calldata
|
||||||
- state variables: storage
|
- state variables: storage
|
||||||
|
|
||||||
Default data location:
|
|
||||||
- parameters (also return) of functions: memory
|
|
||||||
- all other local variables: storage
|
|
||||||
|
|
||||||
.. index:: ! array
|
.. index:: ! array
|
||||||
|
|
||||||
.. _arrays:
|
.. _arrays:
|
||||||
|
Loading…
Reference in New Issue
Block a user