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))``.
|
||||
* 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``.
|
||||
* 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(...)``.
|
||||
|
||||
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 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: 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: 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.
|
||||
@ -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 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.
|
||||
* 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.
|
||||
* 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.
|
||||
|
@ -90,7 +90,7 @@ of votes.
|
||||
// If the first argument of `require` evaluates
|
||||
// to `false`, execution terminates and all
|
||||
// changes to the state and to Ether balances
|
||||
// are reverted.
|
||||
// are reverted.
|
||||
// This used to consume all gas in old EVM versions, but
|
||||
// not anymore.
|
||||
// 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 second action.
|
||||
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.
|
||||
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
|
||||
signed message, we are ready to put the message together, hash it,
|
||||
and sign it. For simplicity, we just concatenate the data.
|
||||
The
|
||||
The
|
||||
`ethereumjs-abi <https://github.com/ethereumjs/ethereumjs-abi>`_ library provides
|
||||
a function called ``soliditySHA3`` that mimics the behavior
|
||||
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"],
|
||||
[recipient, amount, nonce, contractAddress]
|
||||
).toString("hex");
|
||||
|
||||
|
||||
web3.personal.sign(hash, web3.eth.defaultAccount, callback);
|
||||
}
|
||||
|
||||
@ -779,7 +779,7 @@ at the end of this chapter).
|
||||
|
||||
Computing the Message Hash
|
||||
--------------------------
|
||||
|
||||
|
||||
The smart contract needs to know exactly what parameters were signed,
|
||||
and so it must recreate the message from the parameters and use that
|
||||
for signature verification. The functions ``prefixed`` and
|
||||
@ -801,7 +801,7 @@ The full contract
|
||||
|
||||
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]);
|
||||
usedNonces[nonce] = true;
|
||||
|
||||
@ -820,7 +820,7 @@ The full contract
|
||||
}
|
||||
|
||||
/// signature methods.
|
||||
function splitSignature(bytes sig)
|
||||
function splitSignature(bytes memory sig)
|
||||
internal
|
||||
pure
|
||||
returns (uint8 v, bytes32 r, bytes32 s)
|
||||
@ -839,7 +839,7 @@ The full contract
|
||||
return (v, r, s);
|
||||
}
|
||||
|
||||
function recoverSigner(bytes32 message, bytes sig)
|
||||
function recoverSigner(bytes32 message, bytes memory sig)
|
||||
internal
|
||||
pure
|
||||
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.
|
||||
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.
|
||||
|
||||
|
||||
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).
|
||||
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 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.
|
||||
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
|
||||
@ -926,7 +926,7 @@ Here is the modified javascript code to cryptographically sign a message from th
|
||||
[contractAddress, amount]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function signMessage(message, callback) {
|
||||
web3.personal.sign(
|
||||
"0x" + message.toString("hex"),
|
||||
@ -934,10 +934,10 @@ Here is the modified javascript code to cryptographically sign a message from th
|
||||
callback
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// contractAddress is used to prevent cross-contract replay attacks.
|
||||
// amount, in wei, specifies how much Ether should be sent.
|
||||
|
||||
|
||||
function signPayment(contractAddress, amount, callback) {
|
||||
var message = constructPaymentMessage(contractAddress, amount);
|
||||
signMessage(message, callback);
|
||||
@ -1003,7 +1003,7 @@ The full contract
|
||||
expiration = now + duration;
|
||||
}
|
||||
|
||||
function isValidSignature(uint256 amount, bytes signature)
|
||||
function isValidSignature(uint256 amount, bytes memory signature)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
@ -1017,7 +1017,7 @@ The full contract
|
||||
/// the recipient can close the channel at any time by presenting a
|
||||
/// signed amount from the sender. the recipient will be sent that amount,
|
||||
/// 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(isValidSignature(amount, signature));
|
||||
|
||||
@ -1043,7 +1043,7 @@ The full contract
|
||||
/// All functions below this are just taken from the chapter
|
||||
/// 'creating and verifying signatures' chapter.
|
||||
|
||||
function splitSignature(bytes sig)
|
||||
function splitSignature(bytes memory sig)
|
||||
internal
|
||||
pure
|
||||
returns (uint8 v, bytes32 r, bytes32 s)
|
||||
@ -1058,11 +1058,11 @@ The full contract
|
||||
// final byte (first byte of the next 32 bytes)
|
||||
v := byte(0, mload(add(sig, 96)))
|
||||
}
|
||||
|
||||
|
||||
return (v, r, s);
|
||||
}
|
||||
|
||||
function recoverSigner(bytes32 message, bytes sig)
|
||||
|
||||
function recoverSigner(bytes32 message, bytes memory sig)
|
||||
internal
|
||||
pure
|
||||
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
|
||||
openzepplin's `version <https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/ECRecovery.sol>`_ of this code.
|
||||
|
||||
|
||||
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
|
||||
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,
|
||||
but if it's being done in **JavaScript**.
|
||||
@ -1117,14 +1117,14 @@ above:
|
||||
["\x19Ethereum Signed Message:\n32", hash]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function recoverSigner(message, signature) {
|
||||
var split = ethereumjs.Util.fromRpcSig(signature);
|
||||
var publicKey = ethereumjs.Util.ecrecover(message, split.v, split.r, split.s);
|
||||
var signer = ethereumjs.Util.pubToAddress(publicKey).toString("hex");
|
||||
return signer;
|
||||
}
|
||||
|
||||
|
||||
function isValidSignature(contractAddress, amount, signature, expectedSigner) {
|
||||
var message = prefixed(constructPaymentMessage(contractAddress, amount));
|
||||
var signer = recoverSigner(message, signature);
|
||||
|
@ -580,16 +580,18 @@ variables are held).
|
||||
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,
|
||||
non-persistent area where function arguments are stored. Function parameters
|
||||
(not return parameters) of external functions are forced to ``calldata`` and
|
||||
behave mostly like ``memory``.
|
||||
Every complex type, i.e. *arrays* and *structs*, has an additional
|
||||
annotation, the "data location", about where it is stored. There are three data locations:
|
||||
``memory``, ``storage`` and ``calldata``. Calldata is only valid for parameters of external contract
|
||||
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:
|
||||
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
|
||||
- state variables: storage
|
||||
|
||||
Default data location:
|
||||
- parameters (also return) of functions: memory
|
||||
- all other local variables: storage
|
||||
|
||||
.. index:: ! array
|
||||
|
||||
.. _arrays:
|
||||
|
Loading…
Reference in New Issue
Block a user