Constantes
Las constantes son una forma de dar un nombre a valores compartidos y estáticos dentro de un module
o script
.
Las constantes deben ser conocidas en tiempo de compilación. El valor de la constante se almacena en el módulo compilado o script. Y cada vez que la constante se usa, se hace una nueva copia de ese valor.
Declaración
Sección titulada «Declaración»Las declaraciones de constantes comienzan con la palabra clave const
, seguida de un nombre, un tipo y un valor. Pueden existir en un script o módulo.
const <name>: <type> = <expression>;
Por ejemplo:
script { const MY_ERROR_CODE: u64 = 0;
fun main(input: u64) { assert!(input > 0, MY_ERROR_CODE); }}
module 0x42::example { const MY_ADDRESS: address = @0x42;
public fun permissioned(s: &signer) { assert!(std::signer::address_of(s) == MY_ADDRESS, 0); }}
Nomenclatura
Sección titulada «Nomenclatura»Las constantes deben comenzar con una letra mayúscula A
a Z
. Después de la primera letra, los nombres de constantes pueden contener guiones bajos _
, letras a
a z
, letras A
a Z
, o dígitos 0
a 9
.
script { const FLAG: bool = false; const MY_ERROR_CODE: u64 = 0; const ADDRESS_42: address = @0x42;}
Aunque puedes usar letras a
a z
en una constante, las pautas generales de estilo son usar solo letras mayúsculas A
a Z
, con guiones bajos _
entre cada palabra.
Esta restricción de nomenclatura de comenzar con A
a Z
está en lugar para dar espacio para futuras características del lenguaje. Puede o no ser removida más tarde.
Visibilidad
Sección titulada «Visibilidad»Las constantes public
no están actualmente soportadas. Los valores const
pueden ser usados solo en el módulo que los declara.
Expresiones Válidas
Sección titulada «Expresiones Válidas»Actualmente, las constantes están limitadas a los tipos primitivos bool
, u8
, u16
, u32
, u64
, u128
, u256
, address
, y vector<u8>
. El soporte futuro para otros valores vector
(además de los literales estilo “string”) vendrá más tarde.
Valores
Sección titulada «Valores»Comúnmente, las const
se asignan un valor simple, o literal, de su tipo. Por ejemplo:
script { const MY_BOOL: bool = false; const MY_ADDRESS: address = @0x70DD; const BYTES: vector<u8> = b"hello world"; const HEX_BYTES: vector<u8> = x"DEADBEEF";}
Expresiones Complejas
Sección titulada «Expresiones Complejas»Además de literales, las constantes también pueden incluir expresiones más complejas, siempre que el compilador pueda reducirlas a un valor en tiempo de compilación.
Actualmente, las expresiones de igualdad, todas las operaciones booleanas, y todas las operaciones de enteros aritméticos y bit a bit pueden ser usadas.
script { const RULE: bool = true && false; const CAP: u64 = 10 * 100 + 1; const SHIFTY: u8 = { (1 << 1) * (1 << 2) * (1 << 3) * (1 << 4) }; const HALF_MAX: u128 = 340282366920938463463374607431768211455 / 2; const REM: u256 = 57896044618658097711785492504343953926634992332820282019728792003956564819968 % 654321; const EQUAL: bool = 1 == 1;}
Si la operación resultaría en un error en tiempo de ejecución, como división por cero o desbordamiento de enteros, el compilador abortará en lugar de asignar el valor.
script { const DIV_BY_ZERO: u64 = 1 / 0; // error! const SHIFT_BY_A_LOT: u64 = 1 << 100; // error! const NEGATIVE_U64: u64 = 0 - 1; // error!}
Note que las constantes no pueden referirse a otras constantes actualmente.
Ejemplos Prácticos
Sección titulada «Ejemplos Prácticos»Códigos de Error
Sección titulada «Códigos de Error»module 0x42::errors { // Códigos de error estándar const E_NOT_AUTHORIZED: u64 = 1; const E_INSUFFICIENT_BALANCE: u64 = 2; const E_INVALID_AMOUNT: u64 = 3; const E_ACCOUNT_NOT_FOUND: u64 = 4; const E_ALREADY_EXISTS: u64 = 5;
public fun check_authorization(user: address, admin: address) { assert!(user == admin, E_NOT_AUTHORIZED); }}
Configuración del Sistema
Sección titulada «Configuración del Sistema»module 0x42::config { // Límites del sistema const MAX_SUPPLY: u64 = 1_000_000_000; // 1 billón de tokens const MIN_STAKE: u64 = 100; // mínimo para staking const DECIMALS: u8 = 8; // precisión decimal const ADMIN_ADDRESS: address = @0x42; // dirección del administrador
// Tarifas (en puntos básicos: 100 = 1%) const TRANSFER_FEE_BPS: u64 = 25; // 0.25% const STAKE_FEE_BPS: u64 = 50; // 0.5%
public fun get_transfer_fee(): u64 { TRANSFER_FEE_BPS } public fun get_min_stake(): u64 { MIN_STAKE }}
Constantes Matemáticas
Sección titulada «Constantes Matemáticas»module 0x42::math { // Constantes matemáticas (escaladas para enteros) const PI_SCALED: u64 = 314159265359; // π * 10^11 const E_SCALED: u64 = 271828182846; // e * 10^11 const SQRT_2_SCALED: u64 = 141421356237; // √2 * 10^11
// Multiplicadores de tiempo const SECONDS_PER_MINUTE: u64 = 60; const SECONDS_PER_HOUR: u64 = 60 * 60; const SECONDS_PER_DAY: u64 = 24 * 60 * 60; const SECONDS_PER_WEEK: u64 = 7 * 24 * 60 * 60;
public fun days_to_seconds(days: u64): u64 { days * SECONDS_PER_DAY }}
Estados y Flags
Sección titulada «Estados y Flags»module 0x42::status { // Estados de cuenta const STATUS_ACTIVE: u8 = 1; const STATUS_SUSPENDED: u8 = 2; const STATUS_CLOSED: u8 = 3;
// Flags de permisos (usando potencias de 2 para bitwise operations) const PERMISSION_READ: u64 = 1; // 2^0 const PERMISSION_WRITE: u64 = 2; // 2^1 const PERMISSION_EXECUTE: u64 = 4; // 2^2 const PERMISSION_ADMIN: u64 = 8; // 2^3
public fun has_permission(user_permissions: u64, required: u64): bool { (user_permissions & required) == required }
public fun grant_permission(permissions: u64, new_permission: u64): u64 { permissions | new_permission }}
Límites de Protocolo
Sección titulada «Límites de Protocolo»module 0x42::limits { // Límites de transacción const MAX_TRANSACTION_SIZE: u64 = 65_536; // 64 KB const MAX_GAS_LIMIT: u64 = 1_000_000; // 1M gas units const MIN_GAS_PRICE: u64 = 100; // 100 gas units por precio
// Límites de validador const MAX_VALIDATORS: u64 = 100; const MIN_STAKE_TO_VALIDATE: u64 = 1_000_000; // 1M tokens const EPOCH_LENGTH: u64 = 3600; // 1 hora en segundos
// Límites de red const MAX_CONNECTIONS: u64 = 1000; const CONNECTION_TIMEOUT: u64 = 30; // 30 segundos}
Versiones y Compatibilidad
Sección titulada «Versiones y Compatibilidad»module 0x42::version { // Versión del protocolo const MAJOR_VERSION: u64 = 1; const MINOR_VERSION: u64 = 2; const PATCH_VERSION: u64 = 3;
// Compatibilidad const MIN_SUPPORTED_VERSION: u64 = 1_0_0; // version 1.0.0 const CURRENT_VERSION: u64 = 1_2_3; // version 1.2.3
public fun get_version(): (u64, u64, u64) { (MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION) }
public fun is_compatible(version: u64): bool { version >= MIN_SUPPORTED_VERSION }}
Buenas Prácticas
Sección titulada «Buenas Prácticas»1. Usa Nombres Descriptivos
Sección titulada «1. Usa Nombres Descriptivos»// ✓ Bueno: nombres claros y descriptivosconst MAX_SUPPLY: u64 = 1_000_000;const TRANSFER_FEE_BPS: u64 = 25;const E_INSUFFICIENT_BALANCE: u64 = 1;
// ✗ Poco claro: nombres crípticosconst X: u64 = 1_000_000;const FEE: u64 = 25;const ERR1: u64 = 1;
2. Agrupa Constantes Relacionadas
Sección titulada «2. Agrupa Constantes Relacionadas»// ✓ Bueno: constantes agrupadas por propósitomodule errors { const E_NOT_AUTHORIZED: u64 = 1; const E_INSUFFICIENT_BALANCE: u64 = 2; const E_INVALID_AMOUNT: u64 = 3;}
module limits { const MAX_SUPPLY: u64 = 1_000_000; const MIN_DEPOSIT: u64 = 100; const MAX_WITHDRAWAL: u64 = 10_000;}
3. Usa Separadores de Miles
Sección titulada «3. Usa Separadores de Miles»// ✓ Bueno: legible con separadoresconst LARGE_NUMBER: u64 = 1_000_000_000;const WALLET_LIMIT: u64 = 500_000;
// ✗ Difícil de leerconst LARGE_NUMBER: u64 = 1000000000;const WALLET_LIMIT: u64 = 500000;
4. Documenta Valores Complejos
Sección titulada «4. Documenta Valores Complejos»// ✓ Bueno: documentación clara/// Tarifa de transferencia en puntos básicos (100 = 1%)const TRANSFER_FEE_BPS: u64 = 25; // 0.25%
/// Tiempo de bloqueo en segundos (7 días)const LOCK_PERIOD: u64 = 7 * 24 * 60 * 60;
/// Dirección del tesoro del protocoloconst TREASURY_ADDRESS: address = @0x1234;
5. Usa Constantes para Valores Mágicos
Sección titulada «5. Usa Constantes para Valores Mágicos»// ✓ Bueno: reemplaza números mágicos con constantesconst PERCENTAGE_DENOMINATOR: u64 = 100;
public fun calculate_fee(amount: u64, rate: u64): u64 { amount * rate / PERCENTAGE_DENOMINATOR}
// ✗ Número mágico sin explicaciónpublic fun calculate_fee(amount: u64, rate: u64): u64 { amount * rate / 100 // ¿qué significa 100?}
6. Mantén Consistencia en Nomenclatura
Sección titulada «6. Mantén Consistencia en Nomenclatura»// ✓ Bueno: patrón consistente para erroresconst E_NOT_AUTHORIZED: u64 = 1;const E_INSUFFICIENT_BALANCE: u64 = 2;const E_INVALID_AMOUNT: u64 = 3;
// ✓ Bueno: patrón consistente para límitesconst MAX_SUPPLY: u64 = 1_000_000;const MAX_DEPOSIT: u64 = 10_000;const MAX_WITHDRAWAL: u64 = 5_000;