En la primera parte de este artículo, describí un caso en el que el servicio de intercambio rabbit.io intentó enviar una pequeña cantidad de SOL a un cliente, pero la transacción seguía siendo rechazada, aunque, según todas las reglas conocidas de la blockchain de Solana, todo parecía perfectamente válido.
Esa primera parte del artículo también cubrió situaciones en las que una transacción que es técnicamente correcta aún puede ser rechazada en redes como XRP Ledger, Stellar y la Lightning Network (la Capa 2 de Bitcoin). También expliqué un detalle de implementación de las listas negras en el contrato inteligente de USDC que puede causar que las transacciones de USDC fallen inesperadamente, incluso cuando no parece haber nada mal en el lado del remitente.
Si te perdiste la Parte I, puedes leerla aquí.
Hoy quiero ver varios ejemplos similares que involucran otras redes y tokens. En cada uno de ellos, todo puede parecer correcto a primera vista, pero la transacción sigue fallando.
Este caso es específico para desarrolladores y operadores de protocolos DeFi. No obstante, los usuarios ordinarios también pueden sentir sus consecuencias.
Imagina la siguiente situación. Estás intentando depositar USDC, DAI y USDT en algún protocolo. Los depósitos con USDC y DAI funcionan bien, pero la transferencia de USDT se revierte. La dirección es correcta, la red es correcta y hay suficiente gas. ¿Cuál es la razón?
La razón es que USDT en Ethereum no cumple completamente con el estándar ERC-20. El estándar exige que las funciones transfer y transferFrom devuelvan un valor booleano: true en caso de éxito y false en caso de fallo. USDT no devuelve nada.
Si un contrato inteligente está escrito estrictamente según el estándar ERC-20 y espera recibir un valor booleano en respuesta a la llamada transfer, mientras que USDT no devuelve nada, la máquina virtual EVM (cuando se usa Solidity a partir de la versión 0.4.22) interpreta esto como un error y revierte la transferencia. Técnicamente la transacción podría haber tenido éxito, pero se revierte forzosamente. Y el remitente no recibe una indicación clara ni de la red ni del contrato inteligente sobre qué fue exactamente lo que falló.
Este ejemplo no tiene nada que ver con los swaps en rabbit.io. Nuestro sistema está organizado de la manera más simple y fiable posible: recibes una dirección a la que envías tus tokens manualmente, y a cambio recibes los tokens que necesitas de nuestra parte. No intervienen contratos inteligentes DeFi.
No obstante, para los lectores que no solo realizan swaps en rabbit.io sino que también interactúan activamente con DeFi —incluidos desarrolladores— puedo sugerir una solución sencilla. Usa la biblioteca SafeERC20 de OpenZeppelin, que maneja correctamente tokens no estándar.
La mayoría de los protocolos DeFi escritos profesionalmente ya hacen esto. Sin embargo, contratos inteligentes más antiguos o amateur todavía fallan al interactuar con USDT. Este problema está tan extendido que se ha incluído en la base de datos weird-erc20 de peculiaridades conocidas de tokens, donde también puedes encontrar otros tokens con comportamiento similar.
USDT en Ethereum tiene otra peculiaridad que regularmente causa fallos en transacciones con contratos inteligentes.
En el estándar ERC-20, si quieres permitir que un contrato inteligente gaste tus tokens, llamas a la función approve(spender, amount). Por ejemplo, si quieres aumentar la allowance de 100 a 200 USDC, simplemente llamas a approve(spender, 200).
USDT funciona de forma diferente. Su código declara explícitamente que si la dirección destinataria ya tiene una allowance distinta de cero, no está permitido establecer directamente un nuevo valor distinto de cero. Una transacción que sería completamente válida para casi cualquier otro token es rechazada cuando se usa con USDT.
Este comportamiento se introdujo como protección contra un ataque de doble gasto que involucra allowances. Los desarrolladores temían que un atacante pudiera gastar instantáneamente tanto la allowance antigua como la nueva.
El patrón obligatorio para cambiar una allowance de USDT es por lo tanto el siguiente:
approve(spender, 0) para reiniciar la allowanceapprove(spender, new_value)Para los usuarios de aplicaciones descentralizadas esto puede ser confuso. El usuario previamente otorgó una allowance a la aplicación, ahora quiere establecer una allowance diferente, firma la transacción, pero nada cambia y no hay una explicación obvia.
Este ejemplo tampoco tiene que ver con swaps en rabbit.io. Tales transacciones rechazadas no pueden ocurrir en nuestra plataforma porque rabbit.io no requiere conectar una wallet ni solicita permiso para gastar tokens desde ella.
Sin embargo, si en alguna dApp tu transacción approve que involucra USDT falla, la solución suele ser simple. Comprueba el nivel actual de allowance. Si no es cero, primero restablécela a cero y solo entonces establece el nuevo valor.
En la red de Bitcoin existe un concepto llamado dust (polvo). Se refiere a una salida de transacción cuyo valor es menor que la cantidad necesaria para gastarla posteriormente. En otras palabras, las monedas técnicamente existen en tu cartera, pero la comisión requerida para enviarlas sería mayor que las propias monedas.
Es importante entender una distinción fundamental que a menudo se confunde: la diferencia entre las reglas de consenso y la política de los nodos.
Una transacción cuyas salidas son menores que el límite de dust puede ser técnicamente válida según las reglas de consenso de Bitcoin. Sin embargo, la mayoría de los nodos por defecto se negarán a retransmitir dicha transacción, y la mayoría de los mineros se negarán a incluirla en un bloque.
La razón es simple: almacenar monedas extremadamente pequeñas sobrecarga la base de datos sin proporcionar ningún beneficio económico real.
El límite de dust depende del tipo de dirección y de la comisión mínima de retransmisión. Históricamente el límite de dust se considera 546 satoshis. Las transacciones con salidas menores costarían más en comisiones que la cantidad enviada si la tasa mínima es 1 sat/vByte. Pero esto se aplica solo a direcciones legacy que empiezan con "1".
Tipos de direcciones más modernas crean transacciones que ocupan menos espacio en la blockchain, por lo que sus límites de dust pueden ser más bajos. Por ejemplo, para direcciones regulares bc1q... el límite de dust a una tasa de 1 sat/vByte es de 294 satoshis, y con la comisión mínima de retransmisión actualmente aplicada (0.1 sat/vByte) el límite de dust se vuelve diez veces menor.

