Auditoría de Seguridad del Protocolo

Análisis de seguridad del Escrow Inteligente de P2PMoney.xyz — protocolo descentralizado para el intercambio de stablecoins por dinero fiat, sin intermediarios que custodien tus fondos. Verificado contra los contratos reales desplegados.

✅ Sin hallazgos críticos✅ Sin hallazgos altos✅ Verificado on-chain🔐 Gobernanza multisig⚖️ Árbitro independiente

P2PMoney Protocol · P2PMoney.xyz · Documento vigente · Junio 2026

1. Descripción del Protocolo

P2PMoney es un protocolo descentralizado de intercambio entre personas (P2P) que opera sobre un Escrow Inteligente. Permite a cualquier persona comprar y vender stablecoins (como USDC, USDT o COPm) contra dinero fiat sin depender de ningún intermediario centralizado. El protocolo está desplegado en varias redes blockchain (ver Especificaciones Técnicas) y funciona de forma idéntica en todas ellas.

El Escrow Inteligente actúa como intermediario neutral. Custodia los tokens del vendedor bajo condiciones contractuales y los libera únicamente cuando el comprador confirma el pago. Nadie — ni el operador, ni los desarrolladores — puede alterar este proceso unilateralmente.

El mecanismo es análogo al de una custodia notarial, pero ejecutado automáticamente por código:

Custodia notarial tradicionalEscrow Inteligente
El notario guarda el dineroEl contrato custodia los tokens
El dinero se libera al firmarLos tokens se liberan al confirmar el pago
El notario actúa bajo reglas escritasEl código ejecuta las reglas automáticamente, 24/7
El notario no puede apropiarse del dineroNinguna función del contrato permite extraer fondos arbitrariamente
Inmutabilidad: Las reglas del Escrow Inteligente están escritas en la blockchain. Ninguna persona ni organización puede modificarlas retroactivamente.

2. Activos Soportados

El Escrow Inteligente opera exclusivamente con stablecoins aprobadas. El conjunto exacto depende de la red (ver Especificaciones Técnicas); los principales son:

ActivoDescripciónValor de referencia
USDCDólar digital emitido por Circle, entidad regulada en Estados Unidos1 USDC ≈ 1 USD
USDTDólar digital emitido por Tether Limited1 USDT ≈ 1 USD
COPmPeso colombiano digital del protocolo Mento, nativo de Celo1 COPm ≈ 1 COP
Solo estos activos son aceptados por el contrato. La incorporación de cualquier nuevo activo requiere una acción explícita del operador.

3. Arquitectura de Participantes

El pago fiat ocurre fuera del contrato. La transferencia bancaria (Bancolombia, Nequi, Daviplata) se realiza directamente entre las partes por sus canales bancarios. El comprador confirma esta acción en el contrato, pero el dinero nunca pasa por blockchain.
Separación de roles garantizada por el contrato. El Owner gestiona la configuración del protocolo y el Árbitro resuelve disputas. Ambos roles no pueden recaer en la misma wallet — el contrato lo impide de forma explícita e inmutable.

4. Modelo de Órdenes y Operaciones

Dos conceptos clave: Orden vs Deal

Para entender el protocolo hay que distinguir dos cosas. La Orden es el anuncio publicado en el marketplace (una sola persona: quien publica). El Deal es la operación concreta que nace cuando alguien toma esa orden (dos personas: comprador y vendedor). La orden es el aviso; el deal es el apretón de manos.

Cuando un deal se cancela antes del pago, la orden se reabre y otra persona puede tomarla. Sin embargo, si el deal llega a su conclusión — ya sea por liberación exitosa o por resolución de disputa — la orden queda cancelada permanentemente. El maker crea una nueva orden si desea continuar operando.

Orden de Venta

El vendedor publica un anuncio indicando la cantidad de tokens disponibles y las condiciones de la operación. Los tokens quedan bajo custodia del contrato desde el momento de la publicación.

