Skip to main content

Desarrollo de Contratos Custom

Esta guía está dirigida a desarrolladores que necesitan implementar lógica de negocio personalizada que va más allá de las plantillas estándar disponibles en ISBE.

Cuándo necesitas un contrato custom

Usa una Plantilla si

  • Tu caso de uso se ajusta a alguna de las plantillas disponibles
  • No necesitas lógica compleja más allá de lo que ofrece la plantilla
  • Quieres desplegar rápidamente sin proceso de conformidad
  • Prefieres simplificar tiempo de desarrollo

Plantillas disponibles:

  • ERC20 - Tokens fungibles (utilidad, puntos, créditos)
  • ERC721 - Tokens no fungibles (certificados, activos únicos)
  • ERC3643 - Tokens regulados (instrumentos financieros)
  • AssetEventTracker - Trazabilidad de eventos
  • HashTimestamp - Sellado temporal de documentos

Ver Plantillas disponibles

Desarrolla Custom si

  • Necesitas lógica de negocio específica que no existe en plantillas
  • Requieres combinación de funcionalidades no estándar
  • Tu caso de uso tiene reglas de negocio particulares

Ejemplos de casos custom:

  • Sistema de votación con reglas específicas
  • Marketplace con lógica de subasta personalizada
  • Contrato de seguros con cálculo de primas específico
  • Sistema de préstamos con condiciones particulares
  • Gestión de activos con workflow complejo

Requisitos de Conformidad

El proceso de conformidad garantiza que los contratos inteligentes desplegados en ISBE cumplan con los estándares técnicos, de seguridad y arquitectónicos establecidos.

Nota sobre responsabilidad: La responsabilidad sobre el comportamiento funcional y la lógica de negocio del contrato recae en el proveedor del caso de uso. ISBE verifica:

  • Controles técnicos mínimos de seguridad
  • Conformidad con los estándares arquitectónicos de ISBE
  • Correcta implementación de controles de acceso y pausabilidad

Controles Técnicos Obligatorios

Todo contrato que se desee homologar en ISBE debe cumplir los siguientes controles técnicos. Estos controles son necesarios tanto para la seguridad básica como para la compatibilidad con la arquitectura de ISBE.

1. Control de Acceso (RBAC)

Tu contrato debe implementar roles claros basándose en el sistema de control de acceso de ISBE.

ISBE proporciona el sistema de roles. Solo necesitas usar el modificador onlyRole en tus funciones:

contract MiContrato {
function operacionSensible() external onlyRole(_OPERADOR_ROLE) {
// Tu lógica
}

function emitir(address destinatario, uint256 cantidad)
external
onlyRole(_EMISOR_ROLE)
{
// Tu lógica de emisión
}
}

Requisitos:

  • Aplicación del principio de mínimo privilegio
  • Documentación clara de roles y permisos asociados
  • Mecanismos de revocación y rotación de roles

2. Pausabilidad

Las funciones críticas deben poder pausarse mediante el sistema centralizado de pausas de ISBE.

ISBE proporciona el sistema de pausas. Solo necesitas usar el modificador whenNotPaused en tus funciones críticas:

contract MiContrato {
// Operaciones críticas protegidas
function emitir(address destinatario, uint256 cantidad)
external
whenNotPaused
onlyRole(_EMISOR_ROLE)
{
// Tu lógica de emisión
}

function transferir(address destinatario, uint256 cantidad)
external
whenNotPaused
{
// Tu lógica de transferencia
}
}

Funciones que deben estar protegidas:

  • Emisión de tokens
  • Transferencias
  • Cambios de parámetros críticos
  • Operaciones sobre fondos
  • Todas las funciones que modifiquen estado crítico

3. Integridad del Storage

El layout de almacenamiento es crítico para la arquitectura de ISBE. Tu contrato debe usar unstructured storage para evitar colisiones.

Requisito fundamental: Debes implementar tu storage usando el patrón unstructured storage para garantizar la compatibilidad con ISBE.

Ejemplo de unstructured storage:

contract MiContrato {
// Posición única calculada para evitar colisiones
bytes32 constant STORAGE_POSITION = keccak256("mi.caso.uso.storage");

struct MiStorage {
uint256 limiteMaximo;
uint256 limiteMinimo;
bool activo;
mapping(address => uint256) balances;
mapping(address => mapping(address => uint256)) allowances;
}

/**
* @dev Función interna para acceder al storage slot.
* @return storage_ Referencia a la estructura MiStorage en storage.
*/
function _miStorage() private pure returns (MiStorage storage storage_) {
bytes32 position = STORAGE_POSITION;
assembly {
storage_.slot := position
}
}

// Uso del storage
function getLimiteMaximo() external view returns (uint256) {
return _miStorage().limiteMaximo;
}

function setLimiteMaximo(uint256 _limite) external {
_miStorage().limiteMaximo = _limite;
}
}

Requisitos:

  • Implementación de unstructured storage obligatoria
  • Uso de slots de storage únicos calculados con keccak256
  • Sin colisiones de storage
  • No cambiar la posición del storage en actualizaciones
  • Documentación exhaustiva de la estructura de storage

Importante: El uso de unstructured storage es obligatorio para todos los contratos custom en ISBE.

4. Eventos de Trazabilidad

Emite eventos para todas las acciones sensibles.

Ejemplo de eventos:

contract MiContrato {
// Define eventos claros
event TokenEmitido(address indexed destinatario, uint256 cantidad, address indexed emisor);
event ConfiguracionActualizada(uint256 valorAnterior, uint256 valorNuevo, address indexed admin);
event RolAsignado(bytes32 indexed rol, address indexed cuenta, address indexed admin);
event Pausado(address indexed cuenta);
event Despausado(address indexed cuenta);

function emitir(address destinatario, uint256 cantidad)
external
onlyRole(EMISOR_ROLE)
whenNotPaused
{
balances[destinatario] += cantidad;
emit TokenEmitido(destinatario, cantidad, msg.sender);
}

function actualizarLimite(uint256 nuevoLimite)
external
onlyRole(DEFAULT_ADMIN_ROLE)
{
uint256 anterior = limiteMaximo;
limiteMaximo = nuevoLimite;
emit ConfiguracionActualizada(anterior, nuevoLimite, msg.sender);
}
}

Requisitos:

  • Eventos en acciones sensibles y cambios de estado
  • Registro de cambios de rol y permisos
  • Eventos de pausa y reactivación
  • Información suficiente para auditoría posterior

5. Pruebas y Análisis

Debes aportar evidencia de calidad del código.

Ejemplo de tests unitarios:

describe("MiContrato", function () {
describe("Control de acceso", function () {
it("Solo EMISOR_ROLE puede emitir tokens", async function () {
await expect(
contrato.connect(usuario).emitir(destino, 100)
).to.be.revertedWith("AccessControl");
});
});

describe("Pausabilidad", function () {
it("No permite operaciones cuando está pausado", async function () {
await contrato.pause();
await expect(
contrato.emitir(destino, 100)
).to.be.revertedWith("Pausable: paused");
});
});
});

Requisitos:

  • Tests unitarios y de integración
  • Cobertura de código en rutas críticas
  • Análisis estático sin hallazgos críticos abiertos (Slither, Mythril, etc.)
  • Documentación de casos de prueba

6. Build Reproducible

Proporciona toda la información para recompilar tu contrato de forma determinista.

Ejemplo de configuración:

{
"compiler": {
"version": "0.8.20",
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
}
}
}
}

Incluye:

  • Versión exacta de Solidity
  • Flags de compilación
  • metadata.json
  • Dependencias (package.json, lock file)
  • Equivalencia verificable entre bytecode y código fuente

Buenas Prácticas Recomendadas

  • Separación de lógica: Si tu contrato es complejo, separa la lógica en módulos para facilitar la adaptación
  • Cumplimiento GDPR: No almacenar ni exponer datos personales innecesarios
  • Transparencia: Facilitar verificación pública (BlockScout, Sourcify) y emisión de logs relevantes

Niveles de Conformidad

ISBE establece tres niveles de conformidad basados en la evidencia aportada:

Nivel C - Conformidad Mínima

  • Tests unitarios y de integración aprobados
  • Análisis estático sin hallazgos críticos
  • Controles de acceso (RBAC) verificados
  • Pausabilidad implementada
  • Build reproducible

Nivel B - Conformidad Avanzada

  • Todo lo incluido en Nivel C
  • Pruebas de propiedades e invariantes adicionales

Nivel A - Conformidad Certificada

  • Todo lo incluido en Nivel B
  • Auditoría externa de seguridad

Dimensiones de Cumplimiento

El proceso evalúa cuatro dimensiones principales que aseguran tanto la seguridad como la correcta integración en la arquitectura ISBE:

1. Cumplimiento Técnico - Arquitectura

Requisitos técnicos de ISBE:

  • Integridad del storage: Implementación de unstructured storage sin colisiones
  • Selectores únicos: Funciones con selectores no conflictivos
  • Sin funciones ocultas: Transparencia total en capacidades y upgrades
  • Gestión de upgrades: Compatible con los procesos de actualización de ISBE

2. Cumplimiento de Gobernanza ISBE

Tu contrato se integrará con el sistema de gobernanza de ISBE:

  • Control de acceso (RBAC): Uso correcto de roles con onlyRole
  • Pausabilidad gestionada: El sistema de pausas de ISBE controlará tus funciones críticas
  • Control de upgrades: Los cambios seguirán el proceso de gobernanza de ISBE
  • Sin puertas traseras: Prohibidas funciones de administración ocultas

3. Cumplimiento de Seguridad Mínima

  • Tests unitarios y de integración
  • Compilación reproducible y verificable
  • Análisis estático sin hallazgos críticos
  • Cobertura de código en rutas críticas

4. Cumplimiento Normativo Europeo

  • GDPR: No exponer ni almacenar datos personales innecesarios
  • Normativa aplicable: Cumplimiento de regulación según el tipo y uso del activo digital
  • eIDAS2: Identidad digital y trazabilidad
  • NIS2: Resiliencia operativa y ciberseguridad

Flujo del Proceso de Homologación

1. Registro de Solicitud

El proveedor entrega:

  • Formulario de solicitud completado
  • Repositorio con código fuente (público o privado)
  • Commit/branch específico
  • Metadatos de compilación (versión Solidity, flags)
  • Documentación del storage unstructured: Slots utilizados y estructura
  • Scripts de despliegue: Scripts completos de despliegue
  • Resultados de tests unitarios
  • Documentación de roles y permisos

Requisitos de entrega:

  • Contrato con código fuente completo
  • Storage usando patrón unstructured
  • Scripts de despliegue
  • Política de versionado (latest o versión específica)

Salida: ID de expediente, checklist inicial

2. Evaluación Técnica

Verificación de controles mínimos y conformidad con arquitectura de ISBE:

  • Ejecución de tests unitarios y de integración
  • Análisis estático del código
  • Verificación de RBAC y pausabilidad
  • Validación de implementación de unstructured storage
  • Verificación de selectores de función (sin colisiones)
  • Validación de eventos de trazabilidad
  • Verificación de scripts de despliegue

Análisis de conformidad: ISBE evalúa si tu contrato:

  • Está correctamente implementado
  • Usa unstructured storage adecuadamente
  • No tiene conflictos de selectores
  • Está integrado correctamente con la gobernanza

Salida: Reporte de tests, informe de hallazgos, checklist firmado

3. Verificación de Build

  • Recompilación determinista
  • Verificación de equivalencia bytecode ↔ código fuente
  • Validación de parámetros de despliegue

Salida: Prueba de equivalencia, metadata.json

4. Dictamen y Etiquetado

  • Asignación de nivel de conformidad (A/B/C)
  • Resolución del comité técnico
  • Emisión de informe de homologación

Salida: Informe aprobado/condicionado/rechazado, etiqueta de nivel

5. Publicación

  • Alta en catálogo ISBE
  • Despliegue del contrato en ISBE
  • Verificación pública on-chain (BlockScout)
  • Sellado temporal de evidencias (TSA)
  • Configuración de versión (latest o específica)
  • Documentación del contrato desplegado

Salida: Ficha en catálogo, contrato verificado, documentación completa

6. Gestión de Cambios y Upgrades

Para actualizaciones del contrato:

  • Propuesta de cambio documentada
  • Evaluación de impacto en el storage unstructured
  • Validación de compatibilidad
  • Re-ejecución de controles mínimos
  • Control de cambios
  • Nueva versión con trazabilidad completa

Importante: Los upgrades siguen el proceso de gobernanza de ISBE y deben mantener la compatibilidad del storage.


Reglas Críticas

Pausabilidad Restringida

Las pausas solo se activan por:

  • Fuerza mayor debidamente justificada
  • Orden judicial con documentación oficial

Transparencia de Upgrades

  • Prohibidas funciones ocultas de actualización
  • Todos los cambios siguen procesos controlados de ISBE
  • Los upgrades son controlados por la gobernanza de ISBE
  • Separación clara entre lógica de negocio y configuración
  • Trazabilidad completa de cambios

Sin Rollback On-Chain

No se realizan rollbacks de estado. En caso de incidente mayor, se evalúa caso por caso.

Responsabilidad del Proveedor

El proveedor es responsable de:

  • El comportamiento funcional y lógica de negocio de su contrato
  • La corrección de bugs en su lógica específica
  • El cumplimiento de normativas aplicables a su caso de uso

ISBE es responsable de:

  • La verificación de controles técnicos mínimos de seguridad
  • La conformidad con estándares arquitectónicos de ISBE
  • La validación de la correcta implementación de controles de acceso y pausabilidad
  • El despliegue y gestión de contratos en la red

Importante: ISBE no audita la lógica de negocio completa de cada caso de uso.


Qué Debes Entregar a ISBE

Si desarrollas un contrato custom para homologación en ISBE:

1. Contrato Implementado

  • Código fuente completo: Tu contrato con toda su lógica
  • Unstructured Storage: Implementación correcta del patrón de storage
  • Selectores únicos: Sin conflictos con otros contratos de ISBE
  • Integración con gobernanza: RBAC y pausabilidad compatibles

2. Scripts de Despliegue

  • Scripts completos: Scripts de despliegue del contrato
  • Política de versión: Apuntar a latest o fijar versión específica

3. Documentación Técnica

  • Documentación de storage: Slots utilizados, estructura de datos
  • Documentación de roles: Permisos y control de acceso
  • Documentación de funciones: Qué hace cada función, parámetros
  • Metadatos de compilación: Versión Solidity, flags, dependencias

4. Evidencias de Calidad

  • Tests completos: Unitarios y de integración con cobertura
  • Análisis estático: Sin hallazgos críticos abiertos
  • Build reproducible: Equivalencia bytecode ↔ código fuente

Qué NO Necesitas Hacer

Como proveedor de un contrato custom:

  • No necesitas gestionar infraestructura: ISBE gestiona el despliegue

Qué SÍ Necesitas Hacer

