Skip to main contentA-REX Foundation

Whitepaper · 08

Marco de seguridad

Modelo de amenazas, invariantes, control de acceso, frontera de confianza de los hooks, gestión de las claves de cumplimiento, actualizaciones seguras y estado de auditoría de la implementación de referencia de A-REX Core.

La seguridad en un párrafo

Todo cambio de saldo del token de referencia pasa por un único punto (_update). El orden de evaluación es fijo y un bloqueo antirreentrada cubre toda la secuencia de reglas externas (hooks). La autoridad depende de roles y nunca de los saldos, el almacenamiento sigue ERC-7201 y la superficie es pequeña: ocho funciones externas que modifican el estado, además de las de ERC-1155. Las capacidades más sensibles (congelar, transferencia forzosa, administrar hooks, actualizar) son roles separados, pensados para multifirmas y timelocks, y cada uso genera un evento.

Invariantes

InvarianteQuién la garantizaCómo se prueba
totalSupply(id) es igual a la suma de los saldos de idERC1155Supply de OpenZeppelin; transform quema y luego acuña a través de _updatepruebas de linaje (dividir, fusionar, procesar)
status == 255 es un estado finalsetBatchStatus revierte con ARexInvalidStatusTransitionpruebas de estado
Un lote retirado no se puede acuñar ni transferir, solo quemar_updateprueba de lote retirado
amount ≤ balance − frozen cuando el movimiento lo inicia el titular_update; forcedTransfer baja frozen a balance − amountpruebas de congelamiento y de transferencia forzosa
Ningún hook puede volver a entrar en una función que modifica saldosun bloqueo en el almacenamiento se activa antes de las verificaciones y se libera después de las notificacionesprueba con ReentrantHook
Los hooks se evalúan en el orden en que se registraron; quitar uno no altera el ordendesplazamiento del arreglo en removeHookprueba de orden
Una operación rechazada no cambia ningún saldo ni emite transferenciaslas verificaciones corren antes de super._updateprueba de rechazo (el contador de ejecuciones no cambia)
Tener saldo nunca da autoridadcada función que modifica el estado exige un rol o una aprobación de ERC-1155pruebas de «tener tokens no habilita nada»
canTransfer == (transferCheck == 0)canTransfer se define exactamente asípruebas de conformidad

Modelo de amenazas

Actores y capacidades

ActorPuedeNo puede
Titulartransferir unidades no congeladas a cuentas habilitadas; quemar; reagrupar en lotes del mismo producto y unidad sin alterar la cantidad totalcambiar el estado, acuñar, procesar hacia otro producto, mover unidades congeladas
Operador aprobadolo mismo que el titular, sobre la cuenta que lo aprobónada que el titular no pueda hacer
ISSUER_ROLEcrear lotesmover tokens de otras cuentas
TRANSFORMER_ROLEprocesar tokens que tiene o para los que tiene aprobacióntransformar tokens sin aprobación
STATUS_ROLEcambiar el estado (incluido retirar el lote) y actualizar los metadatosmover tokens
ENFORCER_ROLEcongelar cualquier cantidad; forzar cualquier transferenciasaltarse los hooks (se ejecutan con OP_FORCED_TRANSFER)
HOOK_ADMIN_ROLEagregar y quitar hookscambiar saldos directamente
PAUSER_ROLEdetener todo, salvo las transferencias forzosas—
UPGRADER_ROLEreemplazar la implementación— (es control total; consulta la gestión de claves)
Contrato de hookrechazar operaciones; observarlas; responder si una cuenta está habilitadavolver a entrar; cambiar saldos

Escenarios

Hook malicioso o con errores (denegación de servicio). Un hook que siempre rechaza bloquea todas las transferencias del token, y uno que revierte en check tiene el mismo efecto. Mitigación: HOOK_ADMIN_ROLE puede quitar cualquier hook en cualquier momento sin alterar el orden de los demás. PAUSER_ROLE puede detener el token mientras se investiga. Las transferencias forzosas siguen funcionando, así que no se pierden los controles de cumplimiento. Al registrar un hook, el token verifica que soporte ERC-165 y que sus flags no sean cero, y rechaza las EOA. Recomendación: audita los hooks antes de registrarlos, mantén pocos y pon al administrador detrás de un timelock para que cualquier cambio sea visible antes de entrar en vigor.

Reentrada desde un hook. El onExecuted de un hook vuelve a llamar a safeTransferFrom. Mitigación: el bloqueo hace que la llamada revierta con ARexReentrantCall. Ten en cuenta que el callback de recepción de ERC-1155 (onERC1155Received) corre después de liberar el bloqueo, como en cualquier token ERC-1155. Para ese momento, el estado del token ya es definitivo.

Clave de cumplimiento comprometida. Quien tenga ENFORCER_ROLE puede mover cualquier token. Mitigación: una multifirma con un procedimiento documentado (orden judicial, contrato de prenda, aviso de sanciones). Cada acción emite ForcedTransfer o Frozen, y los hooks pueden exigir una referencia a la orden en los datos de la transferencia, porque OP_FORCED_TRANSFER no está exenta de hooks. Para medidas de cumplimiento que no sean urgentes, considera un timelock.

Clave de actualización comprometida. El control es total. Mitigación: multifirma con timelock, validaciones de actualización de OpenZeppelin en CI y almacenamiento ERC-7201 para evitar errores de layout.