Ejemplo: "Ofrezco 100 USDC. Precio: 4.200 COP por dólar. Acepto Bancolombia y Nequi."

Orden de Compra

El comprador publica un anuncio indicando la cantidad que desea adquirir. Los tokens entran al contrato únicamente cuando un vendedor acepta la orden.

Ejemplo: "Quiero comprar 100 USDC. Pago hasta 4.250 COP por dólar. Dispongo de Nequi y Daviplata."

¿Quién deposita los tokens?

En ambos tipos de orden el resultado es el mismo: el vendedor entrega tokens y el comprador paga fiat. Solo cambia cuándo entran los tokens al escrow:

Orden de VentaOrden de Compra
Quién publicaEl vendedorEl comprador
Quién deposita los tokensEl que publica, al crear la ordenEl que la acepta (vendedor), al aceptarla
Quién la tomaEl compradorEl vendedor

Ciclo de vida completo de una operación

Esta es la visión general del recorrido de una operación, de principio a fin:

Por qué se separan orden y deal: la orden es reutilizable si el deal se cancela antes del pago; el deal captura el contexto de una operación concreta — las dos partes, el plazo de pago, la comisión congelada y la disputa.

5. Flujos de Ejecución

Flujo A — Orden de Venta

Si el comprador no confirma el pago antes de que venza el plazo, el vendedor puede cancelar el deal y recuperar sus tokens íntegramente.

Flujo B — Orden de Compra

6. Resolución de Disputas

Si surge un desacuerdo — por ejemplo, el comprador afirma haber pagado pero el vendedor no lo reconoce — cualquiera de las dos partes puede abrir una disputa. Mientras la disputa está activa, los tokens permanecen custodiados por el contrato: ninguna de las partes puede retirarlos hasta que se resuelva.

¿Quién resuelve y cómo?

Las disputas las resuelve un árbitro independiente cuya wallet es diferente e independiente del operador del protocolo. El contrato impide explícitamente que el operador se asigne a sí mismo como árbitro (ArbiterCannotBeOwner). La resolución sigue un proceso de tres pasos obligatorios que el contrato hace cumplir automáticamente:

PasoFunciónQué ocurre
1commitEvidenceEl árbitro registra el hash del expediente (keccak256 del chat de la operación) en blockchain. Sin este paso no puede resolver.
2Ventana de esperaDebe transcurrir el tiempo mínimo de evidencia (configurable, nunca inferior a 15 minutos) entre el commit y la resolución.
3resolveDisputeEl árbitro dirige los tokens al comprador o los devuelve al vendedor. Solo ejecutable tras la ventana mínima.

Resultados posibles

ResoluciónQué ocurre con los tokens
A favor del compradorLos tokens se envían al comprador (menos la comisión). La operación se marca como completada.
A favor del vendedorLos tokens vuelven al vendedor. La orden queda cancelada permanentemente — el maker debe crear una nueva orden si desea continuar.
Protección estructural: No es posible abrir una disputa antes de que el comprador confirme el pago (estado "Activo"). Esto impide disputas sin evidencia de transferencia. El árbitro solo puede dirigir los tokens al comprador o al vendedor de ese deal — nunca a un tercero ni al operador.
Trazabilidad total: El hash del expediente de cada disputa queda registrado en blockchain antes de la resolución. Cualquier persona puede verificar qué evidencia respaldó cada decisión. El árbitro no puede resolver sin haber comprometido el expediente on-chain primero.
El historial de cada disputa queda registrado: a favor de quién se resolvió, el monto y las observaciones del árbitro. Esa información es pública y consultable en las páginas de reputación de cada usuario.

7. Máquina de Estados

Estados de una Orden

EstadoDescripción
AbiertaLa orden está visible en el marketplace. Cualquier usuario puede aceptarla.
AceptadaUn usuario tomó la orden. El intercambio está en curso.
CompletadaEl intercambio finalizó exitosamente. Estado permanente e inmutable.
CanceladaLa orden fue cancelada. Estado permanente — aplica tanto a cancelaciones directas como a resoluciones de disputa.

