Saltearse al contenido

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.

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);
}
}

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.

Las constantes public no están actualmente soportadas. Los valores const pueden ser usados solo en el módulo que los declara.

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.

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";
}

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.

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);
}
}
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 }
}
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
}
}
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
}
}
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
}
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
}
}
// ✓ Bueno: nombres claros y descriptivos
const MAX_SUPPLY: u64 = 1_000_000;
const TRANSFER_FEE_BPS: u64 = 25;
const E_INSUFFICIENT_BALANCE: u64 = 1;
// ✗ Poco claro: nombres crípticos
const X: u64 = 1_000_000;
const FEE: u64 = 25;
const ERR1: u64 = 1;
// ✓ Bueno: constantes agrupadas por propósito
module 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;
}
// ✓ Bueno: legible con separadores
const LARGE_NUMBER: u64 = 1_000_000_000;
const WALLET_LIMIT: u64 = 500_000;
// ✗ Difícil de leer
const LARGE_NUMBER: u64 = 1000000000;
const WALLET_LIMIT: u64 = 500000;
// ✓ 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 protocolo
const TREASURY_ADDRESS: address = @0x1234;
// ✓ Bueno: reemplaza números mágicos con constantes
const PERCENTAGE_DENOMINATOR: u64 = 100;
public fun calculate_fee(amount: u64, rate: u64): u64 {
amount * rate / PERCENTAGE_DENOMINATOR
}
// ✗ Número mágico sin explicación
public fun calculate_fee(amount: u64, rate: u64): u64 {
amount * rate / 100 // ¿qué significa 100?
}
// ✓ Bueno: patrón consistente para errores
const E_NOT_AUTHORIZED: u64 = 1;
const E_INSUFFICIENT_BALANCE: u64 = 2;
const E_INVALID_AMOUNT: u64 = 3;
// ✓ Bueno: patrón consistente para límites
const MAX_SUPPLY: u64 = 1_000_000;
const MAX_DEPOSIT: u64 = 10_000;
const MAX_WITHDRAWAL: u64 = 5_000;