Ir al contenido principal
Change page

Lenguajes de contrato inteligente

Última edición: @danielpg2106(opens in a new tab), 1 de abril de 2024

Un gran aspecto de Ethereum es que los contratos inteligentes pueden programarse utilizando lenguajes relativamente fáciles para el programador. Si tiene experiencia con Python u otro lenguaje entre llaves(opens in a new tab), puede buscar un lenguaje con una sintaxis familiar.

Los dos lenguajes más activos y soportados son:

  • Solidity
  • Vyper

Los desarrolladores más experimentados también podrían querer usar Yul, un lenguaje intermedio para la máquina virtual Ethereum, o Yul+, una extensión de Yul.

Si es curioso y le gustaría ayudar a testear nuevos lenguajes que aún se encuentran bajo gran desarrollo, puede experimentar con Fe, un lenguaje emergente de contratos inteligentes que aún está en sus inicios.

Requisitos previos

El conocimiento previo de lenguajes de programación, especialmente de JavaScript o Python, puede ayudarlo a entender las diferencias en los lenguajes de los contratos inteligentes. También recomendamos que entienda los lenguajes de los contratos inteligentes como concepto antes de profundizar en las comparaciones de lenguajes. Consulte esta Introducción a los contratos inteligentes.

Solidity

  • Lenguaje orientado a objeto de alto nivel para implementar contratos inteligentes.
  • Lenguaje de llaves más influenciado por C++.
  • Escrito estáticamente (el tipo de una variable se conoce en el momento de compilación).
  • Admite:
    • Herencia (puede extende otros contratos).
    • Bibliotecas (puede crear código reutilizable que puede invocar de diferentes contratos, como funciones estáticas en una clase estática en otros lenguajes de programación orientados a objetos).
    • Tipos complejos definidos por el usuario.

Ejemplo de contrato

1// SPDX-License-Identifier: GPL-3.0
2pragma solidity >= 0.7.0;
3
4contract Coin {
5 // The keyword "public" makes variables
6 // accessible from other contracts
7 address public minter;
8 mapping (address => uint) public balances;
9
10 // Events allow clients to react to specific
11 // contract changes you declare
12 event Sent(address from, address to, uint amount);
13
14 // Constructor code is only run when the contract
15 // is created
16 constructor() {
17 minter = msg.sender;
18 }
19
20 // Sends an amount of newly created coins to an address
21 // Can only be called by the contract creator
22 function mint(address receiver, uint amount) public {
23 require(msg.sender == minter);
24 require(amount < 1e60);
25 balances[receiver] += amount;
26 }
27
28 // Sends an amount of existing coins
29 // from any caller to an address
30 function send(address receiver, uint amount) public {
31 require(amount <= balances[msg.sender], "Insufficient balance.");
32 balances[msg.sender] -= amount;
33 balances[receiver] += amount;
34 emit Sent(msg.sender, receiver, amount);
35 }
36}
Mostrar todo
Copiar

Este ejemplo debería darle una idea de cómo es la sintaxis de un contrato Solidity. Para ver una descripción más detallada de las funciones y variables, consulte los documentos(opens in a new tab).

Vyper

  • Lenguaje de programación Pythonic
  • Escritura fuerte
  • Código de compilador pequeño y comprensible
  • Generación eficiente de bytecode
  • Deliberadamente tiene menos funciones que Solidity con el objetivo de hacer que los contratos sean más seguros y más fáciles de auditar. Vyper no admite:
    • Modificadores
    • Herencia
    • Ensamblado en línea
    • Sobrecarga de funciones
    • Sobrecarga de operadores
    • Llamadas recurrentes
    • Bucles de longitud infinita
    • Puntos fijos binarios

Para obtener más información, lea los fundamentos de Vyper(opens in a new tab).

Ejemplo

1# Open Auction
2
3# Auction params
4# Beneficiary receives money from the highest bidder
5beneficiary: public(address)
6auctionStart: public(uint256)
7auctionEnd: public(uint256)
8
9# Current state of auction
10highestBidder: public(address)
11highestBid: public(uint256)
12
13# Set to true at the end, disallows any change
14ended: public(bool)
15
16# Keep track of refunded bids so we can follow the withdraw pattern
17pendingReturns: public(HashMap[address, uint256])
18
19# Create a simple auction with `_bidding_time`
20# seconds bidding time on behalf of the
21# beneficiary address `_beneficiary`.
22@external
23def __init__(_beneficiary: address, _bidding_time: uint256):
24 self.beneficiary = _beneficiary
25 self.auctionStart = block.timestamp
26 self.auctionEnd = self.auctionStart + _bidding_time
27
28# Bid on the auction with the value sent
29# together with this transaction.
30# El valor solo será reembolsado si la subasta
31# no es ganada.
32@external
33@payable
34def bid():
35 # Comprobar si el periodo de oferta ha terminado.
36 assert block.timestamp < self.auctionEnd
37 # Check if bid is high enough
38 assert msg.value > self.highestBid
39 # Track the refund for the previous high bidder
40 self.pendingReturns[self.highestBidder] += self.highestBid
41 # Track new high bid
42 self.highestBidder = msg.sender
43 self.highestBid = msg.value
44
45# Withdraw a previously refunded bid. El patrón de retirada se
46# utiliza aquí para evitar un problema de seguridad. Si los reembolsos fueron directamente
47# enviados como parte de la oferta(), un contrato de licitación malicioso podría bloquear
48# esos reembolsos y así bloquear la entrada de nuevas ofertas más altas.
49@external
50def withdraw():
51 pending_amount: uint256 = self.pendingReturns[msg.sender]
52 self.pendingReturns[msg.sender] = 0
53 send(msg.sender, pending_amount)
54
55# Finalizar la subasta y enviar la oferta más alta
56# al beneficiario.
57@externo
58def endAuction():
59 # Es una buena guía para estructurar funciones que interactúan
60 # con otros contratos (es decir, ellos llaman funciones o envían ether)
61 # en tres frases:
62 # 1. condiciones de comprobación
63 # 2. realizar acciones (condiciones potencialmente cambiantes)
64 # 3. interactuando con otros contratos
65 # Si estas fases se mezclan, el otro contrato podría llamar a
66 # de vuelta al contrato actual y modificar el estado o causar
67 # efectos (pago ether) a ser realizados varias veces.
68 # Si las funciones llamadas internamente incluyen interacción con contratos externos
69 # también deben considerarse interacción con
70 # contratos externos.
71
72 # 1. Condiciones
73 # Comprueba si se ha alcanzado el fin de la subasta
74 assert block.timestamp >= self.auctionEnd
75 # Comprueba si esta función ya ha sido llamada
76 assert not self.ended
77
78 # 2. Efectos
79 self.ended = True
80
81 # 3. Interacción
82 send(self.beneficiary, self.highestBid)
Mostrar todo
Copiar