Estados de un Deal

8. Estructura de Comisiones

TipoQuién pagaPorcentaje
Comisión del Maker (publicador)Quien crea la orden0% — Gratuito
Comisión del Taker (aceptante)Quien acepta la orden0.20% (20 bps)

Ejemplo con 100 USDC

Monto del deal: 100.00 USDC
Comisión (0.20%): −0.20 USDC
Comprador recibe: 99.80 USDC
Comisión destinada al treasury del protocolo (Safe Multisig)

Inmutabilidad de la comisión por deal

La comisión aplicable a cada operación queda fijada contractualmente en el momento en que se acepta la orden. Ningún cambio posterior de parámetros puede afectar deals ya en curso.

9. Control Administrativo

Separación de roles

El protocolo separa estrictamente dos roles que el contrato impide que recaigan en la misma wallet: el Owner gestiona la configuración del protocolo, y el Árbitro resuelve disputas. Esta separación elimina el conflicto de intereses que existiría si quien opera el protocolo también decide quién gana las disputas.

El Owner no puede resolver disputas. El Árbitro no puede modificar parámetros del protocolo ni extraer comisiones. Cada rol está confinado a sus funciones específicas por el código del contrato.

Frenos de emergencia (dos niveles)

El Owner dispone de dos pausas independientes, pensadas como freno de emergencia y gobernadas por el multisig:

FrenoQué hacePara qué sirve
Pausa suaveDetiene la creación de nuevas órdenes y operaciones; las operaciones en curso pueden completarse y todos pueden retirar sus fondosContener riesgo / frenar spam sin atrapar a nadie
Pausa de retirosCongela todas las salidas de tokens (incluidas las legítimas, que quedan congeladas, no perdidas)Detener un ataque en curso; se reactiva con una sola transacción
Toda activación de una pausa queda registrada públicamente en la blockchain y requiere las firmas del multisig. Es el patrón "pause guardian" que usan protocolos como Aave y Compound.

Límites operativos

El protocolo impone límites configurables para prevenir abuso y spam en el marketplace:

LímiteValor actualPropósito
Monto mínimo por orden5 USDC (configurable)Impide órdenes de importes irrisorios que saturarían el marketplace
Máximo de órdenes abiertas por maker5 (configurable)Previene que una wallet bloquee liquidez con decenas de órdenes sin intención de operar
Ventana mínima de evidencia1 hora · mínimo absoluto: 15 minTiempo entre commitEvidence y resolveDispute; impide resoluciones instantáneas sin revisión
Preaviso para cambio de árbitro1 hora · mínimo absoluto: 1 horaTimelock on-chain para que los usuarios vean el cambio propuesto antes de que aplique

10. Flujo de Fondos

Cómo se mueven los fondos en cada escenario:

✅ Operación exitosa (orden de venta)

↩️ Cancelación

Si el comprador no paga a tiempo, el deal se cancela y los fondos vuelven a su dueño:

⚠️ Disputa

Si hay desacuerdo, el árbitro independiente decide a quién van los tokens tras verificar la evidencia on-chain:

11. Seguridad de los Fondos

La pregunta más importante de cualquier custodia: ¿puede alguien retirar fondos que no le pertenecen? La respuesta es no. Solo existen cinco funciones capaces de sacar tokens del contrato, y cada una verifica que quien la llama sea la persona correcta.

Las únicas 5 salidas de fondos

AcciónQuién puedeA dónde van los tokens
Liberar tokensSolo el vendedor del dealAl comprador (menos la comisión)
Cancelar dealComprador o vendedor del dealDevuelve el depósito a su dueño
Cancelar ordenSolo quien la creóDevuelve el depósito a su dueño
Resolver disputaSolo el árbitroAl comprador o al vendedor de ese deal
Retirar comisionesSolo el ownerA la tesorería (fija)
No existe ninguna función de "retirar lo que sea". Cada salida está atada a una operación concreta donde el que llama es una parte legítima.

