diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 0000000000..bb81012240 --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,18 @@ +version: 2 + +build: + os: ubuntu-24.04 + tools: + python: "3.13" + +sphinx: + builder: html + configuration: docs/conf.py + +formats: + - pdf + - epub + +python: + install: + - requirements: docs/requirements.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 18af34d26b..685df98095 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required(VERSION 3.13.0) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + set(ETH_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}/cmake" CACHE PATH "The path to the cmake directory") list(APPEND CMAKE_MODULE_PATH ${ETH_CMAKE_DIR}) @@ -21,7 +23,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.8.25") +set(PROJECT_VERSION "0.8.35") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) @@ -34,19 +36,39 @@ endif() option(SOLC_LINK_STATIC "Link solc executable statically on supported platforms" OFF) option(SOLC_STATIC_STDLIBS "Link solc against static versions of libgcc and libstdc++ on supported platforms" OFF) -option(STRICT_Z3_VERSION "Use the latest version of Z3" ON) +option(STRICT_Z3_VERSION "Require the exact version of Z3 solver expected by our test suite." ON) option(PEDANTIC "Enable extra warnings and pedantic build flags. Treat all warnings as errors." ON) option(PROFILE_OPTIMIZER_STEPS "Output performance metrics for the optimiser steps." OFF) +option( + IGNORE_VENDORED_DEPENDENCIES + "Ignore libraries provided as submodules of the repository and allow CMake to look for \ +them in the typical locations, including system-wide dirs." + OFF +) +option( + ONLY_BUILD_SOLIDITY_LIBRARIES + "Only build library targets that can be statically linked against. Do not build executables or tests." + OFF +) +mark_as_advanced(PROFILE_OPTIMIZER_STEPS) +mark_as_advanced(IGNORE_VENDORED_DEPENDENCIES) +mark_as_advanced(ONLY_BUILD_SOLIDITY_LIBRARIES) # Setup cccache. include(EthCcache) # Let's find our dependencies include(EthDependencies) -include(fmtlib) -include(jsoncpp) -include(range-v3) -include_directories(SYSTEM ${JSONCPP_INCLUDE_DIR}) +if (NOT IGNORE_VENDORED_DEPENDENCIES) + include(fmtlib) + include(nlohmann-json) + include(range-v3) +else () + message(WARNING "-- Ignoring vendored dependencies. Will use installed versions if found. Versions may differ from the ones the compiler was tested with. Make sure to run the test suite and thoroughly test the resulting binaries before using them in production.") + find_package(fmt REQUIRED) + find_package(nlohmann_json REQUIRED) + find_package(range-v3 REQUIRED) +endif() find_package(Threads) @@ -75,62 +97,31 @@ configure_file("${PROJECT_SOURCE_DIR}/cmake/templates/license.h.in" include/lice include(EthOptions) configure_project(TESTS) -set(LATEST_Z3_VERSION "4.12.1") -set(MINIMUM_Z3_VERSION "4.8.16") -find_package(Z3) -if (${Z3_FOUND}) - if (${STRICT_Z3_VERSION}) - if (NOT ("${Z3_VERSION_STRING}" VERSION_EQUAL ${LATEST_Z3_VERSION})) - message( - FATAL_ERROR - "SMTChecker tests require Z3 ${LATEST_Z3_VERSION} for all tests to pass.\n\ -Build with -DSTRICT_Z3_VERSION=OFF if you want to use a different version. \ -You can also use -DUSE_Z3=OFF to build without Z3. In both cases use --no-smt when running tests." - ) - endif() - else() - if ("${Z3_VERSION_STRING}" VERSION_LESS ${MINIMUM_Z3_VERSION}) - message( - FATAL_ERROR - "Solidity requires Z3 ${MINIMUM_Z3_VERSION} or newer. You can also use -DUSE_Z3=OFF to build without Z3." - ) - endif() - endif() -endif() - -if(${USE_Z3_DLOPEN}) - add_definitions(-DHAVE_Z3) - add_definitions(-DHAVE_Z3_DLOPEN) - find_package(Python3 COMPONENTS Interpreter) - if(${Z3_FOUND}) - get_target_property(Z3_HEADER_HINTS z3::libz3 INTERFACE_INCLUDE_DIRECTORIES) - endif() - find_path(Z3_HEADER_PATH z3.h HINTS ${Z3_HEADER_HINTS}) - if(Z3_HEADER_PATH) - set(Z3_FOUND TRUE) - else() - message(SEND_ERROR "Dynamic loading of Z3 requires Z3 headers to be present at build time.") - endif() - if(NOT ${Python3_FOUND}) - message(SEND_ERROR "Dynamic loading of Z3 requires Python 3 to be present at build time.") - endif() - if(${SOLC_LINK_STATIC}) - message(SEND_ERROR "solc cannot be linked statically when dynamically loading Z3.") - endif() -elseif (${Z3_FOUND}) - add_definitions(-DHAVE_Z3) - message("Z3 SMT solver found. This enables optional SMT checking with Z3.") -endif() -find_package(CVC4 QUIET) -if (${CVC4_FOUND}) - add_definitions(-DHAVE_CVC4) - message("CVC4 SMT solver found. This enables optional SMT checking with CVC4.") -endif() - -if (NOT (${Z3_FOUND} OR ${CVC4_FOUND})) - message("No SMT solver found (or it has been forcefully disabled). Optional SMT checking will not be available.\ - \nPlease install Z3 or CVC4 or remove the option disabling them (USE_Z3, USE_CVC4).") +if(EMSCRIPTEN) + set(TESTED_Z3_VERSION "4.13.3") + set(MINIMUM_Z3_VERSION "4.8.16") + find_package(Z3) + if (${Z3_FOUND}) + add_definitions(-DEMSCRIPTEN_BUILD) + if (${STRICT_Z3_VERSION}) + if (NOT ("${Z3_VERSION_STRING}" VERSION_EQUAL ${TESTED_Z3_VERSION})) + message( + FATAL_ERROR + "SMTChecker tests require Z3 ${TESTED_Z3_VERSION} for all tests to pass.\n" + ) + endif() + else() + if ("${Z3_VERSION_STRING}" VERSION_LESS ${MINIMUM_Z3_VERSION}) + message( + FATAL_ERROR + "Solidity requires Z3 ${MINIMUM_Z3_VERSION} or newer." + ) + endif() + endif() + else() + message(FATAL_ERROR "Solidity requires Z3 for emscripten build.") + endif() endif() add_subdirectory(libsolutil) @@ -141,12 +132,15 @@ add_subdirectory(libyul) add_subdirectory(libsolidity) add_subdirectory(libsolc) add_subdirectory(libstdlib) -add_subdirectory(tools) -if (NOT EMSCRIPTEN) - add_subdirectory(solc) -endif() +if (NOT ONLY_BUILD_SOLIDITY_LIBRARIES) + add_subdirectory(tools) -if (TESTS AND NOT EMSCRIPTEN) - add_subdirectory(test) + if (NOT EMSCRIPTEN) + add_subdirectory(solc) + endif() + + if (TESTS AND NOT EMSCRIPTEN) + add_subdirectory(test) + endif() endif() diff --git a/docs/050-breaking-changes.rst b/docs/050-breaking-changes.rst index a40bbcf6e9..19f05adff2 100644 --- a/docs/050-breaking-changes.rst +++ b/docs/050-breaking-changes.rst @@ -6,7 +6,7 @@ This section highlights the main breaking changes introduced in Solidity version 0.5.0, along with the reasoning behind the changes and how to update affected code. For the full list check -`the release changelog `_. +`the release changelog `_. .. note:: Contracts compiled with Solidity v0.5.0 can still interface with contracts diff --git a/docs/060-breaking-changes.rst b/docs/060-breaking-changes.rst index e7c93057f6..030c59988b 100644 --- a/docs/060-breaking-changes.rst +++ b/docs/060-breaking-changes.rst @@ -6,7 +6,7 @@ This section highlights the main breaking changes introduced in Solidity version 0.6.0, along with the reasoning behind the changes and how to update affected code. For the full list check -`the release changelog `_. +`the release changelog `_. Changes the Compiler Might not Warn About @@ -119,7 +119,7 @@ Metadata Hash Options The compiler now appends the `IPFS `_ hash of the metadata file to the end of the bytecode by default (for details, see documentation on :doc:`contract metadata `). Before 0.6.0, the compiler appended the -`Swarm `_ hash by default, and in order to still support this behavior, +`Swarm `_ hash by default, and in order to still support this behavior, the new command-line option ``--metadata-hash`` was introduced. It allows you to select the hash to be produced and appended, by passing either ``ipfs`` or ``swarm`` as value to the ``--metadata-hash`` command-line option. Passing the value ``none`` completely removes the hash. diff --git a/docs/070-breaking-changes.rst b/docs/070-breaking-changes.rst index 05e98a4dcc..a966b547a4 100644 --- a/docs/070-breaking-changes.rst +++ b/docs/070-breaking-changes.rst @@ -6,7 +6,7 @@ This section highlights the main breaking changes introduced in Solidity version 0.7.0, along with the reasoning behind the changes and how to update affected code. For the full list check -`the release changelog `_. +`the release changelog `_. Silent Changes of the Semantics diff --git a/docs/080-breaking-changes.rst b/docs/080-breaking-changes.rst index 310efcc415..b936cc1969 100644 --- a/docs/080-breaking-changes.rst +++ b/docs/080-breaking-changes.rst @@ -2,9 +2,16 @@ Cambios introducidos en Solidity v0.8.0 *************************************** +<<<<<<< HEAD Esta sección versa sobre los principales cambios introducidos en la versión 0.8.0 de Solidity. Para ver la lista completa `registro de cambios de lanzamiento `_. +======= +This section highlights the main breaking changes introduced in Solidity +version 0.8.0. +For the full list check +`the release changelog `_. +>>>>>>> english/develop Cambios silenciosos en la semántica =================================== @@ -160,8 +167,13 @@ Cambios en el interface * La salida de ``--combined-json`` ha cambiado: Los campos JSON ``abi``, ``devdoc``, ``userdoc`` y ``storage-layout`` ahora son subobjetos. Antes de la versión 0.8.0 se usaban serializados como strings. +<<<<<<< HEAD * El "legacy AST" ha sido eliminado (``--ast-json`` en el interfaz de linea de comandos ``legacyAST`` para el standard JSON). Use "compact AST" (``--ast-compact--json`` para ``AST``) en su lugar. +======= +* The "legacy AST" has been removed (``--ast-json`` on the commandline interface and ``legacyAST`` for standard JSON). + Use the "compact AST" (``--ast-compact-json`` resp. ``AST``) as replacement. +>>>>>>> english/develop * El antigüo informador (``--old-reporter``) ha sido eliminado. diff --git a/docs/_static/css/custom-dark.css b/docs/_static/css/custom-dark.css index 044a8f800d..1294a6f648 100644 --- a/docs/_static/css/custom-dark.css +++ b/docs/_static/css/custom-dark.css @@ -590,6 +590,6 @@ stroke: white; } -:root[style*=dark] .a4 .sig-name { +:root[style*=dark] .sig-name { background-color: transparent !important; } diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index 25ab265443..bdfb5ce0bc 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -93,7 +93,7 @@ h1 { } section:first-of-type h1:first-of-type { - font-family: 'Overpass mono', monospace; + font-family: 'Overpass Mono', monospace; font-size: 48px; margin-top: 3rem; margin-bottom: 5rem; @@ -229,7 +229,7 @@ small * { .wy-side-nav-search { background-color: transparent !important; color: var(--color-a) !important; - box-shadow: 0 4 4 0 var(--color-a); + box-shadow: 0 4px 4px 0 var(--color-a); border-bottom: 1px solid var(--color-d) !important; } @@ -823,4 +823,4 @@ a.skip-to-content:focus { #content { scroll-margin-top: 6rem; scroll-behavior: smooth; -} \ No newline at end of file +} diff --git a/docs/_static/css/toggle.css b/docs/_static/css/toggle.css index 6f03e6fb6a..d525ab62a7 100644 --- a/docs/_static/css/toggle.css +++ b/docs/_static/css/toggle.css @@ -85,4 +85,9 @@ html.transition *:after { .wy-menu-vertical a:hover { background-color: #0002; +} + +body { + font-weight: 300; + letter-spacing: 0.5px; } \ No newline at end of file diff --git a/docs/_static/js/constants.js b/docs/_static/js/constants.js index 67fa16cdb0..c88d259b02 100644 --- a/docs/_static/js/constants.js +++ b/docs/_static/js/constants.js @@ -26,12 +26,12 @@ const CONTRIBUTE_PATH = `/en/latest/contributing.html`; const ABOUT_PATH = `${SOLIDITY_HOME_URL}/about`; const FORUM_URL = "https://forum.soliditylang.org/"; const NAV_LINKS = [ - { name: "Blog", href: BLOG_URL }, - { name: "Documentation", href: DOCS_URL }, - { name: "Use cases", href: USE_CASES_PATH }, - { name: "Contribute", href: CONTRIBUTE_PATH }, - { name: "About", href: ABOUT_PATH }, - { name: "Forum", href: FORUM_URL }, + { name: window.NAV_LINKS.blog, href: BLOG_URL }, + { name: window.NAV_LINKS.documentation, href: DOCS_URL }, + { name: window.NAV_LINKS.use_cases, href: USE_CASES_PATH }, + { name: window.NAV_LINKS.contribute, href: CONTRIBUTE_PATH }, + { name: window.NAV_LINKS.about, href: ABOUT_PATH }, + { name: window.NAV_LINKS.forum, href: FORUM_URL }, ]; const MOBILE_MENU_TOGGLE_CLASS = "shift"; diff --git a/docs/_static/js/initialize.js b/docs/_static/js/initialize.js index a20d4fce71..1c3be8aadd 100644 --- a/docs/_static/js/initialize.js +++ b/docs/_static/js/initialize.js @@ -23,18 +23,24 @@ function rearrangeDom() { document.body.prepend(wrapperDiv); const rstVersions = document.querySelector(".rst-versions"); - rstVersions.remove(); const wyNavSide = document.querySelector("nav.wy-nav-side"); - wyNavSide.appendChild(rstVersions); + // NOTE: Since RTD migration to addons, `.rst-versions` is no longer present in the DOM. + // The following code is kept for compatibility with older versions. + // See: https://github.com/readthedocs/readthedocs.org/issues/11474 + if (rstVersions && wyNavSide) { + rstVersions.remove(); + wyNavSide.appendChild(rstVersions); + } const backdrop = document.createElement("div"); backdrop.classList.add("backdrop"); wrapperDiv.appendChild(backdrop); const content = document.querySelector(".wy-nav-content"); - content.id = "content"; - const oldWrap = document.querySelector("section.wy-nav-content-wrap"); - oldWrap.remove(); - document.querySelector(".wy-grid-for-nav").appendChild(content); + if (content) { + content.id = "content"; + document.querySelector("section.wy-nav-content-wrap")?.remove(); + document.querySelector(".wy-grid-for-nav")?.appendChild(content); + } } function buildHeader() { @@ -144,8 +150,15 @@ const updateActiveNavLink = () => { document.addEventListener("locationchange", updateActiveNavLink); function updateGitHubEditPath() { - // Replaces the version number in the GitHub edit path with "develop" + // Replaces the version number in the GitHub edit path with "develop" if it exists. + // This is to ensure that the edit path always points to the `develop` branch instead of the specific version branch. + // Note that it will fail silently if the anchor element is not found, i.e. the page is not editable or + // if the sphinx_rtd_theme is updated to a version that changes the anchor element. + // See: https://github.com/readthedocs/sphinx_rtd_theme/blob/a1c2147b17cbf0e57b7d7a6450ad4d9a5ff362cf/sphinx_rtd_theme/breadcrumbs.html#L35 + // TODO: We should consider a more robust way to handle this in the future. const gitHubEditAnchor = document.querySelector(".wy-breadcrumbs-aside > a"); + if (!gitHubEditAnchor) return; + const url = new URL(gitHubEditAnchor.href); const split = url.pathname.split("/"); const versionIndex = split.indexOf("blob") + 1; @@ -195,10 +208,12 @@ function initialize() { .querySelector(":root") .setAttribute("style", `--color-scheme: ${mode}`); + // NOTE: Since RTD migration to addons, the elements below are no longer present in the DOM. + // The following code is kept for compatibility with older versions. // Remove old input and RTD logo anchor element - document.querySelector("input[name=mode]").remove(); - document.querySelector("label[for=switch]").remove(); - document.querySelector(".wy-side-nav-search > a").remove(); + document.querySelector("input[name=mode]")?.remove(); + document.querySelector("label[for=switch]")?.remove(); + document.querySelector(".wy-side-nav-search > a")?.remove(); // Add footer note addFooterNote(); @@ -239,7 +254,7 @@ document.addEventListener("click", handleClick); const handleKeyDown = (e) => { if (e.metaKey && e.key === "k") { - document.querySelector("#rtd-search-form input").focus(); + document.querySelector("#rtd-search-form input")?.focus(); } else if (e.key === "Escape") { toggleMenu({ force: false }); } diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html index 498c0e6e9b..e4795757fa 100644 --- a/docs/_templates/layout.html +++ b/docs/_templates/layout.html @@ -1,5 +1,19 @@ {% extends "!layout.html" %} +{% block scripts %} + + {{ super() }} +{% endblock %} + {% block menu %} {{ super() }}
    diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index 0d48b51dd7..91da5127c5 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -16,7 +16,7 @@ as described in this specification. The encoding is not self describing and thus We assume that the interface functions of a contract are strongly typed, known at compilation time and static. We assume that all contracts will have the interface definitions of any contracts they call available at compile-time. -This specification does not address contracts whose interface is dynamic or otherwise known only at run-time. +This specification does not address contracts whose interface is dynamic or otherwise known only at run-time. Also, the ABI specification for libraries is :ref:`slightly different `. .. _abi_function_selector: .. index:: ! selector; of a function @@ -47,6 +47,8 @@ without the four bytes specifying the function. Types ===== +Note that the library ABIs can take types different than below e.g. for non-storage structs. See :ref:`library selectors ` for details. + The following elementary types exist: - ``uint``: unsigned integer type of ``M`` bits, ``0 < M <= 256``, ``M % 8 == 0``. e.g. ``uint32``, ``uint8``, ``uint256``. diff --git a/docs/assembly.rst b/docs/assembly.rst index 9bc170ef9c..e42ea2b090 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -8,7 +8,18 @@ Ensamblado en línea Puedes intercalar declaraciones de Solidity con ensamblado en línea en un lenguaje cercano al de la Máquina Virtual de Ethereum. Esto te brinda un control más preciso, especialmente útil cuando estás mejorando el lenguaje escribiendo librerías. +<<<<<<< HEAD El lenguaje utilizado para el ensamblado en línea en Solidity se llama :ref:`Yul ` y está documentado en su propia sección. Esta sección solo cubre cómo el código de ensamblado en línea puede interactuar con el código en Solidity que lo rodea. +======= +You can interleave Solidity statements with inline assembly in a language close +to the one of the Ethereum Virtual Machine. This gives you more fine-grained control, +which is especially useful when you are enhancing the language by writing libraries or +optimizing gas usage. + +The language used for inline assembly in Solidity is called :ref:`Yul ` +and it is documented in its own section. This section will only cover +how the inline assembly code can interface with the surrounding Solidity code. +>>>>>>> english/develop .. warning:: @@ -138,7 +149,16 @@ Para los punteros de función externos, la dirección y el selector de función Para los arreglos dinámicos de calldata, puedes acceder a su offset de calldata (en bytes) y longitud (número de elementos) utilizando ``x.offset`` y ``x.length``. Ambas expresiones también pueden ser asignadas, pero como en el caso estático, no se realizará ninguna validación para asegurarse que el área de datos resultante esté dentro de los límites de ``calldatasize()``. +<<<<<<< HEAD Para las variables de almacenamiento local, o variables de estado, un identificador único Yul no es suficiente ya que no necesariamente ocupan un solo espacio de almacenamiento completo. Por lo tanto, su "dirección" está compuesta por un espacio y un offset de bytes dentro del espacio. Para recuperar el espacio apuntado por la variable `x`, utiliza `x.slot` y para recuperar el offset de bytes utiliza `x.offset`. El uso de `x` en sí mismo resultará en un error. +======= +For local storage variables or state variables (including transient storage) a single Yul identifier +is not sufficient, since they do not necessarily occupy a single full storage slot. +Therefore, their "address" is composed of a slot and a byte-offset +inside that slot. To retrieve the slot pointed to by the variable ``x``, you +use ``x.slot``, and to retrieve the byte-offset you use ``x.offset``. +Using ``x`` itself will result in an error. +>>>>>>> english/develop También puedes asignar a la parte ``.slot`` de un puntero de variable de almacenamiento local. Para estos (estructuras, arreglos o mapeos), la parte ``.offset`` siempre es cero. Sin embargo, no es posible asignar a la parte ``.slot`` o ``.offset`` de una variable de estado. @@ -148,15 +168,18 @@ Las variables locales en Solidity están disponibles para asignaciones, por ejem :force: // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.7.0 <0.9.0; + pragma solidity >=0.8.28 <0.9.0; + // This will report a warning contract C { + bool transient a; uint b; - function f(uint x) public view returns (uint r) { + function f(uint x) public returns (uint r) { assembly { // Ignoramos el desplazamiento de la ranura de almacenamiento, // sabemos que es cero en este caso especial. r := mul(x, sload(b.slot)) + tstore(a.slot, true) } } } @@ -165,9 +188,20 @@ Las variables locales en Solidity están disponibles para asignaciones, por ejem Si accedes a variables de un tipo que abarque menos de 256 bits (por ejemplo, ``uint64``, ``address``, o ``bytes16``), no puedes hacer ninguna suposición acerca de bits que no son parte de la codificación del tipo. Especialmente, no debes suponer que son cero. Para estar seguro, siempre limpia de forma adecuada los datos antes de utilizarlos en un contexto en el que esto sea importante: ``uint32 x = f(); assembly { x := and(x, 0xffffffff) /* now use x */ }`` Para limpiar tipos firmados, puedes usar el código de operación: ``assembly { signextend(, x) }`` +<<<<<<< HEAD Desde Solidity 0.6.0, puede que el nombre de una variable de ensamblado en línea no oculte ninguna declaración visible en el ámbito del bloque de ensamblado en línea (incluyendo declaraciones de variables, contratos y funciones). Desde Solidity 0.7.0, puede que las variables y funciones declaradas dentro del bloque de ensamblado en línea no contengan ``.``, pero usar ``.`` es válido para acceder a las variables de Solidity desde fuera del bloque de ensamblado en línea. +======= +Since Solidity 0.6.0, the name of an inline assembly variable may not +shadow any declaration visible in the scope of the inline assembly block +(including variable, contract and function declarations). + +Since Solidity 0.7.0, variables and functions declared inside the +inline assembly block may not contain ``.``, but using ``.`` is +valid to access Solidity variables from outside the inline assembly block. +However, it is still valid to use dots if you use Solidity in Yul-only mode. +>>>>>>> english/develop Cosas a evitar --------------- @@ -191,7 +225,19 @@ En contraste con el ensamblado EVM, Solidity tiene tipos más estrechos que 256 Gestión de memoria ================= +<<<<<<< HEAD Solidity maneja la memoria de la siguiente forma. Hay un "puntero de memoria libre" en la posición ``0x40`` de la memoria. Si quieres asignar memoria, usa la memoria a partir de donde apunta ese puntero y actualiza el mismo. No hay garantía de que la memoria no haya sido utilizada anteriormente y por lo tanto no puedes asumir que sean bytes en cero. No hay un mecanismo incorporado para soltar o liberar memoria asignada. Aquí tienes un fragmento de ensamblado que puedes usar para asignar memoria siguiendo el proceso descrito anteriormente: +======= +Solidity manages memory in the following way. There is a "free memory pointer" +at position ``0x40`` in memory. If you want to allocate memory, use the memory +starting from where this pointer points at and update it. +There is no guarantee that the memory has not been used before and thus +you cannot assume that its contents are zero bytes. +There is no built-in mechanism to release or free allocated memory. +Solidity does not guarantee and does not require that the values in memory +are placed at positions aligned to a multiple of any value. +Here is an assembly snippet you can use for allocating memory that follows the process outlined above: +>>>>>>> english/develop .. code-block:: yul @@ -287,5 +333,27 @@ of Solidity, you can use a special comment to annotate an assembly block as memo ... } -Note that we will disallow the annotation via comment in a future breaking release; so, if you are not concerned with -backward-compatibility with older compiler versions, prefer using the dialect string. +.. warning:: + The ``memory-safe-assembly`` special comment is deprecated and scheduled for removal. + In new code targeting recent compilers, use the assembly block annotation. + +Advanced Safe Use of Memory +--------------------------- + +Beyond the strict definition of memory-safety given above, there are cases in which you may want to use more than 64 bytes +of scratch space starting at memory offset ``0``. If you are careful, it can be admissible to use memory up to (and not +including) offset ``0x80`` and still safely declare the assembly block as ``memory-safe``. +This is admissible under either of the following conditions: + +- By the end of the assembly block, the free memory pointer at offset ``0x40`` is restored to a sane value (i.e. it is either + restored to its original value or an increment of it due to a manual memory allocation), and the memory word at offset ``0x60`` + is restored to a value of zero. + +- The assembly block terminates, i.e. execution can never return to high-level Solidity code. This is the case, for example, + if your assembly block unconditionally ends in calling the ``revert`` opcode. + +Furthermore, you need to be aware that the default-value of dynamic arrays in Solidity point to memory offset ``0x60``, so +for the duration of temporarily changing the value at memory offset ``0x60``, you can no longer rely on getting accurate +length values when reading dynamic arrays, until you restore the zero value at ``0x60``. To be more precise, we only guarantee +safety when overwriting the zero pointer, if the remainder of the assembly snippet does not interact with the memory of +high-level Solidity objects (including by reading from offsets previously stored in variables). diff --git a/docs/bugs.json b/docs/bugs.json index c853f95edd..5f8d1a1627 100644 --- a/docs/bugs.json +++ b/docs/bugs.json @@ -1,4 +1,28 @@ [ + { + "uid": "SOL-2026-1", + "name": "TransientStorageClearingHelperCollision", + "summary": "Clearing both storage and transient storage variables in the same contract may result in only one of these locations being cleared.", + "description": "The IR-based code generator provides a set of Yul helper functions for basic operations, such as clearing, copying, encoding or type conversions. Not all functions are used by every contract. The codegen appends them to the generated sources individually, only when an operation that would invoke one of them is encountered. Utility functions are often specialized for different types and locations. Since Yul does not support generic functions, specialization is done by generating multiple versions of the same function, with the information distinguishing the variants embedded in their names. However, if not all the necessary bits of distinguishing information are properly accounted for, two helpers may end up with the same name, causing a collision. In this situation the codegen includes only one of them, with calls to both variants invoking it. This happened with the ``set_to_zero`` helper used when an area of transient or persistent storage needs to be cleared. The helper name was missing the location information, which resulted in a collision between the persistent and transient storage variants for the same type. This meant that contracts clearing both locations would actually clear only one, leaving the other untouched. Which location ended up being cleared depended on the order in which the code generator processed the input. The necessary condition to trigger the bug was the use of ``delete`` operator on a transient storage variable. This was due to value types being the only types supported in transient storage and ``delete`` being the only operation invoking the helper allowed on such types. The other necessary condition was clearing of persistent storage and in this case the range of affected operations was wider: operator ``delete``, array ``pop()`` or assignment that resulted in a longer array being overwritten with a shorter one. The cleared variable itself also did not necessarily have to be of the same type. It was enough that a matching value type was nested in it. It also did not always have to be the exact same value type - clearing operations on reference types are usually performed at slot granularity, treating every slot as ``uint256`` rather than clearing every value packed into it individually. To trigger the bug both operations had to be present within the same piece of bytecode. Independent contracts, not related through inheritance, would not affect each other this way. The presence of one operation only in creation code and the other only in deployed code would not trigger the bug either.", + "link": "https://blog.soliditylang.org/2026/02/18/transient-storage-clearing-helper-collision-bug/", + "introduced": "0.8.28", + "fixed": "0.8.34", + "severity": "high", + "conditions": { + "viaIR": true, + "evmVersion": ">=cancun" + } + }, + { + "uid": "SOL-2025-1", + "name": "LostStorageArrayWriteOnSlotOverflow", + "summary": "Operations that involve clearing or copying from arrays that straddle the end of storage could result in silent data retention.", + "description": "Solidity makes it possible to define variables that extend past the last (2**256-th) slot of storage, which results in wrap-around back to slot zero. Since EVM uses 256-bit integer arithmetic, most operations on such variables just work. The only situation which requires special attention is iteration against absolute slot addresses: the invariant that the last slot belonging to a variable has the highest address does not hold. When implemented incorrectly, a loop over an array will immediately terminate if the container spans the end of storage - due to the initial position already being greater than the end position. This affected storage array clearing loops generated by both evmasm and IR pipelines. Additionally, (only in the evmasm pipeline) copying operations whose source was an array straddling the end of storage were also affected. At the language level, the buggy code would be generated for array assignment, array initialization, delete operator, .pop() and .push(). Note that a clearing loop is inserted by the compiler not only for invocations of the delete operator, but also to zero storage when overwriting a longer array with a shorter one, popping an element or even pushing an empty element to a dynamic array. Since clearing is a separate loop, it is possible for the bug to only affect it and not the copy operation it follows (which is always the case in the IR pipeline). The bug is extremely unlikely to be triggered accidentally due to the probabilistic impossibility of a short dynamic array being allocated right at the storage boundary. On the other hand, scenarios in which a user may place a static array there intentionally do not seem realistic and are limited to unusual layouts, in which a contract does not place any storage variables at slot zero (otherwise they would overlap the array).", + "link": "https://blog.soliditylang.org/2025/12/18/lost-storage-array-write-on-slot-overflow-bug/", + "introduced": "0.1.0", + "fixed": "0.8.32", + "severity": "low" + }, { "uid": "SOL-2023-3", "name": "VerbatimInvalidDeduplication", @@ -151,7 +175,7 @@ { "uid": "SOL-2021-1", "name": "KeccakCaching", - "summary": "The bytecode optimizer incorrectly re-used previously evaluated Keccak-256 hashes. You are unlikely to be affected if you do not compute Keccak-256 hashes in inline assembly.", + "summary": "The bytecode optimizer incorrectly reused previously evaluated Keccak-256 hashes. You are unlikely to be affected if you do not compute Keccak-256 hashes in inline assembly.", "description": "Solidity's bytecode optimizer has a step that can compute Keccak-256 hashes, if the contents of the memory are known during compilation time. This step also has a mechanism to determine that two Keccak-256 hashes are equal even if the values in memory are not known during compile time. This mechanism had a bug where Keccak-256 of the same memory content, but different sizes were considered equal. More specifically, ``keccak256(mpos1, length1)`` and ``keccak256(mpos2, length2)`` in some cases were considered equal if ``length1`` and ``length2``, when rounded up to nearest multiple of 32 were the same, and when the memory contents at ``mpos1`` and ``mpos2`` can be deduced to be equal. You maybe affected if you compute multiple Keccak-256 hashes of the same content, but with different lengths inside inline assembly. You are unaffected if your code uses ``keccak256`` with a length that is not a compile-time constant or if it is always a multiple of 32.", "link": "https://blog.soliditylang.org/2021/03/23/keccak-optimizer-bug/", "fixed": "0.8.3", @@ -200,7 +224,7 @@ "uid": "SOL-2020-7", "name": "MissingEscapingInFormatting", "summary": "String literals containing double backslash characters passed directly to external or encoding function calls can lead to a different string being used when ABIEncoderV2 is enabled.", - "description": "When ABIEncoderV2 is enabled, string literals passed directly to encoding functions or external function calls are stored as strings in the intemediate code. Characters outside the printable range are handled correctly, but backslashes are not escaped in this procedure. This leads to double backslashes being reduced to single backslashes and consequently re-interpreted as escapes potentially resulting in a different string being encoded.", + "description": "When ABIEncoderV2 is enabled, string literals passed directly to encoding functions or external function calls are stored as strings in the intermediate code. Characters outside the printable range are handled correctly, but backslashes are not escaped in this procedure. This leads to double backslashes being reduced to single backslashes and consequently re-interpreted as escapes potentially resulting in a different string being encoded.", "introduced": "0.5.14", "fixed": "0.6.8", "severity": "very low", diff --git a/docs/bugs.rst b/docs/bugs.rst index aaf975f76a..bf8b92286b 100644 --- a/docs/bugs.rst +++ b/docs/bugs.rst @@ -8,11 +8,17 @@ Lista de Bugs Conocidos Below, you can find a JSON-formatted list of some of the known security-relevant bugs in the Solidity compiler. The file itself is hosted in the `GitHub repository -`_. +`_. The list stretches back as far as version 0.3.0, bugs known to be present only in versions preceding that are not listed. +<<<<<<< HEAD Hay otro archivo llamado `bugs_by_version.json `_, que se puede utilizar para comprobar qué errores afectan a una versión específica del compilador. +======= +There is another file called `bugs_by_version.json +`_, +which can be used to check which bugs affect a specific version of the compiler. +>>>>>>> english/develop Herramientas para la verificación del código fuente de un contrato, y otras herramientas que interactúen con contratos, deben consultar esta lista de acuerdo a los siguientes criterios: diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 156b846d01..c5576d4b29 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1,6 +1,7 @@ { "0.1.0": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -23,6 +24,7 @@ }, "0.1.1": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -45,6 +47,7 @@ }, "0.1.2": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -67,6 +70,7 @@ }, "0.1.3": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -89,6 +93,7 @@ }, "0.1.4": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -112,6 +117,7 @@ }, "0.1.5": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -135,6 +141,7 @@ }, "0.1.6": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -160,6 +167,7 @@ }, "0.1.7": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -185,6 +193,7 @@ }, "0.2.0": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -211,6 +220,7 @@ }, "0.2.1": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -237,6 +247,7 @@ }, "0.2.2": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -263,6 +274,7 @@ }, "0.3.0": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -291,6 +303,7 @@ }, "0.3.1": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -318,6 +331,7 @@ }, "0.3.2": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -345,6 +359,7 @@ }, "0.3.3": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -371,6 +386,7 @@ }, "0.3.4": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -397,6 +413,7 @@ }, "0.3.5": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -423,6 +440,7 @@ }, "0.3.6": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -447,6 +465,7 @@ }, "0.4.0": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -471,6 +490,7 @@ }, "0.4.1": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -495,6 +515,7 @@ }, "0.4.10": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -518,6 +539,7 @@ }, "0.4.11": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -540,6 +562,7 @@ }, "0.4.12": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -561,6 +584,7 @@ }, "0.4.13": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -582,6 +606,7 @@ }, "0.4.14": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -602,6 +627,7 @@ }, "0.4.15": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -621,6 +647,7 @@ }, "0.4.16": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -643,6 +670,7 @@ }, "0.4.17": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -666,6 +694,7 @@ }, "0.4.18": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -688,6 +717,7 @@ }, "0.4.19": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -711,6 +741,7 @@ }, "0.4.2": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -734,6 +765,7 @@ }, "0.4.20": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -757,6 +789,7 @@ }, "0.4.21": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -780,6 +813,7 @@ }, "0.4.22": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -803,6 +837,7 @@ }, "0.4.23": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -825,6 +860,7 @@ }, "0.4.24": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -847,6 +883,7 @@ }, "0.4.25": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -867,6 +904,7 @@ }, "0.4.26": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -884,6 +922,7 @@ }, "0.4.3": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -906,6 +945,7 @@ }, "0.4.4": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -927,6 +967,7 @@ }, "0.4.5": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -951,6 +992,7 @@ }, "0.4.6": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -974,6 +1016,7 @@ }, "0.4.7": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -997,6 +1040,7 @@ }, "0.4.8": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -1020,6 +1064,7 @@ }, "0.4.9": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "KeccakCaching", "EmptyByteArrayCopy", @@ -1043,6 +1088,7 @@ }, "0.5.0": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -1063,6 +1109,7 @@ }, "0.5.1": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -1083,6 +1130,7 @@ }, "0.5.10": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1101,6 +1149,7 @@ }, "0.5.11": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1118,6 +1167,7 @@ }, "0.5.12": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1135,6 +1185,7 @@ }, "0.5.13": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1152,6 +1203,7 @@ }, "0.5.14": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1171,6 +1223,7 @@ }, "0.5.15": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1189,6 +1242,7 @@ }, "0.5.16": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1206,6 +1260,7 @@ }, "0.5.17": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1222,6 +1277,7 @@ }, "0.5.2": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -1242,6 +1298,7 @@ }, "0.5.3": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -1262,6 +1319,7 @@ }, "0.5.4": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -1282,6 +1340,7 @@ }, "0.5.5": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -1304,6 +1363,7 @@ }, "0.5.6": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -1326,6 +1386,7 @@ }, "0.5.7": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "DirtyBytesArrayToStorage", "ABIDecodeTwoDimensionalArrayMemory", "KeccakCaching", @@ -1346,6 +1407,7 @@ }, "0.5.8": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1367,6 +1429,7 @@ }, "0.5.9": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1387,6 +1450,7 @@ }, "0.6.0": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1405,6 +1469,7 @@ }, "0.6.1": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", "NestedCalldataArrayAbiReencodingSizeValidation", @@ -1422,6 +1487,7 @@ }, "0.6.10": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1438,6 +1504,7 @@ }, "0.6.11": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1454,6 +1521,7 @@ }, "0.6.12": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1470,6 +1538,7 @@ }, "0.6.2": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", @@ -1488,6 +1557,7 @@ }, "0.6.3": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", @@ -1506,6 +1576,7 @@ }, "0.6.4": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", @@ -1524,6 +1595,7 @@ }, "0.6.5": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", @@ -1542,6 +1614,7 @@ }, "0.6.6": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", "DirtyBytesArrayToStorage", @@ -1559,6 +1632,7 @@ }, "0.6.7": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1577,6 +1651,7 @@ }, "0.6.8": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1592,6 +1667,7 @@ }, "0.6.9": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1609,6 +1685,7 @@ }, "0.7.0": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1625,6 +1702,7 @@ }, "0.7.1": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1642,6 +1720,7 @@ }, "0.7.2": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1658,6 +1737,7 @@ }, "0.7.3": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1673,6 +1753,7 @@ }, "0.7.4": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1687,6 +1768,7 @@ }, "0.7.5": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1701,6 +1783,7 @@ }, "0.7.6": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1715,6 +1798,7 @@ }, "0.8.0": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1729,6 +1813,7 @@ }, "0.8.1": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1743,6 +1828,7 @@ }, "0.8.10": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1755,6 +1841,7 @@ }, "0.8.11": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1768,6 +1855,7 @@ }, "0.8.12": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1781,6 +1869,7 @@ }, "0.8.13": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1795,6 +1884,7 @@ }, "0.8.14": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1807,6 +1897,7 @@ }, "0.8.15": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1817,6 +1908,7 @@ }, "0.8.16": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1826,6 +1918,7 @@ }, "0.8.17": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess" @@ -1834,6 +1927,7 @@ }, "0.8.18": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess" @@ -1842,6 +1936,7 @@ }, "0.8.19": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess" @@ -1850,6 +1945,7 @@ }, "0.8.2": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1864,6 +1960,7 @@ }, "0.8.20": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess" @@ -1872,26 +1969,65 @@ }, "0.8.21": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication" ], "released": "2023-07-19" }, "0.8.22": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication" ], "released": "2023-10-25" }, "0.8.23": { - "bugs": [], + "bugs": [ + "LostStorageArrayWriteOnSlotOverflow" + ], "released": "2023-11-08" }, "0.8.24": { - "bugs": [], + "bugs": [ + "LostStorageArrayWriteOnSlotOverflow" + ], "released": "2024-01-25" }, + "0.8.25": { + "bugs": [ + "LostStorageArrayWriteOnSlotOverflow" + ], + "released": "2024-03-14" + }, + "0.8.26": { + "bugs": [ + "LostStorageArrayWriteOnSlotOverflow" + ], + "released": "2024-05-21" + }, + "0.8.27": { + "bugs": [ + "LostStorageArrayWriteOnSlotOverflow" + ], + "released": "2024-09-04" + }, + "0.8.28": { + "bugs": [ + "TransientStorageClearingHelperCollision", + "LostStorageArrayWriteOnSlotOverflow" + ], + "released": "2024-10-09" + }, + "0.8.29": { + "bugs": [ + "TransientStorageClearingHelperCollision", + "LostStorageArrayWriteOnSlotOverflow" + ], + "released": "2025-03-12" + }, "0.8.3": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1903,8 +2039,39 @@ ], "released": "2021-03-23" }, + "0.8.30": { + "bugs": [ + "TransientStorageClearingHelperCollision", + "LostStorageArrayWriteOnSlotOverflow" + ], + "released": "2025-05-07" + }, + "0.8.31": { + "bugs": [ + "TransientStorageClearingHelperCollision", + "LostStorageArrayWriteOnSlotOverflow" + ], + "released": "2025-12-03" + }, + "0.8.32": { + "bugs": [ + "TransientStorageClearingHelperCollision" + ], + "released": "2025-12-18" + }, + "0.8.33": { + "bugs": [ + "TransientStorageClearingHelperCollision" + ], + "released": "2025-12-18" + }, + "0.8.34": { + "bugs": [], + "released": "2026-02-18" + }, "0.8.4": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", "AbiReencodingHeadOverflowWithStaticArrayCleanup", @@ -1917,6 +2084,7 @@ }, "0.8.5": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1930,6 +2098,7 @@ }, "0.8.6": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1943,6 +2112,7 @@ }, "0.8.7": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1956,6 +2126,7 @@ }, "0.8.8": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", @@ -1970,6 +2141,7 @@ }, "0.8.9": { "bugs": [ + "LostStorageArrayWriteOnSlotOverflow", "VerbatimInvalidDeduplication", "FullInlinerNonExpressionSplitArgumentEvaluationOrder", "MissingSideEffectsOnSelectorAccess", diff --git a/docs/cheatsheet.rst b/docs/cheatsheet.rst index d34bcb8255..c95759066f 100644 --- a/docs/cheatsheet.rst +++ b/docs/cheatsheet.rst @@ -23,7 +23,7 @@ ABI Encoding and Decoding Functions - ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes memory)``: :ref:`ABI `-encodes the given arguments starting from the second and prepends the given four-byte selector - ``abi.encodeCall(function functionPointer, (...)) returns (bytes memory)``: ABI-encodes a call to ``functionPointer`` with the arguments found in the - tuple. Performs a full type-check, ensuring the types match the function signature. Result equals ``abi.encodeWithSelector(functionPointer.selector, (...))`` + tuple. Performs a full type-check, ensuring the types match the function signature. Result equals ``abi.encodeWithSelector(functionPointer.selector, ...)`` - ``abi.encodeWithSignature(string memory signature, ...) returns (bytes memory)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature))), ...)`` @@ -53,8 +53,8 @@ Members of ``address`` - ``
    .staticcall(bytes memory) returns (bool, bytes memory)``: issue low-level ``STATICCALL`` with the given payload, returns success condition and return data - ``
    .send(uint256 amount) returns (bool)``: send given amount of Wei to :ref:`address`, - returns ``false`` on failure -- ``
    .transfer(uint256 amount)``: send given amount of Wei to :ref:`address`, throws on failure + returns ``false`` on failure (deprecated) +- ``
    .transfer(uint256 amount)``: send given amount of Wei to :ref:`address`, throws on failure (deprecated) .. index:: blockhash, blobhash, block, block;basefee, block;blobbasefee, block;chainid, block;coinbase, block;difficulty, block;gaslimit, block;number, block;prevrandao, block;timestamp .. index:: gasleft, msg;data, msg;sender, msg;sig, msg;value, tx;gasprice, tx;origin @@ -66,6 +66,7 @@ Block and Transaction Properties - ``blobhash(uint index) returns (bytes32)``: versioned hash of the ``index``-th blob associated with the current transaction. A versioned hash consists of a single byte representing the version (currently ``0x01``), followed by the last 31 bytes of the SHA256 hash of the KZG commitment (`EIP-4844 `_). + Returns zero if no blob with the given index exists. - ``block.basefee`` (``uint``): current block's base fee (`EIP-3198 `_ and `EIP-1559 `_) - ``block.blobbasefee`` (``uint``): current block's blob base fee (`EIP-7516 `_ and `EIP-4844 `_) - ``block.chainid`` (``uint``): current chain id @@ -96,7 +97,7 @@ Validations and Assertions - ``revert()``: abort execution and revert state changes - ``revert(string memory message)``: abort execution and revert state changes providing an explanatory string -.. index:: cryptography, keccak256, sha256, ripemd160, ecrecover, addmod, mulmod +.. index:: cryptography, keccak256, sha256, ripemd160, ecrecover, addmod, mulmod, erc7201 Mathematical and Cryptographic Functions ======================================== @@ -110,6 +111,8 @@ Mathematical and Cryptographic Functions arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0. - ``mulmod(uint x, uint y, uint k) returns (uint)``: compute ``(x * y) % k`` where the multiplication is performed with arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0. +- ``erc7201(string memory id) returns (uint)``: compute the base slot of an ``erc7201`` storage namespace. + Can be used in compile time context. .. index:: this, super, selfdestruct @@ -118,7 +121,7 @@ Contract-related - ``this`` (current contract's type): the current contract, explicitly convertible to ``address`` or ``address payable`` - ``super``: a contract one level higher in the inheritance hierarchy -- ``selfdestruct(address payable recipient)``: destroy the current contract, sending its funds to the given address +- ``selfdestruct(address payable recipient)``: send all funds to the given address and (only on EVMs before Cancun or when invoked within the transaction creating the contract) destroy the contract. .. index:: type;name, type;creationCode, type;runtimeCode, type;interfaceId, type;min, type;max diff --git a/docs/common-patterns.rst b/docs/common-patterns.rst index 1eaab22d3b..5a18ba0b51 100644 --- a/docs/common-patterns.rst +++ b/docs/common-patterns.rst @@ -57,7 +57,8 @@ los fondos de la persona que ahora es la más rica. // Remember to zero the pending refund before // sending to prevent reentrancy attacks pendingWithdrawals[msg.sender] = 0; - payable(msg.sender).transfer(amount); + (bool success, ) = payable(msg.sender).call{value: amount}(""); + require(success); } } @@ -83,8 +84,14 @@ Patrón de envío: function becomeRichest() public payable { if (msg.value <= mostSent) revert NotEnoughEther(); +<<<<<<< HEAD // Esta línea puede causar problemas (explicado más abajo). richest.transfer(msg.value); +======= + // This line can cause problems (explained below). + (bool success, ) = richest.call{value: msg.value}(""); + require(success); +>>>>>>> english/develop richest = payable(msg.sender); mostSent = msg.value; } @@ -211,8 +218,10 @@ restricciones sumamente legibles. revert NotEnoughEther(); _; - if (msg.value > amount) - payable(msg.sender).transfer(msg.value - amount); + if (msg.value > amount) { + (bool success, ) = payable(msg.sender).call{value: msg.value - amount}(""); + require(success); + } } function forceOwnerChange(address newOwner) diff --git a/docs/conf.py b/docs/conf.py index ddc3ee81bb..e71535b9a7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -36,8 +36,55 @@ def setup(sphinx): sphinx.add_css_file('css/custom-dark.css') sphinx.add_css_file('css/pygments.css') -# -- General configuration ------------------------------------------------ +# -- RTD GitHub configuration --------------------------------------------- + +# Taken from: +# https://github.com/readthedocs/readthedocs.org/blob/e366e7fc8649fbcf1b6d06ecc12c5f7766144c46/readthedocs/projects/constants.py#L350 +GITHUB_REGEXS = [ + re.compile(r"github.com/(.+)/(.+)(?:\.git){1}$"), + # This must come before the one without a / to make sure we don't capture the / + re.compile(r"github.com/(.+)/(.+)/"), + re.compile(r"github.com/(.+)/(.+)"), + re.compile(r"github.com:(.+)/(.+)\.git$"), +] +# Taken and adapted from: +# https://github.com/readthedocs/readthedocs.org/blob/e366e7fc8649fbcf1b6d06ecc12c5f7766144c46/readthedocs/builds/utils.py#L24 +def get_github_username_repo(url): + if "github" in url: + for regex in GITHUB_REGEXS: + match = regex.search(url) + if match: + return match.groups() + return (None, None) + +display_github = False +# NOTE: RTD_DISPLAY_GITHUB, RTD_GITHUB_USER and RTD_GITHUB_REPO are set in the RTD project settings +github_user = os.getenv("RTD_GITHUB_USER") +github_repo = os.getenv("RTD_GITHUB_REPO") + +if github_user and github_repo: + display_github = True +else: + git_clone_url = os.getenv("READTHEDOCS_GIT_CLONE_URL") + if git_clone_url: + github_user, github_repo = get_github_username_repo(git_clone_url) + if github_user and github_repo: + display_github = True + +display_github_env = os.getenv("RTD_DISPLAY_GITHUB") +if display_github_env: + display_github = display_github_env.lower() == "true" + +html_context = { + "display_github": display_github, + "github_user": github_user, + "github_repo": github_repo, + "github_version": os.getenv("READTHEDOCS_VERSION", "develop"), + "conf_py_path": "/docs/", +} + +# -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' @@ -45,13 +92,15 @@ def setup(sphinx): # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx_a4doc', + 'sphinx_syntax', 'html_extra_template_renderer', 'remix_code_links', 'sphinx.ext.imgconverter', ] -a4_base_path = os.path.dirname(__file__) + '/grammar' +syntax_base_path = 'grammar' +# generate link anchors compatible with Sphinx-A4Doc’s naming +syntax_a4doc_compat_links = True # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -67,7 +116,7 @@ def setup(sphinx): # General information about the project. project = 'Solidity' -project_copyright = '2016-2023, The Solidity Authors' +project_copyright = '2016-2025, The Solidity Authors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -77,10 +126,12 @@ def setup(sphinx): with open('../CMakeLists.txt', 'r', encoding='utf8') as f: version = re.search('PROJECT_VERSION "([^"]+)"', f.read()).group(1) # The full version, including alpha/beta/rc tags. -if not os.path.isfile('../prerelease.txt') or os.path.getsize('../prerelease.txt') == 0: +if os.path.isfile('../prerelease.txt') and os.path.getsize('../prerelease.txt') == 0: release = version +elif os.path.isfile('../prerelease.txt'): + with open('../prerelease.txt', 'r', encoding='utf8') as prerelease_file: + release = version + '-' + prerelease_file.read() else: - # This is a prerelease version release = version + '-develop' # The language for content autogenerated by Sphinx. Refer to documentation @@ -123,6 +174,10 @@ def setup(sphinx): # If true, keep warnings as "system message" paragraphs in the built documents. #keep_warnings = False +suppress_warnings = [ + # Suppress sphinx-syntax warnings, in particular `diagram descriptions can't have custom resolver_data` + 'sphinx_syntax', +] # -- Options for HTML output ---------------------------------------------- @@ -135,7 +190,8 @@ def setup(sphinx): # documentation. html_theme_options = { 'logo_only': True, - 'display_version': True, + 'version_selector': True, + 'language_selector': True, } # Add any paths that contain custom themes here, relative to this directory. diff --git a/docs/contracts.rst b/docs/contracts.rst index 7d12bf99cc..6435c04c75 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -18,7 +18,10 @@ No existe un concepto "cron" en Ethereum para llamar automáticamente a una func .. include:: contracts/function-modifiers.rst +.. include:: contracts/transient-storage.rst + .. include:: contracts/constant-state-variables.rst +.. include:: contracts/custom-storage-layout.rst .. include:: contracts/functions.rst .. include:: contracts/events.rst diff --git a/docs/contracts/constant-state-variables.rst b/docs/contracts/constant-state-variables.rst index 5ad26ac002..3fb9da32af 100644 --- a/docs/contracts/constant-state-variables.rst +++ b/docs/contracts/constant-state-variables.rst @@ -12,7 +12,13 @@ En ambos casos, estas variables ya no podrán ser modificadas una vez se haya cr Las variables ``constant`` fijarán su valor ya directamente en el propio proceso de compilación, mientras que las variables ``immutable``, podrán hacerlo cuando el contrato sea construido. +<<<<<<< HEAD También se pueden definir variables ``constant`` a nivel de archivo. +======= +Every occurrence of such a variable in the source is replaced by its underlying value +and the compiler does not reserve a storage slot for it. +It cannot be assigned a slot in transient storage using the ``transient`` keyword either. +>>>>>>> english/develop El compilador no reservará un espacio de almacenamiento (storage slot) para estas variables. En su lugar, cada una de estas variables será reemplazada por su respectivo valor. diff --git a/docs/contracts/custom-storage-layout.rst b/docs/contracts/custom-storage-layout.rst new file mode 100644 index 0000000000..def06f3d5a --- /dev/null +++ b/docs/contracts/custom-storage-layout.rst @@ -0,0 +1,59 @@ +.. index:: ! custom storage layout, ! storage layout specifier, ! layout at, ! base slot + +.. _custom-storage-layout: + +********************* +Custom Storage Layout +********************* + +A contract can define an arbitrary location for its storage using the ``layout`` specifier. +The contract's state variables, including those inherited from base contracts, +start from the specified base slot instead of the default slot zero. + +.. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity ^0.8.29; + + contract C layout at 0xAAAA + 0x11 { + uint[3] x; // Occupies slots 0xAABB..0xAABD + } + +As the above example shows, the specifier uses the ``layout at `` syntax +and is located in the header of a contract definition. + +The layout specifier can be placed either before or after the inheritance specifier, and can appear at most once. +The ``base-slot-expression`` must be an :ref:`integer literal` expression +that can be evaluated at compilation time and yields a value in the range of ``uint256``. +The use of constants initialized using such expressions and +the :ref:`built-in function erc7201` is also allowed. + +A custom layout cannot make contract's storage "wrap around". +If the selected base slot would push the static variables past the end of storage, +the compiler will issue an error. +Note that the data areas of dynamic arrays and mappings are not affected by this check because +their layout is not linear. +Regardless of the base slot used, their locations are calculated in a way that always puts them +within the range of ``uint256`` and their sizes are not known at compilation time. + +While there are no other limits placed on the base slot, it is recommended to avoid locations that are +too close to the end of the address space. +Leaving too little space may complicate contract upgrades or cause problems for contracts that store +additional values past their allocated space using inline assembly. + +The storage layout can only be specified for the topmost contract of an inheritance tree, and +affects locations of all the storage variables in all the contracts in that tree. +Variables are laid out according to the order of their definitions and the +positions of their contracts in the :ref:`linearized inheritance hierarchy` +and a custom base slot preserves their relative positions, shifting them all by the same amount. + +The storage layout cannot be specified for abstract contracts, interfaces and libraries. +Also, it is important to note that it does *not* affect transient state variables. + +For details about storage layout and the effect of the layout specifier on it see +:ref:`layout of storage variables`. + +.. warning:: + The identifiers ``layout`` and ``at`` are not yet reserved as keywords in the language. + It is strongly recommended to avoid using them since they will become reserved in a future + breaking release. diff --git a/docs/contracts/errors.rst b/docs/contracts/errors.rst index 4c6a5cc422..86b4909408 100644 --- a/docs/contracts/errors.rst +++ b/docs/contracts/errors.rst @@ -1,20 +1,36 @@ -.. index:: ! error, revert, ! selector; of an error +.. index:: ! error, revert, require, ! selector; of an error .. _errors: +<<<<<<< HEAD ******************************* Errores e Instrucción Revert ******************************* +======= +************* +Custom Errors +************* +>>>>>>> english/develop Los errores en Solidity proporcionan una forma conveniente y eficiente en gas de explicar al usuario por qué ha fallado una operación. Se pueden definir dentro y fuera de los contratos (incluidas las interfaces y bibliotecas). +<<<<<<< HEAD Deben utilizarse junto con la instrucción :ref:`revert statement ` que hace que se reviertan todos los cambios en la llamada actual y que los datos de error se devuelvan al llamador. +======= +They have to be used together with the :ref:`revert statement ` +or the :ref:`require function `. +In the case of ``revert`` statements, or ``require`` calls where the condition is evaluated to be false, +all changes in the current call are reverted, and the error data passed back to the caller. + +The example below shows custom error usage with the ``revert`` statement in function ``transferWithRevertError``, +as well as the newer approach with ``require`` in function ``transferWithRequireError``. +>>>>>>> english/develop .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 - pragma solidity ^0.8.4; + pragma solidity ^0.8.27; /// Insufficient balance for transfer. Needed `required` but only /// `available` available. @@ -24,7 +40,7 @@ que hace que se reviertan todos los cambios en la llamada actual y que los datos contract TestToken { mapping(address => uint) balance; - function transfer(address to, uint256 amount) public { + function transferWithRevertError(address to, uint256 amount) public { if (amount > balance[msg.sender]) revert InsufficientBalance({ available: balance[msg.sender], @@ -33,12 +49,28 @@ que hace que se reviertan todos los cambios en la llamada actual y que los datos balance[msg.sender] -= amount; balance[to] += amount; } + function transferWithRequireError(address to, uint256 amount) public { + require(amount <= balance[msg.sender], InsufficientBalance(balance[msg.sender], amount)); + balance[msg.sender] -= amount; + balance[to] += amount; + } // ... } +<<<<<<< HEAD Los errores no se pueden sobrecargar ni anular, pero se heredan. El mismo error se puede definir en varios lugares, siempre y cuando los ámbitos sean distintos. Las instancias de errores solo se pueden crear utilizando instrucciones ``revert``. +======= +Another important detail to mention when it comes to using ``require`` with custom errors, is that memory +allocation for the error-based revert reason will only happen in the reverting case, which, along with +optimization of constants and string literals makes this about as gas-efficient as the +``if (!condition) revert CustomError(args)`` pattern. + +Errors cannot be overloaded or overridden but are inherited. +The same error can be defined in multiple places as long as the scopes are distinct. +Instances of errors can only be created using ``revert`` statements, or as the second argument to ``require`` functions. +>>>>>>> english/develop El error crea datos que luego se pasan al llamador con la operación de reversión para volver al componente fuera de la cadena o capturarlo en una instrucción :ref:`try/catch `. @@ -62,10 +94,16 @@ El selector consiste en los primeros 4 bytes del hash keccak256 de la firma del que no son identificables por el llamante. Para el exterior, es decir, el ABI, sólo el nombre del error es relevante, no el contrato o el archivo donde está definido. +<<<<<<< HEAD La sentencia ``require(condition, "description");`` sería equivalente a ``if (!condition) revert Error("description")`` si pudiera definir ``error Error(string)``. Tenga en cuenta, sin embargo, que ``Error`` es un tipo integrado y no se puede definir en código proporcionado por el usuario. +======= +The statement ``require(condition, "description");`` would be equivalent to +``if (!condition) revert Error("description")`` if you could define ``error Error(string)``. +Note, however, that ``Error`` is a built-in type and cannot be defined in user-supplied code. +>>>>>>> english/develop De manera similar, un ``assert`` o condiciones similares se revertirán con un error del tipo integrado ``Panic(uint256)`` diff --git a/docs/contracts/events.rst b/docs/contracts/events.rst index 8c73c31603..c83970099a 100644 --- a/docs/contracts/events.rst +++ b/docs/contracts/events.rst @@ -15,7 +15,7 @@ arguments to be stored in the transaction's log - a special data structure in the blockchain. These logs are associated with the address of the contract that emitted them, are incorporated into the blockchain, and stay there as long as a block is accessible (forever as of now, but this might -change in the future). The Log and its event data is not accessible from within +change in the future). The Log and its event data are not accessible from within contracts (not even from the contract that created them). It is possible to request a Merkle proof for logs, so if diff --git a/docs/contracts/function-modifiers.rst b/docs/contracts/function-modifiers.rst index 454e12ab65..2fd0357db0 100644 --- a/docs/contracts/function-modifiers.rst +++ b/docs/contracts/function-modifiers.rst @@ -19,7 +19,6 @@ if they are marked ``virtual``. For details, please see // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.1 <0.9.0; - // This will report a warning due to deprecated selfdestruct contract owned { constructor() { owner = payable(msg.sender); } @@ -41,16 +40,6 @@ if they are marked ``virtual``. For details, please see } } - contract destructible is owned { - // This contract inherits the `onlyOwner` modifier from - // `owned` and applies it to the `destroy` function, which - // causes that calls to `destroy` only have an effect if - // they are made by the stored owner. - function destroy() public onlyOwner { - selfdestruct(owner); - } - } - contract priced { // Modifiers can receive arguments: modifier costs(uint price) { @@ -60,7 +49,7 @@ if they are marked ``virtual``. For details, please see } } - contract Register is priced, destructible { + contract Register is priced, owned { mapping(address => bool) registeredAddresses; uint price; @@ -73,6 +62,9 @@ if they are marked ``virtual``. For details, please see registeredAddresses[msg.sender] = true; } + // This contract inherits the `onlyOwner` modifier from + // the `owned` contract. As a result, calls to `changePrice` will + // only take effect if they are made by the stored owner. function changePrice(uint price_) public onlyOwner { price = price_; } diff --git a/docs/contracts/functions.rst b/docs/contracts/functions.rst index 5b82a93bcc..163a891f12 100644 --- a/docs/contracts/functions.rst +++ b/docs/contracts/functions.rst @@ -174,7 +174,7 @@ Functions can be declared ``view`` in which case they promise not to modify the The following statements are considered modifying the state: -#. Writing to state variables. +#. Writing to state variables (storage and transient storage). #. :ref:`Emitting events `. #. :ref:`Creating other contracts `. #. Using ``selfdestruct``. @@ -226,7 +226,7 @@ This means that reading from ``immutable`` variables can be a non-pure operation In addition to the list of state modifying statements explained above, the following are considered reading from the state: -#. Reading from state variables. +#. Reading from state variables (storage and transient storage). #. Accessing ``address(this).balance`` or ``
    .balance``. #. Accessing any of the members of ``block``, ``tx``, ``msg`` (with the exception of ``msg.sig`` and ``msg.data``). #. Calling any function not marked ``pure``. @@ -267,7 +267,7 @@ This behavior is also in line with the ``STATICCALL`` opcode. .. note:: Prior to version 0.4.17 the compiler did not enforce that ``pure`` is not reading the state. - It is a compile-time type check, which can be circumvented doing invalid explicit conversions + It is a compile-time type check, which can be circumvented by doing invalid explicit conversions between contract types, because the compiler can verify that the type of the contract does not do state-changing operations, but it cannot check that the contract that will be called at runtime is actually of that type. @@ -310,6 +310,10 @@ will consume more gas than the 2300 gas stipend: - Calling an external function which consumes a large amount of gas - Sending Ether +.. warning:: + ``send()`` and ``transfer()`` are deprecated and scheduled for removal. + See the section on :ref:`send ` and :ref:`transfer ` for more information. + .. warning:: When Ether is sent directly to a contract (without a function call, i.e. sender uses ``send`` or ``transfer``) but the receiving contract does not define a receive Ether function or a payable fallback function, @@ -319,7 +323,6 @@ will consume more gas than the 2300 gas stipend: not recommended, since the fallback is invoked and would not fail for interface confusions on the part of the sender). - .. warning:: A contract without a receive Ether function can receive Ether as a recipient of a *coinbase transaction* (aka *miner block reward*) @@ -440,6 +443,7 @@ operations as long as there is enough gas passed on to it. // If someone sends Ether to that contract, // the transfer will fail, i.e. this returns false here. + // This will report a warning (deprecation) return testPayable.send(2 ether); } diff --git a/docs/contracts/inheritance.rst b/docs/contracts/inheritance.rst index 02ab19163f..778cd1c26e 100644 --- a/docs/contracts/inheritance.rst +++ b/docs/contracts/inheritance.rst @@ -40,27 +40,27 @@ Details are given in the following example. // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; - // This will report a warning due to deprecated selfdestruct contract Owned { - constructor() { owner = payable(msg.sender); } address payable owner; + constructor() { owner = payable(msg.sender); } } - // Use `is` to derive from another contract. Derived // contracts can access all non-private members including // internal functions and state variables. These cannot be // accessed externally via `this`, though. - contract Destructible is Owned { + contract Emittable is Owned { + event Emitted(); + // The keyword `virtual` means that the function can change // its behavior in derived classes ("overriding"). - function destroy() virtual public { - if (msg.sender == owner) selfdestruct(owner); + function emitEvent() virtual public { + if (msg.sender == owner) + emit Emitted(); } } - // These abstract contracts are only provided to make the // interface known to the compiler. Note the function // without body. If a contract does not implement all @@ -69,37 +69,35 @@ Details are given in the following example. function lookup(uint id) public virtual returns (address adr); } - abstract contract NameReg { function register(bytes32 name) public virtual; function unregister() public virtual; } - // Multiple inheritance is possible. Note that `Owned` is - // also a base class of `Destructible`, yet there is only a single + // also a base class of `Emittable`, yet there is only a single // instance of `Owned` (as for virtual inheritance in C++). - contract Named is Owned, Destructible { + contract Named is Owned, Emittable { constructor(bytes32 name) { Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970); NameReg(config.lookup(1)).register(name); } // Functions can be overridden by another function with the same name and - // the same number/types of inputs. If the overriding function has different + // the same number/types of inputs. If the overriding function has different // types of output parameters, that causes an error. // Both local and message-based function calls take these overrides // into account. // If you want the function to override, you need to use the // `override` keyword. You need to specify the `virtual` keyword again // if you want this function to be overridden again. - function destroy() public virtual override { + function emitEvent() public virtual override { if (msg.sender == owner) { Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970); NameReg(config.lookup(1)).unregister(); // It is still possible to call a specific // overridden function. - Destructible.destroy(); + Emittable.emitEvent(); } } } @@ -108,93 +106,132 @@ Details are given in the following example. // If a constructor takes an argument, it needs to be // provided in the header or modifier-invocation-style at // the constructor of the derived contract (see below). - contract PriceFeed is Owned, Destructible, Named("GoldFeed") { + contract PriceFeed is Owned, Emittable, Named("GoldFeed") { + uint info; + function updateInfo(uint newInfo) public { if (msg.sender == owner) info = newInfo; } // Here, we only specify `override` and not `virtual`. // This means that contracts deriving from `PriceFeed` - // cannot change the behavior of `destroy` anymore. - function destroy() public override(Destructible, Named) { Named.destroy(); } + // cannot change the behavior of `emitEvent` anymore. + function emitEvent() public override(Emittable, Named) { Named.emitEvent(); } function get() public view returns(uint r) { return info; } - - uint info; } -Note that above, we call ``Destructible.destroy()`` to "forward" the -destruction request. The way this is done is problematic, as +Note that above, we call ``Emittable.emitEvent()`` to "forward" the +emit event request. The way this is done is problematic, as seen in the following example: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; - // This will report a warning due to deprecated selfdestruct - contract owned { - constructor() { owner = payable(msg.sender); } + contract Owned { address payable owner; + constructor() { owner = payable(msg.sender); } } - contract Destructible is owned { - function destroy() public virtual { - if (msg.sender == owner) selfdestruct(owner); + contract Emittable is Owned { + event Emitted(); + + function emitEvent() virtual public { + if (msg.sender == owner) { + emit Emitted(); + } } } - contract Base1 is Destructible { - function destroy() public virtual override { /* do cleanup 1 */ Destructible.destroy(); } + contract Base1 is Emittable { + event Base1Emitted(); + function emitEvent() public virtual override { + /* Here, we emit an event to simulate some Base1 logic */ + emit Base1Emitted(); + Emittable.emitEvent(); + } } - contract Base2 is Destructible { - function destroy() public virtual override { /* do cleanup 2 */ Destructible.destroy(); } + contract Base2 is Emittable { + event Base2Emitted(); + function emitEvent() public virtual override { + /* Here, we emit an event to simulate some Base2 logic */ + emit Base2Emitted(); + Emittable.emitEvent(); + } } contract Final is Base1, Base2 { - function destroy() public override(Base1, Base2) { Base2.destroy(); } + event FinalEmitted(); + function emitEvent() public override(Base1, Base2) { + /* Here, we emit an event to simulate some Final logic */ + emit FinalEmitted(); + Base2.emitEvent(); + } } -A call to ``Final.destroy()`` will call ``Base2.destroy`` because we specify it +A call to ``Final.emitEvent()`` will call ``Base2.emitEvent`` because we specify it explicitly in the final override, but this function will bypass -``Base1.destroy``. The way around this is to use ``super``: +``Base1.emitEvent``, resulting in the following sequence of events: +``FinalEmitted -> Base2Emitted -> Emitted``, instead of the expected sequence: +``FinalEmitted -> Base2Emitted -> Base1Emitted -> Emitted``. +The way around this is to use ``super``: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; - // This will report a warning due to deprecated selfdestruct - contract owned { - constructor() { owner = payable(msg.sender); } + contract Owned { address payable owner; + constructor() { owner = payable(msg.sender); } } - contract Destructible is owned { - function destroy() virtual public { - if (msg.sender == owner) selfdestruct(owner); + contract Emittable is Owned { + event Emitted(); + + function emitEvent() virtual public { + if (msg.sender == owner) { + emit Emitted(); + } } } - contract Base1 is Destructible { - function destroy() public virtual override { /* do cleanup 1 */ super.destroy(); } + contract Base1 is Emittable { + event Base1Emitted(); + function emitEvent() public virtual override { + /* Here, we emit an event to simulate some Base1 logic */ + emit Base1Emitted(); + super.emitEvent(); + } } - contract Base2 is Destructible { - function destroy() public virtual override { /* do cleanup 2 */ super.destroy(); } + contract Base2 is Emittable { + event Base2Emitted(); + function emitEvent() public virtual override { + /* Here, we emit an event to simulate some Base2 logic */ + emit Base2Emitted(); + super.emitEvent(); + } } contract Final is Base1, Base2 { - function destroy() public override(Base1, Base2) { super.destroy(); } + event FinalEmitted(); + function emitEvent() public override(Base1, Base2) { + /* Here, we emit an event to simulate some Final logic */ + emit FinalEmitted(); + super.emitEvent(); + } } -If ``Base2`` calls a function of ``super``, it does not simply +If ``Final`` calls a function of ``super``, it does not simply call this function on one of its base contracts. Rather, it calls this function on the next base contract in the final -inheritance graph, so it will call ``Base1.destroy()`` (note that +inheritance graph, so it will call ``Base1.emitEvent()`` (note that the final inheritance sequence is -- starting with the most -derived contract: Final, Base2, Base1, Destructible, owned). +derived contract: Final, Base2, Base1, Emittable, Owned). The actual function that is called when using super is not known in the context of the class where it is used, although its type is known. This is similar for ordinary @@ -340,8 +377,8 @@ of the variable: .. _modifier-overriding: -Modifier Overriding -=================== +Modifier Overriding (deprecated) +================================ Function modifiers can override each other. This works in the same way as :ref:`function overriding ` (except that there is no overloading for modifiers). The @@ -355,6 +392,7 @@ and the ``override`` keyword must be used in the overriding modifier: contract Base { + // This will report a warning (deprecation) modifier foo() virtual {_;} } @@ -374,11 +412,13 @@ explicitly: contract Base1 { + // This will report a warning (deprecation) modifier foo() virtual {_;} } contract Base2 { + // This will report a warning (deprecation) modifier foo() virtual {_;} } @@ -387,6 +427,8 @@ explicitly: modifier foo() override(Base1, Base2) {_;} } +.. warning:: + ``virtual`` modifiers are deprecated and scheduled for removal. .. index:: ! constructor @@ -511,7 +553,7 @@ Multiple Inheritance and Linearization Languages that allow multiple inheritance have to deal with several problems. One is the `Diamond Problem `_. -Solidity is similar to Python in that it uses "`C3 Linearization `_" +Solidity is similar to Python in that it uses C3 Linearization to force a specific order in the directed acyclic graph (DAG) of base classes. This results in the desirable property of monotonicity but disallows some inheritance graphs. Especially, the order in diff --git a/docs/contracts/libraries.rst b/docs/contracts/libraries.rst index 7256ebe031..a3c04ba064 100644 --- a/docs/contracts/libraries.rst +++ b/docs/contracts/libraries.rst @@ -196,7 +196,7 @@ It is possible to obtain the address of a library by converting the library type to the ``address`` type, i.e. using ``address(LibraryName)``. As the compiler does not know the address where the library will be deployed, the compiled hex code -will contain placeholders of the form ``__$30bbc0abd4d6364515865950d3e0d10953$__``. The placeholder +will contain placeholders of the form ``__$30bbc0abd4d6364515865950d3e0d10953$__`` `(format was different `_. The placeholder is a 34 character prefix of the hex encoding of the keccak256 hash of the fully qualified library name, which would be for example ``libraries/bigint.sol:BigInt`` if the library was stored in a file called ``bigint.sol`` in a ``libraries/`` directory. Such bytecode is incomplete and should not be diff --git a/docs/contracts/transient-storage.rst b/docs/contracts/transient-storage.rst new file mode 100644 index 0000000000..b2d0be2922 --- /dev/null +++ b/docs/contracts/transient-storage.rst @@ -0,0 +1,172 @@ +.. index:: ! transient storage, ! transient, tstore, tload + +.. _transient-storage: + +***************** +Transient Storage +***************** + +Transient storage is another data location besides memory, storage, calldata +(and return-data and code) which was introduced alongside its respective opcodes +``TSTORE`` and ``TLOAD`` by `EIP-1153 `_. +This new data location behaves as a key-value store similar to storage with the main +difference being that data in transient storage is not permanent, but is scoped to +the current transaction only, after which it will be reset to zero. +Since the content of transient storage has very limited lifetime and size, +it does not need to be stored permanently as a part of state +and the associated gas costs are much lower than in case of storage. +EVM version ``cancun`` or newer is required for transient storage to be available. + +Transient storage variables cannot be initialized in place, i.e., they cannot be assigned +to upon declaration, since the value would be cleared at the end of the creation transaction, +rendering the initialization ineffective. +Transient variables will be :ref:`default value` initialized depending on +their underlying type. +``constant`` and ``immutable`` variables conflict with transient storage, since +their values are either inlined or directly stored in code. + +Transient storage variables have completely independent address space from storage, +so that the order of transient state variables does not affect the layout of storage +state variables and vice-versa. +They do need distinct names though because all state variables share the same namespace. +It is also important to note that the values in transient storage are packed in the +same fashion as those in persistent storage. +See :ref:`Storage Layout ` for more information. + +Besides that, transient variables can have visibility as well and ``public`` ones will +have a getter function generated automatically as usual. + +Note that, currently, such use of ``transient`` as a data location is only allowed for +:ref:`value type ` state variable declarations. +Reference types, such as arrays, mappings and structs, as well as local or parameter +variables are not yet supported. + +An expected canonical use case for transient storage is cheaper reentrancy locks, +which can be readily implemented with the opcodes as showcased next. + +.. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity ^0.8.28; + + contract Generosity { + mapping(address => bool) sentGifts; + bool transient locked; + + modifier nonReentrant { + require(!locked, "Reentrancy attempt"); + locked = true; + _; + // Unlocks the guard, making the pattern composable. + // After the function exits, it can be called again, even in the same transaction. + locked = false; + } + + function claimGift() nonReentrant public { + require(address(this).balance >= 1 ether); + require(!sentGifts[msg.sender]); + (bool success, ) = msg.sender.call{value: 1 ether}(""); + require(success); + + // In a reentrant function, doing this last would open up the vulnerability + sentGifts[msg.sender] = true; + } + } + +Transient storage is private to the contract that owns it, in the same way as persistent storage. +Only owning contract frames may access their transient storage, and when they do, all the frames access the same transient store. + +Transient storage is part of the EVM state and is subject to the same mutability enforcements +as persistent storage. As such, any read access to it is not ``pure`` and writing access is not ``view``. + +If the ``TSTORE`` opcode is called within the context of a ``STATICCALL``, +it will result in an exception instead of performing the modification. +``TLOAD`` is allowed within the context of a ``STATICCALL``. + +When transient storage is used in the context of ``DELEGATECALL`` or ``CALLCODE``, +then the owning contract of the transient storage is the contract that issued ``DELEGATECALL`` +or ``CALLCODE`` instruction (the caller) as with persistent storage. +When transient storage is used in the context of ``CALL`` or ``STATICCALL``, +then the owning contract of the transient storage is the contract that is the target +of the ``CALL`` or ``STATICCALL`` instruction (the callee). + +.. note:: + In the case of ``DELEGATECALL``, since references to transient storage variables + are currently not supported, it is not possible to pass those into library calls. + In libraries, access to transient storage is only possible using inline assembly. + +If a frame reverts, all writes to transient storage that took place between entry +to the frame and the return are reverted, including those that took place in inner calls. +The caller of an external call may employ a ``try ... catch`` block to prevent reverts +bubbling up from the inner calls. + +********************************************************************* +Composability of Smart Contracts and the Caveats of Transient Storage +********************************************************************* + +Given the caveats mentioned in the specification of EIP-1153, +in order to preserve the composability of your smart contract, +utmost care is recommended for more advanced use cases of transient storage. + +For smart contracts, composability is a very important design principle to achieve self-contained behaviour, +such that multiple calls into individual smart contracts can be composed to more complex applications. +So far the EVM largely guaranteed composable behaviour, since multiple calls into a smart contract +within a complex transaction are virtually indistinguishable from multiple calls to the contract +stretched over several transactions. However, transient storage allows a violation of this principle, +and incorrect use may lead to complex bugs that only surface when used across several calls. + +Let's illustrate the problem with a simple example: + +.. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity ^0.8.28; + + contract MulService { + uint transient multiplier; + function setMultiplier(uint mul) external { + multiplier = mul; + } + + function multiply(uint value) external view returns (uint) { + return value * multiplier; + } + } + +and a sequence of external calls: + +.. code-block:: solidity + + setMultiplier(42); + multiply(1); + multiply(2); + +If the example used memory or storage to store the multiplier, it would be fully composable. +It would not matter whether you split the sequence into separate transactions or grouped them in some way. +You would always get the same result: after ``multiplier`` is set to ``42``, the subsequent calls +would return ``42`` and ``84`` respectively. +This enables use cases such as batching calls from multiple transactions +together to reduce gas costs. +Transient storage potentially breaks such use cases since composability can no longer be taken for granted. +In the example, if the calls are not executed in the same transaction, then ``multiplier`` +is reset and the next calls to function ``multiply`` would always return ``0``. + +As another example, since transient storage is constructed as a relatively cheap key-value store, +a smart contract author may be tempted to use transient storage as a replacement for in-memory mappings +without keeping track of the modified keys in the mapping and thereby without clearing the mapping +at the end of the call. +This, however, can easily lead to unexpected behaviour in complex transactions, +in which values set by a previous call into the contract within the same transaction remain. + +The use of transient storage for reentrancy locks that are cleared at the end of the call frame +into the contract, is safe. +However, be sure to resist the temptation to save the 100 gas used for resetting the +reentrancy lock, since failing to do so, will restrict your contract to only one call +within a transaction, preventing its use in complex composed transactions, +which have been a cornerstone for complex applications on chain. + +It is recommend to generally always clear transient storage completely at the end of a call +into your smart contract to avoid these kinds of issues and to simplify +the analysis of the behaviour of your contract within complex transactions. +Check the `Security Considerations section of EIP-1153 `_ +for further details. \ No newline at end of file diff --git a/docs/contributing.rst b/docs/contributing.rst index 8ce402680b..b5eb3c08ed 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -8,8 +8,8 @@ In particular, we appreciate support in the following areas: * Reporting issues. * Fixing and responding to `Solidity's GitHub issues - `_, especially those tagged as - `"good first issue" `_ which are + `_, especially those tagged as + `"good first issue" `_ which are meant as introductory issues for external contributors. * Improving the documentation. * `Translating `_ the documentation into more languages. @@ -32,13 +32,16 @@ the team and contributors are working on, you can join our public team call: - Wednesdays at 3PM CET/CEST. -The call takes place on `Jitsi `_. +The call takes place on `Jitsi `_. + +New topics can be freely added to the `agenda `_ +and will be scheduled for discussion on the nearest call. How to Report Issues ==================== To report an issue, please use the -`GitHub issues tracker `_. When +`GitHub issues tracker `_. When reporting issues, please mention the following details: * Solidity version. @@ -76,11 +79,11 @@ New features and bugfixes should be added to the ``Changelog.md`` file: please follow the style of previous entries, when applicable. Finally, please make sure you respect the `coding style -`_ +`_ for this project. Also, even though we do CI testing, please test your code and ensure that it builds locally before submitting a pull request. -We highly recommend going through our `review checklist `_ before submitting the pull request. +We highly recommend going through our `review checklist `_ before submitting the pull request. We thoroughly review every PR and will help you get it right, but there are many common problems that can be easily avoided, making the review much smoother. Thank you for your help! @@ -92,8 +95,9 @@ Prerequisites ------------- For running all compiler tests you may want to optionally install a few -dependencies (`evmone `_, -`libz3 `_). +dependencies (`evmone `_, +`z3 `_, `Eldarica `_, +`cvc5 `). On macOS systems, some of the testing scripts expect GNU coreutils to be installed. This can be easiest accomplished using Homebrew: ``brew install coreutils``. @@ -118,7 +122,7 @@ application ``soltest`` (or its wrapper ``scripts/soltest.sh``), as well as comm compilation tests. The test system automatically tries to discover the location of -the `evmone `_ for running the semantic tests. +the `evmone `_ for running the semantic tests. The ``evmone`` library must be located in the ``deps`` or ``deps/lib`` directory relative to the current working directory, to its parent or its parent's parent. Alternatively, an explicit location @@ -131,13 +135,15 @@ flag to ``scripts/soltest.sh``. The ``evmone`` library should end with the file name extension ``.so`` on Linux, ``.dll`` on Windows systems and ``.dylib`` on macOS. -For running SMT tests, the ``libz3`` library must be installed and locatable -by ``cmake`` during compiler configure stage. +For running SMT tests, the ``z3`` executable must be present in ``PATH``. +A few SMT tests use ``Eldarica`` instead of ``z3``. +These require its executable (``eld``) to be present in ``PATH`` for the tests to pass. +However, if ``Eldarica`` is not found, these tests will be automatically skipped. -If the ``libz3`` library is not installed on your system, you should disable the +If ``z3`` is not present on your system, you should disable the SMT tests by exporting ``SMT_FLAGS=--no-smt`` before running ``./scripts/tests.sh`` or running ``./scripts/soltest.sh --no-smt``. -These tests are ``libsolidity/smtCheckerTests`` and ``libsolidity/smtCheckerTestsJSON``. +These tests are ``libsolidity/smtCheckerTests``. .. note:: @@ -163,7 +169,7 @@ See especially: .. note:: Those working in a Windows environment wanting to run the above basic sets - without libz3. Using Git Bash, you use: ``./build/test/Release/soltest.exe -- --no-smt``. + without z3. Using Git Bash, you use: ``./build/test/Release/soltest.exe -- --no-smt``. If you are running this in plain Command Prompt, use ``.\build\test\Release\soltest.exe -- --no-smt``. If you want to debug using GDB, make sure you build differently than the "usual". @@ -274,7 +280,7 @@ Command-line Tests Our suite of end-to-end command-line tests checks the behaviour of the compiler binary as a whole in various scenarios. -These tests are located in `test/cmdlineTests/ `_, +These tests are located in `test/cmdlineTests/ `_, one per subdirectory, and can be executed using the ``cmdlineTests.sh`` script. By default the script runs all available tests. @@ -544,7 +550,7 @@ The Solidity forum serves as the place to propose and discuss new language featu the early stages of ideation or modifications of existing features. As soon as proposals get more tangible, their -implementation will also be discussed in the `Solidity GitHub repository `_ +implementation will also be discussed in the `Solidity GitHub repository `_ in the form of issues. In addition to the forum and issue discussions, we regularly host language design discussion calls in which selected @@ -552,9 +558,9 @@ topics, issues or feature implementations are debated in detail. The invitation We are also sharing feedback surveys and other content that is relevant to language design in the forum. -If you want to know where the team is standing in terms or implementing new features, you can follow the implementation status in the `Solidity GitHub project `_. +If you want to know where the team is standing in terms of implementing new features, you can follow the implementation status in the `Solidity GitHub project `_. Issues in the design backlog need further specification and will either be discussed in a language design call or in a regular team call. You can -see the upcoming changes for the next breaking release by changing from the default branch (`develop`) to the `breaking branch `_. +see the upcoming changes for the next breaking release by changing from the default branch (`develop`) to the `breaking branch `_. For ad-hoc cases and questions, you can reach out to us via the `Solidity-dev Gitter channel `_ — a dedicated chatroom for conversations around the Solidity compiler and language development. diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 536a7de9e3..613d1d6900 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -109,6 +109,7 @@ de lo contrario la opción ``valor`` no estaría disponible. ``feed.info{value: 10, gas: 800}`` no ejecuta la función y se pierden los ajustes del ``value`` y ``gas``, solo ``feed.info{value: 10, gas: 800}()`` realiza la llamada de la función. +<<<<<<< HEAD Debido al hecho que el EVM considera una llamada a un contrato inexistente siempre tenga éxito, Solitiy utiliza el ``extcodesize`` opcode para comprobar que el contrato que está a punto de ser llamado existe realmente (contiene codigo) @@ -126,6 +127,39 @@ que operan en las direcciones en lugar de instancias de contrato. Las llamadas a funciones también causan excepciones si el propio contrato llamado arroja una excepción o se queda sin gas. +======= +.. warning:: + Due to the fact that the EVM considers a call to a non-existing contract to + always succeed, Solidity uses the ``extcodesize`` opcode to check that + the contract that is about to be called actually exists (it contains code) + and causes an exception if it does not. This check is skipped if the return + data will be decoded after the call and thus the ABI decoder will catch the + case of a non-existing contract. + + This check is not performed in case of :ref:`low-level calls ` which + operate on addresses rather than contract instances. + +.. warning:: + Be careful when using high-level calls to + :ref:`precompiled contracts `, + since the compiler considers them non-existing according to the + above logic even though they execute code and can return data. + +.. note:: + Since the version 0.8.10, the compiler does not check ``extcodesize`` on + high-level external calls if return data is expected, because an empty code + will be unable to return data, and the ABI decoder will revert. + As a consequence, this allows high-level external calls to precompiled + contracts, since they can return data despite having no code + associated with their addresses. + + Read about :ref:`precompiled contracts ` and + :ref:`low-level calls ` + for more information. + +Function calls also cause exceptions if the called contract itself +throws an exception or goes out of gas. +>>>>>>> english/develop .. warning:: Cualquier interacción con otro contrato supone un peligro potencial, especialmente @@ -231,7 +265,13 @@ Como se ve en el ejemplo, es posible traspasar Ether a la creación usando la op pero no es posible limitar la cantidad de gas. Si la creación falla (debido al desbordamiento de la pila, falta de balance o cualquier otro problema), se dispara una excepción. +<<<<<<< HEAD Creaciones de contratos salted / create2 +======= +.. _salted-contract-creations: + +Salted contract creations / create2 +>>>>>>> english/develop ----------------------------------- Al crear un contrato, la dirección del contrato se calcula a partir de @@ -575,7 +615,13 @@ de la llamada en forma de :ref:`error instances `. Los errores incorpora explica a continuación. ``Error`` se usa para condiciones de error "regular", mientras que ``Panic`` se usa para errores que no deberían estar presentes en el código libre de errores. +<<<<<<< HEAD Panic a través de ``assert`` y Error a través de ``require`` +======= +.. _assert-and-require-statements: + +Panic via ``assert`` and Error via ``require`` +>>>>>>> english/develop ---------------------------------------------- Las funciones de conveniencia ``assert`` y ``require`` se pueden usar para verificar las condiciones y lanzar una excepción @@ -603,6 +649,7 @@ El código de error proporcionado con los datos de error indica el tipo de páni #. 0x41: Si asigna demasiada memoria o crea una matriz que es demasiado grande. #. 0x51: Si llama a una variable inicializada en cero de tipo de función interna. +<<<<<<< HEAD La función``'require`` crea un error sin ningún dato o un error del tipo ``Error(string)``. Debe utilizarse para garantizar condiciones válidas que no se puedan detectar hasta el momento de la ejecución. Esto incluye condiciones sobre entradas o valores devueltos de llamadas a contratos externos. @@ -613,6 +660,22 @@ de la ejecución. Esto incluye condiciones sobre entradas o valores devueltos de Utilice ``if (!condition) revert CustomError();`` en su lugar. El compilador genera una excepción ``Error(string)`` (o una excepción sin datos) en las siguientes situaciones: +======= +The ``require`` function provides three overloads: + +1. ``require(bool)`` which will revert without any data (not even an error selector). +2. ``require(bool, string)`` which will revert with an ``Error(string)``. +3. ``require(bool, error)`` which will revert with the custom, user supplied error provided as the second argument. + +.. note:: + ``require`` arguments are evaluated unconditionally, so take special care to make sure that + they are not expressions with unexpected side-effects. + For example, in ``require(condition, CustomError(f()));`` and ``require(condition, f());``, + function ``f()`` will be called regardless of whether the supplied condition is ``true`` or ``false``. + +An ``Error(string)`` exception (or an exception without data) is generated +by the compiler in the following situations: +>>>>>>> english/develop #. Llamar a ``require(x)`` donde ``x`` se evalúa como ``false``. #. Si se utiliza ``revert()`` o ``revert("description")``. @@ -634,11 +697,19 @@ an ``Error`` or a ``Panic`` (or whatever else was given): #. Si crea un contrato utilizando la palabra clave ``new`` pero la creación del contrato :ref:`no finaliza propiamente`. +<<<<<<< HEAD Opcionalmente, puede proporcionar una cadena de mensaje para ``require``, pero no para ``assert``. .. note:: Si no proporciona un argumento de cadena a ``require``, se revertirá con datos de error vacíos, sin siquiera incluir el selector de errores. +======= +You can optionally provide a message string or a custom error to ``require``, but not to ``assert``. + +.. note:: + If you do not provide a string or custom error argument to ``require``, it will revert + with empty error data, not even including the error selector. +>>>>>>> english/develop En el ejemplo siguiente se muestra cómo puede utilizar ``require`` para comprobar las condiciones de las entradas y ``assert`` para la comprobación interna de errores. @@ -647,16 +718,16 @@ y ``assert`` para la comprobación interna de errores. :force: // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.5.0 <0.9.0; + pragma solidity >=0.6.2 <0.9.0; contract Sharer { function sendHalf(address payable addr) public payable returns (uint balance) { require(msg.value % 2 == 0, "Even value required."); uint balanceBeforeTransfer = address(this).balance; - addr.transfer(msg.value / 2); - // Since transfer throws an exception on failure and - // cannot call back here, there should be no way for us to - // still have half of the Ether. + (bool success, ) = addr.call{value: msg.value / 2}(""); + require(success); + // Since require will stop execution and revert if success is false, + // there should be no way for us to still have half of the Ether. assert(address(this).balance == balanceBeforeTransfer - msg.value / 2); return address(this).balance; } @@ -727,7 +798,8 @@ junto con ``revert`` y el equivalente ``require``: if (msg.sender != owner) revert Unauthorized(); - payable(msg.sender).transfer(address(this).balance); + (bool success, ) = payable(msg.sender).call{value: address(this).balance}(""); + require(success); } } diff --git a/docs/docs.sh b/docs/docs.sh index f2c5667612..abe4921e30 100755 --- a/docs/docs.sh +++ b/docs/docs.sh @@ -31,5 +31,8 @@ set -euo pipefail script_dir="$(dirname "$0")" cd "${script_dir}" -pip3 install -r requirements.txt --upgrade --upgrade-strategy eager +# TODO `--ignore-installed` now fixes an issue where pip tries to uninstall a Debian installed package, but is unable to +# TODO since Debian has decided to not use the RECORD file, which then breaks pip. +# TODO https://github.com/pypa/pip/issues/11631 and https://bugs.launchpad.net/ubuntu/+source/wheel/+bug/2063151 +pip3 install -r requirements.txt --ignore-installed --upgrade --upgrade-strategy eager sphinx-build -nW -b html -d _build/doctrees . _build/html diff --git a/docs/examples/blind-auction.rst b/docs/examples/blind-auction.rst index 47e19033f9..e5e3184a86 100644 --- a/docs/examples/blind-auction.rst +++ b/docs/examples/blind-auction.rst @@ -118,13 +118,14 @@ to receive their Ether - contracts cannot activate themselves. if (amount > 0) { // It is important to set this to zero because the recipient // can call this function again as part of the receiving call - // before `send` returns. + // before `call` returns. pendingReturns[msg.sender] = 0; // msg.sender is not of type `address payable` and must be // explicitly converted using `payable(msg.sender)` in order - // use the member function `send()`. - if (!payable(msg.sender).send(amount)) { + // use the member function `call()`. + (bool success, ) = payable(msg.sender).call{value: amount}(""); + if (!success) { // No need to call throw here, just reset the amount owing pendingReturns[msg.sender] = amount; return false; @@ -160,7 +161,8 @@ to receive their Ether - contracts cannot activate themselves. emit AuctionEnded(highestBidder, highestBid); // 3. Interaction - beneficiary.transfer(highestBid); + (bool success, ) = beneficiary.call{value: highestBid}(""); + require(success); } } @@ -310,7 +312,8 @@ invalid bids. // the same deposit. bidToCheck.blindedBid = bytes32(0); } - payable(msg.sender).transfer(refund); + (bool success, ) = payable(msg.sender).call{value: refund}(""); + require(success); } /// Withdraw a bid that was overbid. @@ -319,11 +322,12 @@ invalid bids. if (amount > 0) { // It is important to set this to zero because the recipient // can call this function again as part of the receiving call - // before `transfer` returns (see the remark above about + // before `call` returns (see the remark above about // conditions -> effects -> interaction). pendingReturns[msg.sender] = 0; - payable(msg.sender).transfer(amount); + (bool success, ) = payable(msg.sender).call{value: amount}(""); + require(success); } } @@ -336,7 +340,8 @@ invalid bids. if (ended) revert AuctionEndAlreadyCalled(); emit AuctionEnded(highestBidder, highestBid); ended = true; - beneficiary.transfer(highestBid); + (bool success, ) = beneficiary.call{value: highestBid}(""); + require(success); } // This is an "internal" function which means that it diff --git a/docs/examples/micropayment.rst b/docs/examples/micropayment.rst index 50f28005bf..377ee42f6b 100644 --- a/docs/examples/micropayment.rst +++ b/docs/examples/micropayment.rst @@ -55,7 +55,7 @@ as it provides a number of other security benefits. What to Sign ------------ -For a contract that fulfils payments, the signed message must include: +For a contract that fulfills payments, the signed message must include: 1. The recipient's address. 2. The amount to be transferred. @@ -80,6 +80,10 @@ the contract's address itself will be accepted. You can find an example of this in the first two lines of the ``claimPayment()`` function of the full contract at the end of this section. +Furthermore, instead of destroying the contract by calling ``selfdestruct``, +which is currently deprecated, we will disable the contract's functionalities by freezing it, +resulting in the reversion of any call after it being frozen. + Packing arguments ----------------- @@ -144,30 +148,56 @@ The full contract // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; - // This will report a warning due to deprecated selfdestruct - contract ReceiverPays { - address owner = msg.sender; + contract Owned { + address payable owner; + constructor() { + owner = payable(msg.sender); + } + } + + contract Freezable is Owned { + bool private _frozen = false; + + modifier notFrozen() { + require(!_frozen, "Inactive Contract."); + _; + } + + function freeze() internal { + if (msg.sender == owner) + _frozen = true; + } + } + + contract ReceiverPays is Freezable { mapping(uint256 => bool) usedNonces; constructor() payable {} - function claimPayment(uint256 amount, uint256 nonce, bytes memory signature) external { + function claimPayment(uint256 amount, uint256 nonce, bytes memory signature) + external + notFrozen + { require(!usedNonces[nonce]); usedNonces[nonce] = true; // this recreates the message that was signed on the client bytes32 message = prefixed(keccak256(abi.encodePacked(msg.sender, amount, nonce, this))); - require(recoverSigner(message, signature) == owner); - - payable(msg.sender).transfer(amount); + (bool success, ) = payable(msg.sender).call{value: amount}(""); + require(success); } - /// destroy the contract and reclaim the leftover funds. - function shutdown() external { + /// freeze the contract and reclaim the leftover funds. + function shutdown() + external + notFrozen + { require(msg.sender == owner); - selfdestruct(payable(msg.sender)); + freeze(); + (bool success, ) = payable(msg.sender).call{value: address(this).balance}(""); + require(success); } /// signature methods. @@ -196,7 +226,6 @@ The full contract returns (address) { (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig); - return ecrecover(message, v, r, s); } @@ -247,8 +276,8 @@ Opening the Payment Channel To open the payment channel, Alice deploys the smart contract, attaching the Ether to be escrowed and specifying the intended recipient and a -maximum duration for the channel to exist. This is the function -``SimplePaymentChannel`` in the contract, at the end of this section. +maximum duration for the channel to exist. This is the ``constructor`` +in the ``SimplePaymentChannel`` contract, at the end of this section. Making Payments --------------- @@ -305,7 +334,7 @@ Closing the Payment Channel When Bob is ready to receive his funds, it is time to close the payment channel by calling a ``close`` function on the smart contract. Closing the channel pays the recipient the Ether they are owed and -destroys the contract, sending any remaining Ether back to Alice. To +deactivates the contract by freezing it, sending any remaining Ether back to Alice. To close the channel, Bob needs to provide a message signed by Alice. The smart contract must verify that the message contains a valid signature from the sender. @@ -320,7 +349,7 @@ they could provide a message with a lower amount and cheat the recipient out of The function verifies the signed message matches the given parameters. If everything checks out, the recipient is sent their portion of the Ether, -and the sender is sent the rest via a ``selfdestruct``. +and the sender is sent the remaining funds via a ``transfer``. You can see the ``close`` function in the full contract. Channel Expiration @@ -342,11 +371,24 @@ The full contract // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.7.0 <0.9.0; - // This will report a warning due to deprecated selfdestruct - contract SimplePaymentChannel { - address payable public sender; // The account sending payments. - address payable public recipient; // The account receiving the payments. - uint256 public expiration; // Timeout in case the recipient never closes. + + contract Frozeable { + bool private _frozen = false; + + modifier notFrozen() { + require(!_frozen, "Inactive Contract."); + _; + } + + function freeze() internal { + _frozen = true; + } + } + + contract SimplePaymentChannel is Frozeable { + address payable public sender; // The account sending payments. + address payable public recipient; // The account receiving the payments. + uint256 public expiration; // Timeout in case the recipient never closes. constructor (address payable recipientAddress, uint256 duration) payable @@ -359,16 +401,25 @@ 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 memory signature) external { + function close(uint256 amount, bytes memory signature) + external + notFrozen + { require(msg.sender == recipient); require(isValidSignature(amount, signature)); - recipient.transfer(amount); - selfdestruct(sender); + freeze(); + (bool success, ) = recipient.call{value: amount}(""); + require(success); + (success, ) = sender.call{value: address(this).balance}(""); + require(success); } /// the sender can extend the expiration at any time - function extend(uint256 newExpiration) external { + function extend(uint256 newExpiration) + external + notFrozen + { require(msg.sender == sender); require(newExpiration > expiration); @@ -377,9 +428,14 @@ The full contract /// if the timeout is reached without the recipient closing the channel, /// then the Ether is released back to the sender. - function claimTimeout() external { + function claimTimeout() + external + notFrozen + { require(block.timestamp >= expiration); - selfdestruct(sender); + freeze(); + (bool success, ) = sender.call{value: address(this).balance}(""); + require(success); } function isValidSignature(uint256 amount, bytes memory signature) @@ -388,14 +444,12 @@ The full contract returns (bool) { bytes32 message = prefixed(keccak256(abi.encodePacked(this, amount))); - // check that the signature is from the payment sender return recoverSigner(message, signature) == sender; } /// All functions below this are just taken from the chapter /// 'creating and verifying signatures' chapter. - function splitSignature(bytes memory sig) internal pure @@ -411,7 +465,6 @@ The full contract // final byte (first byte of the next 32 bytes) v := byte(0, mload(add(sig, 96))) } - return (v, r, s); } @@ -421,7 +474,6 @@ The full contract returns (address) { (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig); - return ecrecover(message, v, r, s); } @@ -435,7 +487,7 @@ The full contract .. note:: The function ``splitSignature`` does not use all security checks. A real implementation should use a more rigorously tested library, - such as openzepplin's `version `_ of this code. + such as openzeppelin's `version `_ of this code. Verifying Payments ------------------ diff --git a/docs/examples/safe-remote.rst b/docs/examples/safe-remote.rst index a2651af238..dd2a86b142 100644 --- a/docs/examples/safe-remote.rst +++ b/docs/examples/safe-remote.rst @@ -93,11 +93,12 @@ you can use state machine-like constructs inside a contract. { emit Aborted(); state = State.Inactive; - // We use transfer here directly. It is + // We use call here directly. It is // reentrancy-safe, because it is the // last call in this function and we // already changed the state. - seller.transfer(address(this).balance); + (bool success, ) = seller.call{value: address(this).balance}(""); + require(success); } /// Confirm the purchase as buyer. @@ -124,11 +125,12 @@ you can use state machine-like constructs inside a contract. { emit ItemReceived(); // It is important to change the state first because - // otherwise, the contracts called using `send` below + // otherwise, the contracts called using `call` below // can call in again here. state = State.Release; - buyer.transfer(value); + (bool success, ) = buyer.call{value: value}(""); + require(success); } /// This function refunds the seller, i.e. @@ -140,10 +142,11 @@ you can use state machine-like constructs inside a contract. { emit SellerRefunded(); // It is important to change the state first because - // otherwise, the contracts called using `send` below + // otherwise, the contracts called using `call` below // can call in again here. state = State.Inactive; - seller.transfer(3 * value); + (bool success, ) = seller.call{value: 3 * value}(""); + require(success); } } diff --git a/docs/grammar.rst b/docs/grammar.rst index 92963e894f..d9c8ff2f3f 100644 --- a/docs/grammar.rst +++ b/docs/grammar.rst @@ -2,12 +2,12 @@ Gramática del Lenguaje ********************** -.. a4:autogrammar:: SolidityParser - :only-reachable-from: SolidityParser.sourceUnit +.. syntax:autogrammar:: SolidityParser.g4 + :root-rule: SolidityParser.sourceUnit :undocumented: :cc-to-dash: -.. a4:autogrammar:: SolidityLexer - :only-reachable-from: SolidityParser.sourceUnit +.. syntax:autogrammar:: SolidityLexer.g4 + :root-rule: SolidityParser.sourceUnit :fragments: :cc-to-dash: diff --git a/docs/grammar/SolidityLexer.g4 b/docs/grammar/SolidityLexer.g4 index 43648ceb5d..510b1f180a 100644 --- a/docs/grammar/SolidityLexer.g4 +++ b/docs/grammar/SolidityLexer.g4 @@ -14,6 +14,7 @@ Address: 'address'; Anonymous: 'anonymous'; As: 'as'; Assembly: 'assembly' -> pushMode(AssemblyBlockMode); +At: 'at'; // not a real keyword Bool: 'bool'; Break: 'break'; Bytes: 'bytes'; @@ -54,6 +55,7 @@ Indexed: 'indexed'; Interface: 'interface'; Internal: 'internal'; Is: 'is'; +Layout: 'layout'; // not a real keyword Library: 'library'; Mapping: 'mapping'; Memory: 'memory'; @@ -85,6 +87,7 @@ SignedIntegerType: Storage: 'storage'; String: 'string'; Struct: 'struct'; +Transient: 'transient'; // not a real keyword True: 'true'; Try: 'try'; Type: 'type'; @@ -297,7 +300,7 @@ YulHex: 'hex'; YulEVMBuiltin: 'stop' | 'add' | 'sub' | 'mul' | 'div' | 'sdiv' | 'mod' | 'smod' | 'exp' | 'not' | 'lt' | 'gt' | 'slt' | 'sgt' | 'eq' | 'iszero' | 'and' | 'or' | 'xor' | 'byte' - | 'shl' | 'shr' | 'sar' | 'addmod' | 'mulmod' | 'signextend' | 'keccak256' + | 'shl' | 'shr' | 'sar' | 'clz' | 'addmod' | 'mulmod' | 'signextend' | 'keccak256' | 'pop' | 'mload' | 'mstore' | 'mstore8' | 'sload' | 'sstore' | 'tload' | 'tstore'| 'msize' | 'gas' | 'address' | 'balance' | 'selfbalance' | 'caller' | 'callvalue' | 'calldataload' | 'calldatasize' | 'calldatacopy' | 'extcodesize' | 'extcodecopy' | 'returndatasize' diff --git a/docs/grammar/SolidityParser.g4 b/docs/grammar/SolidityParser.g4 index c46cefd2fa..5ad422913e 100644 --- a/docs/grammar/SolidityParser.g4 +++ b/docs/grammar/SolidityParser.g4 @@ -52,9 +52,14 @@ symbolAliases: LBrace aliases+=importAliases (Comma aliases+=importAliases)* RBr /** * Top-level definition of a contract. */ -contractDefinition: +contractDefinition +locals [boolean layoutSet=false, boolean inheritanceSet=false] +: Abstract? Contract name=identifier - inheritanceSpecifierList? + ( + {!$layoutSet}? Layout At expression {$layoutSet = true;} + | {!$inheritanceSet}? inheritanceSpecifierList {$inheritanceSet = true;} + )* LBrace contractBodyElement* RBrace; /** * Top-level definition of an interface. @@ -251,7 +256,7 @@ structMember: type=typeName name=identifier Semicolon; /** * Definition of an enum. Can occur at top-level within a source unit or within a contract, library or interface. */ -enumDefinition: Enum name=identifier LBrace enumValues+=identifier (Comma enumValues+=identifier)* RBrace; +enumDefinition: Enum name=identifier LBrace enumValues+=identifier (Comma enumValues+=identifier)* RBrace; /** * Definition of a user defined value type. Can occur at top-level within a source unit or within a contract, library or interface. */ @@ -262,7 +267,7 @@ userDefinedValueTypeDefinition: * The declaration of a state variable. */ stateVariableDeclaration -locals [boolean constantnessSet = false, boolean visibilitySet = false, boolean overrideSpecifierSet = false] +locals [boolean constantnessSet = false, boolean visibilitySet = false, boolean overrideSpecifierSet = false, boolean locationSet = false] : type=typeName ( @@ -272,6 +277,7 @@ locals [boolean constantnessSet = false, boolean visibilitySet = false, boolean | {!$constantnessSet}? Constant {$constantnessSet = true;} | {!$overrideSpecifierSet}? overrideSpecifier {$overrideSpecifierSet = true;} | {!$constantnessSet}? Immutable {$constantnessSet = true;} + | {!$locationSet}? Transient {$locationSet = true;} )* name=identifier (Assign initialValue=expression)? @@ -378,7 +384,7 @@ expression: expression LBrack index=expression? RBrack # IndexAccess | expression LBrack startIndex=expression? Colon endIndex=expression? RBrack # IndexRangeAccess | expression Period (identifier | Address) # MemberAccess - | expression LBrace (namedArgument (Comma namedArgument)*)? RBrace # FunctionCallOptions + | expression LBrace (namedArgument (Comma namedArgument)*) RBrace # FunctionCallOptions | expression callArgumentList # FunctionCall | Payable callArgumentList # PayableConversion | Type LParen typeName RParen # MetaType @@ -400,7 +406,7 @@ expression: | New typeName # NewExpr | tupleExpression # Tuple | inlineArrayExpression # InlineArray - | ( + | ( identifier | literal | literalWithSubDenomination @@ -419,7 +425,7 @@ inlineArrayExpression: LBrack (expression ( Comma expression)* ) RBrack; /** * Besides regular non-keyword Identifiers, some keywords like 'from' and 'error' can also be used as identifiers. */ -identifier: Identifier | From | Error | Revert | Global; +identifier: Identifier | From | Error | Revert | Global | Transient | Layout | At; literal: stringLiteral | numberLiteral | booleanLiteral | hexStringLiteral | unicodeStringLiteral; diff --git a/docs/index.rst b/docs/index.rst index cd915a69e5..9f3eddf064 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -4,7 +4,7 @@ Solidity Solidity is an object-oriented, high-level language for implementing smart contracts. Smart contracts are programs that govern the behavior of accounts within the Ethereum state. -Solidity is a `curly-bracket language `_ designed to target the Ethereum Virtual Machine (EVM). +Solidity is a `curly-bracket language `_ designed to target the Ethereum Virtual Machine (EVM). It is influenced by C++, Python, and JavaScript. You can find more details about which languages Solidity has been inspired by in the :doc:`language influences ` section. @@ -14,7 +14,7 @@ With Solidity, you can create contracts for uses such as voting, crowdfunding, b When deploying contracts, you should use the latest released version of Solidity. Apart from exceptional cases, only the latest version receives -`security fixes `_. +`security fixes `_. Furthermore, breaking changes, as well as new features, are introduced regularly. We currently use a 0.y.z version number `to indicate this fast pace of change `_. @@ -28,7 +28,7 @@ Ideas para mejorar Solidity o esta misma documentación son siempre bienvenidas, .. Nota:: You can download this documentation as PDF, HTML or Epub - by clicking on the versions flyout menu in the bottom-left corner and selecting the preferred download format. + by clicking on the versions flyout menu in the bottom-right corner and selecting the preferred download format. Para Comenzar ------------- @@ -85,6 +85,7 @@ Community contributors help translate this documentation into several languages. Note that they have varying degrees of completeness and up-to-dateness. The English version stands as a reference. +<<<<<<< HEAD Puede elegir entre distintos idiomas haciendo click en el menú desplegable que se encuentra en la esquina inferior izquierda y seleccionando su lenguaje preferido. * `Chino `_ @@ -98,6 +99,20 @@ Puede elegir entre distintos idiomas haciendo click en el menú desplegable que * `Turco `_ * `Alemán `_ * `Portugués `_ +======= +You can switch between languages by clicking on the flyout menu in the bottom-right corner +and selecting the preferred language. + +* `Chinese `_ +* `French `_ +* `Indonesian `_ +* `Japanese `_ +* `Korean `_ +* `Persian `_ +* `Russian `_ +* `Spanish `_ +* `Turkish `_ +>>>>>>> english/develop .. Note:: Recientemente se creó una nueva organización en GitHub y un flujo de trabajo para las traducciones, con el motivo de agilizar los esfuerzos de la comunidad. Por favor, consulte la `guía de traducción `_ para obtener información sobre cómo iniciar un nuevo idioma o contribuir en las traducciones de la comunidad. diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index fa0612ff64..2192aa4bf1 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -14,13 +14,12 @@ addition, patch-level releases with major release 0 (i.e. 0.x.y) will not contain breaking changes. That means code that compiles with version 0.x.y can be expected to compile with 0.x.z where z > y. -In addition to releases, we provide **nightly development builds** to make -it easy for developers to try out upcoming features and -provide early feedback. Note, however, that while the nightly builds are usually -very stable, they contain bleeding-edge code from the development branch and are -not guaranteed to be always working. Despite our best efforts, they might -contain undocumented and/or broken changes that will not become a part of an -actual release. They are not meant for production use. +In addition to releases, we provide **prereleases** and **nightly development builds** to make it +easy for developers to try out upcoming features and provide early feedback. +Note that such builds contain bleeding-edge code from the development branch and are not guaranteed +to be of the same quality as full releases. +Despite our best efforts, they might contain undocumented and/or broken changes that will not +become a part of an actual release. They are not meant for production use. Al desplegar contratos, debería usar el último lanzamiento de Solidity. Esto es porque regularmente se introducen cambios con rupturas, funcionalidades nuevas y @@ -33,8 +32,7 @@ Remix *Recomendamos Remix para pequeños contratos y para aprender Solidity rápidamente.* `Access Remix online `_, you do not need to install anything. -If you want to use it without connection to the Internet, go to -https://github.com/ethereum/remix-live/tree/gh-pages#readme and follow the instructions on that page. +If you want to use it without connection to the Internet, download Remix Desktop from `the releases page `_. Remix is also a convenient option for testing nightly builds without installing multiple Solidity versions. @@ -47,21 +45,30 @@ or if you require more compilation options. npm / Node.js ============= +<<<<<<< HEAD Use ``npm`` para instalar ``solcjs``, un compilador de Solidity, de una manera portable y sencilla. El programa `solcjs` tiene menos funcionalidades que el resto de maneras de compilar detalladas más abajo en esta página. La documentación del :ref:`compilador de línea de comandos` asume que está usando el compilador con funcionalidad completa, ``solc``. El uso de ``solcjs`` está documentado dentro de su propio `repositorio `_. +======= +Use ``npm`` for a convenient and portable way to install ``solcjs``, a Solidity compiler. The +``solcjs`` program has fewer features than the ways to access the compiler described +further down this page. The +:ref:`commandline-compiler` documentation assumes you are using +the full-featured compiler, ``solc``. The usage of ``solcjs`` is documented inside its own +`repository `_. +>>>>>>> english/develop Note: The solc-js project is derived from the C++ -`solc` by using Emscripten, which means that both use the same compiler source code. -`solc-js` can be used in JavaScript projects directly (such as Remix). +``solc`` by using Emscripten, which means that both use the same compiler source code. +``solc-js`` can be used in JavaScript projects directly (such as Remix). Please refer to the solc-js repository for instructions. .. code-block:: bash - npm install -g solc + npm install --global solc .. Nota:: @@ -73,7 +80,7 @@ Please refer to the solc-js repository for instructions. Docker ====== -Docker images of Solidity builds are available using the ``solc`` image from the ``ethereum`` organization. +Docker images of Solidity builds are available using the `solc `_ image from the argotorg organization on ghcr.io. Use the ``stable`` tag for the latest released version, and ``nightly`` for potentially unstable changes in the ``develop`` branch. The Docker image runs the compiler executable so that you can pass all compiler arguments to it. @@ -82,26 +89,26 @@ and runs it in a new container, passing the ``--help`` argument. .. code-block:: bash - docker run ethereum/solc:stable --help + docker run ghcr.io/argotorg/solc:stable --help -You can specify release build versions in the tag. For example: - -.. code-block:: bash - - docker run ethereum/solc:stable --help - -Note +.. note:: -Specific compiler versions are supported as the Docker image tag such as `ethereum/solc:0.8.23`. We will be passing the -`stable` tag here instead of specific version tag to ensure that users get the latest version by default and avoid the issue of -an out-of-date version. + Specific compiler versions are supported as the Docker image tag such as ``ghcr.io/argotorg/solc:0.8.23``. + We will be passing the ``stable`` tag here instead of specific version tag to ensure that users get + the latest version by default and avoid the issue of an out-of-date version. To use the Docker image to compile Solidity files on the host machine, mount a local folder for input and output, and specify the contract to compile. For example: .. code-block:: bash - docker run -v /local/path:/sources ethereum/solc:stable -o /sources/output --abi --bin /sources/Contract.sol + docker run \ + --volume "/tmp/some/local/path/:/sources/" \ + ghcr.io/argotorg/solc:stable \ + /sources/Contract.sol \ + --abi \ + --bin \ + --output-dir /sources/output/ You can also use the standard JSON interface (which is recommended when using the compiler with tooling). When using this interface, it is not necessary to mount any directories as long as the JSON input is @@ -110,47 +117,62 @@ self-contained (i.e. it does not refer to any external files that would have to .. code-block:: bash - docker run ethereum/solc:stable --standard-json < input.json > output.json + docker run ghcr.io/argotorg/solc:stable --standard-json < input.json > output.json Paquetes de Linux ================= +<<<<<<< HEAD Los binarios de Solidity están disponibles en `solidity/releases `_. También tenemos PPAs para Ubuntu, puede obtener la versión estable más reciente usando los siguientes comandos: +======= +We provide :ref:`standalone binaries ` of the compiler that should run on most +distributions without any additional installation steps. -.. code-block:: bash +Ubuntu packages for versions up to 0.8.30 are available in the +`ethereum/ethereum PPA `_. +However, we have discontinued this distribution method and future versions will not be added there. +>>>>>>> english/develop - sudo add-apt-repository ppa:ethereum/ethereum - sudo apt-get update - sudo apt-get install solc +Some Linux distributions provide their own packages. +These packages are not directly maintained by us but usually kept up-to-date by the respective +package maintainers. -La versión nocturna puede ser instalada usando estos comandos: +Unofficial, community-maintained scripts for building and installing the compiler are also +available for some distributions: -.. code-block:: bash +<<<<<<< HEAD +La versión nocturna puede ser instalada usando estos comandos: +======= +- Arch Linux / (AUR): +>>>>>>> english/develop - sudo add-apt-repository ppa:ethereum/ethereum - sudo add-apt-repository ppa:ethereum/ethereum-dev - sudo apt-get update - sudo apt-get install solc + - `solidity `_ (builds from source), + - `solidity-bin `_ (uses our standalone binaries). -Furthermore, some Linux distributions provide their own packages. These packages are not directly -maintained by us but usually kept up-to-date by the respective package maintainers. +- Nix: -For example, Arch Linux has packages for the latest development version as AUR packages: `solidity `_ -and `solidity-bin `_. + - `solc.nix `_ (builds from source). .. note:: - Please be aware that `AUR `_ packages - are user-produced content and unofficial packages. Exercise caution when using them. + Please be aware that these scripts are produced and maintained by users and not vetted in any + way by the distro maintainers. + Exercise caution when using them. +<<<<<<< HEAD También hay un `paquete para snap `_, sin embargo actualmente **no se le da mantenimiento**. Se puede instalar en todas las `distros de Linux respaldadas `_. Para instalar la última versión estable de solc: +======= +There is also a `snap package `_, however, it is **currently unmaintained**. +It is installable in all the `supported Linux distros `_. To +install the latest stable version of solc: +>>>>>>> english/develop .. code-block:: bash @@ -210,8 +232,15 @@ Instalar usando ``brew``: # ej. para instalar 0.4.8 brew install solidity.rb +<<<<<<< HEAD Binarios estáticos ================== +======= +.. _static-binaries: + +Static Binaries +=============== +>>>>>>> english/develop Mantenemos un repositorio con todos los binarios estáticos y versiones actuales del compilador para todas las plataformas respaldadas en `solc-bin`_. En esta locación también puede encontrar @@ -223,7 +252,7 @@ herramientas de terceros: - The content is mirrored to https://binaries.soliditylang.org where it can be easily downloaded over HTTPS without any authentication, rate limiting or the need to use git. -- Content is served with correct `Content-Type` headers and lenient CORS configuration so that it +- Content is served with correct ``Content-Type`` headers and lenient CORS configuration so that it can be directly loaded by tools running in the browser. - Binaries do not require installation or unpacking (exception for older Windows builds bundled with necessary DLLs). @@ -254,22 +283,26 @@ Each one includes a ``list.json`` file listing the available binaries. For examp "keccak256": "0x300330ecd127756b824aa13e843cb1f43c473cb22eaf3750d5fb9c99279af8c3", "sha256": "0x2b55ed5fec4d9625b6c7b3ab1abd2b7fb7dd2a9c68543bf0323db2c7e2d55af2", "urls": [ - "bzzr://16c5f09109c793db99fe35f037c6092b061bd39260ee7a677c8a97f18c955ab1", "dweb:/ipfs/QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS" ] } Esto significa que: +<<<<<<< HEAD - Puede encontrar el binario en el mismo directorio bajo el nombre `solc-emscripten-wasm32-v0.7.4+commit.3f05b770.js `_. +======= +- You can find the binary in the same directory under the name + `solc-emscripten-wasm32-v0.7.4+commit.3f05b770.js `_. +>>>>>>> english/develop Note that the file might be a symlink, and you will need to resolve it yourself if you are not using git to download it or your file system does not support symlinks. - The binary is also mirrored at https://binaries.soliditylang.org/emscripten-wasm32/solc-emscripten-wasm32-v0.7.4+commit.3f05b770.js. In this case git is not necessary and symlinks are resolved transparently, either by serving a copy of the file or returning a HTTP redirect. - The file is also available on IPFS at `QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS`_. -- The file might in future be available on Swarm at `16c5f09109c793db99fe35f037c6092b061bd39260ee7a677c8a97f18c955ab1`_. + Please, be aware that the order of items in the ``urls`` array is not predetermined or guaranteed and users should not rely on it. - You can verify the integrity of the binary by comparing its keccak256 hash to ``0x300330ecd127756b824aa13e843cb1f43c473cb22eaf3750d5fb9c99279af8c3``. The hash can be computed on the command-line using ``keccak256sum`` utility provided by `sha3sum`_ or `keccak256() function @@ -297,28 +330,56 @@ Esto significa que: ``soliditylang.org`` y esto también aplica para ``solc-bin``. Aunque recomendamos el nuevo dominio, el antiguo sigue siendo mantenido y se garantiza que apunte a la misma locación. +<<<<<<< HEAD .. Advertencia:: +======= + - Use ``emscripten-wasm32/`` (with a fallback to ``emscripten-asmjs/``) instead of ``bin/`` if + you want the best performance. Until version 0.6.1 we only provided asm.js binaries. + Starting with 0.6.2 we switched to `WebAssembly builds`_ with much better performance. We have + rebuilt the older versions for wasm but the original asm.js files remain in ``bin/``. + The new ones had to be placed in a separate directory to avoid name clashes. + - Use ``emscripten-asmjs/`` and ``emscripten-wasm32/`` instead of ``bin/`` and ``wasm/`` directories + if you want to be sure whether you are downloading a wasm or an asm.js binary. + - Use ``list.json`` instead of ``list.js`` and ``list.txt``. The JSON list format contains all + the information from the old ones and more. + +.. warning:: + - The solc-bin.ethereum.org domain is no longer supported. Going forward, + we recommend any tools which are still using it as the source of Solidity binaries + to switch to binaries.soliditylang.org. +>>>>>>> english/develop Los binarios también están disponbiles en https://ethereum.github.io/solc-bin/ pero esta página dejó de ser actualizada justo después del lanzamiento de la versión 0.7.2, no va a recibir nuevos releases ni compilaciones nocturnas para ninguna plataforma y no sirve la nueva estructura del directorio, incluyendo compilaciones no-emscripten. +<<<<<<< HEAD Si usted la está usando, por favor cambie a https://binaries.soliditylang.org, que es su reemplazo. Esto nos permite hacerle cambios al hosting subyacente de una manera transparente y minimizar disrupciones. Al contrario del dominio ``ethereum.github.io``, el cual no controlamos, ``binaries.soliditylang.org`` está garantizado para funcionar y mantener la misma estructura de URLs en el largo plazo. +======= + The binaries are also available at https://argotorg.github.io/solc-bin/ but this page + stopped being updated just after the release of version 0.7.2, will not receive any new releases + or nightly builds for any platform and does not serve the new directory structure, including + non-emscripten builds. + + If you are using it, please switch to https://binaries.soliditylang.org, which is a drop-in + replacement. This allows us to make changes to the underlying hosting in a transparent way and + minimize disruption. Unlike the ``argotorg.github.io`` domain, which we do not have any control + over, ``binaries.soliditylang.org`` is guaranteed to work and maintain the same URL structure + in the long-term. +>>>>>>> english/develop .. _IPFS: https://ipfs.io -.. _Swarm: https://swarm-gateways.net/bzz:/swarm.eth -.. _solc-bin: https://github.com/ethereum/solc-bin/ -.. _Solidity release page on GitHub: https://github.com/ethereum/solidity/releases +.. _solc-bin: https://github.com/argotorg/solc-bin/ +.. _Solidity release page on GitHub: https://github.com/argotorg/solidity/releases .. _sha3sum: https://github.com/maandree/sha3sum .. _función keccak256() de ethereumjs-util: https://github.com/ethereumjs/ethereumjs-util/blob/master/docs/modules/_hash_.md#const-keccak256 .. _WebAssembly builds: https://emscripten.org/docs/compiling/WebAssembly.html .. _QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS: https://gateway.ipfs.io/ipfs/QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS -.. _16c5f09109c793db99fe35f037c6092b061bd39260ee7a677c8a97f18c955ab1: https://swarm-gateways.net/bzz:/16c5f09109c793db99fe35f037c6092b061bd39260ee7a677c8a97f18c955ab1/ .. _compilando-del-codigo-fuente: @@ -329,6 +390,8 @@ Prerequisites - All Operating Systems A continuación las dependencias para todas las compilaciones de Solidity: +.. Note: This has to be kept in sync with `scripts/ci/install_and_check_minimum_requirements.sh`. + +-----------------------------------+-------------------------------------------------------+ | Software | Notas | +===================================+=======================================================+ @@ -336,7 +399,7 @@ A continuación las dependencias para todas las compilaciones de Solidity: | Windows, 3.13+ otherwise) | | +-----------------------------------+-------------------------------------------------------+ | `Boost`_ (version 1.77+ on | C++ libraries. | -| Windows, 1.65+ otherwise) | | +| Windows, 1.83+ otherwise) | | +-----------------------------------+-------------------------------------------------------+ | `Git`_ | Software de línea de comandos para obtener código | | | fuente. | @@ -344,10 +407,12 @@ A continuación las dependencias para todas las compilaciones de Solidity: | `z3`_ (versión 4.8+, Opcional) | Para usar con SMT checker. | | `z3`_ (version 4.8.16+, Opcional) | Para usar con SMT checker. | +-----------------------------------+-------------------------------------------------------+ +<<<<<<< HEAD | `cvc4`_ (Opcional) | Para usar con SMT checker. | +-----------------------------------+-------------------------------------------------------+ +======= +>>>>>>> english/develop -.. _cvc4: https://cvc4.cs.stanford.edu/web/ .. _Git: https://git-scm.com/download .. _Boost: https://www.boost.org .. _CMake: https://cmake.org/download/ @@ -371,6 +436,19 @@ A continuación las dependencias para todas las compilaciones de Solidity: compilar con cualquier versión que satisfaga los requerimientos de la tabla de arriba. Si hace esto, sin embargo, recuerde pasar la opción ``--no-smt`` a ``scripts/tests.sh`` para saltar las pruebas SMT. +<<<<<<< HEAD +======= +.. note:: + By default the build is performed in *pedantic mode*, which enables extra warnings and tells the + compiler to treat all warnings as errors. + This forces developers to fix warnings as they arise, so they do not accumulate "to be fixed later". + If you are only interested in creating a release build and do not intend to modify the source code + to deal with such warnings, you can pass ``-DPEDANTIC=OFF`` option to CMake to disable this mode. + Doing this is not recommended for general use but may be necessary when using a toolchain we are + not testing with or trying to build an older version with newer tools. + If you encounter such warnings, please consider + `reporting them `_. +>>>>>>> english/develop Versiones Mínimas del Compilador ============================== @@ -388,7 +466,15 @@ Versiones Mínimas del Compilador `_. +<<<<<<< HEAD Los siguientes compiladores de C++ y sus versiones mínimas pueden compilar el código de Solidity: +======= +.. Note: Minimum versions for GCC and Clang are based on availability in Ubuntu 24.04. + +- `GCC `_, version 13.3+ +- `Clang `_, version 18.1.3+ +- `MSVC `_, version 2019+ +>>>>>>> english/develop - `GCC `_, versión 8+ - `Clang `_, versión 7+ @@ -462,7 +548,7 @@ Para clonar el código fuente ejecute el siguiente comando: .. code-block:: bash - git clone --recursive https://github.com/ethereum/solidity.git + git clone --recursive https://github.com/argotorg/solidity.git cd solidity If you want to help develop Solidity, @@ -478,7 +564,7 @@ you should fork Solidity and add your personal fork as a second remote: If you want to re-build a released Solidity compiler, then please use the source tarball on the GitHub release page: - https://github.com/ethereum/solidity/releases/download/v0.X.Y/solidity_0.X.Y.tar.gz + https://github.com/argotorg/solidity/releases/download/v0.X.Y/solidity_0.X.Y.tar.gz (not the "Source code" provided by GitHub). @@ -520,9 +606,15 @@ Y para Windows: cd build cmake -G "Visual Studio 16 2019" .. +<<<<<<< HEAD En caso de querer usar la versión de boost instalada por ``scripts\install_deps.ps1``, deberá pasar adicionalmente las banderas ``-DBoost_DIR="deps\boost\lib\cmake\Boost-*"`` y ``-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded`` como argumentos cuando corra ``cmake``. +======= +In case you want to use the version of boost installed by ``scripts\install_deps.ps1``, you will +additionally need to pass ``-DBoost_ROOT="deps/boost" -DBoost_INCLUDE_DIR="deps/boost/include"`` and ``-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded`` +as arguments to the call to ``cmake``. +>>>>>>> english/develop Esto debería crear un archivo **solidity.sln** en ese directorio. Al hacer doble click en ese archivo Visual Studio debería abrirse. Sugerimos compilar con la configuración @@ -543,9 +635,10 @@ Para ver las opciones de Cmake disponibles solo corra ``cmake .. -LH``. SMT Solvers ----------- -Solidity can be built against SMT solvers and will do so by default if -they are found in the system. Each solver can be disabled by a ``cmake`` option. +Solidity can optionally use SMT solvers, namely ``z3``, ``cvc5`` and ``Eldarica``, +but their presence is checked only at runtime, they are not needed for the build to succeed. +<<<<<<< HEAD *Nota: En algunos casos, esto también puede ser una solución alterna para compilaciones fallidas.* En la carpeta donde compile puede deshabilitarlos, ya que están habilitados por defecto: @@ -560,40 +653,75 @@ En la carpeta donde compile puede deshabilitarlos, ya que están habilitados por # deshabilita los solvers para CVC4 y Z3 cmake .. -DUSE_CVC4=OFF -DUSE_Z3=OFF +======= +.. note:: + + The emscripten builds require Z3 and will statically link against it instead. +>>>>>>> english/develop La Cadena de Versión en Detalle =============================== La cadena de versión de Solidity contiene cuatro partes: +<<<<<<< HEAD - el número de versión - la etiqueta de pre-release, generalmente fijada en ``develop.YYYY.MM.DD`` o ``nightly.YYYY.MM.DD`` - commit en el formato ``commit.GITHASH`` - la plataforma, que contiene un número arbitrario de elementos, e incluye detalles sobre la plataforma y el compilador +======= +- the version number +- pre-release tag, usually set to ``develop.YYYY.MM.DD``, ``pre.N`` or ``nightly.YYYY.MM.DD`` +- commit in the format of ``commit.GITHASH`` +- platform, which has an arbitrary number of items, containing details about the platform and compiler +>>>>>>> english/develop Si hay modificaciones locales, el commit tendrá el sufijo de ``.mod``. Estas partes se combinan según requerimientos de SemVer, donde la etiqueta de pre-release de Solidity equivale al pre-release de SemVer y el commit de Solidity y la plataforma combinados nos dan la metadata del compilado de SemVer. +<<<<<<< HEAD Un ejemplo de release: ``0.4.8+commit.60cc1668.Emscripten.clang``. Un ejemplo de pre-release: ``0.4.9-nightly.2017.1.17+commit.6ecb4aa3.Emscripten.clang`` +======= +Examples: + +- release: ``0.4.8+commit.60cc1668.Emscripten.clang`` +- pre-release: ``0.4.9-pre.3+commit.fb60450bc.Emscripten.clang`` +- nightly build: ``0.4.9-nightly.2017.1.17+commit.6ecb4aa3.Emscripten.clang`` +>>>>>>> english/develop Información Importante Sobre el Versionado ========================================== +<<<<<<< HEAD Después de que se hace un lanzamiento, se aumenta el número de versión de parche, porque asumimos que solo siguen cambios a nivel de parches. Cuando los cambios se fusionan, la versión debería ser aumentada de acuerdo a SemVer y a la severidad del cambio. Finalmente, un lanzamiento siempre se hace con la versión de la compilación nocturna vigente, pero sin el especificador de ``prerelease``. +======= +After a release is made, the patch version level is bumped, because we assume that only +patch level changes follow. When changes are merged, the version should be bumped according +to SemVer and the severity of the change. Finally, a release is always made with the version +of the current build, but without the ``prerelease`` specifier. +>>>>>>> english/develop Ejemplo: +<<<<<<< HEAD 1. Se hace el release de la versión 0.4.0. 2. La compilación nocturna tiene una versión de 0.4.1 de ahora en adelante. 3. Se introducen cambios sin rupturas --> no hay cambio en la versión. 4. Se introduce un cambio con rupturas --> la versión se aumenta a 0.5.0. 5. Se hace el release de la versión 0.5.0. - -This behavior works well with the :ref:`version pragma `. +======= +1. The 0.4.0 release is made. +2. Nightly builds and preerelases have a version of 0.4.1 from now on. +3. Non-breaking changes are introduced --> no change in version. +4. A breaking change is introduced --> version is bumped to 0.5.0. +5. The 0.5.0 release is made. +>>>>>>> english/develop + +This behavior works well with the :ref:`version pragma `. diff --git a/docs/internals/layout_in_storage.rst b/docs/internals/layout_in_storage.rst index 9f86a0bbd6..f09d6c5e17 100644 --- a/docs/internals/layout_in_storage.rst +++ b/docs/internals/layout_in_storage.rst @@ -1,5 +1,6 @@ -.. index:: storage, state variable, mapping +.. index:: storage, state variable, mapping, transient storage +<<<<<<< HEAD ************************************ Diseño de variables de estado en almacenamiento ************************************ @@ -13,6 +14,28 @@ se almacena de manera contigua elemento despues elemento que comienza con la pri que se almacena en ranura ``0``. Para cada variable, un tamaño en bytes se determina según su tipo. Varios, elementos contiguos que necesita menos que 32 bytes se empaquetan en una sola ranura de almacenamiento si es posible, de acuerdo con las siguientes reglas: +======= +********************************************************** +Layout of State Variables in Storage and Transient Storage +********************************************************** + +.. _storage-inplace-encoding: + +.. note:: + The rules described in this section apply for both storage and transient storage data locations. + The layouts are completely independent and don't interfere with each other's variable locations. + Thus storage and transient storage state variables can be safely interleaved without any side effects. + Only value types are supported for transient storage. + +State variables of contracts are stored in storage in a compact way such +that multiple values sometimes use the same storage slot. +Except for dynamically-sized arrays and mappings (see below), data is stored +contiguously item after item starting with the first state variable, +which is stored in slot ``0``. For each variable, +a size in bytes is determined according to its type. +Multiple, contiguous items that need less than 32 bytes are packed into a single +storage slot if possible, according to the following rules: +>>>>>>> english/develop - El primer elemento en una ranura de almacenamiento se almacena alineado en orden inferior. - Los tipos de valor se usa sólo tantos bytes como sean necesarios para almacenarlos. @@ -28,6 +51,110 @@ las variables de estado de diferentes contratos comparten la misma ranura de alm Los elementos de structs y arrays se almacenan uno después del otro, como si se dieran como valores individuales. +If a contract specifies a :ref:`custom storage layout`, the slots assigned +to static storage variables are shifted according the value defined as the layout base. +Locations of dynamic arrays and mappings are also indirectly affected by this due to shifting +of the static slots they are based on. +The custom layout is specified in the most derived contract and, following the order explained +above, starting from the most base-ward contract's variables, all storage slots are adjusted. + +In the following example, contract ``C`` inherits from contracts ``A`` and ``B`` and also +specifies a custom storage base slot. +The result is that all storage variable slots of the inheritance tree are adjusted according to +the value specified by ``C``. + +.. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity ^0.8.29; + + struct S { + int32 x; + bool y; + } + + contract A { + uint a; + uint128 transient b; + uint constant c = 10; + uint immutable d = 12; + } + + contract B { + uint8[] e; + mapping(uint => S) f; + uint16 g; + uint16 h; + bytes16 transient i; + S s; + int8 k; + } + + contract C is A, B layout at 42 { + bytes21 l; + uint8[10] m; + bytes5[8] n; + bytes5 o; + } + +In the example, the storage layout starts with the inherited +state variable ``a`` stored directly inside the base slot (slot ``42``). +Transient, constant and immutable variables are stored in separate +locations, and thus, ``b``, ``i``, ``c`` and ``d`` have no effect on the storage layout. +Then we get to the dynamic array ``e`` and mapping ``f``. +They both reserve a whole slot whose address will be used to :ref:`calculate` +the location where their data is actually stored. +The slot cannot be shared with any other variable, because the resulting addresses must be unique. +The next two variables, ``g`` and ``h``, need 2 bytes each and can be packed together into +slot ``45``, at offsets ``0`` and ``2`` respectively. +Since ``s`` is a struct, its two members are packed contiguously, each taking up 5 bytes. +Even though they both would still fit in slot ``45``, structs and arrays always start a new slot. +Therefore, ``s`` is placed in slot ``46`` and the next variable, ``k``, in slot ``47``. +Base contracts, on the other hand, can share slots with derived ones, so ``l`` does not require an new one. +Then variable ``m``, which is an array of 10 items, gets into slot ``48`` and takes up 10 bytes. +``n`` is an array as well, but due to the size of its items, cannot fill its first slot perfectly +and spills over to the next one. +Finally, variable ``o`` ends up in slot ``51``, even though it is of the same type as items of ``n``. +As explained before, variables after structs and arrays always start a new slot. + +Putting it all together, the storage and transient storage layouts of contract ``C`` can be illustrated as follows: + +- Storage: + :: + + 42 [aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] + 43 [eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee] + 44 [ffffffffffffffffffffffffffffffff] + 45 [ hhgg] + 46 [ yxxxx] + 47 [ lllllllllllllllllllllk] + 48 [ mmmmmmmmmm] + 49 [ nnnnnnnnnnnnnnnnnnnnnnnnnnnnnn] + 50 [ nnnnnnnnnn] + 51 [ ooooo] + +- Transient storage: + :: + + 00 [iiiiiiiiiiiiiiiibbbbbbbbbbbbbbbb] + +Note that the storage specifier affects ``A`` and ``B`` only as a part of ``C``'s inheritance hierarchy. +When deployed independently, their storage starts at ``0``: + +- Storage layout of ``A``: + :: + + 00 [aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa] + +- Storage layout of ``B``: + :: + + 00 [eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee] + 01 [ffffffffffffffffffffffffffffffff] + 02 [ hhgg] + 03 [ yxxxx] + 04 [ k] + .. warning:: Cuando se utilizan elementos de menos de 32 bytes, el uso de gas de su contrato puede ser mayor. Esto se debe a que EVM funciona con 32 bytes a la vez. Por lo tanto, si el elemento es más pequeño @@ -146,10 +273,17 @@ Salida JSON .. _storage-layout-top-level: +<<<<<<< HEAD El diseño de almacenamiento de un contrato se puede solicitar a través de :ref:`standard JSON interface `. La salida es un objeto JSON que contiene dos claves, ``storage`` y ``types``. El objeto ``storage`` es una matriz donde cada elemento tiene la siguiente forma: +======= +The storage (or transient storage) layout of a contract can be requested via +the :ref:`standard JSON interface `. The output is a JSON object containing two keys, +``storage`` and ``types``. The ``storage`` object is an array where each +element has the following form: +>>>>>>> english/develop .. code-block:: json @@ -211,14 +345,19 @@ mismo formato que el ``storage`` de nivel superior (consulte :ref:`above >>>>>> english/develop .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.4.0 <0.9.0; + pragma solidity ^0.8.28; contract A { struct S { uint128 a; @@ -228,15 +367,22 @@ contiene tipos de valor y referencía, tipos codificados empaquetados y tipos an } uint x; - uint y; + uint transient y; + uint w; + uint transient z; + S s; address addr; + address transient taddr; mapping(uint => mapping(address => bool)) map; uint[] array; string s1; bytes b1; } +Storage Layout +-------------- + .. code-block:: json { @@ -250,15 +396,15 @@ contiene tipos de valor y referencía, tipos codificados empaquetados y tipos an "type": "t_uint256" }, { - "astId": 17, + "astId": 19, "contract": "fileA:A", - "label": "y", + "label": "w", "offset": 0, "slot": "1", "type": "t_uint256" }, { - "astId": 20, + "astId": 24, "contract": "fileA:A", "label": "s", "offset": 0, @@ -266,7 +412,7 @@ contiene tipos de valor y referencía, tipos codificados empaquetados y tipos an "type": "t_struct(S)13_storage" }, { - "astId": 22, + "astId": 26, "contract": "fileA:A", "label": "addr", "offset": 0, @@ -274,7 +420,7 @@ contiene tipos de valor y referencía, tipos codificados empaquetados y tipos an "type": "t_address" }, { - "astId": 28, + "astId": 34, "contract": "fileA:A", "label": "map", "offset": 0, @@ -282,7 +428,7 @@ contiene tipos de valor y referencía, tipos codificados empaquetados y tipos an "type": "t_mapping(t_uint256,t_mapping(t_address,t_bool))" }, { - "astId": 31, + "astId": 37, "contract": "fileA:A", "label": "array", "offset": 0, @@ -290,7 +436,7 @@ contiene tipos de valor y referencía, tipos codificados empaquetados y tipos an "type": "t_array(t_uint256)dyn_storage" }, { - "astId": 33, + "astId": 39, "contract": "fileA:A", "label": "s1", "offset": 0, @@ -298,7 +444,7 @@ contiene tipos de valor y referencía, tipos codificados empaquetados y tipos an "type": "t_string_storage" }, { - "astId": 35, + "astId": 41, "contract": "fileA:A", "label": "b1", "offset": 0, @@ -404,3 +550,49 @@ contiene tipos de valor y referencía, tipos codificados empaquetados y tipos an } } } + +Transient Storage Layout +------------------------ + +.. code-block:: json + + { + "storage": [ + { + "astId": 17, + "contract": "fileA:A", + "label": "y", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 21, + "contract": "fileA:A", + "label": "z", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 28, + "contract": "fileA:A", + "label": "taddr", + "offset": 0, + "slot": "2", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } diff --git a/docs/internals/optimizer.rst b/docs/internals/optimizer.rst index 4588cb4835..8c737371c0 100644 --- a/docs/internals/optimizer.rst +++ b/docs/internals/optimizer.rst @@ -11,7 +11,7 @@ The Solidity compiler involves optimizations at three different levels (in order - Optimizing transformations on the Yul IR code. - Optimizations at the opcode level. -The opcode-based optimizer applies a set of `simplification rules `_ +The opcode-based optimizer applies a set of `simplification rules `_ to opcodes. It also combines equal code sets and removes unused code. The Yul-based optimizer is much more powerful, because it can work across function @@ -46,7 +46,7 @@ for a stand-alone Yul mode. enabled by default and can only be turned off via the :ref:`Standard JSON `. .. note:: - An empty optimizer sequence is accepted even without ``--optimize`` in order to fully disable + An empty optimizer sequence, i.e ``:``, is accepted even without ``--optimize`` in order to fully disable the user-supplied portion of the Yul :ref:`optimizer sequence `, as by default, even when the optimizer is not turned on, the :ref:`unused pruner ` step will be run. @@ -295,11 +295,11 @@ backtracking. All components of the Yul-based optimizer module are explained below. The following transformation steps are the main components: -- SSA Transform -- Common Subexpression Eliminator -- Expression Simplifier -- Unused Assign Eliminator -- Full Inliner +- SSATransform +- CommonSubexpressionEliminator +- ExpressionSimplifier +- UnusedAssignEliminator +- FullInliner .. _optimizer-steps: @@ -313,7 +313,7 @@ on the individual steps and their sequence below. Abbreviation Full name ============ =============================== ``f`` :ref:`block-flattener` -``l`` :ref:`circular-reference-pruner` +``l`` :ref:`circular-references-pruner` ``c`` :ref:`common-subexpression-eliminator` ``C`` :ref:`conditional-simplifier` ``U`` :ref:`conditional-unsimplifier` @@ -336,8 +336,8 @@ Abbreviation Full name ``L`` :ref:`load-resolver` ``M`` :ref:`loop-invariant-code-motion` ``m`` :ref:`rematerialiser` -``V`` :ref:`SSA-reverser` -``a`` :ref:`SSA-transform` +``V`` :ref:`ssa-reverser` +``a`` :ref:`ssa-transform` ``t`` :ref:`structural-simplifier` ``r`` :ref:`unused-assign-eliminator` ``p`` :ref:`unused-function-parameter-pruner` @@ -416,7 +416,7 @@ and functions can be optimized in isolation without having to traverse the AST c FunctionGrouper ^^^^^^^^^^^^^^^ -The function grouper has to be applied after the disambiguator and the function hoister. +The function grouper has to be applied after the Disambiguator and the FunctionHoister. Its effect is that all topmost elements that are not function definitions are moved into a single block which is the first statement of the root block. @@ -429,14 +429,14 @@ After this step, a program has the following normal form: 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. -The benefit of this stage is that we always know where the list of function begins. +The benefit of this stage is that we always know where the list of functions begins. .. _for-loop-condition-into-body: ForLoopConditionIntoBody ^^^^^^^^^^^^^^^^^^^^^^^^ -This transformation moves the loop-iteration condition of a for-loop into loop body. +This transformation moves the loop-iteration condition of a ``for`` loop into loop body. We need this transformation because :ref:`expression-splitter` will not apply to iteration condition expressions (the ``C`` in the following example). @@ -455,7 +455,7 @@ is transformed to Body... } -This transformation can also be useful when paired with ``LoopInvariantCodeMotion``, since +This transformation can also be useful when paired with LoopInvariantCodeMotion, since invariants in the loop-invariant conditions can then be taken outside the loop. .. _for-loop-init-rewriter: @@ -463,7 +463,7 @@ invariants in the loop-invariant conditions can then be taken outside the loop. ForLoopInitRewriter ^^^^^^^^^^^^^^^^^^^ -This transformation moves the initialization part of a for-loop to before +This transformation moves the initialization part of a ``for`` loop to before the loop: .. code-block:: text @@ -482,7 +482,7 @@ is transformed to } This eases the rest of the optimization process because we can ignore -the complicated scoping rules of the for loop initialization block. +the complicated scoping rules of the ``for`` loop initialization block. .. _var-decl-initializer: @@ -600,7 +600,7 @@ and it is also easier to perform function call inlining. Furthermore, it is simp to replace individual parts of expressions or re-organize the "expression tree". The drawback is that such code is much harder to read for humans. -.. _SSA-transform: +.. _ssa-transform: SSATransform ^^^^^^^^^^^^ @@ -645,19 +645,19 @@ are not modified) perform the following transforms: Furthermore, always record the current value of ``i`` used for ``a`` and replace each reference to ``a`` by ``a_i``. The current value mapping is cleared for a variable ``a`` at the end of each block -in which it was assigned to and at the end of the for loop init block if it is assigned -inside the for loop body or post block. +in which it was assigned to and at the end of the ``for`` loop init block if it is assigned +inside the ``for`` loop body or post block. If a variable's value is cleared according to the rule above and the variable is declared outside the block, a new SSA variable will be created at the location where control flow joins, this includes the beginning of loop post/body block and the location right after -If/Switch/ForLoop/Block statement. +``if``/``switch``/``for``/block statement. -After this stage, the Unused Assign Eliminator is recommended to remove the unnecessary +After this stage, the UnusedAssignEliminator is recommended to remove the unnecessary intermediate assignments. -This stage provides best results if the Expression Splitter and the Common Subexpression Eliminator +This stage provides best results if the ExpressionSplitter and the CommonSubexpressionEliminator are run right before it, because then it does not generate excessive amounts of variables. -On the other hand, the Common Subexpression Eliminator could be more efficient if run after the +On the other hand, the CommonSubexpressionEliminator could be more efficient if run after the SSA transform. .. _unused-assign-eliminator: @@ -691,7 +691,7 @@ The SSA transform converts this snippet to the following: sstore(a_3, 1) } -The Unused Assign Eliminator removes all the three assignments to ``a``, because +The UnusedAssignEliminator removes all the three assignments to ``a``, because the value of ``a`` is not used and thus turn this snippet into strict SSA form: @@ -716,7 +716,7 @@ mapping from assignment statements to the three states value will be used later by a reference to the variable. When an assignment is visited, it is added to the mapping in the "undecided" state -(see remark about for loops below) and every other assignment to the same variable +(see remark about ``for`` loops below) and every other assignment to the same variable that is still in the "undecided" state is changed to "unused". When a variable is referenced, the state of any assignment to that variable still in the "undecided" state is changed to "used". @@ -731,7 +731,7 @@ Conflicting values are resolved in the following way: - "unused", "used" -> "used" - "undecided", "used" -> "used" -For for-loops, the condition, body and post-part are visited twice, taking +For ``for`` loops, the condition, body and post-part are visited twice, taking the joining control-flow at the condition into account. In other words, we create three control flow paths: Zero runs of the loop, one run and two runs and then combine them at the end. @@ -757,13 +757,13 @@ and thus .. code-block:: none - max(s, f(s), f(f(s))) = max(s, f(s), f(f(s)), f(f(f(s))), ...). + max(s, f(s), f(f(s))) = max(s, f(s), f(f(s)), f(f(f(s))), ...) In summary, running the loop at most twice is enough because there are only three different states. -For switch statements that have a "default"-case, there is no control-flow -part that skips the switch. +For ``switch`` statements that have a default case, there is no control-flow +part that skips the ``switch``. When a variable goes out of scope, all statements still in the "undecided" state are changed to "unused", unless the variable is the return @@ -793,7 +793,7 @@ The following parts make an expression non-movable: DataflowAnalyzer ^^^^^^^^^^^^^^^^ -The Dataflow Analyzer is not an optimizer step itself but is used as a tool +The DataflowAnalyzer is not an optimizer step itself but is used as a tool by other components. While traversing the AST, it tracks the current value of each variable, as long as that value is a movable expression. It records the variables that are part of the expression @@ -804,7 +804,7 @@ of the currently stored expression for ``b``. At control-flow joins, knowledge about variables is cleared if they have or would be assigned in any of the control-flow paths. For instance, upon entering a -for loop, all variables are cleared that will be assigned during the +``for`` loop, all variables are cleared that will be assigned during the body or the post block. Expression-Scale Simplifications @@ -818,7 +818,7 @@ and hopefully simpler expressions. CommonSubexpressionEliminator ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -This step uses the Dataflow Analyzer and replaces subexpressions that +This step uses the DataflowAnalyzer and replaces subexpressions that syntactically match the current value of a variable by a reference to that variable. This is an equivalence transform because such subexpressions have to be movable. @@ -828,24 +828,24 @@ current value if the value is an identifier. The combination of the two rules above allow to compute a local value numbering, which means that if two variables have the same -value, one of them will always be unused. The Unused Pruner or the -Unused Assign Eliminator will then be able to fully eliminate such +value, one of them will always be unused. The UnusedPruner or the +UnusedAssignEliminator will then be able to fully eliminate such variables. -This step is especially efficient if the expression splitter is run +This step is especially efficient if the ExpressionSplitter is run before. If the code is in pseudo-SSA form, the values of variables are available for a longer time and thus we have a higher chance of expressions to be replaceable. -The expression simplifier will be able to perform better replacements -if the common subexpression eliminator was run right before it. +The ExpressionSimplifier will be able to perform better replacements +if the CommonSubexpressionEliminator was run right before it. .. _expression-simplifier: ExpressionSimplifier ^^^^^^^^^^^^^^^^^^^^ -The ExpressionSimplifier uses the Dataflow Analyzer and makes use +The ExpressionSimplifier uses the DataflowAnalyzer and makes use of a list of equivalence transforms on expressions like ``X + 0 -> X`` to simplify the code. @@ -857,7 +857,7 @@ even when the code is in pseudo-SSA form. Some of the patterns like ``X - X -> 0`` can only be applied as long as the expression ``X`` is movable, because otherwise it would remove its potential side-effects. Since variable references are always movable, even if their current -value might not be, the Expression Simplifier is again more powerful +value might not be, the ExpressionSimplifier is again more powerful in split or pseudo-SSA form. .. _literal-rematerialiser: @@ -877,12 +877,12 @@ currently stored in storage resp. memory, if known. Works best if the code is in SSA form. -Prerequisite: Disambiguator, ForLoopInitRewriter. +Prerequisites: Disambiguator, ForLoopInitRewriter. Statement-Scale Simplifications ------------------------------- -.. _circular-reference-pruner: +.. _circular-references-pruner: CircularReferencesPruner ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -895,7 +895,7 @@ neither externally referenced nor referenced from the outermost context. ConditionalSimplifier ^^^^^^^^^^^^^^^^^^^^^ -The Conditional Simplifier inserts assignments to condition variables if the value can be determined +The ConditionalSimplifier inserts assignments to condition variables if the value can be determined from the control-flow. Destroys SSA form. @@ -906,12 +906,12 @@ we cannot assign a specific value. Current features: -- switch cases: insert " := " -- after if statement with terminating control-flow, insert " := 0" +- ``switch`` cases: insert `` := `` +- after ``if`` statement with terminating control-flow, insert `` := 0`` Future features: -- allow replacements by "1" +- allow replacements by ``1`` - take termination of user-defined functions into account Works best with SSA form and if dead code removal has run before. @@ -923,7 +923,7 @@ Prerequisite: Disambiguator. ConditionalUnsimplifier ^^^^^^^^^^^^^^^^^^^^^^^ -Reverse of Conditional Simplifier. +Reverse of ConditionalSimplifier. .. _control-flow-simplifier: @@ -932,14 +932,14 @@ ControlFlowSimplifier Simplifies several control-flow structures: -- replace if with empty body with pop(condition) -- remove empty default switch case -- remove empty switch case if no default case exists -- replace switch with no cases with pop(expression) -- turn switch with single case into if -- replace switch with only default case with pop(expression) and body -- replace switch with const expr with matching case body -- replace ``for`` with terminating control flow and without other break/continue by ``if`` +- replace ``if`` with empty body with ``pop(condition)`` +- remove empty default ``switch`` case +- remove empty ``switch`` case if no default case exists +- replace ``switch`` with no cases with ``pop(expression)`` +- turn ``switch`` with single case into ``if`` +- replace ``switch`` with only default case with ``pop(expression)`` and body +- replace ``switch`` with const expr with matching case body +- replace ``for`` with terminating control flow and without other ``break``/``continue`` by ``if`` - remove ``leave`` at the end of a function. None of these operations depend on the data flow. The StructuralSimplifier @@ -949,6 +949,7 @@ The ControlFlowSimplifier does record the presence or absence of ``break`` and ``continue`` statements during its traversal. Prerequisite: Disambiguator, FunctionHoister, ForLoopInitRewriter. + Important: Introduces EVM opcodes and thus can only be used on EVM code for now. .. _dead-code-eliminator: @@ -959,15 +960,16 @@ DeadCodeEliminator This optimization stage removes unreachable code. Unreachable code is any code within a block which is preceded by a -leave, return, invalid, break, continue, selfdestruct, revert or by a call to a user-defined function that recurses infinitely. +``leave``, ``return``, ``invalid``, ``break``, ``continue``, ``selfdestruct``, ``revert`` or by +a call to a user-defined function that recurses infinitely. Function definitions are retained as they might be called by earlier code and thus are considered reachable. -Because variables declared in a for loop's init block have their scope extended to the loop body, +Because variables declared in a ``for`` loop's init block have their scope extended to the loop body, we require ForLoopInitRewriter to run before this step. -Prerequisite: ForLoopInitRewriter, Function Hoister, Function Grouper +Prerequisites: ForLoopInitRewriter, FunctionHoister, FunctionGrouper. .. _equal-store-eliminator: @@ -978,12 +980,12 @@ This steps removes ``mstore(k, v)`` and ``sstore(k, v)`` calls if there was a previous call to ``mstore(k, v)`` / ``sstore(k, v)``, no other store in between and the values of ``k`` and ``v`` did not change. -This simple step is effective if run after the SSA transform and the -Common Subexpression Eliminator, because SSA will make sure that the variables -will not change and the Common Subexpression Eliminator re-uses exactly the same +This simple step is effective if run after the SSATransform and the +CommonSubexpressionEliminator, because SSA will make sure that the variables +will not change and the CommonSubexpressionEliminator reuses exactly the same variable if the value is known to be the same. -Prerequisites: Disambiguator, ForLoopInitRewriter +Prerequisites: Disambiguator, ForLoopInitRewriter. .. _unused-pruner: @@ -992,8 +994,8 @@ UnusedPruner This step removes the definitions of all functions that are never referenced. -It also removes the declaration of variables that are never referenced. -If the declaration assigns a value that is not movable, the expression is retained, +It also removes declarations of variables that are never referenced. +If a declaration assigns a value that is not movable, the expression is retained, but its value is discarded. All movable expression statements (expressions that are not assigned) are removed. @@ -1006,22 +1008,22 @@ StructuralSimplifier This is a general step that performs various kinds of simplifications on a structural level: -- replace if statement with empty body by ``pop(condition)`` -- replace if statement with true condition by its body -- remove if statement with false condition -- turn switch with single case into if -- replace switch with only default case by ``pop(expression)`` and body -- replace switch with literal expression by matching case body -- replace for loop with false condition by its initialization part +- replace ``if`` statement with empty body by ``pop(condition)`` +- replace ``if`` statement with true condition by its body +- remove ``if`` statement with false condition +- turn ``switch`` with single case into ``if`` +- replace ``switch`` with only default case by ``pop(expression)`` and body +- replace ``switch`` with literal expression by matching case body +- replace ``for`` loop with false condition by its initialization part -This component uses the Dataflow Analyzer. +This component uses the DataflowAnalyzer. .. _block-flattener: BlockFlattener ^^^^^^^^^^^^^^ -This stage eliminates nested blocks by inserting the statement in the +This stage eliminates nested blocks by inserting the statements in the inner block at the appropriate place in the outer block. It depends on the FunctionGrouper and does not flatten the outermost block to keep the form produced by the FunctionGrouper. @@ -1062,10 +1064,9 @@ This optimization moves movable SSA variable declarations outside the loop. Only statements at the top level in a loop's body or post block are considered, i.e variable declarations inside conditional branches will not be moved out of the loop. -Requirements: +ExpressionSplitter and SSATransform should be run upfront to obtain better results. -- The Disambiguator, ForLoopInitRewriter and FunctionHoister must be run upfront. -- Expression splitter and SSA transform should be run upfront to obtain better result. +Prerequisites: Disambiguator, ForLoopInitRewriter, FunctionHoister. Function-Level Optimizations @@ -1092,7 +1093,7 @@ function ``f_1`` that takes only one argument, i.e., Other optimization steps will be able to make more simplifications to the function. The optimization step is mainly useful for functions that would not be inlined. -Prerequisites: Disambiguator, FunctionHoister +Prerequisites: Disambiguator, FunctionHoister. LiteralRematerialiser is recommended as a prerequisite, even though it's not required for correctness. @@ -1122,7 +1123,7 @@ The step LiteralRematerialiser is not required for correctness. It helps deal wi ``function f(x) -> y { revert(y, y} }`` where the literal ``y`` will be replaced by its value ``0``, allowing us to rewrite the function. -.. index:: ! unused store eliminator +.. index:: ! UnusedStoreEliminator .. _unused-store-eliminator: UnusedStoreEliminator @@ -1149,7 +1150,7 @@ For example, the following code sstore(c, 3) } -will be transformed into the code below after the Unused Store Eliminator step is run +will be transformed into the code below after the UnusedStoreEliminator step is run .. code-block:: yul @@ -1159,7 +1160,7 @@ will be transformed into the code below after the Unused Store Eliminator step i sstore(c, 3) } -For memory store operations, things are generally simpler, at least in the outermost yul block as all such +For memory store operations, things are generally simpler, at least in the outermost Yul block as all such statements will be removed if they are never read from in any code path. At function analysis level, however, the approach is similar to ``sstore``, as we do not know whether the memory location will be read once we leave the function's scope, so the statement will be removed only if all code paths lead to a memory overwrite. @@ -1177,8 +1178,8 @@ If two functions are syntactically equivalent, while allowing variable renaming but not any re-ordering, then any reference to one of the functions is replaced by the other. -The actual removal of the function is performed by the Unused Pruner. +The actual removal of the function is performed by the UnusedPruner. Function Inlining ----------------- @@ -1199,7 +1200,7 @@ Furthermore, for all parameters, all of the following need to be true: - The argument is movable. - The parameter is either referenced less than twice in the function body, or the argument is rather cheap - ("cost" of at most 1, like a constant up to 0xff). + ("cost" of at most 1, like a constant up to ``0xff``). Example: The function to be inlined has the form of ``function f(...) -> r { r := E }`` where ``E`` is an expression that does not reference ``r`` and all arguments in the function call are movable expressions. @@ -1255,7 +1256,7 @@ variables as much as possible. ExpressionJoiner ^^^^^^^^^^^^^^^^ -This is the opposite operation of the expression splitter. It turns a sequence of +This is the opposite operation of the ExpressionSplitter. It turns a sequence of variable declarations that have exactly one reference into a complex expression. This stage fully preserves the order of function calls and opcode executions. It does not make use of any information concerning the commutativity of the opcodes; @@ -1275,21 +1276,21 @@ Because of that, the snippet ``let x := add(0, 2) let y := mul(x, 3)`` is transformed to ``let y := mul(add(0, 2), 3)``, even though the ``add`` opcode would be executed after the evaluation of the literal ``3``. -.. _SSA-reverser: +.. _ssa-reverser: SSAReverser ^^^^^^^^^^^ -This is a tiny step that helps in reversing the effects of the SSA transform -if it is combined with the Common Subexpression Eliminator and the -Unused Pruner. +This is a tiny step that helps in reversing the effects of the SSATransform +if it is combined with the CommonSubexpressionEliminator and the +UnusedPruner. The SSA form we generate is detrimental to code generation because it produces many local variables. It would -be better to just re-use existing variables with assignments instead of +be better to just reuse existing variables with assignments instead of fresh variable declarations. -The SSA transform rewrites +The SSATransform rewrites .. code-block:: yul @@ -1307,7 +1308,7 @@ to a := a_2 The problem is that instead of ``a``, the variable ``a_1`` is used -whenever ``a`` was referenced. The SSA transform changes statements +whenever ``a`` was referenced. The SSATransform changes statements of this form by just swapping out the declaration and the assignment. The above snippet is turned into @@ -1320,10 +1321,10 @@ snippet is turned into let a_2 := a This is a very simple equivalence transform, but when we now run the -Common Subexpression Eliminator, it will replace all occurrences of ``a_1`` -by ``a`` (until ``a`` is re-assigned). The Unused Pruner will then +CommonSubexpressionEliminator, it will replace all occurrences of ``a_1`` +by ``a`` (until ``a`` is re-assigned). The UnusedPruner will then eliminate the variable ``a_1`` altogether and thus fully reverse the -SSA transform. +SSATransform. .. _stack-compressor: @@ -1354,9 +1355,9 @@ is comparatively cheap to evaluate. Furthermore, it is only semantically equival the value of the expression did not change between the point of assignment and the point of use. The main benefit of this stage is that it can save stack slots if it leads to a variable being eliminated completely (see below), but it can also -save a DUP opcode on the EVM if the expression is very cheap. +save a ``DUP`` opcode on the EVM if the expression is very cheap. -The Rematerialiser uses the Dataflow Analyzer to track the current values of variables, +The Rematerialiser uses the DataflowAnalyzer to track the current values of variables, which are always movable. If the value is very cheap or the variable was explicitly requested to be eliminated, the variable reference is replaced by its current value. diff --git a/docs/internals/variable_cleanup.rst b/docs/internals/variable_cleanup.rst index 7790aa3cc1..87b5718378 100644 --- a/docs/internals/variable_cleanup.rst +++ b/docs/internals/variable_cleanup.rst @@ -120,7 +120,7 @@ Positivo 0000...0000 0000 0001 0000...0000 0000 0010 .... - 0000...0000 1111 1111 + 0000...0000 0111 1111 El compilador ``signextend`` el bit de signo, que es 1 para valores negativos y 0 para valores positivos, sobrescribiendo los bits superiores: diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index 15c2ebe2fc..bc495af9f6 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -84,8 +84,9 @@ registering with a username and password, all you need is an Ethereum keypair. .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 - pragma solidity ^0.8.4; + pragma solidity ^0.8.26; + // This will only compile via IR contract Coin { // The keyword "public" makes variables // accessible from other contracts @@ -117,12 +118,7 @@ registering with a username and password, all you need is an Ethereum keypair. // Sends an amount of existing coins // from any caller to an address function send(address receiver, uint amount) public { - if (amount > balances[msg.sender]) - revert InsufficientBalance({ - requested: amount, - available: balances[msg.sender] - }); - + require(amount <= balances[msg.sender], InsufficientBalance(amount, balances[msg.sender])); balances[msg.sender] -= amount; balances[receiver] += amount; emit Sent(msg.sender, receiver, amount); @@ -134,7 +130,7 @@ This contract introduces some new concepts, let us go through them one by one. The line ``address public minter;`` declares a state variable of type :ref:`address
    `. The ``address`` type is a 160-bit value that does not allow any arithmetic operations. It is suitable for storing addresses of contracts, or a hash of the public half -of a keypair belonging to :ref:`external accounts`. +of a keypair belonging to :ref:`externally-owned accounts`. The keyword ``public`` automatically generates a function that allows you to access the current value of the state variable from outside of the contract. Without this keyword, other contracts have no way to access the variable. @@ -224,8 +220,8 @@ than the maximum value of ``uint`` (``2**256 - 1``). This is also true for the s :ref:`Errors ` allow you to provide more information to the caller about why a condition or operation failed. Errors are used together with the :ref:`revert statement `. The ``revert`` statement unconditionally -aborts and reverts all changes similar to the ``require`` function, but it also -allows you to provide the name of an error and additional data which will be supplied to the caller +aborts and reverts all changes, much like the :ref:`require function `. +Both approaches allow you to provide the name of an error and additional data which will be supplied to the caller (and eventually to the front-end application or block explorer) so that a failure can more easily be debugged or reacted upon. @@ -341,11 +337,11 @@ Accounts ======== There are two kinds of accounts in Ethereum which share the same -address space: **External accounts** that are controlled by +address space: **Externally-owned accounts** that are controlled by public-private key pairs (i.e. humans) and **contract accounts** which are controlled by the code stored together with the account. -The address of an external account is determined from +The address of an externally-owned account is determined from the public key while the address of a contract is determined at the time the contract is created (it is derived from the creator address and the number @@ -418,13 +414,15 @@ In case of an exception that reverts changes, already used up gas is not refunde Since EVM executors can choose to include a transaction or not, transaction senders cannot abuse the system by setting a low gas price. -.. index:: ! storage, ! memory, ! stack +.. index:: ! storage, ! memory, ! stack, ! transient storage -Storage, Memory and the Stack -============================= +.. _locations: + +Storage, Transient Storage, Memory and the Stack +================================================ -The Ethereum Virtual Machine has three areas where it can store data: -storage, memory and the stack. +The Ethereum Virtual Machine has different areas where it can store data with the most +prominent being storage, transient storage, memory and the stack. Each account has a data area called **storage**, which is persistent between function calls and transactions. @@ -435,7 +433,15 @@ you should minimize what you store in persistent storage to what the contract ne Store data like derived calculations, caching, and aggregates outside of the contract. A contract can neither read nor write to any storage apart from its own. -The second data area is called **memory**, of which a contract obtains +Similar to storage, there is another data area called **transient storage**, +where the main difference is that it is reset at the end of each transaction. +The values stored in this data location persist only across function calls originating +from the first call of the transaction. +When the transaction ends, the transient storage is reset and the values stored there +become unavailable to calls in subsequent transactions. +Despite this, the cost of reading and writing to transient storage is significantly lower than for storage. + +The third data area is called **memory**, of which a contract obtains a freshly cleared instance for each message call. Memory is linear and can be addressed at byte level, but reads are limited to a width of 256 bits, while writes can be either 8 bits or 256 bits wide. Memory is expanded by a word (256-bit), when @@ -457,6 +463,31 @@ in order to get deeper access to the stack, but it is not possible to just access arbitrary elements deeper in the stack without first removing the top of the stack. +Calldata, Returndata and Code +============================= + +There are also other data areas which are not as apparent as those discussed previously. +However, they are routinely used during the execution of smart contract transactions. + +The calldata region is the data sent to a transaction as part of a smart contract transaction. +For example, when creating a contract, calldata would be the constructor code of the new contract. +The parameters of external functions are always initially stored in calldata in an ABI-encoded form +and only then decoded into the location specified in their declaration. +If declared as ``memory``, the compiler will eagerly decode them into memory at the beginning of the function, +while marking them as ``calldata`` means that this will be done lazily, only when accessed. +Value types and ``storage`` pointers are decoded directly onto the stack. + +The returndata is the way a smart contract can return a value after a call. +In general, external Solidity functions use the ``return`` keyword to ABI-encode values into the returndata area. + +The code is the region where the EVM instructions of a smart contract are stored. +Code is the bytes read, interpreted, and executed by the EVM during smart contract execution. +Instruction data stored in the code is persistent as part of a contract account state field. +Immutable and constant variables are stored in the code region. +All references to immutables are replaced with the values assigned to them. +A similar process is performed for constants which have their expressions inlined +in the places where they are referenced in the smart contract code. + .. index:: ! instruction Instruction Set @@ -505,6 +536,7 @@ operations, loops should be preferred over recursive calls. Furthermore, only 63/64th of the gas can be forwarded in a message call, which causes a depth limit of a little less than 1000 in practice. +.. _delegatecall: .. index:: delegatecall, library Delegatecall and Libraries @@ -562,9 +594,23 @@ idea, but it is potentially dangerous, as if someone sends Ether to removed contracts, the Ether is forever lost. .. warning:: - From version 0.8.18 and up, the use of ``selfdestruct`` in both Solidity and Yul will trigger a - deprecation warning, since the ``SELFDESTRUCT`` opcode will eventually undergo breaking changes in behavior - as stated in `EIP-6049 `_. + From ``EVM >= Cancun`` onwards, ``selfdestruct`` will **only** send all Ether in the account to the given recipient and not destroy the contract. + However, when ``selfdestruct`` is called in the same transaction that creates the contract calling it, + the behaviour of ``selfdestruct`` before Cancun hardfork (i.e., ``EVM <= Shanghai``) is preserved and will destroy the current contract, + deleting any data, including storage keys, code and the account itself. + See `EIP-6780 `_ for more details. + + The new behaviour is the result of a network-wide change that affects all contracts present on + the Ethereum mainnet and testnets. + It is important to note that this change is dependent on the EVM version of the chain on which + the contract is deployed. + The ``--evm-version`` setting used when compiling the contract has no bearing on it. + + Also, note that the ``selfdestruct`` opcode has been deprecated in Solidity version 0.8.18, + as recommended by `EIP-6049 `_. + The deprecation is still in effect and the compiler will still emit warnings on its use. + Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. + Future changes to the EVM might further reduce the functionality of the opcode. .. warning:: Even if a contract is removed by ``selfdestruct``, it is still part of the @@ -588,7 +634,7 @@ Precompiled Contracts ===================== There is a small set of contract addresses that are special: -The address range between ``1`` and (including) ``8`` contains +The address range between ``1`` and (including) ``0x0a`` contains "precompiled contracts" that can be called as any other contract but their behavior (and their gas consumption) is not defined by EVM code stored at that address (they do not contain code) diff --git a/docs/ir-breaking-changes.rst b/docs/ir-breaking-changes.rst index 4917cfc715..30c1c61116 100644 --- a/docs/ir-breaking-changes.rst +++ b/docs/ir-breaking-changes.rst @@ -258,6 +258,8 @@ hiding new and different behavior in existing code. Internals ========= +.. _internal-function-pointers-in-ir: + Internal function pointers -------------------------- @@ -276,6 +278,12 @@ The ID ``0`` is reserved for uninitialized function pointers which then cause a In the old code generator, internal function pointers are initialized with a special function that always causes a panic. This causes a storage write at construction time for internal function pointers in storage. +.. note:: + The compiler is free to omit internal functions that are never explicitly referenced by name. + As a consequence, assigning to a function type variable in inline assembly does not guarantee + that the assigned value will be included in the internal dispatch. + The function must also be explicitly referenced elsewhere in the code. + Cleanup ------- diff --git a/docs/language-influences.rst b/docs/language-influences.rst index 838c266e1a..a5b5c89442 100644 --- a/docs/language-influences.rst +++ b/docs/language-influences.rst @@ -2,6 +2,11 @@ Influencias del Lenguaje ######################## +<<<<<<< HEAD +======= +Solidity is a `curly-bracket language `_ +that has been influenced and inspired by several well-known programming languages. +>>>>>>> english/develop Solidity es un `lenguaje de llaves `_, que ha sido influenciado e inspirado por varios lenguajes de programación conocidos. diff --git a/docs/layout-of-source-files.rst b/docs/layout-of-source-files.rst index d295659f74..6e86bdfdc3 100644 --- a/docs/layout-of-source-files.rst +++ b/docs/layout-of-source-files.rst @@ -69,9 +69,30 @@ ABI Coder Pragma Al usar ``pragma abicoder v1`` o ``pragma abicoder v2`` puedes seleccionar entre las dos implementaciones del codificador y decodificador ABI. +<<<<<<< HEAD El nuevo codificador ABI (v2) es capaz de codificar y decodificar arrays y structs anidadas arbitrariamente. Además de admitir más tipos, implica una validación y comprobaciones de seguridad más amplias, lo que puede dar como resultado mayores costes de gas, pero también una mayor seguridad. Se considera no experimental a partir de Solidity 0.6.0 y está habilitado de forma predeterminada iniciando con Solidity 0.8.0. El antiguo codificador ABI todavía puede ser seleccionado usando ``pragma abicoder v1;``. El conjunto de tipos soportados por el nuevo codificador es un superset de aquellos soportados por el viejo. Los contratos que lo usan pueden interactuar con aquellos que no lo usan sin limitaciones. Lo opuesto es posible solo siempre y cuando el contrato no-``abicoder v2`` no intente hacer llamadas que requerirían decodificador tipos solamente soportados por el nuevo codificador. El compilador puede detectar esto y emitirá un error. Simplemente con activar ``abicoder v2`` para su contrato es suficiente para hacer que estos errores desaparezcan. +======= +The new ABI coder (v2) is able to encode and decode arbitrarily nested +arrays and structs. Apart from supporting more types, it involves more extensive +validation and safety checks, which may result in higher gas costs, but also heightened +security. +It is considered non-experimental as of Solidity 0.6.0 and it is enabled by default starting +with Solidity 0.8.0. The old ABI coder can still be selected using ``pragma abicoder v1;``. + +.. warning:: + The ABI coder v1 is deprecated and scheduled for removal. + Use ABI coder v2 instead. + +The set of types supported by the new encoder is a strict superset of +the ones supported by the old one. Contracts that use it can interact with ones +that do not without limitations. The reverse is possible only as long as the +non-``abicoder v2`` contract does not try to make calls that would require +decoding types only supported by the new encoder. The compiler can detect this +and will issue an error. Simply enabling ``abicoder v2`` for your contract is +enough to make the error go away. +>>>>>>> english/develop .. note:: @@ -102,10 +123,24 @@ Debido a que el codificador ABI v2 ya no es considerado experimental, puede ser SMTChecker ~~~~~~~~~~ +<<<<<<< HEAD Este componente tiene que ser habilitado cuando el compilador de Solidity es construido y, por lo tanto, no está disponible en todos los binarios Solidity. Las :ref:`instrucciones de construcción` explican cómo activar esta opción. Está activado para todas los lanzamientos PPA de Ubuntu en la mayoría de las versiones, pero no para las imágenes de Docker, los binarios de Windows o los binarios de Linux construidos estáticamente. Se puede activar para solc-js a través de `smtCallback `_ si tiene un SMT solver instalado localmente y ejecute solc-js por medio de node (no a través del navegador). Si usa ``pragma experimental SMTChecker;``, entonces obtiene :ref:`avisos de seguridad` adicionales los cuales se obtienen al consultar un SMT solver. El componente todavía no soporta todas las características del lenguaje Solidity y probablemente genera muchas advertencias. En caso de que señale características no soportadas, el análisis pudiese no ser enteramente sólido. +======= +If you use ``pragma experimental SMTChecker;``, then you get additional +:ref:`safety warnings` which are obtained by querying an +SMT solver. +The component does not yet support all features of the Solidity language and +likely outputs many warnings. In case it reports unsupported features, the +analysis may not be fully sound. +>>>>>>> english/develop + +.. note:: + + The ``SMTChecker`` pragma is deprecated and will be removed. + To enable SMTChecker, simply select :ref:`select an engine` when invoking the compiler. .. index:: source file, ! import, module, source unit diff --git a/docs/metadata.rst b/docs/metadata.rst index ede16a73fd..b4a8d7cfc6 100644 --- a/docs/metadata.rst +++ b/docs/metadata.rst @@ -124,60 +124,41 @@ explanatory purposes. "version": 1 // NatSpec version } }, - // Required: Compiler settings. Reflects the settings in the JSON input during compilation. - // Check the documentation of standard JSON input's "settings" field + // Required: Compiler settings. + // Reflects the settings in the JSON input during compilation, except: + // - Different format: "libraries" field + // - Added field in metadata.settings: "compilationTarget" + // - Not in metadata.settings: "stopAfter", "debug.debugInfo", "outputSelection" + // See the standard JSON input's "settings" field docs for the rest. "settings": { // Required for Solidity: File path and the name of the contract or library this - // metadata is created for. + // metadata is created for. This field is not present in the standard JSON input settings. "compilationTarget": { "myDirectory/myFile.sol": "MyContract" }, - // Required for Solidity. - "evmVersion": "london", + // Optional (false if omitted): Indicates whether experimental mode has been enabled. + // Always matches the value of the `experimental` flag in CBOR metadata. + // Note that experimental mode being enabled does not necessarily mean that any + // experimental features were actually used, or if they were, that those features + // affected the bytecode. + "experimental": true, // Required for Solidity: Addresses for libraries used. + // Note that metadata has a different format for "libraries" field than the standard JSON input. + // metadata format = { "MyLib.sol:MyLib": "0x123123..." } + // standard JSON input format = { "MyLib.sol": { "MyLib": "0x123123..." } } "libraries": { - "MyLib": "0x123123..." + "MyLib.sol:MyLib": "0x123123..." }, - "metadata": { - // Reflects the setting used in the input json, defaults to "true" - "appendCBOR": true, - // Reflects the setting used in the input json, defaults to "ipfs" - "bytecodeHash": "ipfs", - // Reflects the setting used in the input json, defaults to "false" - "useLiteralContent": true - }, - // Optional: Optimizer settings. The fields "enabled" and "runs" are deprecated - // and are only given for backward-compatibility. - "optimizer": { - "details": { - "constantOptimizer": false, - "cse": false, - "deduplicate": false, - // inliner defaults to "false" - "inliner": false, - // jumpdestRemover defaults to "true" - "jumpdestRemover": true, - "orderLiterals": false, - // peephole defaults to "true" - "peephole": true, - "yul": true, - // Optional: Only present if "yul" is "true" - "yulDetails": { - "optimizerSteps": "dhfoDgvulfnTUtnIf...", - "stackAllocation": false - } - }, - "enabled": true, - "runs": 500 - }, - // Required for Solidity: Sorted list of import remappings. - "remappings": [ ":g=/dir" ] + // ... + // ... + // ... + // The rest of the fields and their defaults same as in std JSON input. }, // Required: Compilation source files/source units, keys are file paths "sources": { - "destructible": { + "settable": { // Required (unless "url" is used): literal contents of the source file - "content": "contract destructible is owned { function destroy() { if (msg.sender == owner) selfdestruct(owner); } }", + "content": "contract settable is owned { uint256 private x = 0; function set(uint256 _x) public { if (msg.sender == owner) x = _x; } }", // Required: keccak256 hash of the source file "keccak256": "0x234..." }, @@ -222,12 +203,14 @@ Below are all the possible fields: .. code-block:: javascript { + // Present if "bytecodeHash" was "ipfs" in compiler settings "ipfs": "", - // If "bytecodeHash" was "bzzr1" in compiler settings not "ipfs" but "bzzr1" + // Present if "bytecodeHash" was "bzzr1" in compiler settings "bzzr1": "", // Previous versions were using "bzzr0" instead of "bzzr1" "bzzr0": "", - // If any experimental features that affect code generation are used + // Present if experimental mode has been enabled either via "--experimental" flag or + // "settings.experimental" option in Standard JSON "experimental": true, "solc": "" } diff --git a/docs/natspec-format.rst b/docs/natspec-format.rst index 5a6da5c9bb..e98054fa83 100644 --- a/docs/natspec-format.rst +++ b/docs/natspec-format.rst @@ -35,9 +35,16 @@ herramientas de verificación. Ejemplo de Documentación ===================== +<<<<<<< HEAD La documentación se inserta encima de cada ``contrato``, ``interfaz``, ``biblioteca``, ``función`` y ``evento`` usando el formato de notación Doxygen. Una variable de estado ``pública`` es equivalente a una ``función`` para los propósitos de NatSpec. +======= +Documentation is inserted above each ``contract``, ``interface``, ``library``, +``function``, ``enum``, ``enum`` value and ``event`` using the Doxygen notation format. +A ``public`` state variable is equivalent to a ``function`` +for the purposes of NatSpec. +>>>>>>> english/develop - Para Solidity puede optar ``///`` para comentarios de una línea o múltiples líneas, o ``/**`` y finalizar con ``*/``. @@ -67,12 +74,22 @@ El siguiente ejemplo muestra un contrato y una función usando todas las etiquet /// @dev Todas las llamadas a funciones están actualmente implementadas sin efectos secundarios /// @custom:experimental Este es un contrato experimental. contract Tree { +<<<<<<< HEAD /// @notice Calcula la edad del árbol en años, redondeado hacia arriba, para los árboles vivos. /// @dev El algoritmo de Alexandr N. Tetearing podría incrementar la precisión /// @param rings El número de anillos de una muestra dendrocronológica /// @return Edad en años, redondeado hacia arriba para años parciales function age(uint256 rings) external virtual pure returns (uint256) { return rings + 1; +======= + /// @notice Calculate tree age in years, rounded up, for live trees + /// @dev The Alexandr N. Tetearing algorithm could increase precision + /// @param rings The number of rings from dendrochronological sample + /// @return Age in years, rounded up for partial years + /// @return Name of the tree + function age(uint256 rings) external virtual pure returns (uint256, string memory) { + return (rings + 1, "tree"); +>>>>>>> english/develop } /// @notice Retorna la cantidad de hojas que tiene el árbol. @@ -89,8 +106,8 @@ El siguiente ejemplo muestra un contrato y una función usando todas las etiquet } contract KumquatTree is Tree, Plant { - function age(uint256 rings) external override pure returns (uint256) { - return rings + 2; + function age(uint256 rings) external override pure returns (uint256, string memory) { + return (rings + 2, "Kumquat"); } /// Retorna la cantidad de hojas que tiene este tipo específico de árbol @@ -113,13 +130,13 @@ la misma manera como si fuese etiquetado con ``@notice``. =============== ====================================================================================== ============================= Etiqueta Contexto =============== ====================================================================================== ============================= -``@title`` A title that should describe the contract/interface contract, library, interface, struct, enum -``@author`` The name of the author contract, library, interface, struct, enum -``@notice`` Explain to an end user what this does contract, library, interface, function, public state variable, event, struct, enum -``@dev`` Explain to a developer any extra details contract, library, interface, function, state variable, event, struct, enum -``@param`` Documents a parameter just like in Doxygen (must be followed by parameter name) function, event -``@return`` Documents the return variables of a contract's function function, public state variable -``@inheritdoc`` Copies all missing tags from the base function (must be followed by the contract name) function, public state variable +``@title`` A title that should describe the contract/interface contract, library, interface, struct, enum, enum values +``@author`` The name of the author contract, library, interface, struct, enum, enum values +``@notice`` Explain to an end user what this does contract, library, interface, function, public state variable, event, struct, enum, enum values error +``@dev`` Explain to a developer any extra details contract, library, interface, function, state variable, event, struct, enum, enum values, error +``@param`` Documents a parameter just like in Doxygen (must be followed by parameter name) function, event, enum values, error +``@return`` Documents the return variables of a contract's function function, enum, enum values, public state variable +``@inheritdoc`` Copies all missing tags from the base function (must be followed by the contract name) function, enum, enum values, public state variable ``@custom:...`` Custom tag, semantics is application-defined everywhere =============== ====================================================================================== ============================= @@ -193,8 +210,13 @@ Y la salida está abajo. Documentación del Usuario ------------------ +<<<<<<< HEAD La documentación de arriba producirá el siguiente archivo JSON de la documentación del usuario como salida: +======= +The above documentation will produce the following user documentation +JSON file as output for the ``Tree`` contract: +>>>>>>> english/develop .. code-block:: json @@ -205,7 +227,15 @@ de la documentación del usuario como salida: { "age(uint256)" : { +<<<<<<< HEAD "notice" : "Calcula la edad del árbol en años, redondeado hacia arriba, para los árboles vivos" +======= + "notice" : "Calculate tree age in years, rounded up, for live trees" + }, + "leaves()" : + { + "notice" : "Returns the amount of leaves the tree has." +>>>>>>> english/develop } }, "notice" : "Puede usar este contrato solo para la simulación más básica" @@ -239,7 +269,18 @@ también se debería producir y debería asemejarse a esto: { "rings" : "El número de anillos de una muestra dendrocronológica" }, +<<<<<<< HEAD "return" : "Edad en años, redondeado hacia arriba para años parciales" +======= + "returns" : { + "_0" : "Age in years, rounded up for partial years", + "_1" : "Name of the tree" + } + }, + "leaves()" : + { + "details" : "Returns only a fixed number." +>>>>>>> english/develop } }, "title" : "Un simulador para árboles" diff --git a/docs/path-resolution.rst b/docs/path-resolution.rst index ff4930bc9d..2339a3624c 100644 --- a/docs/path-resolution.rst +++ b/docs/path-resolution.rst @@ -39,7 +39,7 @@ compilation fails. By default, the command-line compiler provides the *Host Filesystem Loader* - a rudimentary callback that interprets a source unit name as a path in the local filesystem. This callback can be disabled using the ``--no-import-callback`` command-line option. -The `JavaScript interface `_ does not provide any by default, +The `JavaScript interface `_ does not provide any by default, but one can be provided by the user. This mechanism can be used to obtain source code from locations other than the local filesystem (which may not even be accessible, e.g. when the compiler is running in a browser). @@ -83,7 +83,7 @@ The initial content of the VFS depends on how you invoke the compiler: #. **Standard JSON** When using the :ref:`Standard JSON ` API (via either the `JavaScript interface - `_ or the ``--standard-json`` command-line option) + `_ or the ``--standard-json`` command-line option) you provide input in JSON format, containing, among other things, the content of all your source files: @@ -629,9 +629,9 @@ Here are the detailed rules governing the behavior of remappings: #. **At most one remapping is applied to a single import.** - - If multiple remappings match the same source unit name, the one with the longest matching - prefix is chosen. - - If prefixes are identical, the one specified last wins. + - If multiple remappings match the same source unit name, the one with the longest matching context is chosen. + - If contexts are identical, the one with the longest matching prefix is chosen. + - If contexts and prefixes are identical, the one specified last wins. - Remappings do not work on other remappings. For example ``a=b b=c c=d`` will not result in ``a`` being remapped to ``d``. diff --git a/docs/requirements.txt b/docs/requirements.txt index b1b21a8691..8f5f27ffff 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,10 +1,12 @@ # Older versions of sphinx-rtd-theme do not work with never docutils but have a bug in the dependency # which could result in it being installed anyway and the style (especially bullet points) being broken. # See https://github.com/readthedocs/sphinx_rtd_theme/issues/1115 -sphinx_rtd_theme>=0.5.2 +# theme >=3.0.0 removes the display_version option in favor of version_selector and language_selector +# Use rtd theme version that supports sphinx>=8.0 +sphinx_rtd_theme>=3.0.0 pygments-lexer-solidity>=0.7.0 -sphinx-a4doc>=1.6.0 +sphinx-syntax>=1.0.1 -# Sphinx 2.1.0 is the oldest version that accepts a lexer class in add_lexer() -sphinx>=2.1.0, <6.0 +# Sphinx version constraints for sphinx-syntax compatibility +sphinx>=8.0.0, <9.0.0 diff --git a/docs/resources.rst b/docs/resources.rst index 712f587589..3d55708484 100644 --- a/docs/resources.rst +++ b/docs/resources.rst @@ -5,6 +5,7 @@ Recursos Recursos Generales ================= +<<<<<<< HEAD * `Portal del Desarrollador Ethereum.org `_ * `Ethereum StackExchange `_ * `Portal de Solidity `_ @@ -15,10 +16,24 @@ Recursos Generales * `Awesome Solidity `_ * `Solidity by Example `_ * `Traducciones de la documentación por la comunidad de Solidity `_ +======= +* `Ethereum.org Developers page `_ +* `Ethereum StackExchange `_ +* `Solidity website `_ +* `Solidity changelog `_ +* `Solidity codebase on GitHub `_ +* `Solidity language users chat `_ +* `Solidity compiler developers chat `_ +* `awesome-solidity `_ +* `Solidity by Example `_ +* `Solidity documentation community translations `_ +* `Solidity and Smart Contract Glossary `_ +>>>>>>> english/develop Ambientes de Desarrollo Integrado (Ethereum) ============================================== +<<<<<<< HEAD * `Brownie `_ Framework de desarrollo y testing basado en Python para contratos inteligentes dirigido a la Máquina Virtual de Ethereum. @@ -41,6 +56,36 @@ Ambientes de Desarrollo Integrado (Ethereum) Framework para el desarollo en Ethereum. Integraciones de Editores +======= +* `Ape `_ + A Python-based web3 development tool for compiling, testing, and interacting with smart contracts. + +* `Brownie `_ + A Python-based development and testing framework for smart contracts targeting the Ethereum Virtual Machine. + 💡 Note: As per the official docs, Brownie is no longer actively maintained. + Future releases may come sporadically - or never at all. + Check out Ape Framework (first in list) for all your python Ethereum development needs. + +* `Dapp `_ + Tool for building, testing and deploying smart contracts from the command-line. + +* `Foundry `_ + Fast, portable and modular toolkit for Ethereum application development written in Rust. + +* `Hardhat `_ + Ethereum development environment with local Ethereum network, debugging features and plugin ecosystem. + +* `Remix `_ + Browser-based IDE with integrated compiler and Solidity runtime environment without server-side components. + +* `Truffle `_ + Ethereum development framework. + 💡 Note: Consensys announced the sunset of Truffle on September 21, 2023. + Current users may check out the migration path and available product support `here. + `_ + +Editor Integrations +>>>>>>> english/develop =================== * Emacs @@ -71,8 +116,12 @@ Integraciones de Editores * Visual Studio Code (VS Code) + * `Aderyn Visual Studio Code extension `_ + Solidity Smart contract analyzer designed to help find vulnerabilities. It supports projects built with Hardhat, Foundry, or any custom framework. + * `Ethereum Remix Visual Studio Code extension `_ Ethereum Remix extension pack for VS Code + 💡 Note: As per the official repository, this extension has been removed from the VSCODE marketplace and will be replaced by a dedicated stand-alone desktop application. * `Solidity Visual Studio Code extension, by Juan Blanco `_ Plugin de Solidity para Microsoft Visual Studio Code que incluye resaltado de sintaxis y el compilador de Solidity. @@ -84,7 +133,14 @@ Integraciones de Editores Agrega sintaxis céntrica de seguridad y resaltado semántico para Visual Studio Code. * `Truffle for VS Code `_ +<<<<<<< HEAD Desarrollo, debug y deploy de contratos inteligentes en Ethereum y cadenas de bloques compatibles con EVM. +======= + Build, debug and deploy smart contracts on Ethereum and EVM-compatible blockchains. + 💡 Note: This extension has built-in support for the Truffle Suite which is being sunset. + For information on ongoing support, migration options and FAQs, visit the `Consensys blog. + `_ +>>>>>>> english/develop Herramientas para Solidity ============== @@ -95,17 +151,35 @@ Herramientas para Solidity * `abi-to-sol `_ Herramienta para generar la fuente de interfaz de Solidity desde un ABI JSON dado. +<<<<<<< HEAD * `Doxity `_ Generador de documentación para Solidity. * `Ethlint `_ Linter para identificar y corregir asuntos de estilo y seguridad en Solidity. +======= +* `Aderyn `_ + Command Line Tool that helps find vulnerabilities in Solidity smart contracts. It supports projects built with Hardhat, Foundry, or any custom framework. + +* `Doxity `_ + Documentation Generator for Solidity. + +* `ethdebug `_ + A standard debugging data format for smart contracts on Ethereum-compatible networks. + +* `Ethlint `_ + Linter to identify and fix style and security issues in Solidity. +>>>>>>> english/develop * `evmdis `_ Desensamblador EVM que lleva a cabo análisis estático en el bytecode para proveer un nivel alto de abstracción que las operaciones EVM sin procesar. * `EVM Lab `_ +<<<<<<< HEAD Paquete abundante de herramientas para interactuar con el EVM. Incluye un VM, Etherchain API, y un mostrador con muestra de costo de gas. +======= + A collection of tools to interact with the EVM. The package includes a VM, Etherchain API, and a trace-viewer with gas cost display. +>>>>>>> english/develop * `hevm `_ Debugger EVM y motor de ejecución simbólica. @@ -113,8 +187,16 @@ Herramientas para Solidity * `leafleth `_ Un generador de documentación para contratos inteligentes de Solidity. +<<<<<<< HEAD * `Scaffold-ETH `_ Stack de desarollo en Ethereum forkeable enfocado en iteraciones rápidas de productos. +======= +* `Scaffold-ETH 2 `_ + Forkable Ethereum development stack focused on fast product iterations. +>>>>>>> english/develop + +* `Slippy `_ + A simple and powerful linter for Solidity. * `sol2uml `_ Generador de diagrama de clase Unified Modeling Language (UML) para contratos en Solidity. @@ -143,7 +225,14 @@ Herramientas para Solidity * `Universal Mutator `_ Una herramienta para generación de mutaciones, con reglas configurables y soporte para Solidity y Vyper. +<<<<<<< HEAD Parsers y Grammars de Terceros +======= +* `Wake `_ + A Python-based Solidity development and testing framework with built-in vulnerability detectors. + +Third-Party Solidity Parsers and Grammars +>>>>>>> english/develop ========================================= * `Solidity Parser for JavaScript `_ diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index 3d510d2819..464ad901d9 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -63,6 +63,7 @@ To give an example, the following code contains a bug (it is just a snippet and mapping(address => uint) shares; /// Withdraw your share. function withdraw() public { + // This will report a warning (deprecation) if (payable(msg.sender).send(shares[msg.sender])) shares[msg.sender] = 0; } @@ -74,7 +75,7 @@ Ether transfer can always include code execution, so the recipient could be a contract that calls back into ``withdraw``. This would let it get multiple refunds and, basically, retrieve all the Ether in the contract. In particular, the following contract will allow an attacker to refund multiple times -as it uses ``call`` which forwards all remaining gas by default: +as it uses ``call`` which does not limit the amount of gas that is forwarded by default: .. code-block:: solidity @@ -98,7 +99,7 @@ To avoid reentrancy, you can use the Checks-Effects-Interactions pattern as demo .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.6.0 <0.9.0; + pragma solidity >=0.6.2 <0.9.0; contract Fund { /// @dev Mapping of ether shares of the contract. @@ -107,7 +108,8 @@ To avoid reentrancy, you can use the Checks-Effects-Interactions pattern as demo function withdraw() public { uint share = shares[msg.sender]; shares[msg.sender] = 0; - payable(msg.sender).transfer(share); + (bool success, ) = payable(msg.sender).call{value: share}(""); + require(success); } } @@ -142,7 +144,7 @@ Please be explicit about such cases in the documentation of your contracts. Envío y Recepción de Ether =========================== -- Neither contracts nor "external accounts" are currently able to prevent someone from sending them Ether. +- Neither contracts nor "externally-owned accounts" are currently able to prevent someone from sending them Ether. Contracts can react on and reject a regular transfer, but there are ways to move Ether without creating a message call. One way is to simply "mine to" the contract address and the second way is using ``selfdestruct(x)``. @@ -156,8 +158,9 @@ Envío y Recepción de Ether (for example in the "details" section in Remix). - There is a way to forward more gas to the receiving contract using ``addr.call{value: x}("")``. - This is essentially the same as ``addr.transfer(x)``, only that it forwards all remaining gas - and opens up the ability for the recipient to perform more expensive actions + This is essentially the same as ``addr.transfer(x)``, only that it forwards all remaining gas, + subject to additional limits imposed by some EVM versions (such as the `63/64th rule `_ + introduced by ``tangerineWhistle``), and opens up the ability for the recipient to perform more expensive actions (and it returns a failure code instead of automatically propagating the error). This might include calling back into the sending contract or other state changes you might not have thought of. So it allows for great flexibility for honest users but also for malicious actors. @@ -251,6 +254,7 @@ Let's say you have a wallet contract like this: function transferTo(address payable dest, uint amount) public { // EL BUS ESTA JUSTO AQUÍ, usted debe usar msg.sender en lugar de tx.origin require(tx.origin == owner); + // This will report a warning (deprecation) dest.transfer(amount); } } @@ -360,7 +364,21 @@ and calling ``readMap(4, 128)`` returns 256 even without another call to ``write SI su información de ``mapping`` debe ser eliminada, considere usar una biblioteca similar a `iterable mapping `_, que le permite atravesar las claves y eliminar sus valores en el ``mapping`` apropiado. +<<<<<<< HEAD Detalles Menores +======= +Internal Function Pointers in Upgradeable Contracts +=================================================== + +Updating the code of your contract may :ref:`invalidate the values of variables of internal function +types`. +Consider such values ephemeral and avoid storing them in state variables. +If you do, you must ensure that they never persist across code updates and are never used by +other contracts having access to the same storage space as a result of a delegatecall or account +abstraction. + +Minor Details +>>>>>>> english/develop ============= - Types that do not occupy the full 32 bytes might contain "dirty higher order bits". diff --git a/docs/smtchecker.rst b/docs/smtchecker.rst index f8085b63de..4f1b49c8d0 100644 --- a/docs/smtchecker.rst +++ b/docs/smtchecker.rst @@ -263,7 +263,7 @@ A common type of properties in smart contracts are properties that involve the state of the contract. Multiple transactions might be needed to make an assertion fail for such a property. -As an example, consider a 2D grid where both axis have coordinates in the range (-2^128, 2^128 - 1). +As an example, consider a 2D grid where both axis have coordinates in the range (-2^127, 2^127 - 1). Let us place a robot at position (0, 0). The robot can only move diagonally, one step at a time, and cannot move outside the grid. The robot's state machine can be represented by the smart contract below. @@ -488,8 +488,8 @@ Proved Targets If there are any proved targets, the SMTChecker issues one warning per engine stating how many targets were proved. If the user wishes to see all the specific -proved targets, the CLI option ``--model-checker-show-proved`` and -the JSON option ``settings.modelChecker.showProved = true`` can be used. +proved targets, the CLI option ``--model-checker-show-proved-safe`` and +the JSON option ``settings.modelChecker.showProvedSafe = true`` can be used. Unproved Targets ================ @@ -822,20 +822,16 @@ which is primarily an SMT solver and makes `Spacer `_ which does both. The user can choose which solvers should be used, if available, via the CLI -option ``--model-checker-solvers {all,cvc4,eld,smtlib2,z3}`` or the JSON option +option ``--model-checker-solvers {all,cvc5,eld,smtlib2,z3}`` or the JSON option ``settings.modelChecker.solvers=[smtlib2,z3]``, where: -- ``cvc4`` is only available if the ``solc`` binary is compiled with it. Only BMC uses ``cvc4``. +- ``cvc5`` is used via its binary which must be installed in the system. Only BMC uses ``cvc5``. - ``eld`` is used via its binary which must be installed in the system. Only CHC uses ``eld``, and only if ``z3`` is not enabled. - ``smtlib2`` outputs SMT/Horn queries in the `smtlib2 `_ format. - These can be used together with the compiler's `callback mechanism `_ so that + These can be used together with the compiler's `callback mechanism `_ so that any solver binary from the system can be employed to synchronously return the results of the queries to the compiler. This can be used by both BMC and CHC depending on which solvers are called. -- ``z3`` is available - - - if ``solc`` is compiled with it; - - if a dynamic ``z3`` library of version >=4.8.x is installed in a Linux system (from Solidity 0.7.6); - - statically in ``soljson.js`` (from Solidity 0.6.9), that is, the JavaScript binary of the compiler. +- ``z3`` is available statically in ``soljson.js`` (from Solidity 0.6.9), that is, the JavaScript binary of the compiler. Otherwise it is used via its binary which must be installed in the system. .. note:: z3 version 4.8.16 broke ABI compatibility with previous versions and cannot @@ -849,7 +845,7 @@ concerned about this option. More advanced users might apply this option to try alternative solvers on more complex problems. Please note that certain combinations of chosen engine and solver will lead to -the SMTChecker doing nothing, for example choosing CHC and ``cvc4``. +the SMTChecker doing nothing, for example choosing CHC and ``cvc5``. ******************************* Abstraction and False Positives @@ -935,16 +931,16 @@ the arguments. +-----------------------------------+--------------------------------------+ |``addmod``, ``mulmod`` |Supported precisely. | +-----------------------------------+--------------------------------------+ -|``gasleft``, ``blockhash``, |Abstracted with UF. | -|``keccak256``, ``ecrecover`` | | -|``ripemd160`` | | +|``gasleft``, ``blobhash``, |Abstracted with UF. | +|``blockhash``, ``keccak256``, | | +|``ecrecover``, ``ripemd160`` | | +-----------------------------------+--------------------------------------+ |pure functions without |Abstracted with UF | |implementation (external or | | |complex) | | +-----------------------------------+--------------------------------------+ |external functions without |BMC: Erase state knowledge and assume | -|implementation |result is nondeterminisc. | +|implementation |result is nondeterministic. | | |CHC: Nondeterministic summary. | | |Try to infer invariants that hold | | |after the call returns. | diff --git a/docs/structure-of-a-contract.rst b/docs/structure-of-a-contract.rst index 4eb7fd94b7..67142a9180 100644 --- a/docs/structure-of-a-contract.rst +++ b/docs/structure-of-a-contract.rst @@ -21,7 +21,14 @@ el cual sirve para proveer un rápido resumen. Variables de Estado =============== +<<<<<<< HEAD Las variables de estado son variables cuyos valores se almacenan permanentemente en el almacenamiento del contrato. +======= +State variables are variables whose values are either permanently stored in contract +storage or, alternatively, temporarily stored in transient storage which is cleaned at +the end of each transaction. +See :ref:`data locations ` for more details. +>>>>>>> english/develop .. code-block:: solidity diff --git a/docs/style-guide.rst b/docs/style-guide.rst index 427ede5ee3..87e604124b 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -662,10 +662,11 @@ Yes: return balanceOf[from]; } - function shutdown() public onlyOwner { - selfdestruct(owner); + function increment(uint x) public pure onlyOwner returns (uint) { + return x + 1; } + No: .. code-block:: solidity @@ -674,8 +675,8 @@ No: return balanceOf[from]; } - function shutdown() onlyOwner public { - selfdestruct(owner); + function increment(uint x) onlyOwner public pure returns (uint) { + return x + 1; } For long function declarations, it is recommended to drop each argument onto diff --git a/docs/types/conversion.rst b/docs/types/conversion.rst index dafb336bd0..92f0e19dc3 100644 --- a/docs/types/conversion.rst +++ b/docs/types/conversion.rst @@ -174,15 +174,14 @@ converted to any fixed-size bytes type: bytes4 g = 0x0; // fine String literals and hex string literals can be implicitly converted to fixed-size byte arrays, -if their number of characters matches the size of the bytes type: +if their number of characters is less than or equal to the size of the bytes type: .. code-block:: solidity bytes2 a = hex"1234"; // fine bytes2 b = "xy"; // fine - bytes2 c = hex"12"; // not allowed - bytes2 d = hex"123"; // not allowed - bytes2 e = "x"; // not allowed + bytes2 c = hex"12"; // fine + bytes2 e = "x"; // fine bytes2 f = "xyz"; // not allowed .. index:: literal;address @@ -199,4 +198,4 @@ An ``address a`` can be converted explicitly to ``address payable`` via ``payabl .. note:: Prior to version 0.8.0, it was possible to explicitly convert from any integer type (of any size, signed or unsigned) to ``address`` or ``address payable``. - Starting with in 0.8.0 only conversion from ``uint160`` is allowed. \ No newline at end of file + Starting with 0.8.0 only conversion from ``uint160`` is allowed. diff --git a/docs/types/reference-types.rst b/docs/types/reference-types.rst index da40ef5dbe..c6bbb047d5 100644 --- a/docs/types/reference-types.rst +++ b/docs/types/reference-types.rst @@ -29,18 +29,32 @@ annotation, the "data location", about where it is stored. There are three data ``memory``, ``storage`` and ``calldata``. Calldata is a non-modifiable, non-persistent area where function arguments are stored, and behaves mostly like memory. +.. note:: + ``transient`` is not yet supported as a data location for reference types. + .. note:: If you can, try to use ``calldata`` as data location because it will avoid copies and also makes sure that the data cannot be modified. Arrays and structs with ``calldata`` data location can also be returned from functions, but it is not possible to allocate such types. +.. note:: + Arrays and structs with ``calldata`` location declared in a function body + or as its return parameters must be assigned before being used or returned. + There are certain cases in which non-trivial control flow is used and the compiler + can't properly detect the initialization. + A common workaround in such cases is to assign the affected variable to itself before + the correct initialization takes place. + .. note:: Prior to version 0.6.9 data location for reference-type arguments was limited to ``calldata`` in external functions, ``memory`` in public functions and either ``memory`` or ``storage`` in internal and private ones. Now ``memory`` and ``calldata`` are allowed in all functions regardless of their visibility. +.. note:: + Constructor parameters cannot use ``calldata`` as their data location. + .. 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 @@ -393,8 +407,7 @@ Array Members // Data location for all state variables is storage. bool[2][] pairsOfFlags; - // newPairs is stored in memory - the only possibility - // for public contract function arguments + // newPairs is stored in memory function setAllFlagPairs(bool[2][] memory newPairs) public { // assignment to a storage array performs a copy of ``newPairs`` and // replaces the complete array ``pairsOfFlags``. @@ -668,7 +681,7 @@ shown in the following example: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.6.0 <0.9.0; + pragma solidity >=0.6.2 <0.9.0; // Defines a new type with two fields. // Declaring a struct outside of a contract allows @@ -717,8 +730,8 @@ shown in the following example: return false; uint amount = c.amount; c.amount = 0; - c.beneficiary.transfer(amount); - return true; + (bool success, ) = c.beneficiary.call{value: amount}(""); + return success; } } diff --git a/docs/types/value-types.rst b/docs/types/value-types.rst index 12fcb0b171..035857d7ac 100644 --- a/docs/types/value-types.rst +++ b/docs/types/value-types.rst @@ -7,6 +7,12 @@ Value Types The following are called value types because their variables will always be passed by value, i.e. they are always copied when they are used as function arguments or in assignments. +Unlike :ref:`reference types `, value type declarations do not +specify a data location since they are small enough to be stored on the stack. +The only exception is :ref:`state variables `. +Those are by default located in storage, but can also be marked as +:ref:`transient `, :ref:`constant or immutable `. + .. index:: ! bool, ! true, ! false Booleans @@ -198,7 +204,7 @@ must be explicit via ``payable(
    )``. Explicit conversions to and from ``address`` are allowed for ``uint160``, integer literals, ``bytes20`` and contract types. -Only expressions of type ``address`` and contract-type can be converted to the type ``address +Only expressions of type ``address`` and contract type can be converted to the type ``address payable`` via the explicit conversion ``payable(...)``. For contract-type, this conversion is only allowed if the contract can receive Ether, i.e., the contract either has a :ref:`receive ` or a payable fallback function. Note that ``payable(0)`` is valid and is @@ -209,7 +215,7 @@ an exception to this rule. declare its type as ``address payable`` to make this requirement visible. Also, try to make this distinction or conversion as early as possible. - The distinction between ``address`` and ``address payable`` was introduced with version 0.5.0. + The distinction between ``address`` and ``address payable`` was introduced in version 0.5.0. Also starting from that version, contracts are not implicitly convertible to the ``address`` type, but can still be explicitly converted to ``address`` or to ``address payable``, if they have a receive or payable fallback function. @@ -223,7 +229,7 @@ Operators: To reduce conversion ambiguity, starting with version 0.4.24, the compiler will force you to make the truncation explicit in the conversion. Take for example the 32-byte value ``0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC``. - You can use ``address(uint160(bytes20(b)))``, which results in ``0x111122223333444455556666777788889999aAaa``, + You can use ``address(bytes20(b))``, which results in ``0x111122223333444455556666777788889999aAaa``, or you can use ``address(uint160(uint256(b)))``, which results in ``0x777788889999AaAAbBbbCcccddDdeeeEfFFfCcCc``. .. note:: @@ -236,111 +242,148 @@ Members of Addresses For a quick reference of all members of address, see :ref:`address_related`. +.. _balance-transfer-address-members: + * ``balance`` and ``transfer`` -It is possible to query the balance of an address using the property ``balance`` -and to send Ether (in units of wei) to a payable address using the ``transfer`` function: + It is possible to query the balance of an address using the property ``balance`` + and to send Ether (in units of wei) to a payable address using the ``transfer`` function: -.. code-block:: solidity - :force: + .. code-block:: solidity + :force: - address payable x = payable(0x123); - address myAddress = address(this); - if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10); + address payable x = payable(0x123); + address myAddress = address(this); + if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10); -The ``transfer`` function fails if the balance of the current contract is not large enough -or if the Ether transfer is rejected by the receiving account. The ``transfer`` function -reverts on failure. + The ``transfer`` function fails if the balance of the current contract is not large enough + or if the Ether transfer is rejected by the receiving account. The ``transfer`` function + reverts on failure. -.. note:: - If ``x`` is a contract address, its code (more specifically: its :ref:`receive-ether-function`, if present, or otherwise its :ref:`fallback-function`, if present) will be executed together with the ``transfer`` call (this is a feature of the EVM and cannot be prevented). If that execution runs out of gas or fails in any way, the Ether transfer will be reverted and the current contract will stop with an exception. + .. note:: + If ``x`` is a contract address, its code (more specifically: its :ref:`receive-ether-function`, if present, or otherwise its :ref:`fallback-function`, if present) will be executed together with the ``transfer`` call (this is a feature of the EVM and cannot be prevented). If that execution runs out of gas or fails in any way, the Ether transfer will be reverted and the current contract will stop with an exception. + + .. warning:: + ``transfer`` is deprecated and scheduled for removal. + Simple ether transfers can still be performed using the :ref:`call function ` + with with an optionally provided maximum amount of gas and empty payload, i.e., ``call{value: }("")``. + By default this forwards all the remaining gas, subject to additional limits imposed by some EVM versions + (such as the `63/64th rule `_ introduced by ``tangerineWhistle``). + As with any external call, the ``gas`` call option can be used to set a lower limit. + + While it is possible to recreate the functionality by explicitly setting the limit to the value of the stipend (2300 gas), + this value no longer holds its original meaning due to changing opcode costs. + It is recommended to use different means to protect against reentrancy. + +.. _send-address-member: * ``send`` -``send`` is the low-level counterpart of ``transfer``. If the execution fails, the current contract will not stop with an exception, but ``send`` will return ``false``. + ``send`` is the low-level counterpart of ``transfer``. If the execution fails, the current contract will not stop with an exception, but ``send`` will return ``false``. -.. warning:: - There are some dangers in using ``send``: The transfer fails if the call stack depth is at 1024 - (this can always be forced by the caller) and it also fails if the recipient runs out of gas. So in order - to make safe Ether transfers, always check the return value of ``send``, use ``transfer`` or even better: - use a pattern where the recipient withdraws the Ether. + .. warning:: + There are some dangers in using ``send``: The transfer fails if the call stack depth is at 1024 + (this can always be forced by the caller) and it also fails if the recipient runs out of gas. So in order + to make safe Ether transfers, always check the return value of ``send``, use ``transfer`` or even better: + use a pattern where the recipient withdraws the Ether. + + .. warning:: + ``send`` is deprecated and scheduled for removal. + Simple ether transfers can still be performed using the :ref:`call function ` + with with an optionally provided maximum amount of gas and empty payload, i.e., ``call{value: }("")``. + By default this forwards all the remaining gas, subject to additional limits imposed by some EVM versions + (such as the `63/64th rule `_ introduced by ``tangerineWhistle``). + As with any external call, the ``gas`` call option can be used to set a lower limit. + + While it is possible to recreate the functionality by explicitly setting the limit to the value of the stipend (2300 gas), + this value no longer holds its original meaning due to changing opcode costs. + It is recommended to use different means to protect against reentrancy. + +.. _address_call_functions: * ``call``, ``delegatecall`` and ``staticcall`` -In order to interface with contracts that do not adhere to the ABI, -or to get more direct control over the encoding, -the functions ``call``, ``delegatecall`` and ``staticcall`` are provided. -They all take a single ``bytes memory`` parameter and -return the success condition (as a ``bool``) and the returned data -(``bytes memory``). -The functions ``abi.encode``, ``abi.encodePacked``, ``abi.encodeWithSelector`` -and ``abi.encodeWithSignature`` can be used to encode structured data. + In order to interface with contracts that do not adhere to the ABI, + or to get more direct control over the encoding, + the functions ``call``, ``delegatecall`` and ``staticcall`` are provided. + They all take a single ``bytes memory`` parameter and + return the success condition (as a ``bool``) and the returned data + (``bytes memory``). + The functions ``abi.encode``, ``abi.encodePacked``, ``abi.encodeWithSelector`` + and ``abi.encodeWithSignature`` can be used to encode structured data. -Example: + Example: -.. code-block:: solidity + .. code-block:: solidity - bytes memory payload = abi.encodeWithSignature("register(string)", "MyName"); - (bool success, bytes memory returnData) = address(nameReg).call(payload); - require(success); + bytes memory payload = abi.encodeWithSignature("register(string)", "MyName"); + (bool success, bytes memory returnData) = address(nameReg).call(payload); + require(success); -.. warning:: - All these functions are low-level functions and should be used with care. - Specifically, any unknown contract might be malicious and if you call it, you - hand over control to that contract which could in turn call back into - your contract, so be prepared for changes to your state variables - when the call returns. The regular way to interact with other contracts - is to call a function on a contract object (``x.f()``). + .. warning:: + All these functions are low-level functions and should be used with care. + Specifically, any unknown contract might be malicious and if you call it, you + hand over control to that contract which could in turn call back into + your contract, so be prepared for changes to your state variables + when the call returns. The regular way to interact with other contracts + is to call a function on a contract object (``x.f()``). -.. note:: - Previous versions of Solidity allowed these functions to receive - arbitrary arguments and would also handle a first argument of type - ``bytes4`` differently. These edge cases were removed in version 0.5.0. + .. note:: + Previous versions of Solidity allowed these functions to receive + arbitrary arguments and would also handle a first argument of type + ``bytes4`` differently. These edge cases were removed in version 0.5.0. -It is possible to adjust the supplied gas with the ``gas`` modifier: + It is possible to adjust the supplied gas with the ``gas`` modifier: -.. code-block:: solidity + .. code-block:: solidity - address(nameReg).call{gas: 1000000}(abi.encodeWithSignature("register(string)", "MyName")); + address(nameReg).call{gas: 1000000}(abi.encodeWithSignature("register(string)", "MyName")); -Similarly, the supplied Ether value can be controlled too: + Similarly, the supplied Ether value can be controlled too: -.. code-block:: solidity + .. code-block:: solidity - address(nameReg).call{value: 1 ether}(abi.encodeWithSignature("register(string)", "MyName")); + address(nameReg).call{value: 1 ether}(abi.encodeWithSignature("register(string)", "MyName")); -Lastly, these modifiers can be combined. Their order does not matter: + Lastly, these modifiers can be combined. Their order does not matter: -.. code-block:: solidity + .. code-block:: solidity - address(nameReg).call{gas: 1000000, value: 1 ether}(abi.encodeWithSignature("register(string)", "MyName")); + address(nameReg).call{gas: 1000000, value: 1 ether}(abi.encodeWithSignature("register(string)", "MyName")); -In a similar way, the function ``delegatecall`` can be used: the difference is that only the code of the given address is used, all other aspects (storage, balance, ...) are taken from the current contract. The purpose of ``delegatecall`` is to use library code which is stored in another contract. The user has to ensure that the layout of storage in both contracts is suitable for delegatecall to be used. + In a similar way, the function ``delegatecall`` can be used: the difference is that only the code of the given address is used, all other aspects (storage, balance, ...) are taken from the current contract. The purpose of ``delegatecall`` is to use library code which is stored in another contract. The user has to ensure that the layout of storage in both contracts is suitable for delegatecall to be used. -.. note:: - Prior to homestead, only a limited variant called ``callcode`` was available that did not provide access to the original ``msg.sender`` and ``msg.value`` values. This function was removed in version 0.5.0. + .. note:: + Prior to homestead, only a limited variant called ``callcode`` was available that did not provide access to the original ``msg.sender`` and ``msg.value`` values. This function was removed in version 0.5.0. -Since byzantium ``staticcall`` can be used as well. This is basically the same as ``call``, but will revert if the called function modifies the state in any way. + Since byzantium ``staticcall`` can be used as well. This is basically the same as ``call``, but will revert if the called function modifies the state in any way. -All three functions ``call``, ``delegatecall`` and ``staticcall`` are very low-level functions and should only be used as a *last resort* as they break the type-safety of Solidity. + All three functions ``call``, ``delegatecall`` and ``staticcall`` are very low-level functions and should only be used as a *last resort* as they break the type-safety of Solidity. -The ``gas`` option is available on all three methods, while the ``value`` option is only available -on ``call``. + The ``gas`` option is available on all three methods, while the ``value`` option is only available + on ``call``. -.. note:: - It is best to avoid relying on hardcoded gas values in your smart contract code, - regardless of whether state is read from or written to, as this can have many pitfalls. - Also, access to gas might change in the future. + .. note:: + It is best to avoid relying on hardcoded gas values in your smart contract code, + regardless of whether state is read from or written to, as this can have many pitfalls. + Also, access to gas might change in the future. * ``code`` and ``codehash`` -You can query the deployed code for any smart contract. Use ``.code`` to get the EVM bytecode as a -``bytes memory``, which might be empty. Use ``.codehash`` to get the Keccak-256 hash of that code -(as a ``bytes32``). Note that ``addr.codehash`` is cheaper than using ``keccak256(addr.code)``. + You can query the deployed code for any smart contract. Use ``.code`` to get the EVM bytecode as a + ``bytes memory``, which might be empty. Use ``.codehash`` to get the Keccak-256 hash of that code + (as a ``bytes32``). Note that ``addr.codehash`` is cheaper than using ``keccak256(addr.code)``. -.. note:: - All contracts can be converted to ``address`` type, so it is possible to query the balance of the - current contract using ``address(this).balance``. + .. warning:: + The output of ``addr.codehash`` may be ``0`` if the account associated with ``addr`` is empty or non-existent + (i.e., it has no code, zero balance, and zero nonce as defined by `EIP-161 `_). + If the account has no code but a non-zero balance or nonce, then ``addr.codehash`` will output the Keccak-256 hash of empty data + (i.e., ``keccak256("")`` which is equal to ``c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470``), as defined by + `EIP-1052 `_. + + .. note:: + All contracts can be converted to ``address`` type, so it is possible to query the balance of the + current contract using ``address(this).balance``. .. index:: ! contract type, ! type; contract @@ -715,7 +758,7 @@ that has the same data representation as the input, whereas ``toUFixed256x18`` r Function Types -------------- -Function types are the types of functions. Variables of function type +Function types are the types of functions. Variables of a function type can be assigned from functions and function parameters of function type can be used to pass functions to and return functions from function calls. Function types come in two flavours - *internal* and *external* functions: @@ -730,6 +773,20 @@ contract internally. External functions consist of an address and a function signature and they can be passed via and returned from external function calls. +Note that public functions of the current contract can be used both as an +internal and as an external function. To use ``f`` as an internal function, +just use ``f``, if you want to use its external form, use ``this.f``. + +If a function type variable is not initialised, calling it results +in a :ref:`Panic error`. The same happens if you call a function after using ``delete`` +on it. + +.. note:: + Lambda or inline functions are planned but not yet supported. + +Declaration syntax +^^^^^^^^^^^^^^^^^^ + Function types are notated as follows: .. code-block:: solidity @@ -746,7 +803,8 @@ omitted. Note that this only applies to function types. Visibility has to be specified explicitly for functions defined in contracts, they do not have a default. -Conversions: +Conversions +^^^^^^^^^^^ A function type ``A`` is implicitly convertible to a function type ``B`` if and only if their parameter types are identical, their return types are identical, @@ -775,18 +833,10 @@ Which makes it possible to assign a ``payable`` function pointer to a ``non-paya function pointer ensuring both types behave the same way, i.e, both cannot be used to send ether. -If a function type variable is not initialised, calling it results -in a :ref:`Panic error`. The same happens if you call a function after using ``delete`` -on it. - If external function types are used outside of the context of Solidity, they are treated as the ``function`` type, which encodes the address followed by the function identifier together in a single ``bytes24`` type. -Note that public functions of the current contract can be used both as an -internal and as an external function. To use ``f`` as an internal function, -just use ``f``, if you want to use its external form, use ``this.f``. - A function of an internal type can be assigned to a variable of an internal function type regardless of where it is defined. This includes private, internal and public functions of both contracts and libraries as well as free @@ -815,7 +865,8 @@ Libraries are excluded because they require a ``delegatecall`` and use :ref:`a d convention for their selectors `. Functions declared in interfaces do not have definitions so pointing at them does not make sense either. -Members: +Members +^^^^^^^ External (or public) functions have the following members: @@ -830,6 +881,59 @@ External (or public) functions have the following members: respectively. See :ref:`External Function Calls ` for more information. +.. _function-type-value-stability-across-contract-updates: + +Value stability across contract updates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +An important aspect to consider when using values of function types is whether the value will +remain valid if the underlying code changes. + +The state of the blockchain is not completely immutable and there are multiple ways to place +different code under the same address: + +- Directly deploying different code using :ref:`salted contract creation`. +- Delegating to a different contract via :ref:`DELEGATECALL` + (upgradeable code behind a proxy contract is a common example of this). +- Account abstraction as defined by `EIP-7702 `_. + +External function types can be considered as stable as contract's ABI, which makes them very portable. +Their ABI representation always consists of a contract address and a function selector and it is +perfectly safe to store them long-term or pass them between contracts. +While it is possible for the referenced function to change or disappear, a direct external call +would be affected the same way, so there is no additional risk in such use. + +In case of internal functions, however, the value is an identifier that is strongly tied to +contract's bytecode. +The actual representation of the identifier is an implementation detail and may change between +compiler versions or even :ref:`between different backends`. +Values assigned under a given representation are deterministic (i.e. guaranteed to remain the same +as long as the source code is the same) but are easily affected by changes such as adding, removing +or reordering of functions. +The compiler is also free to remove internal functions that are never used, which may affect other identifiers. +Some representations, e.g. one where identifiers are simply jump targets, may be affected by +virtually any change, even one completely unrelated to internal functions. + +To counter this, the language limits the use of internal function types outside of the context in +which they are valid. +This is why internal function types cannot be used as parameters of external functions (or in any +other way that is exposed in contract's ABI). +However, there are still situations where it is up to the user to decide whether their use is safe or not. +For example long-term storage of such values in state variables is discouraged, but may be safe if +the contract code is never going to be updated. +It is also always possible to side-step any safeguards by using inline assembly. +Such use always needs careful consideration. + +.. note:: + The removal of unused internal functions only takes into account explicit references to + such functions by name. + Implicit references, such as assigning a new value to a function type variable in inline assembly + may still lead to the removal of the function if it is not also referenced explicitly elsewhere + in the source. + +Examples +^^^^^^^^ + Example that shows how to use the members: .. code-block:: solidity @@ -953,6 +1057,3 @@ Another example that uses external function types: exchangeRate = response; } } - -.. note:: - Lambda or inline functions are planned but not yet supported. diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index 958d1cc36c..b18f81d8ce 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -72,6 +72,7 @@ Propiedades de bloques y transacciones - ``blobhash(uint index) returns (bytes32)``: versioned hash of the ``index``-th blob associated with the current transaction. A versioned hash consists of a single byte representing the version (currently ``0x01``), followed by the last 31 bytes of the SHA256 hash of the KZG commitment (`EIP-4844 `_). + Returns zero if no blob with the given index exists. - ``block.basefee`` (``uint``): current block's base fee (`EIP-3198 `_ and `EIP-1559 `_) - ``block.blobbasefee`` (``uint``): current block's blob base fee (`EIP-7516 `_ and `EIP-4844 `_) - ``block.chainid`` (``uint``): current chain id @@ -174,7 +175,7 @@ Consulte la sección dedicada a :ref:`assert y require` para ``revert(string memory reason)`` anular la ejecución y revertir los cambios de estado, proporcionar una cadena explicativa -.. index:: keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, +.. index:: keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, erc7201, .. _mathematical-and-cryptographic-functions: @@ -223,12 +224,19 @@ Funciones matemáticas y criptográficas Al ejecutar ``sha256``, ``ripemd160`` o ``ecrecover`` en un *blockchain privado*, es posible que se encuentre sin gas. Esto se debe a que estas funciones se implementan como "contratos precompilados" y solo existen realmente después de recibir el primer mensaje (aunque su código de contrato está codificado). Los mensajes a contratos inexistentes son más caros y, por lo tanto, la ejecución podría encontrarse con un error de falta de gas. Una solución para este problema es enviar primero Wei (1 por ejemplo) a cada uno de los contratos antes de utilizarlos en sus contratos reales. Esto no es un problema en la red principal o de prueba. +``erc7201(string memory id) returns (uint)`` + compute the base slot of a storage namespace of a given ``id`` according to the ``erc7201`` formula defined by `ERC-7201`. + The formula is equivalent to ``keccak256(keccak256(id) - 1) & ~0xff``. + The builtin accepts arbitrary strings, including ones containing whitespace. + The function can be used in compile-time context. + .. index:: balance, codehash, send, transfer, call, callcode, delegatecall, staticcall .. _address_related: Miembros de tipos de direcciones ------------------------ +These members are explained in more detail in the section on :ref:`members of address `. ``
    .balance`` (``uint256``) balance de la :ref:`dirección` en Wei @@ -245,7 +253,12 @@ Miembros de tipos de direcciones ``
    .send(uint256 amount) returns (bool)`` envìa la cantidad dada de Wei a :ref:`dirección`, devuelve ``false`` en caso de error, adelanta 2300 estipendios de gas, no ajustable +.. warning:: + ``send()`` and ``transfer()`` are deprecated and scheduled for removal. + See the section on :ref:`send ` and :ref:`transfer ` for more information. + ``
    .call(bytes memory) returns (bool, bytes memory)`` +<<<<<<< HEAD emite ``CALL`` de bajo nivel con la carga útil dada, devuelve la condición de éxito y devuelve datos, reenvía todo el gas disponible, ajustable ``
    .delegatecall(bytes memory) returns (bool, bytes memory)`` @@ -253,6 +266,18 @@ Miembros de tipos de direcciones ``
    .staticcall(bytes memory) returns (bool, bytes memory)`` emite ``STATICCALL`` de bajo nivel con la carga útil dada, devuelve la condición de éxito y devuelve datos, reenvía todo el gas disponible, ajustable +======= + issue low-level ``CALL`` with the given payload, returns success condition and return data, + forwards all available gas (subject to additional limits imposed by some EVM versions), adjustable + +``
    .delegatecall(bytes memory) returns (bool, bytes memory)`` + issue low-level ``DELEGATECALL`` with the given payload, returns success condition and return data, + forwards all available gas (subject to additional limits imposed by some EVM versions), adjustable + +``
    .staticcall(bytes memory) returns (bool, bytes memory)`` + issue low-level ``STATICCALL`` with the given payload, returns success condition and return data, + forwards all available gas (subject to additional limits imposed by some EVM versions), adjustable +>>>>>>> english/develop Para obtener más información, consulte la sección sobre :ref:`dirección`. @@ -312,9 +337,23 @@ Contract-related Además, todas las funciones del contrato actual son llamables directamente, incluida la función actual. .. warning:: - From version 0.8.18 and up, the use of ``selfdestruct`` in both Solidity and Yul will trigger a - deprecation warning, since the ``SELFDESTRUCT`` opcode will eventually undergo breaking changes in behavior - as stated in `EIP-6049 `_. + From ``EVM >= Cancun`` onwards, ``selfdestruct`` will **only** send all Ether in the account to the given recipient and not destroy the contract. + However, when ``selfdestruct`` is called in the same transaction that creates the contract calling it, + the behaviour of ``selfdestruct`` before Cancun hardfork (i.e., ``EVM <= Shanghai``) is preserved and will destroy the current contract, + deleting any data, including storage keys, code and the account itself. + See `EIP-6780 `_ for more details. + + The new behaviour is the result of a network-wide change that affects all contracts present on + the Ethereum mainnet and testnets. + It is important to note that this change is dependent on the EVM version of the chain on which + the contract is deployed. + The ``--evm-version`` setting used when compiling the contract has no bearing on it. + + Also, note that the ``selfdestruct`` opcode has been deprecated in Solidity version 0.8.18, + as recommended by `EIP-6049 `_. + The deprecation is still in effect and the compiler will still emit warnings on its use. + Any use in newly deployed contracts is strongly discouraged even if the new behavior is taken into account. + Future changes to the EVM might further reduce the functionality of the opcode. .. note:: Antes de la versión 0.5.0, había una función llamada ``suicide`` con la misma semántica que ``selfdestruct``. diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 97abbdba9d..478ccd146c 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -71,7 +71,7 @@ For a detailed explanation with examples and discussion of corner cases please r Library Linking --------------- -If your contracts use :ref:`libraries `, you will notice that the bytecode contains substrings of the form ``__$53aea86b7d70b31448b230b20ae141a537$__``. These are placeholders for the actual library addresses. +If your contracts use :ref:`libraries `, you will notice that the bytecode contains substrings of the form ``__$53aea86b7d70b31448b230b20ae141a537$__`` `(format was different `_. These are placeholders for the actual library addresses. The placeholder is a 34 character prefix of the hex encoding of the keccak256 hash of the fully qualified library name. The bytecode file will also contain lines of the form ``// -> `` at the end to help identify which libraries the placeholders represent. Note that the fully qualified library name @@ -174,13 +174,16 @@ at each version. Backward compatibility is not guaranteed between each version. - The block's base fee (`EIP-3198 `_ and `EIP-1559 `_) can be accessed via the global ``block.basefee`` or ``basefee()`` in inline assembly. - ``paris`` - Introduces ``prevrandao()`` and ``block.prevrandao``, and changes the semantics of the now deprecated ``block.difficulty``, disallowing ``difficulty()`` in inline assembly (see `EIP-4399 `_). -- ``shanghai`` (**default**) +- ``shanghai`` - Smaller code size and gas savings due to the introduction of ``push0`` (see `EIP-3855 `_). - ``cancun`` - The block's blob base fee (`EIP-7516 `_ and `EIP-4844 `_) can be accessed via the global ``block.blobbasefee`` or ``blobbasefee()`` in inline assembly. - Introduces ``blobhash()`` in inline assembly and a corresponding global function to retrieve versioned hashes of blobs associated with the transaction (see `EIP-4844 `_). - Opcode ``mcopy`` is available in assembly (see `EIP-5656 `_). - Opcodes ``tstore`` and ``tload`` are available in assembly (see `EIP-1153 `_). +- ``prague`` +- ``osaka`` (**default**) + - ``clz`` builtin function is available in inline assembly. (`EIP-7939 `_) .. index:: ! standard JSON, ! --standard-json .. _compiler-api: @@ -236,12 +239,12 @@ Input Description // `--allow-paths `. ] }, - "destructible": + "settable": { // Optional: keccak256 hash of the source file "keccak256": "0x234...", // Required (unless "urls" is used): literal contents of the source file - "content": "contract destructible is owned { function shutdown() { if (msg.sender == owner) selfdestruct(owner); } }" + "content": "contract settable is owned { uint256 private x = 0; function set(uint256 _x) public { if (msg.sender == owner) x = _x; } }" }, "myFile.sol_json.ast": { @@ -276,79 +279,100 @@ Input Description { // Optional: Stop compilation after the given stage. Currently only "parsing" is valid here "stopAfter": "parsing", - // Optional: Sorted list of remappings + // Optional: List of remappings "remappings": [ ":g=/dir" ], + // Optional: Experimental mode toggle (Default: false) + // Makes it possible to use experimental features (but does not enable any such feature by itself). + // The use of this mode is recorded in contract metadata. + "experimental": true, // Optional: Optimizer settings "optimizer": { - // Disabled by default. - // NOTE: enabled=false still leaves some optimizations on. See comments below. - // WARNING: Before version 0.8.6 omitting the 'enabled' key was not equivalent to setting - // it to false and would actually disable all the optimizations. + // Turn on the optimizer. Optional. Default: false. + // NOTE: The state of the optimizer is fully determined by the 'details' dict and this setting + // only affects its defaults - when enabled, all components default to being enabled. + // The opposite is not true - there are several components that always default to being + // enabled an can only be explicitly disabled via 'details'. + // WARNING: Before version 0.8.6 omitting this setting was not equivalent to setting + // it to false and would result in all components being disabled instead. + // WARNING: Enabling optimizations for EVMAssembly input is allowed but not necessary under normal + // circumstances. It forces the opcode-based optimizer to run again and can produce bytecode that + // is not reproducible from metadata. "enabled": true, - // Optimize for how many times you intend to run the code. + // Optimize for how many times you intend to run the code. Optional. Default: 200. // Lower values will optimize more for initial deployment cost, higher // values will optimize more for high-frequency usage. "runs": 200, - // Switch optimizer components on or off in detail. - // The "enabled" switch above provides two defaults which can be - // tweaked here. If "details" is given, "enabled" can be omitted. + // State of all optimizer components. Optional. + // Default values are determined by whether the optimizer is enabled or not. + // Note that the 'enabled' setting only affects the defaults here and has no effect when + // all values are provided explicitly. "details": { - // The peephole optimizer is always on if no details are given, - // use details to switch it off. + // Peephole optimizer (opcode-based). Optional. Default: true. + // Default for EVMAssembly input: false when optimization is not enabled. + // NOTE: Always runs (even with optimization disabled) except for EVMAssembly input or when explicitly turned off here. "peephole": true, - // The inliner is always off if no details are given, - // use details to switch it on. + // Inliner (opcode-based). Optional. Default: true when optimization is enabled. "inliner": false, - // The unused jumpdest remover is always on if no details are given, - // use details to switch it off. + // Unused JUMPDEST remover (opcode-based). Optional. Default: true. + // Default for EVMAssembly input: false when optimization is not enabled. + // NOTE: Always runs (even with optimization disabled) except for EVMAssembly input or when explicitly turned off here. "jumpdestRemover": true, - // Sometimes re-orders literals in commutative operations. + // Literal reordering (codegen-based). Optional. Default: true when optimization is enabled. + // Moves literals to the right of commutative binary operators during code generation, helping exploit associativity. "orderLiterals": false, - // Removes duplicate code blocks + // Block deduplicator (opcode-based). Optional. Default: true when optimization is enabled. + // Unifies assembly code blocks that share content. "deduplicate": false, - // Common subexpression elimination, this is the most complicated step but - // can also provide the largest gain. + // Common subexpression elimination (opcode-based). Optional. Default: true when optimization is enabled. + // This is the most complicated step but can also provide the largest gain. "cse": false, - // Optimize representation of literal numbers and strings in code. + // Constant optimizer (opcode-based). Optional. Default: true when optimization is enabled. + // Tries to find better representations of literal numbers and strings, that satisfy the + // size/cost trade-off determined by the 'runs' setting. "constantOptimizer": false, - // Use unchecked arithmetic when incrementing the counter of for loops - // under certain circumstances. It is always on if no details are given. + // Unchecked loop increment (codegen-based). Optional. Default: true. + // Use unchecked arithmetic when incrementing the counter of 'for' loops under certain circumstances. + // NOTE: Always runs (even with optimization disabled) unless explicitly turned off here. "simpleCounterForLoopUncheckedIncrement": true, - // The new Yul optimizer. Mostly operates on the code of ABI coder v2 - // and inline assembly. - // It is activated together with the global optimizer setting - // and can be deactivated here. - // Before Solidity 0.6.0 it had to be activated through this switch. + // Yul optimizer. Optional. Default: true when optimization is enabled. + // Used to optimize the IR produced by the Yul IR-based pipeline as well as inline assembly + // and utility Yul code generated by the compiler. + // NOTE: Before Solidity 0.6.0 the default was false. "yul": false, - // Tuning options for the Yul optimizer. + // Tuning options for the Yul optimizer. Optional. "yulDetails": { // Improve allocation of stack slots for variables, can free up stack slots early. - // Activated by default if the Yul optimizer is activated. + // Optional. Default: true if Yul optimizer is enabled. "stackAllocation": true, - // Select optimization steps to be applied. It is also possible to modify both the - // optimization sequence and the clean-up sequence. Instructions for each sequence - // are separated with the ":" delimiter and the values are provided in the form of - // optimization-sequence:clean-up-sequence. For more information see - // "The Optimizer > Selecting Optimizations". - // This field is optional, and if not provided, the default sequences for both - // optimization and clean-up are used. If only one of the sequences is provided - // the other will not be run. - // If only the delimiter ":" is provided then neither the optimization nor the clean-up - // sequence will be run. - // If set to an empty value, only the default clean-up sequence is used and - // no optimization steps are applied. - "optimizerSteps": "dhfoDgvulfnTUtnIf..." + // Optimization step sequence. + // The general form of the value is "
    :". + // The setting is optional and when omitted, default values are used for both sequences. + // If the value does not contain the ':' delimiter, it is interpreted as the main + // sequence and the default is used for the cleanup sequence. + // To make one of the sequences empty, the delimiter must be present at the first or last position. + // In particular if the whole value consists only of the delimiter, both sequences are empty. + // Note that there are several hard-coded steps that always run, even when both sequences are empty. + // For more information see "The Optimizer > Selecting Optimizations". + "optimizerSteps": "dfDvulfnTUtnIf..." } } }, - // Version of the EVM to compile for. + // Version of the EVM to compile for (optional). // Affects type checking and code generation. Can be homestead, // tangerineWhistle, spuriousDragon, byzantium, constantinople, - // petersburg, istanbul, berlin, london, paris or shanghai (default) - "evmVersion": "shanghai", + // petersburg, istanbul, berlin, london, paris, shanghai, cancun, + // prague, osaka (default), or @future (experimental). + "evmVersion": "osaka", + // EVM Object Format version to compile for (optional, experimental). + // Currently the only valid value is 1. If not specified, legacy non-EOF bytecode will be generated. + // Requires `evmVersion` >= osaka. + "eofVersion": null, // Optional: Change compilation pipeline to go through the Yul intermediate representation. // This is false by default. "viaIR": true, + // Optional: Turn on SSA CFG-based code generation via the IR (experimental). + // Implies viaIR: true. This is false by default. + "viaSSACFG": false, // Optional: Debugging settings "debug": { // How to treat revert (and require) reason strings. Settings are @@ -367,8 +391,11 @@ Input Description // - `` is the index of the first byte after that location. // - `snippet`: A single-line code snippet from the location indicated by `@src`. // The snippet is quoted and follows the corresponding `@src` annotation. - // - `*`: Wildcard value that can be used to request everything. - "debugInfo": ["location", "snippet"] + // - `ast-id`: Annotations of the form `@ast-id ` over elements that can be mapped back to a definition in the original Solidity file. + // `` is a node ID in the Solidity AST ('ast' output). + // - `ethdebug`: Ethdebug annotations (experimental). Automatically enabled when any ethdebug output is requested. + // - `*`: Wildcard value that can be used to request all non-experimental components. + "debugInfo": ["location", "snippet", "ast-id", "ethdebug"] }, // Metadata settings (optional) "metadata": { @@ -403,7 +430,8 @@ Input Description // but to the whole source file like the AST. // A star as contract name refers to all contracts in the file. // Similarly, a star as a file name matches all files. - // To select all outputs the compiler can possibly generate, use + // To select all outputs the compiler can possibly generate, with the exclusion of + // Yul intermediate representation outputs, use // "outputSelection: { "*": { "*": [ "*" ], "": [ "*" ] } }" // but note that this might slow down the compilation process needlessly. // @@ -418,12 +446,15 @@ Input Description // userdoc - User documentation (natspec) // metadata - Metadata // ir - Yul intermediate representation of the code before optimization - // irAst - AST of Yul intermediate representation of the code before optimization + // irAst - AST of Yul intermediate representation of the code before optimization (experimental) // irOptimized - Intermediate representation after optimization - // irOptimizedAst - AST of intermediate representation after optimization - // storageLayout - Slots, offsets and types of the contract's state variables. + // irOptimizedAst - AST of intermediate representation after optimization (experimental) + // storageLayout - Slots, offsets and types of the contract's state variables in storage + // transientStorageLayout - Slots, offsets and types of the contract's state variables in transient storage // evm.assembly - New assembly format // evm.legacyAssembly - Old-style assembly format in JSON + // evm.bytecode.ethdebug - Debug information in ethdebug format (ethdebug/format/program schema for creation bytecode). Can only be requested when compiling via IR. (experimental) + // evm.deployedBytecode.ethdebug - Debug information in ethdebug format (ethdebug/format/program schema for deployed bytecode). Can only be requested when compiling via IR. (experimental) // evm.bytecode.functionDebugData - Debugging information at function level // evm.bytecode.object - Bytecode object // evm.bytecode.opcodes - Opcodes list @@ -434,6 +465,11 @@ Input Description // evm.deployedBytecode.immutableReferences - Map from AST ids to bytecode ranges that reference immutables // evm.methodIdentifiers - The list of function hashes // evm.gasEstimates - Function gas estimates + // yulCFGJson - Control Flow Graph (CFG) of the Single Static Assignment (SSA) form of the contract (experimental) + // + // Global level (needs "*" as file name and "*" as contract name): + // ethdebug.resources - Global ethdebug output (ethdebug/format/info/resources schema) containing source list and compiler info (experimental) + // ethdebug.compilation - Global ethdebug compilation output (the 'compilation' key from ethdebug/format/info/resources schema) (experimental) // // Note that using `evm`, `evm.bytecode`, etc. will select every // target part of that output. Additionally, `*` can be used as a wildcard to request everything. @@ -478,14 +514,14 @@ Input Description // Choose which types of invariants should be reported to the user: contract, reentrancy. "invariants": ["contract", "reentrancy"], // Choose whether to output all proved targets. The default is `false`. - "showProved": true, + "showProvedSafe": true, // Choose whether to output all unproved targets. The default is `false`. "showUnproved": true, // Choose whether to output all unsupported language features. The default is `false`. "showUnsupported": true, // Choose which solvers should be used, if available. // See the Formal Verification section for the solvers description. - "solvers": ["cvc4", "smtlib2", "z3"], + "solvers": ["cvc5", "smtlib2", "z3"], // Choose which targets should be checked: constantCondition, // underflow, overflow, divByZero, balance, assert, popEmptyArray, outOfBounds. // If the option is not given all targets are checked by default, @@ -576,6 +612,8 @@ Output Description "irOptimizedAst": {/* ... */}, // See the Storage Layout documentation. "storageLayout": {"storage": [/* ... */], "types": {/* ... */} }, + // See the Storage Layout documentation. + "transientStorageLayout": {"storage": [/* ... */], "types": {/* ... */} }, // EVM-related outputs "evm": { // Assembly (string) @@ -584,6 +622,8 @@ Output Description "legacyAssembly": {}, // Bytecode and related details. "bytecode": { + // Ethdebug output (experimental) + "ethdebug": {/* ... */}, // Debugging data at the level of functions. "functionDebugData": { // Now follows a set of functions including compiler-internal and @@ -626,6 +666,8 @@ Output Description } }, "deployedBytecode": { + // Ethdebug output (experimental) + "ethdebug": {/* ... */}, /* ..., */ // The same layout as above. "immutableReferences": { // There are two references to the immutable with AST ID 3, both 32 bytes long. One is @@ -650,10 +692,19 @@ Output Description "internal": { "heavyLifting()": "infinite" } - } + }, + // Yul CFG representation of the SSA form (experimental) + "yulCFGJson": {/* ... */} } } } + }, + // Global Ethdebug output (experimental) + "ethdebug": { + // Requested via ethdebug.resources output selection + "resources": {/* ... */}, + // Requested via ethdebug.compilation output selection + "compilation": {/* ... */} } } @@ -676,3 +727,59 @@ Error Types 13. ``YulException``: Error during Yul code generation - this should be reported as an issue. 14. ``Warning``: A warning, which didn't stop the compilation, but should be addressed if possible. 15. ``Info``: Information that the compiler thinks the user might find useful, but is not dangerous and does not necessarily need to be addressed. + +.. index:: ! Experimental mode, ! --experimental +.. _experimental-mode: + +Experimental Mode +***************** + +Some language and compiler features included in stable releases are not themselves considered stable. +They are sparsely documented, if at all, often not adequately tested, and thus not yet intended for production use. +In many cases it is possible to develop a big feature incrementally, with each iteration being already stable. +Sometimes, however, it is preferable to start with a prototype and stabilize it over multiple releases, while receiving feedback from users. +To prevent accidental use, such features can be only accessed by enabling the experimental mode. + +There are no backwards compatibility guarantees for experimental features. +They are subject to change in breaking ways in non-breaking releases of the compiler. +Only major changes affecting them are recorded in the changelog. + +To enable the experimental mode, use the ``--experimental`` flag on the command line, +or the analogous ``settings.experimental`` boolean setting in the Standard JSON input. + +Note that the use of this mode is recorded in the metadata: + +- ``experimental`` flag in CBOR metadata is set to ``true``, +- ``settings.experimental`` in JSON metadata is set to ``true``, + +.. note:: + Prior to version 0.8.34, most of the experimental features were usable without any extra safeguards. + Some were gated behind ``pragma experimental``, but this was not done consistently. + The information about them was also only recorded in CBOR metadata and even then not always. + The main goal of the experimental mode is to systematize this and make users fully aware when relying on features which are unfinished or not production-ready. + +The table below details all currently available experimental features. + ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| Feature | ID | Affects bytecode | Flag/pragma | ++=======================+==========================+==================+=========================================================================================================================================+ +| AST import | ``ast-import`` | yes | ``--import-ast`` | ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| LSP | ``lsp`` | no | ``--lsp`` | ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| EVM Assembly import | ``evmasm-import`` | yes | ``--import-asm-json`` | ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| Generic Solidity | ``generic-solidity`` | yes | ``pragma experimental solidity`` | ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| IR AST | ``ir-ast`` | no | ``--ir-ast-json``, ``--ir-optimized-ast-json`` | ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| EOF | ``eof`` | yes | ``--experimental-eof-version`` | ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| Non-mainnet EVMs | ``evm`` | yes | ``--evm-version `` | ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| Ethdebug | ``ethdebug`` | no | ``--ethdebug-resources``, ``--ethdebug-compilation``, ``--ethdebug-program``, ``--ethdebug-program-runtime``, ``--debug-info ethdebug`` | ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| | | no | ``--yul-cfg-json`` | +| SSA CFG + ``ssa-cfg`` +------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ +| | | yes | ``--via-ssa-cfg`` | ++-----------------------+--------------------------+------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ diff --git a/docs/yul.rst b/docs/yul.rst index 3cf2785fc4..5c8086b001 100644 --- a/docs/yul.rst +++ b/docs/yul.rst @@ -752,8 +752,8 @@ This document does not want to be a full description of the Ethereum virtual mac Please refer to a different document if you are interested in the precise semantics. Opcodes marked with ``-`` do not return a result and all others return exactly one value. -Opcodes marked with ``F``, ``H``, ``B``, ``C``, ``I``, ``L``, ``P`` and ``N`` are present since Frontier, -Homestead, Byzantium, Constantinople, Istanbul, London, Paris or Cancun respectively. +Opcodes marked with ``F``, ``H``, ``B``, ``C``, ``I``, ``L``, ``P``, ``N`` and ``O`` are present since +Frontier, Homestead, Byzantium, Constantinople, Istanbul, London, Paris, Cancun or Osaka respectively. In the following, ``mem[a...b)`` signifies the bytes of memory starting at position ``a`` up to but not including position ``b``, ``storage[p]`` signifies the storage contents at slot ``p``, and @@ -812,6 +812,8 @@ the ``dup`` and ``swap`` instructions as well as ``jump`` instructions, labels a +-------------------------+-----+---+-----------------------------------------------------------------+ | sar(x, y) | | C | signed arithmetic shift right y by x bits | +-------------------------+-----+---+-----------------------------------------------------------------+ +| clz(x) | | O | number of leading zero bits of x, 256 if x == 0 | ++-------------------------+-----+---+-----------------------------------------------------------------+ | addmod(x, y, m) | | F | (x + y) % m with arbitrary precision arithmetic, 0 if m == 0 | +-------------------------+-----+---+-----------------------------------------------------------------+ | mulmod(x, y, m) | | F | (x * y) % m with arbitrary precision arithmetic, 0 if m == 0 | @@ -820,8 +822,6 @@ the ``dup`` and ``swap`` instructions as well as ``jump`` instructions, labels a +-------------------------+-----+---+-----------------------------------------------------------------+ | keccak256(p, n) | | F | keccak(mem[p...(p+n))) | +-------------------------+-----+---+-----------------------------------------------------------------+ -| pc() | | F | current position in code | -+-------------------------+-----+---+-----------------------------------------------------------------+ | pop(x) | `-` | F | discard value x | +-------------------------+-----+---+-----------------------------------------------------------------+ | mload(p) | | F | mem[p...(p+32)) | @@ -934,7 +934,8 @@ the ``dup`` and ``swap`` instructions as well as ``jump`` instructions, labels a +-------------------------+-----+---+-----------------------------------------------------------------+ | blockhash(b) | | F | hash of block nr b - only for last 256 blocks excluding current | +-------------------------+-----+---+-----------------------------------------------------------------+ -| blobhash(i) | | N | versioned hash of transaction's i-th blob | +| blobhash(i) | | N | versioned hash of transaction's i-th blob, 0 if blob does not | +| | | | exist | +-------------------------+-----+---+-----------------------------------------------------------------+ | coinbase() | | F | current mining beneficiary | +-------------------------+-----+---+-----------------------------------------------------------------+ @@ -1070,7 +1071,7 @@ by two, without the optimizer touching the constant two, you can use let double := verbatim_1i_1o(hex"600202", x) This code will result in a ``dup1`` opcode to retrieve ``x`` -(the optimizer might directly re-use result of the +(the optimizer might directly reuse result of the ``calldataload`` opcode, though) directly followed by ``600202``. The code is assumed to consume the copied value of ``x`` and produce the result @@ -1095,7 +1096,8 @@ the compiler. Violations of these restrictions can result in undefined behavior. - Control-flow should not jump into or out of verbatim blocks, - but it can jump within the same verbatim block. + but it can jump within the same verbatim block. In particular, + reverting or returning from the block is *not* allowed. - Stack contents apart from the input and output parameters should not be accessed. - The stack height difference should be exactly ``m - n``