Skip to main content

Referencia Técnica

Documentación técnica detallada de la arquitectura interna de ISBE para desarrolladores avanzados.

Componentes Core

Los Componentes Core son las capacidades fundamentales que heredan automáticamente todos los contratos desplegados en ISBE.

Visión General

El Core agrupa las funcionalidades base del sistema:

  • Inicialización: Patrón seguro para proxies Diamond
  • Introspección: Detección de interfaces soportadas (ERC165)
  • Control de Acceso: Sistema RBAC integrado con DIDs
  • Propiedad: Gestión de propietario del contrato
  • Pausabilidad: Capacidad de pausa de emergencia
  • Utilidades: Validaciones y acceso a contexto blockchain

Todos estos componentes se agregan en Common, que actúa como clase base universal.

Common

Common agrega todas las capacidades Core. Todos los contratos ISBE heredan de Common.

contract MiCasoDeUso is Common {
// Tu contrato hereda automáticamente todas las capacidades Core
}

Inicialización de Proxies

ISBE usa el patrón Diamond Proxy (EIP-2535). Los proxies no pueden usar constructores, por lo que el Core proporciona inicialización segura.

bytes32 constant FACET_KEY = keccak256("MiToken.v1");

function initialize(string memory nombre)
external
initializer(FACET_KEY)
{
// Se ejecuta solo una vez por facet
}

El modificador initializer(_facetKey) garantiza ejecución única y previene re-inicializaciones.

Introspección de Interfaces

Implementa el estándar ERC165 para detección de interfaces. Permite consultar qué capacidades soporta un contrato:

bool soportaERC20 = contrato.supportsInterface(type(IERC20).interfaceId);

Los contratos registran automáticamente sus interfaces implementadas (ERC20, ERC721, AccessControl, etc.).

Control de Acceso (RBAC)

Sistema de control de acceso basado en roles integrado con identidades descentralizadas (DIDs).

Protección de Funciones:

modifier onlyRole(bytes32 _role) {
_checkRole(_role);
_;
}

Gestión de Roles:

// Otorgar/revocar roles por dirección (EOA)
function _grantRole(bytes32 role, address account) internal;
function _revokeRole(bytes32 role, address account) internal;

// Otorgar/revocar roles por DID
function _grantDidRole(bytes32 role, bytes32 did) internal;
function _revokeDidRole(bytes32 role, bytes32 did) internal;

// Verificar roles
function _hasRole(bytes32 role, address account) internal view returns (bool);
function _hasDidRole(bytes32 role, bytes32 did) internal view returns (bool);

Ejemplo de Uso:

contract MiCasoDeUso is Common {
bytes32 public constant OPERADOR_ROLE = keccak256("OPERADOR_ROLE");

function operar() external onlyRole(OPERADOR_ROLE) {
// Solo operadores pueden ejecutar
}
}

Nota: Los roles iniciales se configuran durante el despliegue del proxy (parámetros roles y members en deployUseCase). Las actualizaciones posteriores se realizan mediante AccessControlFacet (grantRole/revokeRole)

Integración DID: Los roles pueden asignarse tanto a direcciones Ethereum como a DIDs. Si una dirección tiene un DID asociado, se validan ambos automáticamente.

Gestión de Propiedad

Mecanismo de propiedad única del contrato. Solo el propietario puede ejecutar funciones protegidas.

modifier onlyOwner() {
_checkOwner();
_;
}

Funciones:

function _owner() internal view returns (address);
function _transferOwnership(address newOwner) internal;

Pausabilidad

Capacidad de pausar todas las operaciones del contrato en caso de emergencia.

modifier whenNotPaused() {
_requireNotPaused();
_;
}

Funciones:

function _paused() internal view returns (bool);
function _requireNotPaused() internal view;

Ejemplo:

function transfer(address to, uint256 amount) 
external
whenNotPaused
returns (bool)
{
// Bloqueado si el contrato está pausado
}

Todas las plantillas ISBE implementan pausabilidad automática en operaciones críticas.

Utilidades y Validaciones

Funciones de contexto blockchain y validaciones comunes.

Contexto Blockchain:

function _blockTimestamp() internal view returns (uint256);
function _blockChainId() internal view returns (uint256);
function _msgSender() internal view returns (address);
function _msgSig() internal view returns (bytes4);

Validaciones:

// Validaciones de contenido
function _checkAddressIsNotZero(address addr) internal pure;
function _checkBytes32IsNotZero(bytes32 hash) internal pure;
function _checkEmptyBytes(bytes memory code) internal pure;
function _checkEmptyString(string memory str) internal pure;
function _checkUintIsNotZero(uint256 value) internal pure;

// Comparaciones
function _equalStrings(string memory a, string memory b) internal pure returns (bool);
function _equalBytes(bytes memory a, bytes memory b) internal pure returns (bool);

// Validación temporal
function _checkValidDates(uint256 before, uint256 after) internal pure;

Resumen Componentes Core

ComponenteCapacidad
CommonClase base universal
Inicializacióninitializer(_facetKey)
IntrospecciónsupportsInterface()
Control de AccesoonlyRole(), integración DID
PropiedadonlyOwner()
PausabilidadwhenNotPaused()
UtilidadesValidaciones y contexto blockchain

Al heredar de Common, todos estos componentes están disponibles automáticamente.


Sistema de Identidad Descentralizada (DID)

ISBE usa identidades descentralizadas (DIDs) basadas en el estándar W3C, adaptadas para entornos permisionados con verificación institucional.

Qué es un DID

Un DID es un identificador único que representa una organización verificada en ISBE. Permite que múltiples wallets (empleados, dispositivos) operen bajo una misma identidad corporativa.

did:isbe:0x1234567890abcdef...

Ventajas vs Solo Direcciones

Direcciones EthereumDIDs en ISBE
Una dirección = una cuentaUn DID = múltiples wallets de una organización
Cambiar wallet = perder historialRotar wallets manteniendo identidad
Sin metadata verificadaInformación corporativa verificada
Sin gestión delegadaControladores autorizados

Creación de DIDs (Onboarding)

Importante: Los DIDs NO se auto-registran. ISBE los crea tras verificar la identidad corporativa.

Flujo de Onboarding:

  1. Organización solicita acceso a ISBE
  2. Verificación institucional (certificados cualificados, documentación legal)
  3. Firma de acuerdos contractuales
  4. ISBE admin crea el DID con rol ISBE_ROLE
  5. Se designan controladores autorizados (representantes legales)
// Solo ISBE admin
function insertFirstDidDocument(
bytes32 did,
string memory baseDocument,
bytes memory signature
) external onlyRole(ISBE_ROLE);

Componentes del DID

1. Controladores

Quién puede modificar el DID. Representantes legales autorizados de la organización.

// Añadir controlador
function addController(bytes32 did, bytes32 newController) external;

// Revocar controlador
function revokeController(bytes32 did, bytes32 controller) external;

// Consultar control
function checkController(bytes32 did, address account) external view returns (bool);

2. Verification Methods (Claves/Wallets)

Wallets de empleados asociadas al DID corporativo.

// Añadir wallet de empleado
function addVerificationMethod(
bytes32 did,
bytes32 vMethodId,
bytes memory publicKey
) external;

// Revocar wallet
function revokeVerificationMethod(bytes32 did, bytes32 vMethodId) external;

// Rotar wallet (cambiar antigua por nueva)
function rollVerificationMethod(
bytes32 did,
bytes32 oldVMethodId,
bytes32 newVMethodId,
bytes memory newPublicKey
) external;

3. Verification Relationships (Propósitos)

Define para qué sirve cada clave:

  • authentication: Login/autenticación
  • assertionMethod: Firma de documentos
  • keyAgreement: Cifrado
  • capabilityInvocation: Invocar permisos
// Asignar propósito a una clave
function addVerificationRelationship(
bytes32 did,
bytes32 vMethodId,
string memory relationship,
uint256 notBefore,
uint256 notAfter
) external;

Consultas

// ¿Está registrada esta dirección?
function isKnownDid(address account) external view returns (bool);

// ¿Qué DID tiene esta dirección?
function didOf(address account) external view returns (bytes32);

// Obtener DID Document actual
function getDidDocument(bytes32 did) external view returns (DidDocument memory);

// Obtener DID Document histórico
function getDidDocumentByTimestamp(bytes32 did, uint256 timestamp) external view
returns (DidDocument memory);

// Listar todos los DIDs (paginado)
function getDids(uint256 page, uint256 pageSize) external view
returns (bytes32[] memory);

Integración con Control de Acceso

ISBE integra DIDs con RBAC, permitiendo asignar roles a identidades (no solo direcciones).

Fallback Automático:

Cuando se verifica un rol:

  1. ¿La dirección tiene el rol? → Permitir
  2. Si no, obtener DID de esa dirección
  3. ¿El DID tiene el rol? → Permitir
  4. Si ninguno → Denegar
function hasRole(bytes32 role, address account) public view returns (bool) {
// 1. Verificar por dirección
if (_hasRoleByAddress(role, account)) return true;

// 2. Obtener DID
bytes32 did = didRegistry.didOf(account);
if (did == bytes32(0)) return false;

// 3. Verificar por DID
return _hasRoleByDid(role, did);
}

Ventajas:

  • Multiwallet: Un DID, múltiples empleados con acceso
  • Rotación de claves: Cambiar wallet sin perder roles
  • Recuperación: Añadir nueva wallet si se pierde una

Ejemplo: Un DID, Tres Wallets

DID Corporativo: did:isbe:empresa-abc
├─ Wallet CEO: 0x123...
├─ Wallet CFO: 0x456...
└─ Wallet Manager: 0x789...

Rol OPERATOR asignado al DID
→ Las 3 wallets tienen el rol automáticamente

Resumen Sistema de Identidad

ComponenteDescripción
DIDIdentidad corporativa única y verificada
OnboardingISBE crea DIDs tras verificación institucional
ControladoresRepresentantes legales que gestionan el DID
Verification MethodsWallets de empleados asociadas al DID
Verification RelationshipsPropósitos de cada wallet (auth, firma, etc.)
ConsultasResolución dirección → DID
Integración RBACRoles asignados a identidades, no solo direcciones

El sistema DID de ISBE combina la flexibilidad de identidades descentralizadas con la verificación institucional requerida en entornos regulados.


Patrón Diamond (EIP-2535)

El Patrón Diamond (EIP-2535) es la arquitectura obligatoria en ISBE para todos los contratos de negocio. Permite construir contratos modulares, actualizables y sin límites de tamaño mediante facets (módulos independientes).

Qué es el Patrón Diamond

Arquitectura que permite que un único contrato (diamond) enrute llamadas a múltiples módulos (facets):

Usuario → Diamond → Facet 1 (HashTimestamp)
├→ Facet 2 (AccessControl)
├→ Facet 3 (Pausable)
└→ Facet N (BusinessLogic)

Características:

  • Un punto de entrada: Dirección única del diamond
  • Múltiples facets: Funcionalidades modulares
  • Storage compartido: Todas las facets acceden al mismo storage
  • Actualizable: Sin cambiar dirección del contrato
  • Sin límites de tamaño: Supera el límite de 24KB de la EVM

Por qué Diamond en ISBE

ISBE adopta Diamond como único estándar.

Ventajas:

AspectoBeneficio
ModularidadCada funcionalidad es un módulo autocontenido
EscalabilidadSin límites de tamaño
UpgradeabilidadActualizar módulos sin migración
GobernanzaControl centralizado de cambios
Pausado globalTodas las facets pausables desde un punto
RBAC unificadoRoles y permisos gestionados centralmente
AuditoríaUna dirección, trazabilidad completa

Arquitectura Diamond en ISBE

1. Diamond Contract (Núcleo)

Recibe todas las llamadas y enruta a las facets mediante delegatecall:

abstract contract EIP2535 is FacetAddressResolver {
receive() external payable {}

fallback() external payable {
// Get facet from function selector
address facet = _resolveFacetAddress(msg.sig);

// Execute external function from facet using delegatecall
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}

function _resolveFacetAddress(bytes4 _sig) private view returns (address) {
address facet = _facetAddress(_sig);
require(facet != address(0), FunctionNotFound(_sig));
return facet;
}
}

2. Facets (Módulos)

FacetPropósito
DiamondLoupeFacetIntrospección (consultar estructura)
DiamondCutFacetGestión de facets (añadir/actualizar/eliminar)
Business Logic FacetsLógica específica del caso de uso

3. Diamond Storage

Storage compartido usando unstructured storage (slots únicos calculados con keccak256):

// Estructura del storage del diamond
struct DiamondStorage {
mapping(bytes4 => FacetAddressAndItemPosition) facetAddressAndSelectorPosition;
bytes4[] selectors;
mapping(bytes4 => FacetAddressAndItemPosition) facetAddressAndInterfacePosition;
bytes4[] interfaces;
}

// Posición fija del storage
bytes32 constant _DIAMOND_STORAGE_POSITION =
keccak256("isbe.contracts.diamond.storage");

function _diamondStorage()
private
pure
returns (DiamondStorage storage storage_)
{
bytes32 position = _DIAMOND_STORAGE_POSITION;
assembly {
storage_.slot := position
}
}

Storage de Facets: Cada facet usa su propio slot único para evitar colisiones:

struct MyFacetStorage {
mapping(bytes32 => uint256) data;
}

bytes32 constant _MY_FACET_STORAGE_POSITION =
keccak256("isbe.contracts.myfacet.storage");

function _myFacetStorage()
internal
pure
returns (MyFacetStorage storage storage_)
{
bytes32 position = _MY_FACET_STORAGE_POSITION;
assembly {
storage_.slot := position
}
}

Estructura de Facets en ISBE

Interfaz Obligatoria: IEIP2535Introspection

interface IEIP2535Introspection {
// Interfaces ERC-165 soportadas
function interfacesIntrospection() external pure returns (bytes4[] memory);

// Identificador único de la facet
function businessIdIntrospection() external pure returns (bytes32);

// Funciones expuestas
function selectorsIntrospection() external pure returns (bytes4[] memory);
}

Patrón Internal/External:

Las facets separan lógica interna de funciones públicas:

Internal: Storage y lógica interna con prefijo _

abstract contract HashTimestampInternal {
struct HashTimestampStorage {
mapping(bytes32 => uint256) hashTimestamps;
}

function _hashTimestampStorage()
internal pure
returns (HashTimestampStorage storage storage_)
{
bytes32 position = _HASH_TIMESTAMP_STORAGE_POSITION;
assembly {
storage_.slot := position
}
}

function _timestampHash(bytes32 _hash) internal {
uint256 timestamp = _blockTimestamp();
_hashTimestampStorage().hashTimestamps[_hash] = timestamp;
emit IHashTimestamp.HashTimestamped(_hash, msg.sender, timestamp);
}
}

External: Funciones públicas que usan las internas

abstract contract HashTimestamp is HashTimestampInternal {
function timestampHash(bytes32 _hash)
external
override
whenNotPaused
onlyRole(_HASH_TIMESTAMP_ROLE)
{
_timestampHash(_hash);
}
}

Facet: Combina external + introspección

contract HashTimestampFacet is HashTimestamp, IEIP2535Introspection {
function businessIdIntrospection() external pure returns (bytes32) {
return _HASH_TIMESTAMP_RESOLVER_KEY;
}

function selectorsIntrospection() external pure returns (bytes4[] memory) {
// ... retorna selectores
}
}

Patrón clave: Funciones externas usan métodos internos. NUNCA acceden directamente al storage.

Gestión de Facets (DiamondCut)

Operaciones:

enum ItemCutAction {
Add, // Agregar nuevos selectores
Replace, // Reemplazar selectores existentes
Remove // Eliminar selectores
}

struct ItemCut {
address facetAddress;
ItemCutAction action;
bytes4[] items;
}

Funciones:

interface IDiamondCut {
function diamondCut(
ItemCut[] calldata _diamondCut,
address _init,
bytes calldata _calldata
) external;
}

Seguridad: Solo DEFAULT_ADMIN_ROLE puede ejecutar diamondCut.

Introspección (DiamondLoupe)

Consultar estructura del diamond:

interface IDiamondLoupe {
function facets() external view returns (Facet[] memory);
function facetFunctionSelectors(address facet) external view returns (bytes4[] memory);
function facetAddresses() external view returns (address[] memory);
function facetAddress(bytes4 selector) external view returns (address);
}

Interacción con Diamond

Desde Solidity:

import {IHashTimestamp} from '@isbe/contracts/hashtimestamp/IHashTimestamp.sol';

IHashTimestamp hashRegistry = IHashTimestamp(diamondAddress);
hashRegistry.timestampHash(hash);

Desde Web3/Ethers:

const diamondAbi = [...hashTimestampAbi, ...accessControlAbi];
const diamond = new ethers.Contract(diamondAddress, diamondAbi, signer);
await diamond.timestampHash(documentHash);

Comparación con Otros Patrones

CaracterísticaStandaloneProxy UUPSDiamond
Tamaño máximo24KB24KBIlimitado
ActualizaciónMigraciónMono-implementaciónMulti-facet granular
DirecciónCambiaFijaFija
ModularidadBajaBajaAlta
IntrospecciónNoLimitadaCompleta

Resumen Diamond

AspectoDescripción
ArquitecturaUn diamond + múltiples facets
StorageUnstructured, compartido
ActualizaciónGranular, sin cambio de dirección
TamañoIlimitado
IntrospecciónCompleta (DiamondLoupe)
Obligatorio en ISBESí, único patrón permitido