¿Cómo decide el contrato si dejarte sacar tokens?

¿Y si un atacante lo intenta sin haber participado?

No tiene ningún camino: todas las salidas le serían rechazadas por control de acceso.

¿Podría crear órdenes falsas para robar?

Tampoco. Crear órdenes solo compromete sus propios tokens, y no puede operar consigo mismo.

Modelo de riesgo

Todos los fondos comparten un mismo balance; la separación por operación es contable. Por eso el riesgo no se reparte entre operaciones: se concentra en la corrección del contrato. De ahí el valor de esta auditoría, las pruebas automáticas y la inmutabilidad de la lógica.

12. Análisis Técnico de Seguridad

Esta sección resume las técnicas de seguridad del código que protegen contra los ataques más comunes a smart contracts.

Control de acceso — quién puede llamar cada función

FunciónQuién puede llamarla
Pausar, comisiones, tesorería, tokens, retirar comisiones, configurar parámetrosSolo el owner (Safe Multisig)
commitEvidence, resolveDisputeSolo el árbitro
proposeArbiter, applyArbiterSolo el owner (con timelock entre propuesta y aplicación)
Confirmar pagoSolo el comprador del deal
Liberar tokensSolo el vendedor del deal
Cancelar dealComprador o vendedor del deal
Abrir disputaComprador o vendedor del deal
Cancelar disputaSolo quien la abrió
Cancelar ordenSolo quien la creó
Cancelar orden expiradaCualquiera (no mueve fondos)
Calificar contraparteComprador o vendedor del deal

Manejo de fondos y solvencia

Todas las transferencias usan SafeERC20, la librería estándar de OpenZeppelin que maneja correctamente cualquier token. Los tokens entran al escrow al crear una orden de venta o al aceptar una de compra, y salen solo por las 5 vías analizadas en la sección 11. Seguridad de los Fondos.

Invariante de solvencia: en todo momento el contrato comprueba que su balance cubre la totalidad de los fondos comprometidos más las comisiones acumuladas (balance ≥ comprometido + comisiones). Esta verificación es instantánea (tiempo constante), sin importar cuántas operaciones históricas existan.

Patrón CEI (Checks-Effects-Interactions)

Toda función que mueve fondos sigue un orden estricto de tres pasos. Transferir los tokens es siempre el último paso:

Ejemplo: cuando el vendedor libera los tokens, el contrato primero marca la operación como "completada" y descuenta el saldo interno, y solo al final transfiere los tokens. Así, aunque el token fuera malicioso, no podría "volver a entrar" para drenar más fondos.

Protección contra reentrancy

Además del patrón CEI, todas las funciones que mueven fondos llevan un "candado" (nonReentrant) que impide que se ejecuten de forma recursiva. Es una doble protección contra el tipo de ataque que ha drenado a otros protocolos DeFi.

Aritmética segura

El contrato usa Solidity 0.8+, que revierte automáticamente ante cualquier desbordamiento numérico. Las comisiones tienen un techo del 1% por lado, y el cálculo del monto a entregar nunca puede dar un resultado negativo ni mayor que lo depositado.

13. Hallazgos de Seguridad

Sobre la auditoría

Una auditoría de smart contracts es un análisis sistemático del código fuente para identificar vulnerabilidades, comportamientos no intencionados y riesgos de diseño. El análisis cubre el control de acceso, los flujos de fondos, la aritmética, los patrones de reentrancy y la lógica de estados.

Resumen de Hallazgos

