Está en la página 1de 28

Introducción a los contratos

inteligentes
Un contrato inteligente simple

Comencemos con un ejemplo básico que establece el valor de una variable y lo


expone para que accedan otros contratos. Está bien si no comprende todo en este
momento, entraremos en más detalles más adelante.

Ejemplo de almacenamiento
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;

contract SimpleStorage {
uint storedData;

function set(uint x) public {


storedData = x;
}

function get() public view returns (uint) {


return storedData;
}
}

La primera línea le dice que el código fuente tiene la licencia GPL versión 3.0. Los
especificadores de licencias legibles por máquina son importantes en un entorno
en el que la publicación del código fuente es la predeterminada.

La siguiente línea especifica que el código fuente está escrito para la versión
0.4.16 de Solidity, o una versión más reciente del idioma hasta, pero sin incluir la
versión 0.9.0. Esto es para asegurar que el contrato no sea compilable con una
nueva versión del compilador (rompiendo), donde podría comportarse de manera
diferente. Los pragmas son instrucciones comunes para los compiladores sobre
cómo tratar el código fuente (por ejemplo, pragma una vez ).

Un contrato en el sentido de Solidez es una colección de código (sus funciones ) y


datos (su estado ) que residen en una dirección específica en la cadena de
bloques Ethereum. La línea declara una variable de estado de llamada de
tipo ( u nsigned int Eger de 256 bits). Puede pensar en ello como una única ranura
en una base de datos que puede consultar y modificar llamando a funciones del
código que administra la base de datos. En este ejemplo, el contrato define las
funciones y eso se puede utilizar para modificar o recuperar el valor de la
variable. uint storedData;storedDatauintsetget

Para acceder a un miembro (como una variable de estado) del contrato actual,
normalmente no agrega el  this. prefijo, solo accede a él directamente a través de
su nombre. A diferencia de otros idiomas, omitirlo no es solo una cuestión de
estilo, da como resultado una forma completamente diferente de acceder al
miembro, pero más sobre esto más adelante.

Este contrato aún no hace mucho aparte de (debido a la infraestructura construida


por Ethereum) que permite a cualquier persona almacenar un solo número al que
puede acceder cualquier persona en el mundo sin una forma (factible) de evitar
que publique este número. Cualquiera podría  set volver a llamar con un valor
diferente y sobrescribir su número, pero el número aún se almacena en el historial
de la cadena de bloques. Más adelante, verá cómo puede imponer restricciones
de acceso para que solo usted pueda alterar el número.

Advertencia

Tenga cuidado con el uso de texto Unicode, ya que los caracteres de aspecto
similar (o incluso idénticos) pueden tener diferentes puntos de código y, como
tales, se codifican como una matriz de bytes diferente.
Nota

Todos los identificadores (nombres de contratos, nombres de funciones y nombres


de variables) están restringidos al juego de caracteres ASCII. Es posible
almacenar datos codificados en UTF-8 en variables de cadena.

Ejemplo de submoneda

El siguiente contrato implementa la forma más simple de una criptomoneda. El


contrato permite que solo su creador cree nuevas monedas (son posibles
diferentes esquemas de emisión). Cualquiera puede enviarse monedas entre sí sin
necesidad de registrarse con un nombre de usuario y contraseña, todo lo que
necesita es un par de claves Ethereum.
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.4;

