Un día, un usuario se puso en contacto con el soporte de rabbit.io afirmando que, después de un intercambio, recibió 1 XLM en lugar de 1,000 USDC.
Parecía una pérdida grave. Un lumen vale mucho menos que un dólar: en este momento, el XLM cotiza a unos 0,22 $. Perder casi la totalidad de la suma de esa manera sería alarmante para cualquiera.
Naturalmente, empezamos a investigar el caso de inmediato. Si hubiera resultado que se envió la cantidad incorrecta o el activo equivocado por nuestra culpa, habríamos tomado medidas de inmediato y nos habríamos asegurado de que el usuario recibiera los fondos correctos.
Pero la historia resultó ser mucho más interesante.
Nuestros sistemas funcionaron exactamente como se esperaba. Se enviaron 1,000 USDC a la dirección proporcionada por el usuario, sin errores ni fallos por nuestra parte. Y, sin embargo, en la red Stellar existe un sutil detalle arquitectónico que puede, literalmente, convertir 1,000 USDC en 1 XLM si se pasa por alto.
Permítanme explicarles cómo sucede esto.
El cliente de rabbit.io no era un principiante. Al contrario, era un usuario de criptomonedas experimentado que almacenaba deliberadamente sus fondos en monederos no custodiales en lugar de en intercambios. Sin embargo, la mayor parte de su experiencia procedía de redes basadas en EVM.
En el mundo de Ethereum, los usuarios se acostumbran a un modelo sencillo: cualquier token enviado a su dirección llegará con éxito. En el peor de los casos, solo hay que añadir manualmente el token a la interfaz del monedero. E incluso cuando la aplicación del monedero no admite un token específico en absoluto, puedes importar tu frase semilla en otro monedero que sí lo haga.
Stellar funciona de forma muy diferente.
Su arquitectura es fundamentalmente distinta a la de Ethereum, Binance Smart Chain o Polygon. Incluso el concepto de dirección es diferente. En las redes EVM, las direcciones son efectivamente gratuitas. En Stellar, crear una dirección en el libro mayor (ledger) cuesta 1 XLM.
Y esa cantidad exacta —1 XLM— es lo que nuestro cliente vio en su monedero tras el intercambio.
La diferencia más importante entre Stellar y las redes basadas en EVM radica en cómo se reciben los activos.
En Stellar, un monedero debe aprobar explícitamente cualquier token nuevo antes de que pueda ser acreditado. Por ejemplo, para recibir USDC por primera vez, una cuenta de Stellar tiene que crear una trustline (línea de confianza) con el emisor de USDC. Crear una línea de confianza requiere bloquear 0,5 XLM como reserva, lo que asegura la entrada correspondiente en el libro mayor.
Originalmente, si se enviaba un token a una dirección sin una línea de confianza existente, la transacción simplemente fallaba. La cantidad total permanecía en poder del remitente.
A partir del Protocolo 15 de Stellar, este comportamiento se modificó con la introducción de los saldos reclamables (claimable balances). El objetivo era mejorar la usabilidad y permitir el envío de tokens incluso a cuentas "no preparadas".
Cuando enviamos USDC a la dirección Stellar de nuestro cliente que no tenía una línea de confianza para USDC, el protocolo gestionó la transacción de la siguiente manera:
En otras palabras, los fondos se registraron en el libro mayor y permanecieron allí, esperando a que alguien los reclamara explícitamente. Quién está autorizado a hacerlo se define en las condiciones de la transacción. Por defecto, tanto el remitente como el destinatario son reclamantes elegibles.
Pero, ¿de dónde salieron los 1 XLM en la cuenta del destinatario? La respuesta es: de nosotros, aunque nunca los enviamos intencionadamente.
Así es como se procesan realmente estas transacciones.
Paso 1. El remitente inicia una transferencia de USDC y firma una transacción con los siguientes parámetros:
En esta etapa, el remitente acepta implícitamente pagar cualquier cantidad de XLM que se requiera para procesar la transacción. En la práctica, los usuarios rara vez prestan atención a este detalle, porque las comisiones de las transacciones en Stellar suelen ser insignificantes.
Paso 2. Stellar realiza una serie de validaciones básicas para comprobar si la operación puede ejecutarse:
En conjunto, estas condiciones significan que un pago directo no es posible.
Paso 3. En lugar de rechazar la transacción de plano, Stellar activa el mecanismo de saldo reclamable.
Para ello, la red:
Sin embargo, para que el destinatario figure como posible reclamante, su cuenta debe existir en la red. En el momento de la transacción, la cuenta solo existía dentro de la aplicación del monedero del destinatario. Aún no se había creado en el libro mayor de Stellar.
Bajo estas condiciones, la cuenta se crea como parte de la misma transacción.
Como se mencionó anteriormente, crear una cuenta en Stellar no es gratis. El 1 XLM necesario para crear la cuenta se toma del origen de la operación, es decir, del saldo del remitente:
Este 1 XLM forma parte del coste de ejecución de la transacción, un coste que aceptamos implícitamente al firmar la transacción. Técnicamente, termina en el saldo del destinatario, pero este no puede utilizarlo realmente. En particular, el destinatario no puede tomar la mitad de esa cantidad para crear una línea de confianza para USDC y reclamar los fondos.
Si la cuenta del destinatario ya hubiera existido en la red, pero simplemente careciera de una línea de confianza para USDC, no habrían sido necesarios 1 XLM adicionales. En ese caso, el destinatario no habría visto ningún cambio visible en su monedero en absoluto.
El primer paso fue que el destinatario firmara una operación changeTrust para el activo USDC. Para que esta operación tenga éxito, el monedero debe tener al menos 0,5 XLM de saldo libre, que queda bloqueado como reserva cuando se crea la línea de confianza.
Nuestro cliente no tenía ningún XLM libre. Más concretamente, el único XLM en la cuenta era el 1 XLM que apareció allí como resultado del intercambio, pero esa cantidad estaba totalmente bloqueada como reserva base y no podía utilizarse.
Por lo tanto, sugerimos una solución sencilla: intercambiar una pequeña cantidad de cualquier criptomoneda disponible por lúmenes. Tras hacerlo, el cliente tuvo finalmente suficiente XLM libre para crear una línea de confianza en su monedero.
Una vez establecida la línea de confianza con USDC, el usuario pudo reclamar los 1,000 USDC. En este caso, todo terminó bien para todas las partes implicadas.
La situación que encontró nuestro cliente no es única. Y tuvo verdadera suerte de utilizar monederos no custodiales bajo su propio control. Eso es precisamente lo que hizo que el problema fuera relativamente fácil de resolver.
Recordé esta historia porque hace apenas unos días leí sobre un caso muy similar que afectaba a otro usuario. La cantidad era exactamente la misma —1,000 USDC—, pero las circunstancias hacían que el problema fuera mucho más difícil de solucionar.
Hace tres días, apareció un comentario en LinkedIn bajo la última publicación del CEO de Uphold, Simon McLoughlin, donde un usuario de Uphold describía la siguiente situación:
Dada la similitud de los síntomas, creo que el problema de fondo es exactamente el mismo.
Lo más probable es que Uphold genere direcciones de depósito bajo demanda, y la dirección de XLM a la que el usuario envió los fondos aún no se había creado en el libro mayor de Stellar. Eso explicaría por qué apareció 1 XLM en la cuenta como resultado de la transacción. Sin embargo, los 1,000 USDC no aparecieron, y resolver la situación requeriría que Uphold creara manualmente una línea de confianza para USDC para esa dirección.
¿Por qué se negó el soporte a ayudar?
Mi suposición es la arquitectura de seguridad. Cualquier empresa que trabaje con criptomonedas invierte mucho en la seguridad de los monederos. Parece que Uphold no implementó un proceso para crear líneas de confianza fuera del flujo de depósito estándar esperado. Añadir tal funcionalidad de forma retroactiva, cumpliendo con todos los requisitos de seguridad internos, puede costarle al intercambio mucho más que los 1,000 USDC perdidos por el usuario.
A día de hoy, el comentario bajo la publicación del CEO ha sido eliminado. No sé si fue borrado por el propio usuario o por el intercambio. Espero que el problema se haya resuelto y que el usuario haya decidido eliminar el comentario por su cuenta. Pero si el comentario fue eliminado por Uphold, sería una señal preocupante.
Estos problemas no deben enterrarse silenciosamente. Al contrario, merecen atención para que otros usuarios no repitan el mismo error. Por eso decidí compartir aquí tanto nuestra historia como la del usuario de Uphold.
Si al menos uno de los monederos implicados —ya sea el del remitente o el del destinatario— está totalmente controlado por el propietario de los fondos, la situación es relativamente sencilla:
Sin embargo, cuando hay monederos de custodia de por medio —por ejemplo, monederos de CEX— las cosas se complican mucho más.
Los servicios de custodia no están obligados a interferir manualmente en su infraestructura de monederos para corregir el error de un usuario, especialmente si al hacerlo se introducen riesgos operativos o de seguridad adicionales. Como resultado, es posible que se le deniegue la asistencia, aunque técnicamente los fondos sigan existiendo en el libro mayor.
Dicho esto, merece la pena intentarlo. Mientras el intercambio controle las claves privadas, existe la posibilidad de recuperar los fondos.
Si se encuentra en esta situación:
En última instancia, la mejor solución sigue siendo la prevención. Ser tu propio custodio tiene muchas ventajas, pero también conlleva un alto nivel de responsabilidad. Al enviar criptomonedas, la atención a los detalles importa, porque algunos errores son mucho más fáciles de cometer que de corregir.