NivelCantidadDescripción
🔴 Crítico0Vulnerabilidades que permitirían robo o pérdida irreversible de fondos
🟠 Alto0Riesgos de configuración o control de acceso
🟡 Medio0Pérdidas potenciales en escenarios específicos
🟢 Bajo0Impacto limitado o poco probable
ℹ️ Informativo5Observaciones de diseño sin riesgo para los fondos de los usuarios
Veredicto: El Escrow Inteligente no presenta vulnerabilidades críticas, altas ni medias. El control administrativo está protegido por un Safe Multisig 2-de-3. Los cinco hallazgos informativos son observaciones de diseño que no representan riesgo para los fondos de los usuarios.

🔐 H-01Control Administrativo con Safe Multisig✅ Mitigado

El control del Escrow Inteligente está protegido por un Safe Multisig 2-de-3 desplegado en Celo Mainnet. Cualquier acción administrativa — retirar comisiones, pausar el contrato, configurar parámetros — requiere la aprobación independiente de los tres firmantes. Ninguna persona individual puede tomar decisiones unilaterales sobre el protocolo.

Dirección del Safe Multisig:

0x8C2A86F1253a14961dCaA1eb82b8bd57bcfc9DC3 · Celo Mainnet · 2 de 3 firmantes
🔐 H-02Griefing: bloqueo permanente de capital por re-aceptación✅ Mitigado

Riesgo identificado: Un actor malicioso podía aceptar una orden de venta, abrir una disputa, y cuando la disputa se resolvía a favor del vendedor, la orden se reabría automáticamente en el marketplace. El atacante podía aceptarla de inmediato nuevamente, repitiendo el ciclo indefinidamente. El resultado: el capital del maker quedaba bloqueado sin posibilidad de cancelar la orden ni recuperar los fondos.

Solución implementada: Tanto cancelDeal como resolveDispute(favorBuyer=false) ahora marcan la orden como Cancelada permanentemente. Los tokens se devuelven al depositante de inmediato. Si el maker desea continuar operando, crea una nueva orden. El contrato elimina la ruta de re-aceptación.

Este hallazgo fue identificado durante el análisis del ciclo de vida de órdenes y corregido antes del despliegue en producción. El contrato actualmente desplegado no es vulnerable a este ataque.
🔐 H-03Árbitro independiente con evidencia on-chain✅ Mitigado

Riesgo original: El operador del protocolo podía resolver disputas arbitrariamente a su favor — incluso actuando como comprador mediante una wallet secundaria — sin que existiera ningún mecanismo de rendición de cuentas. El poder de resolución era completamente unilateral.

Solución implementada: La resolución de disputas se transfirió a un rol arbiter separado e independiente del owner. El contrato rechaza explícitamente que el owner sea el árbitro (ArbiterCannotBeOwner).

El flujo de resolución tiene 3 capas de protección:

  • Rol separado: Solo el árbitro puede llamar resolveDispute. El owner solo administra el protocolo.
  • Evidencia comprometida on-chain: El árbitro debe llamar primero a commitEvidence(dealId, keccak256(chatJSON)). El hash queda registrado en blockchain antes de la resolución.
  • Ventana mínima configurable: Tras commitEvidence, debe esperarse la ventana mínima (configurable, con un floor de 15 minutos que el contrato impone) antes de resolver. Impide resoluciones instantáneas sin revisión.

El cambio de árbitro también está protegido: proposeArbiter inicia un timelock configurable (mínimo absoluto 1 hora) visible on-chain, bloqueado si hay disputas activas (ArbiterLockedByActiveDisputes). Los usuarios pueden ver el cambio propuesto en /explorar y cerrar sus operaciones antes de que aplique.

Árbitro activo en Celo Mainnet:

0x9DCaBb8B928dCe75D8EAb0a015012a5D562404C0 · Celo Mainnet
✅ I-01Longitud de texto en disputas (implementado)✅ Mitigado

El campo de razón al abrir una disputa ahora tiene un límite máximo (500 bytes), validado por el contrato. Esto evita entradas de texto de tamaño arbitrario que incrementarían el costo de gas. La interfaz muestra un contador y un mensaje claro si se supera el límite.