Este ejemplo debería darle una idea de cómo es la sintaxis de contratos de Vyper. Para ver una descripción más detallada de las funciones y variables, consulte los documentos(opens in a new tab).

Yul y Yul+

Si es nuevo en Ethereum y aún no ha hecho ninguna codificación con lenguajes de contrato inteligente, le recomendamos empezar con Solidity o Vyper. Solo póngase con Yul o Yul+ una vez que esté familiarizado con las prácticas recomendadas de seguridad de los contratos inteligentes y los detalles de trabajar con la EVM.

Yul

  • Lenguaje intermedio para Ethereum.
  • Es compatible con EVM y Ewasm(opens in a new tab), un WebAssembly parecido a Ethereum, y está diseñado para ser un denominador común utilizable de ambas plataformas.
  • Buen objetivo para las etapas de optimización de alto nivel, que puede beneficiar a las plataformas de EVM y eWASM.

Yul+

  • Una extensión de bajo nivel y alta eficiencia para Yul.
  • Diseñado inicialmente para ser un contrato de rollup optimista.
  • Yul+ se puede considerar una propuesta de actualización experimental de Yul, que le añade nuevas funciones.

Ejemplo de contrato

El siguiente ejemplo sencillo implementa una power function. Puede compilarse mediante solc --strict-assembly --bin input.yul. El ejemplo debe almacenarse en el archivo input.yul.

1{
2 function power(base, exponent) -> result
3 {
4 switch exponent
5 case 0 { result := 1 }
6 case 1 { result := base }
7 default
8 {
9 result := power(mul(base, base), div(exponent, 2))
10 if mod(exponent, 2) { result := mul(base, result) }
11 }
12 }
13 let res := power(calldataload(0), calldataload(32))
14 mstore(0, res)
15 return(0, 32)
16}
Mostrar todo

Si ya tiene experiencia con contratos inteligentes, puede encontrar una implementación ERC20 completa en Yul aquí(opens in a new tab).

Fe

  • Lenguaje escrito estáticamente para la Máquina Virtual de Ethereum (EVM).
  • Inspirado en Python y Rust.
  • Pretende ser fácil de aprender, incluso para desarrolladores que son nuevos en el ecosistema de Ethereum.
  • El desarrollo de Fe se encuentra aún en sus inicios; el lenguaje tuvo su lanzamiento alpha en enero de 2021.

Ejemplo de contrato

El siguiente es un contrato simple implementado en Fe.

1type BookMsg = bytes[100]
2
3contrato GuestBook:
4 pub guest_book: map<address, BookMsg>
5
6 event Signed:
7 book_msg: BookMsg
8
9 pub def sign(book_msg: BookMsg):
10 self. uest_book[msg.sender] = book_msg
11
12 emit Signed(book_msg=book_msg)
13
14 pub def get_msg(addr: address) -> BookMsg:
15 return self. uest_book[addr].to_mem()
16
Mostrar todo

¿Cómo escoger?

Como sucede con cualquier otro lenguaje de programación, se trata principalmente de elegir la herramienta adecuada para el trabajo correcto, así como las preferencias personales.

Estas son algunas cosas que debe tener en cuenta si aún no ha probado ninguno de los lenguajes:

¿Qué tiene de genial Solidity?

  • Si es principiante, encontrará muchos tutoriales y herramientas de aprendizaje por ahí. Obtenga más información al respecto en la sección Aprender programando.
  • Buenas herramientas de desarrollador disponibles.
  • Solidity tiene una gran comunidad de desarrolladores, lo que significa que muy probablemente encontrará rápidamente las respuestas a sus preguntas.

¿Qué tiene de genial Vyper?

  • Es una fantástica forma de comenzar para aquellos desarrolladores de Python que deseen escribir contratos inteligentes.
  • Vyper dispone de una menor cantidad de funciones que lo convierten en la opción ideal para elaborar prototipos de ideas rápidamente.
  • Vyper pretende ser una herramienta fácil de auditar y ofrecer el nivel máximo de legibilidad para las personas.

¿Qué tienen de genial Yul y Yul+?

  • Lenguaje simple y funcional de bajo nivel.
  • Le permite aproximarse mucho más a la EVM sin procesar, lo que puede ayudarlo a optimizar el uso de gas en los contratos.

Comparación de lenguajes

Si desea obtener comparaciones sobre la sintaxis básica, el ciclo de vida de los contratos, las interfaces, los operadores, las estructuras de datos, las funciones, el flujo de control, etc., eche un vistazo a esta hoja de apuntes de Auditless(opens in a new tab).

Más información

¿Le ha resultado útil este artículo?