Abuso del estado. STATUS_ROLE puede retirar un lote que está en manos de otros. Es intencional: un almacén, un inspector o un regulador puede declarar que un lote no es apto. Los titulares deben saberlo. Mitigación: asigna este rol a una institución que rinda cuentas; cada cambio queda como evento con su motivo.

Fraude del emisor. ISSUER_ROLE puede crear un lote que no existe físicamente. El token no lo puede impedir, pero sí deja claro quién lo hizo (issuer, originRef, metadataHash). Además, con AttestationHook puedes exigir atestaciones (certificados o constancias verificables) de terceros independientes, como un almacén, un inspector o un registro, antes de cualquier transferencia.

Sustitución de metadatos. setBatchMetadata cambia el hash y la URI. Mitigación: la función exige un rol, y los eventos BatchMetadataUpdated y URI conservan el historial. Los documentos anteriores se pueden seguir verificando contra los hashes anteriores.

Front-running de transferCheck. Una verificación previa puede quedar desactualizada antes de que se ejecute la transacción, por ejemplo si cambia el estado de un hook. La transacción vuelve a evaluar todo; en el peor caso, revierte con un código preciso.

Gas griefing mediante hooks. Cada hook agrega una llamada externa por cada id afectado y por cada fase. Un hook con bucles sin límite puede encarecer tanto las transferencias que nadie pueda pagarlas. Mitigación: reglas para escribir hooks (check con costo acotado) y revisión antes de registrarlos.

Confianza en hooks actualizables. Un hook desplegado detrás de un proxy puede cambiar la política de transferencias sin que cambie nada en el token. Mitigación: protege las claves de administración de los hooks con el mismo cuidado que HOOK_ADMIN_ROLE y, en producción, prefiere hooks inmutables.

Modelo de control de acceso

El token usa AccessControl de OpenZeppelin con ocho roles, y el registro de atestaciones tiene uno más. DEFAULT_ADMIN_ROLE administra todos. Esta es la distribución recomendada para producción:

RolQuién lo tiene
DEFAULT_ADMIN_ROLE, UPGRADER_ROLE, HOOK_ADMIN_ROLEmultifirma de gobernanza detrás de un timelock
ENFORCER_ROLEmultifirma de cumplimiento (áreas de cumplimiento y legal)
PAUSER_ROLEclave de respuesta a incidentes (de acción rápida)
ISSUER_ROLE, STATUS_ROLE, TRANSFORMER_ROLEservicios operativos con privilegios mínimos y claves rotadas
ATTEST_ADMIN_ROLEentidad certificadora o plataforma

Por comodidad, initialize otorga todos los roles a un solo administrador. La checklist de despliegue exige redistribuirlos antes de pasar a producción.

Controles de cumplimiento y pausa

  • La pausa bloquea acuñaciones, transferencias, quemas y transformaciones. No bloquea las transferencias forzosas, de modo que una orden legal se puede ejecutar aunque haya un incidente en curso.
  • Las transferencias forzosas omiten canSend/canReceive y la verificación del saldo congelado, y bajan el monto congelado a lo que queda. Aun así, ejecutan los hooks con OP_FORCED_TRANSFER. Los hooks de referencia devuelven OK para esa operación; un hook que regule los controles de cumplimiento puede exigir referencias a la orden en data.
  • El monto congelado puede superar el saldo (ERC-7943), así que un gravamen puede cubrir depósitos futuros.

Actualizaciones seguras

  • UUPS; _authorizeUpgrade exige UPGRADER_ROLE.
  • Struct de almacenamiento con espacio de nombres ERC-7201; los campos nuevos solo se agregan al final.
  • Las validaciones del plugin de actualizaciones de OpenZeppelin corren en las pruebas y deben correr en CI antes de cualquier transacción de actualización.
  • El ajuste optimizer.runs = 1 por archivo mantiene la implementación dentro del límite de EIP-170. Si un cambio lo supera, la compilación emite una advertencia y el despliegue revierte.

Seguridad de dependencias y compilación

  • OpenZeppelin Contracts y Contracts-Upgradeable fijados en la versión 5.3.0; el lockfile está en el repositorio y CI usa npm ci.
  • Solidity 0.8.22, viaIR, EVM paris: no depende del almacenamiento transitorio y se puede desplegar en cadenas que aún no adoptaron Cancun.
  • No hay bibliotecas externas enlazadas ni delegatecall fuera del proxy UUPS.

Estado de la auditoría

  • 46 pruebas sobre la implementación de referencia, los hooks y las extensiones cubren todas las invariantes anteriores, incluida una ejecución aleatoria de invariantes con semilla fija.
  • Scripts del repositorio miden el gas y el tamaño de los contratos.
  • Una auditoría externa de ARexToken, ARexAttestations y los hooks de referencia es requisito declarado para un despliegue ancla en producción y para presentar el ERC (consulta Desarrollos futuros).
  • La verificación formal de las invariantes de la cadena de reglas está en la hoja de ruta. Las invariantes son lo bastante acotadas como para expresarlas como propiedades.

Riesgos residuales que el estándar no elimina

  • La existencia física y la calidad de un lote se atestan, no se demuestran. El token hace que cada afirmación tenga un responsable, no que sea verdadera.
  • La disponibilidad de los metadatos fuera de la cadena depende del almacenamiento elegido. El hash garantiza la integridad, no la disponibilidad.
  • La gobernanza de hooks y módulos es tan sólida como las claves que la controlan.