
Hola a todos! En este artículo, le diré cómo lanzar un contrato inteligente de recolección de dinero para su ICO en Ethereum en 5 minutos y varios comandos en la terminal. Este ensayo potencialmente le ahorrará decenas de miles de dólares estadounidenses, ya que cualquier programador, y no un programador también, podrá lanzar un contrato inteligente auditado y seguro (en lugar de pagar $ 15,000 - $ 75,000 para el desarrollo). En resumen, puede enviar dinero a este contrato inteligente y recibir tokens ERC20 por él. Se puede decir que este artículo es una recopilación de toda la experiencia que obtuve al lanzar un ICO para mi proyecto.
En Internet, estos suyos ya están llenos de artículos sobre contratos inteligentes, pero tan pronto como comienza a escribir uno, se da cuenta de que la información se repite en todas partes, y simplemente no hay tutoriales sobre cómo engañar a su ERC20, o ya están desactualizados. Por cierto, para que este artículo siga siendo relevante, intentaré indicar los lugares potenciales donde puede quedar obsoleto (y cómo solucionarlo). Vamos!
Solidez
Este es el nombre del idioma principal que el equipo de kéfir desarrolló para lanzar contratos inteligentes. Si usted es un programador, simplemente revise la
documentación del lenguaje , es indecentemente simple. Por cierto, lo hicieron simple para que fuera más difícil cometer un error al escribir un contrato inteligente. Así que
absolutamente cualquier programador, al menos en el nivel junior, podrá resolverlo.
No tiene absolutamente ningún sentido pagar grandes cantidades de dinero a los desarrolladores que conocen la solidez: será un orden de magnitud más barato capacitar a un desarrollador existente.
Contratos inteligentes
... y todo lo que necesitas saber sobre ellos. Omita esta sección si no es un programador. Un contrato inteligente es una pieza de código. En principio, esta es una clase de solidez (OOP, sí), que tiene dos tipos de funciones: cambia de estado y no cambia de estado. Bueno, para ejecutar funciones en un contrato inteligente simplemente enviándole kéfir, debe marcar esta función como
payable
.
State es un almacén de datos, blockchain, EPT. Los contratos pueden cambiar la cadena de bloques (estado, almacenamiento), pero para cambiar la cadena de bloques debe pagar el kéfir a los mineros. La forma en que compartirán el kéfir no se analizará en el marco de este artículo. El pago a los mineros por ejecutar código de cambio de estado se llama Gas. Si alguien de afuera arroja kéfir a la dirección de un contrato inteligente con una llamada a una función marcada como
payable
pero no marcada como
Constant
,
View
o
Pure
, entonces la cantidad requerida de kéfir para el pago a los mineros se deducirá de la cantidad enviada. Por lo general, en los tokens ERC20, estas son funciones que entregan el remitente del token para kéfir o transfieren tokens de un titular de tokens a otro.
Y si marca una función en el contrato con las palabras
Constant
o
View
(significan lo mismo, solo le permiten leer el estado) o
Pure
(lo mismo, ni siquiera lee el estado), ¡ni siquiera tendrá que gastar kéfir en la ejecución de esta función! Incluso diré más que estas funciones no necesitan ser llamadas por transacciones, después de todo, cualquier cliente de yogurt puede ejecutarlas teóricamente en casa, y ya nadie necesita saber sobre esto (después de todo, nada está escrito en la cadena de bloques).
Y hay dos cosas importantes en la solidez: herencia múltiple y modificadores de función. También necesitas saber sobre ellos.
El primero: los contratos justos se pueden heredar simultáneamente de varias clases, como
TimedCrowdsale
,
CappedCrowdsale
,
MintedCrowdsale
,
Ownable
, mientras que las funciones de los constructores también se lanzan una tras otra, pero lo explicaré más adelante como ejemplo.
El segundo es la capacidad de crear funciones que luego se insertarán en otras funciones. Es como una simple encapsulación, solo un poco más flexible: es literalmente
una plantilla de función. Cuando crea un modificador, escribe el carácter especial
_
donde se refiere al código de una función que usa este modificador. Es decir, los modificadores no son solo funcionalidades encapsuladas que devuelven un valor; Esta es una plantilla de función cuando el código de un modificador se inserta literalmente en una función utilizando este modificador.
Pasemos a practicar.
Ambiente de cocina
Si no sabe qué es Terminal, lea
este artículo aquí . Si está en Windows, configure una Terminal a través de WLS. Si ya está familiarizado con la Terminal, continuemos. Además,
póngase inmediatamente Node.js: será necesario para los próximos pasos. Es mejor instalar LTS, pero, de hecho, no importa cuál de las versiones modernas del nodo instalar.
Lo primero que instalamos e iniciamos inmediatamente el proceso de sincronización de bloques es
geth
. En resumen, esta es una utilidad escrita en Go que nos permitirá ejecutar el nodo ether en la computadora local y conectarnos a las redes de prueba y reales. Puede realizar la instalación a
través de instaladores , pero le recomiendo que se
geth
inmediatamente en la Terminal, como se describe
aquí . Puede verificar si sus estándares
geth
están
geth
ejecutando el comando en la Terminal:
geth version
Si te escupió la versión geth: todo está calado, continúa el tutorial. Si no, mal, correcto; parece que tendrá que hacer el amor con la Terminal y su sistema operativo, pero esta no es la primera vez que se da cuenta. Cómo instalar geth, ejecuta el comando en la Terminal:
geth --testnet console
Esto iniciará el proceso de sincronización de su nodo con el servidor de prueba, cuyos bloques se pueden ver
aquí . Puede verificar si sincronizó con la red en la consola
geth
:
eth.blockNumber
El proceso de sincronización me llevó de 1 a 4 horas, ¿cuándo? Además, además de la sincronización de bloques, también tendrá que esperar la sincronización de estado, que a menudo es más larga que la sincronización de bloques. También puede usar los
geth
con el indicador
--light
- luego la sincronización dura de unos segundos a un minuto y aún puede implementar contratos.
Bien, instalamos la primera utilidad, pon la siguiente. Necesitamos poner un análogo de
geth
, solo una simulación de blockchain muy local:
testrpc
. Sí, tenemos
3 blockchains :
testrpc
- simulación local de blockchain; rápido, pero falso y almacenado solo en su máquinageth --testnet
ya es una verdadera cadena de bloques, pero no perderá dinero donde puede obtener kéfir y probar todo geth --testnet
gratisgeth
- mainnet, main, blockchain real, kéfir real; todo de una manera adulta, los errores aquí son las pérdidas de kéfir real
En consecuencia, comenzaremos el contrato de prueba con
testrpc
, luego lo instalaremos en
geth --testnet
, y luego lo descargaremos directamente en
geth
.
Ponemos
testrpc
ejecutando el siguiente comando:
npm install -g ethereumjs-testrpc
Bueno, o se eleva inmediatamente con una trufa, ya que ahora
testrpc
bajo el ala de la trufa y se llama
ganache-cli
. Aunque el diablo lo sabe, todo funcionó
testrpc
con vainilla
testrpc
. Y si funciona, no lo toques, como me enseñaron en la academia intergaláctica. También puede ejecutarlo para verificar la instalación registrando
truffle
en la consola, pero el blockchain de prueba ya está sincronizado con nosotros, no lo molestemos.
Bueno, ¿descubriste las cadenas de bloques? ¿Ahora hay nodos y la prueba está incluso sincronizada? Ponemos una práctica utilidad para trabajar con contratos inteligentes en kéfir -
truffle
, con el siguiente comando:
npm install -g truffle truffle version
Truffle es una herramienta que le permite mantener contratos inteligentes en diferentes archivos, importar otros archivos y también compila su código de contrato inteligente en un código de bytes grande (ilegible por una persona), encuentra automáticamente su
geth
localmente ejecutable (prueba y real ) o
testrpc
, implemente su contrato inteligente en esta red. Además, verifica el código de su contrato inteligente en busca de errores y las transacciones recientemente completadas
también ayudan a depurar . Masthead, en resumen.
En esta etapa, debería haber instalado:
testrpc
,
geth
,
testrpc
; si falta algo de esto o la versión no se escupe en la consola a pedido, corríjala; de lo contrario no tendrá éxito.
Además, lancé un script bash simple que instalará todo por ti. Llamado así:
source <(curl -s https://raw.githubusercontent.com/backmeupplz/eth-installer/master/install.sh)
- pero aún no lo he probado, así que no estoy seguro de su rendimiento. Sin embargo, me complacerá recibir solicitudes.
Contrato de Figash
Todo ya ha sido inventado y escrito para ti, eso está bien. Un pequeño golpe será todo lo mismo, pero intentaré minimizarlo para ti.
Utilizaremos los contratos ERC20 listos para usar de OpenZeppelin : este es ahora el estándar de la industria, han pasado la auditoría y, de hecho, todos usan su código. Muchas gracias por tu contribución al código abierto.
Haga el
cd
en una carpeta segura y luego escriba:
mkdir contract && cd contract
En esta carpeta trabajaremos. Cree un trozo aquí para nuestro contrato inteligente:
truffle init
Tropezar, claramente. Ahora tenemos dos carpetas muy importantes en las que escalaremos:
contracts
y
migrations
. El primero es el código de nuestros contratos, el segundo es el código de trufa para saber qué hacer al implementar contratos en la cadena de bloques.
A continuación, necesitamos tomar el código de contrato inteligente actual de npm y, de hecho, comenzar el proyecto en sí:
npm init -y
Bueno, el código de contratos inteligentes de OpenZeppelin está en nuestro bolsillo en la carpeta
node_modules/openzeppelin-solidity/contracts
. Ahora vamos a la carpeta principal de
contracts
, eliminamos todos los archivos y agregamos los archivos
MyToken.sol
y
MyCrowdsale.sol
; naturalmente, nombrará sus contratos de manera diferente. El primero será un contrato para nuestro Token ERC20, y el segundo será un contrato de nuestro ICO, que aceptará kéfir y distribuirá
MyToken
personas. Este artículo puede estar desactualizado, pero siempre puede ver cómo OpenZeppelin sugiere que cree contratos
en su repositorio . Así es como se verá
MyToken.sol
:
pragma solidity ^0.4.23;
Agradable: ¡tienes un contrato inteligente de tu propio token (solo cambia los nombres en las constantes)! Puedes ver qué
MintableToken
herencia hay de
MintableToken
, pero allí todo es lo más simple posible. Este es un token que se puede emitir (del inglés "Mint" - para acuñar), y solo el propietario tiene derecho a emitirlo, ya que el
MintableToken
también se hereda de
Ownable
. Además,
MintableToken
también hereda de clases de tokens ERC20 escritos por OpenZeppelin, en los que se implementa la interfaz ERC20:
contract ERC20Basic { function totalSupply() public view returns (uint256); function balanceOf(address who) public view returns (uint256); function transfer(address to, uint256 value) public returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); }
Sí, aquí tienes toda la interfaz ERC20. ¿Es dificil? No lo creo Le da la oportunidad de ver cuántos tokens se emitieron, verificar el saldo de la dirección y transferir los tokens a otra dirección escupiendo un evento de transferencia para clientes de kéfir ligero en la red. Y todo esto lo obtienes gratis en tu
MyToken.sol
gracias al trabajo de OpenZeppelin: son geniales.
Y ahora pasemos a la parte principal de nuestra ICO: ¡debemos aceptar el kéfir y entregar
MyToken
! Así se
MyCrowdsale.sol
su
MyCrowdsale.sol
:
pragma solidity ^0.4.23;
Así que, ¿qué pasa con nosotros? ¿Qué, muchachos, contratos inteligentes? Nuestra venta pública de tokens hereda tres de las propiedades más populares: tiene un límite máximo, que ya no se puede recolectar; tapa blanda, que no recoge los ésteres que se devuelven; momento del comienzo y fin de la venta de tokens. De hecho, ¿qué más se necesita para la felicidad?
Programadores, noten cómo los constructores de múltiples clases de herencia están organizados en una fila y obtienen argumentos del constructor principal de
MyCrowdsale
. Además, comprobamos que la tecla fija es más alta que la tecla programable: ¡Ales Gut! Además, no se
MyCrowdsale
parámetros
MyCrowdsale
en el constructor
MyCrowdsale
: los pasaremos en la etapa de implementación del contrato en la trufa.
Eso es todo: tiene contratos listos para usar de su propio token ERC20 e incluso un contrato inteligente ICO, que se configura de acuerdo con su deseo y entrega sus tokens para kéfir. Además, es compatible con todas las billeteras ERC20, ¡un error! Pasemos a las pruebas manuales y la implementación.
Migraciones
Como dije antes, probaremos secuencialmente en tres redes blockchain, pero el proceso de prueba con bolígrafos siempre será el mismo. Comencemos con
testrpc
, luego pasemos a
geth --testnet
y continuemos con
geth
. Faros de Sou, acabamos de escribir el código, intentemos compilarlo. En la carpeta del proyecto, escriba:
truffle compile
Si todo se compiló sin problemas, verá la
build
, que contendrá el krakozyab para la trufa para que pueda incrustar el código de bytes de sus contratos inteligentes en la cadena de bloques. Antes de implementar contratos inteligentes, debemos decirle a la trufa qué hacer en absoluto. El despliegue de trufas de los contratos inteligentes se llama migración, bueno, sigamos con esta terminología. Vaya a
migrations/1_initial_migration.js
y cámbielo de la siguiente manera:
const token = artifacts.require("../contracts/MyToken.sol"); const crowdsale = artifacts.require("../contracts/MyCrowdsale.sol"); module.exports = function(deployer, network, accounts) { const openingTime = 1514764800;
Este es el mismo archivo que utilizará la trufa para desplegar contratos. Entonces, ¿qué estamos haciendo aquí? Primero, solicitamos
MyToken
y
MyCrowdsale
compilados. Después, establecemos las constantes con todos los argumentos de nuestro ICO: establecemos las horas de inicio y finalización; cuántas fichas recibirán las personas por 1 vey de kéfir (0.000000000000000001 eth = 1 wei; establecer
decimals
indica cuántas órdenes se necesitan para obtener 1 de sus fichas recién hechas); billetera, donde vendrá el kéfir obtenido de la venta; tapa dura y tapa blanda. Tenga en cuenta que el tiempo de
openingTime
siempre debe ser posterior al momento del bloqueo actual en la cadena de bloques; de lo contrario, su contrato inteligente no se bloqueará debido a la verificación de la condición en
TimedCrowdsale
. Pisé este rastrillo, y las transacciones fallidas no se pueden debitar en absoluto. Cambie estas constantes como desee.
El siguiente paso es precisamente el despliegue de contratos inteligentes. Nada interesante aquí: tenemos un objeto de despliegue que despliega artefactos de contratos inteligentes y pasa argumentos allí. Tenga en cuenta que MyToken se
MyToken
primero, y solo luego
MyCrowdsale
, y la dirección del primero se pasa en el segundo como argumento.
Entonces, lo más interesante es sobre lo que no escriben ni en la documentación ni en los libros. Cuando crea un
MyToken
desde una billetera, esta billetera se convierte en el propietario de
MyToken
en la superclase
Ownable
; lo mismo ocurre con
MyCrowdsale
. Si profundizas en el
MintableToken
, puedes ver que solo el
Owner
puede acuñar monedas. ¿Y quién es el dueño de
MyToken
? Así es: la dirección que lo molestó. ¿Y quién enviará solicitudes para acuñar monedas? Correcto: contrato inteligente
MyCrowdsale
. Permítame recordarle que la dirección que creó
MyToken
y
MyCrowdsale
son dos direcciones diferentes.
Por lo tanto, estamos agregando el tercer paso de implementación no ortodoxo, donde la dirección que ha desafiado los contratos (
web3.eth.accounts[0]
) llama a la función
transferOwnership
en el contrato
MyToken
que
MyCrowdsale
propietario de
MyToken
y pueda acuñar monedas. Y
MyCrowdsale
todavía está bajo la propiedad de
web3.eth.accounts[0]
, por lo que todo está incluido.
Nota sobre web3.eth.accounts[0]
: cuando implemente un contrato inteligente, asegúrese de que geth o testrpc tengan la billetera correcta en web3.eth.accounts[0]
: no pierda la clave privada, aunque esto no le hace daño, pero de repente el dueño tendrá que hacer algo más tarde, pero ¿la clave ya no está?
En testrpc
, como regla, las cuentas se crean inmediatamente al inicio y se desbloquean de inmediato; sin embargo, en una prueba y en una cadena de bloques de aire real, vale la pena crear una cuenta a través de personal.newAccount()
, luego reponga esta dirección a través de Faucet en la cadena de bloques de prueba o kéfir real en la cadena de bloques real. No pierdas tu contraseña y claves privadas.
Además, puede agregar una billetera existente a sus cuentas llamando a web3.personal.importRawKey('pvt_key', 'password')
, pero para esto necesita llamar a geth
con el parámetro adicional --rpcapi="db,eth,net,web3,personal,web3"
. Creo que lo resolverás.
Pruebas e implementación
Sí, los contratos están listos, las migraciones están escritas, solo queda desplegar y verificar. Tanto
geth
(test y real) como
testrpc
administran de la misma manera a través de la
truffle console
, por lo que describiré el método de verificación para
testrpc
y simplemente le diré cómo habilitar
geth
después. Y así, lanzamos la prueba blockchain de kéfir local:
testrpc
Um ... eso es todo. Simula la cadena de bloques de kéfir localmente.
Y para implementar en la cadena de prueba ether blockchain, en lugar de este comando, obtendrá geth --testnet --rpc
. Y para implementar en la cadena de bloques real de ether, simplemente geth --rpc
. La bandera --rpc
necesaria para que la trufa pueda conectarse. Los siguientes pasos de implementación y prueba son más o menos los mismos para los tres tipos de blockchain. Lo único es que después de ejecutar la prueba o la cadena de bloques real a través de geth
, comenzará a sincronizar los bloques, y esto puede demorar hasta 4-5 horas en una buena conexión a Internet. Una observación sobre esto fue al comienzo del artículo. Antes de implementar contratos inteligentes, recomiendo esperar la sincronización completa. Además, la cadena de bloques pesa en la región de 60-100 gigabytes, así que prepare el espacio en disco para esto.
Además, también asegúrese de que web3.eth.accounts[0]
desbloqueado. Por lo general, puede registrar testrpc
en la consola, que se abre inmediatamente, o en una ventana de Terminal separada en la consola, que se abre a través de geth console
: eth.unlockAccount(eth.accounts[0], ", ", 24*3600)
- esto desbloqueará su cuenta, lo que debería crear un contrato inteligente
Ahora abra una nueva ventana de Terminal (no
testrpc
, debería funcionar) y escríbala en la carpeta del proyecto:
truffle migrate --reset
Este comando mágico compilará un contrato inteligente (es decir, no necesita escribir una
truffle compile
cada vez) y lo implementará en el micro servidor blockchain que se encuentra abierto localmente. Vale la pena señalar que si
testrpc
hace esto instantáneamente, entonces la prueba y las cadenas de bloques reales incluirán la transacción en los siguientes bloques mucho más tiempo. Después de eso, debes escupir algo como esto en la consola:
Using network 'development'. Running migration: 1_initial_migration.js Running step... Replacing MyToken... ... 0x86a7090b0a279f8befc95b38fa8bee6918df30928dda0a3c48416454e2082b65 MyToken: 0x2dc35f255e56f06bd2935f5a49a0033548d85477 Replacing MyCrowdsale... ... 0xf0aab5d550f363478ac426dc2aff570302a576282c6c2c4e91205a7a3dea5d72 MyCrowdsale: 0xaac611907f12d5ebe89648d6459c1c81eca78151 ... 0x459303aa0b79be2dc2c8041dd48493f2d0e109fac19588f50c0ac664f34c7e30 Saving artifacts...
Creo que ya se dio cuenta de que la consola le dio las direcciones de los contratos inteligentes
MyToken
y
MyCrowdsale
. Eso es todo! El contrato inteligente está incrustado en la cadena de bloques cuyo micro servidor ha abierto. Solo queda verificar que los tokens se distribuyan realmente a los usuarios que envían kéfir al contrato inteligente
MyCrowdsale
. Escribimos lo siguiente en la Terminal para ingresar a la consola de trufa:
truffle console
Escribimos lo siguiente en la trufa ahora (sin comentarios solamente):
En el caso de, testrpc
puede verificar inmediatamente el saldo de nuestra billetera nuevamente, pero en el caso de la prueba y la cadena de bloques real, debe esperar hasta que nuestra transacción se incluya en el bloque, generalmente cuando esto sucede, la trufa le da el número de transacción. Has esperado? Verifique nuevamente nuestro saldo en MyToken
:
Eso es todo!
Primero pruebe su contrato testrpc
, luego geth --testnet
, luego despliegue geth
. ¡Así que lanzaste tu propio ICO! Y no tenía que gastar decenas de kilobaks para auditoría y lanzamiento. Enredar con lo que los chicos de OpenZeppelin nos proporcionaron es realmente muy difícil. Y cuando lo usas truffle
, así es como el desarrollo solidario generalmente se convierte en un cuento de hadas. Bueno, excepto en los casos en que las transacciones se invierten durante la ejecución de un contrato inteligente, debuta en el infierno. Pero la depuración de los contratos inteligentes es realmente digna de un artículo separado.Conclusión
¡Muchas gracias por leer hasta el final de este artículo! Si logré ahorrarle tiempo o dinero, o si aprendió algo nuevo de este artículo, entonces me alegraré mucho. También le agradecería que comparta este artículo con sus amigos o conocidos que quieran llevar a cabo una ICO: ahorre $ 75,000 para los subprogramadores que extraen dinero del mercado criptográfico como parásitos, copiando las mismas 25 líneas de código .¡Buena suerte en el desarrollo de contratos inteligentes! ¿Aún tienes preguntas? Te pregunto en los comentarios. Estaré encantado de responder todo y tratar de ayudar con los problemas.Bono
Pero, ¿qué sucede si desea cambiar la lógica por la cual se considera el precio de compra de los tokens? Por supuesto, puede cambiarlo correctamente rate
o usar una de las clases de contratos de OpenZeppelin, pero ¿qué pasa si quiere algo aún más pervertido? En un contrato inteligente, puede anular la función de la getTokenAmount
siguiente manera: function _getTokenAmount(uint256 _weiAmount) internal view returns (uint256) { if (block.timestamp < 1533081600) {
En general, esto puede hacer que el precio de la ficha dependa del momento de la compra: cuanto más se adentre en el bosque, más caras serán las fichas. No tenga miedo de experimentar y reescribir algunas de las características de los contratos inteligentes: ¡es divertido!