contract Coin {
// The keyword "public" makes variables
// accessible from other contracts
address public minter;
mapping (address => uint) public balances;

// Events allow clients to react to specific


// contract changes you declare
event Sent(address from, address to, uint amount);

// Constructor code is only run when the contract


// is created
constructor() {
minter = msg.sender;
}

// Sends an amount of newly created coins to an address


// Can only be called by the contract creator
function mint(address receiver, uint amount) public {
require(msg.sender == minter);
balances[receiver] += amount;
}

// Errors allow you to provide information about


// why an operation failed. They are returned
// to the caller of the function.
error InsufficientBalance(uint requested, uint available);

// Sends an amount of existing coins


// from any caller to an address
function send(address receiver, uint amount) public {
if (amount > balances[msg.sender])
revert InsufficientBalance({
requested: amount,
available: balances[msg.sender]
});

balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
}

Este contrato introduce algunos conceptos nuevos, repasemos uno por uno.

La línea declara una variable de estado de tipo dirección . El tipo es un valor de


160 bits que no permite operaciones aritméticas. Es adecuado para almacenar
direcciones de contratos o un hash de la mitad pública de un par de claves que
pertenece a cuentas externas . address public minter;address

La palabra clave  public genera automáticamente una función que le permite


acceder al valor actual de la variable de estado desde fuera del contrato. Sin esta
palabra clave, otros contratos no tienen forma de acceder a la variable. El código
de la función generado por el compilador es equivalente al siguiente
(ignorar  external y  view por ahora):

function minter() external view returns (address) { return minter; }

Puede agregar una función como la anterior usted mismo, pero tendría una
función y una variable de estado con el mismo nombre. No es necesario que haga
esto, el compilador lo resolverá por usted.

La siguiente línea también crea una variable de estado pública, pero es un tipo de


datos más complejo. El tipo de mapeo asigna direcciones a enteros sin
signo . mapping (address => uint) public balances;

Las asignaciones pueden verse como tablas hash que se inicializan virtualmente


de modo que todas las claves posibles existen desde el principio y se asignan a un
valor cuya representación de bytes es todo ceros. Sin embargo, no es posible
obtener una lista de todas las claves de una asignación, ni una lista de todos los
valores. Registre lo que agregó al mapeo o utilícelo en un contexto en el que no
sea necesario. O mejor aún, mantenga una lista o use un tipo de datos más
adecuado.

La función getter creada por la  public palabra clave es más compleja en el caso de
un mapeo. Se parece a lo siguiente:

function balances(address _account) external view returns (uint) {


return balances[_account];
}

Puede utilizar esta función para consultar el saldo de una sola cuenta.

La línea declara un "evento" , que se emite en la última línea de la función . Los


clientes de Ethereum, como las aplicaciones web, pueden escuchar estos eventos
emitidos en la cadena de bloques sin mucho costo. Tan pronto como se emite, el
detector reciba los argumentos , y , lo que hace posible el seguimiento de las
transacciones. event Sent(address from, address to, uint amount);sendfromtoamount
Para escuchar este evento, puede usar el siguiente código JavaScript, que
usa web3.js para crear el  Coin objeto del contrato, y cualquier interfaz de usuario
llama a la  balances función generada automáticamente desde arriba:

Coin.Sent().watch({}, '', function(error, result) {


if (!error) {
console.log("Coin transfer: " + result.args.amount +
" coins were sent from " + result.args.from +
" to " + result.args.to + ".");
console.log("Balances now:\n" +
"Sender: " + Coin.balances.call(result.args.from) +
"Receiver: " + Coin.balances.call(result.args.to));
}
})

El constructor es una función especial que se ejecuta durante la creación del


contrato y no se puede llamar posteriormente. En este caso, almacena
permanentemente la dirección de la persona que crea el contrato. La  msg variable
(junto con  tx y  block ) es una variable global especial que contiene propiedades
que permiten el acceso a la cadena de bloques.  msg.sender es siempre la dirección
de donde vino la llamada de función actual (externa).

Las funciones que componen el contrato, y que los usuarios y contratos pueden
llamar son  mint y  send .

La  mint función envía una cantidad de monedas recién creadas a otra
dirección. La llamada a la función require define condiciones que revierten todos
los cambios si no se cumplen. En este ejemplo, asegura que solo el creador del
contrato pueda llamar . En general, el creador puede acuñar tantas fichas como
quiera, pero en algún momento, esto conducirá a un fenómeno llamado
"desbordamiento". Tenga en cuenta que debido a la aritmética
Checked predeterminada , la transacción se revertiría si la expresión se desborda,
es decir, cuando la aritmética de precisión arbitraria es mayor que el valor máximo
de ( ). Esto también es cierto para la declaración de la
función . require(msg.sender == minter);mintbalances[receiver] += amount;balances[receiv
er] + amountuint2**256 - 1balances[receiver] += amount;send

Los errores le permiten brindar más información a la persona que llama sobre por
qué falló una condición u operación. Los errores se utilizan junto con
la declaración revert . La declaración de reversión anula incondicionalmente y
revierte todos los cambios similares a la require función, pero también le permite
proporcionar el nombre de un error y datos adicionales que se proporcionarán a la
persona que llama (y eventualmente a la aplicación front-end o al explorador de
bloques). que una falla se puede depurar o reaccionar más fácilmente.

La  send función puede ser utilizada por cualquier persona (que ya tenga algunas
de estas monedas) para enviar monedas a cualquier otra persona. Si el remitente
no tiene suficientes monedas para enviar, la  if condición se evalúa como
verdadera. Como resultado,  revert hará que la operación falle mientras se
proporciona al remitente los detalles del  InsufficientBalance error utilizando el error.

Nota

Si usa este contrato para enviar monedas a una dirección, no verá nada cuando
mire esa dirección en un explorador de blockchain, porque el registro que envió
monedas y los saldos cambiados solo se almacenan en el almacenamiento de
datos de esta moneda en particular. contrato. Mediante el uso de eventos, puede
crear un "explorador de blockchain" que rastrea las transacciones y los saldos de
su nueva moneda, pero debe inspeccionar la dirección del contrato de la moneda
y no las direcciones de los propietarios de la moneda.

Conceptos básicos de blockchain

Las cadenas de bloques como concepto no son demasiado difíciles de entender


para los programadores. La razón es que la mayoría de las complicaciones
(minería, hash , criptografía de curva elíptica , redes peer-to-peer , etc.) están ahí
para proporcionar un cierto conjunto de características y promesas para la
plataforma. Una vez que acepta estas funciones como se ofrecen, no tiene que
preocuparse por la tecnología subyacente, ¿o debe saber cómo funciona AWS de
Amazon internamente para poder usarla?

Actas

Una cadena de bloques es una base de datos transaccional compartida


globalmente. Esto significa que todos pueden leer las entradas en la base de
datos simplemente participando en la red. Si desea cambiar algo en la base de
datos, debe crear una llamada transacción que debe ser aceptada por todos los
demás. La palabra transacción implica que el cambio que desea realizar (suponga
que desea cambiar dos valores al mismo tiempo) no se realizó en absoluto o se
aplicó por completo. Además, mientras su transacción se aplica a la base de
datos, ninguna otra transacción puede alterarla.

Como ejemplo, imagine una tabla que enumere los saldos de todas las cuentas en
una moneda electrónica. Si se solicita una transferencia de una cuenta a otra, la
naturaleza transaccional de la base de datos asegura que si el monto se resta de
una cuenta, siempre se agrega a la otra cuenta. Si por alguna razón no es posible
agregar el monto a la cuenta de destino, la cuenta de origen tampoco se modifica.

Además, una transacción siempre está firmada criptográficamente por el remitente


(creador). Esto hace que sea sencillo proteger el acceso a modificaciones
específicas de la base de datos. En el ejemplo de la moneda electrónica, un
simple cheque asegura que solo la persona que tiene las llaves de la cuenta
puede transferir dinero desde ella.

Bloques

Un obstáculo importante a superar es lo que (en términos de Bitcoin) se llama un


"ataque de doble gasto": ¿Qué sucede si existen dos transacciones en la red que
quieren vaciar una cuenta? Solo una de las transacciones puede ser válida,
normalmente la que se acepta primero. El problema es que "primero" no es un
término objetivo en una red de igual a igual.

La respuesta abstracta a esto es que no tiene por qué preocuparse. Se


seleccionará para usted un orden globalmente aceptado de las transacciones,
resolviendo el conflicto. Las transacciones se agruparán en lo que se denomina un
"bloque" y luego se ejecutarán y distribuirán entre todos los nodos participantes. Si
dos transacciones se contradicen, la que acabe en segundo lugar será rechazada
y no pasará a formar parte del bloque.

Estos bloques forman una secuencia lineal en el tiempo y de ahí proviene la


palabra “blockchain”. Los bloques se agregan a la cadena en intervalos bastante
regulares; para Ethereum, esto es aproximadamente cada 17 segundos.
Como parte del "mecanismo de selección de orden" (que se llama "minería")
puede suceder que los bloques se reviertan de vez en cuando, pero solo en la
"punta" de la cadena. Cuantos más bloques se agreguen encima de un bloque en
particular, es menos probable que este bloque se revierta. Por lo tanto, es posible
que sus transacciones se reviertan e incluso se eliminen de la cadena de bloques,
pero cuanto más espere, menos probable será.

Nota

No se garantiza que las transacciones se incluyan en el siguiente bloque o en


cualquier bloque futuro específico, ya que no depende del remitente de una
transacción, sino de los mineros determinar en qué bloque se incluye la
transacción.

Si desea programar futuras llamadas de su contrato, puede usar el despertador o


un servicio similar de Oracle.

La máquina virtual Ethereum


Visión general

La máquina virtual Ethereum o EVM es el entorno de tiempo de ejecución para


contratos inteligentes en Ethereum. No solo está en un espacio aislado, sino que
en realidad está completamente aislado, lo que significa que el código que se
ejecuta dentro del EVM no tiene acceso a la red, el sistema de archivos u otros
procesos. Los contratos inteligentes incluso tienen acceso limitado a otros
contratos inteligentes.

Cuentas

Hay dos tipos de cuentas en Ethereum que comparten el mismo espacio de


direcciones: cuentas externas que están controladas por pares de claves público-
privadas (es decir, humanos) y cuentas de contrato que están controladas por el
código almacenado junto con la cuenta.

La dirección de una cuenta externa se determina a partir de la clave pública,


mientras que la dirección de un contrato se determina en el momento en que se
crea el contrato (se deriva de la dirección del creador y el número de
transacciones enviadas desde esa dirección, la llamada " mientras tanto").

Independientemente de si la cuenta almacena código o no, el EVM trata los dos


tipos por igual.

Cada cuenta tiene un almacén de clave-valor persistente que asigna palabras de


256 bits a palabras de 256 bits llamadas almacenamiento .

Además, cada cuenta tiene un saldo en éter (en “Wei” para ser exactos, es ) que
puede ser modificado mediante el envío de transacciones que incluyen
éter. 1 ether10**18 wei

Actas

Una transacción es un mensaje que se envía de una cuenta a otra (que puede ser
la misma o estar vacía, ver más abajo). Puede incluir datos binarios (que se
denominan "carga útil") y Ether.

Si la cuenta de destino contiene código, ese código se ejecuta y la carga útil se


proporciona como datos de entrada.

Si la cuenta de destino no está configurada (la transacción no tiene un destinatario


o el destinatario está configurado para  null ), la transacción crea un nuevo
contrato . Como ya se mencionó, la dirección de ese contrato no es la dirección
cero sino una dirección derivada del remitente y su número de transacciones
enviadas (el "nonce"). La carga útil de dicha transacción de creación de contrato
se toma como código de bytes EVM y se ejecuta. Los datos de salida de esta
ejecución se almacenan permanentemente como el código del contrato. Esto
significa que para crear un contrato, no envía el código real del contrato, sino el
código que devuelve ese código cuando se ejecuta.

Nota
Mientras se crea un contrato, su código aún está vacío. Por eso, no debe volver a
llamar al contrato en construcción hasta que su constructor haya terminado de
ejecutarse.

Gas

Al momento de su creación, cada transacción se carga con una cierta cantidad


de gas , cuyo propósito es limitar la cantidad de trabajo que se necesita para
ejecutar la transacción y pagar por esta ejecución al mismo tiempo. Mientras EVM
ejecuta la transacción, el gas se agota gradualmente de acuerdo con reglas
específicas.

El precio del gas es un valor establecido por el creador de la transacción, quien


tiene que pagar por adelantado desde la cuenta de envío. Si queda algo de gas
después de la ejecución, se reembolsa al creador de la misma
manera. gas_price * gas

Si el gas se agota en cualquier momento (es decir, sería negativo), se activa una
excepción de falta de gas, que revierte todas las modificaciones realizadas al
estado en la trama de llamada actual.

Almacenamiento, memoria y pila

La máquina virtual Ethereum tiene tres áreas donde puede almacenar datos:
almacenamiento, memoria y pila, que se explican en los siguientes párrafos.

Cada cuenta tiene un área de datos llamada almacenamiento , que es persistente


entre las llamadas a funciones y las transacciones. El almacenamiento es un
almacén de valores clave que asigna palabras de 256 bits a palabras de 256
bits. No es posible enumerar el almacenamiento desde dentro de un contrato, es
comparativamente costoso de leer y aún más inicializar y modificar el
almacenamiento. Debido a este costo, debe minimizar lo que almacena en el
almacenamiento persistente a lo que el contrato necesita para
ejecutarse. Almacene datos como cálculos derivados, almacenamiento en caché y
agregados fuera del contrato. Un contrato no puede leer ni escribir en ningún
almacenamiento que no sea el propio.
La segunda área de datos se llama memoria , de la cual un contrato obtiene una
instancia recién borrada para cada llamada de mensaje. La memoria es lineal y se
puede direccionar a nivel de bytes, pero las lecturas están limitadas a un ancho de
256 bits, mientras que las escrituras pueden tener un ancho de 8 bits o 256
bits. La memoria se expande por una palabra (256 bits), cuando se accede (ya sea
leyendo o escribiendo) una palabra de memoria previamente intacta (es decir,
cualquier desplazamiento dentro de una palabra). En el momento de la expansión,
se debe pagar el costo en gas. La memoria es más costosa cuanto más crece
(escala cuadráticamente).

El EVM no es una máquina de registro sino una máquina de pila, por lo que todos
los cálculos se realizan en un área de datos llamada pila . Tiene un tamaño
máximo de 1024 elementos y contiene palabras de 256 bits. El acceso a la pila
está limitado al extremo superior de la siguiente manera: Es posible copiar uno de
los 16 elementos superiores a la parte superior de la pila o intercambiar el
elemento superior por uno de los 16 elementos inferiores. Todas las demás
operaciones toman los dos elementos superiores (o uno, o más, dependiendo de
la operación) de la pila y empujan el resultado a la pila. Por supuesto, es posible
mover elementos de la pila al almacenamiento o memoria para obtener un acceso
más profundo a la pila, pero no es posible acceder simplemente a elementos
arbitrarios más profundos en la pila sin quitar primero la parte superior de la pila.

Conjunto de instrucciones

El conjunto de instrucciones del EVM se mantiene al mínimo para evitar


implementaciones incorrectas o inconsistentes que podrían causar problemas de
consenso. Todas las instrucciones operan en el tipo de datos básico, palabras de
256 bits o en segmentos de memoria (u otras matrices de bytes). Están presentes
las operaciones aritméticas, de bits, lógicas y de comparación habituales. Los
saltos condicionales e incondicionales son posibles. Además, los contratos pueden
acceder a propiedades relevantes del bloque actual como su número y marca de
tiempo.

Para obtener una lista completa, consulte la lista de códigos de operación como


parte de la documentación de ensamblaje en línea.
Llamadas de mensaje

Los contratos pueden llamar a otros contratos o enviar Ether a cuentas sin
contrato mediante llamadas de mensajes. Las llamadas de mensajes son similares
a las transacciones, ya que tienen una fuente, un objetivo, una carga útil de datos,
Ether, gas y datos de retorno. De hecho, cada transacción consta de una llamada
de mensaje de nivel superior que, a su vez, puede crear más llamadas de
mensaje.

Un contrato puede decidir cuánto de su gas restante debe enviarse con la llamada


de mensaje interno y cuánto desea retener. Si ocurre una excepción de falta de
gas en la llamada interna (o cualquier otra excepción), esto será señalado por un
valor de error puesto en la pila. En este caso, solo se agota el gas enviado junto
con la llamada. En Solidity, el contrato de llamada provoca una excepción manual
de forma predeterminada en tales situaciones, de modo que las excepciones
"burbujean" en la pila de llamadas.

Como ya se dijo, el contrato llamado (que puede ser el mismo que el de la persona
que llama) recibirá una instancia de memoria recién borrada y tendrá acceso a la
carga útil de la llamada, que se proporcionará en un área separada
llamada calldata . Una vez finalizada la ejecución, puede devolver datos que se
almacenarán en una ubicación en la memoria de la persona que llama
previamente asignada por la persona que llama. Todas estas llamadas son
completamente sincrónicas.

Las llamadas están limitadas a una profundidad de 1024, lo que significa que


para operaciones más complejas, los bucles deben preferirse a las llamadas
recursivas. Además, solo el 63/64 del gas se puede reenviar en una llamada de
mensaje, lo que provoca un límite de profundidad de un poco menos de 1000 en la
práctica.

Delegatecall / Callcode y bibliotecas

Existe una variante especial de una llamada de mensaje,


llamada delegatecall, que es idéntica a una llamada de mensaje, aparte del hecho
de que el código en la dirección de destino se ejecuta en el contexto del contrato
de llamada  msg.sender y  msg.value no cambia sus valores.

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 saldo aún se refieren al contrato de llamada, solo se toma el código de la
dirección llamada.

Esto hace posible implementar la función de "biblioteca" en Solidity: código de


biblioteca reutilizable que se puede aplicar al almacenamiento de un contrato, por
ejemplo, para implementar una estructura de datos compleja.

Registros

Es posible almacenar datos en una estructura de datos especialmente indexada


que se mapea hasta el nivel del bloque. Esta característica llamada logs es
utilizada por Solidity para implementar eventos . Los contratos no pueden acceder
a los datos de registro después de que se hayan creado, pero se puede acceder a
ellos de manera eficiente desde fuera de la cadena de bloques. Dado que una
parte de los datos de registro se almacena en filtros de floración , es posible
buscar estos datos de una manera eficiente y criptográficamente segura, por lo
que los pares de la red que no descargan toda la cadena de bloques (los llamados
"clientes ligeros") aún pueden encuentre estos registros.

Crear

Los contratos pueden incluso crear otros contratos utilizando un código de


operación especial (es decir, no llaman simplemente a la dirección cero como lo
haría una transacción). La única diferencia entre estas llamadas de creación y
las llamadas de mensajes normales es que los datos de carga útil se ejecutan y el
resultado se almacena como código y la persona que llama / creador recibe la
dirección del nuevo contrato en la pila.

Desactivar y autodestruirse
La única forma de eliminar el código de la cadena de bloques es cuando un
contrato en esa dirección realiza la  selfdestruct operación. El Ether restante
almacenado en esa dirección se envía a un destino designado y luego el
almacenamiento y el código se eliminan del estado. Eliminar el contrato en teoría
suena como una buena idea, pero es potencialmente peligroso, ya que si alguien
envía Ether a contratos eliminados, el Ether se pierde para siempre.

Advertencia

Incluso si un contrato es eliminado por  selfdestruct , sigue siendo parte de la


historia de la cadena de bloques y probablemente retenido por la mayoría de los
nodos de Ethereum. Entonces, usar  selfdestruct no es lo mismo que eliminar datos
de un disco duro.
Nota

Incluso si el código de un contrato no contiene una llamada a  selfdestruct , aún


puede realizar esa operación usando  delegatecall o  callcode .

Si desea desactivar sus contratos, debe desactivarlos cambiando algún estado


interno que hace que todas las funciones se reviertan. Esto hace que sea
imposible utilizar el contrato, ya que devuelve Ether inmediatamente.

Contratos precompilados

Hay un pequeño conjunto de direcciones de contrato que son especiales: el rango


de direcciones entre  1 e (incluido)  8 contiene "contratos precompilados" que se
pueden llamar como cualquier otro contrato, pero su comportamiento (y su
consumo de gas) no está definido por el código EVM almacenado en esa dirección
(no contienen código) sino que se implementa en el propio entorno de ejecución
de EVM.

Diferentes cadenas compatibles con EVM pueden usar un conjunto diferente de


contratos precompilados. También es posible que se agreguen nuevos contratos
precompilados a la cadena principal de Ethereum en el futuro, pero puede esperar
razonablemente que siempre estén en el rango entre  1 y  0xffff (inclusive).

 Anteriorpróximo 
Instalación del compilador de solidez
Control de versiones

Las versiones de Solidity siguen versiones semánticas y, además de los


lanzamientos, también están disponibles las compilaciones de desarrollo
nocturno . No se garantiza que las compilaciones nocturnas funcionen y, a pesar
de los mejores esfuerzos, pueden contener cambios indocumentados y / o
rotos. Recomendamos utilizar la última versión. Los instaladores de paquetes a
continuación utilizarán la última versión.

Remezclar

Recomendamos Remix para contratos pequeños y para aprender rápidamente


Solidity.

Acceda a Remix en línea , no necesita instalar nada. Si desea utilizarlo sin


conexión a Internet, vaya a https://github.com/ethereum/remix-live/tree/gh-pages y
descargue el  .zip archivo como se explica en esa página. Remix también es una
opción conveniente para probar compilaciones nocturnas sin instalar múltiples
versiones de Solidity.

Otras opciones en esta página detallan la instalación del software compilador


Solidity de la línea de comandos en su computadora. Elija un compilador de línea
de comandos si está trabajando en un contrato más grande o si necesita más
opciones de compilación.

npm / Node.js
Úselo  npm para instalar  solcjs un compilador Solidity de una manera conveniente y
portátil . El programa solcjs tiene menos funciones que las formas de acceder al
compilador descritas más abajo en esta página. El uso de la línea de comandos
del compilador documentación supone que está utilizando el compilador con todas
las funciones,  solc . El uso de  solcjs está documentado dentro de su
propio repositorio .
Nota: El proyecto solc-js se deriva de C ++ solc usando Emscripten, lo que
significa que ambos usan el mismo código fuente del compilador. solc-js se puede
utilizar directamente en proyectos de JavaScript (como Remix). Consulte el
repositorio solc-js para obtener instrucciones.

npm install -g solc

Nota

El ejecutable de la línea de comandos se llama  solcjs .

Las opciones de la línea de comandos de  solcjs no son compatibles con  solc y las
herramientas (como  geth ) que esperan el comportamiento de  solc no
funcionarán  solcjs .

Estibador

Las imágenes de Docker de las compilaciones de Solidity están disponibles


utilizando la  solc imagen de la  ethereum organización. Utilice la  stable etiqueta para
la última versión publicada y  nightly para cambios potencialmente inestables en la
rama de desarrollo.

La imagen de Docker ejecuta el ejecutable del compilador, por lo que puede


pasarle todos los argumentos del compilador. Por ejemplo, el siguiente comando
extrae la versión estable de la  solc imagen (si aún no la tiene) y la ejecuta en un
nuevo contenedor, pasando el  --help argumento.

docker run ethereum/solc:stable --help

También puede especificar versiones de compilación de lanzamiento en la


etiqueta, por ejemplo, para la versión 0.5.4.

docker run ethereum/solc:0.5.4 --help

Para usar la imagen de Docker para compilar archivos de Solidity en la máquina


host, monte una carpeta local para entrada y salida, y especifique el contrato a
compilar. Por ejemplo.

docker run -v /local/path:/sources ethereum/solc:stable -o /sources/output --abi --bin


/sources/Contract.sol
También puede utilizar la interfaz JSON estándar (que se recomienda cuando se
utiliza el compilador con herramientas). Cuando se utiliza esta interfaz, no es
necesario montar ningún directorio siempre que la entrada JSON sea autónoma
(es decir, no se refiere a ningún archivo externo que deba cargarse mediante la
devolución de llamada de importación ).

docker run ethereum/solc:stable --standard-json < input.json > output.json

Paquetes de Linux

Los paquetes binarios de Solidity están disponibles en solidez / lanzamientos .

También tenemos PPA para Ubuntu, puede obtener la última versión estable
usando los siguientes comandos:

sudo add-apt-repository ppa:ethereum/ethereum


sudo apt-get update
sudo apt-get install solc

La versión nocturna se puede instalar usando estos comandos:

sudo add-apt-repository ppa:ethereum/ethereum


sudo add-apt-repository ppa:ethereum/ethereum-dev
sudo apt-get update
sudo apt-get install solc

También estamos lanzando un paquete instantáneo , que se puede instalar en


todas las distribuciones de Linux compatibles . Para instalar la última versión
estable de solc:

sudo snap install solc

Si desea ayudar a probar la última versión de desarrollo de Solidity con los


cambios más recientes, utilice lo siguiente:

sudo snap install solc --edge

Nota

El  solc complemento utiliza un confinamiento estricto. Este es el modo más seguro


para los paquetes instantáneos, pero viene con limitaciones, como acceder solo a
los archivos en sus directorios  /home y  /media . Para obtener más información, vaya
a Desmitificar el confinamiento instantáneo .
Arch Linux también tiene paquetes, aunque limitados a la última versión de
desarrollo:

pacman -S solidity

Gentoo Linux tiene una superposición de Ethereum que contiene un paquete


Solidity. Una vez configurada la superposición,  solc se puede instalar en
arquitecturas x86_64 mediante:

emerge dev-lang/solidity

Paquetes macOS

Distribuimos el compilador Solidity a través de Homebrew como una versión


compilada desde el código fuente. Actualmente no se admiten botellas
prefabricadas.

brew update
brew upgrade
brew tap ethereum/ethereum
brew install solidity

Para instalar la versión 0.4.x / 0.5.x más reciente de Solidity también puede
usar y , respectivamente. brew install solidity@4brew install solidity@5

Si necesita una versión específica de Solidity, puede instalar una fórmula


Homebrew directamente desde Github.

Ver solidity.rb confirmaciones en Github .

Copie el hash de confirmación de la versión que desee y compruébelo en su


máquina.

git clone https://github.com/ethereum/homebrew-ethereum.git


cd homebrew-ethereum
git checkout <your-hash-goes-here>

Instálelo usando  brew :

brew unlink solidity


# eg. Install 0.4.8
brew install solidity.rb
Binarios estáticos

Mantenemos un repositorio que contiene compilaciones estáticas de versiones


pasadas y actuales del compilador para todas las plataformas compatibles en solc-
bin . Esta es también la ubicación donde puedes encontrar las construcciones
nocturnas.

El repositorio no solo es una forma rápida y fácil para que los usuarios finales
preparen binarios para usarlos de inmediato, sino que también está destinado a
ser compatible con herramientas de terceros:

 El contenido se refleja en https://binaries.soliditylang.org, donde se puede


descargar fácilmente a través de HTTPS sin ninguna autenticación, limitación
de velocidad o la necesidad de usar git.
 El contenido se sirve con encabezados de tipo de contenido correctos y una
configuración CORS indulgente para que pueda cargarse directamente
mediante herramientas que se ejecutan en el navegador.
 Los archivos binarios no requieren instalación o desempaquetado (con la
excepción de las versiones anteriores de Windows que se incluyen con las DLL
necesarias).
 Nos esforzamos por lograr un alto nivel de compatibilidad con versiones
anteriores. Los archivos, una vez agregados, no se eliminan ni se mueven sin
proporcionar un enlace simbólico / redireccionamiento a la ubicación
anterior. Tampoco se modifican nunca en su lugar y siempre deben coincidir
con la suma de comprobación original. La única excepción serían los archivos
rotos o inutilizables que podrían causar más daño que bien si se dejan como
están.
 Los archivos se sirven tanto a través de HTTP como de HTTPS. Siempre que
obtenga la lista de archivos de forma segura (a través de git, HTTPS, IPFS o
simplemente la tenga en caché localmente) y verifique los hash de los binarios
después de descargarlos, no tiene que usar HTTPS para los binarios en sí.
En la mayoría de los casos, los mismos binarios están disponibles en la página de
lanzamiento de Solidity en Github . La diferencia es que generalmente no
actualizamos las versiones antiguas en la página de versiones de Github. Esto
significa que no les cambiamos el nombre si cambia la convención de
nomenclatura y no agregamos compilaciones para plataformas que no eran
compatibles en el momento del lanzamiento. Esto solo ocurre en  solc-bin .

El  solc-bin repositorio contiene varios directorios de nivel superior, cada uno de los
cuales representa una única plataforma. Cada uno contiene un  list.json archivo
que enumera los binarios disponibles. Por ejemplo,
en  emscripten-wasm32/list.json encontrará la siguiente información sobre la versión
0.7.4:

{
"path": "solc-emscripten-wasm32-v0.7.4+commit.3f05b770.js",
"version": "0.7.4",
"build": "commit.3f05b770",
"longVersion": "0.7.4+commit.3f05b770",
"keccak256": "0x300330ecd127756b824aa13e843cb1f43c473cb22eaf3750d5fb9c99279af8c3",
"sha256": "0x2b55ed5fec4d9625b6c7b3ab1abd2b7fb7dd2a9c68543bf0323db2c7e2d55af2",
"urls": [
"bzzr://16c5f09109c793db99fe35f037c6092b061bd39260ee7a677c8a97f18c955ab1",
"dweb:/ipfs/QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS"
]
}

Esto significa que:

 Puede encontrar el binario en el mismo directorio con el nombre solc-


emscripten-wasm32-v0.7.4 + commit.3f05b770.js . Tenga en cuenta que el
archivo puede ser un enlace simbólico y deberá resolverlo usted mismo si no
está utilizando git para descargarlo o si su sistema de archivos no admite
enlaces simbólicos.
 El binario también se refleja en https://binaries.soliditylang.org/emscripten-
wasm32/solc-emscripten-wasm32-v0.7.4+commit.3f05b770.js . En este caso,
git no es necesario y los enlaces simbólicos se resuelven de forma
transparente, ya sea entregando una copia del archivo o devolviendo una
redirección HTTP.
 El archivo también está disponible en IPFS
en QmTLs5MuLEWXQkths41HiACoXDiH8zxyqBHGFDRSzVE5CS .
 El archivo podría estar disponible en el futuro en Swarm
en 16c5f09109c793db99fe35f037c6092b061bd39260ee7a677c8a97f18c955ab
1 .
 Puede verificar la integridad del binario comparando su hash keccak256
con  0x300330ecd127756b824aa13e843cb1f43c473cb22eaf3750d5fb9c99279af8c3 . El hash se
puede calcular en la línea de comando utilizando la  keccak256sum utilidad
proporcionada por la función sha3sum o keccak256 () de ethereumjs-util en
JavaScript.
 También puede verificar la integridad del binario comparando su hash sha256
con  0x2b55ed5fec4d9625b6c7b3ab1abd2b7fb7dd2a9c68543bf0323db2c7e2d55af2 .
Advertencia

Debido al fuerte requisito de compatibilidad con versiones anteriores, el repositorio


contiene algunos elementos heredados, pero debe evitar usarlos al escribir nuevas
herramientas:

 Úselo  emscripten-wasm32/ (con un respaldo a  emscripten-asmjs/ ) en lugar


de  bin/ si desea el mejor rendimiento. Hasta la versión 0.6.1, solo
proporcionábamos binarios asm.js. Comenzando con 0.6.2, cambiamos
a compilaciones de WebAssembly con un rendimiento mucho mejor. Hemos
reconstruido las versiones anteriores de wasm, pero los archivos asm.js
originales permanecen en formato  bin/ . Los nuevos tenían que colocarse en
un directorio separado para evitar conflictos de nombres.
 Utilice  emscripten-asmjs/ y en  emscripten-wasm32/ lugar de
los directorios  bin/ y  wasm/ si desea estar seguro de si está descargando un
binario wasm o asm.js.
 Utilice en  list.json lugar de  list.js y  list.txt . El formato de lista JSON
contiene toda la información de los antiguos y más.
 Utilice https://binaries.soliditylang.org en lugar de https://solc-
bin.ethereum.org . Para simplificar las cosas, movimos casi todo lo relacionado
con el compilador al nuevo  soliditylang.org  dominio y esto también se
aplica  solc-bin . Si bien se recomienda el nuevo dominio, el antiguo aún es
totalmente compatible y se garantiza que apunte a la misma ubicación.
Advertencia

Los binarios también están disponibles en https://ethereum.github.io/solc-bin/ pero


esta página dejó de actualizarse justo después del lanzamiento de la versión 0.7.2,
no recibirá nuevas versiones ni compilaciones nocturnas para ninguna plataforma
y no no sirven a la nueva estructura de directorios, incluidas las compilaciones que
no son de emscripten.
Si lo está utilizando, cambie a https://binaries.soliditylang.org , que es un
reemplazo directo. Esto nos permite realizar cambios en el alojamiento subyacente
de forma transparente y minimizar las interrupciones. A diferencia
del  ethereum.github.io dominio, sobre el que no tenemos ningún
control,  binaries.soliditylang.org se garantiza que funcionará y mantendrá la misma
estructura de URL a largo plazo.

Construyendo desde la fuente


Requisitos previos: todos los sistemas operativos

Las siguientes son dependencias para todas las compilaciones de Solidity:

Software Notas

CMake (versión 3.13+) Generador de archivos de compilación


multiplataforma.

Boost (versión 1.77+ en Windows, 1.65+ Bibliotecas C ++.


en caso contrario)

Git Herramienta de línea de comandos para


recuperar código fuente.

z3 (versión 4.8+, opcional) Para usar con el verificador SMT.

cvc4 (opcional) Para usar con el verificador SMT.


Nota

Las versiones de Solidity anteriores a 0.5.10 pueden fallar al vincularse


correctamente con las versiones de Boost 1.70+. Una posible solución es cambiar
el nombre temporalmente antes de ejecutar el comando cmake para configurar la
solidez. <Boost install path>/lib/cmake/Boost-1.70.0

A partir de 0.5.10, la vinculación con Boost 1.70+ debería funcionar sin


intervención manual.
Nota

La configuración de compilación predeterminada requiere una versión Z3


específica (la última en el momento en que se actualizó el código por última
vez). Los cambios introducidos entre las versiones de Z3 a menudo dan como
resultado resultados ligeramente diferentes (pero aún válidos) que se
devuelven. Nuestras pruebas SMT no tienen en cuenta estas diferencias y
probablemente fallarán con una versión diferente a la que fueron escritas. Esto no
significa que una compilación con una versión diferente sea defectuosa. Si pasa
la  -DSTRICT_Z3_VERSION=OFF opción a CMake, puede compilar con cualquier versión
que cumpla con los requisitos indicados en la tabla anterior. Sin embargo, si hace
esto, recuerde pasar la  --no-smt opción  scripts/tests.sh  para omitir las pruebas
SMT.
Versiones mínimas del compilador

Los siguientes compiladores de C ++ y sus versiones mínimas pueden construir el


código base de Solidity:

 GCC , versión 8+
 Clang , versión 7+
 MSVC , versión 2019+
Requisitos previos: macOS

Para compilaciones de macOS, asegúrese de tener instalada la última versión


de Xcode . Este contiene el compilador Clang C ++ , el IDE de Xcode y otras
herramientas de desarrollo de Apple que se requieren para construir aplicaciones
C ++ en OS X. Si está instalando Xcode por primera vez, o acaba de instalar una
nueva versión, deberá aceptar la licencia antes de poder hacer compilaciones de
línea de comandos:

sudo xcodebuild -license accept

Nuestro script de compilación de OS X utiliza el administrador de


paquetes Homebrew para instalar dependencias externas. Aquí le mostramos
cómo desinstalar Homebrew , si alguna vez desea comenzar de nuevo desde
cero.

Requisitos previos: Windows

Debe instalar las siguientes dependencias para las compilaciones de Windows de


Solidity:
Software Notas

Herramientas de compilación de Visual Studio Compilador de C ++


2019

Visual Studio 2019 (opcional) Entorno de desarrollo y compilador de C


++.

Boost (versión 1.77+) Bibliotecas C ++.

Si ya tiene un IDE y solo necesita el compilador y las bibliotecas, puede instalar


Visual Studio 2019 Build Tools.

Visual Studio 2019 proporciona tanto IDE como el compilador y las bibliotecas
necesarios. Entonces, si no tiene un IDE y prefiere desarrollar Solidity, Visual
Studio 2019 puede ser una opción para que pueda configurar todo fácilmente.

Aquí está la lista de componentes que deben instalarse en Visual Studio 2019
Build Tools o Visual Studio 2019:

 Características principales de Visual Studio C ++


 Conjunto de herramientas VC ++ 2019 v141 (x86, x64)
 SDK de Windows Universal CRT
 SDK de Windows 8.1
 Soporte C ++ / CLI
Tenemos un script de ayuda que puede utilizar para instalar todas las
dependencias externas necesarias:

scripts\install_deps.ps1

Esto se instalará  boost y  cmake en el  deps subdirectorio.

Clonar el repositorio

Para clonar el código fuente, ejecute el siguiente comando:

git clone --recursive https://github.com/ethereum/solidity.git


cd solidity

Si desea ayudar a desarrollar Solidity, debe bifurcar Solidity y agregar su


bifurcación personal como segundo control remoto:
git remote add personal git@github.com:[username]/solidity.git

Nota

Este método dará como resultado una versión preliminar que conducirá, por
ejemplo, a que se establezca una bandera en cada código de bytes producido por
dicho compilador. Si desea volver a compilar un compilador de Solidity publicado,
utilice el tarball de origen en la página de lanzamiento de github:

https://github.com/ethereum/solidity/releases/download/v0.XY/solidity_0.XYtar.gz

(no el "código fuente" proporcionado por github).

Compilación de la línea de comandos

Asegúrese de instalar dependencias externas (ver arriba) antes de compilar.

El proyecto Solidity usa CMake para configurar la compilación. Es posible que


desee instalar ccache para acelerar las compilaciones repetidas. CMake lo
recogerá automáticamente. La construcción de Solidity es bastante similar en
Linux, macOS y otros Unices:

mkdir build
cd build
cmake .. && make

o incluso más fácil en Linux y macOS, puede ejecutar:

#note: this will install binaries solc and soltest at usr/local/bin


./scripts/build.sh

Advertencia

Las compilaciones de BSD deberían funcionar, pero el equipo de Solidity no las ha


probado.

Y para Windows:

mkdir build
cd build
cmake -G "Visual Studio 16 2019" ..

En caso de que desee utilizar la versión de boost instalada por  scripts\


install_deps.ps1 , también deberá pasar  -DBoost_DIR="deps\boost\lib\cmake\Boost-
*" y  -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded  como argumentos a la llamada
a  cmake .

Esto debería resultar en la creación de solidity.sln en ese directorio de


compilación. Hacer doble clic en ese archivo debería hacer que Visual Studio se
encienda. Sugerimos crear la configuración de la versión , pero todas las demás
funcionan.

Alternativamente, puede compilar para Windows en la línea de comandos, así:

cmake --build . --config Release

Opciones de CMake
Si está interesado en las opciones de CMake disponibles, ejecute . cmake .. -LH

Solucionadores SMT

Solidity se puede construir contra solucionadores SMT y lo hará de forma


predeterminada si se encuentran en el sistema. Cada solucionador puede
desactivarse mediante una opción de cmake .

Nota: En algunos casos, esto también puede ser una posible solución para los
errores de compilación.

Dentro de la carpeta de compilación puede deshabilitarlos, ya que están


habilitados de forma predeterminada:

# disables only Z3 SMT Solver.


cmake .. -DUSE_Z3=OFF

# disables only CVC4 SMT Solver.


cmake .. -DUSE_CVC4=OFF

# disables both Z3 and CVC4


cmake .. -DUSE_CVC4=OFF -DUSE_Z3=OFF

La cadena de versión en detalle

La cadena de la versión Solidity contiene cuatro partes:


 el número de versión
 etiqueta de prelanzamiento, generalmente establecida
en  develop.YYYY.MM.DD o nightly.YYYY.MM.DD
 cometer en el formato de  commit.GITHASH
 plataforma, que tiene un número arbitrario de elementos, que contiene detalles
sobre la plataforma y el compilador
Si hay modificaciones locales, la confirmación se corregirá con  .mod .

Estas partes se combinan como lo requiere Semver, donde la etiqueta de


prelanzamiento de Solidity es igual a la prelanzamiento de Semver y el
compromiso de Solidity y la plataforma combinados conforman los metadatos de
compilación de Semver.

Un ejemplo de salida:  0.4.8+commit.60cc1668.Emscripten.clang .

Un ejemplo de prelanzamiento:  0.4.9-


nightly.2017.1.17+commit.6ecb4aa3.Emscripten.clang

Información importante sobre el control de


versiones

Después de que se realiza un lanzamiento, el nivel de la versión del parche se


modifica, porque asumimos que solo siguen los cambios en el nivel del
parche. Cuando se combinan los cambios, la versión debe modificarse de acuerdo
con semver y la gravedad del cambio. Por último, siempre se realiza un
lanzamiento con la versión de la compilación nocturna actual, pero sin
el  prerelease especificador.

Ejemplo:

1. Se realiza la versión 0.4.0.


2. La compilación nocturna tiene una versión 0.4.1 a partir de ahora.
3. Se introducen cambios irreversibles -> sin cambios en la versión.
4. Se introduce un cambio importante -> la versión se cambia a 0.5.0.
5. Se realiza la versión 0.5.0.
Este comportamiento funciona bien con la versión pragma .

También podría gustarte