- Los smart contracts son programas que se ejecutan en la EVM de Ethereum y automatizan acuerdos sin intermediarios.
- Remix, Truffle, Ganache y MetaMask simplifican el desarrollo, prueba y despliegue de contratos en testnets y mainnet.
- La ABI, el bytecode y un nodo de Ethereum (propio o gestionado) son esenciales para que DApps y scripts interactúen con los contratos.
- La verificación en exploradores como Etherscan aporta transparencia y facilita la auditoría y uso de los contratos inteligentes.
La irrupción de Ethereum y los smart contracts ha cambiado radicalmente la forma en la que entendemos los acuerdos digitales, los pagos condicionados y, en general, la confianza en entornos online. Lo que antes requería intermediarios, papeleo y procesos manuales ahora puede automatizarse con código que se ejecuta de forma descentralizada en una blockchain pública.
Si te suena a algo complicado o reservado solo a expertos, tranquilo: crear y desplegar tu propio contrato inteligente es mucho más accesible de lo que parece. Con las herramientas actuales (Remix, Truffle, Ganache, MetaMask, nodos en la nube, etc.) puedes pasar de cero a tener un smart contract funcionando en una testnet o incluso en la red principal de Ethereum siguiendo una serie de pasos claros.
Qué es exactamente un Smart Contract en Ethereum
Un smart contract es, en esencia, un programa que vive y se ejecuta en una blockchain. En el caso de Ethereum, ese programa corre dentro de la Ethereum Virtual Machine (EVM), que está replicada en todos los nodos de la red. El contrato define reglas, condiciones y acciones que se ejecutan automáticamente cuando se cumplen esos requisitos, sin necesidad de que una tercera parte supervise el proceso.
Podemos verlo como un acuerdo digital del tipo “si pasa X, haz Y”. Por ejemplo: “si el usuario A envía un pago superior a una cantidad ‘n’ a la dirección ‘M’ antes del día ‘Z’, marcar la factura como pagada correctamente”. Antes de la aparición de blockchain, no había forma de hacer cumplir este tipo de reglas de forma automática y sin intermediarios confiables.
Ethereum es la plataforma más popular para smart contracts porque ofrece un entorno muy flexible, una comunidad enorme, abundante documentación y herramientas maduras para desarrollo. Todo esto facilita que tanto desarrolladores junior como perfiles avanzados puedan crear aplicaciones descentralizadas (DApps) y contratos complejos.
Los smart contracts no dejan de ser código fuente escrito en un lenguaje específico (Solidity o Vyper, entre otros), que se compila a bytecode y se despliega en una dirección de contrato dentro de la red. A partir de ahí, cualquier usuario o aplicación puede interactuar con ese contrato llamando a sus funciones públicas.
Solidity, la EVM y otros lenguajes para contratos

Solidity es el lenguaje de programación estrella para desarrollar contratos en Ethereum. Es un lenguaje de alto nivel, con una sintaxis que recuerda a JavaScript, C++ o Java, pensado específicamente para compilar a bytecode que entiende la Ethereum Virtual Machine.
La EVM (Ethereum Virtual Machine) es la máquina virtual que ejecuta tu contrato en cada nodo de la red. Se parece conceptualmente a la Java Virtual Machine, con la diferencia importante de que en Ethereum cada nodo ejecuta el mismo bytecode para validar las transacciones y mantener el estado global de la blockchain sincronizado.
Cuando compilas un contrato Solidity obtienes el bytecode y la ABI. El bytecode es la representación binaria que la EVM sabe ejecutar; la ABI (Application Binary Interface) describe las funciones, los parámetros y los tipos que se pueden invocar desde fuera. Cualquier DApp o script que quiera hablar con tu contrato necesita esa ABI y la dirección del contrato.
Existen también otros lenguajes y “wrappers”. Aunque Solidity es el estándar de facto, hay implementaciones y bindings desde lenguajes como Java o Python, y lenguajes alternativos como Vyper, que apuesta por una sintaxis más simple y restricciones diseñadas para evitar errores y vulnerabilidades.
Herramientas básicas para desarrollar Smart Contracts

