La Máquina Virtual de TRON (TVM) ofrece un entorno de alto rendimiento y compatible con la EVM para desplegar contratos inteligentes en Solidity. Aunque comparte gran parte del conjunto de herramientas de Ethereum, esta guía destaca comportamientos críticos específicos de la TVM, como el manejo de marcas de tiempo en milisegundos y la lógica de autodestrucción actualizada, para garantizar despliegues seguros y optimizados.
Históricamente, el opcode selfdestruct estaba deshabilitado en TRON. Sin embargo, tras la aprobación de la Propuesta de Gobernanza de TRON N.° 106 (abril de 2026), el comportamiento ahora se alinea con Ethereum (EIP-6780) para mejorar la compatibilidad con la TVM:
Un contrato solo será eliminado si selfdestruct se ejecuta dentro de la misma transacción que creó el contrato.
Si se ejecuta en cualquier transacción posterior, solo ocurre la transferencia del activo TRX, y el código del contrato permanece en cadena.
El costo de Energía para llamar a selfdestruct se ha ajustado a 5000.
El soporte para TSTORE, TLOAD (EIP-1153) y MCOPY (EIP-5656) se añadió a la TVM como parte de la actualización GreatVoyage-v4.8.0 (Kant) (junio de 2025). Esto garantiza que los desarrolladores puedan migrar contratos que utilizan las actualizaciones Cancun/Dencun de Ethereum sin modificaciones.
Las direcciones de TRON tienen 21 bytes internamente (las direcciones de Ethereum tienen 20 bytes). La codificación ABI rellena a 32 bytes como en la EVM, por lo que las llamadas a contratos codificadas en ABI funcionan correctamente. Sin embargo, si estás haciendo manipulación de bytes sin procesar de direcciones (por ejemplo, en assembly), ten en cuenta el tamaño de 21 bytes.
En Ethereum, block.coinbase es la dirección del minero/validador. En la TVM, es la dirección del Super Representante que produjo el bloque actual. No uses block.coinbase como fuente de aleatoriedad — es predecible y manipulable por los SRs.
El opcode CREATE deriva una dirección de contrato de forma diferente en TRON que en Ethereum. Si estás desplegando contratos que dependen de direcciones CREATE deterministas calculadas fuera de cadena, recalcúlalas para el esquema de derivación de direcciones de TRON. CREATE2 con un salt explícito funciona correctamente para direcciones deterministas.
En Ethereum, address.transfer(amount) tiene un estipendio fijo de 2,300 de gas. En la TVM, esta llamada usa Energía. Los patrones de reentrada que dependían del límite de 2,300 de gas por seguridad pueden comportarse de forma diferente. Usa el patrón de verificaciones-efectos-interacciones independientemente.
TronBox es compatible con Solidity hasta 0.8.x. Usa pragma ^0.8.0 o fija una versión específica. Solidity 0.8 incluye comprobaciones de desbordamiento integradas, lo que elimina la necesidad de SafeMath.
version.sol
// Tarea: Especificar la versión del compilador de Solidity para la TVM.
TRC-20 es funcionalmente idéntico a ERC-20. La referencia completa de firmas de funciones, definiciones de eventos y direcciones de contratos conocidos en la red principal están en Estándares de Tokens. A continuación se muestra un TRC-20 mínimo y desplegable completo con notas específicas de la TVM en línea.
SimpleTRC20.sol
// Tarea: Este código define un contrato de token TRC-20 mínimo.
// SPDX-License-Identifier: MIT
pragmasolidity^0.8.18;
/**
* @title SimpleTRC20
* @dev Token TRC-20 mínimo y desplegable para TRON.
6,// decimales (6 coincide con la convención de USDT en TRON)
1_000_000// suministro inicial
);
};
Un ERC-20 estándar de OpenZeppelin también se despliega correctamente en TRON como TRC-20. Revisa solo dos cosas antes de desplegar: cada comparación de block.timestamp (multiplica los umbrales por 1000) y cómo manejas selfdestruct (dado que el comportamiento de eliminación ha sido actualizado).
Cada opcode consume Energía. Escribir Solidity eficiente en gas para Ethereum produce contratos eficientes en Energía en TRON también — los principios son los mismos. (Para desarrolladores de Web2: Optimizar el uso de gas es como optimizar consultas de base de datos costosas. En servidores tradicionales, las malas consultas solo ralentizan las cosas; en las blockchains, directamente le cuestan dinero real a tus usuarios).
config =Config(a, b, c); // un único SSTORE en un solo slot
}
Usa funciones view y pure para las lecturas. Las llamadas view/pure no cuestan Energía cuando se llaman fuera de cadena (son gratuitas). Solo las llamadas que cambian de estado cuestan Energía.
Emite eventos en lugar de escribir en almacenamiento para datos históricos. Los eventos se almacenan en logs (económico) en lugar de en el almacenamiento del contrato (costoso).
Usa calldata en lugar de memory para parámetros de funciones cuando los datos solo se leen y no se modifican:
MemoryUsage.sol
// Tarea: Evitar copiar arrays grandes a memoria si solo se leen.
Verificar el código fuente de tu contrato en TRONSCAN permite que los usuarios y otros desarrolladores lean tu lógica, inspeccionen el ABI e interactúen directamente a través del explorador.
Pasos de verificación
Ve a la dirección de tu contrato en tronscan.org
Haz clic en la pestaña Contract
Haz clic en Verify and Publish
Selecciona la versión del compilador usada por TronBox (debe coincidir exactamente)
Pega el código fuente de Solidity
Envía — TRONSCAN compila y verifica que el bytecode coincida con el que está en cadena
Para proyectos de múltiples archivos, usa el método Standard JSON Input, que acepta la entrada completa del compilador incluyendo todos los archivos importados. La salida de TronBox en build/contracts/*.json contiene la entrada del compilador necesaria.
Para un desglose completo de cómo funcionan la Energía y el Ancho de banda, el multiplicador del Modelo de Energía Dinámica y cómo implementar la delegación de comisiones para que tu DApp subsidie los costos de los usuarios, consulta Modelo de Comisiones y Delegación.
Cada transacción que llama a un contrato especifica un límite de comisión — el máximo de TRX que el remitente está dispuesto a quemar si se agota la Energía. Si la ejecución del contrato supera la Energía disponible y se alcanza el límite de comisión, la transacción revierte y el límite de comisión se consume parcialmente.
En tronweb, establece el límite de comisión por llamada:
sdk_call.js
// Tarea: Especificar un límite de comisión para protegerse de bucles infinitos o costos elevados.
awaitcontract.someMethod().send({
feeLimit: 1_000_000_000, // máximo 1,000 TRX
shouldPollResponse: true,
});
Establece el límite de comisión generosamente durante el desarrollo y ajústalo después de conocer el costo real de Energía a través del historial de transacciones de TRONSCAN.
Toda la lógica basada en tiempo debe usar milisegundos, no segundos. Audita cada comparación de block.timestamp en los contratos migrados.
Comportamiento de SELFDESTRUCT
Ten en cuenta el nuevo comportamiento de SELFDESTRUCT (Propuesta 106): los contratos ya no se eliminan a menos que sean destruidos en su transacción de creación. Ajusta tu lógica de actualización y limpieza en consecuencia.
Cálculo de direcciones fuera de cadena
Si tus scripts de despliegue calculan direcciones de contratos fuera de cadena (para fábricas CREATE), recalcúlalos usando el esquema de derivación de direcciones de TRON.
Subestimación de Energía
Siempre prueba el consumo de Energía en Nile antes de ir a la red principal. Subestimar los límites de comisiones provoca reversiones en el peor momento posible.