docs: Fix indentation in some of the code snippets

This commit is contained in:
Kamil Śliwak 2021-07-14 18:56:55 +02:00
parent ce79e2515b
commit 42f982c063
6 changed files with 222 additions and 221 deletions

View File

@ -530,12 +530,12 @@ i.e. ``0xcf479181``, ``uint256(0)``, ``uint256(amount)``.
The error selectors ``0x00000000`` and ``0xffffffff`` are reserved for future use. The error selectors ``0x00000000`` and ``0xffffffff`` are reserved for future use.
.. warning:: .. warning::
Never trust error data. Never trust error data.
The error data by default bubbles up through the chain of external calls, which The error data by default bubbles up through the chain of external calls, which
means that a contract may receive an error not defined in any of the contracts means that a contract may receive an error not defined in any of the contracts
it calls directly. it calls directly.
Furthermore, any contract can fake any error by returning data that matches Furthermore, any contract can fake any error by returning data that matches
an error signature, even if the error is not defined anywhere. an error signature, even if the error is not defined anywhere.
.. _abi_json: .. _abi_json:
@ -619,24 +619,24 @@ would result in the JSON:
.. code-block:: json .. code-block:: json
[{ [{
"type":"error", "type":"error",
"inputs": [{"name":"available","type":"uint256"},{"name":"required","type":"uint256"}], "inputs": [{"name":"available","type":"uint256"},{"name":"required","type":"uint256"}],
"name":"InsufficientBalance" "name":"InsufficientBalance"
}, { }, {
"type":"event", "type":"event",
"inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"bytes32","indexed":false}], "inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"bytes32","indexed":false}],
"name":"Event" "name":"Event"
}, { }, {
"type":"event", "type":"event",
"inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"bytes32","indexed":false}], "inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"bytes32","indexed":false}],
"name":"Event2" "name":"Event2"
}, { }, {
"type":"function", "type":"function",
"inputs": [{"name":"a","type":"uint256"}], "inputs": [{"name":"a","type":"uint256"}],
"name":"foo", "name":"foo",
"outputs": [] "outputs": []
}] }]
Handling tuple types Handling tuple types
-------------------- --------------------
@ -671,61 +671,61 @@ would result in the JSON:
.. code-block:: json .. code-block:: json
[ [
{ {
"name": "f", "name": "f",
"type": "function", "type": "function",
"inputs": [ "inputs": [
{ {
"name": "s", "name": "s",
"type": "tuple", "type": "tuple",
"components": [ "components": [
{ {
"name": "a", "name": "a",
"type": "uint256" "type": "uint256"
}, },
{ {
"name": "b", "name": "b",
"type": "uint256[]" "type": "uint256[]"
}, },
{ {
"name": "c", "name": "c",
"type": "tuple[]", "type": "tuple[]",
"components": [ "components": [
{ {
"name": "x", "name": "x",
"type": "uint256" "type": "uint256"
}, },
{ {
"name": "y", "name": "y",
"type": "uint256" "type": "uint256"
} }
] ]
} }
] ]
}, },
{ {
"name": "t", "name": "t",
"type": "tuple", "type": "tuple",
"components": [ "components": [
{ {
"name": "x", "name": "x",
"type": "uint256" "type": "uint256"
}, },
{ {
"name": "y", "name": "y",
"type": "uint256" "type": "uint256"
} }
] ]
}, },
{ {
"name": "a", "name": "a",
"type": "uint256" "type": "uint256"
} }
], ],
"outputs": [] "outputs": []
} }
] ]
.. _abi_packed_mode: .. _abi_packed_mode:
@ -786,12 +786,12 @@ for prepending a function selector. Since the encoding is ambiguous, there is no
.. warning:: .. warning::
If you use ``keccak256(abi.encodePacked(a, b))`` and both ``a`` and ``b`` are dynamic types, If you use ``keccak256(abi.encodePacked(a, b))`` and both ``a`` and ``b`` are dynamic types,
it is easy to craft collisions in the hash value by moving parts of ``a`` into ``b`` and it is easy to craft collisions in the hash value by moving parts of ``a`` into ``b`` and
vice-versa. More specifically, ``abi.encodePacked("a", "bc") == abi.encodePacked("ab", "c")``. vice-versa. More specifically, ``abi.encodePacked("a", "bc") == abi.encodePacked("ab", "c")``.
If you use ``abi.encodePacked`` for signatures, authentication or data integrity, make If you use ``abi.encodePacked`` for signatures, authentication or data integrity, make
sure to always use the same types and check that at most one of them is dynamic. sure to always use the same types and check that at most one of them is dynamic.
Unless there is a compelling reason, ``abi.encode`` should be preferred. Unless there is a compelling reason, ``abi.encode`` should be preferred.
.. _indexed_event_encoding: .. _indexed_event_encoding:

View File

@ -124,17 +124,17 @@ The output of the above looks like the following (trimmed):
.. code-block:: json .. code-block:: json
{ {
"returnValues": { "returnValues": {
"_from": "0x1111…FFFFCCCC", "_from": "0x1111…FFFFCCCC",
"_id": "0x50…sd5adb20", "_id": "0x50…sd5adb20",
"_value": "0x420042" "_value": "0x420042"
}, },
"raw": { "raw": {
"data": "0x7f…91385", "data": "0x7f…91385",
"topics": ["0xfd4…b4ead7", "0x7f…1a91385"] "topics": ["0xfd4…b4ead7", "0x7f…1a91385"]
} }
} }
Additional Resources for Understanding Events Additional Resources for Understanding Events
============================================== ==============================================

View File

@ -89,21 +89,21 @@ the sequence:
.. code-block:: none .. code-block:: none
PUSH 32 PUSH 32
PUSH 0 PUSH 0
CALLDATALOAD CALLDATALOAD
PUSH 100 PUSH 100
DUP2 DUP2
MSTORE MSTORE
KECCAK256 KECCAK256
or the equivalent Yul or the equivalent Yul
.. code-block:: yul .. code-block:: yul
let x := calldataload(0) let x := calldataload(0)
mstore(x, 100) mstore(x, 100)
let value := keccak256(x, 32) let value := keccak256(x, 32)
In this case, the optimizer tracks the value at a memory location ``calldataload(0)`` and then In this case, the optimizer tracks the value at a memory location ``calldataload(0)`` and then
realizes that the Keccak-256 hash can be evaluated at compile time. This only works if there is no realizes that the Keccak-256 hash can be evaluated at compile time. This only works if there is no
@ -116,14 +116,14 @@ For example,
.. code-block:: yul .. code-block:: yul
let x := calldataload(0) let x := calldataload(0)
mstore(x, 100) mstore(x, 100)
// Current knowledge memory location x -> 100 // Current knowledge memory location x -> 100
let y := add(x, 32) let y := add(x, 32)
// Does not clear the knowledge that x -> 100, since y does not write to [x, x + 32) // Does not clear the knowledge that x -> 100, since y does not write to [x, x + 32)
mstore(y, 200) mstore(y, 200)
// This Keccak-256 can now be evaluated // This Keccak-256 can now be evaluated
let value := keccak256(x, 32) let value := keccak256(x, 32)
Therefore, modifications to storage and memory locations, of say location ``l``, must erase Therefore, modifications to storage and memory locations, of say location ``l``, must erase
knowledge about storage or memory locations which may be equal to ``l``. More specifically, for knowledge about storage or memory locations which may be equal to ``l``. More specifically, for
@ -239,8 +239,8 @@ for all references to ``tag_f`` leaving it unused, s.t. it can be removed, yield
.. code-block:: text .. code-block:: text
...body of function f... ...body of function f...
...opcodes after call to f... ...opcodes after call to f...
So the call to function ``f`` is inlined and the original definition of ``f`` can be removed. So the call to function ``f`` is inlined and the original definition of ``f`` can be removed.
@ -375,7 +375,7 @@ After this step, a program has the following normal form:
.. code-block:: text .. code-block:: text
{ I F... } { I F... }
Where ``I`` is a (potentially empty) block that does not contain any function definitions (not even recursively) Where ``I`` is a (potentially empty) block that does not contain any function definitions (not even recursively)
and ``F`` is a list of function definitions such that no function contains a function definition. and ``F`` is a list of function definitions such that no function contains a function definition.
@ -1053,8 +1053,8 @@ remove the parameter and create a new "linking" function as follows:
.. code-block:: yul .. code-block:: yul
function f(a,b) -> x { x := div(a,b) } function f(a,b) -> x { x := div(a,b) }
function f2(a,b,c) -> x, y { x := f(a,b) } function f2(a,b,c) -> x, y { x := f(a,b) }
and replace all references to ``f`` by ``f2``. and replace all references to ``f`` by ``f2``.
The inliner should be run afterwards to make sure that all references to ``f2`` are replaced by The inliner should be run afterwards to make sure that all references to ``f2`` are replaced by

View File

