Contenido del curso
Entendiendo la EVM
Herramientas de Solidity
Retiros y control de permisos
Interactuando con la Blockchain de Celo
Interactuando con Smart Contracts
- 16

Conectando React con Celo usando ContractKit
09:34 min - 17

Conectar Valora a contratos inteligentes con Wallet Connect
05:16 min - 18

Despliegue de Contratos Inteligentes en Testnet Alfajores con Remix
03:07 min - 19

Liberación arbitral con Celo ContractKit
04:30 min - 20

Firma de transacciones con WalletConnect y Valora
03:06 min
Sigue practicando
Modificadores y ownable en contratos escrow
Resumen
Construir un contrato escrow en Celo con Solidity implica algo más que escribir funciones que muevan dinero: requiere un código limpio, modular y seguro que cualquier desarrollador pueda mantener. Aquí avanzas en un proyecto real de smart contract donde el comprador deposita un pago en garantía, el vendedor retira las ganancias y un árbitro resuelve disputas, todo con buenas prácticas de Solidity como modificadores y el patrón ownable de OpenZeppelin.
¿Cómo se estructura el constructor de un contrato escrow?
El constructor es la puerta de entrada del contrato. Cuando creas la instancia, recibe los parámetros que definen el acuerdo entre las partes y los asigna a las variables de estado.
En este proyecto, el constructor recibe cuatro datos clave:
- La address del comprador.
- La address del vendedor.
- El monto del pago acordado.
- La dirección del árbitro que resolverá disputas [01:30].
Además, defines tres variables booleanas que controlan el flujo: depositoListo, pagoListo y compradorOK, todas inicializadas en false. Estas banderas marcan en qué etapa del proceso se encuentra la transacción y son la base de las verificaciones posteriores.
¿Qué hace el constructor en un smart contract? Inicializa las variables de estado al momento de desplegar el contrato. Se ejecuta una sola vez y fija los valores que regirán toda la lógica futura.
¿Cómo funciona el depósito en garantía con la función payable?
La primera función operativa es depositarPago, que el comprador usa para dejar el dinero en custodia. Para que el contrato pueda recibir Celo Gold, debes marcarla con el modificador payable [02:30].
Dentro de la función ocurren dos verificaciones críticas:
- Que el
msg.sendersea efectivamente el comprador registrado. - Que el monto enviado coincida con el valor pactado en el constructor.
Si ambas condiciones se cumplen, la variable depositoListo cambia a true y el primer paso queda completado. Esta lógica garantiza que ningún tercero pueda alterar el flujo ni enviar montos incorrectos.
¿Qué pasa después del depósito? La confirmación del comprador
Una vez que el dinero está en garantía, el comprador debe confirmar que recibió el producto conforme. Para eso existe la función compradorConfirmoOK [03:30], que verifica nuevamente que quien llama sea el comprador y luego cambia compradorOK a true.
Este paso es el que habilita al vendedor para retirar el pago. Sin esta confirmación explícita, los fondos permanecen bloqueados en el contrato.
¿Cómo retira el vendedor sus ganancias en un contrato escrow?
La función retirarPago es la que ejecuta el vendedor cuando quiere cobrar. Antes de transferir cualquier monto, el contrato exige que compradorOK esté en true, lo que prueba que la entrega fue conforme.
Luego ocurre algo técnicamente interesante: necesitas convertir la address del vendedor en una address payable mediante un wrap. Solo las direcciones marcadas como payable pueden recibir transferencias de Celo Gold desde el contrato [04:30].
Finalmente, la variable pagoListo pasa a true y el flujo queda cerrado.
¿Qué es una address payable en Solidity? Es un tipo de dirección que tiene permitido recibir transferencias de tokens nativos. Si una address normal intenta recibir fondos directamente, la transacción falla.
¿Y si el comprador no reconoce la entrega? El rol del árbitro
Cuando el comprador intenta no confirmar la recepción, entra en juego la función pagarPorArbitro. Esta función verifica que quien la invoca sea el árbitro designado y, en ese caso, libera el pago al vendedor reutilizando la misma lógica de transferencia [05:30].
Es un mecanismo simple pero poderoso: una tercera parte neutral resuelve la disputa con base en evidencias externas, y el contrato ejecuta la decisión de forma automática.
¿Cómo hacer el código de Solidity más elegante con modificadores?
Notarás que la verificación require(msg.sender == comprador) aparece repetida en varias funciones. Cuando un patrón se repite, Solidity te da una herramienta poderosa: los modificadores.
Creas un modificador llamado onlyComprador en la parte superior del contrato, mueves la verificación dentro de él y cierras con un guion bajo y punto y coma (_;). Ese símbolo le indica al compilador que el resto del código de la función se ejecuta a continuación [07:00].
Luego reemplazas las líneas repetidas por el modificador en cada función:
solidity modifier onlyComprador() { require(msg.sender == comprador, "No eres el comprador"); _; }
function compradorConfirmoOK() public onlyComprador { compradorOK = true; }
El resultado es un contrato más corto, más legible y mucho más fácil de mantener.
¿Qué aporta el patrón ownable de OpenZeppelin?
El último refinamiento es incorporar el patrón ownable desde el repositorio de OpenZeppelin, una librería estándar en el ecosistema Ethereum y compatible con Celo.
Al heredar de Ownable, el contrato gana automáticamente una propiedad owner que representa al creador. En este proyecto, decides que el árbitro sea precisamente ese owner, lo que te permite:
- Eliminar la variable
arbitrodel contrato. - Quitar su parámetro del constructor.
- Reemplazar la verificación manual por el modificador
onlyOwnerenpagarPorArbitro[08:30].
Con ese cambio, el árbitro queda definido como quien despliega el contrato y es la única persona autorizada a forzar la liberación del pago en caso de disputa. Menos código, más seguridad y un patrón ya auditado por la comunidad.
¿Cómo vas a personalizar tu propio contrato escrow? Cuéntame en los comentarios qué validaciones adicionales le agregarías, como un plazo máximo de confirmación o múltiples árbitros.