aboutsummaryrefslogtreecommitdiffstats
path: root/docs/solidity-by-example.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/solidity-by-example.rst')
-rw-r--r--docs/solidity-by-example.rst46
1 files changed, 23 insertions, 23 deletions
diff --git a/docs/solidity-by-example.rst b/docs/solidity-by-example.rst
index 7d325746..adf00546 100644
--- a/docs/solidity-by-example.rst
+++ b/docs/solidity-by-example.rst
@@ -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);