├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE.md ├── Makefile ├── README.md ├── abi-spec.rst ├── assembly.rst ├── bugs.json ├── bugs.rst ├── bugs_by_version.json ├── common-patterns.rst ├── conf.py ├── contracts.rst ├── contributing.rst ├── control-structures.rst ├── frequently-asked-questions.rst ├── grammar.txt ├── index.rst ├── installing-solidity.rst ├── introduction-to-smart-contracts.rst ├── layout-of-source-files.rst ├── logo.svg ├── make.bat ├── miscellaneous.rst ├── security-considerations.rst ├── solidity-by-example.rst ├── solidity-in-depth.rst ├── structure-of-a-contract.rst ├── style-guide.rst ├── types.rst ├── units-and-global-variables.rst ├── using-the-compiler.rst └── utils └── SolidityLexer.py /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | os: linux 4 | dist: trusty 5 | sudo: required 6 | before_install: 7 | - sudo apt-get -y install python-sphinx 8 | 9 | git: 10 | depth: 2 11 | 12 | script: 13 | - sphinx-build -nW -b html -d _build/doctrees . _build/html -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contribuciones 2 | Para editar un fichero, primero entra en la pestaña "Pull requests" para comprobar que no está siendo traducido por otra persona. 3 | 4 | Para mejor organización, sólo debe traducirse un fichero por Pull request. 5 | 6 | ### Qué traducir 7 | Este documento pretende ser una versión en español de la documentación original, de modo que lo que se escriba aquí debe ser un reflejo de lo que haya en la versión en inglés. Esto quiere decir que si crees que falta algo por documentar o puedes mejorar la documentación (que no traducción), el proceso que debes seguir es proponerlo primero en la versión en inglés y, una vez aceptado allí, reflejar aquí la versión en español. 8 | 9 | Los documentos que se deben traducir son los **documentos .rst**. Dentro de estos, se debe traducir **el texto y los comentarios del código**. Los nombres de los contratos, variables y demás no deben ser traducidos. 10 | 11 | Ahora mismo se encuentra en periodo de actualización, puedes ver los cambios a realizar en el siguiente gist: https://gist.github.com/chriseth/5e06fb08433a03d1e4c05224f4287264 12 | 13 | ### Estilo 14 | Algunas cosas a tener en cuenta cuando se traduzca un documento: 15 | * El código, nombres de funciones y variables no se traducen (los comentarios sí). 16 | * Palabras que pese a estar en inglés sean de uso común en español no se traducen (ej: blockchain, timestamp, etc.) 17 | * Los asteriscos (\*), signos de igual (=), almohadillas (#), guiones (-), etc. que acompañen a títulos, deberán extender su longitud a la longitud del título. Ejemplo: 18 | ~~~ 19 | ************ 20 | Título corto 21 | ************ 22 | 23 | Títular más largo 24 | ================= 25 | ~~~ 26 | * En inglés, existe la norma de empezar la primera letra de cada palabra "importante" de un título en mayúscula. En español esta norma no existe, así que mejor empezar con mayúscula sólo la primera letra (y nombres propios y demás). 27 | * Las rutas de enlaces del siguiente estilo no se traducen: 28 | ~~~ 29 | -.. _structure-state-variables: 30 | ~~~ 31 | * En los enlaces a las rutas del apartado anterior, se traduce el nombre del enlace, no la ruta. Ejemplo: 32 | ~~~ 33 | :ref:`variables de estado ` 34 | ~~~ 35 | 36 | ### Etiquetas 37 | * work in progress: ya hay alguien trabajando en el fichero. 38 | * needs review: el fichero ya ha sido traducido, necesita al menos una revisión de una persona distinta al traductor para incorporarlo al repositorio final. 39 | * open: el fichero estaba siendo traducido por alguien, pero esa persona está inactiva. Puedes continuar con la traducción a partir de donde lo dejó el anterior. 40 | 41 | ### Pasos para editar 42 | Elige el fichero que quieras traducir y haz click en el logo del lapicero de arriba a la derecha, en donde pone "Edit this file": 43 | ![](http://i.imgur.com/B6jRrsZ.png) 44 | 45 | Se abrirá un editor de texto online. Ahí puedes hacer los cambios que consideres necesarios: 46 | ![](http://i.imgur.com/RMrIMWW.png) 47 | 48 | En la pestaña "Preview changes" puedes ver cómo va quedando el resultado de los cambios realizados: 49 | ![](http://i.imgur.com/hUlAlcj.png) 50 | 51 | Cuando quieras guardar el fichero (recomiendo hacerlo al poco de empezar para que otros usuarios puedan ver que estás trabajando en el fichero), ve al botón verde de abajo, donde pone "Propose file change": 52 | ![](http://i.imgur.com/F24VZal.png) 53 | 54 | Esto te llevará a una nueva ventana donde puedes revisar los cambios realizados. Tras comprobar que todo es correcto, dale a "Create pull request" 2 veces (no hace falta cambiar el nombre del pull request): 55 | ![](http://i.imgur.com/CZrIxLK.png) 56 | 57 | ![](http://i.imgur.com/EmDXLd1.png) 58 | 59 | Ahora, si vas a la pestaña "Pull requests" puedes ver tu trabajo en curso junto con los de otras personas. Para ver el estado de tu edición, haz click en tu Pull request, y luego en la pestaña "Files changed". 60 | ![](http://i.imgur.com/TOymUt4.png) 61 | 62 | Si quieres continuar, desde "Files changes" haz click en editar el fichero como en el primer paso. Al acabar, haz click en el botón verde de abajo "Commit changes" como en la siguiente imagen: 63 | ![](http://i.imgur.com/mSu1fZK.png) 64 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " devhelp to make HTML files and a Devhelp project" 34 | @echo " epub to make an epub" 35 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 36 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 37 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 38 | @echo " text to make text files" 39 | @echo " man to make manual pages" 40 | @echo " texinfo to make Texinfo files" 41 | @echo " info to make Texinfo files and run them through makeinfo" 42 | @echo " gettext to make PO message catalogs" 43 | @echo " changes to make an overview of all changed/added/deprecated items" 44 | @echo " xml to make Docutils-native XML files" 45 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 46 | @echo " linkcheck to check all external links for integrity" 47 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 48 | 49 | clean: 50 | rm -rf $(BUILDDIR)/* 51 | 52 | html: 53 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 54 | @echo 55 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 56 | 57 | dirhtml: 58 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 59 | @echo 60 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 61 | 62 | singlehtml: 63 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 64 | @echo 65 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 66 | 67 | pickle: 68 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 69 | @echo 70 | @echo "Build finished; now you can process the pickle files." 71 | 72 | json: 73 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 74 | @echo 75 | @echo "Build finished; now you can process the JSON files." 76 | 77 | htmlhelp: 78 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 79 | @echo 80 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 81 | ".hhp project file in $(BUILDDIR)/htmlhelp." 82 | 83 | qthelp: 84 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 85 | @echo 86 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 87 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 88 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Solidity.qhcp" 89 | @echo "To view the help file:" 90 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Solidity.qhc" 91 | 92 | devhelp: 93 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 94 | @echo 95 | @echo "Build finished." 96 | @echo "To view the help file:" 97 | @echo "# mkdir -p $$HOME/.local/share/devhelp/Solidity" 98 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Solidity" 99 | @echo "# devhelp" 100 | 101 | epub: 102 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 103 | @echo 104 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 105 | 106 | latex: 107 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 108 | @echo 109 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 110 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 111 | "(use \`make latexpdf' here to do that automatically)." 112 | 113 | latexpdf: 114 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 115 | @echo "Running LaTeX files through pdflatex..." 116 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 117 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 118 | 119 | latexpdfja: 120 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 121 | @echo "Running LaTeX files through platex and dvipdfmx..." 122 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 123 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 124 | 125 | text: 126 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 127 | @echo 128 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 129 | 130 | man: 131 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 132 | @echo 133 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 134 | 135 | texinfo: 136 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 137 | @echo 138 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 139 | @echo "Run \`make' in that directory to run these through makeinfo" \ 140 | "(use \`make info' here to do that automatically)." 141 | 142 | info: 143 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 144 | @echo "Running Texinfo files through makeinfo..." 145 | make -C $(BUILDDIR)/texinfo info 146 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 147 | 148 | gettext: 149 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 150 | @echo 151 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 152 | 153 | changes: 154 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 155 | @echo 156 | @echo "The overview file is in $(BUILDDIR)/changes." 157 | 158 | linkcheck: 159 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 160 | @echo 161 | @echo "Link check complete; look for any errors in the above output " \ 162 | "or in $(BUILDDIR)/linkcheck/output.txt." 163 | 164 | doctest: 165 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 166 | @echo "Testing of doctests in the sources finished, look at the " \ 167 | "results in $(BUILDDIR)/doctest/output.txt." 168 | 169 | xml: 170 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 171 | @echo 172 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 173 | 174 | pseudoxml: 175 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 176 | @echo 177 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 178 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Documentación de Solidity en español 2 | Repositorio para traducir la [documentación oficial de Solidity (en inglés)](https://github.com/ethereum/solidity) al español. 3 | 4 | Para consultar la documentación en español: https://solidity-es.readthedocs.io/es/latest/index.html 5 | 6 | ## Versión 7 | Este repositorio es una copia de la documentación de Solidity con último commit: [26ea9ce07cf85849cd881465a4322f14bff87eb8](https://github.com/ethereum/solidity/tree/26ea9ce07cf85849cd881465a4322f14bff87eb8) 8 | 9 | Actualmente está actualizándose al commit: [a6b52fdc34650c74597c1bcdc5075b6375c62650](https://github.com/ethereum/solidity/tree/a6b52fdc34650c74597c1bcdc5075b6375c62650) 10 | 11 | ## Contribuciones 12 | Por favor, lee primero la [guía sobre cómo contribuir](https://github.com/AdrianClv/solidity-docs-es/blob/master/CONTRIBUTING.md). 13 | 14 | Si tienes cualquier duda o sugerencia, no dudes en escribir. Solemos coordinarnos mediante un canal de Slack, ¡serás bienvenido! 15 | -------------------------------------------------------------------------------- /abi-spec.rst: -------------------------------------------------------------------------------- 1 | .. index:: abi, application binary interface 2 | 3 | .. _ABI: 4 | 5 | ********************************************** 6 | Especificación de Application Binary Interface 7 | ********************************************** 8 | 9 | Diseño básico 10 | ============= 11 | 12 | La Application Binary Interface (Interfaz Binaria de Aplicación) o ABI es el modo estándar de interactuar con contratos en el ecosistema Ethereum, tanto desde fuera de la blockchain como en interacciones contrato-contrato. Los datos se codifican siguiendo su tipo acorde a esta especificación. 13 | 14 | Asumimos que la Application Binary Interface (ABI) está fuertemente tipada, es conocida en tiempo de compilación y es estática. No se van a proveer mecanismos de introspección. Además, afirmamos que los contratos tendrán las definiciones de la interfaz de cada contrato que vayan a llamar en tiempo de compilación. 15 | 16 | Esta especificación no abarca los contratos cuya interfaz sea dinámica o conocida exclusivamente en tiempo de ejecución. Estos casos, de volverse importantes, podrían manejarse adecuadamente como servicios construidos dentro del ecosistema Ethereum. 17 | 18 | Función Selector 19 | ================ 20 | 21 | Los primeros cuatro bytes de los datos de una llamada a una función especifican la función a llamar. Se trata de los primeros (los más a la izquierda, los más extremos por orden) cuatro bytes del hash Keccak (SHA-3) de la firma de la función. La firma se define como la expresión canónica del prototipo básico como puede ser el nombre de la función con la lista de parámetros entre paréntesis. Los tipos de parámetros se separan por comas, no por espacios. 22 | 23 | Codificación de argumentos 24 | ========================== 25 | 26 | A partir del quinto byte, prosiguen los argumentos codificados. Esta codificación es también usada en otros sitios, por ejemplo, en los valores de retorno y también en los argumentos de eventos, sin los cuatro bytes especificando la función. 27 | 28 | Tipos 29 | ===== 30 | 31 | Los tipos elementales existentes son: 32 | 33 | - `uint`: enteros sin signo de `M` bits, `0 < M <= 256`, `M % 8 == 0`. Ejemplos: `uint32`, `uint8`, `uint256`. 34 | 35 | - `int`: enteros con signo complemento a dos de `M` bits, `0 < M <= 256`, `M % 8 == 0`. 36 | 37 | - `address`: equivalente a `uint160`, exceptuando la interpretación asumida y la tipología del lenguaje. 38 | 39 | - `uint`, `int`: sinónimos de `uint256`, `int256` respectivamente (no para ser usados para computar la función selector). 40 | 41 | - `bool`: equivalente a `uint8` restringido a los valores 0 y 1. 42 | 43 | - `fixedx`: número decimal con signo y formato decimal fijo de `M` bits, `0 < M <= 256`, `M % 8 ==0`, y `0 < N <= 80`, que denota el valor `v` como `v / (10 ** N)`. 44 | 45 | - `ufixedx`: variante sin signo de `fixedx`. 46 | 47 | - `fixed`, `ufixed`: sinónimos de `fixed128x19`, `ufixed128x19` respectivamente (no para ser usados para computar la función selector). 48 | 49 | - `bytes`: tipo binario de `M` bytes, `0 < M <= 32`. 50 | 51 | - `function`: equivalente a `bytes24`: un address, seguido de la función selector 52 | 53 | El siguiente array, de tipo fijo, existente es: 54 | 55 | - `[M]`: un array de longitud fija del tipo de longitud fija dada. 56 | 57 | Los siguientes tipos de tamaño no fijo existentes son: 58 | 59 | - `bytes`: secuencia de bytes de tamaño dinámico. 60 | 61 | - `string`: string unicode de tamaño dinámico codificado como UTF-8. 62 | 63 | - `[]`: array de longitud variable del tipo de longitud fija dada. 64 | 65 | Los distintos tipos se pueden combinar en structs anónimos cerrando un número finito no negativo de ellos entre paréntesis, separados por comas: 66 | 67 | - `(T1,T2,...,Tn)`: struct anónimo (tupla ordenada) consistente de los tipos `T1`, ..., `Tn`, `n >= 0` 68 | 69 | Es posible formar structs de structs, arrays de structs, etc. 70 | 71 | 72 | Especificación formal de la codificación 73 | ======================================== 74 | 75 | Vamos a especificar formalmente la codificación, de tal forma que tendrá las siguientes propiedades, que son especialmente útiles si los argumentos son arrays anidados: 76 | 77 | Propiedades: 78 | 79 | 1. El número de lecturas necesarias para acceder a un valor es, como mucho, equivalente a la máxima profundidad del array. Por ejemplo, cuatro lecturas se requieren para obtener `a_i[k][l][r]`. En una versión previa de la ABI, el número de lecturas escalaba linealmente con el número total de parámetros dinámicos en el peor caso. 80 | 81 | 2. Los datos de una variable o elemento de un array no se intercalan con otros datos y son recolocables. Por ejemplo, sólo usan "addresses" relativos. 82 | 83 | Distinguimos entre tipos estáticos y dinámicos. Los estáticos se codifican insitu y los dinámicos se codifican en una posición asignada separadamente después del bloque actual. 84 | 85 | **Definición:** Los siguientes tipos se llaman "dinámicos": 86 | * `bytes` 87 | * `string` 88 | * `T[]` para cada `T` 89 | * `T[k]` para cualquier dinámico `T` y todo `k > 0` 90 | 91 | Todo el resto de tipos son "estáticos". 92 | 93 | **Definición:** `len(a)` es el número de bytes en un string binario `a`. 94 | El tipo de `len(a)` se presume como `uint256`. 95 | 96 | Definimos `enc`, la codificación actual, como un mapping de valores de tipos de la ABI a string binarios como `len(enc(X))` depende del valor de `X` si y solo si el tipo de `X` es dinámico. 97 | 98 | **Definición:** Para cada valor de ABI `X`, definimos recursivamente `enc(X)`, dependiendo del tipo de `X` siendo 99 | 100 | - `(T1,...,Tk)` para `k >= 0` y cualquier tipo `T1`, ..., `Tk` 101 | 102 | `enc(X) = head(X(1)) ... head(X(k-1)) tail(X(0)) ... tail(X(k-1))` 103 | 104 | donde `X(i)` es el `ith` componente del valor, y 105 | `head` y `tail` son definidos por `Ti` siendo un tipo estático como 106 | 107 | `head(X(i)) = enc(X(i))` y `tail(X(i)) = ""` (el string vacío) 108 | 109 | y como 110 | 111 | `head(X(i)) = enc(len(head(X(0)) ... head(X(k-1)) tail(X(0)) ... tail(X(i-1))))` 112 | `tail(X(i)) = enc(X(i))` 113 | 114 | en otros casos como si, por ejemplo, `Ti` es un tipo dinámico. 115 | 116 | Hay que tener en cuenta que en el caso dinámico, `head(X(i))` está bien definido ya que las longitudes de las partes de head sólo dependen de los tipos y no de los valores. Su valor es el offset del principio de `tail(X(i))` relativo al comienzo de `enc(X)`. 117 | 118 | - `T[k]` para cada `T` y `k`: 119 | 120 | `enc(X) = enc((X[0], ..., X[k-1]))` 121 | 122 | como ejemplo, es codificado como si fuera un struct anónimo de `k` elementos del mismo tipo. 123 | 124 | - `T[]` donde `X` tiene `k` elementos (`k` se presume que es del tipo `uint256`): 125 | 126 | `enc(X) = enc(k) enc([X[1], ..., X[k]])` 127 | 128 | Otro ejemplo codificado como si fuera un array estático de tamaño `k`, prefijado con el número de elementos. 129 | 130 | - `bytes`, de longitud `k` (que se presume que es del tipo `uint256`): 131 | 132 | `enc(X) = enc(k) pad_right(X)`. Por ejemplo, el número de bytes es codificado como un `uint256` seguido del valor actual de `X` como una secuencia de bytes, seguido por el número mínimo de bytes-cero como que `len(enc(X))` es un múltiplo de 32. 133 | 134 | - `string`: 135 | 136 | `enc(X) = enc(enc_utf8(X))`, en este caso `X` se codifica como utf-8 y su valor se interpreta como de tipo `bytes` y codificado posteriormente. Hay que tener en cuenta que la longitud usada en la subsecuente codificación es el número de bytes del string codificado como utf-8, no su número de caracteres. 137 | 138 | - `uint`: `enc(X)` es el mayor extremo de la codificación de `X`, rellenado en el lado de orden mayor (izquierda) con bytes cero de tal forma que la longitud acabe siendo de 32 bytes. 139 | - `address`: como en el caso de `uint160` 140 | - `int`: `enc(X)` es el complemento a dos de mayor extremo en la codificación de `X`, rellenado en el lado de mayor orden (izquierda) con `0xff` para `X` negativo y bytes cero para `X` positivo de tal forma que la longitud final sea un múltiplo de 32 bytes. 141 | - `bool`: como en el caso de `uint8`, donde `1` se usa para `true` y `0` para `false` 142 | - `fixedx`: `enc(X)` es `enc(X * 10**N)` donde `X * 10**N` se interpreta como un `int256`. 143 | - `fixed`: como en el caso de `fixed128x19` 144 | - `ufixedx`: `enc(X)` es `enc(X * 10**N)` donde `X * 10**N` se interpreta como un `uint256`. 145 | - `ufixed`: como en el caso de `ufixed128x19` 146 | - `bytes`: `enc(X)` es la secuencia de bytes en `X` rellenado con bytes cero hasta una longitud de 32. 147 | 148 | Resaltar que para cada `X`, `len(enc(X))` es un múltiplo de 32. 149 | 150 | Función Selector y codificación de argumentos 151 | ============================================= 152 | 153 | Siempre, una llamada a la función `f` con parámetros `a_1, ..., a_n` se codifican como 154 | 155 | `function_selector(f) enc((a_1, ..., a_n))` 156 | 157 | y los valores de retorno `v_1, ..., v_k` de `f` son codificados como 158 | 159 | `enc((v_1, ..., v_k))` 160 | 161 | p.ej.: los valores se combinan en struct anónimos y codificados. 162 | 163 | Ejemplos 164 | ======== 165 | 166 | Para el siguiente contrato: 167 | 168 | :: 169 | 170 | contract Foo { 171 | function bar(bytes3[2] xy) {} 172 | function baz(uint32 x, bool y) returns (bool r) { r = x > 32 || y; } 173 | function sam(bytes name, bool z, uint[] data) {} 174 | } 175 | 176 | 177 | Para nuestro ejemplo `Foo`, si queremos llamar a `baz` pasando como parámetros `69` y `true`, emplearíamos 68 bytes en total, que se podrían dividir en las siguientes partes: 178 | 179 | - `0xcdcd77c0`: el ID del método. Se deriva como los 4 primeros bytes del hash Keccak en ASCII de la firma `baz(uint32,bool)`. 180 | - `0x0000000000000000000000000000000000000000000000000000000000000045`: el primer parámetro, un uint32 de valor `69` rellenado hasta 32 bytes 181 | - `0x0000000000000000000000000000000000000000000000000000000000000001`: el segundo parámetro - boolean `true`, rellenado hasta 32 bytes 182 | 183 | En total:: 184 | 185 | 0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001 186 | 187 | Devuelve un `bool` simple. Si, por ejemplo, devolviese `false`, su salida sería un array de byte sencillo `0x0000000000000000000000000000000000000000000000000000000000000000`, un único bool. 188 | 189 | Si quisiéramos llamar a `bar` con el argumento `["abc", "def"]`, pasaríamos 68 bytes en total, divido en: 190 | 191 | - `0xfce353f6`: el ID del método. Este se deriva de la firma `bar(bytes3[2])`. 192 | - `0x6162630000000000000000000000000000000000000000000000000000000000`: La primera parte del primer parámetro, un valor `bytes3` `"abc"` (alineado a la izquierda). 193 | - `0x6465660000000000000000000000000000000000000000000000000000000000`: La segunda parte del primer parámetro, un valor `bytes3` `"def"` (alineado a la izquierda). 194 | 195 | En total:: 196 | 197 | 0xfce353f661626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000 198 | 199 | Si quisiéramos llamar a `sam` con los argumentos `"dave"`, `true` y `[1,2,3]`, pasaríamos 292 bytes en total, dividido en: 200 | - `0xa5643bf2`: el ID del método. Este se deriva de la firma `sam(bytes,bool,uint256[])`. Aquí `uint` se reemplaza por su representación canónica `uint256`. 201 | - `0x0000000000000000000000000000000000000000000000000000000000000060`: La localización de la parte de datos del primer parámetro (tipo dinámico), medido en bytes desde el principio del bloque de argumentos. En este caso, `0x60`. 202 | - `0x0000000000000000000000000000000000000000000000000000000000000001`: el segundo parámetro: boolean verdadero. 203 | - `0x00000000000000000000000000000000000000000000000000000000000000a0`: La localización de la parte de datos del tercer parámetro (tipo dinámico), medido en bytes. En este caso, `0xa0`. 204 | - `0x0000000000000000000000000000000000000000000000000000000000000004`: La parte de datos del primer argumento, comienza con la longitud del array de bytes en elementos, en este caso, 4. 205 | - `0x6461766500000000000000000000000000000000000000000000000000000000`: Los contenidos del primer argumento: el UTF-8 (equivalente a ASCII en este caso) codificación de `"dave"`, rellenado hasta 32 bytes por la derecha. 206 | - `0x0000000000000000000000000000000000000000000000000000000000000003`: La parte de datos del tercer argumento, comenzando con la longitud del array en elementos, en este caso, 3. 207 | - `0x0000000000000000000000000000000000000000000000000000000000000001`: la primera entrada del tercer parámetro. 208 | - `0x0000000000000000000000000000000000000000000000000000000000000002`: la segunda entrada del tercer parámetro. 209 | - `0x0000000000000000000000000000000000000000000000000000000000000003`: la tercera entrada del tercer parámetro. 210 | 211 | En total:: 212 | 213 | 0xa5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003 214 | 215 | Uso de tipos dinámicos 216 | ====================== 217 | 218 | Una llamada a una función con la firma `f(uint,uint32[],bytes10,bytes)` con valores `(0x123, [0x456, 0x789], "1234567890", "Hello, world!")` se codifica de la siguiente manera: 219 | 220 | Obtenemos los primeros cuatro bytes de `sha3("f(uint256,uint32[],bytes10,bytes)")`, p.ej.: `0x8be65246`. 221 | Entonces codificamos las cabeceras de los cuatro argumentos. Para los tipos estáticos `uint256` y `bytes10`, estos son los valores que queremos pasar directamente, mientras que para los tipos dinámicos `uint32[]` y `bytes`, usamos el offset en bytes hasta el inicio de su área de datos, contando desde el comienzo de la codificación del valor (p.ej.: sin contar los primeros cuatro bytes que contienen el hash de la firma de la función). Estos son: 222 | 223 | - `0x0000000000000000000000000000000000000000000000000000000000000123` (`0x123` rellenado hasta 32 bytes) 224 | - `0x0000000000000000000000000000000000000000000000000000000000000080` (offset del inicio de la parte de datos del segundo parámetro, 4*32 bytes, exactamente el tamaño de la parte de la cabecera) 225 | - `0x3132333435363738393000000000000000000000000000000000000000000000` (`"1234567890"` rellenado hasta 32 bytes por la derecha) 226 | - `0x00000000000000000000000000000000000000000000000000000000000000e0` (offset del comienzo de la parte de datos del cuarto parámetro = offset del inicio de la parte de datos del primer parámetro dinámico + tamaño de la parte de datos del primer parámetro dinámico = 4\*32 + 3\*32 (ver abajo)) 227 | 228 | Después de esto, la parte de datos del primer argumento dinámico, `[0x456, 0x789]` sigue así: 229 | 230 | - `0x0000000000000000000000000000000000000000000000000000000000000002` (número de elementos del array, 2) 231 | - `0x0000000000000000000000000000000000000000000000000000000000000456` (primer elemento) 232 | - `0x0000000000000000000000000000000000000000000000000000000000000789` (segundo elemento) 233 | 234 | Finalmente, codificamos la parte de datos del segundo argumento dinámico, `"Hello, world!"`: 235 | 236 | - `0x000000000000000000000000000000000000000000000000000000000000000d` (número de elementos (bytes en este caso): 13) 237 | - `0x48656c6c6f2c20776f726c642100000000000000000000000000000000000000` (`"Hello, world!"` rellenado hasta 32 bytes por la derecha) 238 | 239 | Todo junto, la codificación es (nueva línea después de la función selector y cada 32-bytes por claridad): 240 | 241 | :: 242 | 243 | 0x8be65246 244 | 0000000000000000000000000000000000000000000000000000000000000123 245 | 0000000000000000000000000000000000000000000000000000000000000080 246 | 3132333435363738393000000000000000000000000000000000000000000000 247 | 00000000000000000000000000000000000000000000000000000000000000e0 248 | 0000000000000000000000000000000000000000000000000000000000000002 249 | 0000000000000000000000000000000000000000000000000000000000000456 250 | 0000000000000000000000000000000000000000000000000000000000000789 251 | 000000000000000000000000000000000000000000000000000000000000000d 252 | 48656c6c6f2c20776f726c642100000000000000000000000000000000000000 253 | 254 | Eventos 255 | ======= 256 | 257 | Los eventos son una abstracción del protocolo de monitorización de eventos de Ethereum. Las entradas de log proveen la dirección del contrato, una cadena de máximo cuatro tópicos y algún dato binario de longitud arbitraria. Los eventos apalancan la función ABI existente para poder interpretarla (junto con una especificación de interfaz) como una estructura apropiada. 258 | 259 | Dado un nombre de evento y una serie de parámetros de evento, los separamos en dos sub-series: los que están indexados y los que no. Los indexados, cuyo número podría llegar hasta tres, se usan junto al hash Keccack de la firma del evento para formar los tópicos de la entrada de log. Los no indexados forman el array de bytes del evento. 260 | 261 | En efecto, una entrada de log que usa esta ABI se define como: 262 | 263 | - `address`: la dirección del contrato (intrínsecamente provista por Ethereum); 264 | - `topics[0]`: `keccak(EVENT_NAME+"("+EVENT_ARGS.map(canonical_type_of).join(",")+")")` (`canonical_type_of` es una función que simplemente devuelve el tipo canónico del argumento dado, p.ej.: para `uint indexed foo`, devolvería `uint256`). Si el evento se declara como `anonymous` no se genera `topics[0]`; 265 | - `topics[n]`: `EVENT_INDEXED_ARGS[n - 1]` (`EVENT_INDEXED_ARGS` es la serie de `EVENT_ARGS` que están indexados); 266 | - `data`: `abi_serialise(EVENT_NON_INDEXED_ARGS)` (`EVENT_NON_INDEXED_ARGS` es la serie de `EVENT_ARGS` que no están indexados, `abi_serialise` es la función de serialización ABI usada para devolver una serie de valores tipificados desde una función, como se detalla abajo). 267 | 268 | JSON 269 | ==== 270 | 271 | El formato JSON para la interfaz de un contrato viene dada por un array de descripciones de función y/o evento. Una descripción de función es un objeto JSON con los siguientes campos: 272 | 273 | - `type`: `"function"`, `"constructor"`, o `"fallback"` (el :ref:`función sin nombre "default" `); 274 | - `name`: nombre de la función; 275 | - `inputs`: array de objetos, cada uno contiene: 276 | * `name`: nombre del parámetro; 277 | * `type`: tipo canónico del parámetro. 278 | - `outputs`: un array de objetos similar a `inputs`, puede omitirse si la función no devuelve nada; 279 | - `constant`: `true` si la función es :ref:`especificada para no modificar el estado de la blockchain `); 280 | - `payable`: `true` si la función acepta ether, por defecto a `false`. 281 | 282 | `type` se puede omitir, dejándolo por defecto a `"function"`. 283 | 284 | La función Constructor y fallback nunca tienen `name` o `outputs`. Fallback tampoco tiene `inputs`. 285 | 286 | Enviar una cantidad de ether no-nula a una función no payable lanzará excepción. No lo hagas. 287 | 288 | Una descripción de evento es un objeto JSON con prácticamente los mismos campos: 289 | 290 | - `type`: siempre `"event"` 291 | - `name`: nombre del evento; 292 | - `inputs`: array de objetos, cada uno contiene: 293 | * `name`: nombre del parámetro; 294 | * `type`: tipo canónico del parámetro. 295 | * `indexed`: `true` si el campo es parte de los tópicos del log, `false` si es parte del segmento de datos del log. 296 | - `anonymous`: `true` si el evento se declaró `anonymous`. 297 | 298 | Por ejemplo, 299 | 300 | :: 301 | 302 | contract Test { 303 | function Test(){ b = 0x12345678901234567890123456789012; } 304 | event Event(uint indexed a, bytes32 b) 305 | event Event2(uint indexed a, bytes32 b) 306 | function foo(uint a) { Event(a, b); } 307 | bytes32 b; 308 | } 309 | 310 | resultaría en el JSON: 311 | 312 | .. code:: json 313 | 314 | [{ 315 | "type":"event", 316 | "inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"bytes32","indexed":false}], 317 | "name":"Event" 318 | }, { 319 | "type":"event", 320 | "inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"bytes32","indexed":false}], 321 | "name":"Event2" 322 | }, { 323 | "type":"event", 324 | "inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"bytes32","indexed":false}], 325 | "name":"Event2" 326 | }, { 327 | "type":"function", 328 | "inputs": [{"name":"a","type":"uint256"}], 329 | "name":"foo", 330 | "outputs": [] 331 | }] 332 | -------------------------------------------------------------------------------- /bugs.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "ConstantOptimizerSubtraction", 4 | "summary": "In some situations, the optimizer replaces certain numbers in the code with routines that compute different numbers.", 5 | "description": "The optimizer tries to represent any number in the bytecode by routines that compute them with less gas. For some special numbers, an incorrect routine is generated. This could allow an attacker to e.g. trick victims about a specific amount of ether, or function calls to call different functions (or none at all).", 6 | "link": "https://blog.ethereum.org/2017/05/03/solidity-optimizer-bug/", 7 | "fixed": "0.4.11", 8 | "severity": "low", 9 | "conditions": { 10 | "optimizer": true 11 | } 12 | }, 13 | { 14 | "name": "IdentityPrecompileReturnIgnored", 15 | "summary": "Failure of the identity precompile was ignored.", 16 | "description": "Calls to the identity contract, which is used for copying memory, ignored its return value. On the public chain, calls to the identity precompile can be made in a way that they never fail, but this might be different on private chains.", 17 | "severity": "low", 18 | "fixed": "0.4.7" 19 | }, 20 | { 21 | "name": "OptimizerStateKnowledgeNotResetForJumpdest", 22 | "summary": "The optimizer did not properly reset its internal state at jump destinations, which could lead to data corruption.", 23 | "description": "The optimizer performs symbolic execution at certain stages. At jump destinations, multiple code paths join and thus it has to compute a common state from the incoming edges. Computing this common state was simplified to just use the empty state, but this implementation was not done properly. This bug can cause data corruption.", 24 | "severity": "medium", 25 | "introduced": "0.4.5", 26 | "fixed": "0.4.6", 27 | "conditions": { 28 | "optimizer": true 29 | } 30 | }, 31 | { 32 | "name": "HighOrderByteCleanStorage", 33 | "summary": "For short types, the high order bytes were not cleaned properly and could overwrite existing data.", 34 | "description": "Types shorter than 32 bytes are packed together into the same 32 byte storage slot, but storage writes always write 32 bytes. For some types, the higher order bytes were not cleaned properly, which made it sometimes possible to overwrite a variable in storage when writing to another one.", 35 | "link": "https://blog.ethereum.org/2016/11/01/security-alert-solidity-variables-can-overwritten-storage/", 36 | "severity": "high", 37 | "introduced": "0.1.6", 38 | "fixed": "0.4.4" 39 | }, 40 | { 41 | "name": "OptimizerStaleKnowledgeAboutSHA3", 42 | "summary": "The optimizer did not properly reset its knowledge about SHA3 operations resulting in some hashes (also used for storage variable positions) not being calculated correctly.", 43 | "description": "The optimizer performs symbolic execution in order to save re-evaluating expressions whose value is already known. This knowledge was not properly reset across control flow paths and thus the optimizer sometimes thought that the result of a SHA3 operation is already present on the stack. This could result in data corruption by accessing the wrong storage slot.", 44 | "severity": "medium", 45 | "fixed": "0.4.3", 46 | "conditions": { 47 | "optimizer": true 48 | } 49 | }, 50 | { 51 | "name": "LibrariesNotCallableFromPayableFunctions", 52 | "summary": "Library functions threw an exception when called from a call that received Ether.", 53 | "description": "Library functions are protected against sending them Ether through a call. Since the DELEGATECALL opcode forwards the information about how much Ether was sent with a call, the library function incorrectly assumed that Ether was sent to the library and threw an exception.", 54 | "severity": "low", 55 | "introduced": "0.4.0", 56 | "fixed": "0.4.2" 57 | }, 58 | { 59 | "name": "SendFailsForZeroEther", 60 | "summary": "The send function did not provide enough gas to the recipient if no Ether was sent with it.", 61 | "description": "The recipient of an Ether transfer automatically receives a certain amount of gas from the EVM to handle the transfer. In the case of a zero-transfer, this gas is not provided which causes the recipient to throw an exception.", 62 | "severity": "low", 63 | "fixed": "0.4.0" 64 | }, 65 | { 66 | "name": "DynamicAllocationInfiniteLoop", 67 | "summary": "Dynamic allocation of an empty memory array caused an infinite loop and thus an exception.", 68 | "description": "Memory arrays can be created provided a length. If this length is zero, code was generated that did not terminate and thus consumed all gas.", 69 | "severity": "low", 70 | "fixed": "0.3.6" 71 | }, 72 | { 73 | "name": "OptimizerClearStateOnCodePathJoin", 74 | "summary": "The optimizer did not properly reset its internal state at jump destinations, which could lead to data corruption.", 75 | "description": "The optimizer performs symbolic execution at certain stages. At jump destinations, multiple code paths join and thus it has to compute a common state from the incoming edges. Computing this common state was not done correctly. This bug can cause data corruption, but it is probably quite hard to use for targeted attacks.", 76 | "severity": "low", 77 | "fixed": "0.3.6", 78 | "conditions": { 79 | "optimizer": true 80 | } 81 | }, 82 | { 83 | "name": "CleanBytesHigherOrderBits", 84 | "summary": "The higher order bits of short bytesNN types were not cleaned before comparison.", 85 | "description": "Two variables of type bytesNN were considered different if their higher order bits, which are not part of the actual value, were different. An attacker might use this to reach seemingly unreachable code paths by providing incorrectly formatted input data.", 86 | "severity": "medium/high", 87 | "fixed": "0.3.3" 88 | }, 89 | { 90 | "name": "ArrayAccessCleanHigherOrderBits", 91 | "summary": "Access to array elements for arrays of types with less than 32 bytes did not correctly clean the higher order bits, causing corruption in other array elements.", 92 | "description": "Multiple elements of an array of values that are shorter than 17 bytes are packed into the same storage slot. Writing to a single element of such an array did not properly clean the higher order bytes and thus could lead to data corruption.", 93 | "severity": "medium/high", 94 | "fixed": "0.3.1" 95 | }, 96 | { 97 | "name": "AncientCompiler", 98 | "summary": "This compiler version is ancient and might contain several undocumented or undiscovered bugs.", 99 | "description": "The list of bugs is only kept for compiler versions starting from 0.3.0, so older versions might contain undocumented bugs.", 100 | "severity": "high", 101 | "fixed": "0.3.0" 102 | } 103 | ] -------------------------------------------------------------------------------- /bugs.rst: -------------------------------------------------------------------------------- 1 | .. index:: Bugs 2 | 3 | .. _known_bugs: 4 | 5 | ########################## 6 | Lista de errores conocidos 7 | ########################## 8 | 9 | Abajo encontrarás una lista en formato JSON de algunos de los errores de seguridad 10 | en el compilador Solidity. El archivo en sí está alojado en el `repositorio de Github 11 | `_. 12 | La lista comienza con la versión 0.3.0, y sólo los errores conocidos antes de esa versíon no 13 | están listados. 14 | 15 | Hay otro archivo llamado `bugs_by_version.json 16 | `_, 17 | que puede usarse para revisar qué errores afectan a una versión específica del compilador. 18 | 19 | Herramientas de verificación de código fuente y otras herramientas para contratos 20 | deben consultar esta lista con los siguientes criterios: 21 | 22 | - Es relativamente sospechoso que un contrato se haya compilado con una versión 23 | nightly y no con una release. Esta lista no mantiene un registro de las versiones 24 | nightly. 25 | - También es sospechoso cuando un contrato fue compilado con una versión que no era 26 | la más reciente en el momento que el contrato fue creado. Para contratos 27 | creados de otros contratos, tienes que seguir la cadena de creación de 28 | vuelta a una transacción y revisar la fecha de esa transacción. 29 | - Es muy sospechoso que un contrato haya sido compilado con un compilador que contiene 30 | un error conocido, y que se cree cuando una versión del compilador con una corrección 31 | ya haya sido publicada. 32 | 33 | El archivo JSON de errores conocidos es una lista de objetos, uno por cada error, 34 | con la siguiente información: 35 | 36 | nombre (name) 37 | Nombre único asignado al error 38 | resumen (summary) 39 | Pequeña descripción del error 40 | descripción (description) 41 | Descripción detallada del error 42 | enlace (link) 43 | URL de un sitio web con más información, opcional 44 | introducido (introduced) 45 | La primera versión del compilador que contiene ese error, opcional 46 | corregido (fixed) 47 | La primera versión del compilador que ya no contiene el error 48 | publicado (publish) 49 | La fecha en la cual el error se hizo públicamente conocido, opcional 50 | gravedad (severity) 51 | Gravedad del error: baja, media, alta. Considera la facilidad 52 | de ser detectado en tests de contratos, probabilidad de ocurrir 53 | y potencial daño. 54 | condiciones (conditions) 55 | Condiciones que tienen que cumplirse para iniciar el error. Actualmente 56 | es un objeto que puede contener un valor booleano ``optimizer``, que 57 | significa que el optimizador tiene que ser activado para reproducir el error. 58 | Si no se da ninguna condición, se da por hecho que el error está presente. 59 | 60 | .. literalinclude:: bugs.json 61 | :language: js 62 | -------------------------------------------------------------------------------- /bugs_by_version.json: -------------------------------------------------------------------------------- 1 | { 2 | "0.1.0": { 3 | "bugs": [ 4 | "ConstantOptimizerSubtraction", 5 | "IdentityPrecompileReturnIgnored", 6 | "OptimizerStaleKnowledgeAboutSHA3", 7 | "SendFailsForZeroEther", 8 | "DynamicAllocationInfiniteLoop", 9 | "OptimizerClearStateOnCodePathJoin", 10 | "CleanBytesHigherOrderBits", 11 | "ArrayAccessCleanHigherOrderBits", 12 | "AncientCompiler" 13 | ], 14 | "released": "2015-07-10" 15 | }, 16 | "0.1.1": { 17 | "bugs": [ 18 | "ConstantOptimizerSubtraction", 19 | "IdentityPrecompileReturnIgnored", 20 | "OptimizerStaleKnowledgeAboutSHA3", 21 | "SendFailsForZeroEther", 22 | "DynamicAllocationInfiniteLoop", 23 | "OptimizerClearStateOnCodePathJoin", 24 | "CleanBytesHigherOrderBits", 25 | "ArrayAccessCleanHigherOrderBits", 26 | "AncientCompiler" 27 | ], 28 | "released": "2015-08-04" 29 | }, 30 | "0.1.2": { 31 | "bugs": [ 32 | "ConstantOptimizerSubtraction", 33 | "IdentityPrecompileReturnIgnored", 34 | "OptimizerStaleKnowledgeAboutSHA3", 35 | "SendFailsForZeroEther", 36 | "DynamicAllocationInfiniteLoop", 37 | "OptimizerClearStateOnCodePathJoin", 38 | "CleanBytesHigherOrderBits", 39 | "ArrayAccessCleanHigherOrderBits", 40 | "AncientCompiler" 41 | ], 42 | "released": "2015-08-20" 43 | }, 44 | "0.1.3": { 45 | "bugs": [ 46 | "ConstantOptimizerSubtraction", 47 | "IdentityPrecompileReturnIgnored", 48 | "OptimizerStaleKnowledgeAboutSHA3", 49 | "SendFailsForZeroEther", 50 | "DynamicAllocationInfiniteLoop", 51 | "OptimizerClearStateOnCodePathJoin", 52 | "CleanBytesHigherOrderBits", 53 | "ArrayAccessCleanHigherOrderBits", 54 | "AncientCompiler" 55 | ], 56 | "released": "2015-09-25" 57 | }, 58 | "0.1.4": { 59 | "bugs": [ 60 | "ConstantOptimizerSubtraction", 61 | "IdentityPrecompileReturnIgnored", 62 | "OptimizerStaleKnowledgeAboutSHA3", 63 | "SendFailsForZeroEther", 64 | "DynamicAllocationInfiniteLoop", 65 | "OptimizerClearStateOnCodePathJoin", 66 | "CleanBytesHigherOrderBits", 67 | "ArrayAccessCleanHigherOrderBits", 68 | "AncientCompiler" 69 | ], 70 | "released": "2015-09-30" 71 | }, 72 | "0.1.5": { 73 | "bugs": [ 74 | "ConstantOptimizerSubtraction", 75 | "IdentityPrecompileReturnIgnored", 76 | "OptimizerStaleKnowledgeAboutSHA3", 77 | "SendFailsForZeroEther", 78 | "DynamicAllocationInfiniteLoop", 79 | "OptimizerClearStateOnCodePathJoin", 80 | "CleanBytesHigherOrderBits", 81 | "ArrayAccessCleanHigherOrderBits", 82 | "AncientCompiler" 83 | ], 84 | "released": "2015-10-07" 85 | }, 86 | "0.1.6": { 87 | "bugs": [ 88 | "ConstantOptimizerSubtraction", 89 | "IdentityPrecompileReturnIgnored", 90 | "HighOrderByteCleanStorage", 91 | "OptimizerStaleKnowledgeAboutSHA3", 92 | "SendFailsForZeroEther", 93 | "DynamicAllocationInfiniteLoop", 94 | "OptimizerClearStateOnCodePathJoin", 95 | "CleanBytesHigherOrderBits", 96 | "ArrayAccessCleanHigherOrderBits", 97 | "AncientCompiler" 98 | ], 99 | "released": "2015-10-16" 100 | }, 101 | "0.1.7": { 102 | "bugs": [ 103 | "ConstantOptimizerSubtraction", 104 | "IdentityPrecompileReturnIgnored", 105 | "HighOrderByteCleanStorage", 106 | "OptimizerStaleKnowledgeAboutSHA3", 107 | "SendFailsForZeroEther", 108 | "DynamicAllocationInfiniteLoop", 109 | "OptimizerClearStateOnCodePathJoin", 110 | "CleanBytesHigherOrderBits", 111 | "ArrayAccessCleanHigherOrderBits", 112 | "AncientCompiler" 113 | ], 114 | "released": "2015-11-17" 115 | }, 116 | "0.2.0": { 117 | "bugs": [ 118 | "ConstantOptimizerSubtraction", 119 | "IdentityPrecompileReturnIgnored", 120 | "HighOrderByteCleanStorage", 121 | "OptimizerStaleKnowledgeAboutSHA3", 122 | "SendFailsForZeroEther", 123 | "DynamicAllocationInfiniteLoop", 124 | "OptimizerClearStateOnCodePathJoin", 125 | "CleanBytesHigherOrderBits", 126 | "ArrayAccessCleanHigherOrderBits", 127 | "AncientCompiler" 128 | ], 129 | "released": "2015-12-02" 130 | }, 131 | "0.2.1": { 132 | "bugs": [ 133 | "ConstantOptimizerSubtraction", 134 | "IdentityPrecompileReturnIgnored", 135 | "HighOrderByteCleanStorage", 136 | "OptimizerStaleKnowledgeAboutSHA3", 137 | "SendFailsForZeroEther", 138 | "DynamicAllocationInfiniteLoop", 139 | "OptimizerClearStateOnCodePathJoin", 140 | "CleanBytesHigherOrderBits", 141 | "ArrayAccessCleanHigherOrderBits", 142 | "AncientCompiler" 143 | ], 144 | "released": "2016-01-30" 145 | }, 146 | "0.2.2": { 147 | "bugs": [ 148 | "ConstantOptimizerSubtraction", 149 | "IdentityPrecompileReturnIgnored", 150 | "HighOrderByteCleanStorage", 151 | "OptimizerStaleKnowledgeAboutSHA3", 152 | "SendFailsForZeroEther", 153 | "DynamicAllocationInfiniteLoop", 154 | "OptimizerClearStateOnCodePathJoin", 155 | "CleanBytesHigherOrderBits", 156 | "ArrayAccessCleanHigherOrderBits", 157 | "AncientCompiler" 158 | ], 159 | "released": "2016-02-17" 160 | }, 161 | "0.3.0": { 162 | "bugs": [ 163 | "ConstantOptimizerSubtraction", 164 | "IdentityPrecompileReturnIgnored", 165 | "HighOrderByteCleanStorage", 166 | "OptimizerStaleKnowledgeAboutSHA3", 167 | "SendFailsForZeroEther", 168 | "DynamicAllocationInfiniteLoop", 169 | "OptimizerClearStateOnCodePathJoin", 170 | "CleanBytesHigherOrderBits", 171 | "ArrayAccessCleanHigherOrderBits" 172 | ], 173 | "released": "2016-03-11" 174 | }, 175 | "0.3.1": { 176 | "bugs": [ 177 | "ConstantOptimizerSubtraction", 178 | "IdentityPrecompileReturnIgnored", 179 | "HighOrderByteCleanStorage", 180 | "OptimizerStaleKnowledgeAboutSHA3", 181 | "SendFailsForZeroEther", 182 | "DynamicAllocationInfiniteLoop", 183 | "OptimizerClearStateOnCodePathJoin", 184 | "CleanBytesHigherOrderBits" 185 | ], 186 | "released": "2016-03-31" 187 | }, 188 | "0.3.2": { 189 | "bugs": [ 190 | "ConstantOptimizerSubtraction", 191 | "IdentityPrecompileReturnIgnored", 192 | "HighOrderByteCleanStorage", 193 | "OptimizerStaleKnowledgeAboutSHA3", 194 | "SendFailsForZeroEther", 195 | "DynamicAllocationInfiniteLoop", 196 | "OptimizerClearStateOnCodePathJoin", 197 | "CleanBytesHigherOrderBits" 198 | ], 199 | "released": "2016-04-18" 200 | }, 201 | "0.3.3": { 202 | "bugs": [ 203 | "ConstantOptimizerSubtraction", 204 | "IdentityPrecompileReturnIgnored", 205 | "HighOrderByteCleanStorage", 206 | "OptimizerStaleKnowledgeAboutSHA3", 207 | "SendFailsForZeroEther", 208 | "DynamicAllocationInfiniteLoop", 209 | "OptimizerClearStateOnCodePathJoin" 210 | ], 211 | "released": "2016-05-27" 212 | }, 213 | "0.3.4": { 214 | "bugs": [ 215 | "ConstantOptimizerSubtraction", 216 | "IdentityPrecompileReturnIgnored", 217 | "HighOrderByteCleanStorage", 218 | "OptimizerStaleKnowledgeAboutSHA3", 219 | "SendFailsForZeroEther", 220 | "DynamicAllocationInfiniteLoop", 221 | "OptimizerClearStateOnCodePathJoin" 222 | ], 223 | "released": "2016-05-31" 224 | }, 225 | "0.3.5": { 226 | "bugs": [ 227 | "ConstantOptimizerSubtraction", 228 | "IdentityPrecompileReturnIgnored", 229 | "HighOrderByteCleanStorage", 230 | "OptimizerStaleKnowledgeAboutSHA3", 231 | "SendFailsForZeroEther", 232 | "DynamicAllocationInfiniteLoop", 233 | "OptimizerClearStateOnCodePathJoin" 234 | ], 235 | "released": "2016-06-10" 236 | }, 237 | "0.3.6": { 238 | "bugs": [ 239 | "ConstantOptimizerSubtraction", 240 | "IdentityPrecompileReturnIgnored", 241 | "HighOrderByteCleanStorage", 242 | "OptimizerStaleKnowledgeAboutSHA3", 243 | "SendFailsForZeroEther" 244 | ], 245 | "released": "2016-08-10" 246 | }, 247 | "0.4.0": { 248 | "bugs": [ 249 | "ConstantOptimizerSubtraction", 250 | "IdentityPrecompileReturnIgnored", 251 | "HighOrderByteCleanStorage", 252 | "OptimizerStaleKnowledgeAboutSHA3", 253 | "LibrariesNotCallableFromPayableFunctions" 254 | ], 255 | "released": "2016-09-08" 256 | }, 257 | "0.4.1": { 258 | "bugs": [ 259 | "ConstantOptimizerSubtraction", 260 | "IdentityPrecompileReturnIgnored", 261 | "HighOrderByteCleanStorage", 262 | "OptimizerStaleKnowledgeAboutSHA3", 263 | "LibrariesNotCallableFromPayableFunctions" 264 | ], 265 | "released": "2016-09-09" 266 | }, 267 | "0.4.10": { 268 | "bugs": [ 269 | "ConstantOptimizerSubtraction" 270 | ], 271 | "released": "2017-03-15" 272 | }, 273 | "0.4.11": { 274 | "bugs": [], 275 | "released": "2017-05-03" 276 | }, 277 | "0.4.2": { 278 | "bugs": [ 279 | "ConstantOptimizerSubtraction", 280 | "IdentityPrecompileReturnIgnored", 281 | "HighOrderByteCleanStorage", 282 | "OptimizerStaleKnowledgeAboutSHA3" 283 | ], 284 | "released": "2016-09-17" 285 | }, 286 | "0.4.3": { 287 | "bugs": [ 288 | "ConstantOptimizerSubtraction", 289 | "IdentityPrecompileReturnIgnored", 290 | "HighOrderByteCleanStorage" 291 | ], 292 | "released": "2016-10-25" 293 | }, 294 | "0.4.4": { 295 | "bugs": [ 296 | "ConstantOptimizerSubtraction", 297 | "IdentityPrecompileReturnIgnored" 298 | ], 299 | "released": "2016-10-31" 300 | }, 301 | "0.4.5": { 302 | "bugs": [ 303 | "ConstantOptimizerSubtraction", 304 | "IdentityPrecompileReturnIgnored", 305 | "OptimizerStateKnowledgeNotResetForJumpdest" 306 | ], 307 | "released": "2016-11-21" 308 | }, 309 | "0.4.6": { 310 | "bugs": [ 311 | "ConstantOptimizerSubtraction", 312 | "IdentityPrecompileReturnIgnored" 313 | ], 314 | "released": "2016-11-22" 315 | }, 316 | "0.4.7": { 317 | "bugs": [ 318 | "ConstantOptimizerSubtraction" 319 | ], 320 | "released": "2016-12-15" 321 | }, 322 | "0.4.8": { 323 | "bugs": [ 324 | "ConstantOptimizerSubtraction" 325 | ], 326 | "released": "2017-01-13" 327 | }, 328 | "0.4.9": { 329 | "bugs": [ 330 | "ConstantOptimizerSubtraction" 331 | ], 332 | "released": "2017-01-31" 333 | } 334 | } -------------------------------------------------------------------------------- /common-patterns.rst: -------------------------------------------------------------------------------- 1 | ################ 2 | Patrones comunes 3 | ################ 4 | 5 | .. index:: withdrawal 6 | 7 | .. _withdrawal_pattern: 8 | 9 | ************************ 10 | Retirada desde contratos 11 | ************************ 12 | 13 | El método recomendado de envío de fondos después de una acción, 14 | es usando el patrón de retirada (withdrawal pattern). Aunque el método 15 | más intuitivo para enviar Ether tras una acción es 16 | llamar directamente a ``send``, esto no es recomendable ya que 17 | introduce un potencial riesgo de seguridad. Puedes leer más 18 | sobre esto en la página :ref:`security_considerations`. 19 | 20 | Este es un ejemplo del patrón de retirada en un 21 | contrato donde el objetivo es enviar la mayor cantidad de Ether 22 | al contrato a fin de convertirse en el más "adinerado", inspirado por 23 | `King of the Ether `_. 24 | 25 | En el siguiente contrato, si dejas de ser el más adinerado, 26 | recibes los fondos de la persona que te destronó. 27 | 28 | :: 29 | 30 | pragma solidity ^0.4.11; 31 | 32 | contract WithdrawalContract { 33 | address public richest; 34 | uint public mostSent; 35 | 36 | mapping (address => uint) pendingWithdrawals; 37 | 38 | function WithdrawalContract() public payable { 39 | richest = msg.sender; 40 | mostSent = msg.value; 41 | } 42 | 43 | function becomeRichest() public payable returns (bool) { 44 | if (msg.value > mostSent) { 45 | pendingWithdrawals[richest] += msg.value; 46 | richest = msg.sender; 47 | mostSent = msg.value; 48 | return true; 49 | } else { 50 | return false; 51 | } 52 | } 53 | 54 | function withdraw() public { 55 | uint amount = pendingWithdrawals[msg.sender]; 56 | // Acuérdate de poner a cero la cantidad a reembolsar antes 57 | // de enviarlo para evitar re-entrancy attacks 58 | pendingWithdrawals[msg.sender] = 0; 59 | msg.sender.transfer(amount); 60 | } 61 | } 62 | 63 | Esto en lugar del patrón más intuitivo de envío: 64 | 65 | :: 66 | 67 | pragma solidity ^0.4.11; 68 | 69 | contract SendContract { 70 | address public richest; 71 | uint public mostSent; 72 | 73 | function SendContract() public payable { 74 | richest = msg.sender; 75 | mostSent = msg.value; 76 | } 77 | 78 | function becomeRichest() public payable returns (bool) { 79 | if (msg.value > mostSent) { 80 | // Esta línea puede causar problemas (explicado abajo). 81 | richest.transfer(msg.value); 82 | richest = msg.sender; 83 | mostSent = msg.value; 84 | return true; 85 | } else { 86 | return false; 87 | } 88 | } 89 | } 90 | 91 | Nótese que, en este ejemplo, un atacante puede bloquear 92 | el contrato en un estado inútil haciendo que ``richest`` 93 | sea la dirección de un contrato que tiene una función fallback 94 | que falla (ej. usando ``revert()`` o simplemente consumiendo más de 95 | 2300 de gas). De esa forma, cuando se llama a ``transfer`` 96 | para enviar fondos al contrato "envenenado", fallará 97 | y también fallará la función ``becomeRichest``, bloqueando el 98 | contrario para siempre. 99 | 100 | Por el contrario, si usas el patrón "withdrawl" del primer ejemplo, 101 | el atacante sólo puede causar que su propio withdrawl falle y no 102 | el resto del contrato. 103 | 104 | .. index:: access;restricting 105 | 106 | *********************** 107 | Restringiendo el acceso 108 | *********************** 109 | 110 | Restringiendo el acceso (Restricting access) es un patrón común para contratos. 111 | Nótese que nunca se puede evitar que un humano o un ordenador 112 | lean el contenido de una transacción o el estado de un 113 | contrato. Lo puedes hacer un poco más difícil de leer usando 114 | criptografía, pero si tu contrato debe leer los datos, todos 115 | podrán leerlo. 116 | 117 | Puedes restringir el acceso de lectura al estado de tu contrato 118 | por **otros contratos**. Esto ocurre por defecto 119 | salvo que declares tus variables como ``public``. 120 | 121 | Además, puedes restringir quién puede hacer modificaciones 122 | al estado de tu contrato o quién puede llamar a las funciones. 123 | De eso se trata esta sección. 124 | 125 | .. index:: function;modifier 126 | 127 | El uso de **modificadores de funciones** 128 | hace estas restricciones altamente visibles. 129 | 130 | :: 131 | 132 | pragma solidity ^0.4.11; 133 | 134 | contract AccessRestriction { 135 | // Estas serán asignadas en la fase de 136 | // compilación, donde `msg.sender` es 137 | // la cuenta que crea este contrato. 138 | address public owner = msg.sender; 139 | uint public creationTime = now; 140 | 141 | // Los modificadores pueden usarse para 142 | // cambiar el cuerpo de una función. 143 | // Si se usa este modificador, agregará 144 | // un chequeo que sólo pasa si la 145 | // función se llama desde una cierta 146 | // dirección. 147 | modifier onlyBy(address _account) 148 | { 149 | require(msg.sender == _account); 150 | // ¡No olvides el "_;"! 151 | // Esto se reemplazará por el cuerpo 152 | // de la función cuando se use 153 | // el modificador 154 | _; 155 | } 156 | 157 | /// Hacer que `_newOwner` sea el nuevo owner de 158 | /// este contrato. 159 | function changeOwner(address _newOwner) 160 | public 161 | onlyBy(owner) 162 | { 163 | owner = _newOwner; 164 | } 165 | 166 | modifier onlyAfter(uint _time) { 167 | require(now >= _time); 168 | _; 169 | } 170 | 171 | /// Borra la información del dueño. 172 | /// Sólo puede llamarse 6 semanas 173 | /// después de que el contrato haya sido 174 | /// creado. 175 | function disown() 176 | public 177 | onlyBy(owner) 178 | onlyAfter(creationTime + 6 weeks) 179 | { 180 | delete owner; 181 | } 182 | 183 | // Este modificador requiere del pago de 184 | // una comisión asociada a la llamada 185 | // de una función. 186 | // Si el llamador envió demasiado, será 187 | // reembolsado, pero sólo después del cuerpo 188 | // de la función. 189 | // Esto era peligroso antes de la versión 190 | // 0.4.0 de Solidity, donde era posible 191 | // saltarse la parte después de `_;`. 192 | modifier costs(uint _amount) { 193 | require(msg.value >= _amount); 194 | _; 195 | if (msg.value > _amount) 196 | msg.sender.send(msg.value - _amount); 197 | } 198 | 199 | function forceOwnerChange(address _newOwner) 200 | public 201 | costs(200 ether) 202 | { 203 | owner = _newOwner; 204 | // sólo una condición de ejemplo 205 | if (uint(owner) & 0 == 1) 206 | // Esto no se hacía antes de Solidity 207 | // 0.4.0 208 | return; 209 | // reembolsar los fees excesivos 210 | } 211 | } 212 | 213 | Una manera más especializada de la forma en la que se puede 214 | reestringir el acceso a la llamada de funciones se verá en el 215 | próximo ejemplo. 216 | 217 | .. index:: state machine 218 | 219 | ****************** 220 | Máquina de estados 221 | ****************** 222 | 223 | Los contratos a menudo actúan como una máquina de estados, 224 | lo que significa que tienen ciertas **etapas** en donde se 225 | comportan de manera diferente o en donde distintas funciones 226 | pueden ser llamadas. Una llamada de función a menudo 227 | termina una etapa y pasa el contrato a la siguiente 228 | etapa (especialmente si el contrato modela la **interacción**). 229 | También es común que algunas etapas se alcancen 230 | automáticamente en cierto punto en el **tiempo**. 231 | 232 | Un ejemplo de esto es el contrato de subastas a ciegas 233 | que comienza en la etapa "aceptando pujas a ciegas", luego 234 | pasa a "revelando pujas" que es finalizado por 235 | "determinar resultado de la subasta". 236 | 237 | .. index:: function;modifier 238 | 239 | Los modificadores de funciones se pueden usar en esta 240 | situación para modelar los estados y evitar 241 | el uso incorrecto del contrato. 242 | 243 | Ejemplo 244 | ======= 245 | 246 | En el siguiente ejemplo, 247 | el modificador ``atStage`` asegura que la función 248 | sólo pueda ser llamada en una cierta etapa. 249 | 250 | El modificador ``timeTransitions`` gestiona las 251 | transiciones de etapas de forma automática en función 252 | del tiempo. Debe ser usado en todas las funciones. 253 | 254 | .. note:: 255 | **El orden de los modificadores importa**. 256 | Si atStage se combina 257 | con timesTransitions, asegúrate de que puedas 258 | mencionarlo después de éste, para que la nueva 259 | etapa sea tomada en cuenta. 260 | 261 | Finalmente, el modificador ``transitionNext`` puede 262 | ser usado para ir automáticamente a la próxima etapa 263 | cuando la función termine. 264 | 265 | .. note:: 266 | **El modificador puede ser omitido**. 267 | Esto sólo se aplica a Solidity antes de la versión 268 | 0.4.0: 269 | Puesto que los modificadores se aplican simplemente 270 | reemplazando código y no realizando una llamada a una función, 271 | el código del modificador transitionNext se puede omitir 272 | si la propia función usa return. Si es lo que quieres hacer, asegúrate 273 | de llamar manualmente a nextStage desde esas funciones. 274 | A partir de la versión 0.4.0, el código de los modificadores 275 | se ejecutará incluso en el caso de que la función 276 | ejecute explícitamente un return. 277 | 278 | :: 279 | 280 | pragma solidity ^0.4.11; 281 | 282 | contract StateMachine { 283 | enum Stages { 284 | AcceptingBlindedBids, 285 | RevealBids, 286 | AnotherStage, 287 | AreWeDoneYet, 288 | Finished 289 | } 290 | 291 | // Ésta es la etapa actual. 292 | Stages public stage = Stages.AcceptingBlindedBids; 293 | 294 | uint public creationTime = now; 295 | 296 | modifier atStage(Stages _stage) { 297 | require(stage == _stage); 298 | _; 299 | } 300 | 301 | function nextStage() internal { 302 | stage = Stages(uint(stage) + 1); 303 | } 304 | 305 | // Hace transiciones temporizadas. Asegúrate de 306 | // mencionar este modificador primero, si no, 307 | // no se tendrá en cuenta la nueva etapa. 308 | modifier timedTransitions() { 309 | if (stage == Stages.AcceptingBlindedBids && 310 | now >= creationTime + 10 days) 311 | nextStage(); 312 | if (stage == Stages.RevealBids && 313 | now >= creationTime + 12 days) 314 | nextStage(); 315 | // La transición del resto de etapas se produce por transacciones 316 | _; 317 | } 318 | 319 | // ¡El orden de los modificadores importa aquí! 320 | function bid() 321 | public 322 | payable 323 | timedTransitions 324 | atStage(Stages.AcceptingBlindedBids) 325 | { 326 | // No implementaremos esto aquí 327 | } 328 | 329 | function reveal() 330 | public 331 | timedTransitions 332 | atStage(Stages.RevealBids) 333 | { 334 | } 335 | 336 | // Este modificador pasa a la próxima etapa 337 | // una vez terminada la función. 338 | modifier transitionNext() 339 | { 340 | _; 341 | nextStage(); 342 | } 343 | 344 | function g() 345 | public 346 | timedTransitions 347 | atStage(Stages.AnotherStage) 348 | transitionNext 349 | { 350 | } 351 | 352 | function h() 353 | public 354 | timedTransitions 355 | atStage(Stages.AreWeDoneYet) 356 | transitionNext 357 | { 358 | } 359 | 360 | function i() 361 | public 362 | timedTransitions 363 | atStage(Stages.Finished) 364 | { 365 | } 366 | } 367 | -------------------------------------------------------------------------------- /conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Solidity documentation build configuration file, created by 5 | # sphinx-quickstart on Mon Dec 7 12:32:57 2015. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | import sys 17 | import os 18 | import re 19 | 20 | # If extensions (or modules to document with autodoc) are in another directory, 21 | # add these directories to sys.path here. If the directory is relative to the 22 | # documentation root, use os.path.abspath to make it absolute, like shown here. 23 | 24 | def setup(sphinx): 25 | sys.path.insert(0, os.path.abspath('./utils')) 26 | from SolidityLexer import SolidityLexer 27 | sphinx.add_lexer('Solidity', SolidityLexer()) 28 | 29 | # -- General configuration ------------------------------------------------ 30 | 31 | # If your documentation needs a minimal Sphinx version, state it here. 32 | #needs_sphinx = '1.0' 33 | 34 | # Add any Sphinx extension module names here, as strings. They can be 35 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 36 | # ones. 37 | extensions = [] 38 | 39 | # Add any paths that contain templates here, relative to this directory. 40 | templates_path = ['_templates'] 41 | 42 | # The suffix of source filenames. 43 | source_suffix = '.rst' 44 | 45 | # The encoding of source files. 46 | #source_encoding = 'utf-8-sig' 47 | 48 | # The master toctree document. 49 | master_doc = 'index' 50 | 51 | # General information about the project. 52 | project = 'Solidity' 53 | copyright = '2016-2017, Ethereum' 54 | 55 | # The version info for the project you're documenting, acts as replacement for 56 | # |version| and |release|, also used in various other places throughout the 57 | # built documents. 58 | # 59 | # The short X.Y version. 60 | #with open('../CMakeLists.txt', 'r') as f: 61 | # version = re.search('PROJECT_VERSION "([^"]+)"', f.read()).group(1) 62 | ## The full version, including alpha/beta/rc tags. 63 | #if os.path.isfile('../prerelease.txt') != True or os.path.getsize('../prerelease.txt') == 0: 64 | # release = version 65 | #else: 66 | # # This is a prerelease version 67 | # release = version + '-develop' 68 | version = 'UNKNOWN' 69 | release = version 70 | 71 | # The language for content autogenerated by Sphinx. Refer to documentation 72 | # for a list of supported languages. 73 | #language = None 74 | 75 | # There are two options for replacing |today|: either, you set today to some 76 | # non-false value, then it is used: 77 | #today = '' 78 | # Else, today_fmt is used as the format for a strftime call. 79 | #today_fmt = '%B %d, %Y' 80 | 81 | # List of patterns, relative to source directory, that match files and 82 | # directories to ignore when looking for source files. 83 | exclude_patterns = ['_build'] 84 | 85 | # The reST default role (used for this markup: `text`) to use for all 86 | # documents. 87 | #default_role = None 88 | 89 | # If true, '()' will be appended to :func: etc. cross-reference text. 90 | #add_function_parentheses = True 91 | 92 | # If true, the current module name will be prepended to all description 93 | # unit titles (such as .. function::). 94 | #add_module_names = True 95 | 96 | # If true, sectionauthor and moduleauthor directives will be shown in the 97 | # output. They are ignored by default. 98 | #show_authors = False 99 | 100 | # The name of the Pygments (syntax highlighting) style to use. 101 | pygments_style = 'sphinx' 102 | 103 | highlight_language = 'Solidity' 104 | 105 | # A list of ignored prefixes for module index sorting. 106 | #modindex_common_prefix = [] 107 | 108 | # If true, keep warnings as "system message" paragraphs in the built documents. 109 | #keep_warnings = False 110 | 111 | 112 | # -- Options for HTML output ---------------------------------------------- 113 | 114 | # The theme to use for HTML and HTML Help pages. See the documentation for 115 | # a list of builtin themes. 116 | html_theme = 'default' 117 | 118 | # Theme options are theme-specific and customize the look and feel of a theme 119 | # further. For a list of options available for each theme, see the 120 | # documentation. 121 | #html_theme_options = {} 122 | 123 | # Add any paths that contain custom themes here, relative to this directory. 124 | #html_theme_path = [] 125 | 126 | # The name for this set of Sphinx documents. If None, it defaults to 127 | # " v documentation". 128 | #html_title = None 129 | 130 | # A shorter title for the navigation bar. Default is the same as html_title. 131 | #html_short_title = None 132 | 133 | # The name of an image file (relative to this directory) to place at the top 134 | # of the sidebar. 135 | #html_logo = None 136 | 137 | # The name of an image file (within the static path) to use as favicon of the 138 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 139 | # pixels large. 140 | #html_favicon = None 141 | 142 | # Add any paths that contain custom static files (such as style sheets) here, 143 | # relative to this directory. They are copied after the builtin static files, 144 | # so a file named "default.css" will overwrite the builtin "default.css". 145 | html_static_path = [] 146 | 147 | # Add any extra paths that contain custom files (such as robots.txt or 148 | # .htaccess) here, relative to this directory. These files are copied 149 | # directly to the root of the documentation. 150 | #html_extra_path = [] 151 | 152 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 153 | # using the given strftime format. 154 | #html_last_updated_fmt = '%b %d, %Y' 155 | 156 | # If true, SmartyPants will be used to convert quotes and dashes to 157 | # typographically correct entities. 158 | #html_use_smartypants = True 159 | 160 | # Custom sidebar templates, maps document names to template names. 161 | #html_sidebars = {} 162 | 163 | # Additional templates that should be rendered to pages, maps page names to 164 | # template names. 165 | #html_additional_pages = {} 166 | 167 | # If false, no module index is generated. 168 | #html_domain_indices = True 169 | 170 | # If false, no index is generated. 171 | #html_use_index = True 172 | 173 | # If true, the index is split into individual pages for each letter. 174 | #html_split_index = False 175 | 176 | # If true, links to the reST sources are added to the pages. 177 | #html_show_sourcelink = True 178 | 179 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 180 | #html_show_sphinx = True 181 | 182 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 183 | #html_show_copyright = True 184 | 185 | # If true, an OpenSearch description file will be output, and all pages will 186 | # contain a tag referring to it. The value of this option must be the 187 | # base URL from which the finished HTML is served. 188 | #html_use_opensearch = '' 189 | 190 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 191 | #html_file_suffix = None 192 | 193 | # Output file base name for HTML help builder. 194 | htmlhelp_basename = 'Soliditydoc' 195 | 196 | 197 | # -- Options for LaTeX output --------------------------------------------- 198 | 199 | latex_elements = { 200 | # The paper size ('letterpaper' or 'a4paper'). 201 | #'papersize': 'letterpaper', 202 | 203 | # The font size ('10pt', '11pt' or '12pt'). 204 | #'pointsize': '10pt', 205 | 206 | # Additional stuff for the LaTeX preamble. 207 | #'preamble': '', 208 | } 209 | 210 | # Grouping the document tree into LaTeX files. List of tuples 211 | # (source start file, target name, title, 212 | # author, documentclass [howto, manual, or own class]). 213 | latex_documents = [ 214 | ('index', 'solidity.tex', 'Solidity Documentation', 'Ethereum', 'manual'), 215 | ] 216 | 217 | # The name of an image file (relative to this directory) to place at the top of 218 | # the title page. 219 | #latex_logo = None 220 | 221 | # For "manual" documents, if this is true, then toplevel headings are parts, 222 | # not chapters. 223 | #latex_use_parts = False 224 | 225 | # If true, show page references after internal links. 226 | #latex_show_pagerefs = False 227 | 228 | # If true, show URL addresses after external links. 229 | #latex_show_urls = False 230 | 231 | # Documents to append as an appendix to all manuals. 232 | #latex_appendices = [] 233 | 234 | # If false, no module index is generated. 235 | #latex_domain_indices = True 236 | 237 | 238 | # -- Options for manual page output --------------------------------------- 239 | 240 | # One entry per manual page. List of tuples 241 | # (source start file, name, description, authors, manual section). 242 | man_pages = [ 243 | ] 244 | 245 | # If true, show URL addresses after external links. 246 | #man_show_urls = False 247 | 248 | 249 | # -- Options for Texinfo output ------------------------------------------- 250 | 251 | # Grouping the document tree into Texinfo files. List of tuples 252 | # (source start file, target name, title, author, 253 | # dir menu entry, description, category) 254 | texinfo_documents = [ 255 | ] 256 | 257 | # Documents to append as an appendix to all manuals. 258 | #texinfo_appendices = [] 259 | 260 | # If false, no module index is generated. 261 | #texinfo_domain_indices = True 262 | 263 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 264 | #texinfo_show_urls = 'footnote' 265 | 266 | # If true, do not generate a @detailmenu in the "Top" node's menu. 267 | #texinfo_no_detailmenu = False 268 | -------------------------------------------------------------------------------- /contributing.rst: -------------------------------------------------------------------------------- 1 | ########## 2 | Contribuir 3 | ########## 4 | 5 | ¡La ayuda siempre es bienvenida! 6 | 7 | Para comenzar, puedes intentar :ref:`construir a partir del código ` para familiarizarte 8 | con los componentes de Solidity y el proceso de build. También, puede ser útil 9 | especializarse en escribir smart contrats en Solidity. 10 | 11 | En particular, necesitamos ayuda en las siguientes áreas: 12 | 13 | * Mejorando la documentación 14 | * Respondiendo a las preguntas de otros usarios en `StackExchange 15 | `_ y el `Gitter de Solidity 16 | `_ 17 | * Corrigiendo y respondiendo a los `issues del GitHub de Solidity 18 | `_, especialmente esos 19 | taggeados como `up-for-grabs `_ 20 | que están destinados a contribuidores externos como temas introductorios. 21 | 22 | Cómo reportar un Issue 23 | ====================== 24 | 25 | Para reportar un issue, por favor, usa el 26 | `Issue tracker de GitHub `_. Cuando 27 | reportes un issue, por favor, menciona los siguientes detalles: 28 | 29 | * Qué versión de Solidity estás usando 30 | * Cuál es el código fuente (si es aplicable) 31 | * En qué plataforma lo estás ejecutando 32 | * Cómo reproducir el resultado 33 | * Cuál fue el resultado del issue 34 | * Cuál es el resultado esperado 35 | 36 | Reducir el código fuente que causó el issue a lo mínimo es siempre muy 37 | útil y a veces incluso aclara un malentendido. 38 | 39 | Flujo de trabajo para Pull Requests 40 | =================================== 41 | 42 | A fin de contribuir, haz un fork de la rama ``develop`` y haz tus cambios ahí. 43 | Tus mensajes de commit deben detallar *por qué* hiciste el cambio además de *lo que* 44 | hiciste (al menos que sea un pequeño cambio). 45 | 46 | Si necesitas hacer un pull de ``develop`` después de haber hecho tu fork (por ejemplo, 47 | para resolver potenciales conflictos de merge), evita utilizar ``git merge``. Usa en su lugar ``git rebase`` para tu rama. 48 | 49 | Adicionalmente, si estás escribiendo una nueva funcionalidad, por favor, asegúrate de 50 | hacer tests unitarios Boost y ponerlos en ``test/``. 51 | 52 | Sin embargo, si estás haciendo cambios más grandes, consulta primero con el canal Gitter. 53 | 54 | Finalmente, siempre asegúrate de respetar los `estándares de código 55 | `_ 56 | de este proyecto. También, aunque hacemos testing CI, testea tu código y asegúrate que 57 | puedas hacer un build localmente antes de enviar un pull request. 58 | 59 | ¡Gracias por tu ayuda! 60 | 61 | Ejecutando los tests de compilador 62 | ================================== 63 | 64 | Solidity incluye diferentes tipos de tests. Están incluídos en la aplicación llamada 65 | ``soltest``. Algunos de ellos requieren el cliente ``cpp-ethereum`` en modo test. 66 | 67 | Para ejecutar ``cpp-ethereum`` en modo test: ``eth --test -d /tmp/testeth``. 68 | 69 | Para lanzar los tests: ``soltest -- --ipcpath /tmp/testeth/geth.ipc``. 70 | 71 | Para ejecutar un subconjunto de los tests, se pueden usar filtros: 72 | ``soltest -t TestSuite/TestName -- --ipcpath /tmp/testeth/geth.ipc``, donde ``TestName`` puede ser un comodín ``*``. 73 | 74 | Alternativamente, hay un script de testing en ``scripts/test.sh`` que ejecuta todos los tests. 75 | -------------------------------------------------------------------------------- /control-structures.rst: -------------------------------------------------------------------------------- 1 | #################################### 2 | Expresiones y estructuras de control 3 | #################################### 4 | 5 | .. index:: ! parameter, parameter;input, parameter;output 6 | 7 | Parámetros de entrada y de salida 8 | ================================= 9 | 10 | Al igual que en Javascript, las funciones obtienen parámetros como entrada. Por otro lado, al contrario que en Javascript y C, estas también deberían devolver un número aleatorio de parámetros como salida. 11 | 12 | Parámetros de entrada 13 | --------------------- 14 | 15 | Los parámetros de entrada se declaran de la misma forma que las variables. Como una excepción, los parámetros no usados pueden omitir el nombre de la variable. Por ejemplo, si quisiéramos que nuestro contrato acepte un tipo de llamadas externas con dos enteros, el código quedaría similar a este:: 16 | 17 | contract Simple { 18 | function taker(uint _a, uint _b) { 19 | // hace algo con _a y _b. 20 | } 21 | } 22 | 23 | Parámetros de salida 24 | -------------------- 25 | 26 | Los parámetros de salida se pueden declarar con la misma sintaxis después de la palabra reservada ``returns``. Por ejemplo, supongamos que deseamos devolver dos resultados: la suma y el producto de dos valores dados. Entonces, escribiríamos un código como este:: 27 | 28 | contract Simple { 29 | function arithmetics(uint _a, uint _b) returns (uint o_sum, uint o_product) { 30 | o_sum = _a + _b; 31 | o_product = _a * _b; 32 | } 33 | } 34 | 35 | Los nombres de los parámetros de salida se pueden omitir. 36 | Los valores de salida se pueden especificar también usando declaraciones ``return``. 37 | Las declaraciones ``return`` también son capaces de devolver múltiples valores, ver :ref:`multi-return`. 38 | Los parámetros de retorno se inicializan a cero; si no se especifica explícitamente su valor, permanecen con dicho valor cero. 39 | 40 | Los parámetros de entrada y salida se pueden usar como expresiones en el cuerpo de la función. En este caso, también pueden ir en el lado izquierdo de una asignación. 41 | 42 | .. index:: if, else, while, do/while, for, break, continue, return, switch, goto 43 | 44 | Estructuras de control 45 | ====================== 46 | 47 | La mayoría de las estructuras de control disponibles en JavaScript, también lo están en Solidity exceptuando ``switch`` y ``goto``. Esto significa que tenemos: ``if``, ``else``, ``while``, ``do``, ``for``, ``break``, ``continue``, ``return``, ``? :``, con la semántica habitual conocida de C o JavaScript. 48 | 49 | Los paréntesis no se pueden omitir para condicionales, pero sí las llaves alrededor de los cuerpos de las declaraciones sencillas. 50 | 51 | Hay que tener en cuenta que no hay conversión de tipos desde non-boolean a boolean como hay en C y JavaScript, por lo que ``if (1) { ... }`` *no* es válido en Solidity. 52 | 53 | .. _multi-return: 54 | 55 | Devolver múltiples valores 56 | -------------------------- 57 | 58 | Cuando una función tiene múltiples parámetros de salida, ``return (v0, v1, ..., 59 | vn)`` puede devolver múltiples valores. El número de componentes debe ser el mismo que el de parámetros de salida. 60 | 61 | .. index:: ! function;call, function;internal, function;external 62 | 63 | .. _function-calls: 64 | 65 | Llamadas a funciones 66 | ==================== 67 | 68 | Llamadas a funciones internas 69 | ----------------------------- 70 | 71 | Las funciones del contrato actual pueden ser llamadas directamente ("internamente") y, también, recursivamente como se puede ver en este ejemplo sin sentido funcional:: 72 | 73 | contract C { 74 | function g(uint a) returns (uint ret) { return f(); } 75 | function f() returns (uint ret) { return g(7) + f(); } 76 | } 77 | 78 | Estas llamadas a funciones son traducidas en simples saltos dentro de la máquina virtual de Ethereum (EVM). Esto tiene como consecuencia que la memoria actual no se limpia, así que pasar referencias de memoria a las funciones llamadas internamente es muy eficiente. Sólo las funciones del mismo contrato pueden ser llamadas internamente. 79 | 80 | Llamadas a funciones externas 81 | ----------------------------- 82 | 83 | Las expresiones ``this.g(8);`` and ``c.g(2);`` (donde ``c`` es la instancia de un contrato) son también llamadas válidas, pero en esta ocasión, la función se llamará "externamente" mediante un message call y no directamente por saltos. 84 | Por favor, es importante tener en cuenta que las llamadas a funciones en ``this`` no pueden ser usadas en el constructor, ya que el contrato en cuestión no se ha creado todavía. 85 | 86 | Las funciones de otros contratos se tienen que llamar de forma externa. Para una llamada externa, 87 | todos los argumentos de la función tienen que ser copiados en memoria. 88 | 89 | Cuando se llama a funciones de otros contratos, la cantidad de Wei enviada con la llamada y el gas pueden especificarse con las opciones especiales ``.value()`` y ``.gas()``, respectivamente:: 90 | 91 | contract InfoFeed { 92 | function info() payable returns (uint ret) { return 42; } 93 | } 94 | 95 | 96 | contract Consumer { 97 | InfoFeed feed; 98 | function setFeed(address addr) { feed = InfoFeed(addr); } 99 | function callFeed() { feed.info.value(10).gas(800)(); } 100 | } 101 | 102 | El modificador ``payable`` se tiene que usar para ``info``, porque de otra manera la opción `.value()` no estaría disponible. 103 | 104 | Destacar que la expresión ``InfoFeed(addr)`` realiza una conversión de tipo explícita afirmando que "sabemos que el tipo de contrato en la dirección dada es ``InfoFeed``", sin ejecutar un constructor. Las conversiones de tipo explícitas tienen que ser gestionadas con extrema precaución. Nunca se debe llamar a una función en un contrato donde no se sabe con seguridad cuál es su tipo. 105 | 106 | También se podría usar ``function setFeed(InfoFeed _feed) { feed = _feed; }`` directamente. 107 | Hay que tener cuidado con el hecho de que ``feed.info.value(10).gas(800)`` sólo (localmente) establece el valor y la cantidad de gas enviada con la llamada a la función. Sólo tras el último paréntesis se realiza realmente la llamada. 108 | 109 | Las llamadas a funciones provocan excepciones si el contrato invocado no existe (en el sentido de que la cuenta no contiene código) o si el contrato invocado por sí mismo dispara una excepción o se queda sin gas. 110 | 111 | .. warning:: 112 | Cualquier interacción con otro contrato supone un daño potencial, especialmente si el código fuente del contrato no se conoce de antemano. El contrato actual pasa el control al contrato invocado y eso potencialmente podría suponer que haga cualquier cosa. Incluso si el contrato invocado hereda de un contrato padre conocido, el contrato del que hereda sólo requiere tener una interfaz correcta. La implementación del contrato, sin embargo, puede ser totalmente aleatoria y, por ello, crear un perjuicio. Además, hay que estar preparado en caso de que llame dentro de otros contratos del sistema o, incluso, volver al contrato que lo llama antes de que la primera llamada retorne. Esto significa que el contrato invocado puede cambiar variables de estado del contrato que le llama mediante sus funciones. Escribir tus funciones de manera que realicen, por ejemplo, llamadas a funciones externas ocurridas después de cualquier cambio en variables de estado en tu contrato, hace que este contrato no sea vulnerable a un ataque de reentrada. 113 | 114 | 115 | Llamadas con nombre y parámetros de funciones anónimas 116 | ------------------------------------------------------ 117 | 118 | Los argumentos de una llamada a una función pueden venir dados por el nombre, en cualquier orden, si están entre ``{ }`` como se puede ver en el siguiente ejemplo. La lista de argumentos tiene que coincidir por el nombre con la lista de parámetros de la declaración de la función, pero pueden estar en orden aleatorio. 119 | 120 | :: 121 | 122 | pragma solidity ^0.4.0; 123 | 124 | contract C { 125 | function f(uint key, uint value) { ... } 126 | 127 | function g() { 128 | // argumentos con nombre 129 | f({value: 2, key: 3}); 130 | } 131 | } 132 | 133 | Nombres de parámetros de función omitidos 134 | ----------------------------------------- 135 | 136 | Los nombres de parámetros no usados (especialmente los de retorno) se pueden omitir. 137 | Esos nombres estarán presentes en la pila, pero serán inaccesibles. 138 | 139 | :: 140 | 141 | pragma solidity ^0.4.0; 142 | 143 | contract C { 144 | // Se omite el nombre para el parámetro 145 | function func(uint k, uint) returns(uint) { 146 | return k; 147 | } 148 | } 149 | 150 | 151 | .. index:: ! new, contracts;creation 152 | 153 | .. _creating-contracts: 154 | 155 | Creando contratos mediante ``new`` 156 | ================================== 157 | 158 | Un contrato puede crear un nuevo contrato usando la palabra reservada ``new``. El código completo del contrato que se está creando tiene que ser conocido de antemano, por lo que no son posibles las dependencias de creación recursivas. 159 | 160 | :: 161 | 162 | pragma solidity ^0.4.0; 163 | 164 | contract D { 165 | uint x; 166 | function D(uint a) payable { 167 | x = a; 168 | } 169 | } 170 | 171 | 172 | contract C { 173 | D d = new D(4); // Se ejecutará como parte del constructor de C 174 | 175 | function createD(uint arg) { 176 | D newD = new D(arg); 177 | } 178 | 179 | function createAndEndowD(uint arg, uint amount) { 180 | // Envía Ether junto con la creación 181 | D newD = (new D).value(amount)(arg); 182 | } 183 | } 184 | 185 | Como se ve en el ejemplo, es posible traspasar Ether a la creación usando la opción ``.value()``, 186 | pero no es posible limitar la cantidad de gas. Si la creación falla 187 | (debido al desbordamiento de la pila, falta de balance o cualquier otro problema), se dispara una excepción. 188 | 189 | Orden de la evaluación de expresiones 190 | ===================================== 191 | 192 | El orden de evaluación de expresiones no se especifica (más formalmente, el orden en el que los hijos de un nodo en el árbol de la expresión son evaluados no es especificado. Eso sí, son evaluados antes que el propio nodo). Sólo se garantiza que las sentencias se ejecutan en orden y que se hace un cortocircuito para las expresiones booleanas. Ver :ref:`order` para más información. 193 | 194 | .. index:: ! assignment 195 | 196 | Asignación 197 | ========== 198 | 199 | .. index:: ! assignment;destructuring 200 | 201 | Asignaciones para desestructurar y retornar múltiples valores 202 | ------------------------------------------------------------- 203 | 204 | Solidity internamente permite tipos tupla, p.ej.: una lista de objetos de, potencialmente, diferentes tipos cuyo tamaño es constante en tiempo de compilación. Esas tuplas pueden ser usadas para retornar múltiples valores al mismo tiempo y, también, asignarlos a múltiples variables (o lista de valores en general) también al mismo tiempo:: 205 | 206 | contract C { 207 | uint[] data; 208 | 209 | function f() returns (uint, bool, uint) { 210 | return (7, true, 2); 211 | } 212 | 213 | function g() { 214 | // Declara y asigna variables. No es posible especificar el tipo de forma explícita. 215 | var (x, b, y) = f(); 216 | // Asigna a una variable pre-existente. 217 | (x, y) = (2, 7); 218 | // Truco común para intercambiar valores -- no funciona con tipos de almacenamiento sin valor. 219 | (x, y) = (y, x); 220 | // Los componentes se pueden dejar fuera (también en declaraciones de variables). 221 | // Si la tupla acaba en un componente vacío, 222 | // el resto de los valores se descartan. 223 | (data.length,) = f(); // Establece la longitud a 7 224 | // Lo mismo se puede hacer en el lado izquierdo. 225 | (,data[3]) = f(); // Sets data[3] to 2 226 | // Los componentes sólo se pueden dejar en el lado izquierdo de las asignaciones, con 227 | // una excepción: 228 | (x,) = (1,); 229 | // (1,) es la única forma de especificar una tupla de un componente, porque (1) 230 | // equivale a 1. 231 | } 232 | } 233 | 234 | Complicaciones en Arrays y Structs 235 | ---------------------------------- 236 | 237 | La sintaxis de asignación es algo más complicada para tipos sin valor como arrays y structs. 238 | Las asignaciones *a* variables de estado siempre crean una copia independiente. Por otro lado, asignar una variable local crea una copia independiente sólo para tipos elementales, como tipos estáticos que encajan en 32 bytes. Si los structs o arrays (incluyendo ``bytes`` y ``string``) son asignados desde una variable de estado a una local, la variable local se queda una referencia a la variable de estado original. Una segunda asignación a la variable local no modifica el estado, sólo cambia la referencia. Las asignaciones a miembros (o elementos) de la variable local *hacen* cambiar el estado. 239 | 240 | .. index:: ! scoping, declarations, default value 241 | 242 | .. _default-value: 243 | 244 | Scoping y declaraciones 245 | ========================= 246 | 247 | Una variable cuando se declara tendrá un valor inicial por defecto que, representado en bytes, será todo ceros. 248 | Los valores por defecto de las variables son los típicos "estado-cero" cualquiera que sea el tipo. Por ejemplo, el valor por defecto para un ``bool`` es ``false``. El valor por defecto para un ``uint`` o ``int`` es ``0``. Para arrays de tamaño estático y ``bytes1`` hasta ``bytes32``, cada elemento individual será inicializado a un valor por defecto según sea su tipo. Finalmente, para arrays de tamaño dinámico, ``bytes``y ``string``, el valor por defecto es un array o string vacío. 249 | 250 | Una variable declarada en cualquier punto de una función estará dentro del alcance de *toda la función*, independientemente de donde se haya declarado. Esto ocurre porque Solidity hereda sus reglas de scoping de JavaScript. 251 | Esto difiere de muchos lenguajes donde las variables sólo están en el alcance de donde se declaran hasta que acaba el bloque semántico. 252 | Como consecuencia de esto, el código siguiente es ilegal y hace que el compilador devuelva un error porque el identificador se ha declarado previamente, ``Identifier already declared``:: 253 | 254 | pragma solidity ^0.4.0; 255 | 256 | contract ScopingErrors { 257 | function scoping() { 258 | uint i = 0; 259 | 260 | while (i++ < 1) { 261 | uint same1 = 0; 262 | } 263 | 264 | while (i++ < 2) { 265 | uint same1 = 0; // Ilegal, segunda declaración para same1 266 | } 267 | } 268 | 269 | function minimalScoping() { 270 | { 271 | uint same2 = 0; 272 | } 273 | 274 | { 275 |               uint same2 = 0; // Ilegal, segunda declaración para same2 276 | } 277 | } 278 | 279 | function forLoopScoping() { 280 | for (uint same3 = 0; same3 < 1; same3++) { 281 | } 282 | 283 |           for (uint same3 = 0; same3 < 1; same3++) { // Ilegal, segunda declaración para same3 284 | } 285 | } 286 | } 287 | 288 | Como añadido a esto, si la variable se declara, se inicializará al principio de la función con su valor por defecto. 289 | Esto significa que el siguiente código es legal, aunque se haya escrito de manera un tanto pobre:: 290 | 291 | function foo() returns (uint) { 292 | // baz se inicializa implícitamente a 0 293 | uint bar = 5; 294 | if (true) { 295 | bar += baz; 296 | } else { 297 | uint baz = 10;// Nunca se ejecuta 298 | } 299 | return bar;// devuelve 5 300 | } 301 | 302 | .. index:: ! exception, ! throw 303 | 304 | Excepciones 305 | =========== 306 | 307 | Hay algunos casos en los que las excepciones se lanzan automáticamente (ver más adelante). Se puede usar la instrucción ``throw`` para lanzarlas manualmente. La consecuencia de una excepción es que la llamada que se está ejecutando en ese momento se para y se revierte (todos los cambios en los estados y balances se deshacen) y la excepción también se genera mediante llamadas de función de Solidity (las excepciones ``send`` y las funciones de bajo nivel ``call``, ``delegatecall`` y ``callcode``, todas ellas devuelven ``false`` en caso de una excepción). 308 | 309 | Todavía no es posible capturar excepciones. 310 | 311 | En el siguiente ejemplo, se enseña como ``throw`` se puede usar para revertir fácilmente una transferencia de Ether y, además, se enseña como comprobar el valor de retorno de ``send``:: 312 | 313 | pragma solidity ^0.4.0; 314 | 315 | contract Sharer { 316 | function sendHalf(address addr) payable returns (uint balance) { 317 | if (!addr.send(msg.value / 2)) 318 | throw; // También revierte la transferencia de Sharer 319 | return this.balance; 320 | } 321 | } 322 | 323 | Actualmente, Solidity genera automáticamente una excepción en tiempo de ejecución en las siguientes situaciones: 324 | 325 | #. Si se accede a un array en un índice demasiado largo o negativo (ejemplo: ``x[i]`` donde ``i >= x.length`` o ``i < 0``). 326 | #. Si se accede a un ``bytesN`` de longitud fija en un índice demasiado largo o negativo. 327 | #. Si se llama a una función con un message call, pero no finaliza adecuadamente (ejemplo: se queda sin gas, no tiene una función de matching, o dispara una excepción por sí mismo), exceptuando el caso en el que se use una operación de bajo nivel ``call``, ``send``, ``delegatecall`` o ``callcode``. Las operaciones de bajo nivel nunca disparan excepciones, pero indican fallos devolviendo ``false``. 328 | #. Si se crea un contrato usando la palabra reservada ``new``, pero la creación del contrato no finaliza correctamente (ver más arriba la definición de "no finalizar correctamente"). 329 | #. Si se divide o se hace módulo por cero (ejemplos: ``5 / 0`` o ``23 % 0``). 330 | #. Si se hace un movimiento por una cantidad negativa. 331 | #. Si se convierte un valor muy grande o negativo en un tipo enum. 332 | #. Si se realiza una llamada de función externa apuntando a un contrato que no contiene código. 333 | #. Si un contrato recibe Ether mediante una función sin el modificador ``payable`` (incluyendo el constructor y la función de fallback). 334 | #. Si un contrato recibe Ether mediante una función getter pública. 335 | #. Si se llama a una variable inicializada a cero de un tipo de función interna. 336 | #. Si un ``.transfer()`` falla. 337 | #. Si se invoca con ``assert`` junto con un argumento que evalúa a falso. 338 | 339 | Un usuario genera una excepción en las siguientes situaciones: 340 | 341 | #. Llamando a ``throw``. 342 | #. Llamando a ``require`` junto con un argumento que evalúa a ``false``. 343 | 344 | Internamente, Solidity realiza una operación de revertir (revert, instrucción ``0xfd``) cuando una excepción provista por un usuario se lanza o la condición de la llamada ``require`` no se satisface. Por contra, realiza una operación inválida (instrucción ``0xfe``) si una excepción en tiempo de ejecución aparece o la condición de una llamada ``assert`` no se satisface. En ambos casos, esto ocasiona que la EVM revierta todos los cambios de estado acaecidos. El motivo de todo esto es que no existe un modo seguro de continuar con la ejecución debido a que no sucedió el efecto esperado. Como se quiere mantener la atomicidad de las transacciones, lo más seguro es revertir todos los cambios y hacer que la transacción no tenga ningún efecto en su totalidad o, como mínimo, en la llamada. 345 | 346 | En el caso de que los contratos se escriban de tal manera que ``assert`` sólo sea usado para probar condiciones internas y ``require`` se use en caso de que haya una entrada malformada, una herramienta de análisis formal que verifique que el opcode inválido nunca pueda ser alcanzado, se podría usar para chequear la ausencia de errores asumiendo entradas válidas. 347 | -------------------------------------------------------------------------------- /index.rst: -------------------------------------------------------------------------------- 1 | Solidity 2 | ======== 3 | 4 | .. image:: logo.svg 5 | :width: 120px 6 | :alt: Solidity logo 7 | :align: center 8 | 9 | Solidity es un lenguaje orientado a objetos, de alto nivel para la implementación de contratos inteligentes. Los contratos inteligentes son programas que gobiernan el comportamiento de las cuentas dentro de Ethereum. 10 | 11 | Solidity fue influenciado por C++, Python, JavaScript y diseñado para ser utilizado por la Máquina Virtual de Ethereum (EVM). 12 | 13 | Solidity está tipado de manera estática y acepta, entre otras cosas, herencia, bibliotecas y tipos complejos definidos por el usuario. 14 | 15 | Con Solidity es posible crear contratos para votar, para el crowdfunding, para subastas a ciegas y para monederos multi firmas. 16 | 17 | Al desplegar contratos, deberias usar la última versión liberada de Solidity. Fuera de casos excepcionales, sólo la última versión recibe `Actualizaciones de Seguridad `_. 18 | Además, tanto cambios importantes como nuevas características son introducidas regularmente. Actualmente utilizamos un sistema de numeración de versiones 0.y.z `para indicar este ritmo rápido de cambio `_. 19 | 20 | .. note:: 21 | La mejor manera de probar Solidity ahora mismo es usando `Remix `_ (puede tardar un rato en cargarse, por favor sea paciente). 22 | 23 | Enlaces útiles 24 | -------------- 25 | 26 | * `Ethereum `_ 27 | 28 | * `Registro de Cambios `_ 29 | 30 | * `Trabajos Pendientes (Story Backlog) `_ 31 | 32 | * `Código Fuente `_ 33 | 34 | * `Ethereum Stackexchange `_ 35 | 36 | * `Chat de Gitter `_ 37 | 38 | Integraciones de Solidity disponibles 39 | ------------------------------------- 40 | 41 | * `Remix `_ 42 | Entorno integrado de desarrollo (IDE) basado en un navegador que integra un compilador y un entorno en tiempo de ejecución para Solidity sin los componentes orientados al servidor. 43 | 44 | * `Ethereum Studio `_ 45 |   Entorno integrado de desarrollo (IDE) especializado que proporciona acceso a un entorno completo de Ethereum a través de un intérprete de comandos (shell). 46 | 47 | * `Plugin IntelliJ IDEA `_ 48 | Plugin de Solidity para IntelliJ IDEA (y el resto de IDEs de JetBrains). 49 | 50 | * `Extensión de Visual Studio `_ 51 | Plugin de Solidity para Microsoft Visual Studio que incluye un compilador de Solidity. 52 | 53 | * `Paquete para SublimeText `_ 54 |   Paquete para resaltar la sintáxis de Solidity en el editor SublimeText. 55 | 56 | * `Etheratom `_ 57 |   Plugin para el editor Atom que ofrece: resaltar la sintaxis, un entorno de compilación y un entorno en tiempo de ejecución (compatible con un nodo en segundo plano y con una máquina virtual). 58 | 59 | * `Linter de Solidity para Atom `_ 60 | Plugin para el editor Atom que ofrece linting para Solidity. 61 | 62 | * `Linter de Solium para Atom `_ 63 | Programa de linting de Solidity configurable para Atom que usa Solium como base. 64 | 65 | * `Solium `_ 66 |   Programa de linting de Solidity para la interfaz de línea de comandos que sigue estrictamente las reglas prescritas por la `Guía de Estilo de Solidity `_. 67 | 68 | * `Extensión para Visual Studio Code `_ 69 | Plugin de Solidity para Microsoft Visual Studio que incluye resaltar la sintaxis y el compilador de Solidity. 70 | 71 | * `Emacs Solidity `_ 72 |   Plugin para el editor Emacs que incluye resaltar la sintaxis y el reporte de los errores de compilación. 73 | 74 | * `Vim Solidity `_ 75 | Plugin para el editor Vim que incluye resaltar la sintaxis. 76 | Plugin for the Vim editor providing syntax highlighting. 77 | 78 | * `Vim Syntastic `_ 79 |   Plugin para el editor Vim que incluye la verificación de la compilación. 80 | 81 | Descontinuados: 82 | 83 | * `Mix IDE `_ 84 | Entorno integrado de desarrollo (IDE) basado en Qt para el diseño, debugging y testeo de contratos inteligentes en Solidity. 85 | 86 | 87 | Herramientas para Solidity 88 | -------------------------- 89 | 90 | * `Dapp `_ 91 |   Herramienta de construcción, gestión de paquetes y asistente de despliegue para Solidity. 92 | 93 | * `Solidity REPL `_ 94 | Prueba Solidity al instante gracias a una consola de línea de comandos de Solidity. 95 | 96 | * `solgraph `_ 97 | Visualiza el flujo de control de Solidity y resalta potenciales vulnerabilidades de seguridad. 98 | 99 | * `evmdis `_ 100 |   Desensamblador de la Máquina Virtual de Ethereum (EVM) que realiza análisis estáticos sobre el bytecode y así proporciona un mayor nivel de abstracción que las operaciones brutas del EVM. 101 | 102 | * `Doxity `_ 103 |   Generador de documentación para Solidity. 104 | 105 | Analizadores de sintaxis y de gramática alternativos para Solidity 106 | ------------------------------------------------------------------ 107 | 108 | * `solidity-parser `_ 109 |   Analizador de sintaxis para JavaScript. 110 | 111 | * `Solidity Grammar para ANTLR 4 `_ 112 |   Analizador de gramática de Solidity para el generador de sintaxis ANTLR 4. 113 | 114 | Documentación del lenguaje 115 | -------------------------- 116 | 117 | A continuación, primero veremos un :ref:`contrato inteligente sencillo ` escrito en Solidity, seguido de una introducción sobre :ref:`blockchains ` y sobre la :ref:`Máquina Virtual de Ethereum `. 118 | 119 | En la siguiente sección se explicarán distintas *características* de Solidity con varios :ref:`ejemplos de contratos `. Recuerde que siempre puede probar estos contratos `en su navegador `_!. 120 | 121 | La última sección (y también la más amplia) cubre, en profundidad, todos los aspectos de Solidity. 122 | 123 | Si todavía tiene dudas o preguntas, puede buscar y preguntar en la web de `Ethereum Stackexchange `_, o puede unirse a nuestro `canal de gitter `_. ¡Ideas para mejorar Solidity o esta documentación siempre son bienvenidas! 124 | 125 | También existe la `versión rusa (русский перевод) `_. 126 | 127 | Contenidos 128 | ========== 129 | 130 | :ref:`Índice de palabras clave `, :ref:`Página de búsqueda ` 131 | 132 | .. toctree:: 133 | :maxdepth: 2 134 | 135 | introduction-to-smart-contracts.rst 136 | installing-solidity.rst 137 | solidity-by-example.rst 138 | solidity-in-depth.rst 139 | security-considerations.rst 140 | using-the-compiler.rst 141 | abi-spec.rst 142 | style-guide.rst 143 | common-patterns.rst 144 | bugs.rst 145 | contributing.rst 146 | frequently-asked-questions.rst 147 | -------------------------------------------------------------------------------- /installing-solidity.rst: -------------------------------------------------------------------------------- 1 | .. index:: ! installing 2 | 3 | .. _installing-solidity: 4 | 5 | ################### 6 | Instalando Solidity 7 | ################### 8 | 9 | Control de Versiones 10 | ==================== 11 | 12 | Las versiones de Solidity siguen un `versionado semántico `_, y además 13 | de los releases, también hay **nightly developement builds**. El funcionamiento de los nightly builds 14 | no está garantizado y puede que contengan cambios no documentados o que no funcionen. 15 | Recomendamos usar la última release. Los siguientes instaladores de paquetes usarán la release 16 | más actual. 17 | 18 | Remix 19 | ===== 20 | 21 | Si sólo quieres probar Solidity para pequeños contratos, puedes usar 22 | `Remix `_ 23 | que no necesita instalación. Si quieres usarlo sin conexión a internet, 24 | puedes ir a https://github.com/ethereum/browser-solidity/tree/gh-pages 25 | y bajar el .ZIP como se explica en esa página. 26 | 27 | npm / Node.js 28 | ============= 29 | 30 | Esta es probablemente la manera más portable y conveniente de instalar Solidity localmente. 31 | 32 | Se proporciona una librería Javascript independiente de plataforma mediante la compilación del código C++ 33 | a Javascript usando Emscripten. Puede ser usado en proyectos directamente (como Remix). 34 | Visita el repositorio `solc-js `_ para ver las instrucciones. 35 | 36 | También contiene una herramienta de línea de comandos llamada `solcjs` que puede ser instalada vía npm: 37 | 38 | .. code:: bash 39 | 40 | npm install -g solc 41 | 42 | .. note:: 43 | 44 | Las opciones de línea de comandos de `solcjs` no son compatibles con `solc`, y las herramientas 45 | (tales como `geth`) que esperen el comportamiento de `solc` no funcionarán con `solcjs`. 46 | 47 | Docker 48 | ====== 49 | 50 | Proveemos builds de docker actualizadas para el compilador. El repositorio 51 | ``stable`` contiene las versiones publicadas mientras que el ``nightly`` 52 | contiene cambios potencialmente inestables de la rama de desarrollo. 53 | 54 | .. code:: bash 55 | 56 | docker run ethereum/solc:stable solc --version 57 | 58 | Actualmente, la imagen de docker contiene el compilador ejecutable, 59 | así que tendrás que enlazar las carpetas de código y de output. 60 | 61 | Paquetes Binarios 62 | ================= 63 | 64 | Los paquetes binarios de Solidity están disponibles en 65 | `solidity/releases `_. 66 | 67 | También tenemos PPAs para Ubuntu. Para la versión estable más reciente. 68 | 69 | .. code:: bash 70 | 71 | sudo add-apt-repository ppa:ethereum/ethereum 72 | sudo apt-get update 73 | sudo apt-get install solc 74 | 75 | Si quieres la versión en desarrollo más reciente: 76 | 77 | .. code:: bash 78 | 79 | sudo add-apt-repository ppa:ethereum/ethereum 80 | sudo add-apt-repository ppa:ethereum/ethereum-dev 81 | sudo apt-get update 82 | sudo apt-get install solc 83 | 84 | Arch Linux también tiene paquetes, pero limitados a la versión de desarrollo más reciente: 85 | 86 | .. code:: bash 87 | 88 | pacman -S solidity-git 89 | 90 | Homebrew aún no tiene paquetes preconstruidos, 91 | siguiendo una migración de Jenkins a TavisCI, pero Homebrew 92 | todavía debería funcionar para construir desde el código. 93 | Pronto se agregarán los paquetes preconstruidos. 94 | 95 | .. code:: bash 96 | 97 | brew update 98 | brew upgrade 99 | brew tap ethereum/ethereum 100 | brew install solidity 101 | brew linkapps solidity 102 | 103 | Si necesitas una versión específica de Solidity, puedes instalar 104 | una fórmula Homebrew desde Github. 105 | 106 | Ver 107 | `solidity.rb commits on Github `_. 108 | 109 | Sigue los enlaces de historia hasta que veas un enlace a un fichero de un 110 | commit específico de ``solidity.rb``. 111 | 112 | instalar con ``brew``: 113 | 114 | .. code:: bash 115 | 116 | brew unlink solidity 117 | # Install 0.4.8 118 | brew install https://raw.githubusercontent.com/ethereum/homebrew-ethereum/77cce03da9f289e5a3ffe579840d3c5dc0a62717/solidity.rb 119 | 120 | Gentoo también provee un paquete Solidity que puede instalarse con ``emerge``: 121 | 122 | .. code:: bash 123 | 124 | demerge ev-lang/solidity 125 | 126 | .. _building-from-source: 127 | 128 | Construir desde el código 129 | ========================= 130 | 131 | Clonar el Repositorio 132 | --------------------- 133 | 134 | Para clonar el código fuente, ejecuta el siguiente comando: 135 | 136 | .. code:: bash 137 | 138 | git clone --recursive https://github.com/ethereum/solidity.git 139 | cd solidity 140 | 141 | Si quieres ayudar a desarrollar Solidity, 142 | debes hacer un fork de Solidity y agregar tu fork personal como un remoto secundario: 143 | 144 | .. code:: bash 145 | 146 | cd solidity 147 | git remote add personal git@github.com:[username]/solidity.git 148 | 149 | Solidity tiene submódulos de git. Asegúrate que están cargados correctamente: 150 | 151 | .. code:: bash 152 | 153 | git submodule update --init --recursive 154 | 155 | Prerrequisitos - macOS 156 | ---------------------- 157 | 158 | Para macOS, asegúrate de tener la versión más reciente de 159 | `Xcode instalada `_. 160 | Esto contiene el `compilador Clang C++ `_, las 161 | herramientas que se necesitan para construir aplicaciones C++ en OS X. 162 | Si estás instalando Xcode por primera vez, necesitarás aceptar las condiciones de uso 163 | antes de poder hacer builds de línea de comandos: 164 | 165 | .. code:: bash 166 | 167 | sudo xcodebuild -license accept 168 | 169 | Nuestras builds OS X requieren instalar el gestor de paquetes 170 | `Homebrew `_ para instalar dependencias externas. 171 | Aquí puedes ver cómo `desinstalar Homebrew 172 | `_, 173 | si alguna vez quieres empezar de nuevo. 174 | 175 | Prerrequisitos - Windows 176 | ------------------------ 177 | 178 | Necesitarás instalar las siguientes dependencias para los builds de Solidity en Windows: 179 | 180 | +------------------------------+--------------------------------------------------------+ 181 | | Software | Notas | 182 | +==============================+========================================================+ 183 | | `Git para Windows`_ | Herramienta de línea de comandos para repositorios git.| 184 | +------------------------------+--------------------------------------------------------+ 185 | | `CMake`_ | Generador de build multi plataforma. | 186 | +------------------------------+--------------------------------------------------------+ 187 | | `Visual Studio 2015`_ | Compilador C++ y entorno de desarrollo. | 188 | +------------------------------+--------------------------------------------------------+ 189 | 190 | .. _Git para Windows: https://git-scm.com/download/win 191 | .. _CMake: https://cmake.org/download/ 192 | .. _Visual Studio 2015: https://www.visualstudio.com/products/vs-2015-product-editions 193 | 194 | 195 | Dependencias Externas 196 | --------------------- 197 | 198 | Ahora tenemos un script fácil de usar que instala todas las dependencias externas 199 | en macOS, Windows y varias distros Linux. Esto solía ser un proceso manual de varias 200 | etapas, pero ahora es una sola línea: 201 | 202 | .. code:: bash 203 | 204 | ./scripts/install_deps.sh 205 | 206 | o, en Windows: 207 | 208 | .. code:: bat 209 | 210 | scripts\install_deps.bat 211 | 212 | Build en línea de comandos 213 | -------------------------- 214 | 215 | Construir Solidity es bastante similar en Linux, macOS y otros sistemas Unix: 216 | 217 | .. code:: bash 218 | 219 | mkdir build 220 | cd build 221 | cmake .. && make 222 | 223 | o aún más fácil: 224 | 225 | .. code:: bash 226 | 227 | #nota: esto instalará los binarios de solc y soltest en usr/local/bin 228 | ./scripts/build.sh 229 | 230 | Incluso para Windows: 231 | 232 | .. code:: bash 233 | 234 | mkdir build 235 | cd build 236 | cmake -G "Visual Studio 14 2015 Win64" .. 237 | 238 | Estas últimas instrucciones deberían resultar en la creación de 239 | **solidity.sln** en ese directorio de build. Hacer doble click en ese 240 | archivo debería abrir Visual Studio. Sugerimos construir 241 | la configuración **RelWithDebugInfo**, pero todas funcionan. 242 | 243 | O si no, puedes construir para Windows en la línea de comandos de la siguiente manera: 244 | 245 | .. code:: bash 246 | 247 | cmake --build . --config RelWithDebInfo 248 | 249 | La cadena de versión en detalle 250 | =============================== 251 | 252 | La cadena de versión de Solidity está compuesta por 4 partes: 253 | 254 | - el número de la versión 255 | - etiqueta pre-release, en general en formato ``develop.YYYY.MM.DD`` o ``nightly.YYYY.MM.DD`` 256 | - commit en formato ``commit.GITHASH`` 257 | - la plataforma tiene número arbitrario de ítems, contiene detalles de la plataforma y el compilador 258 | 259 | Si hay modificaciones locales, el commit tendrá el sufijo ``.mod``. 260 | 261 | Éstas partes se combinan como es requerido por Semver, donde la etiqueta pre-release de Solidity equivale al pre-release de Semver y el commit Solidity y plataforma combinadas hacen el metadata del build de Semver. 262 | 263 | Un ejemplo de release: ``0.4.8+commit.60cc1668.Emscripten.clang``. 264 | 265 | Un ejemplo pre-release: ``0.4.9-nightly.2017.1.17+commit.6ecb4aa3.Emscripten.clang`` 266 | 267 | Información importante sobre versiones 268 | ====================================== 269 | 270 | Tras hacer un release, se incrementa el nivel de versión patch, porque asumimos que sólo 271 | siguen cambios de nivel de patch. Cuando se integran los cambios, la versión se aumenta 272 | de acuerdo a la versión Semver y la urgencia de los cambios. Finalmente, un release siempre se hace con la versión de la build nightly actual, pero sin el especificador ``prerelease``. 273 | 274 | Ejemplo: 275 | 276 | 0. se hace el release 0.4.0 277 | 1. el nightly build tiene versión 0.4.1 a partir de ahora 278 | 2. se introducen cambios compatibles - no hay cambio en versión 279 | 3. se introduce cambios no compatibles - la versión se aumenta a 0.5.0 280 | 4. se hace el release 0.5.0 281 | 282 | Este comportamiento funciona bien con la :ref:`versión pragma `. 283 | -------------------------------------------------------------------------------- /introduction-to-smart-contracts.rst: -------------------------------------------------------------------------------- 1 | ######################################### 2 | Introducción a los Contratos Inteligentes 3 | ######################################### 4 | 5 | .. _simple-smart-contract: 6 | 7 | ****************************** 8 | Un contrato inteligente simple 9 | ****************************** 10 | 11 | Vamos a comenzar con el ejemplo más básico. No pasa nada si no entiendes nada ahora, entraremos más en detalle posteriormente. 12 | 13 | Almacenamiento 14 | ============== 15 | 16 | :: 17 | 18 | pragma solidity ^0.4.0; 19 | 20 | contract SimpleStorage { 21 | uint storedData; 22 | 23 | function set(uint x) { 24 | storedData = x; 25 | } 26 | 27 | function get() constant returns (uint) { 28 | return storedData; 29 | } 30 | } 31 | 32 | La primera línea simplemente dice que el código fuente se ha escrito para la versión 0.4.0 de Solidity o en otra superior totalmente compatible (cualquiera anterior a la 0.5.0). Esto es para garantizar que el contrato no se comporte de una forma diferente con una versión más nueva del compilador. La palabra reservada ``pragma`` es llamada de esa manera porque, en general, los "pragmas" son instrucciones para el compilador que indican como este debe operar con el código fuente (p.ej.: `pragma once `_). . 33 | 34 | Un contrato para Solidity es una colección de código (sus *funciones*) y datos (su *estado*) que residen en una dirección específica en la blockchain de Ethereum. La línea ``uint storedData;`` declara una variable de estado llamada ``storedData`` del tipo ``uint`` (unsigned integer de 256 bits). Esta se puede entender como una parte única en una base de datos que puede ser consultada o modificada llamando a funciones del código que gestiona dicha base de datos. En el caso de Ethereum, este es siempre el contrato propietario. Y en este caso, las funciones ``set`` y ``get`` se pueden usar para modificar o consultar el valor de la variable. 35 | 36 | Para acceder a una variable de estado, no es necesario el uso del prefijo ``this.`` como es habitual en otros lenguajes. 37 | 38 | Este contrato no hace mucho todavía (debido a la infraestructura construída por Ethereum), simplemente permite a cualquiera almacenar un número accesible para todos sin un (factible) modo de prevenir la posibilidad de publicar este número. Por supuesto, cualquiera podría simplemente hacer una llamada ``set`` de nuevo con un valor diferente y sobrescribir el número inicial, pero este número siempre permanecería almacenado en la historía de la blockchain. Más adelante, veremos como imponer restricciones de acceso de tal manera que sólo tú puedas cambiar el número. 39 | 40 | .. index:: ! submoneda 41 | 42 | Ejemplo de Submoneda 43 | ==================== 44 | 45 | El siguiente contrato va a implementar la forma más sencilla de una criptomoneda. Se pueden generar monedas de la nada, pero sólo la persona que creó el contrato estará habilitada para hacerlo (es trivial implementar un esquema diferente de emisión). Es más, cualquiera puede enviar monedas a otros sin necesidad de registrarse con usuario y contraseña - sólo hace falta un par de claves de Ethereum. 46 | 47 | 48 | :: 49 | 50 | pragma solidity ^0.4.0; 51 | 52 | contract Coin { 53 | // La palabra clave "public" hace que dichas variables 54 | // puedan ser leídas desde fuera. 55 | address public minter; 56 | mapping (address => uint) public balances; 57 | 58 | // Los eventos permiten a los clientes ligeros reaccionar 59 | // de forma eficiente a los cambios. 60 | event Sent(address from, address to, uint amount); 61 | 62 | // Este es el constructor cuyo código 63 | // sólo se ejecutará cuando se cree el contrato. 64 | function Coin() { 65 | minter = msg.sender; 66 | } 67 | 68 | function mint(address receiver, uint amount) { 69 | if (msg.sender != minter) return; 70 | balances[receiver] += amount; 71 | } 72 | 73 | function send(address receiver, uint amount) { 74 | if (balances[msg.sender] < amount) return; 75 | balances[msg.sender] -= amount; 76 | balances[receiver] += amount; 77 | Sent(msg.sender, receiver, amount); 78 | } 79 | } 80 | 81 | Este contrato introduce algunos conceptos nuevos que vamos a detallar uno a uno. 82 | 83 | La línea ``address public minter;`` declara una variable de estado de tipo address (dirección) que es públicamente accesible. El tipo ``address`` es un valor de 160 bits que no permite operaciones aritméticas. Es apropiado para almacenar direcciones de contratos o pares de claves pertenecientes a personas externas. La palabra reservada ``public`` genera automáticamente una función que permite el acceso al valor actual de la variable de estado. Sin esta palabra reservada, otros contratos no tienen manera de acceder a la variable. 84 | Esta función sería algo como esto:: 85 | 86 | function minter() returns (address) { return minter; } 87 | 88 | Por supuesto, añadir una función exactamente como esa no funcionará porque deberíamos tener una función y una variable de estado con el mismo nombre, pero afortunadamente, has cogido la idea - el compilador se lo imagina por tí. 89 | 90 | .. index:: mapping 91 | 92 | La siguiente línea, ``mapping (address => uint) public balances;`` también crea una variable de estado pública, pero se trata de un tipo de datos más complejo. El tipo mapea direcciones a enteros sin signo. 93 | Los mapeos (Mappings) pueden ser vistos como tablas hash `hash tables `_ que son virtualmente inicializadas de tal forma que cada clave candidata existe y es mapeada a un valor cuya representación en bytes es todo ceros. 94 | Esta anología no va mucho más allá, ya que no es posible obtener una lista de todas las claves de un mapeo, ni tampoco una lista de todos los valores. Por eso hay que tener en cuenta (o mejor, conservar una lista o usar un tipo de datos más avanzado) lo que se añade al mapping o usarlo en un contexto donde no es necesario, como este caso. La función getter creada mediante la palabra reservada ``public`` es un poco más compleja en este caso. De forma aproximada, es algo parecido a lo siguiente:: 95 | 96 | function balances(address _account) returns (uint) { 97 | return balances[_account]; 98 | } 99 | 100 | Como se puede ver, se puede usar esta función para, de forma sencilla, consultar el balance de una única cuenta. 101 | 102 | .. index:: event 103 | 104 | La línea ``event Sent(address from, address to, uint amount);`` declara un evento que es disparado en la última línea de la ejecución de 105 | ``send``. Las interfaces de usuario (como las de servidor, por supuesto) pueden escuchar esos eventos que están siendo disparados en la blockchain sin mucho coste. Tan pronto son disparados, el listener también recibirá los argumentos ``from``, ``to`` y ``amount``, que hacen más fácil trazar las transacciones. Con el fin de escuchar este evento, se podría usar :: 106 | 107 | Coin.Sent().watch({}, '', function(error, result) { 108 | if (!error) { 109 | console.log("Coin transfer: " + result.args.amount + 110 | " coins were sent from " + result.args.from + 111 | " to " + result.args.to + "."); 112 | console.log("Balances now:\n" + 113 | "Sender: " + Coin.balances.call(result.args.from) + 114 | "Receiver: " + Coin.balances.call(result.args.to)); 115 | } 116 | }) 117 | 118 | Es interesante como la función generada automáticamente ``balances`` es llamada desde la interfaz de usuario. 119 | 120 | .. index:: coin 121 | 122 | La función especial ``Coin`` es el constructor que se ejecuta durante la creación de un contrato y no puede ser llamada con posterioridad. Almacena permanentemente la dirección de la persona que crea el contrato: ``msg`` (junto con ``tx`` y ``block``) es una variable global mágica que contiene propiedades que permiten el acceso a la blockchain. ``msg.sender`` es siempre la dirección desde donde se origina la llamada a la función actual (externa). 123 | 124 | Finalmente, las funciones que realmente habrá en el contrato y que podrán ser llamadas por usuarios y contratos como son ``mint`` y ``send``. Si se llama a ``mint`` desde una cuenta distinta a la del creador del contrato, no ocurrirá nada. Por otro lado, ``send`` puede ser usado por todos (los que ya tienen algunas de estas monedas) para enviar monedas a cualquier otro. Hay que tener en cuenta que si se usa este contrato para enviar monedas a una dirección, no se verá reflejado cuando se busque la dirección en un explorador de la blockchain por el hecho de enviar monedas, y que los balances sólo serán guardados en el almacenamiento de este contrato de moneda. Con el uso de eventos es relativamente sencillo crear un "explorador de la blockchain" que monitorice las transacciones y los balances de la nueva moneda. 125 | 126 | .. _blockchain-basics: 127 | 128 | ************************* 129 | Fundamentos de Blockchain 130 | ************************* 131 | 132 | Las blockchains son un concepto no muy difícil de entender para desarrolladores. La razón es que la mayoría de las complicaciones (minería, `hashes `_, `criptografa de curva elíptica `_, `redes P2P `_, etc.) están justo ahí para proveer un conjunto de funcionalidades y espectativas. Una vez que aceptas estas funcionalidades tal cual vienen dadas, no tienes que preocuparte por la tecnología que lleva inmersa - o, ¿Tienes que saber realmente cómo funciona internamente Amazon AWS para poder usarlo?. 133 | 134 | .. index:: transaction 135 | 136 | Transacciones 137 | ============= 138 | 139 | Una blockchain es una base de datos transaccional globalmente compartida. Esto quiere decir que todos pueden leer las entradas en la base de datos simplemente participando en la red. Si quieres cambiar algo en la base de datos, tienes que crear una transacción a tal efecto que tiene que ser aceptada por todos los demás. 140 | La palabra transacción implica que el cambio que quieres hacer (asumiendo que quieres cambiar dos valores al mismo tiempo) o se aplica por completo, o no se realiza. Es más, mientras tu transacción es aplicada en la base de datos, ninguna otra transacción puede modificarla. 141 | 142 | Como ejemplo, imagine una tabla que lista los balances de todas las cuentas en una divisa electrónica. Si se solicita una transferencia de una cuenta a otra, la naturaleza transaccional de la base de datos garantiza que la cantidad que es sustraída de una cuenta, es añadida en la otra. Si por la razón que sea, no es posible añadir la cantidad a la cuenta de destino, la cuenta origen tampoco se modifica. 143 | 144 | Yendo más allá, una transacción es siempre firmada criptográficamente por el remitente (creador). Esto la hace más robusta para garantizar el acceso a modificaciones específicas de la base de datos. En el ejemplo de divisas electrónicas, un simple chequeo asegura que sólo la persona que posee las claves de la cuenta puede transferir dinero desde ella. 145 | 146 | .. index:: ! block 147 | 148 | Bloques 149 | ======= 150 | 151 | Un obstáculo mayor que sobrepasar es el que, en términos de Bitcoin, se llama ataque de "doble gasto": ¿Qué ocurre si dos transacciones existentes en la red quieren borrar una cuenta?, ¿Un conflicto?. 152 | 153 | La respuesta abstracta a esto es que no tienes de qué preocuparte. El orden de las transacciones se seleccionará por ti, las transacciones se aglutinarán en lo que es llamado "bloque" y entonces serán ejecutadas y distribuídas entre todos los nodos participantes. Si dos transacciones se contradicen, la que concluye en segundo lugar será rechazada y no formará parte del bloque. 154 | 155 | Estos bloques forman una secuencia lineal en el tiempo de la que viene la palabra cadena de bloques o "blockchain". Los bloques son añadidos a la cadena en intervalos regulares - para Ethereum esto viene a significar cada 17 segundos. 156 | 157 | Como parte del "mecanismo de selección de orden" (que se conoce como minería), tiene que pasar que los bloques sean revertidos de cuando en cuando, pero sólo en el extremo o "tip" de la cadena. Cuantos más bloques se añaden encima, menos probable es. En ese caso, lo que ocurre es que tus transacciones son revertidas e incluso borradas de la blockchain, pero cuanto más esperes, menos probable será. 158 | 159 | 160 | .. _the-ethereum-virtual-machine: 161 | 162 | .. index:: !evm, ! ethereum virtual machine 163 | 164 | *************************** 165 | Máquina Virtual de Ethereum 166 | *************************** 167 | 168 | Introducción 169 | ============ 170 | 171 | La máquina virtual de Ethereum (EVM por sus siglas en inglés) es un entorno de ejecución de contratos inteligentes en Ethereum. Va más allá de una configuración tipo sandbox ya que se encuentra totalmente aislada, lo que significa que el código que se ejecuta en la EVM no tiene acceso a la red, ni al sistema de ficheros, ni a ningún otro proceso. Incluso los contratos inteligentes tienen acceso limitado a otros contratos inteligentes. 172 | 173 | .. index:: ! account, address, storage, balance 174 | 175 | Cuentas 176 | ======= 177 | 178 | Hay dos tipos de cuentas en Ethereum que comparten el mismo espacio de dirección: **Cuentas externas** que están controladas por un par de claves pública-privada (p-ej.: humanos) y **Cuentas contrato** que están controladas por el código almacenado conjuntamente con la cuenta. 179 | 180 | La dirección de una cuenta externa viene determinada por la clave pública mientras que la dirección de la cuenta contrato se define en el momento en que se crea dicho contrato (se deriva de la dirección del creador y del número de transacciones enviadas desde esa dirección, el llamado "nonce"). 181 | 182 | Independientemente de que la cuenta almacene código, los dos tipos se tratan de forma equitativa por la EVM. 183 | 184 | Cada cuenta tiene un almacenamiento persistente clave-valor que mapea palabras de 256 bits a palabras de 256 bits llamado **almacenamiento**. 185 | 186 | Además, cada cuenta tiene un **balance** en Ether (en "Wei" para ser exactos) que puede ser modificado enviando transacciones que incluyen Ether. 187 | 188 | .. index:: ! transaction 189 | 190 | Transacciones 191 | ============= 192 | 193 | Una transacción es un mensaje que se envía de una cuenta a otra (que debería ser la misma o la especial cuenta-cero, ver más adelante). Puede incluir datos binarios (payload) y Ether. 194 | 195 | Si la cuenta destino contiene código, este es ejecutado y el payload se provee como dato de entrada. 196 | 197 | Si la cuenta destino es la cuenta-cero (la cuenta con dirección ``0``), la transacción crea un **nuevo contrato**. Como se ha mencionado, la dirección del contrato no es la dirección cero, sino de una dirección derivada del emisor y su número de transacciones enviadas (el "nonce"). Los datos binarios de la transacción que crea el contrato son obtenidos como bytecode por la EVM y ejecutados. La salida de esta ejecución es permanentemente almacenada como el código del contrato. Esto significa que para crear un contrato, no se envía el código actual del contrato, realmente se envía código que nos devuelve ese código final. 198 | 199 | .. index:: ! gas, ! gas price 200 | 201 | Gas 202 | === 203 | 204 | En cuanto se crean, cada transacción se carga con una determinada cantidad de **gas**, 205 | cuyo propósito es limitar la cantidad de trabajo que se necesita para ejecutar la transacción y pagar por esta ejecución. Mientras la EVM ejecuta la transacción, el gas se gasta gradualmente según unas reglas específicas. 206 | 207 | El **precio del gas** (gas price) es un valor establecido por el creador de la transacción, quien tiene que pagar el ``gas_price * gas`` desde la cuenta de envío. Si queda algo de gas después de la ejecución, se le reembolsa. 208 | 209 | Si se ha gastado todo el gas en un punto (p.ej.: es negativo), 210 | se lanza una excepción de out-of-gas, que revierte todas las modificaciones hechas al estado en el contexto de la ejecución actual. 211 | 212 | .. index:: ! storage, ! memory, ! stack 213 | 214 | Almacenamiento, Memoria y la Pila 215 | ================================= 216 | 217 | Cada cuenta tiene un área de memoria persistente que se llama **almacenamiento**. 218 | El almacenamiento es un almacén clave-valor que mapea palabras de 256 bits con palabras de 256 bits. 219 | No es posible enumerar el almacenamiento interno desde un contrato y es comparativamente costoso leer y, más todavía, modificar el almacenamiento. Un contrato no pueder leer ni escribir en otro almacenamiento que no sea el suyo. 220 | 221 | La segunda área de memoria se conoce como **memoria**, de la que un contrato obtiene de forma ágil una instancia clara de cada message call (llamada de mensaje). La memoria es lineal y puede ser tratada a nivel de byte, pero las lecturas están limitadas a un ancho de 256 bits, mientras que las escrituras pueden ser tanto de 8 bits como de 256 bits de ancho. La memoria se expande por palabras (256 bits), cuando se accede (tanto para leer o escribir) a una palabra de memoria sin modificar previamente (p.ej.: cualquier offset de una palabra). En el momento de expansión, se debe pagar el coste en gas. La memoria es más costosa cuanto más crece (escala cuadráticamente). 222 | 223 | La EVM no es una máquina de registro, es una máquina de pila por lo que todas las operaciones se hacen en un área llamada la **pila**. Tiene un espacio máximo de 1024 elementos y contiene palabras de 256 bits. El acceso a la pila está limitado a su cima de la siguiente manera: 224 | Es posible copiar uno de los 16 elementos superiores a la cima de la pila o intercambiar el elemento superior justo después de uno de los 16 elementos superiores. 225 | El resto de operaciones cogen los dos elementos más superiores (o uno, o más, dependiendo de la operación) de la pila y ponen el resultado en ella. Por supuesto, es posible mover elementos de la pila al almacenamiento o a la memoria, pero no es posible acceder simplemente a elementos arbitrarios más profundos dentro de la pila sin, primeramente, borrar los que ya están encima. 226 | 227 | .. index:: ! instruction 228 | 229 | Conjunto de instrucciones 230 | ========================= 231 | 232 | El conjunto de instrucciones de la EVM se mantiene mínimo con el objetivo de evitar implementaciones incorrectas que podrían causar problemas de consenso. Todas las instrucciones operan con el tipo de datos básico, palabras de 256 bits. 233 | Las operaciones de aritmética habitual, bit, lógica y de comparación están presentes. 234 | Se permiten tanto los saltos condicionales como los no condicionales. Es más, los contratos pueden acceder a propiedades relevantes del bloque actual como su número y timestamp. 235 | 236 | .. index:: ! message call, function;call 237 | 238 | Message Calls 239 | ============= 240 | 241 | Los contratos pueden llamar a otros contratos o enviar Ether a cuentas que no sean de contratos usando message calls. Los Message calls son similares a las transacciones, en el sentido de que tienen un origen, un destino, datos, Ether, gas y datos de retorno. De hecho, cada transacción consiste en un message call de alto nivel que de forma consecutiva puede crear message calls posteriores. 242 | 243 | Un contrato puede decidir cuánto de su **gas** restante podría ser enviado con el message call interno y cuánto quiere retener. Si ocurre una excepción de out-of-gas durante la llamada interna (o cualquier otra excepción), se mostrará como un valor de error introducido dentro de la pila. En este caso, sólo se gasta el gas enviado junto con la llamada. 244 | En Solidity, el contrato que hace la llamada causa una excepción manual por defecto en estas situaciones, por lo que esas excepciones ascienden en la pila de llamada. 245 | 246 | Como se ha mencionado, el contrato llamado (que podría ser el mismo que el que hace la llamada) recibirá una instancia de memoria vacía y tendrá acceso a los datos de la llamada - que serán provistos en un área separada que se llama **calldata**. 247 | Después de finalizar su ejecución, puede devolver datos que serán almacenados en una localización en la memoria del que hace la llamada que éste ha reservado previamente. 248 | 249 | Las llamadas están **limitadas** a la profundidad de 1024, lo que quiere decir que para operaciones más complejas, se debería preferir bucles sobre llamadas recursivas. 250 | 251 | .. index:: delegatecall, callcode, library 252 | 253 | Delegatecall / Callcode y librerías 254 | =================================== 255 | 256 | Existe una variante especial de message call llamada **delegatecall** 257 | que es idéntica a un message call con la excepción de que el código en la dirección destino se ejecuta en el contexto del que hace la llamada y ``msg.sender`` y ``msg.value`` no cambian sus valores. 258 | 259 | Esto significa que un contrato puede cargar código dinámicamente desde una dirección diferente en tiempo de ejecución. El almacenamiento, la dirección actual y el balance siguen referenciando al contrato que realiza la llamada, sólo se coge el código desde la dirección llamada. 260 | 261 | Esto hace posible implementar la funcionalidad de "librería" en Solidity: 262 | Código de librería reusable que se puede aplicar a un almacenamiento de contrato, por ejemplo, con el fin de implementar una estructura de datos compleja. 263 | 264 | .. index:: log 265 | 266 | Logs 267 | ==== 268 | 269 | Es posible almacenar datos en una estructura de datos indexada que mapea todo el recorrido hasta el nivel de bloque. Esta funcionalidad llamada **logs** se usa en Solidity para implementar **eventos**. 270 | Los contratos no pueden acceder a los datos del log después de crearse, pero pueden ser accedidos desde fuera de la blockchain de forma eficiente. Como parte de los datos del log se guardan en `bloom filters `_ (Filtro de Bloom), es posible buscar estos datos eficientemente y criptográficamente de manera segura, por lo que los otros miembros de la red que no se han descargado la blockchain entera ("light clients") todavía pueden buscarlos. 271 | 272 | .. index:: contract creation 273 | 274 | Creación 275 | ======== 276 | 277 | Los contratos pueden incluso crear otros contratos usando un opcode especial (p.ej.: ellos no llaman simplemente a la dirección cero). La única diferencia entre estos **create calls** y los message calls normales es que los datos son ejecutados y el resultado almacenado como código y el caller / creador recibe la dirección del nuevo contrato en la pila. 278 | 279 | .. index:: selfdestruct 280 | 281 | Auto-destrucción 282 | ================ 283 | 284 | La única posibilidad de borrar el código de la blockchain es cuando un contrato en esa dirección realiza una operación de ``selfdestruct``. Los Ether restantes almacenados en esa dirección son enviados al destinatario designado y, entonces, se borran el almacenamiento y el código del estado. 285 | 286 | .. warning:: Aunque un contrato no contenga una llamada a ``selfdestruct``, 287 | todavía podría hacer esa operación mediante ``delegatecall`` o ``callcode``. 288 | 289 | .. note:: La eliminación de contratos antiguos puede, o no, ser implementada en clientes de Ethereum. Adicionalmente, los nodos de archivo podrían elegir mantener el almacenamiento del contrato y el código de forma indefinida. 290 | 291 | .. note:: Actualmente las **cuentas externas** no se pueden borrar del estado. 292 | -------------------------------------------------------------------------------- /layout-of-source-files.rst: -------------------------------------------------------------------------------- 1 | ******************************************** 2 | Composición de un fichero fuente de Solidity 3 | ******************************************** 4 | 5 | Los ficheros fuente pueden contener un número arbitrario de definiciones de contrato, incluir directivas y directivas de pragma. 6 | 7 | .. index:: ! pragma, version 8 | 9 | .. _version_pragma: 10 | 11 | Versión de Pragma 12 | ================= 13 | 14 | Es altamente recomendable anotar los ficheros fuente con la versión de pragma para impedir que se compilen con una version posterior del compilador que podría introducir cambios incompatibles. Intentamos mantener este tipo de cambios al mínimo y que los cambios que introduzcamos y modifiquen la semántica requieran también un cambio en la sintáxis, pero esto no siempre es posible. Por ese motivo, siempre es buena idea repasar el registro de cambios por lo menos para las nuevas versiones que contienen cambios de ruptura. Estas nuevas versiones siempre tendrán un número de versión del tipo ``0.x.0`` o ``x.0.0``. 15 | 16 | La versión de pragma se usa de la siguiente manera: 17 | 18 | pragma solidity ^0.4.0; 19 | 20 | Un fichero como este no se compilará con un compilador con una versión anterior a ``0.4.0`` y tampoco funcionará con un compilador que tiene una versión posterior a ``0.5.0`` (se especifíca esta segunda condición usando el ``^``). La idea detrás de esto es que no va a haber un cambio de ruptura antes de la versión ``0.5.0``, así que podemos estar seguro de que nuestro código se compilará de la manera en que nosotros esperamos. No fijamos la versión exacta del compilador, de manera que podemos liberar nuevas versiones que corrigen bugs. 21 | 22 | Se puede especificar reglas mucho más complejas para la versión del compilador, la expresión sigue las utilizadas por `npm `_. 23 | 24 | .. index:: source file, ! import 25 | 26 | .. _import: 27 | 28 | Importar otros ficheros fuente 29 | ============================== 30 | 31 | Sintáxis y semántica 32 | -------------------- 33 | 34 | Solidity soporta la importación de declaraciones, que son muy similares a las que se hacen en JavaScript (a partir de ES6), aunque Solidity no conoce el concepto de "default export". 35 | 36 | A nivel global, se puede usar la importación de declaraciones de la siguiente manera: 37 | 38 | :: 39 | 40 | import "filename"; 41 | 42 | Esta declaración importa todos los símbolos globales de "filename" (junto con los símbolos importados desde allí) en el alcance global actual (diferente que en ES6 pero compatible con versiones anteriores de Solidity). 43 | 44 | :: 45 | 46 | import * as symbolName from "filename"; 47 | 48 | ...crea un nuevo símbolo global ``symbolName`` cuyos miembros son todos los símbolos globales de ``"filename"``. 49 | 50 | :: 51 | 52 | import {symbol1 as alias, symbol2} from "filename"; 53 | 54 | ...crea un nuevo símbolo global ``alias`` y ``symbol2`` que referencian respectivamente ``symbol1`` y ``symbol2`` desde ``"filename"``. 55 | 56 | Esta otra sintaxis no forma parte de ES6 pero es probablemente conveniente: 57 | 58 | :: 59 | 60 | import "filename" as symbolName; 61 | 62 | lo que es equivalente a ``import * as symbolName from "filename";``. 63 | 64 | Ruta 65 | ---- 66 | 67 | En lo que hemos visto más arriba, ``filename`` siempre se trata como una ruta con el ``/`` como separador de directorio, ``.`` como el directorio actual y ``..`` como el directorio padre. Cuando ``.`` o ``..`` es seguido por un carácter excepto ``/``, no se considera como el directorio actual o directorio padre. Se tratan todos los nombres de ruta como rutas absolutas, a no ser que empiecen por ``.`` o el directorio padre ``..``. 68 | 69 | Para importar un fichero ``x`` desde el mismo directorio que el fichero actual, se usa `import "./x" as x;``. Si en lugar de esa expresión se usa ``import "x" as x;``, podría ser que se referencie un fichero distinto (en un "include directory" global). 70 | 71 | Cómo se resuelve la ruta depende del compilador (ver más abajo). En general, la jerarquía de directorios no necesita mapear estrictamente su sistema local de ficheros, también puede mapear recursos que se descubren con por ejemplo ipfs, http or git. 72 | 73 | Uso en compiladores actuales 74 | ---------------------------- 75 | 76 | Cuando se invoca el compilador, no sólo se puede especificar la manera en que se descubre el primer elemento de la ruta, también es posible especificar un prefijo de ruta de remapeo, de tal manera que por ejemplo ``github.com/ethereum/dapp-bin/library`` se remapee por ``/usr/local/dapp-bin/library`` y el compilador lea el fichero desde allí. Si bien se pueden hacer múltiples remapeos, se intentará primero con el remapeo con la clave más larga. Esto permite "fallback-remapping" con, por ejemplo, ``""`` mapea a ``/usr/local/include/solidity``. Además, estos remapeos pueden depender del contexto, lo que permite configurar paquetes para importar por ejemplo diferentes versiones de una librería con el mismo nombre. 77 | 78 | **solc**: 79 | 80 | Para solc (el compilador de línea de comando), los remapeos se proporcionan como argumentos ``context:prefix=target``, donde tanto la parte ``context:`` como la parte ``=target`` son opcionales (en este caso target toma por defecto el valor de prefix). Todos los valores que remapean que son ficheros estándares son compilados (incluyendo sus dependencias). Este mecanismo es completamente compatible con versiones anteriores (siempre y cuando ningún nombre de fichero contenga = o :) y por lo tanto no es un cambio de ruptura. Todas las importaciones en los ficheros en el directorio ``context`` (o debajo de él) que importa un fichero que empieza con un ``prefix`` están redireccionados reemplazando ``prefix`` por ``target``. 81 | 82 | Como ejemplo, si clonas ``github.com/ethereum/dapp-bin/`` en tu local a ``/usr/local/dapp-bin``, puedes usar lo siguiente en tu código fuente: 83 | 84 | :: 85 | 86 | import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol" as it_mapping; 87 | 88 | y luego se corre el compilador de esa manera: 89 | 90 | .. code-block:: bash 91 | 92 | solc github.com/ethereum/dapp-bin/=/usr/local/dapp-bin/ source.sol 93 | 94 | Como ejemplo un poco más complejo, imaginemos que nos basamos en algún módulo que utiliza una versión muy antigua de dapp-bin. Esta versión anterior de dapp-bin se comprueba en ``/usr/local/dapp-bin_old``, y luego se puede usar: 95 | 96 | .. code-block:: bash 97 | 98 | solc module1:github.com/ethereum/dapp-bin/=/usr/local/dapp-bin/ \ 99 | module2:github.com/ethereum/dapp-bin/=/usr/local/dapp-bin_old/ \ 100 | source.sol 101 | 102 | así, todas las importaciones en ``module2`` apuntan a la versión anterior pero las importaciones en ``module1`` consiguen la nueva versión. 103 | 104 | Nótese que solc sólo permite incluir ficheros desde algunos directorios. Tienen que estar en el diretorio (o subdirectorio) de uno de los ficheros fuente explícitamente especificado o en el directorio (o subdirectorio) de un target de remapeo. Si se desea permitir inclusiones directas absolutas, sólo hace falta añadir el ``=/`` de remapeo. 105 | 106 | Si hay múltiples remapeos que conducen a un fichero válido, se elige el remapeo con el prefijo común más largo. 107 | 108 | **Remix**: 109 | 110 | `Remix `_ proporciona un remapeo automático para github y también recupera automáticamente el fichero desde la red: se puede importar el mapeo iterable con por ejemplo ``import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol" as it_mapping;``. 111 | 112 | A futuro se podrían añadir otros proveedores de código fuente. 113 | 114 | 115 | .. index:: ! comment, natspec 116 | 117 | Comentarios 118 | =========== 119 | 120 | Se aceptan los comentarios de línea simple (``//``) y los comentarios de múltiples líneas (``/*...*/``). 121 | 122 | :: 123 | 124 | // Esto es un comentario de línea simple. 125 | 126 | /* 127 | Esto es un comentario 128 | de múltiples líneas. 129 | */ 130 | 131 | 132 | Adicionalmente, existe otro tipo de comentario llamado natspec, pero la documentación todavía no está escrita. Estos comentarios se escriben con tres barras ***oblícuas (``///``) o como un bloque de comentarios con doble asterísco (``/** ... */``) y se deben usar justo arriba de las declaraciones de función o instrucciones. Para documentar funciones, anotar condiciones para la verificación formal y para proporcionar un **texto de confirmación** al usuario cuando intenta invocar una función, se puede usar etiquetas del tipo `Doxygen `_ dentro de estos comentarios. 133 | 134 | En el siguiente ejemplo, documentamos el título del contrato, la explicación para los dos parametros de entrada y para los dos valores de retorno. 135 | 136 | :: 137 | 138 | pragma solidity ^0.4.0; 139 | 140 | /** @title Shape calculator.*/ 141 | contract shapeCalculator{ 142 | /**@dev Calculates a rectangle's surface and perimeter. 143 | * @param w Width of the rectangle. 144 | * @param h Height of the rectangle. 145 | * @return s The calculated surface. 146 | * @return p The calculated perimeter. 147 | */ 148 | function rectangle(uint w, uint h) returns (uint s, uint p) { 149 | s = w * h; 150 | p = 2 * (w + h); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | Vector 1 8 | Created with Sketch. 9 | 10 | 11 | 12 | 14 | 16 | 18 | 20 | 22 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=_build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 10 | set I18NSPHINXOPTS=%SPHINXOPTS% . 11 | if NOT "%PAPER%" == "" ( 12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% 14 | ) 15 | 16 | if "%1" == "" goto help 17 | 18 | if "%1" == "help" ( 19 | :help 20 | echo.Please use `make ^` where ^ is one of 21 | echo. html to make standalone HTML files 22 | echo. dirhtml to make HTML files named index.html in directories 23 | echo. singlehtml to make a single large HTML file 24 | echo. pickle to make pickle files 25 | echo. json to make JSON files 26 | echo. htmlhelp to make HTML files and a HTML help project 27 | echo. qthelp to make HTML files and a qthelp project 28 | echo. devhelp to make HTML files and a Devhelp project 29 | echo. epub to make an epub 30 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 31 | echo. text to make text files 32 | echo. man to make manual pages 33 | echo. texinfo to make Texinfo files 34 | echo. gettext to make PO message catalogs 35 | echo. changes to make an overview over all changed/added/deprecated items 36 | echo. xml to make Docutils-native XML files 37 | echo. pseudoxml to make pseudoxml-XML files for display purposes 38 | echo. linkcheck to check all external links for integrity 39 | echo. doctest to run all doctests embedded in the documentation if enabled 40 | goto end 41 | ) 42 | 43 | if "%1" == "clean" ( 44 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 45 | del /q /s %BUILDDIR%\* 46 | goto end 47 | ) 48 | 49 | 50 | %SPHINXBUILD% 2> nul 51 | if errorlevel 9009 ( 52 | echo. 53 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 54 | echo.installed, then set the SPHINXBUILD environment variable to point 55 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 56 | echo.may add the Sphinx directory to PATH. 57 | echo. 58 | echo.If you don't have Sphinx installed, grab it from 59 | echo.http://sphinx-doc.org/ 60 | exit /b 1 61 | ) 62 | 63 | if "%1" == "html" ( 64 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 65 | if errorlevel 1 exit /b 1 66 | echo. 67 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 68 | goto end 69 | ) 70 | 71 | if "%1" == "dirhtml" ( 72 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 73 | if errorlevel 1 exit /b 1 74 | echo. 75 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 76 | goto end 77 | ) 78 | 79 | if "%1" == "singlehtml" ( 80 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 81 | if errorlevel 1 exit /b 1 82 | echo. 83 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 84 | goto end 85 | ) 86 | 87 | if "%1" == "pickle" ( 88 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 89 | if errorlevel 1 exit /b 1 90 | echo. 91 | echo.Build finished; now you can process the pickle files. 92 | goto end 93 | ) 94 | 95 | if "%1" == "json" ( 96 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 97 | if errorlevel 1 exit /b 1 98 | echo. 99 | echo.Build finished; now you can process the JSON files. 100 | goto end 101 | ) 102 | 103 | if "%1" == "htmlhelp" ( 104 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 105 | if errorlevel 1 exit /b 1 106 | echo. 107 | echo.Build finished; now you can run HTML Help Workshop with the ^ 108 | .hhp project file in %BUILDDIR%/htmlhelp. 109 | goto end 110 | ) 111 | 112 | if "%1" == "qthelp" ( 113 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 114 | if errorlevel 1 exit /b 1 115 | echo. 116 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 117 | .qhcp project file in %BUILDDIR%/qthelp, like this: 118 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Solidity.qhcp 119 | echo.To view the help file: 120 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Solidity.ghc 121 | goto end 122 | ) 123 | 124 | if "%1" == "devhelp" ( 125 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 126 | if errorlevel 1 exit /b 1 127 | echo. 128 | echo.Build finished. 129 | goto end 130 | ) 131 | 132 | if "%1" == "epub" ( 133 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 134 | if errorlevel 1 exit /b 1 135 | echo. 136 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 137 | goto end 138 | ) 139 | 140 | if "%1" == "latex" ( 141 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 142 | if errorlevel 1 exit /b 1 143 | echo. 144 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 145 | goto end 146 | ) 147 | 148 | if "%1" == "latexpdf" ( 149 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 150 | cd %BUILDDIR%/latex 151 | make all-pdf 152 | cd %BUILDDIR%/.. 153 | echo. 154 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 155 | goto end 156 | ) 157 | 158 | if "%1" == "latexpdfja" ( 159 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 160 | cd %BUILDDIR%/latex 161 | make all-pdf-ja 162 | cd %BUILDDIR%/.. 163 | echo. 164 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 165 | goto end 166 | ) 167 | 168 | if "%1" == "text" ( 169 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 170 | if errorlevel 1 exit /b 1 171 | echo. 172 | echo.Build finished. The text files are in %BUILDDIR%/text. 173 | goto end 174 | ) 175 | 176 | if "%1" == "man" ( 177 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 178 | if errorlevel 1 exit /b 1 179 | echo. 180 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 181 | goto end 182 | ) 183 | 184 | if "%1" == "texinfo" ( 185 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo 186 | if errorlevel 1 exit /b 1 187 | echo. 188 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. 189 | goto end 190 | ) 191 | 192 | if "%1" == "gettext" ( 193 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale 194 | if errorlevel 1 exit /b 1 195 | echo. 196 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale. 197 | goto end 198 | ) 199 | 200 | if "%1" == "changes" ( 201 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 202 | if errorlevel 1 exit /b 1 203 | echo. 204 | echo.The overview file is in %BUILDDIR%/changes. 205 | goto end 206 | ) 207 | 208 | if "%1" == "linkcheck" ( 209 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 210 | if errorlevel 1 exit /b 1 211 | echo. 212 | echo.Link check complete; look for any errors in the above output ^ 213 | or in %BUILDDIR%/linkcheck/output.txt. 214 | goto end 215 | ) 216 | 217 | if "%1" == "doctest" ( 218 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 219 | if errorlevel 1 exit /b 1 220 | echo. 221 | echo.Testing of doctests in the sources finished, look at the ^ 222 | results in %BUILDDIR%/doctest/output.txt. 223 | goto end 224 | ) 225 | 226 | if "%1" == "xml" ( 227 | %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml 228 | if errorlevel 1 exit /b 1 229 | echo. 230 | echo.Build finished. The XML files are in %BUILDDIR%/xml. 231 | goto end 232 | ) 233 | 234 | if "%1" == "pseudoxml" ( 235 | %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml 236 | if errorlevel 1 exit /b 1 237 | echo. 238 | echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. 239 | goto end 240 | ) 241 | 242 | :end 243 | -------------------------------------------------------------------------------- /security-considerations.rst: -------------------------------------------------------------------------------- 1 | .. _security_considerations: 2 | 3 | ############################ 4 | Consideraciones de seguridad 5 | ############################ 6 | 7 | Aunque en general es bastante fácil hacer software que funcione como esperamos, 8 | es mucho más difícil de chequear que nadie lo pueda usar de alguna forma que **no** 9 | fue anticipada. 10 | 11 | En solidity, esto es aún más importante ya que se pueden usar los contratos 12 | inteligentes para mover tokens, o posiblemente, cosas aún más valiosas. Además, 13 | cada ejecución de un contrato inteligente es pública, y a ello se suma 14 | que el código fuente muchas veces está disponible. 15 | 16 | Por supuesto, siempre se tiene que considerar lo que está en juego: 17 | Puedes comparar un contrato inteligente con un servicio web que está abierto 18 | al público (y por lo tanto, también a gente malintencionada) y quizá 19 | de código abierto. 20 | Si sólo se guarda la lista de compras en ese servicio web, puede que no tengas 21 | que tener mucho cuidado, pero si accedes a tu cuenta bancaria usando ese servicio, 22 | deberíás tener más cuidado. 23 | 24 | Esta sección nombrará algunos errores comunes y recomendaciones de seguridad 25 | generales pero no puede, por supuesto, ser una lista completa. Además, recordar 26 | que incluso si tu contrato inteligente está libre de errores, el compilador 27 | o la plataforma puede que los tenga. Una lista de errores de seguridad públicamente 28 | conocidos del compilador puede encontrarse en: :ref:`lista de errores conocidos`, 29 | la lista también es legible por máquina. Nótese que hay una recompensa 30 | por encontrar errores (bug-bounty) que cubre el generador de código del compilador de Solidity. 31 | 32 | Como siempre ocurre con la documentación de código abierto, por favor, ayúdanos a extender 33 | esta sección, ¡especialmente con algunos ejemplos! 34 | 35 | 36 | *************** 37 | Errores Comunes 38 | *************** 39 | 40 | Información privada y aleatoriedad 41 | ================================== 42 | 43 | Todo lo que usas en un contrato inteligente es públicamente visible, incluso 44 | variables locales y variables de estado marcadas como ``private``. 45 | 46 | Es bastante complejo usar números aleatorios en contratos inteligentes si no 47 | quieres que los mineros puedan hacer trampa. 48 | 49 | Reentrada 50 | ========= 51 | 52 | Cualquier interacción desde un contrato (A) con otro contrato (B) y cualquier 53 | transferencia de Ether, le da el control a ese contrato (B). Esto hace posible 54 | que B vuelva a llamar a A antes de terminar la interacción. Para dar un ejemplo, 55 | el siguiente código contiene un error (esto es sólo un snippet y no un contrato 56 | completo): 57 | 58 | :: 59 | 60 | pragma solidity ^0.4.0; 61 | 62 | // ESTE CONTRATO CONTIENE UN ERROR - NO USAR 63 | contract Fund { 64 | /// Mapping de distribución de ether del contrato. 65 | mapping(address => uint) shares; 66 | /// Retira tu parte. 67 | function withdraw() { 68 | if (msg.sender.send(shares[msg.sender])) 69 | shares[msg.sender] = 0; 70 | } 71 | } 72 | 73 | El problema aquí no es tan grave por el límite de gas de la función 74 | ``send``, pero aun así, expone una debilidad: una transferencia de Ether 75 | siempre incluye ejecución de código, así que el receptor puede ser un 76 | contrato que vuelve a llamar a ``withdraw``. Esto le permitiría obtener 77 | múltiples devoluciones, y por lo tanto, vaciar el Ether del contrato. 78 | 79 | Para evitar reentradas, puedes usar el orden Comprobaciones-Efectos-Interacciones 80 | como detallamos aquí: 81 | 82 | :: 83 | 84 | pragma solidity ^0.4.11; 85 | 86 | contract Fund { 87 | /// Mapping de distribución de ether del contrato. 88 | mapping(address => uint) shares; 89 | /// Retira tu parte. 90 | function withdraw() { 91 | var share = shares[msg.sender]; 92 | shares[msg.sender] = 0; 93 | msg.sender.transfer(share); 94 | } 95 | } 96 | 97 | Nótese que las reentradas no sólo son un riesgo al transferir Ether, sino 98 | de cualquier ejecución de una función de otro contrato. Además, también tienes que 99 | considerar situaciones de multi-contrato. Un contrato ejecutado podría modificar el 100 | estado de otro contrato del cual dependes. 101 | 102 | Límite de gas y bucles 103 | ====================== 104 | 105 | Los bucles que no tienen un número fijo de iteraciones, por ejemplo, bucles que dependen de valores de almacenamiento, tienen que 106 | usarse con cuidado: 107 | Dado el límite de gas del bloque, las transacciones sólo pueden consumir una cierta cantidad de gas. Ya sea explícitamente, 108 | o por una operación normal, el número de iteraciones en un bucle puede crecer más allá del límite de gas, lo que puede causar que el 109 | contrato se detenga por completo en un cierto punto. Esto no se aplica a funciones ``constant`` que sólo se llaman para 110 | leer información de la blockchain. Pero aun así, estas funciones pueden ser llamadas por otros contratos como parte de operaciones 111 | on-chain y detenerlos a ellos. Por favor, sé explícito con estos casos en la documentación de tus contratos. 112 | 113 | Envío y recibo de Ether 114 | ======================= 115 | 116 | - Ni los contratos ni las "cuentas externas", son actualmente capaces de prevenir que alguien 117 | les envíe Ether. Los contratos pueden reaccionar y rechazar una transferencia normal, pero hay maneras de mover 118 | Ether sin provocar la ejecución de código. Una manera es simplemente "minando" a la 119 | cuenta del contrato y la otra es usando ``selfdestruct(x)``. 120 | 121 | - Si un contrato recibe Ether (sin que se llame a ninguna función), se ejecuta la función fallback. 122 | Si no tiene una función fallback, el Ether será rechazado (lanzando una excepción). 123 | Durante la ejecución de la función fallback, el contrato sólo puede depender del 124 | "estipendio de gas" (2300 gas) que tiene disponible en ese momento. Este estipendio no es suficiente para acceder 125 | al almacenamiento de ninguna forma. Para asegurarte de que tu contrato pueda recibir Ether de ese modo, verifica los 126 | requerimientos de gas de la función fallback (por ejemplo, en la sección de "details" de Remix). 127 | 128 | - Hay una manera de enviar más gas al contrato receptor usando ``addr.call.value(x)()``. 129 | Esto es esencialmente lo mismo que ``addr.transfer(x)``, solo que envía todo el gas restante 130 | y permite la posibilidad al receptor de realizar acciones más caras (y sólo devuelve un código 131 | de error y no propaga automáticamente el error). Dentro de estas acciones se incluyen llamar de nuevo al contrato 132 | emisor u otros cambios de estado que no fueron previstos. Permite más flexibilidad para 133 | usuarios honestos pero también para los usuarios maliciosos. 134 | 135 | - Si quieres enviar Ether usando ``address.transfer``, hay ciertos detalles que hay que saber: 136 | 137 | 1. Si el receptor es un contrato, se ejecutará la función fallback, lo cual puede llamar de vuelta al 138 | contrato que envía Ether. 139 | 2. El envío de Ether puede fallar debido a la profundidad de la llamada subiendo por encima 1024. Puesto que el que 140 | llama tiene el control total de la profundidad de la llamada, pueden forzar la transferencia para que falle; 141 | tened en consideración esta posibilidad o utilizad siempre ``send`` y aseguraos siempre de revisar el valor 142 | de retorno. O mejor aún, escribid el contrato siguiendo un patrón de modo que sea el receptor el que tenga que sacar el Ether. 143 | 3. El envío de Ether también puede fallar porque la ejecución del contrato receptor necesita más gas que 144 | la cantidad asignada (OOG, por sus siglas en inglés "Out of Gas"). Esto ocurre porque 145 | explícitamente se usó ``require``, ``assert``, ``revert``, ``throw``, o simplemente porque la operación es 146 | demasiado cara. Si usas ``transfer`` o ``send`` comprobando el valor de retorno, esto puede hacer que el receptor bloquee 147 | el progreso en el contrato emisor.Pero volviendo a insistir, aquí lo mejor es usar un 148 | :ref:`patrón de "retirada" en vez de un "orden de envío" `. 149 | 150 | Profundidad de la pila de llamadas (Callstack) 151 | ============================================== 152 | 153 | Las llamadas externas a funciones pueden fallar en cualquier momento al 154 | exceder la profundidad máxima de la pila de llamadas de 1024. En tales situaciones, 155 | Solidity lanza una excepción. Los usuarios maliciosos podrían forzar la profundidad de 156 | la pila a un valor alto antes de interactuar con el contrato. 157 | 158 | Ten en cuenta que ``.send()`` **no** lanza una excepción si la pila está vacía, sino 159 | que retorna ``false`` en ese caso. Las funciones de bajo nivel como ``.call()``, 160 | ``.callcode()`` ``.delegatecall()`` se comportan de la misma manera. 161 | 162 | tx.origin 163 | ========= 164 | 165 | No uses nunca tx.origin para dar autorización. Digamos que tienes un contrato de cartera como este: 166 | 167 | :: 168 | 169 | pragma solidity ^0.4.11; 170 | 171 | // ESTE CONTRATO CONTIENE UN ERROR - NO USAR 172 | contract TxUserWallet { 173 | address owner; 174 | 175 | function TxUserWallet() { 176 | owner = msg.sender; 177 | } 178 | 179 | function transferTo(address dest, uint amount) { 180 | require(tx.origin == owner); 181 | dest.transfer(amount); 182 | } 183 | } 184 | 185 | Ahora alguien te engaña para que le envíes Ether a esta cartera maliciosa: 186 | 187 | :: 188 | 189 | pragma solidity ^0.4.0; 190 | 191 | contract TxAttackWallet { 192 | address owner; 193 | 194 | function TxAttackWallet() { 195 | owner = msg.sender; 196 | } 197 | 198 | function() { 199 | TxUserWallet(msg.sender).transferTo(owner, msg.sender.balance); 200 | } 201 | } 202 | 203 | Si tu cartera hubiera comprobado ``msg.sender`` para darle autorización, recibiría la cuenta de la cartera atacante, en vez de la cartera del 'owner'. Pero al chequear ``tx.origin``, recibe la cuenta original que envió la transacción, que es la cuenta owner. La cartera atacante inmediatamente vacía todos tus fondos. 204 | 205 | Detalles Menores 206 | ================ 207 | 208 | - En ``for (var i = 0; i < arrayName.length; i++) { ... }``, el tipo de ``i`` será ``uint8``, porque este es el tipo más pequeño que es requerido para guardar el valor ``0``. Si el vector (array) tiene más de 255 elementos, el bucle no se terminará. 209 | - La palabra reservada ``constant`` para funciones no es actualmente forzada por el compilador. 210 | Tampoco está forzada por la EVM, de modo que una función de un contrato que "pretenda" ser constante, 211 | todava podría hacer cambios al estado. 212 | - Los tipos que no utilizan totalmente los 32 bytes pueden contener basura en los bits más significativos. 213 | Esto es especialmente importante si se accede a ``msg.data`` ya que supone un riesgo de maleabilidad: 214 | Puedes crear transacciones que llaman una función ``f(uint8 x)`` con un argumento de tipo byte 215 | de ``0xff000001`` y ``0x00000001``. Ambos se pasarán al contrato y ambos se verán como 216 | el número ``1``. Pero ``msg.data`` es diferente, así que si se usa ``keccak246(msg.data)`` para 217 | algo, tendrás resultados diferentes. 218 | 219 | *************** 220 | Recomendaciones 221 | *************** 222 | 223 | Restringir la cantidad de Ether 224 | =============================== 225 | 226 | Restringir la cantidad de Ether (u otros tokens) que puedan ser almacenados 227 | en un contrato inteligente. Si el código fuente, el compilador o la plataforma 228 | tiene un error, estos fondos podrían perderse. Si quieres limitar la pérdida, 229 | limita la cantidad de Ether. 230 | 231 | Pequeño y modular 232 | ================= 233 | 234 | Mantén tus contratos pequeños y fáciles de entender. Separa las funcionalidades 235 | no relacionadas en otros contratos o en librerías. Se pueden aplicar las recomendaciones 236 | estándar de calidad de código: Limitar la cantidad de variables locales, limitar la longitud 237 | de las funciones, etc. Documenta tus funciones para que otros puedan ver cuál era la 238 | intención del código y para ver si hace algo diferente de lo que pretendía. 239 | 240 | Usa el orden Comprobaciones-Efectos-Interacciones 241 | ======================================================= 242 | 243 | La mayoría de las funciones primero ejecutan algunos chequeos (¿quién ha llamado a 244 | la función?, ¿los argumentos están en el rango?, ¿mandaron suficiente Ether? 245 | ¿La cuenta tiene tokens?, etc.). Estos chequeos deben de hacerse primero. 246 | 247 | Como segundo paso, si se pasaron todos los chequeos, se deben ejecutar los efectos a las 248 | variables de estado del contrato actual. La interacción con otros contratos debe 249 | hacerse como último paso en cualquier función. 250 | 251 | Al principio, algunos contratos retrasaban la ejecución de los efectos y esperaban a que 252 | una función externa devolviera un estado sin errores. Esto es un error grave ya que se puede 253 | hacer un reingreso, como explicamos arriba. 254 | 255 | También hay que tener en cuenta que las llamadas a contratos conocidos pueden a su vez causar llamadas 256 | a otros contratos no conocidos, así que siempre es mejor aplicar este orden. 257 | 258 | Incluir un modo a prueba de fallos 259 | ================================== 260 | 261 | Aunque hacer que tu sistema sea completamente descentralizado eliminará cualquier intermediario, 262 | puede que sea una buena idea, especialmente para nuevo código, incluir un sistema 263 | a prueba de fallos: 264 | 265 | Puedes agregar una función a tu contrato que realize algunas comprobaciones internas como 266 | "¿se ha filtrado Ether?", "¿es igual la suma de los tokens al balance de la cuenta?" 267 | o cosas similares. Recordad que no se puede usar mucho gas para eso, así que ayuda mediante 268 | computaciones off-chain podrían ser necesarias. 269 | 270 | Si los chequeos fallan, el contrato automáticamente cambia a modo a prueba de fallos, donde, 271 | por ejemplo, se desactivan muchas funciones, da el control a una entidad tercera de confianza 272 | o se convierte en un contrato "devuélveme mi dinero". 273 | 274 | 275 | ******************* 276 | Verificación formal 277 | ******************* 278 | 279 | Usando verificación formal, es posible realizar pruebas matemáticas automatizadas de que el código 280 | sigue una cierta especificación formal. La especificación aún es formal (como el código fuente), 281 | pero normalmente mucho más simple. Hay un prototipo en Solidity que realiza verificación formal y 282 | pronto se documentará mejor. 283 | 284 | Ten en cuenta que la verificación formal en sí misma sólo puede ayudarte a entender la diferencia 285 | entre lo que hiciste (la especificación) y cómo lo hiciste (la implementación real). Aún necesitas 286 | chequear si la especificación es lo que querías y que no hayas olvidado efectos inesperados de ello. 287 | -------------------------------------------------------------------------------- /solidity-in-depth.rst: -------------------------------------------------------------------------------- 1 | ################ 2 | Solidity a fondo 3 | ################ 4 | 5 | Esta sección debería proveerte de todo lo que necesitas saber sobre Solidity. 6 | Si falta algo, por favor, ponte en contacto con nosotros en 7 | `Gitter `_ o haz un pull request en 8 | `Github `_. 9 | 10 | .. toctree:: 11 | :maxdepth: 2 12 | 13 | layout-of-source-files.rst 14 | structure-of-a-contract.rst 15 | types.rst 16 | units-and-global-variables.rst 17 | control-structures.rst 18 | contracts.rst 19 | assembly.rst 20 | miscellaneous.rst 21 | -------------------------------------------------------------------------------- /structure-of-a-contract.rst: -------------------------------------------------------------------------------- 1 | .. index:: contract, state variable, function, event, struct, enum, function;modifier 2 | 3 | .. _contract_structure: 4 | 5 | ************************* 6 | Estructura de un contrato 7 | ************************* 8 | 9 | Los Contratos en Solidity son similares a las clases de los lenguajes orientados a objetos. 10 | Cualquier contrato puede contener declaraciones del tipo :ref:`variables de estado `, :ref:`funciones `, :ref:`modificadores de función `, :ref:`eventos `, :ref:`structs ` y :ref:`enums `. 11 | Además, los contratos pueden heredar de otros contratos. 12 | 13 | .. _structure-state-variables: 14 | 15 | Variables de estado 16 | =================== 17 | 18 | Las variables de estado son valores que están permanentemente almacenados en una parte del contrato conocida como storage del contrato. 19 | 20 | :: 21 | 22 | pragma solidity ^0.4.0; 23 | 24 | contract SimpleStorage { 25 | uint storedData; // Variable de estado 26 | // ... 27 | } 28 | 29 | Véase la sección :ref:`tipos ` para conocer los diferentes tipos válidos de variables de estado y :ref:`visibilidad-y-getters ` para conocer las distintas posibilidades de visibilidad que pueden tener las variables de estado. 30 | 31 | .. _structure-functions: 32 | 33 | Funciones 34 | ========= 35 | 36 | Las funciones son las unidades ejecutables del código dentro de un contrato. 37 | 38 | :: 39 | 40 | pragma solidity ^0.4.0; 41 | 42 | contract SimpleAuction { 43 |     function bid() public payable { // Función 44 | // ... 45 | } 46 | } 47 | 48 | Las :ref:`llamadas a una función ` pueden ocurrir dentro o fuera de la misma. Una función puede tener varios niveles de :ref:`visibilidad ` con respecto a otros contratos. 49 | 50 | .. _structure-function-modifiers: 51 | 52 | Modificadores de función 53 | ======================== 54 | 55 | Los modificadores de función se usan para enmendar de un modo declarativo la semántica de las funciones (véase :ref:`modificadores ` en la sección sobre contratos). 56 | 57 | :: 58 | 59 | pragma solidity ^0.4.11; 60 | 61 | contract Purchase { 62 | address public seller; 63 | 64 | modifier onlySeller() { // Modificador 65 | require(msg.sender == seller); 66 | _; 67 | } 68 | 69 | function abort() public onlySeller { // Uso de modificador 70 | // ... 71 | } 72 | } 73 | 74 | .. _structure-events: 75 | 76 | Eventos 77 | ======= 78 | 79 | Los eventos son interfaces de conveniencia con los servicios de registro de la EVM (Máquina Virtual de Ethereum). 80 | 81 | :: 82 | 83 | pragma solidity ^0.4.0; 84 | 85 | contract SimpleAuction { 86 | event HighestBidIncreased(address bidder, uint amount); // Evento 87 | 88 | function bid() public payable { 89 | // ... 90 | HighestBidIncreased(msg.sender, msg.value); // Lanzamiento del evento 91 | } 92 | } 93 | 94 | Véase :ref:`eventos ` en la sección sobre contratos para tener más información sobre cómo se declaran los eventos y cómo se pueden usar dentro de una dapp. 95 | 96 | .. _structure-struct-types: 97 | 98 | Tipos de structs 99 | ================ 100 | 101 | Las estructuras de datos (Structs) son tipos definidos por el propio usuario y pueden agrupar mútiples variables (véase :ref:`structs ` en la sección sobre tipos). 102 | 103 | :: 104 | 105 | pragma solidity ^0.4.0; 106 | 107 | contract Ballot { 108 | struct Voter { // Structs 109 | uint weight; 110 | bool voted; 111 | address delegate; 112 | uint vote; 113 | } 114 | } 115 | 116 | .. _structure-enum-types: 117 | 118 | Tipos de enum 119 | ============= 120 | 121 | Los enumerados (Enums) se usan para crear tipos con un conjunto de valores finitos y están definidos por el propio usuario (véase :ref:`enums ` en la sección sobre tipos). 122 | 123 | :: 124 | 125 | pragma solidity ^0.4.0; 126 | 127 | contract Purchase { 128 | enum State { Created, Locked, Inactive } // Enum 129 | } 130 | -------------------------------------------------------------------------------- /style-guide.rst: -------------------------------------------------------------------------------- 1 | .. index:: style, coding style 2 | 3 | ############## 4 | Guía de estilo 5 | ############## 6 | 7 | ************ 8 | Introducción 9 | ************ 10 | 11 | Esta guía pretende proporcionar convenciones de codificación para escribir código con Solidity. 12 | Esta guía debe ser entendida como un documento en evolución que cambiará con el tiempo según aparecen nuevas convenciones útiles y antiguas convenciones se vuelven obsoletas. 13 | 14 | Muchos proyectos implementarán sus propias guías de estilo. En el caso de conflictos, las guías de estilo específicas del proyecto tendrán prioridad. 15 | 16 | La estructura y muchas de las recomendaciones de esta guía de estilo fueron tomadas de Python: `guía de estilo pep8 `_. 17 | 18 | El objetivo de esta guía *no* es ser la forma correcta o la mejor manera de escribir código con Solidity. El objetivo de esta guía es la *consistencia*. Una cita de python `pep8 `_ capta bien este concepto. 19 | 20 | Una guía de estilo es sobre consistencia. La consistencia con esta guía de estilo es importante. La consistencia dentro de un proyecto es más importante. La consistencia dentro de un módulo o función es lo más importante. 21 | Pero sobre todo: saber cuándo ser inconsistente - a veces la guía de estilo simplemente no se aplica. En caso de duda, use su mejor juicio. Mire otros ejemplos y decida qué parece mejor. ¡Y no dude en preguntar! 22 | 23 | 24 | ***************** 25 | Diseño del código 26 | ***************** 27 | 28 | 29 | Sangría 30 | ======= 31 | 32 | Utilice 4 espacios por nivel de sangría. 33 | 34 | Tabulador o espacios 35 | ==================== 36 | 37 | Los espacios son el método de indentación preferido. 38 | 39 | Se deben evitar la mezcla del tabulador y los espacios. 40 | 41 | Líneas en blanco 42 | ================ 43 | 44 | Envuelva las declaraciones de nivel superior en el código de Solidity con dos líneas en blanco. 45 | 46 | Sí:: 47 | 48 | contract A { 49 | ... 50 | } 51 | 52 | 53 | contract B { 54 | ... 55 | } 56 | 57 | 58 | contract C { 59 | ... 60 | } 61 | 62 | No:: 63 | 64 | contract A { 65 | ... 66 | } 67 | contract B { 68 | ... 69 | } 70 | 71 | contract C { 72 | ... 73 | } 74 | 75 | Dentro de un contrato, rodee las declaraciones de una función con una sola línea en blanco. 76 | 77 | Las líneas en blanco se pueden omitir entre grupos de una frase relacionada (tales como las funciones stub en un contrato abstracto) 78 | 79 | Sí:: 80 | 81 | contract A { 82 | function spam(); 83 | function ham(); 84 | } 85 | 86 | 87 | contract B is A { 88 | function spam() { 89 | ... 90 | } 91 | 92 | function ham() { 93 | ... 94 | } 95 | } 96 | 97 | No:: 98 | 99 | contract A { 100 | function spam() { 101 | ... 102 | } 103 | function ham() { 104 | ... 105 | } 106 | } 107 | 108 | Codificación de archivos de origen 109 | ================================== 110 | 111 | Se prefiere la codificación del texto en UTF-8 o ASCII. 112 | 113 | Importación 114 | =========== 115 | 116 | Las declaraciones de importación siempre deben colocarse en la parte superior del archivo. 117 | 118 | Sí:: 119 | 120 | import "owned"; 121 | 122 | 123 | contract A { 124 | ... 125 | } 126 | 127 | 128 | contract B is owned { 129 | ... 130 | } 131 | 132 | No:: 133 | 134 | contract A { 135 | ... 136 | } 137 | 138 | 139 | import "owned"; 140 | 141 | 142 | contract B is owned { 143 | ... 144 | } 145 | 146 | Orden de funciones 147 | ================== 148 | 149 | La ordenación ayuda a que los lectores puedan identificar las funciones que pueden invocar y encontrar las definiciones de constructor y de retorno más fácilmente. 150 | 151 | Las funciones deben agruparse de acuerdo con su visibilidad y ser ordenadas de acuerdo a: 152 | 153 | - constructor 154 | - función fallback (Si existe) 155 | - external 156 | - public 157 | - internal 158 | - private 159 | 160 | Dentro de un grupo, coloque las funciones ``constant`` al final. 161 | 162 | Sí:: 163 | 164 | contract A { 165 | function A() { 166 | ... 167 | } 168 | 169 | function() { 170 | ... 171 | } 172 | 173 | // Funciones external 174 | // ... 175 | 176 | // Funciones external que son constantes 177 | // ... 178 | 179 | // Funciones public 180 | // ... 181 | 182 | // Funciones internal 183 | // ... 184 | 185 | // Funciones private 186 | // ... 187 | } 188 | 189 | No:: 190 | 191 | contract A { 192 | 193 | // Funciones external 194 | // ... 195 | 196 | // Funciones private 197 | // ... 198 | 199 | // Funciones public 200 | // ... 201 | 202 | function A() { 203 | ... 204 | } 205 | 206 | function() { 207 | ... 208 | } 209 | 210 | // Funciones internal 211 | // ... 212 | } 213 | 214 | Espacios en blanco en expresiones 215 | ================================= 216 | 217 | Evite los espacios en blanco superfluos en las siguientes situaciones: 218 | 219 | Inmediatamente entre paréntesis, llaves o corchetes, con la excepción de declaraciones de una función en una sola línea. 220 | 221 | Sí:: 222 | 223 | spam(ham[1], Coin({name: "ham"})); 224 | 225 | No:: 226 | 227 | spam( ham[ 1 ], Coin( { name: "ham" } ) ); 228 | 229 | Excepción:: 230 | 231 | function singleLine() { spam(); } 232 | 233 | Inmediatamente después de una coma, punto y coma: 234 | 235 | Sí:: 236 | 237 | function spam(uint i, Coin coin); 238 | 239 | No:: 240 | 241 | function spam(uint i , Coin coin) ; 242 | 243 | Más de un espacio alrededor de una asignación u otro operador para alinearlo con otro: 244 | 245 | Sí:: 246 | 247 | x = 1; 248 | y = 2; 249 | long_variable = 3; 250 | 251 | No:: 252 | 253 | x = 1; 254 | y = 2; 255 | long_variable = 3; 256 | 257 | No incluya un espacio en blanco en la función fallback: 258 | 259 | Sí:: 260 | 261 | function() { 262 | ... 263 | } 264 | 265 | No:: 266 | 267 | function () { 268 | ... 269 | } 270 | 271 | Estructuras de control 272 | ====================== 273 | 274 | Las llaves que denotan el cuerpo de un contrato, biblioteca, funciones y estructuras deberán: 275 | 276 | * Abrir en la misma línea que la declaración 277 | * Cerrar en su propia línea en el mismo nivel de sangría que la declaración. 278 | * La llave de apertura debe ser procedida por un solo espacio. 279 | 280 | Sí:: 281 | 282 | contract Coin { 283 | struct Bank { 284 | address owner; 285 | uint balance; 286 | } 287 | } 288 | 289 | No:: 290 | 291 | contract Coin 292 | { 293 | struct Bank { 294 | address owner; 295 | uint balance; 296 | } 297 | } 298 | 299 | Las mismas recomendaciones se aplican a las estructuras de control ``if``, ``else``, ``while`` y ``for``. 300 | 301 | Además, debería existir un único espacio entre las estructuras de control ``if``, ``while``, y ``for``, y el bloque entre paréntesis que representa el condicional, así como un único espacio entre el bloque del paréntesis condicional y la llave de apertura. 302 | 303 | Sí:: 304 | 305 | if (...) { 306 | ... 307 | } 308 | 309 | for (...) { 310 | ... 311 | } 312 | 313 | No:: 314 | 315 | if (...) 316 | { 317 | ... 318 | } 319 | 320 | while(...){ 321 | } 322 | 323 | for (...) { 324 | ...;} 325 | 326 | Para las estructuras de control cuyo cuerpo sólo contiene declaraciones únicas, se pueden omitir los corchetes *si* la declaración cabe en una sola línea. 327 | 328 | Sí:: 329 | 330 | if (x < 10) 331 | x += 1; 332 | 333 | No:: 334 | 335 | if (x < 10) 336 | someArray.push(Coin({ 337 | name: 'spam', 338 | value: 42 339 | })); 340 | 341 | Para los bloques ``if`` que contienen una condición ``else`` o ``else if``, el ``else`` debe estar en la misma línea que el corchete de cierre del ``if``. Esto es una excepción en comparación con las reglas de otras estructuras de tipo bloque. 342 | 343 | Sí:: 344 | 345 | if (x < 3) { 346 | x += 1; 347 | } else if (x > 7) { 348 | x -= 1; 349 | } else { 350 | x = 5; 351 | } 352 | 353 | 354 | if (x < 3) 355 | x += 1; 356 | else 357 | x -= 1; 358 | 359 | No:: 360 | 361 | if (x < 3) { 362 | x += 1; 363 | } 364 | else { 365 | x -= 1; 366 | } 367 | 368 | Declaración de funciones 369 | ======================== 370 | 371 | Para declaraciones de función cortas, se recomienda dejar el corchete de apertura del cuerpo de la función en la misma línea que la declaración de la función. 372 | 373 | El corchete de cierre debe estar al mismo nivel de sangría que la declaración de la función. 374 | 375 | El corchete de apertura debe estar precedido por un solo espacio. 376 | 377 | Sí:: 378 | 379 | function increment(uint x) returns (uint) { 380 | return x + 1; 381 | } 382 | 383 | function increment(uint x) public onlyowner returns (uint) { 384 | return x + 1; 385 | } 386 | 387 | No:: 388 | 389 | function increment(uint x) returns (uint) 390 | { 391 | return x + 1; 392 | } 393 | 394 | function increment(uint x) returns (uint){ 395 | return x + 1; 396 | } 397 | 398 | function increment(uint x) returns (uint) { 399 | return x + 1; 400 | } 401 | 402 | function increment(uint x) returns (uint) { 403 | return x + 1;} 404 | 405 | Se debe especificar la visibilidad de los modificadores para una función antes de cualquier modificador personalizado. 406 | 407 | Sí:: 408 | 409 | function kill() public onlyowner { 410 | selfdestruct(owner); 411 | } 412 | 413 | No:: 414 | 415 | function kill() onlyowner public { 416 | selfdestruct(owner); 417 | } 418 | 419 | Para las declaraciones de función largas, se recomienda dejar a cada argumento su propia línea al mismo nivel de sangría que el cuerpo de la función. El paréntesis de cierre y el corchete de apertura deben de estar en su propia línea también y con el mismo nivel de sangría que la declaración de la función. 420 | 421 | Sí:: 422 | 423 | function thisFunctionHasLotsOfArguments( 424 | address a, 425 | address b, 426 | address c, 427 | address d, 428 | address e, 429 | address f 430 | ) { 431 | doSomething(); 432 | } 433 | 434 | No:: 435 | 436 | function thisFunctionHasLotsOfArguments(address a, address b, address c, 437 | address d, address e, address f) { 438 | doSomething(); 439 | } 440 | 441 | function thisFunctionHasLotsOfArguments(address a, 442 | address b, 443 | address c, 444 | address d, 445 | address e, 446 | address f) { 447 | doSomething(); 448 | } 449 | 450 | function thisFunctionHasLotsOfArguments( 451 | address a, 452 | address b, 453 | address c, 454 | address d, 455 | address e, 456 | address f) { 457 | doSomething(); 458 | } 459 | 460 | Si una declaración de función larga tiene modificadores, cada uno de ellos debe de estar en su propia línea. 461 | 462 | Sí:: 463 | 464 | function thisFunctionNameIsReallyLong(address x, address y, address z) 465 | public 466 | onlyowner 467 | priced 468 | returns (address) 469 | { 470 | doSomething(); 471 | } 472 | 473 | function thisFunctionNameIsReallyLong( 474 | address x, 475 | address y, 476 | address z, 477 | ) 478 | public 479 | onlyowner 480 | priced 481 | returns (address) 482 | { 483 | doSomething(); 484 | } 485 | 486 | No:: 487 | 488 | function thisFunctionNameIsReallyLong(address x, address y, address z) 489 | public 490 | onlyowner 491 | priced 492 | returns (address) { 493 | doSomething(); 494 | } 495 | 496 | function thisFunctionNameIsReallyLong(address x, address y, address z) 497 | public onlyowner priced returns (address) 498 | { 499 | doSomething(); 500 | } 501 | 502 | function thisFunctionNameIsReallyLong(address x, address y, address z) 503 | public 504 | onlyowner 505 | priced 506 | returns (address) { 507 | doSomething(); 508 | } 509 | 510 | Para las funciones de tipo constructor en contratos heredados que requieren argumentos, si la declaración de la función es larga o difícil de leer, se recomienda poner cada constructor base en su propia línea de la misma manera que con los modificadores. 511 | 512 | Sí:: 513 | 514 | contract A is B, C, D { 515 | function A(uint param1, uint param2, uint param3, uint param4, uint param5) 516 | B(param1) 517 | C(param2, param3) 518 | D(param4) 519 | { 520 | // do something with param5 521 | } 522 | } 523 | 524 | No:: 525 | 526 | contract A is B, C, D { 527 | function A(uint param1, uint param2, uint param3, uint param4, uint param5) 528 | B(param1) 529 | C(param2, param3) 530 | D(param4) 531 | { 532 | // do something with param5 533 | } 534 | } 535 | 536 | contract A is B, C, D { 537 | function A(uint param1, uint param2, uint param3, uint param4, uint param5) 538 | B(param1) 539 | C(param2, param3) 540 | D(param4) { 541 | // do something with param5 542 | } 543 | } 544 | 545 | Cuando se declara funciones cortas con una sola declaración, está permitido hacerlo en una solo línea. 546 | 547 | Permisible:: 548 | 549 | function shortFunction() { doSomething(); } 550 | 551 | Esta guía sobre la declaración de funciones está pensada para mejorar la legibilidad. Sin embargo, los autores deberían utilizar su mejor juicio, ya que esta guía tampoco intenta cubrir todas las posibles permutaciones para las declaraciones de función. 552 | 553 | Mapeo 554 | ===== 555 | 556 | Pendiente de hacer 557 | 558 | Declaración de variables 559 | ======================== 560 | 561 | La declaración de variables tipo array no deben incluir un espacio entre el tipo y el corchete. 562 | 563 | Sí:: 564 | 565 | uint[] x; 566 | 567 | No:: 568 | 569 | uint [] x; 570 | 571 | 572 | Otras recommendaciones 573 | ====================== 574 | 575 | * Los strings deben de citarse con comillas dobles en lugar de comillas simples. 576 | 577 | Sí:: 578 | 579 | str = "foo"; 580 | str = "Hamlet says, 'To be or not to be...'"; 581 | 582 | No:: 583 | 584 | str = 'bar'; 585 | str = '"Be yourself; everyone else is already taken." -Oscar Wilde'; 586 | 587 | * Se envuelve los operadores con un solo espacio de cada lado. 588 | 589 | Sí:: 590 | 591 | x = 3; 592 | x = 100 / 10; 593 | x += 3 + 4; 594 | x |= y && z; 595 | 596 | No:: 597 | 598 | x=3; 599 | x = 100/10; 600 | x += 3+4; 601 | x |= y&&z; 602 | 603 | * Para los operadores con una prioridad mayor que otros, se pueden omitir los espacios de cada lado del operador para marcar la precedencia. Esto se hace para mejorar la legibilidad de declaraciones complejas. Se debe usar siempre el mismo número de espacios a cada lado de un operador. 604 | 605 | Sí:: 606 | 607 | x = 2**3 + 5; 608 | x = 2*y + 3*z; 609 | x = (a+b) * (a-b); 610 | 611 | No:: 612 | 613 | x = 2** 3 + 5; 614 | x = y+z; 615 | x +=1; 616 | 617 | 618 | ************************ 619 | Convención sobre nombres 620 | ************************ 621 | 622 | Las convenciones sobre nombres son extremadamente útiles siempre y cuando se usen de forma ámplia. El uso de diferentes convenciones puede transmitir *meta* información significativa a la que de otro modo no tendríamos acceso de manera inmediata. 623 | 624 | Las recomendaciones de nombres que se dan aquí están pensadas para mejorar la legibilidad, y por lo tanto no se deben considerar como reglas. Son más bien una guía para intentar transmitir la mayor información posible a través del nombre de las cosas. 625 | 626 | Finalmente, la consistencia dentro de un bloque de código siempre debe prevalecer sobre cualquier convención destacada en este documento. 627 | 628 | 629 | Estilos para poner nombres 630 | ========================== 631 | 632 | Para evitar confusiones, se usarán los siguiente nombres para referirse a diferentes estilos para poner nombres. 633 | 634 | * ``b`` (letra minúscula única) 635 | * ``B`` (letra mayúscula única) 636 | * ``minuscula`` 637 | * ``minuscula_con_guiones_bajos`` 638 | * ``MAYUSCULA`` 639 | * ``MAYUSCULA_CON_GUIONES_BAJOS`` 640 | * ``PalabrasConLaInicialEnMayuscula`` (también llamado CapWords) 641 | * ``mezclaEntreMinusculaYMayuscula`` (¡distinto a PalabrasConLaInicialEnMayuscula por el uso de una minúscula en la letra inicial!) 642 | * ``Palabras_Con_La_Inicial_En_Mayuscula_Y_Guiones_Bajos`` 643 | 644 | .. note:: Cuando se usan abreviaciones en CapWords, usar mayúsculas para todas las letras de la abreviación. Es decir que HTTPServerError es mejor que HttpServerError 645 | 646 | 647 | Nombres a evitar 648 | ================ 649 | 650 | * ``l`` - Letra minúscula ele 651 | * ``O`` - Letra mayúscula o 652 | * ``I`` - Letra mayúscula i 653 | 654 | No usar jamás ninguna de estas letras únicas para nombrar una variable. Estas letras generalmente no se diferencian de los dígitos uno y cero. 655 | 656 | 657 | Contratos y librerías de nombres 658 | ================================ 659 | 660 | Contratos y librerías deben de nombrarse usando el estilo CapWord (PalabrasConLaInicialEnMayuscula). 661 | 662 | 663 | Eventos 664 | ======= 665 | 666 | Los eventos deben de nombrarse usando el estilo CapWord (PalabrasConLaInicialEnMayuscula). 667 | 668 | 669 | Nombres para funciones 670 | ====================== 671 | 672 | Las funciones deben de nombrarse usando el estilo mezclaEntreMinusculaYMayuscula. 673 | 674 | 675 | Argumentos de funciones 676 | ======================= 677 | 678 | Cuando se escriben funciones de librerías que operan sobre un struct personalizado, el struct debe ser el primer argumento y debe nombrarse siempre ``self``. 679 | 680 | 681 | Variables locales y de estado 682 | ============================= 683 | 684 | Usar el estilo mezclaEntreMinusculaYMayuscula. 685 | 686 | 687 | Constantes 688 | ========== 689 | 690 | Las constantes deben de nombrarse con todas las letras mayúsculas y guiones bajos para separar las palabras (p.ej. ``MAX_BLOCKS``). 691 | 692 | 693 | Modificadores 694 | ============= 695 | 696 | Usar el estilo mezclaEntreMinusculaYMayuscula. 697 | 698 | 699 | Evitar Colisiones 700 | ================= 701 | 702 | * ``guion_bajo_unico_con_cola_`` 703 | 704 | Se recomienda usar esta convención cuando el nombre deseado colisiona con un nombre inherente al sistema o reservado. 705 | 706 | 707 | Recommendaciones generales 708 | ========================== 709 | 710 | Pendiente de hacer 711 | -------------------------------------------------------------------------------- /units-and-global-variables.rst: -------------------------------------------------------------------------------- 1 | ******************************************** 2 | Unidades y variables disponibles globalmente 3 | ******************************************** 4 | 5 | .. index:: wei, finney, szabo, ether 6 | 7 | Unidades de Ether 8 | ================= 9 | 10 | Un numero literal puede tomar un sufijo como el ``wei``, el ``finney``, el ``szabo`` o el ``ether`` para convertirlo entre las subdenominaciones del Ether. Se asume que un numero sin sufijo para representar la moneda Ether está expresado en Wei, por ejemplo, ``2 ether == 2000 finney`` devuelve ``true``. 11 | 12 | .. index:: time, seconds, minutes, hours, days, weeks, years 13 | 14 | Unidades de tiempo 15 | ================== 16 | 17 | Sufijos como ``seconds``, ``minutes``, ``hours``, ``days``, ``weeks`` y ``years`` utilizados después de numeros literales pueden usarse para convertir unidades de tiempo donde los segundos son la unidad de base. Las equivalencias son las siguientes: 18 | 19 | * ``1 == 1 seconds`` 20 | * ``1 minutes == 60 seconds`` 21 | * ``1 hours == 60 minutes`` 22 | * ``1 days == 24 hours`` 23 | * ``1 weeks == 7 days`` 24 | * ``1 years == 365 days`` 25 | 26 | Ojo si utilizan estas unidades para realizar cálculos de calendario, porque no todos los años tienen 365 días y no todos los días tienen 24 horas, por culpa de los `_segundos intercalares `_. Debido a que los segundos intercalares no son predecibles, la librería del calendario extacto tiene que estar actualizada por un oráculo externo. 27 | 28 | Estos sufijos no pueden aplicarse a variables. Si desea interpretar algunas variables de entrada, como por ejemplo días, puede hacerlo de siguiente forma:: 29 | 30 | function f(uint start, uint daysAfter) { 31 | if (now >= start + daysAfter * 1 days) { ... } 32 | } 33 | 34 | Variables y funciones especiales 35 | ================================ 36 | 37 | Existen variables y funciones especiales de ámbito global que siempre están disponibles y que se usan principalmente para proporcionar información sobre la blockchain. 38 | 39 | .. index:: block, coinbase, difficulty, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, now, gas price, origin 40 | 41 | Bloque y propiedades de las transacciones 42 | ----------------------------------------- 43 | 44 | - ``block.blockhash(uint blockNumber) returns (bytes32)``: el hash de un bloque dado - sólo funciona para los 256 bloques más recientes, excluyendo el actual 45 | - ``block.coinbase`` (``address``): devuelve la dirección del minero que está procesando el bloque actual 46 | - ``block.difficulty`` (``uint``): devuelve la dificultad del bloque actual 47 | - ``block.gaslimit`` (``uint``): devuelve el límite de gas del bloque actual 48 | - ``block.number`` (``uint``): devuelve el número del bloque actual 49 | - ``block.timestamp`` (``uint``): devuelve el timestamp del bloque actual en forma de segundos siguiendo el tiempo universal de Unix (Unix epoch) 50 | - ``msg.data`` (``bytes``): datos enviados en la transacción (calldata) 51 | - ``msg.gas`` (``uint``): devuelve el gas que queda 52 | - ``msg.sender`` (``address``): devuelve remitente de la llamada actual 53 | - ``msg.sig`` (``bytes4``): devuelve los primeros cuatro bytes de los datos enviados en la transacción (i.e. el identificador de la función) 54 | - ``msg.value`` (``uint``): devuelve el numero de Wei enviado con la llamada 55 | - ``now`` (``uint``): devuelve el timestamp del bloque actual (es un alias de ``block.timestamp``) 56 | - ``tx.gasprice`` (``uint``): devuelve el precio del gas de la transacción 57 | - ``tx.origin`` (``address``): devuelve el emisor original de la transacción 58 | 59 | .. note:: 60 |   Los valores de todos los elementos de ``msg``, incluido ``msg.sender`` y ``msg.value`` pueden cambiar para cada llamada a una función **externa**. Incluyendo las llamadas a funciones de una librería. 61 | 62 |   Si desea implementar restricciones de acceso para funciones de una librería utilizando ``msg.sender``, tiene que proporcionar manualmente el valor de ``msg.sender`` como argumento. 63 | 64 | .. note:: 65 |   Los hashes de los bloques no están disponibles para todos los bloques por motivos de escalabilidad. Sólo se puede acceder a los hashes de los 256 bloques más recientes. El valor del hash para bloques más antiguos será cero. 66 | 67 | .. index:: assert, revert, keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, this, super, selfdestruct, balance, send 68 | 69 | Funciones matemáticas y criptográficas 70 | -------------------------------------- 71 | 72 | ``assert(bool condition)``: lanza excepción si la condición no está satisfecha. 73 | ``addmod(uint x, uint y, uint k) returns (uint)``: computa ``(x + y) % k`` donde la suma se realiza con una precisión arbitraria y no se desborda en ``2**256``. 74 | ``mulmod(uint x, uint y, uint k) returns (uint)``: computa ``(x * y) % k`` donde la multiplicación se realiza con una precisión arbitraria y no se desborda en ``2**256``. 75 | ``keccak256(...) returns (bytes32)``: computa el hash de Ethereum-SHA-3 (Keccak-256) de la unión (compactada) de los argumentos. 76 | ``sha3(...) returns (bytes32)``: equivalente a ``keccak256()``. 77 | ``sha256(...) returns (bytes32)``: computa el hash de SHA-256 de la unión (compactada) de los argumentos. 78 | ``ripemd160(...) returns (bytes20)``: computa el hash de RIPEMD-160 de la unión (compactada) de los argumentos. 79 | ``ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)``: recupera la dirección asociada a la clave pública de la firma de tipo curva elíptica o devuelve cero si hay un error (`ejempo de uso `_). 80 | ``revert()``: aborta la ejecución y revierte los cambios de estado a como estaban. 81 | 82 | Más arriba, "compactado" significa que los argumentos están concatenados sin relleno (padding). 83 | Esto significa que las siguientes llamadas son todas identicas:: 84 | 85 | keccak256("ab", "c") 86 | keccak256("abc") 87 | keccak256(0x616263) 88 | keccak256(6382179) 89 | keccak256(97, 98, 99) 90 | 91 | Si hiciera falta relleno (padding), se pueden usar las conversiones explícitas de tipo: ``keccak256("\x00\x12")`` es lo mismo que ``keccak256(uint16(0x12))``. 92 | 93 | Ten en cuenta que las constantes se compactarán usando el mínimo numero de bytes requeridos para almacenarlas. 94 | Eso significa por ejemplo que ``keccak256(0) == keccak256(uint8(0))`` y ``keccak256(0x12345678) == keccak256(uint32(0x12345678))``. 95 | 96 | Podría pasar que le falte gas para llamar a las funciones ``sha256``, ``ripemd160`` or ``ecrecover`` en *blockchain privadas*. La razón de ser así se debe a que esas funciones están implementadas como contratos precompilados y estos contratos sólo existen depués de recibir el primer mensaje (a pesar de que el contrato está hardcodeado). Los mensajes que se envían a contratos que todavía no existen son más caros y por lo tanto su ejecución puede llevar a un error por una falta de gas (Out-of-Gas error). Una solución a este problema consiste por ejemplo en mandar 1 Wei a todos los contratos antes de empezar a usarlos. Note que esto no llevará a un error en la red oficial o en la red de testeo. 97 | 98 | .. _address_related: 99 | 100 | En relación a las direcciones 101 | ----------------------------- 102 | 103 | ``
.balance`` (``uint256``): balance en Wei de la :ref:`dirección
`. 104 | ``
.transfer(uint256 amount)``: envía el importe deseado en Wei a la :ref:`dirección
` o lanza excepción si falla. 105 | ``
.send(uint256 amount) returns (bool)``: envía el importe deseado en Wei a la :ref:`dirección
` o devuelve ``false`` si falla. 106 | ``
.call(...) returns (bool)``: crea una instrucción de tipo ``CALL`` a bajo nivel o devuelve ``false`` si falla. 107 | ``
.callcode(...) returns (bool)``: crea una instrucción de tipo ``CALLCODE`` a bajo nivel o devuelve ``false`` si falla. 108 | ``
.delegatecall(...) returns (bool)``: crea una instrucción de tipo ``DELEGATECALL`` a bajo nivel o devuelve ``false`` si falla. 109 | 110 | Para más información, véase la sección :ref:`dirección
`. 111 | 112 | .. warning:: 113 |   Existe un peligro a la hora de usar ``send``: la transferencia falla si la profundidad de la pila de llamadas es de 1024 (esto siempre lo puede forzar el que hace la llamada); también falla si el destinatario se queda sin gas. Entonces, para asegurarse de hacer transferencias seguras en Ether, fíjese siempre en el valor devuelto por ``send``, use ``transfer`` en lugar de ``send``, o mejor aún, use un patrón donde es el destinatario quien retira los fondos. 114 | 115 | .. index:: this, selfdestruct 116 | 117 | En relación a los contratos 118 | --------------------------- 119 | 120 | ``this`` (el tipo del contrato actual): el contrato actual, explicitamente convertible en :ref:`address`. 121 | ``selfdestruct(address recipient)``: destruye el contrato actual y envía los fondos que tiene a una :ref:`dirección
` especificada. 122 | 123 | Además, todas las funciones del contrato actual se pueden llamar directamente, incluida la función actual. 124 | -------------------------------------------------------------------------------- /using-the-compiler.rst: -------------------------------------------------------------------------------- 1 | ****************** 2 | Uso del compilador 3 | ****************** 4 | 5 | .. index:: ! commandline compiler, compiler;commandline, ! solc, ! linker 6 | 7 | .. _commandline-compiler: 8 | 9 | Utilizar el compilador de línea de comandos 10 | ******************************************* 11 | 12 | Uno de los objetivos de compilación del repositorio de Solidity es ``solc``, el compilador de línea de comandos de solidity. 13 | 14 | Utilizando ``solc --help`` proporciona una explicación de todas las opciones. El compilador puede producir varias salidas, desde binarios simples y ensamblador sobre un árbol de sintaxis abstracto (árbol de análisis) hasta estimaciones de uso de gas. 15 | Si sólo deseas compilar un único archivo, lo ejecutas como ``solc --bin sourceFile.sol`` y se imprimirá el binario. Antes de implementar tu contrato, activa el optimizador mientras compilas usando ``solc --optimize --bin sourceFile.sol``. Si deseas obtener algunas de las variantes de salida más avanzadas de ``solc``, probablemente sea mejor decirle que salga todo por ficheros separados usando``solc -o outputDirectory --bin --ast --asm sourceFile.sol``. 16 | 17 | El compilador de línea de comandos leerá automáticamente los archivos importados del sistema de archivos, aunque es posible proporcionar un redireccionamiento de ruta utilizando ``prefix=path`` de la siguiente manera: 18 | 19 | :: 20 | 21 | solc github.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/ =/usr/local/lib/fallback file.sol 22 | 23 | Esencialmente esto instruye al compilador a buscar cualquier cosa que empiece con 24 | ``github.com/ethereum/dapp-bin/`` bajo ``/usr/local/lib/dapp-bin`` y si no localiza el fichero ahí, mirará en ``/usr/local/lib/fallback`` (el prefijo vacío siempre coincide). ``solc`` no leerá ficheros del sistema de ficheros que se encuentren fuera de los objetivos de reasignación y fuera de los directorios donde se especifica explícitamente la fuente de ficheros donde residen, con lo cual cosas como ``import "/etc/passwd";`` sólo funcionan si le añades ``=/`` como una reasignacion. 25 | 26 | Si hay coincidencias múltiples debido a reasignaciones, se selecciona el prefijo común más largo. 27 | 28 | Por razones de seguridad, el compilador tiene restricciones sobre a qué directorios puede acceder. Las rutas de acceso (y sus subdirectorios) de los archivos de origen especificados en la línea de comandos y las rutas definidas por las reasignaciones se permiten para las instrucciones de importación, pero todo lo demás se rechaza. Se pueden permitir rutas adicionales (y sus subdirectorios) a través de la opción ``--allow-paths /sample/path,/another/sample/path``. 29 | 30 | Si tus contratos usan :ref:`bibliotecas `, notarás que el bytecode contiene subcadenas del tipo ``__LibraryName______``. Puedes utilizar ``solc`` como un enlazador, lo que significa que insertará las direcciones de la biblioteca en esos puntos: 31 | 32 | Agregue ``--libraries "Math:0x12345678901234567890 Heap:0xabcdef0123456"`` a su comando para proporcionar una dirección para cada biblioteca o almacenar la cadena en un archivo (una biblioteca por línea) y ejecutar `` solc`` usando `` --libraries fileName``. 33 | 34 | Si ``solc`` se llama con la opción ``--link``, todos los archivos de entrada se interpretan como binarios desvinculados (codificados en hexadecimal) en el ``__LibraryName____``-format dado anteriormente y están enlazados in situ (si la entrada se lee desde stdin, se escribe en stdout). Todas las opciones excepto ``--libraries`` son ignoradas (incluyendo ``-o``) en este caso. 35 | 36 | Si ``solc`` se llama con la opción ``--standard-json``, esperará una entrada JSON (como se explica a continuación) en la entrada estándar, y devolverá una salida JSON a la salida estándar. 37 | 38 | .. _compiler-api: 39 | 40 | Compilador de entrada y salida JSON Descripción 41 | *********************************************** 42 | 43 | Estos formatos JSON son utilizados por la API del compilador y están disponibles a través de ``solc``. Estos están sujetos a cambios, algunos campos son opcionales (como se ha señalado), pero está dirigido a hacer sólo cambios compatibles hacia atrás. 44 | 45 | La API del compilador espera una entrada con formato JSON y genera el resultado de la compilación en una salida con formato JSON. 46 | 47 | Por supuesto, los comentarios no se permiten y se utilizan aquí sólo con fines explicativos. 48 | 49 | Descripción de entrada 50 | ---------------------- 51 | 52 | .. code-block:: none 53 | 54 | { 55 | // Requerido: Lenguaje del código fuente, tal como "Solidity", "serpent", "lll", "assembly", etc. 56 | language: "Solidity", 57 | // Requerido 58 | sources: 59 | { 60 | // Las claves aquí son los nombres "globales" de los ficheros fuente, 61 | // las importaciones pueden utilizar otros ficheros mediante remappings (vér más abajo). 62 | "myFile.sol": 63 | { 64 | // Opcional: keccak256 hash del fichero fuente 65 | // Se utiliza para verificar el contenido recuperado si se importa a través de URLs. 66 | "keccak256": "0x123...", 67 | // Requerido (a menos que se use "contenido", ver abajo): URL (s) al fichero fuente. 68 | // URL(s) deben ser importadas en este orden y el resultado debe ser verificado contra el fichero 69 | // keccak256 hash (si está disponible). Si el hash no coincide con ninguno de los 70 | // URL(s) resultado en el éxito, un error debe ser elevado. 71 | "urls": 72 | [ 73 | "bzzr://56ab...", 74 | "ipfs://Qma...", 75 | "file:///tmp/path/to/file.sol" 76 | ] 77 | }, 78 | "mortal": 79 | { 80 | // Opcional: keccak256 hash del fichero fuente 81 | "keccak256": "0x234...", 82 | // Requerido (a menos que se use "urls"): contenido literal del fichero fuente 83 | "content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }" 84 | } 85 | }, 86 | // Opcional 87 | settings: 88 | { 89 | // Opcional: Lista ordenada de remappings 90 | remappings: [ ":g/dir" ], 91 | // Opcional: Ajustes de optimización (activación de valores predeterminados a false) 92 | optimizador: { 93 | enabled: true, 94 | runs: 500 95 | }, 96 | // Configuración de metadatos (opcional) 97 | metadata: { 98 | // Usar sólo contenido literal y no URLs (falso por defecto) 99 | useLiteralContent: true 100 | }, 101 | // Direcciones de las bibliotecas. Si no todas las bibliotecas se dan aquí, puede resultar con objetos no vinculados cuyos datos de salida son diferentes. 102 | libraries: { 103 | // La clave superior es el nombre del fichero fuente donde se utiliza la biblioteca. 104 | // Si se utiliza remappings, este fichero fuente debe coincidir con la ruta global después de que se hayan aplicado los remappings. 105 | // Si esta clave es una cadena vacía, se refiere a un nivel global. 106 | 107 | "myFile.sol": { 108 | "MyLib": "0x123123..." 109 | } 110 | } 111 | // Para seleccionar las salidas deseadas se puede utilizar lo siguiente. 112 | // Si este campo se omite, el compilador se carga y comprueba el tipo, pero no genera ninguna salida aparte de errores. 113 | // La clave de primer nivel es el nombre del fichero y la segunda es el nombre del contrato, donde el nombre vacío del contrato se refiere al fichero mismo, 114 | // mientras que la estrella se refiere a todos los contratos. 115 | // 116 | // Las clases de mensajes disponibles son las siguientes: 117 | // abi - ABI 118 | // ast - AST de todos los ficheros fuente 119 | // legacyAST - legado AST de todos los ficheros fuente 120 | // devdoc - Documentación para desarrolladores (natspec) 121 | // userdoc - Documentación de usuario (natspec) 122 | // metadata - Metadatos 123 | // ir - Nuevo formato de ensamblador antes del desazucarado 124 | // evm.assembly - Nuevo formato de ensamblador después del desazucarado 125 | // evm.legacyAssembly - Formato de ensamblador antiguo en JSON 126 | // evm.bytecode.object - Objeto bytecode 127 | // evm.bytecode.opcodes - Lista de Opcodes 128 | // evm.bytecode.sourceMap - Asignación de fuentes (útil para depuración) 129 | // evm.bytecode.linkReferences - Referencias de enlace (si es objeto no enlazado) 130 | // evm.deployedBytecode* - Desplegado bytecode (tiene las mismas opciones que evm.bytecode) 131 | // evm.methodIdentifiers - La lista de funciones de hashes 132 | // evm.gasEstimates - Funcion de estimación de gas 133 | // ewasm.wast - eWASM S-formato de expresiones (no compatible por el momento) 134 | // ewasm.wasm - eWASM formato binario (no compatible por el momento) 135 | // 136 | // Ten en cuenta que el uso de `evm`, `evm.bytecode`, `ewasm`, etc. seleccionara cada 137 | // parte objetiva de esa salida. 138 | // 139 | outputSelection: { 140 | // Habilita los metadatos y las salidas de bytecode de cada contrato. 141 | "*": { 142 | "*": [ "metadata", "evm.bytecode" ] 143 | }, 144 | // Habilitar la salida abi y opcodes de MyContract definida en el fichero def. 145 | "def": { 146 | "MyContract": [ "abi", "evm.opcodes" ] 147 | }, 148 | // Habilita la salida del mapa de fuentes de cada contrato individual. 149 | "*": { 150 | "*": [ "evm.sourceMap" ] 151 | }, 152 | // Habilita la salida AST heredada de cada archivo. 153 | "*": { 154 | "": [ "legacyAST" ] 155 | } 156 | } 157 | } 158 | } 159 | 160 | Descripción de los mensajes de salida 161 | ------------------------------------- 162 | 163 | .. code-block:: none 164 | 165 | { 166 | // Opcional: no está presente si no se han encontrado errores/avisos 167 | errors: [ 168 | { 169 | // Opcional: Ubicación dentro del fichero fuente. 170 | sourceLocation: { 171 | file: "sourceFile.sol", 172 | start: 0, 173 | end: 100 174 | ], 175 | // Obligatorio: Tipo de error, como "TypeError", "InternalCompilerError", "Exception", etc 176 | type: "TypeError", 177 | // Obligatorio: Componente donde se originó el error, como "general", "ewasm", etc. 178 | component: "general", 179 | // Obligatorio ("error" o "warning") 180 | severity: "error", 181 | // Obligatorio 182 | message: "Invalid keyword" 183 | // Opcional: el mensaje formateado con la ubicación de origen 184 | formattedMessage: "sourceFile.sol:100: Invalid keyword" 185 | } 186 | ], 187 | // Contiene las salidas a nivel de fichero. Puede ser limitado/filtrado por los ajustes de outputSelection. 188 | sources: { 189 | "sourceFile.sol": { 190 | // Identificador (utilizado en los mapas fuente) 191 | id: 1, 192 | // El objeto AST 193 | ast: {}, 194 | // El objeto legado AST 195 | legacyAST: {} 196 | } 197 | }, 198 | // Contiene las salidas contract-level. Puede ser limitado/filtrado por los ajustes de outputSelection. 199 | contracts: { 200 | "sourceFile.sol": { 201 | // Si el idioma utilizado no tiene nombres de contrato, este campo debe ser igual a una cadena vacía. 202 | "ContractName": { 203 | // El ABI del contrato de Ethereum. Si está vacío, se representa como una matriz vacía. 204 | // Ver https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI 205 | abi: [], 206 | // Ver la documentación de salida de metadatos (cadena JSON seriada) 207 | metadata: "{...}", 208 | // Documentación de usuario (natspec) 209 | userdoc: {}, 210 | // Documentación para desarrolladores (natspec) 211 | devdoc: {}, 212 | // Representación intermedia (cadena) 213 | ir: "", 214 | // EVM-salidas relacionadas 215 | evm: { 216 | // Ensamblador (cadena) 217 | assembly: "", 218 | // Ensamblador antiguo (objeto) 219 | legacyAssembly: {}, 220 | // Bytecode y detalles relacionados. 221 | bytecode: { 222 | // El bytecode como una cadena hexadecimal. 223 | object: "00fe", 224 | // Lista de Opcodes (cadena) 225 | opcodes: "", 226 | // El mapeo de fuentes como una cadena. Ve la definición del mapeo de fuentes. 227 | sourceMap: "", 228 | // Si se da, este es un objeto no ligado. 229 | linkReferences: { 230 | "libraryFile.sol": { 231 | // Traslados de bytes en el bytecode. El enlace sustituye a los 20 bytes que se encuentran allí. 232 | "Library1": [ 233 | { start: 0, length: 20 }, 234 | { start: 200, length: 20 } 235 | ] 236 | } 237 | } 238 | }, 239 | // La misma disposición que la anterior. 240 | deployedBytecode: { }, 241 | // La lista de hashes de función 242 | methodIdentifiers: { 243 | "delegate(address)": "5c19a95c" 244 | }, 245 | // Estimación de gas de la función 246 | gasEstimates: { 247 | creation: { 248 | codeDepositCost: "420000", 249 | executionCost: "infinite", 250 | totalCost: "infinite" 251 | }, 252 | external: { 253 | "delegate(address)": "25000" 254 | }, 255 | internal: { 256 | "heavyLifting()": "infinite" 257 | } 258 | } 259 | }, 260 | // eWASM resultados relacionados 261 | ewasm: { 262 | // S-formato de expressiones 263 | wast: "", 264 | // Formato Binario (cadena hexagonal) 265 | wasm: "" 266 | } 267 | } 268 | } 269 | } 270 | } 271 | -------------------------------------------------------------------------------- /utils/SolidityLexer.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import re 4 | import copy 5 | 6 | from pygments.lexer import RegexLexer, ExtendedRegexLexer, bygroups, using, \ 7 | include, this 8 | from pygments.token import Text, Comment, Operator, Keyword, Name, String, \ 9 | Number, Other, Punctuation, Literal 10 | 11 | __all__ = ['SolidityLexer'] 12 | 13 | class SolidityLexer(RegexLexer): 14 | name = "Solidity" 15 | aliases = ['sol', 'solidity'] 16 | filenames = ['*.sol'] 17 | mimetypes = [] 18 | flags = re.DOTALL 19 | tokens = { 20 | 'commentsandwhitespace': [ 21 | (r'\s+', Text), 22 | (r'