Para ponerte manos a la obra con Ethereum vas a necesitar un pequeño kit de herramientas que te dará todo lo necesario para escribir, probar y desplegar contratos inteligentes sin volverte loco con la infraestructura.
Node.js y npm son la base para gestionar dependencias y ejecutar scripts de desarrollo. A partir de ahí, se apoyan varios frameworks y librerías que facilitan todo el flujo de trabajo: compilación, migraciones, test y despliegue.
Truffle Suite es uno de los frameworks más veteranos para desarrollo de smart contracts. Con él puedes crear un proyecto con truffle init, organizar tus contratos en la carpeta contracts, definir scripts de migración y ejecutar tests automatizados. Además se integra muy bien con Ganache.
Ganache es una blockchain local para hacer pruebas. Emula una red de Ethereum en tu propia máquina, generando varias cuentas con Ether “falso” para que puedas desplegar contratos, hacer transacciones y depurar sin gastar un céntimo real ni esperar a mineros de verdad.
MetaMask actúa como puente entre tu navegador y la blockchain. Es una wallet que se integra como extensión y te permite conectar DApps, firmar transacciones, cambiar entre redes (testnets, mainnet, sidechains) y gestionar tus cuentas de forma bastante cómoda.
Remix IDE: el entorno más sencillo para empezar
Si estás empezando, Remix es probablemente la forma más rápida de ver tu primer contrato funcionando. Remix es un IDE que se ejecuta en el navegador, accesible directamente desde https://remix.ethereum.org o desplegable en tu propio servidor, que incluye editor, compilador, herramientas de despliegue y panel de interacción.
La interfaz de Remix se organiza en varias pestañas clave: el explorador de archivos, el compilador de Solidity y el panel de “Deploy & run transactions”. Desde el explorador puedes crear ficheros como FirstContract.sol o HelloWorld.sol dentro de un directorio de contratos.
En la pestaña “Solidity compiler” eliges la versión del compilador (debe ser igual o mayor que la especificada en la directiva pragma solidity de tu contrato) y lanzas la compilación con el botón “Compile …”. Si todo está correcto, verás un icono de verificación en verde junto al contrato.
Tras compilar, Remix genera artefactos como el JSON con bytecode y ABI. En el panel de archivos puedes ver algo como FirstContract.json, que contiene campos muy importantes como bytecode y la abi. Estos datos son los que más tarde usarás en librerías como Web3.js o Web3.py para desplegar e interactuar con el contrato desde tu backend o scripts externos.
En la pestaña “Deploy & run transactions” eliges el entorno de ejecución para desplegar el contrato. Aquí entran en juego varias opciones que conviene entender bien antes de tocar la red real.
Entornos de ejecución en Remix: de local a redes públicas
El combo “Environment” de Remix controla dónde se envían las transacciones y dónde se va a desplegar exactamente tu contrato inteligente. No es lo mismo hacer pruebas rápidas en memoria que publicar algo en la mainnet.
JavaScript VM (por ejemplo, London) es un entorno completamente local, en memoria. Remix crea varias cuentas con 100 ETH de prueba, genera los bloques al vuelo y descarta todo si recargas la página. Es perfecto para aprender, probar lógicas y equivocarte sin consecuencias.
Injected Web3 utiliza el proveedor que inyecta tu navegador, normalmente MetaMask. Eso significa que las transacciones irán a la red que tengas seleccionada en la wallet: puede ser una testnet como Sepolia o una red principal como Ethereum Mainnet o una sidechain tipo Polygon.
Web3 Provider permite conectar directamente con un nodo remoto indicando su URL HTTP, por ejemplo un nodo privado corriendo en tu propia infraestructura (http://192.168.41.88:8041) o un endpoint ofrecido por un proveedor externo. Remix envía las transacciones a ese nodo usando Web3.
Una vez elegido el entorno, seleccionas la cuenta desde la que se desplegará el contrato. En las VMs locales verás una lista de direcciones con saldo simulado; con MetaMask o un nodo remoto será la cuenta que tenga configurada ese proveedor. El despliegue siempre consume “gas”, aunque en local ese coste no sea real.
Después eliges el contrato en el desplegable de “Contract” y pulsas “Deploy”. Si el constructor del contrato recibe parámetros (por ejemplo una dirección de propietario o un mensaje inicial), Remix mostrará inputs para rellenarlos antes de enviar la transacción de despliegue.
Ejemplo práctico: contratos sencillos en Solidity
Para entender la mecánica completa, viene muy bien arrancar con un contrato simple que permita almacenar un valor y recuperarlo, o actualizar un mensaje. Es el equivalente al clásico “Hello World” pero en versión blockchain.
Un ejemplo moderno podría ser un contrato HelloWorld con una variable de estado message, un constructor que la inicializa y una función para actualizarla. Todo ello con una versión reciente de Solidity (^0.8.0) y buenas prácticas de visibilidad.
Otro ejemplo más elaborado es el contrato FirstContract, que introduce variables como owner, ownerName, ownerAge y una lista de posts (por ejemplo, URLs). Además, define modificadores de acceso personalizados como onlyOwner, existsUrl y notExistsUrl para centralizar las comprobaciones de permisos y coherencia de datos.
Estos modificadores de acceso propios permiten evitar repetir la misma lógica una y otra vez en cada función. Por ejemplo, onlyOwner comprueba con require(msg.sender == owner) que la cuenta que ejecuta la función sea la propietaria del contrato, y el símbolo _; indica el punto en el que continuará la ejecución si la condición se cumple.
Las funciones de lectura suelen ir acompañadas del modificador view, que indica que no modifican el estado del contrato. Esto implica que pueden ejecutarse como “call” sin coste de gas desde el punto de vista del usuario, ya que no escriben nada en la blockchain. De forma aún más estricta, pure indica que la función ni lee ni escribe estado.
Probar contratos en local y entender el gas
Cuando despliegas un contrato en la JavaScript VM de Remix, el IDE crea una transacción que consume gas simulado. Nada de ese gas sale de tu bolsillo, pero te sirve para entender que en un entorno real cualquier despliegue y cualquier función que cambie el estado tiene un coste asociado.
Al desplegar verás que la cuenta emisora baja de 100 ETH a 99.x ETH en la VM local. Eso refleja el coste de almacenar el bytecode del contrato y de ejecutar el constructor en la blockchain. En una testnet o mainnet, ese gasto se descuenta del saldo de tu wallet real.
Gas, fee, wei y ether son conceptos clave aquí. El gas mide el trabajo computacional necesario para ejecutar una operación; el gas price (en gwei, fracciones de ether) es lo que estás dispuesto a pagar por cada unidad de gas. El fee total es gas usado multiplicado por gas price. El saldo de las cuentas se maneja internamente en wei (10^18 wei = 1 ETH).
En Remix, tras desplegar el contrato, se muestra un panel con todos los elementos interactivos: botones naranjas para funciones que envían transacciones (escrituras) y botones azules para funciones de solo lectura. Puedes introducir datos en los campos correspondientes, llamar a funciones como addPostUrl o setOwnerState y observar cómo cambia el estado.
Si cambias de cuenta en el panel “Account” de Remix notarás que los permisos cambian. Las funciones protegidas con onlyOwner fallarán cuando las ejecute una cuenta distinta del propietario actual del contrato, lo que te permite comprobar que los modificadores de acceso están haciendo su trabajo.
Despliegue en testnets públicas: Sepolia, Rinkeby y compañía
Una vez dominas el flujo en local, el siguiente paso natural es irte a una testnet. Históricamente se ha utilizado Rinkeby, aunque hoy en día redes como Sepolia o Goerli tienen mucho más protagonismo. La idea es la misma: replicar el comportamiento de mainnet pero con Ether de prueba que se obtiene gratuitamente en faucets.
Para desplegar desde Remix en una testnet te basta con usar “Injected Web3” como entorno y configurar tu wallet (MetaMask, por ejemplo) en la red de prueba que quieras usar. Al darle a “Deploy”, MetaMask mostrará la transacción, el gas estimado y te pedirá confirmación.
Una vez que la transacción se mina, el contrato obtiene su propia dirección (contract account) en la testnet. Puedes copiarla desde Remix o desde la ventana de confirmación de la wallet y pegarla en el explorador de bloques correspondiente (por ejemplo, Sepolia Etherscan).
En el explorador verás la cuenta del contrato, su bytecode y las transacciones asociadas. Inicialmente solo aparecerá la transacción de creación, pero luego irás viendo las llamadas de lectura y escritura que hagan los usuarios o las DApps que interactúen con ese contrato.
Muchos exploradores permiten incluso interactuar con el contrato directamente desde las pestañas “Read Contract” y “Write Contract”, una vez que el código fuente ha sido verificado y publicado, lo que resulta muy cómodo para pruebas rápidas sin montar todavía una interfaz web propia.
Verificar y publicar el código del contrato en Etherscan
Verificar un contrato en Etherscan (o el explorador equivalente) es un paso clave de transparencia. Consiste en subir el código fuente, especificar la versión del compilador y las opciones utilizadas, para que el explorador pueda recompilar y comprobar que el bytecode coincide con el desplegado.
El proceso típico en una red como Sepolia es el siguiente: entras en la página de la dirección del contrato, pulsas en el enlace “Verify and Publish”, introduces la dirección, seleccionas el compilador de Solidity concreto, indicas la licencia y, en la siguiente pantalla, pegas el contenido de tu archivo .sol.
Tras superar el captcha y enviar el formulario, el explorador recompila el código y compara el resultado con el bytecode que hay almacenado en la blockchain. Si coinciden, marca el contrato como verificado con un check verde junto al botón “Contract”.
A partir de ese momento el explorador muestra el código fuente, la ABI y una interfaz gráfica para ejecutar funciones de lectura (“Read Contract”) y de escritura (“Write Contract”), utilizando tu wallet para firmar transacciones si es necesario. Es una forma muy cómoda de que cualquier persona audite o pruebe el contrato.
Un ejemplo típico es el contrato Register01.sol en una testnet, que permite guardar un texto en una variable storedInfo con la función setInfo y recuperarlo con getInfo. Puedes escribir “Hello World” desde “Write Contract” y luego comprobar el valor en “Read Contract”.
Interacción desde DApps y scripts: Web3.js, Node.js y bases de datos
Más allá de Remix y los exploradores, la vida real de un smart contract empieza cuando una DApp lo utiliza. Una DApp suele componerse de tres piezas básicas: el propio contrato, un backend (por ejemplo en Node.js) y una base de datos de apoyo, como MongoDB, para cachear lecturas y mejorar el rendimiento.
En el backend se suele utilizar Web3.js (en Node) o Web3.py (en Python) para conectar con un nodo Ethereum (público, privado o gestionado) a través de un endpoint HTTP o WebSocket. Para ello necesitas, de nuevo, la URL del nodo, la dirección del contrato y su ABI.
Un script típico en Node podría crear una instancia de Web3 con new Web3(new Web3.providers.HttpProvider("http://localhost:8042")), parsear la ABI con JSON.parse y usar web3.eth.contract(interface) combinado con .at("0xDirecciónDelContrato") para obtener una referencia al contrato desplegado.
Para poder enviar transacciones desde el backend es necesario desbloquear la cuenta que firmará esas operaciones, bien con web3.personal.unlockAccount si tu nodo lo permite, o bien firmando las transacciones localmente con la clave privada (mucho más delicado en términos de seguridad y custodia).
En producción, casi siempre se añade una capa adicional de seguridad: vaults para guardar claves privadas, políticas de acceso estricto, separación entre front y back, y uso de proveedores como MetaMask, Infura o nodos gestionados, para no exponer directamente la infraestructura crítica.
Nodos gestionados y despliegues avanzados con AWS Managed Blockchain
Cuando el proyecto crece, tiene sentido apoyarse en infraestructura gestionada para los nodos de Ethereum. Un ejemplo es Amazon Managed Blockchain, que permite desplegar nodos de Ethereum (por ejemplo en la Mainnet) sin pelearte con la instalación, sincronización y mantenimiento del software de nodo.
Desde la consola de AWS puedes unirte a la red pública de Ethereum, elegir la red (por ejemplo Ethereum Mainnet), el tipo de instancia, la zona de disponibilidad y crear uno o varios nodos para alta disponibilidad. Tras unos minutos, el nodo pasa a estado “Disponible”.
El acceso a estos nodos puede hacerse mediante firmas SigV4 o mediante tokens. El acceso basado en token simplifica mucho la integración con herramientas estándar del ecosistema Ethereum (Ethers.js, Hardhat, MetaMask, The Graph, Chainlink, etc.), que esperan un endpoint RPC directo sin tener que saber nada de AWS.
El endpoint HTTP típico tiene una forma como https://id-del-nodo.t.ethereum.managedblockchain.us-east-1.amazonaws.com/<ruta>?billingtoken=token. Con ese endpoint puedes crear una instancia de Web3 en Python, por ejemplo, y llamar a métodos como w3.is_connected() o w3.eth.syncing para comprobar si el nodo está sincronizado.
Una vez verificada la conexión, puedes hacer lecturas como w3.eth.get_block("latest") para obtener el minero del último bloque, o w3.eth.get_balance(address) para mirar el saldo de una cuenta (expresado en wei y convertible a ether con Web3.from_wei).
Gestión de cuentas, claves y despliegue desde código
Desplegar contratos desde código implica trabajar con claves privadas. En Python, por ejemplo, podrías generar una clave privada nueva con la librería secrets, crear una cuenta con w3.eth.account.from_key(private_key) y obtener su dirección pública.
Esa dirección empieza con saldo cero y deberás financiarla bien comprando ETH a través de una wallet, bien recibiendo fondos desde otro monedero. Hasta que el nodo que usas no esté totalmente sincronizado, las lecturas del balance pueden no reflejar todavía ese ingreso, así que conviene comprobar periódicamente w3.eth.syncing.
Para desplegar un contrato desde Web3.py necesitas el bytecode y la ABI. Si has escrito el contrato en Vyper, por ejemplo, puedes compilarlo con vyper safe-remote-purchase.vy > bytecode.bin y vyper -f abi safe-remote-purchase.vy > abi.json, y luego leer ambos ficheros desde tu script.
Con esos datos creas el objeto contrato con w3.eth.contract(abi=abi, bytecode=bytecode), consultas el gas price actual con w3.eth.gas_price, y preparas la transacción de despliegue con .constructor().build_transaction({...}) indicando campos como from, nonce, gas y opcionalmente value si el constructor necesita un depósito.
La transacción se firma con la clave privada y se envía con w3.eth.send_raw_transaction. Después esperas el recibo con w3.eth.wait_for_transaction_receipt; si el estado es exitoso, el recibo contendrá la dirección del contrato desplegado en contractAddress.
Ejemplo avanzado: compra remota segura con Vyper
Un caso más complejo y muy ilustrativo es el contrato de “compra remota segura”, documentado en los ejemplos de Vyper. El objetivo es regular una compraventa entre un vendedor y un comprador, con depósitos que garantizan el comportamiento honesto de ambas partes.
El flujo general es el siguiente: el vendedor despliega el contrato depositando el doble del valor del producto; mientras nadie haya comprado, puede abortar y recuperar el dinero. El comprador, cuando decide adquirir el artículo, envía el valor del mismo más un depósito igual (dos veces el precio).
Cuando el comprador recibe el producto, llama a la función correspondiente (por ejemplo received), lo que provoca que parte del depósito vuelva a sus manos y el vendedor reciba tanto el precio del producto como su depósito inicial. De esta forma, ambas partes tienen incentivos económicos alineados.
Tras compilar el contrato con Vyper, obtienes su bytecode y ABI, que usarás con Web3 para desplegarlo. Una vez desplegado, puedes obtener una instancia con w3.eth.contract(address=contractAddress, abi=abi) e invocar métodos como abort(), purchase() o received() desde las cuentas pertinentes (vendedor o comprador).
Este tipo de ejemplo muestra cómo los smart contracts permiten automatizar acuerdos complejos donde, en los sistemas tradicionales, haría falta un tercero de confianza, un escrow o contratos legales de por medio. En la blockchain, la lógica del acuerdo está en el propio código, auditado y ejecutado por todos los nodos.
Con todo lo anterior ya tienes una visión completa del ciclo de vida de un smart contract: desde la teoría básica de qué es un contrato inteligente y cómo se ejecuta en la EVM, pasando por la escritura en Solidity o Vyper, las pruebas en Remix y Ganache, el despliegue en testnets y mainnet, la verificación en Etherscan, la interacción desde DApps y la operación con nodos gestionados en la nube. A partir de aquí, el siguiente paso natural es profundizar en patrones avanzados (proxies, upgradability, herencia, seguridad) y explorar casos de uso como NFTs, DeFi o gobernanza on-chain, aprovechando el enorme ecosistema que se ha construido alrededor de Ethereum.
Redactor apasionado del mundo de los bytes y la tecnología en general. Me encanta compartir mis conocimientos a través de la escritura, y eso es lo que haré en este blog, mostrarte todo lo más interesante sobre gadgets, software, hardware, tendencias tecnológicas, y más. Mi objetivo es ayudarte a navegar por el mundo digital de forma sencilla y entretenida.