ℹ️ I-02Historial de operaciones sin límite superiorSin riesgo real

El contrato almacena el historial completo de órdenes y deals por usuario sin límite. Para el horizonte temporal actual no existe problema de rendimiento. La aplicación consulta el historial mediante eventos de blockchain sin depender de funciones on-chain.

ℹ️ I-03Órdenes existentes con tokens deshabilitadosSin riesgo real

Si el operador deshabilita un token, las órdenes abiertas previamente pueden seguir siendo aceptadas. Las nuevas órdenes de ese token ya no pueden crearse. Este comportamiento es intencional: protege a vendedores que tienen fondos bloqueados en órdenes abiertas al momento de la deshabilitación.

ℹ️ I-04Disputas resueltas contra el comprador y conteo de reputaciónSin riesgo real

Cuando el árbitro resuelve una disputa a favor del vendedor, el deal se cancela y no se incrementa el contador de deals completados. Solo contabilizan las operaciones finalizadas exitosamente. Decisión de diseño intencional del sistema de reputación.

ℹ️ I-05Orden de emisión de eventosSin riesgo real

En algunas funciones, el evento de notificación se emite antes de que se actualice un contador interno. No existe riesgo de reentrancy — el contrato aplica el patrón CEI en todas las rutas críticas. Observación de estilo para futuras iteraciones.

14. Mecanismos de Protección

El Escrow Inteligente implementa las siguientes protecciones de seguridad de forma nativa:

✅ Árbitro independiente del operador

Las disputas las resuelve un árbitro cuya wallet es diferente e independiente del owner del contrato. El contrato rechaza explícitamente (ArbiterCannotBeOwner) que el operador se asigne a sí mismo como árbitro. Cualquier cambio de árbitro requiere un preaviso on-chain configurable (mínimo 1 hora) visible públicamente, y está bloqueado mientras haya disputas activas.

✅ Evidencia comprometida on-chain antes de resolver

El árbitro debe registrar el hash del expediente (keccak256 del chat de disputa) en blockchain antes de poder resolver. Después de commitEvidence, existe una ventana mínima configurable (con un floor de seguridad de 15 minutos que el contrato impone y no puede reducirse) antes de que resolveDispute pueda ejecutarse. Cualquier persona puede verificar qué evidencia respaldó cada decisión.

✅ Cancelación permanente ante resolución de disputa

Cuando el árbitro resuelve a favor del vendedor, la orden queda cancelada permanentemente — no reabre en el marketplace. Esto elimina el vector de ataque donde un bot podía aceptar la misma orden repetidamente tras cada resolución, bloqueando el capital del maker indefinidamente.

✅ Límites anti-flood configurables

El contrato impone un monto mínimo por orden (5 USDC por defecto) y un máximo de órdenes abiertas por maker (5 por defecto). Ambos límites son configurables por el owner para adaptarse a las condiciones del mercado. Previenen que una sola wallet sature el marketplace con decenas de micrórdenes o anuncios fantasma.

✅ Ventana de evidencia con floor de seguridad

La ventana mínima entre commitEvidence y resolveDispute es configurable por el owner, pero el contrato impone un floor absoluto de 15 minutos que nunca puede reducirse. Los cambios quedan registrados on-chain vía evento MinEvidenceWindowUpdated, garantizando transparencia total.

✅ Comisión fijada al momento de aceptar

La comisión aplicable a cada deal queda registrada contractualmente en el momento exacto en que se acepta la orden. Cualquier modificación posterior de los parámetros de comisión por el operador únicamente afecta a las nuevas operaciones, nunca a las que ya están en curso.

✅ Límites de longitud en campos de texto

Los campos de texto tienen límites máximos: método de pago (100 bytes) e instrucciones de pago (600 bytes). Esto previene abusos mediante entradas de texto de tamaño arbitrario que incrementarían el costo de gas de forma maliciosa.

✅ Gestión de tokens sin duplicados

