Update documentation.

This commit is contained in:
chriseth 2018-08-07 15:10:42 +02:00
parent 683bce1869
commit e3b6c5a4bd
3 changed files with 37 additions and 38 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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: