Contratos inteligentes - Parte 3 - Cómo se hace
Hola Steemians como han estado. El concurso ya ha terminado... lamentablemente no tuvo mucha acogida a pesar que el plazo fue de una semana. Seguramente el premio de 0.03 ETH no era tan tentativo como para tomarse el tiempo de participar y también es cierto que igualmente hay que pagar gas para participar, aunque sea poco!
Ya para terminar con este ciclo sobre ethereum, quiero mostrarles el código del contrato inteligente, que he tratado que sea lo más sencillo posible para explicarlo y que cualquiera pueda entenderlo aunque no tenga conocimientos de programación.
De nuevo explico la idea principal del contrato: Cualquiera puede participar y para hacerlo envía 0 ETH de forma que pueda quedar registrada su dirección. El ganador será el participante número 50, o el último que haya participado antes de una fecha límite (que definí como el 9 de septiembre).
Aquí va el código:
pragma solidity ^0.4.0;
contract countGame {
address public best_gamer;
uint public count = 0;
uint public endTime = 1504969200;
function fund() payable {
require(now <= endTime);
}
function (){
require(now<=endTime && count<50);
best_gamer = msg.sender;
count++;
}
function endGame(){
require(now>endTime || count == 50);
best_gamer.transfer(this.balance);
}
}
Lo voy a explicar paso por paso. Primero tenemos:
pragma solidity ^0.4.0;
Esta línea de código siempre debe estar en todos los contratos y hace referencia a la versión de solidity que estemos usando para que el compilador comprenda el formato en el que está escrito.
Luego viene contract countGame
que define el nombre de nuestro contrato y dentro de llaves {}
escribimos su contenido.
Ahora definimos 3 variables, que son las que nos ayudarán a almacenar la información relevante. Necesitamos una dirección address public
que llamaremos best_gamer
, y es donde almacenaremos la dirección del último participante, el que será el candidato a ganador, ya que los anteriores participantes ya no nos interesan. Luego necesitamos un número entero positivo uint public
que llamaremos count
y lo usamos para contar cuántos participantes han habido hasta el momento. Por último necesitamos un número entero uint public
que llamaremos endTime
que define la fecha límite del juego. Así tenemos:
address public best_gamer;
uint public count = 0;
uint public endTime = 1504969200;
Es importante notar que las fechas se definen en tiempo unix, el cual es un contador de segundos para facilitar los cálculos por computador. Para calcular cualquier fecha podemos usar esta herramienta, de donde obtuve que el 9 de septiembre a las 3pm GMT correspondía al segundo 1504969200.
Después de aquí definimos 3 funciones que nos permitirán definir por completo el juego. Vamos con la primera, llamada fund
function fund() payable {
require(now <= endTime);
}
Cada vez que se llama a esta función lo que queremos es que el contrato reciba dinero, es la forma de recibir fondos. Por esto es necesario que tenga la palabra payable
. Dentro de él nada más tenemos que decir solo se recibe el dinero si aun el concurso está en curso, es decir, si now
(momento actual), es menor que endTime
, la fecha que definimos como límite. Si esto no se cumple el dinero nunca es transferido. Esta fue la función que yo usé para enviar 0.03 ETH al contrato.
La segunda función no tiene ningún nombre y la definimos así:
function (){
require(now<=endTime && count<50);
best_gamer = msg.sender;
count++;
}
Esta es la función con la que interactúan los participantes. Cada vez que alguien interactúa con un contrato debe escoger la función con la que quiere interactuar, sin embargo, si no se define ninguna función o su nombre no coincide con ninguna de la lista entonces se ejecuta la función sin nombre. Como los participantes normalmente tienen billeteras que no soportan interacción con contratos inteligentes, lo mejor es definirla aquí y que se ejecute simplemente con enviar 0 ETH al contrato.
¿Qué contiene esta función? primero nos aseguramos que no haya pasado el tiempo limite now<=endTime
, y que el contador de participantes sea menor a 50. La forma de concatenar estos dos condicionales se hace con &&
, que significa "AND" (en español "y").
require(now<=endTime && count<50);
Luego se saber que esto se cumple pasamos a modificar nuestras variables: El candidato a ganador será la dirección de quien está participando, que en ethereum se define como msg.sender
, y quiere decir "del mensaje msg
tome la dirección de quien envía (sender
)". Y por último aumentamos el contador en 1, que para esto usamos ++
.
best_gamer = msg.sender;
count++;
De esta forma, cada vez que alguien participa, se almacena su dirección y el contador aumenta. Vamos con la última función.
function endGame(){
require(now>endTime || count == 50);
best_gamer.transfer(this.balance);
}
Esta función llamada endGame
la usamos para entregarle el premio al ganador. Primero nos aseguramos que el juego haya terminado, esto sucede cuando el tiempo límite ya ha pasado now>endTime
, o cuando el contador ha llegado a 50, count == 50
, la forma de unir estas condiciones se hace con ||
, que significa "OR" (en español "o").
require(now>endTime || count == 50);
y por último si esto se ha cumplido, transferimos la cantidad total de dinero que tiene el contrato (this.balance
) al último participante (best_gamer
).
best_gamer.transfer(this.balance);
Con esto hemos terminado de definir nuestro contrato inteligente.
¿Cómo compilarlo y publicarlo?
Para compilar el contrato podemos entrar en https://remix.ethereum.org/, una herramienta en línea que es muy útil para contratos sencillos, no es necesario instalar nada. Allí podemos compilar y al mismo tiempo hacer pruebas para ver que funcione correctamente.
Una vez lo tenemos listo y compilado, el sistema nos arrojará una serie de datos e información, de allí debemos tomar el contenido de BYTECODE, que es el que nos servirá para publicar.
Para publicar el contrato existen igualmente varias herramientas, la más sencilla a mi modo de ver es https://www.myetherwallet.com/. Allí vamos a Contracts y luego Deploy Contract. Escribimos allí el ByteCode, pagamos el gas por publicar, que en mi caso fue de $2.
Me sorprende que nadie participara en el concurso, supongo que el anuncio no tuvo suficiente repercusión.
Cuando lo vi, pensé: seguro que alguien programa un script para ganar, generando la transacción en cuanto llegase la número 49 o justo antes de que se acabara el tiempo.
Entonces, ¿el ETH depositado se ha perdido?
Sí. Una lástima. Yo participé para que el dinero no se perdiera, lo cogí de vuelta.
Para nosotros los minnows es muy difícil generar una buena difusión lamentablemente. Lo unico es perseverar y continuar publicando.
Gracias por comentar. Un saludo
Congratulations @jga! You have completed some achievement on Steemit and have been rewarded with new badge(s) :
Award for the number of comments
Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here
If you no longer want to receive notifications, reply to this comment with the word
STOP