Ethereum — Introducción a contratos inteligentes — Parte ll

Hola amigos, continuamos con esta serie de tutoriales en español de la documentación del lenguaje de programación Solidity. Pueden ver la primera parte aquí.

Ejemplo de Sub-moneda

El siguiente contrato implementará la forma más simple de una criptoconversión. Es posible generar monedas fuera del aire, pero sólo la persona que creó el contrato será capaz de hacer eso (es trivial implementar un esquema de emisión diferente). Además, cualquier persona puede enviar monedas entre sí sin necesidad de registrarse con nombre de usuario y contraseña.

pragma solidity ^0.4.11;

contract Coin {
// The keyword "public" makes those variables
// readable from outside.
address public minter;
mapping (address => uint) public balances;

// Events allow light clients to react on
// changes efficiently.
event Sent(address from, address to, uint amount);

// This is the constructor whose code is
// run only when the contract is created.
function Coin() {
minter = msg.sender;
}

function mint(address receiver, uint amount) {
if (msg.sender != minter) return;
balances[receiver] += amount;
}

function send(address receiver, uint amount) {
if (balances[msg.sender] < amount) return;
balances[msg.sender] -= amount;
balances[receiver] += amount;
Sent(msg.sender, receiver, amount);
}
}

Este contrato introduce algunos nuevos conceptos, vamos a pasar por ellos uno por uno.

La línea de dirección address public minter; Declara una variable de estado de tipo dirección que es accesible al público. El tipo de dirección es un valor de 160 bits que no permite operaciones aritméticas. Es adecuado para almacenar direcciones de contratos o de llaves pertenecientes a personas externas. La palabra clave public genera automáticamente una función que le permite acceder al valor actual de la variable de estado. Sin esta palabra clave, otros contratos no tienen forma de acceder a la variable. La función se verá así:

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

Por supuesto, la adición de una función exactamente como esa no funcionará porque tendríamos una función y una variable de estado con el mismo nombre, pero esperamos que se obtenga la idea, el compilador lo interpretará por.

La siguiente línea, mapping (dirección => uint) public balances; También crea una variable de estado público, pero es un tipo de datos más complejo. El tipo asigna direcciones a enteros sin signo. Las asignaciones se pueden ver como tablas de hash que son prácticamente inicializadas de tal manera que cada clave posible existe y se asigna a un valor cuya representación de bytes es todos ceros. Esta analogía no va demasiado lejos, sin embargo, ya que no es posible obtener una lista de todas las claves de un mapeo, ni una lista de todos los valores. Por lo tanto, tenga en cuenta (o mejor, guarde una lista o utilice un tipo de datos más avanzado) lo que agregó a la asignación o utilícelo en un contexto en el que no se necesite, como éste. La función getter creada por la palabra clave pública es un poco más compleja en este caso. Se parece aproximadamente a lo siguiente:

function balances(address _account) returns (uint) {
return balances[_account];
}

Como puede ver, puede utilizar esta función para consultar fácilmente el saldo de una sola cuenta.

La línea event Sent(address from, address to, uint amount); Declara un llamado “evento” que se dispara en la última línea de la función enviar. Interfaces de usuario (así como aplicaciones de servidor, por supuesto) pueden escuchar los eventos que se dispararon en la cadena de bloque sin mucho costo. Tan pronto como se dispara, el oyente también recibirá los argumentos de, hasta y cantidad, lo que hace que sea fácil de realizar un seguimiento de las transacciones. Para escuchar este evento, usted usaría:

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));
}
})

Observe cómo se llama a la función balances automáticamente desde la interfaz de usuario.

La función especial Coin es el constructor que se ejecuta durante la creación del contrato y no puede ser llamado después. 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 algunas propiedades que permiten el acceso a la cadena de bloqueo. Msg.sender es siempre la dirección de donde proviene la llamada de la función (externa) actual.

Por último, las funciones que en realidad terminan con el contrato y pueden ser llamadas por usuarios y contratos por igual son de mint y send. Si la mint es llamada por cualquier persona excepto la cuenta que creó el contrato, nada sucederá. Por otro lado, send puede ser utilizado por cualquier persona (que ya tiene algunas de estas monedas) para enviar monedas a otra persona. Tenga en cuenta que si utiliza este contrato para enviar monedas a una dirección, no verá nada cuando mire esa dirección en un explorador de bloques, porque el hecho de que haya enviado monedas y los saldos modificados sólo se almacenan en el almacenamiento de datos de este Contrato de monedas en particular. Mediante el uso de eventos es relativamente fácil crear un "explorador de bloque de bloques" que realiza un seguimiento de transacciones y saldos de su nueva moneda.

Bueno eso es todo en este post, en el siguiente hablaremos de los principios básicos de la tecnología Blockchain.

Si este post te ayudo de alguna forma no olvides seguirme en mi cuenta de Twitter @luis_acervantes

También puedes invitarme un café con tus donaciones:

Ethereum donacioness: 0x53eaCf773b0cF360ABA080EB8FF4D7B79Da62c4F

Bitcoin: 35jPWkqe3dRhTJceKHpK4eFCsZ3GVwji4m