Como proveedor de un contrato custom:

  • Implementar tu contrato: Con toda la lógica de negocio
  • Usar unstructured storage: Obligatorio para evitar colisiones
  • Implementar RBAC claro: Con roles bien definidos y documentados
  • Implementar pausabilidad: En todas las funciones críticas con whenNotPaused
  • Documentar exhaustivamente: Storage, roles, funciones
  • Proporcionar tests completos: Cobertura de rutas críticas
  • Emitir eventos de trazabilidad: Para todas las acciones sensibles
  • Build reproducible: Con metadatos completos de compilación
  • Scripts de despliegue: Completos y documentados
  • Sin funciones ocultas: Transparencia total en capacidades del contrato

Ejemplo Completo de Contrato Custom

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;

/// @title TrazabilidadLoteContract
/// @notice Contrato para trazabilidad de lotes de productos
/// @dev Ejemplo de contrato custom con controles de conformidad ISBE
contract TrazabilidadLoteContract {
// Posición única del storage
bytes32 constant STORAGE_POSITION = keccak256("trazabilidad.lote.storage");

struct Lote {
bytes32 id;
string producto;
uint256 fechaProduccion;
address productor;
bool activo;
}

struct TrazabilidadLoteStorage {
mapping(bytes32 => Lote) lotes;
bytes32[] lotesIds;
uint256 totalLotes;
}

// Eventos
event LoteCreado(bytes32 indexed id, string producto, address productor);
event LoteActualizado(bytes32 indexed id, bool activo);

/**
* @dev Acceso al storage unstructured
* @return storage_ Referencia a TrazabilidadLoteStorage en storage
*/
function _trazabilidadLoteStorage()
private
pure
returns (TrazabilidadLoteStorage storage storage_)
{
bytes32 position = STORAGE_POSITION;
assembly {
storage_.slot := position
}
}

/// @notice Crea un nuevo lote
/// @param _id Identificador único del lote
/// @param _producto Nombre del producto
function crearLote(bytes32 _id, string memory _producto)
external
onlyRole(_OPERADOR_ROLE)
whenNotPaused
{
TrazabilidadLoteStorage storage $ = _trazabilidadLoteStorage();

require(_id != bytes32(0), "ID no puede ser cero");
require(bytes(_producto).length > 0, "Producto no puede estar vacio");
require($.lotes[_id].id == bytes32(0), "Lote ya existe");

$.lotes[_id] = Lote({
id: _id,
producto: _producto,
fechaProduccion: block.timestamp,
productor: msg.sender,
activo: true
});

$.lotesIds.push(_id);
$.totalLotes++;

emit LoteCreado(_id, _producto, msg.sender);
}

/// @notice Desactiva un lote existente
/// @param _id Identificador del lote
function desactivarLote(bytes32 _id)
external
onlyRole(_OPERADOR_ROLE)
whenNotPaused
{
TrazabilidadLoteStorage storage $ = _trazabilidadLoteStorage();

require($.lotes[_id].id != bytes32(0), "Lote no existe");
require($.lotes[_id].activo, "Lote ya desactivado");

$.lotes[_id].activo = false;
emit LoteActualizado(_id, false);
}

/// @notice Consulta un lote por su ID
/// @param _id Identificador del lote
/// @return El lote consultado
function obtenerLote(bytes32 _id)
external
view
returns (Lote memory)
{
return _trazabilidadLoteStorage().lotes[_id];
}

/// @notice Obtiene el total de lotes registrados
/// @return Total de lotes
function getTotalLotes() external view returns (uint256) {
return _trazabilidadLoteStorage().totalLotes;
}
}

Próximos Pasos

Una vez homologado tu contrato:

  1. Recibirás un informe de conformidad con el nivel asignado (A/B/C)
  2. Tu contrato será desplegado y estará operativo en ISBE
  3. Estará disponible para verificación pública en BlockScout
  4. Podrás gestionar actualizaciones siguiendo el proceso de cambios

¿Necesitas ayuda con el proceso de conformidad o los requisitos técnicos? Contacta con el equipo de soporte de ISBE.

¿Quieres profundizar en la arquitectura y los componentes técnicos de ISBE?

Ir a Referencia Técnica →