El contrato utiliza un algoritmo eficiente de tipo swap-and-pop para mantener la lista de tokens habilitados. Garantiza que no pueden existir entradas duplicadas y que las operaciones de habilitación y deshabilitación siempre resultan en un estado consistente.

✅ Verificación de solvencia en tiempo constante

La función isSolvent() verifica instantáneamente que el balance del contrato cubre la totalidad de los fondos comprometidos en deals activos. Opera en tiempo constante O(1) gracias al contador _totalLocked, independientemente del número de operaciones históricas.

✅ Validación de identificadores

Todas las funciones del contrato rechazan explícitamente identificadores con valor cero (ID 0). Esto elimina un vector de comportamiento indefinido donde llamadas con parámetros inválidos podrían ejecutarse contra la orden o deal equivocado.

✅ Expiración de órdenes de compra

Las órdenes de compra abiertas tienen un tiempo máximo de vigencia configurable por el operador. Una vez expiradas no pueden aceptarse, y cualquier persona puede retirarlas del marketplace. Esto evita que el marketplace se sature con anuncios abandonados, sin que ningún fondo quede en riesgo.

✅ Freno de emergencia de dos niveles

El protocolo cuenta con dos pausas independientes: una suave que detiene la entrada de nuevas operaciones permitiendo que todos retiren sus fondos, y una de retiros que congela todas las salidas de tokens para detener un eventual ataque. Ambas son reversibles, quedan registradas en blockchain y requieren las firmas del multisig.

✅ Consistencia entre operaciones y métricas

Toda operación que se completa emite un registro verificable en blockchain, de modo que las métricas públicas del protocolo (volumen, operaciones exitosas) reflejan fielmente lo ocurrido on-chain, incluidas las operaciones que se cierran mediante la resolución de una disputa a favor del comprador.

✅ Autenticación por wallet (SIWE)

El acceso a todos los datos privados (chat, notificaciones, comprobantes) requiere una firma criptográfica de la wallet. Sin sesión válida, la base de datos devuelve cero filas en todas las tablas con información personal — incluso conociendo la clave pública de lectura.

✅ Comprobantes de pago en almacenamiento privado

Los archivos enviados en el chat (comprobantes bancarios, capturas) se almacenan en un bucket privado. Solo son accesibles mediante una URL firmada de 2 minutos de duración, generada por el servidor tras verificar que el solicitante es participante del trade.

15. Seguridad de Datos e Identidad

El protocolo implementa una capa de identidad basada en firma de wallet (SIWE — Sign‑In With Ethereum) que protege todos los datos off-chain. Cada sesión queda vinculada criptográficamente a una dirección de wallet: la base de datos sabe quién eres antes de devolverte cualquier dato.

Arquitectura de autenticación

El flujo combina el estándar EIP‑4361 (SIWE) con JWT firmados con el mismo secreto que usa Supabase internamente, de modo que las políticas de Row Level Security (RLS) pueden leer el claim wallet del token y aplicar reglas por dirección.

Modelo de acceso por tabla

TablaLecturaEscritura
messagesSolo sender o receiverSolo sender
dispute_messagesPartes del trade + árbitroPartes del trade + árbitro
notificationsSolo el destinatarioSolo servidor (service role)
push_subscriptionsSolo el dueñoSolo el dueño
orders, ratingsPúblicoSolo wallet propia
dispute_resolutions, chain_configPúblicoSolo árbitro / admin
event_cacheSolo servidorSolo servidor

Comprobantes de pago privados

Los archivos enviados en el chat (comprobantes bancarios, capturas de pantalla) se almacenan en un bucket privado de Supabase Storage. No existe URL pública para acceder a ellos. El servidor genera una URL firmada de 2 minutos de duración vía /api/chat-image únicamente después de verificar que la wallet solicitante es participante del trade correspondiente.

Separación de claves