@ -182,7 +182,7 @@ At a global level, you can use import statements of the following form:
:: ::
import "filename"; import "filename";
The ``filename`` part is called an *import path*. The ``filename`` part is called an *import path*.
This statement imports all global symbols from "filename" (and symbols imported there) into the This statement imports all global symbols from "filename" (and symbols imported there) into the
@ -197,7 +197,7 @@ the global symbols from ``"filename"``:
:: ::
import * as symbolName from "filename"; import * as symbolName from "filename";
which results in all global symbols being available in the format ``symbolName.symbol``. which results in all global symbols being available in the format ``symbolName.symbol``.
@ -215,7 +215,7 @@ the code below creates new global symbols ``alias`` and ``symbol2`` which refere
:: ::
import {symbol1 as alias, symbol2} from "filename"; import {symbol1 as alias, symbol2} from "filename";
.. index:: virtual filesystem, source unit name, import; path, filesystem path, import callback, Remix IDE .. index:: virtual filesystem, source unit name, import; path, filesystem path, import callback, Remix IDE
@ -255,12 +255,12 @@ Single-line comments (``//``) and multi-line comments (``/*...*/``) are possible
:: ::
// This is a single-line comment. // This is a single-line comment.
/* /*
This is a This is a
multi-line comment. multi-line comment.
*/ */
.. note:: .. note::
A single-line comment is terminated by any unicode line terminator A single-line comment is terminated by any unicode line terminator

View File

@ -44,23 +44,24 @@ where the default is no engine. Selecting the engine enables the SMTChecker on a
.. note:: .. note::
Prior to Solidity 0.8.4, the default way to enable the SMTChecker was via Prior to Solidity 0.8.4, the default way to enable the SMTChecker was via
``pragma experimental SMTChecker;`` and only the contracts containing the ``pragma experimental SMTChecker;`` and only the contracts containing the
pragma would be analyzed. That pragma has been deprecated, and although it pragma would be analyzed. That pragma has been deprecated, and although it
still enables the SMTChecker for backwards compatibility, it will be removed still enables the SMTChecker for backwards compatibility, it will be removed
in Solidity 0.9.0. Note also that now using the pragma even in a single file in Solidity 0.9.0. Note also that now using the pragma even in a single file
enables the SMTChecker for all files. enables the SMTChecker for all files.
.. note:: .. note::
The lack of warnings for a verification target represents an undisputed
mathematical proof of correctness, assuming no bugs in the SMTChecker and The lack of warnings for a verification target represents an undisputed
the underlying solver. Keep in mind that these problems are mathematical proof of correctness, assuming no bugs in the SMTChecker and
*very hard* and sometimes *impossible* to solve automatically in the the underlying solver. Keep in mind that these problems are
general case. Therefore, several properties might not be solved or might *very hard* and sometimes *impossible* to solve automatically in the
lead to false positives for large contracts. Every proven property should general case. Therefore, several properties might not be solved or might
be seen as an important achievement. For advanced users, see :ref:`SMTChecker Tuning <smtchecker_options>` lead to false positives for large contracts. Every proven property should
to learn a few options that might help proving more complex be seen as an important achievement. For advanced users, see :ref:`SMTChecker Tuning <smtchecker_options>`
properties. to learn a few options that might help proving more complex
properties.
******** ********
Tutorial Tutorial
@ -202,8 +203,9 @@ Note that in this example the SMTChecker will automatically try to prove three p
3. The assertion is always true. 3. The assertion is always true.
.. note:: .. note::
The properties involve loops, which makes it *much much* harder than the previous
examples, so beware of loops! The properties involve loops, which makes it *much much* harder than the previous
examples, so beware of loops!
All the properties are correctly proven safe. Feel free to change the All the properties are correctly proven safe. Feel free to change the
properties and/or add restrictions on the array to see different results. properties and/or add restrictions on the array to see different results.
@ -233,18 +235,18 @@ gives us:
.. code-block:: bash .. code-block:: bash
Warning: CHC: Assertion violation happens here. Warning: CHC: Assertion violation happens here.
Counterexample: Counterexample:
_a = [0, 0, 0, 0, 0] _a = [0, 0, 0, 0, 0]
= 0 = 0
Transaction trace: Transaction trace:
Test.constructor() Test.constructor()
Test.max([0, 0, 0, 0, 0]) Test.max([0, 0, 0, 0, 0])
--> max.sol:14:4: --> max.sol:14:4:
| |
14 | assert(m > _a[i]); 14 | assert(m > _a[i]);
State Properties State Properties
@ -323,26 +325,26 @@ the SMTChecker tells us exactly *how* to reach (2, 4):
.. code-block:: bash .. code-block:: bash
Warning: CHC: Assertion violation happens here. Warning: CHC: Assertion violation happens here.
Counterexample: Counterexample:
x = 2, y = 4 x = 2, y = 4
Transaction trace: Transaction trace:
Robot.constructor() Robot.constructor()
State: x = 0, y = 0 State: x = 0, y = 0
Robot.moveLeftUp() Robot.moveLeftUp()
State: x = (- 1), y = 1 State: x = (- 1), y = 1
Robot.moveRightUp() Robot.moveRightUp()
State: x = 0, y = 2 State: x = 0, y = 2
Robot.moveRightUp() Robot.moveRightUp()
State: x = 1, y = 3 State: x = 1, y = 3
Robot.moveRightUp() Robot.moveRightUp()
State: x = 2, y = 4 State: x = 2, y = 4
Robot.reach_2_4() Robot.reach_2_4()
--> r.sol:35:4: --> r.sol:35:4:
| |
35 | assert(!(x == 2 && y == 4)); 35 | assert(!(x == 2 && y == 4));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note that the path above is not necessarily deterministic, as there are Note that the path above is not necessarily deterministic, as there are
other paths that could reach (2, 4). The choice of which path is shown other paths that could reach (2, 4). The choice of which path is shown
@ -367,36 +369,36 @@ anything, including reenter the caller contract.
pragma solidity >=0.8.0; pragma solidity >=0.8.0;
interface Unknown { interface Unknown {
function run() external; function run() external;
} }
contract Mutex { contract Mutex {
uint x; uint x;
bool lock; bool lock;
Unknown immutable unknown; Unknown immutable unknown;
constructor(Unknown _u) { constructor(Unknown _u) {
require(address(_u) != address(0)); require(address(_u) != address(0));
unknown = _u; unknown = _u;
} }
modifier mutex { modifier mutex {
require(!lock); require(!lock);
lock = true; lock = true;
_; _;
lock = false; lock = false;
} }
function set(uint _x) mutex public { function set(uint _x) mutex public {
x = _x; x = _x;
} }
function run() mutex public { function run() mutex public {
uint xPre = x; uint xPre = x;
unknown.run(); unknown.run();
assert(xPre == x); assert(xPre == x);
} }
} }
The example above shows a contract that uses a mutex flag to forbid reentrancy. The example above shows a contract that uses a mutex flag to forbid reentrancy.
@ -410,20 +412,20 @@ that the assertion fails:
.. code-block:: bash .. code-block:: bash
Warning: CHC: Assertion violation happens here. Warning: CHC: Assertion violation happens here.
Counterexample: Counterexample:
x = 1, lock = true, unknown = 1 x = 1, lock = true, unknown = 1
Transaction trace: Transaction trace:
Mutex.constructor(1) Mutex.constructor(1)
State: x = 0, lock = false, unknown = 1 State: x = 0, lock = false, unknown = 1
Mutex.run() Mutex.run()
unknown.run() -- untrusted external call, synthesized as: unknown.run() -- untrusted external call, synthesized as:
Mutex.set(1) -- reentrant call Mutex.set(1) -- reentrant call
--> m.sol:32:3: --> m.sol:32:3:
| |
32 | assert(xPre == x); 32 | assert(xPre == x);
| ^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^
.. _smtchecker_options: .. _smtchecker_options:
@ -494,12 +496,11 @@ which has the following form:
.. code-block:: none .. code-block:: none
contracts contracts
{ {
"source1.sol": ["contract1"], "source1.sol": ["contract1"],
"source2.sol": ["contract2", "contract3"] "source2.sol": ["contract2", "contract3"]
} }
.. _smtchecker_engines: .. _smtchecker_engines:

View File

@ -136,13 +136,13 @@ key in the ``"settings"`` field:
.. code-block:: none .. code-block:: none
{ {
"sources": { ... }, "sources": { ... },
"settings": { "settings": {
"optimizer": { ... }, "optimizer": { ... },
"evmVersion": "<VERSION>" "evmVersion": "<VERSION>"
}
} }
}
Target Options Target Options
-------------- --------------
@ -781,7 +781,7 @@ It is recommended to explicitly specify the upgrade modules by using ``--modules
.. code-block:: none .. code-block:: none
$ solidity-upgrade --modules constructor-visibility,now,dotsyntax Source.sol $ solidity-upgrade --modules constructor-visibility,now,dotsyntax Source.sol
The command above applies all changes as shown below. Please review them carefully (the pragmas will The command above applies all changes as shown below. Please review them carefully (the pragmas will
have to be updated manually.) have to be updated manually.)