From de93610bd30014158a726abd2cc4916736139e94 Mon Sep 17 00:00:00 2001 From: iamdefinitelyahuman Date: Sat, 28 Dec 2019 01:50:06 +0200 Subject: [PATCH 1/2] minor docs updates --- docs/built-in-functions.rst | 8 +++++- docs/contributing.rst | 5 ++-- docs/index.rst | 55 ++++++++++++------------------------- docs/release-notes.rst | 12 ++++---- 4 files changed, 32 insertions(+), 48 deletions(-) diff --git a/docs/built-in-functions.rst b/docs/built-in-functions.rst index 53020fe2bd..d74f25e0b6 100644 --- a/docs/built-in-functions.rst +++ b/docs/built-in-functions.rst @@ -93,7 +93,13 @@ contracts. .. py:function:: ecrecover(hash: bytes32, v: uint256, r: uint256, s: uint256) -> address - Takes a signed hash and vrs and returns the public key of the signer. + Recovers the address associated with the public key from the given elliptic curve signature. + + * ``r``: first 32 bytes of signature + * ``s``: second 32 bytes of signature + * ``v``: final 1 byte of signature + + Returns the associated address, or ``0`` on error. .. py:function:: ecadd(a: uint256[2], b: uint256[2]) -> uint256[2] diff --git a/docs/contributing.rst b/docs/contributing.rst index 7696418532..d5cc7d3565 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -52,7 +52,7 @@ Style Guide =========== -Vyper's codebase follows the +Vyper's codebase follows the `Snake Charmer's Style Guide `_. Some of the things not covered by style guide that we maintain in our codebase is the use of `f-strings `_ across the repository (when helpful for clarity), @@ -71,8 +71,7 @@ and instead, ``git rebase`` your branch. **Implement Features** -If you are writing a new feature, please ensure you write appropriate -Boost test cases and place them under ``tests/``. +If you are writing a new feature, please ensure you write appropriate Pytest test cases and place them under ``tests/``. If you are making a larger change, please consult first with the Gitter channel. diff --git a/docs/index.rst b/docs/index.rst index 7fc9a90e23..87ba14cdaf 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,8 +1,3 @@ -.. Vyper documentation master file, created by - sphinx-quickstart on Wed Jul 26 11:18:29 2017. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - Vyper ##### @@ -16,47 +11,31 @@ Vyper is a contract-oriented, pythonic programming language that targets the `Et Principles and Goals ******************** -* **Security:** It should be possible and natural to build secure smart-contracts in Vyper. -* **Language and compiler simplicity:** The language and the compiler implementation should strive to be simple. -* **Auditability:** Vyper code should be maximally human-readable. Furthermore, it should be maximally difficult to write misleading code. Simplicity for the reader - is more important than simplicity for the writer, and simplicity for readers with low prior experience with Vyper (and low prior experience with programming in - general) is particularly important. +* **Security**: It should be possible and natural to build secure smart-contracts in Vyper. +* **Language and compiler simplicity**: The language and the compiler implementation should strive to be simple. +* **Auditability**: Vyper code should be maximally human-readable. Furthermore, it should be maximally difficult to write misleading code. Simplicity for the reader is more important than simplicity for the writer, and simplicity for readers with low prior experience with Vyper (and low prior experience with programming in general) is particularly important. -Because of this Vyper aims to provide the following features: +Because of this Vyper provides the following features: -* **Bounds and overflow checking:** On array accesses as well as on arithmetic level. +* **Bounds and overflow checking**: On array accesses and arithmetic. * **Support for signed integers and decimal fixed point numbers** -* **Decidability:** It should be possible to compute a precise upper bound for the gas consumption of any function call. -* **Strong typing:** Including support for units (e.g. timestamp, timedelta, seconds, wei, wei per second, meters per second squared). +* **Decidability**: It is possible to compute a precise upper bound for the gas consumption of any Vyper function call. +* **Strong typing**: Including support for units (e.g. timestamp, timedelta, seconds, wei, wei per second, meters per second squared). * **Small and understandable compiler code** -* **Limited support for pure functions:** Anything marked constant is not allowed to change the state. +* **Limited support for pure functions**: Anything marked constant is not allowed to change the state. Following the principles and goals, Vyper **does not** provide the following features: -* **Modifiers**: For example in Solidity you can define a ``function foo() mod1 { ... }``, where ``mod1`` can be defined elsewhere in the code to include a check that is done before execution, - a check that is done after execution, some state changes, or possibly other things. Vyper does not have this, because it makes it too easy to write misleading code. ``mod1`` just looks - too innocuous for something that could add arbitrary pre-conditions, post-conditions or state changes. Also, it encourages people to write code where the execution jumps around the file, - harming auditability. The usual use case for a modifier is something that performs a single check before execution of a program; our recommendation is to simply inline these checks as asserts. -* **Class inheritance:** Class inheritance requires people to jump between multiple files to understand what a program is doing, and requires people to understand the rules of precedence in case of conflicts - ("Which class's function 'X' is the one that's actually used?"). Hence, it makes code too complicated to understand which negatively impacts auditability. -* **Inline assembly:** Adding inline assembly would make it no longer possible to search for a variable name in order to find all instances where that variable is read or modified. -* **Function overloading** - This can cause lots of confusion on which function is called at any given time. Thus it's easier to write missleading code (``foo("hello")`` logs "hello" but ``foo("hello", "world")`` steals you funds). - Another problem with function overloading is that it makes the code much harder to search through as you have to keep track on which call refers to which function. -* **Operator overloading:** Operator overloading makes writing misleading code possible. For example "+" could be overloaded so that it executes commands that are not visible at a first glance, such as sending funds the - user did not want to send. -* **Recursive calling:** Recursive calling makes it impossible to set an upper bound on gas limits, opening the door for gas limit attacks. -* **Infinite-length loops:** Similar to recursive calling, infinite-length loops make it impossible to set an upper bound on gas limits, opening the door for gas limit attacks. -* **Binary fixed point:** Decimal fixed point is better, because any decimal fixed point value written as a literal in code has an exact representation, whereas with binary fixed point approximations are often required - (e.g. (0.2)\ :sub:`10` = (0.001100110011...)\ :sub:`2`, which needs to be truncated), leading to unintuitive results, e.g. in Python 0.3 + 0.3 + 0.3 + 0.1 != 1. - - -Some changes that may be considered after Metropolis when `STATICCALL `_ becomes available include: - -* Forbidding state changes after non-static calls unless the address being non-statically called is explicitly marked "trusted". This would reduce risk of re-entrancy attacks. -* Forbidding "inline" non-static calls, e.g. `send(some_address, contract.do_something_and_return_a_weivalue())`, enforcing clear separation between "call to get a response" and "call to do something". +* **Modifiers**: For example in Solidity you can define a ``function foo() mod1 { ... }``, where ``mod1`` can be defined elsewhere in the code to include a check that is done before execution, a check that is done after execution, some state changes, or possibly other things. Vyper does not have this, because it makes it too easy to write misleading code. ``mod1`` just looks too innocuous for something that could add arbitrary pre-conditions, post-conditions or state changes. Also, it encourages people to write code where the execution jumps around the file, harming auditability. The usual use case for a modifier is something that performs a single check before execution of a program; our recommendation is to simply inline these checks as asserts. +* **Class inheritance**: Class inheritance requires people to jump between multiple files to understand what a program is doing, and requires people to understand the rules of precedence in case of conflicts ("Which class's function ``X`` is the one that's actually used?"). Hence, it makes code too complicated to understand which negatively impacts auditability. +* **Inline assembly**: Adding inline assembly would make it no longer possible to search for a variable name in order to find all instances where that variable is read or modified. +* **Function overloading**: This can cause lots of confusion on which function is called at any given time. Thus it's easier to write missleading code (``foo("hello")`` logs "hello" but ``foo("hello", "world")`` steals your funds). Another problem with function overloading is that it makes the code much harder to search through as you have to keep track on which call refers to which function. +* **Operator overloading**: Operator overloading makes writing misleading code possible. For example ``+`` could be overloaded so that it executes commands that are not visible at a first glance, such as sending funds the user did not want to send. +* **Recursive calling**: Recursive calling makes it impossible to set an upper bound on gas limits, opening the door for gas limit attacks. +* **Infinite-length loops**: Similar to recursive calling, infinite-length loops make it impossible to set an upper bound on gas limits, opening the door for gas limit attacks. +* **Binary fixed point**: Decimal fixed point is better, because any decimal fixed point value written as a literal in code has an exact representation, whereas with binary fixed point approximations are often required (e.g. (0.2)\ :sub:`10` = (0.001100110011...)\ :sub:`2`, which needs to be truncated), leading to unintuitive results, e.g. in Python 0.3 + 0.3 + 0.3 + 0.1 != 1. -Vyper does NOT strive to be a 100% replacement for everything that can be done in Solidity; it will deliberately forbid things or make things harder if it deems fit to do so for the goal of -increasing security. +Vyper **does not** strive to be a 100% replacement for everything that can be done in Solidity; it will deliberately forbid things or make things harder if it deems fit to do so for the goal of increasing security. Glossary ******** diff --git a/docs/release-notes.rst b/docs/release-notes.rst index 996260ffff..f47bbb79f6 100644 --- a/docs/release-notes.rst +++ b/docs/release-notes.rst @@ -32,7 +32,7 @@ Date released: 27-09-2019 The following VIPs were implemented for Beta 13: -- Add `vyper-json` compilation mode (VIP `#1520 `_) +- Add ``vyper-json`` compilation mode (VIP `#1520 `_) - Environment variables and constants can now be used as default parameters (VIP `#1525 `_) - Require unitialized memory be set on creation (VIP `#1493 `_) @@ -41,7 +41,7 @@ Some of the bug and stability fixes: - Type check for default params and arrays (`#1596 `_) - Fixed bug when using assertions inside for loops (`#1619 `_) - Fixed zero padding error for ABI encoder (`#1611 `_) -- Check `calldatasize` before `calldataload` for function selector (`#1606 `_) +- Check ``calldatasize`` before ``calldataload`` for function selector (`#1606 `_) v0.1.0-beta.12 ************** @@ -79,7 +79,7 @@ Beta 11 brings some performance and stability fixes. - Improvements for Windows users (`#1486 `_) (`#1488 `_) - Array copy optimisation (`#1487 `_) - Fixing ``@nonreentrant`` decorator for return statements (`#1532 `_) -- `sha3` builtin function removed (`#1328 `_) +- ``sha3`` builtin function removed (`#1328 `_) - Disallow conflicting method IDs (`#1530 `_) - Additional ``convert()`` supported types (`#1524 `_) (`#1500 `_) - Equality operator for strings and bytes (`#1507 `_) @@ -110,9 +110,9 @@ v0.1.0-beta.9 Date released: 12-03-2019 - Add support for list constants (`#1211 `_) -- Add sha256 function (`#1327 `_) -- Renamed create_with_code_of to create_forwarder_to (`#1177 `_) -- @nonreentrant Decorator (`#1204 `_) +- Add ``sha256`` function (`#1327 `_) +- Renamed ``create_with_code_of`` to ``create_forwarder_to`` (`#1177 `_) +- ``@nonreentrant`` Decorator (`#1204 `_) - Add opcodes and opcodes_runtime flags to compiler (`#1255 `_) - Improved External contract call interfaces (`#885 `_) From 5d066574d4c899c7a226c33a7d11f705f334637e Mon Sep 17 00:00:00 2001 From: iamdefinitelyahuman Date: Sat, 28 Dec 2019 14:03:06 +0200 Subject: [PATCH 2/2] add basic documentation for self variable --- docs/constants-and-vars.rst | 136 +++++++++++++++++++++---------- docs/structure-of-a-contract.rst | 95 ++++++++++----------- docs/types.rst | 2 + 3 files changed, 144 insertions(+), 89 deletions(-) diff --git a/docs/constants-and-vars.rst b/docs/constants-and-vars.rst index 1b9dc5df2e..9f41ae2447 100644 --- a/docs/constants-and-vars.rst +++ b/docs/constants-and-vars.rst @@ -1,10 +1,85 @@ .. index:: type -.. _types: - -Constants and Environment Variables +Environment Variables and Constants *********************************** +.. _types-env-vars: + +Environment Variables +===================== + +Environment variables always exist in the namespace and are primarily used to provide information about the blockchain or current transaction. + +Block and Transaction Properties +-------------------------------- + +==================== ================ ============================================= +Name Type Value +==================== ================ ============================================= +``block.coinbase`` ``address`` Current block miner’s address +``block.difficulty`` ``uint256`` Current block difficulty +``block.number`` ``uint256`` Current block number +``block.prevhash`` ``bytes32`` Equivalent to ``blockhash(block.number - 1)`` +``block.timestamp`` ``uint256`` Current block epoch timestamp +``msg.gas`` ``uint256`` Remaining gas +``msg.sender`` ``address`` Sender of the message (current call) +``msg.value`` ``uint256(wei)`` Number of wei sent with the message +``tx.origin`` ``address`` Sender of the transaction (full call chain) +==================== ================ ============================================= + +.. note:: + + ``msg.sender`` and ``msg.value`` can only be accessed from public functions. If you require these values within a private function they must be passed as parameters. + +.. _constants-self: + +The self Variable +----------------- + +``self`` is an environment variable used to reference a contract from within itself. Along with the normal :ref:`address
` members, ``self`` allows you to read and write to state variables and to call private functions within the contract. + +==================== ================ ========================== +Name Type Value +==================== ================ ========================== +``self`` ``address`` Current contract's address +``self.balance`` ``uint256(wei)`` Current contract's balance +==================== ================ ========================== + +Accessing State Variables +~~~~~~~~~~~~~~~~~~~~~~~~~ + +``self`` is used to access a contract's :ref:`state variables`, as shown in the following example: + +.. code-block:: python + + state_var: uint256 + + @public + def set_var(value: uint256) -> bool: + self.state_var = value + return True + + @public + @constant + def get_var() -> uint256: + return self.state_var + + +Calling Private Functions +~~~~~~~~~~~~~~~~~~~~~~~~~ + +``self`` is also used to call :ref:`private functions` within a contract: + +.. code-block:: python + + @private + def _times_two(amount: uint256) -> uint256: + return amount * 2 + + @public + def calculate(amount: uint256) -> uint256: + return self._times_two(amount) + .. _types-constants: Built In Constants @@ -31,50 +106,27 @@ Custom Constants Custom constants can be defined at a global level in Vyper. To define a constant make use of the ``constant`` keyword. **Example:** -:: - TOTAL_SUPPLY: constant(uint256) = 10000000 - total_supply: public(uint256) +.. code-block:: python - @public - def __init__(): - self.total_supply = TOTAL_SUPPLY + TOTAL_SUPPLY: constant(uint256) = 10000000 + total_supply: public(uint256) -**Advanced Example:** -:: - - units: { - share: "Share unit" - } - - MAX_SHARES: constant(uint256(share)) = 1000 - SHARE_PRICE: constant(uint256(wei/share)) = 5 - - @public - def market_cap() -> uint256(wei): - return MAX_SHARES * SHARE_PRICE + @public + def __init__(): + self.total_supply = TOTAL_SUPPLY -.. _types-env-vars: - -Environment Variables -===================== +**Advanced Example:** -Environment variables always exist in the namespace and are used to provide information about the blockchain or current transaction. +.. code-block:: python -.. note:: + units: { + share: "Share unit" + } - ``msg.sender`` and ``msg.value`` can only be accessed from public functions. If you require these values within a private function they must be passed as parameters. + MAX_SHARES: constant(uint256(share)) = 1000 + SHARE_PRICE: constant(uint256(wei/share)) = 5 -==================== ================ ============================================= -Name Type Value -==================== ================ ============================================= -``block.coinbase`` ``address`` Current block miner’s address -``block.difficulty`` ``uint256`` Current block difficulty -``block.number`` ``uint256`` Current block number -``block.prevhash`` ``bytes32`` Equivalent to ``blockhash(block.number - 1)`` -``block.timestamp`` ``uint256`` Current block epoch timestamp -``msg.gas`` ``uint256`` Remaining gas -``msg.sender`` ``address`` Sender of the message (current call) -``msg.value`` ``uint256(wei)`` Number of wei sent with the message -``tx.origin`` ``address`` Sender of the transaction (full call chain) -==================== ================ ============================================= + @public + def market_cap() -> uint256(wei): + return MAX_SHARES * SHARE_PRICE diff --git a/docs/structure-of-a-contract.rst b/docs/structure-of-a-contract.rst index 82f2decc31..3e6f19fb7a 100644 --- a/docs/structure-of-a-contract.rst +++ b/docs/structure-of-a-contract.rst @@ -15,10 +15,10 @@ Versions Vyper supports version pragma which is used to reject being compiled with future compiler versions that might introduce incompatible changes. -:: +.. code-block:: python + + # @version 0.1.0b13 - # @version 0.1.0b13 - The version pragma checks that the compiler version is not a major version. .. _structure-state-variables: @@ -26,11 +26,11 @@ The version pragma checks that the compiler version is not a major version. State Variables =============== -State variables are values which are permanently stored in contract storage. +State variables are values which are permanently stored in contract storage. They must be declared at deployment (outside of any functions), and if not initialized they will take the corresponding :ref:`initial value` for their type. State variables are accessed via the :ref:`self` variable. -:: +.. code-block:: python - storedData: int128 + storedData: int128 See the :ref:`types` section for valid state variable types. @@ -41,12 +41,12 @@ Functions Functions are the executable units of code within a contract. -:: +.. code-block:: python - @public - @payable - def bid(): // Function - // ... + @public + @payable + def bid(): // Function + // ... Function calls can happen internally or externally and have different levels of visibility (see :ref:`structure-decorators`) towards other contracts. Functions must be explicitely declared as public or private. @@ -58,12 +58,14 @@ Public functions (decorated with ``@public``) are a part of the contract interfa Public functions in Vyper are equivalent to external functions in Solidity. +.. _structure-functions-private: + Private Functions ----------------- -Private functions (decorated with ``@private``) are only accessible from other functions within the same contract. They are called via the ``self`` variable: +Private functions (decorated with ``@private``) are only accessible from other functions within the same contract. They are called via the :ref:`self` variable: -:: +.. code-block:: python @private def _times_two(amount: uint256) -> uint256: @@ -80,8 +82,7 @@ Private functions do not have access to ``msg.sender`` or ``msg.value``. If you Non-reentrant Functions ----------------------- -The `@nonreentrant()` decorator places a lock on the current function, and all functions with the same `` value. An attempt by an external contract to call back into any of these functions will cause a REVERT call. - +The ``@nonreentrant()`` decorator places a lock on the current function, and all functions with the same ```` value. An attempt by an external contract to call back into any of these functions will cause a ``REVERT`` call. Decorators ---------- @@ -113,7 +114,7 @@ If the function is annotated as ``@payable``, this function is executed whenever **Example:** -:: +.. code-block:: python Payment: event({amount: int128, from: indexed(address)}) @@ -125,7 +126,7 @@ If the function is annotated as ``@payable``, this function is executed whenever Considerations ~~~~~~~~~~~~~~ -Just as in Solidity, Vyper generates a default function if one isn't found, in the form of a REVERT call. Note that this still `generates an exception `_ and thus will not succeed in receiving funds. +Just as in Solidity, Vyper generates a default function if one isn't found, in the form of a ``REVERT`` call. Note that this still `generates an exception `_ and thus will not succeed in receiving funds. Ethereum specifies that the operations will be rolled back if the contract runs out of gas in execution. ``send`` calls to the contract come with a free stipend of 2300 gas, which does not leave much room to perform other operations except basic logging. **However**, if the sender includes a higher gas amount through a ``call`` instead of ``send``, then more complex functionality can be run. @@ -149,7 +150,7 @@ Events Events may be logged in specially indexed data structures that allow clients, including light clients, to efficiently search for them. -:: +.. code-block:: python Payment: event({amount: int128, arg2: indexed(address)}) @@ -163,46 +164,46 @@ Events may be logged in specially indexed data structures that allow clients, in Events must be declared before global declarations and function definitions. -.. structure-metadata: +.. _structure-metadata: NatSpec Metadata ================ Vyper supports structured documentation for state variables and functions and events. -:: +.. code-block:: python - carrotsEaten: int128 - """ - @author Bob Clampett - @notice Number of carrots eaten - @dev Chewing does not count, carrots must pass the throat to be "eaten" - """ + carrotsEaten: int128 + """ + @author Bob Clampett + @notice Number of carrots eaten + @dev Chewing does not count, carrots must pass the throat to be "eaten" + """ -:: +.. code-block:: python - @public - @payable - def doesEat(food: string): - """ - @author Bob Clampett - @notice Determine if Bugs will accept `food` to eat - @dev Compares the entire string and does not rely on a hash - @param food The name of a food to evaluate (in English) - @return true if Bugs will eat it, false otherwise - """ + @public + @payable + def doesEat(food: string): + """ + @author Bob Clampett + @notice Determine if Bugs will accept `food` to eat + @dev Compares the entire string and does not rely on a hash + @param food The name of a food to evaluate (in English) + @return true if Bugs will eat it, false otherwise + """ - // ... + // ... -:: +.. code-block:: python - Ate: event({food: string}) - """ - @author Bob Clampett - @notice Bugs did eat `food` - @dev Chewing does not count, carrots must pass the throat to be "eaten" - @param food The name of a food that was eaten (in English) - """ + Ate: event({food: string}) + """ + @author Bob Clampett + @notice Bugs did eat `food` + @dev Chewing does not count, carrots must pass the throat to be "eaten" + @param food The name of a food that was eaten (in English) + """ Additional information about Ethereum Natural Specification (NatSpec) can be found `here `_. @@ -248,7 +249,7 @@ The interface name can also be used as a type annotation for storage variables. Specifying ``modifying`` annotation indicates that the call made to the external contract will be able to alter storage, whereas the ``constant`` call will use a ``STATICCALL`` ensuring no storage can be altered during execution. -:: +.. code-block:: python contract FooBar: def calculate() -> uint256: constant diff --git a/docs/types.rst b/docs/types.rst index 9517e1166e..abb41fdcaa 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -483,6 +483,8 @@ Here ``_KeyType`` can be any base or bytes type. Mappings, contract or structs a .. index:: !initial +.. _types-initial: + Initial Values **************