Imagina la siguiente situación.
Tienes 100.000 satoshis (0.001 BTC). Quieres enviar 99.000 satoshis a alguien. Construyes una transacción, y la comisión de red es de 980 satoshis. Los 20 satoshis restantes deberían volver a ti como cambio.
Pero eso no sucederá. No recibirás tu cambio, y el pago principal tampoco llegará al destinatario. La red de nodos relé rechazará silenciosamente la transacción porque una de sus salidas está por debajo del límite de dust.
También existe un problema relacionado: gastar dust más tarde. Si recibes muchas salidas menores de 294 satoshis mientras las comisiones son bajas, y más tarde las comisiones aumentan, cualquier transacción que intente gastar esas monedas puede volverse tan cara que la cantidad transferida ni siquiera cubra la comisión requerida.
Por lo tanto, al intercambiar otros activos cripto por bitcoin, asegúrate de que las salidas creadas excedan el límite de dust. Rabbit.io permite swaps en cantidades varias veces superiores al límite de dust actual. Sin embargo, si las comisiones de red aumentan, dichas cantidades pequeñas pueden volverse difíciles de enviar posteriormente.
En Ethereum y en cualquier blockchain compatible con EVM (como BSC, HyperEVM y otras), cada transacción enviada desde una dirección concreta tiene un número secuencial llamado nonce.
La red procesa las transacciones estrictamente en orden: primero la transacción con nonce = 0, luego nonce = 1, luego 2, y así sucesivamente. Es imposible saltarse un número.
Si una transacción se queda atascada en el mempool debido a una comisión de gas demasiado baja, todas las transacciones posteriores desde la misma dirección con nonces superiores también permanecerán pendientes, incluso si tienen comisiones normales.
Aquí hay un escenario muy realista. Hace unas semanas enviaste una transacción con una comisión baja. Se quedó atascada. Te olvidaste de ella. Ahora intentas enviar una transacción nueva. Especificas la dirección correcta y pones una comisión adecuada, pero la transacción sigue sin procesarse.
El problema no es la transacción actual, sino la antigua pendiente.
La solución es enviar una transacción con el mismo nonce antiguo pero con una comisión de gas mayor. Esto acelerará la transacción original (speed up) o la cancelará. Esto último ocurre si envías una transferencia a ti mismo con el mismo nonce y una comisión de gas mayor.
Sin embargo, ten en cuenta que no todas las wallets permiten a los usuarios controlar el valor del nonce. Por ejemplo, wallets populares como Trust Wallet y Exodus no ofrecen esta función. Mientras tanto, MetaMask —que mucha gente considera anticuada e incómoda— en realidad sí lo hace.
La red TRON tiene un modelo de recursos inusual. En lugar de una única comisión por transacción, las transacciones consumen dos tipos de recursos:
La Energy se puede obtener congelando TRX. Si esto no se hace, la red quema TRX automáticamente para cubrir el coste.
Y aquí aparece un problema de precios inesperado:
Si el remitente tiene 15 TRX disponibles para comisiones pero la transferencia va a una dirección nueva, la transacción puede fallar con el error OUT OF ENERGY. El TRX gastado en este intento no es reembolsado.
En otras palabras, la situación vuelve a parecerse a los otros ejemplos de este artículo: la dirección es correcta, la red es correcta, el remitente tiene USDT, había TRX presente —y aun así la transacción falla.
La conclusión es simple: para un funcionamiento estable con USDT TRC-20, es aconsejable mantener al menos 27 TRX en el balance para cubrir posibles costes de transacción.
La historia con la transferencia fallida de SOL me enseñó una lección valiosa. No en el sentido de que no entendiera las blockchains, sino en el sentido de que cada blockchain es su propio ecosistema con reglas ocultas que no siempre están bien documentadas y a veces se revelan solo en situaciones inusuales.
Cada fallo confuso no es motivo de frustración, sino una oportunidad para aprender algo nuevo. Y cuanto más cosas nuevas aprendo, más me interesa seguir trabajando con criptomonedas.
Si sientes lo mismo, documenta los casos inusuales y comparte tus hallazgos. La industria cripto se vuelve más fiable cuando la experiencia práctica se difunde más rápido de lo que la documentación oficial puede actualizarse.