ClaveUsoAcceso
anon keyCliente web (pública, embebida en el frontend)Solo lo que RLS permite según el JWT
service role keyServidor (rutas API, cron jobs)Bypassa RLS — nunca expuesta al cliente

16. Especificaciones Técnicas

El protocolo está desplegado en las siguientes redes. Cada contrato es público, verificable e inmutable. Despliega cada red para ver sus detalles:

BlockchainCelo Mainnet (Chain ID: 42220)
Bloque de deploy71061728
Versión del contratoV7.9
Owner
Árbitro
Activos soportadosUSDC · USDT · COPm
Comisión Maker / Taker0% / 0.20% (20 bps)
Ventana de pago5 minutos — 24 horas
Ventana de evidencia (disputas)… · mínimo absoluto: 15 min
Preaviso cambio de árbitro… · mínimo absoluto: 1 hora
Monto mínimo por orden
Máx. órdenes abiertas por maker
Máx. deals activos por taker
Ver contrato en Celoscan
Código fuente público y verificable. En cada explorador puedes consultar todas las transacciones, el balance actual y el historial completo — todo público e inmutable en blockchain. Cualquiera puede comprobar que el contrato desplegado corresponde exactamente al código auditado.

17. Glosario

Blockchain
Base de datos pública e inmutable distribuida en miles de nodos
Smart Contract
Programa que vive en la blockchain y se ejecuta automáticamente según sus reglas
Token
Activo digital (USDC, USDT o COPm) intercambiado en el protocolo
Deal
La ejecución específica de un intercambio entre comprador y vendedor
Orden
El anuncio publicado: 'quiero comprar/vender X cantidad a Y precio'
Escrow
Custodia neutral que retiene el activo hasta que se cumplen condiciones predefinidas
Safe Multisig
Billetera que requiere múltiples aprobaciones independientes para ejecutar cualquier acción
Árbitro
Rol independiente del owner que resuelve disputas. El contrato impide que sea la misma wallet. Cualquier cambio requiere un timelock de preaviso on-chain configurable.
commitEvidence
Función que el árbitro llama antes de resolver una disputa. Registra el hash del expediente en blockchain, garantizando trazabilidad total de la decisión.
minEvidenceWindow
Tiempo mínimo configurable entre commitEvidence y resolveDispute. Tiene un floor absoluto de 15 minutos que el contrato impone y no puede reducirse.
arbiterChangeDelay
Timelock on-chain requerido antes de que un cambio de árbitro propuesto pueda aplicarse. Mínimo 1 hora, configurable por el owner.
Deadline
Plazo máximo para que el comprador confirme el pago
Fee / Comisión
Porcentaje que cobra el protocolo al completar un intercambio
Bps (basis points)
1 bps = 0.01%. 20 bps = 0.20% de comisión
CEI Pattern
Técnica de seguridad: validar → actualizar estado → interactuar. Previene ataques de reentrancy
Reentrancy
Tipo de ataque donde un contrato malicioso se llama recursivamente para drenar fondos
Fiat
Dinero convencional (pesos, dólares) transferido por canales bancarios fuera de blockchain
O(1)
Operación que ejecuta en tiempo constante, sin importar el volumen de datos históricos
Pausa de retiros
Freno de emergencia que congela las salidas de tokens para detener un ataque; reversible y gobernado por multisig
Expiración de orden
Tiempo máximo que una orden de compra permanece abierta antes de poder retirarse del marketplace
Disputa
Mecanismo para resolver desacuerdos: un árbitro independiente revisa la evidencia comprometida on-chain y dirige los tokens al comprador o al vendedor
Cancelación permanente
Cuando una disputa se resuelve a favor del vendedor o se cancela un deal, la orden no reabre en el marketplace — queda cancelada definitivamente y los fondos se devuelven al maker.

Documento vigente · Julio 2026 · P2PMoney Protocol

Auditoría de seguridad del Escrow Inteligente del protocolo P2PMoney

Contratos verificables en cada red — ver Especificaciones Técnicas