Diamond permite a ISBE mantener control centralizado de gobernanza con máxima flexibilidad modular.


Sistema de Gobernanza

El Sistema de Gobernanza de ISBE es el contrato central que controla el despliegue y gestión de todos los casos de uso en la red mediante el patrón Diamond (EIP-2535).

Visión General

ISBE utiliza una arquitectura de gobernanza centralizada:

  • Diamond de Gobernanza: Contrato central que coordina toda la red
  • Diamonds de Casos de Uso: Cada aplicación/organización tiene su propio diamond independiente
  • Facets: Módulos reutilizables desplegados mediante factories

Principios:

  1. Centralización: Un único diamond de gobernanza coordina toda la red
  2. Modularidad: Casos de uso independientes mediante patrón Diamond
  3. Control de Acceso: Roles específicos para cada operación
  4. Seguridad: Pausado global y gestión centralizada de DIDs

Capacidades del Diamond de Gobernanza

Factories (Despliegue):

  • BusinessLogicFactory: Despliega y versiona facets reutilizables
  • ConfigurationManagement: Crea configuraciones (conjuntos de facets)
  • ProxyFactory: Despliega diamonds de casos de uso

Gestión:

  • AccessControl: Control de roles y permisos
  • DiamondCut/Loupe: Gestión e introspección del diamond
  • GlobalPause: Pausado de emergencia de cualquier caso de uso
  • DidRegistry: Registro centralizado de identidades (DIDs)
  • ENS: Sistema de nombres descentralizado

Roles

Roles de Gobernanza:

  • GOVERNANCE_MANAGER_ROLE: Gestiona el diamond de gobernanza
  • BUSINESS_LOGIC_DEPLOYER_ROLE: Despliega facets mediante factory
  • GOVERNANCE_CONFIGURATION_MANAGER_ROLE: Crea configuraciones
  • PROXY_DEPLOYER_ROLE: Despliega casos de uso
  • ISBE_PAUSER_ROLE: Pausado global de emergencia
  • DID_REGISTRY_ROLE: Gestiona DIDs (onboarding institucional)
  • DEFAULT_ADMIN_ROLE: Administración de roles

Roles en Casos de Uso:

  • DEFAULT_ADMIN_ROLE: Admin local del caso de uso
  • ISBE_ROLE: Representante de gobernanza (inmutable)
  • PAUSER_ROLE: Pausado local
  • Roles específicos: Según las facets incluidas

ISBE_ROLE: Este rol es inmutable y garantiza que gobernanza siempre mantiene control sobre los casos de uso.

Cómo Funciona

1. Despliegue de Facets

ISBE despliega facets mediante la BusinessLogicFactory:

  • Cada facet se identifica con un businessId único
  • El sistema versiona automáticamente: misma facet → v1, v2, v3...
  • Las facets son módulos reutilizables que implementan funcionalidad específica

2. Configuraciones

Las configuraciones son conjuntos predefinidos de facets:

  • Se crean mediante ConfigurationManagement
  • Ejemplo: Config "Trazabilidad" = HashTimestamp + Pausable + AccessControl
  • También se versionan automáticamente al actualizarse

3. Despliegue de Casos de Uso

La ProxyFactory crea diamonds de casos de uso:

  • Se selecciona una configuración existente
  • Se añaden automáticamente facets de gobernanza
  • Se configuran roles iniciales
  • Resultado: Diamond completo listo para usar

4. Gestión Continua

  • Pausado local: Cada caso de uso puede pausarse individualmente
  • Pausado global: Gobernanza puede pausar cualquier caso de uso (emergencias)
  • DIDs: Registro centralizado consultable por todos los casos de uso

Resumen Gobernanza

AspectoDescripción
ArquitecturaDiamond central de gobernanza coordina todos los casos de uso
FactoriesBusinessLogic, Configuration, Proxy - despliegan facets y casos de uso
RolesControl granular: GOVERNANCE_MANAGER, BUSINESS_LOGIC_DEPLOYER, PROXY_DEPLOYER, etc.
ConfiguracionesConjuntos predefinidos de facets, versionados automáticamente
SeguridadPausado local/global, roles inmutables (ISBE_ROLE), DIDs centralizados
ModularidadPatrón Diamond (EIP-2535) permite facets ilimitadas y actualizables

El sistema de gobernanza proporciona despliegue controlado y gestión centralizada de toda la red ISBE.


¿Tienes dudas frecuentes sobre el desarrollo en ISBE?

Ir a Preguntas Frecuentes →