
La mayoría de las veces, cuando la gente empieza a aprender a escribir contratos inteligentes, lo primero que oyen es Solidity y Ethereum. Yo también lo oí primero. Es en lo que se centran la mayoría de los tutoriales, y con razón. Solidity hizo posible escribir programas que residen en una cadena de bloques, y Ethereum se convirtió en el punto de partida de mucha gente.
Pero Solidity no es el único lenguaje de contratos inteligentes disponible. Y Ethereum no es la única blockchain que admite aplicaciones descentralizadas.
También existe TON , abreviatura de The Open Network . Fue creada por Telegram, pero ahora es una cadena pública impulsada por la comunidad. Es rápida, ligera y gestiona las cosas de forma ligeramente diferente a lo que podrías estar acostumbrado en Ethereum. Esto incluye la forma en que se escriben los contratos inteligentes. Cuando empecé a explorar la documentación de TON, encontré cuatro lenguajes diferentes para escribir contratos inteligentes: Tact, Tolk, FunC y Fift . No los analizaré en profundidad aquí.
Esta guía se centra en el lenguaje Tact y veremos cómo usarlo para crear un contrato de votación básico que permita a los usuarios emitir votos y verificar los resultados en la cadena.
El ecosistema TON admite varios lenguajes, cada uno con diferentes casos de uso, niveles de abstracción y experiencia de desarrollo. A continuación, se presenta una breve descripción de cada uno:
Tact proporciona una ruta más rápida para crear e implementar contratos en la cadena de bloques TON.
Antes de empezar a escribir código, es importante comprender cómo se estructuran los contratos inteligentes de Tact. Un contrato típico de Tact incluye algunos componentes principales:
bloque contract
: aquí es donde define el nombre de su contrato y declara cualquier variable de estado.
Bloque init
: Inicializa las variables de estado del contrato y establece sus condiciones iniciales. Este bloque se ejecuta una vez al momento de la implementación.
Bloques receive
: son como detectores de eventos. Gestionan los mensajes entrantes y definen cómo reacciona el contrato a ellos.
Funciones getter ( get fun
): son funciones opcionales de solo lectura que permiten a los usuarios u otros contratos consultar el estado del contrato sin cambiarlo.
Tact utiliza la comunicación basada en mensajes, que es como funcionan todas las interacciones en TON. Cada contrato recibe un mensaje y lo procesa en su propio bloque receive
. Esta estructura basada en mensajes ayuda a organizar la lógica de sus contratos de forma modular y fácil de mantener.
Apliquemos ahora esto en un ejemplo real construyendo un contrato de votación simple.
En esta sección, explicaremos cómo implementar un sistema de votación básico con Tact. Este contrato de votación permite a los usuarios votar por candidatos predefinidos y registra el número total de votos que recibe cada candidato.
Haremos todo dentro de TON Web IDE, que es una herramienta en el navegador donde puedes escribir, crear y probar tus contratos sin instalar nada localmente.
VotingContract
.
Después de crear el proyecto, abra el archivo main.tact
. Verá una configuración estándar:
// Import the Deployable trait so the contract can be deployed easily import "@stdlib/deploy"; contract BlankContract with Deployable { init() { } }
import "@stdlib/deploy";
para que la implementación funcione y no debe eliminarse del código.BlankContract
es el nombre del marcador de posición.init()
se ejecuta solo una vez cuando se implementa el contrato y se utiliza para inicializar variables de estado.
Ahora, vamos a mapear nuestro propio código.
Primero, definiremos la estructura del mensaje para la votación:
// Import the Deployable trait so the contract can be deployed easily import "@stdlib/deploy"; // Define a message structure for voting message Vote { candidate: Int as uint32; // 1 = Alice, 2 = Bob }
Este es el mensaje de votación. Cuando alguien quiera votar, enviará un mensaje al contrato con un número:
Tact utiliza esta estructura para procesar el voto entrante y decidir qué candidato obtiene el punto.
A continuación, configuraremos nuestro contrato y agregaremos dos variables de estado para realizar un seguimiento de los votos de cada candidato:
... contract VotingContract with Deployable { // State variables to track votes votesAlice: Int as uint32; votesBob: Int as uint32;
Dentro del contrato definimos dos variables:
votesAlice
: almacena el número de votos que recibe Alice.votesBob
: almacena la cantidad de votos que recibe Bob.
Ahora inicializaremos esos recuentos de votos a cero dentro del bloque init
para establecer el estado inicial del contrato cuando se implementa por primera vez.
init() { self.votesAlice = 0; self.votesBob = 0; }
El bloque init
se ejecuta solo una vez , justo cuando se implementa el contrato y establece ambos recuentos de votos en cero.
Ahora viene la lógica. Cuando se envía un voto, queremos que el contrato verifique a quién va dirigido y aumente el recuento de votos correctos.
// Handle vote messages receive(msg: Vote) { if (msg.candidate == 1) { self.votesAlice += 1; } else if (msg.candidate == 2) { self.votesBob += 1; } }
Entonces, cuando se recibe un voto:
msg.candidate
es 1, sumamos +1 a votesAlice
msg.candidate
es 2, sumamos +1 a votesBob
Por último, crearemos funciones getter para permitir que cualquiera pueda consultar el recuento de votos de cada candidato sin cambiar el estado del contrato.
// Getter for Alice's votes get fun getVotesForAlice(): Int { return self.votesAlice; } // Getter for Bob's votes get fun getVotesForBob(): Int { return self.votesBob; } }
Estas dos funciones getter nos permiten comprobar el número de votos que ha recibido cada candidato sin modificar el contrato. Es una operación de solo lectura.
A continuación se muestra el código completo del contrato de votación:
import "@stdlib/deploy"; // Define a message structure for voting message Vote { candidate: Int as uint32; // 1 = Alice, 2 = Bob } contract VotingContract with Deployable { // State variables to track votes votesAlice: Int as uint32; votesBob: Int as uint32; init() { self.votesAlice = 0; self.votesBob = 0; } // Handle vote messages receive(msg: Vote) { if (msg.candidate == 1) { self.votesAlice += 1; } else if (msg.candidate == 2) { self.votesBob += 1; } } // Getter for Alice's votes get fun getVotesForAlice(): Int { return self.votesAlice; } // Getter for Bob's votes get fun getVotesForBob(): Int { return self.votesBob; } }
Una vez implementado, desplácese hacia abajo y verá dos secciones:
getVotesForAlice
, getVotesForBob
Vote
Para votar: En la sección "Votar" , introduce 1
en el campo de entrada candidate
y haz clic en " Enviar". ¡Acabas de votar por Alice! Puedes repetir el proceso para emitir más votos.
Para comprobar el recuento de votos : haga clic en Llamar en getVotesForAlice
y verifique el panel de registros para ver el recuento de votos
2
en el campo candidate
, luego marca getVotesForBob
En mi prueba, voté por Alice 9 veces y por Bob 6 veces , y las funciones getter mostraron exactamente eso.
¡Felicitaciones si leíste todo el libro!
Ahora que has visto cómo funciona un contrato de votación simple en Tact, has dado el primer paso en el desarrollo de contratos inteligentes en TON. Este contrato puede ser básico, pero su estructura y conceptos también se aplican a lógicas más complejas.
Si quieres seguir experimentando, intenta ampliar este contrato o explorar otras plantillas prediseñadas en https://tact-by-example.org/all . El IDE web de TON también facilita la prueba de diferentes casos de uso e incluye plantillas para ayudarte a desarrollar y aprender más rápido.
Así que adelante, modifique, pruebe y construya algo mejor.