Cheat Sheet de Solidity
Estructura de un contrato
Cada archivo empieza con una licencia y un pragma; el contrato es la unidad de despliegue.
| Sintaxis | Significado |
|---|---|
// SPDX-License-Identifier: MIT | Comentario de licencia que el compilador espera en la línea 1 |
pragma solidity ^0.8.0; | Versión del compilador para la que está escrito el archivo |
contract Counter { ... } | Declarar un contrato (estado + funciones) |
constructor(uint start) { count = start; } | Se ejecuta una sola vez, en el despliegue |
import "./Token.sol"; | Importar otro archivo |
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | Importar un paquete de librería |
interface IToken { function balanceOf(address a) external view returns (uint); } | Declarar una interfaz (sin cuerpos) |
library Math { function min(uint a, uint b) internal pure returns (uint) { ... } } | Una librería de funciones reutilizables |
Tipos de valor
Los enteros tienen tamaño fijo y no admiten decimales; 0.8 revierte en caso de desbordamiento.
| Tipo | Qué contiene |
|---|---|
uint256 / uint | Entero sin signo, de 0 a 2^256 - 1 (uint es uint256) |
uint8, uint16, ... uint128 | Enteros sin signo más pequeños, en pasos de 8 bits |
int256 / int | Entero con signo (admite negativos) |
bool | true o false |
address | Dirección de cuenta o contrato de 20 bytes |
address payable | Dirección que puede recibir Ether mediante transfer/send |
bytes32, bytes1... | Arrays de bytes de tamaño fijo |
enum Status { Open, Closed } | Conjunto de constantes con nombre, almacenado como uint8 |
1 ether, 1 gwei, 1 wei | Unidades de Ether: 1 ether = 10^18 wei |
1 days, 2 hours, 30 minutes | Unidades de tiempo, en segundos |
Tipos de referencia y ubicación de datos
Arrays, strings, bytes, structs y mappings viven en storage, memory o calldata.
| Sintaxis | Significado |
|---|---|
string memory name | String UTF-8 dinámico (una copia temporal) |
bytes memory data | Array de bytes dinámico |
uint[] public scores; | Array dinámico en storage |
uint[3] fixed; | Array de tamaño fijo de 3 elementos |
uint[] memory tmp = new uint[](5); | Reservar un array en memory |
scores.push(42); | Añadir al final de un array en storage |
scores.pop(); | Eliminar el último elemento |
scores.length | Número de elementos |
storage | Persistente, on-chain, caro de escribir |
memory | Temporal, vive durante una llamada |
calldata | Entrada de solo lectura de funciones external, la más barata |
Mappings y structs
Un mapping es una tabla hash sin longitud ni iteración; un struct agrupa campos.
| Sintaxis | Significado |
|---|---|
mapping(address => uint) public balances; | Almacén clave-valor; toda clave existe (por defecto vale 0) |
balances[msg.sender] += 1; | Leer/escribir por clave |
mapping(address => mapping(address => uint)) allowance; | Mapping anidado |
struct User { string name; uint age; bool active; } | Definir un struct |
User memory u = User("Ada", 36, true); | Crear un struct en memory |
User memory u = User({name: "Ada", age: 36, active: true}); | Creación con campos con nombre |
users[msg.sender] = u; | Guardar un struct en un mapping |
users[msg.sender].age = 37; | Actualizar un campo en storage |
delete users[msg.sender]; | Restablecer a los valores por defecto |
Funciones y visibilidad
Cada función declara quién puede llamarla y si lee o escribe el estado.
| Sintaxis | Significado |
|---|---|
function add(uint a, uint b) public pure returns (uint) { return a + b; } | Una función con parámetros y valor de retorno |
public | Llamable desde cualquier lugar (dentro y fuera) |
external | Llamable solo desde fuera del contrato |
internal | Este contrato y los contratos que heredan de él |
private | Solo este contrato |
view | Lee el estado, nunca lo escribe |
pure | No lee ningún estado |
payable | Puede recibir Ether con la llamada |
returns (uint sum, bool ok) | Varios valores de retorno con nombre |
(uint s, bool ok) = f(); | Desestructurar varios valores de retorno |
uint public count; | Una variable de estado pública obtiene un getter automático count() |
Modifiers, constantes y herencia
Reutiliza comprobaciones con modifiers; fija valores con constant e immutable.
| Sintaxis | Significado |
|---|---|
modifier onlyOwner() { require(msg.sender == owner, "Not owner"); _; } | Definir un modifier (_ = ejecutar el cuerpo de la función) |
function withdraw() public onlyOwner { ... } | Aplicar un modifier |
uint public constant MAX = 100; | Constante en tiempo de compilación |
address public immutable owner; | Se asigna una vez en el constructor y luego queda fija |
contract Token is ERC20, Ownable { ... } | Heredar de otros contratos |
function f() public virtual { ... } | Permitir la sobrescritura |
function f() public override { ... } | Sobrescribir una función del padre |
super.f(); | Llamar a la implementación del padre |
abstract contract Base { function f() public virtual; } | Contrato con funciones sin implementar |
Control de flujo
Las sentencias habituales de la familia C; no hay switch, y los bucles cuestan gas por iteración.
| Sintaxis | Significado |
|---|---|
if (x > 5) { ... } else if (x > 2) { ... } else { ... } | Ramas condicionales |
for (uint i = 0; i < n; i++) { ... } | Bucle con contador |
while (x < 10) { x++; } | Repetir mientras se cumpla una condición |
do { ... } while (cond); | Se ejecuta al menos una vez |
break; / continue; | Salir del bucle / saltar a la siguiente iteración |
x > 0 ? a : b | Expresión ternaria |
a / b | División entera (descarta el resto) |
a % b | Resto |
a ** 2 | Potencia |
unchecked { x++; } | Omitir las comprobaciones de desbordamiento (ahorra gas, úsalo con cuidado) |
Errores: require, revert, assert
Una comprobación fallida deshace toda la transacción y devuelve el gas no usado.
| Sintaxis | Significado |
|---|---|
require(amount > 0, "Amount must be positive"); | Validar la entrada o el estado; revertir con un mensaje |
revert("Not allowed"); | Abortar incondicionalmente |
error Insufficient(uint available, uint requested); | Declarar un error personalizado (más barato que los strings) |
revert Insufficient(balance, amount); | Revertir con un error personalizado |
assert(total == a + b); | Comprobar un invariante que nunca debe fallar |
try token.transfer(to, amt) returns (bool ok) { ... } catch { ... } | Gestionar una llamada externa que falla |
Eventos
Los eventos escriben logs a los que las apps off-chain pueden suscribirse; no se pueden leer desde los contratos.
| Sintaxis | Significado |
|---|---|
event Transfer(address indexed from, address indexed to, uint value); | Declarar un evento |
emit Transfer(msg.sender, to, amount); | Emitirlo |
indexed | Parámetro filtrable (hasta 3 por evento) |
event Log(string message); | Cualquier tipo ABI puede registrarse en un log |
Ether, direcciones y variables globales
El contexto de la transacción viene de msg, block y tx.
| Sintaxis | Significado |
|---|---|
msg.sender | Dirección que llamó a esta función |
msg.value | Wei enviados con la llamada (requiere payable) |
block.timestamp | Hora del bloque actual (segundos desde epoch) |
block.number | Altura del bloque actual |
tx.origin | La cuenta externa (EOA) que originó la tx (evítala para autenticación) |
address(this).balance | Saldo en Ether de este contrato |
payable(to).transfer(1 ether); | Enviar Ether; revierte si falla |
(bool ok, ) = to.call{value: amt}(""); | Envío de bajo nivel; devuelve un indicador de éxito |
receive() external payable {} | Se ejecuta en una transferencia simple de Ether |
fallback() external payable {} | Se ejecuta cuando ninguna función coincide |
keccak256(abi.encodePacked(a, b)) | Calcular el hash de valores |
abi.encode(x), abi.decode(data, (uint)) | Codificar / decodificar datos ABI |
Toda la sintaxis de Solidity que usas a diario, en una sola página. Esta cheat sheet de Solidity es una referencia rápida del lenguaje de smart contracts de Ethereum y de todas las cadenas EVM: declarar un contrato, elegir tipos, guardar datos en mappings y structs, escribir funciones con la visibilidad y mutabilidad correctas, y protegerlas con require, modifiers y eventos.
La sintaxis es la de Solidity 0.8, que comprueba el desbordamiento aritmético por defecto y funciona con Remix, Hardhat y Foundry. Copia lo que necesites o pruébalo en vivo en el playground de Solidity: escribe un contrato, compílalo y ejecútalo en una EVM en tu navegador.