Depuración de errores en contratos
Para entender cómo depurar errores de Soroban, primero debemos comprender cómo se asocian los errores con cada paso del flujo de la transacción, así como los errores más probables y comunes en cada paso del flujo de la transacción.
Flujo general de la transacción
El proceso típico de envío de una transacción puede dividirse en los siguientes pasos secuenciales, excluyendo interacciones externas como las interacciones con carteras. Cada paso tiene su propio conjunto de posibles errores:
-
Simulación de transacción (opcional):
- Qué sucede: Este paso implica ejecutar el endpoint RPC
simulateTransaction
. El endpoint ejecuta una transacción en modo "simulación" del host y registra las entradas necesarias del libro mayor, las instrucciones de CPU y las autorizaciones requeridas. El resultado final es similar a ejecutar transacciones en Core con recursos máximos, acceso irrestricto al libro mayor y sin tarifas. - Fallos comunes: Los errores suelen implicar superar el límite de la red o problemas de lógica en el contrato.
- Qué sucede: Este paso implica ejecutar el endpoint RPC
-
Core acepta la transacción:
- Qué sucede: Core evalúa cada transacción para decidir si aceptarla o rechazarla. Las transacciones rechazadas suelen ser inválidas o tener tarifas insuficientes, especialmente durante períodos de alto tráfico.
- Fallos comunes: Se rechazan transacciones inválidas, como aquellas con tarifas de recursos incorrectas o valores de recursos demasiado altos, y huellas inválidas. Otros errores comunes incluyen firmas de transacción incorrectas o fondos insuficientes en la cuenta fuente. Las transacciones válidas pueden ser rechazadas solo debido a una tarifa de inclusión baja.
-
Core incluye la transacción en el libro mayor:
- Qué sucede: Las transacciones aceptadas permanecen en la memoria de Core hasta que son incluidas en el libro mayor o eliminadas.
- Fallos comunes: Las transacciones pueden no ser incluidas en el libro mayor si tienen una tarifa de inclusión baja y necesitan ser eliminadas durante picos de tráfico para dar cabida a más transacciones.
-
Core aplica la transacción al libro mayor:
- Qué sucede: Core ejecuta la transacción incluida.
- Fallos comunes: Este paso tiene la gama más amplia de errores potenciales. Los fallos pueden incluir acceso a entradas archivadas, agotamiento de recursos, acceso a entradas fuera de la huella especificada o fallos lógicos dentro del contrato.
Para más información sobre tarifas, visita Tarifas, límites de recursos y medición.
Errores detallados de Soroban
1. Simulación de transacción
Los errores aquí son devueltos por el host y se propagan a través del RPC. Esto no cubre otros posibles errores (por ejemplo, errores de red, errores en el RPC mismo, etc.).
Error | Explicación | Solución |
---|---|---|
HostError(Budget, LimitExceeded) | Se ha superado un límite de recursos definido por la red (ya sea de instrucciones o memoria). Consulta los eventos diagnósticos para verificar cuál límite ha sido superado (el 99% de las veces será el de instrucciones). | Optimiza el contrato para consumir menos recursos. |
HostError(Storage, MissingValue) | Se intenta acceder a una entrada del libro mayor que no existe. El 99.9% de las veces esto significa que el contrato o Wasm no existen en el libro mayor (los casos restantes solo pueden ocurrir si el desarrollador no utiliza el SDK de Soroban para contratos). Los eventos diagnósticos deberían indicar qué entrada falta. | Despliega el contrato o Wasm correspondiente. |
HostError(WasmVm, InvalidAction) | Ha habido un fallo en algún contrato Wasm, típicamente un panic!() . Los eventos diagnósticos pueden proporcionar información más detallada, pero no siempre, ya que los mensajes panic!() no se incluyen en las compilaciones Wasm. | Corrige la lógica del contrato o los argumentos de invocación. Dado que la razón más común para este error es panic!() , podría ser buena idea usar panic_with_error!() en lugar de panic!() en todas partes. Se recomienda escribir más pruebas unitarias. |
HostError(<some other code>) | Un error arbitrario de ejecución, como acceder a un valor fuera de los límites del contenedor, desbordamiento en aritmética i128, tipo de argumento de invocación incorrecto, etc. El código de error debería dar una idea general de qué está fallando, pero consulta los eventos diagnósticos para detalles. | Corrige la lógica del contrato o los argumentos de invocación. Se puede hacer una depuración adicional mediante pruebas unitarias. |
2. Core acepta la transacción
El error es devuelto inmediatamente por Core como respuesta al envío de la transacción y se muestra al usuario a través del RPC. Hay varios campos relacionados con errores en la respuesta de Core:
status
contiene uno de los pocos códigos generales: es "ERROR" para cualquier error de validación de transacción, o uno de los pocos estados especiales no relacionados con la validación.result
contiene el TransactionResult codificado en XDR que, en caso de estado "ERROR", contendrá el código de error a nivel de transacción comenzando con "tx", comotxMALFORMED
.- Los errores de transacción
txFAILED
en esta etapa corresponden a los errores de validación específicos de operación, por lo que se debe examinar el código de resultado de la operación. diagnostics
contendrá información adicional del error en el formato de eventos diagnósticos de Soroban. Esto típicamente se devolverá para errores de transaccióntxSOROBAN_INVALID
pero puede ser utilizado más extensivamente en el futuro.
Error de Core | Explicación | Solución |
---|---|---|
status: TRY_AGAIN_LATER | Ya hay una transacción de la misma cuenta fuente en memoria. La transacción ha sido rechazada por tener una tarifa de inclusión demasiado baja y ha sido reenviada demasiado pronto. | Espera a que la transacción anterior se aplique y reenvía, o cambia a cuentas de canal si necesitas mayor rendimiento. Espera más tiempo antes de reenviar la transacción. Construye una transacción dentro de los límites de la red. |
status: ERROR , error: txMALFORMED | La transacción es fundamentalmente incorrecta: la operación Soroban no es la única operación en la transacción; falta la extensión Soroban; la tarifa o la tarifa por recursos es negativa; la tarifa por recursos es mayor que la tarifa de la tx; los recursos declarados superan los límites de red (ejemplo: quiere usar 200M de instrucciones, mientras el límite general del libro mayor es solo 100M). | Asegúrate de que la transacción esté bien formada y de que la tarifa total de la transacción sea lo suficientemente alta. |
status: ERROR , error: txINSUFFICIENT_FEE | Probablemente: la tarifa de inclusión es demasiado baja durante un aumento del tráfico. Poco probable: la tarifa de inclusión es menor que el mínimo de la red (es decir, menor a 100 stroops). | Incrementa la tarifa de la transacción o espera a que haya menos tráfico. |
status: ERROR , error: txSOROBAN_INVALID , diagnostics: “los recursos transaction $RESOURCE_NAME exceden el límite de configuración de la red” o similar | Algún valor de recurso especificado en la transacción supera el límite de la red. Por ejemplo, esto se activaría si la transacción especifica 200M instrucciones, mientras el límite de red es solo 100M. Ten en cuenta que esto no tiene nada que ver con lo que hace la transacción realmente. Solo se examinan las declaraciones de recursos en este punto. | Optimiza el contrato para ajustarlo al límite de recursos y especifica el valor respectivo en la transacción (típicamente ejecutando simulateTransaction ). En caso de que exista un 'margen de seguridad' demasiado grande para los recursos (ejemplo: +20% dado que la transacción ya necesita el 90% del límite de la red), reduce la declaración de recursos para ajustarla al límite. |
status: ERROR , error: txSOROBAN_INVALID , diagnostics: mensaje relacionado con la huella | Hay una serie de requisitos para la huella, como que no debe contener claves duplicadas, ni entradas no soportadas por Soroban, etc. El mensaje diagnóstico especificará los detalles sobre cuál requisito se ha violado. | Corrige la huella. Esto solo debería ocurrir si la huella fue construida o modificada manualmente; las huellas incluidas en la respuesta de simulateTransaction siempre deberían pasar todas las verificaciones. |
status: ERROR , error: txSOROBAN_INVALID , diagnostics: "transaction sorobanData.resourceFee es menor que la tarifa real del recurso Soroban" | La tarifa de recurso especificada en la transacción no es suficiente para cubrir los recursos especificados en la transacción. Ten en cuenta que esto no tiene nada que ver con lo que hace la transacción realmente. Solo se examinan las declaraciones de recursos en este punto. | Aumenta la tarifa de recurso. Esto normalmente solo ocurre cuando los recursos se calculan o modifican manualmente. simulateTransaction siempre calcula la tarifa suficiente para recursos. |
status: ERROR , error: txFAILED , error de operación: EXTEND_FOOTPRINT_TTL_MALFORMED | Uno de los requisitos de la huella para la operación ExtendFootprintTTL no se ha cumplido: - Solo se pueden ampliar entradas de libro mayor de Soroban. - Solo debe estar poblada la huella de solo lectura. - La extensión TTL no debe ser mayor que la extensión TTL máxima permitida. | Asegúrate de que las huellas cumplan con los requisitos. Idealmente, las librerías del lado cliente deberían garantizar que las transacciones de extensión TTL estén bien formadas. |
status: ERROR , error: txFAILED , error de operación: RESTORE_FOOTPRINT_MALFORMED | Uno de los requisitos de la huella para la operación RestoreFootprint no se ha cumplido: Solo se pueden restaurar entradas persistentes de libro mayor Soroban; Solo debe estar poblada la huella de lectura-escritura. | Asegúrate de que las huellas cumplan con los requisitos. Idealmente, las librerías del lado cliente deberían garantizar que las transacciones de restauración estén bien formadas. |
status: ERROR , error: tx$CODE | Los códigos de error restantes tienen la misma semántica para Soroban que para Stellar; incluyen errores como saldo insuficiente, número de secuencia incorrecto, etc. Estos errores suelen ser fáciles de interpretar según su nombre. | Corrige el problema correspondiente al código. No hay nada específico de Soroban aquí. |
3. Core incluye la transacción en el libro mayor
Hay casos en los que Core parece no incluir la transacción en el libro mayor. Se recomienda la siguiente mejor práctica:
Error | Explicación | Solución |
---|---|---|
La transacción parece estar 'atascada' y nunca se aplica | Aquí no hay un reporte de error directo porque la red no puede comunicar razonablemente qué transacción elimina (Por ejemplo, que el Nodo A haya eliminado la transacción no significa necesariamente que otro Nodo B también la haya eliminado). Al consultar contra un endpoint de datos, la transacción puede ser reportada como 'pendiente'. | Introduce límites de tiempo para la transacción en el lado cliente. Si una transacción no se ha aplicado en 1-2 minutos, es muy poco probable que la red aún la recuerde. Se recomienda encarecidamente que todas las transacciones incluyan un límite de tiempo o límite de libro mayor. Tener un límite permite al desarrollador reenviar la transacción después de que se supere el límite de tiempo y opcionalmente aumentar la tarifa si el error persiste. |
Se recomienda encarecidamente que todas las transacciones incluyan un límite de tiempo o límite de libro mayor.
4. Core aplica la transacción al libro mayor
Los errores y eventos diagnósticos se registran en el flujo meta de la transacción emitido por la instancia de Core cuando se cierra el libro mayor. Luego, el RPC ingiere los metadatos de la transacción (tx meta) y permite a los desarrolladores consultar el tx meta.
Cuando ocurre un error, Core almacena algunos campos relacionados con el error en el meta resultado de la transacción:
- El resultado de la transacción (error) será
txFAILED
para fallos relacionados con Soroban (o cualquier fallo de operación en general). A veces es posible obtener otros errorestx$ERROR
(comotxBAD_AUTH
), pero no están relacionados con Soroban y son más casos extremos. - El error de operación será uno de
INVOKE_HOST_FUNCTION_$ERROR
,RESTORE_FOOTPRINT_$ERROR
yEXTEND_FOOTPRINT_TTL_$ERROR
(correspondientes a las operaciones InvokeHostFunction, RestoreFootprint y ExtendFootprintTTL). Los errores de operación no son muy granulares, y típicamente se deberían usar eventos diagnósticos para entender el error exacto. - Si la instancia Core que produce meta tiene diagnósticos Soroban habilitados (que normalmente debería tener), los meta también contendrán eventos diagnósticos con información de error más detallada.
- Ten en cuenta que puede haber algunas lagunas en la cobertura de eventos diagnósticos. Dado que esto no es un cambio de protocolo, Core puede añadir más eventos diagnósticos en futuras versiones.
Nota: $OPERATION aquí se refiere a cualquiera de las operaciones Soroban: INVOKE_HOST_FUNCTION
, RESTORE_FOOTPRINT
y EXTEND_FOOTPRINT_TTL
.
Error y diagnósticos | Explicación | Solución |
---|---|---|
$OPERATION_RESOURCE_LIMIT_EXCEEDED , diagnostics: mensaje que especifica qué límite de recurso ha sido superado | La transacción ha superado el límite de recursos durante la ejecución. Para la mayoría de recursos (instrucciones, bytes de lectura, bytes de escritura), esto no tiene que ver con el límite general de red; es el límite especificado en la transacción. Por ejemplo, una transacción tiene especificadas 10M instrucciones pero consume al menos 10M + 1 instructión y falla inmediatamente. Los eventos diagnósticos especifican qué límite se ha superado y contienen tanto el límite como el valor que la transacción intentó consumir. | Si superas el límite especificado en la transacción, aumenta el recurso respectivo declarado en la transacción. Si simulateTransaction determinó los límites de recurso, lo más probable es que la razón de superarlos dependa de la lógica respecto al estado volátil del libro mayor (por ejemplo, RNG o secuencia del libro mayor). Asegúrate de que la lógica esté estimada suficientemente por simulateTransaction . Si superas los límites de red (tamaño de entrada, memoria), modifica u optimiza el contrato. |
$OPERATION_INSUFFICIENT_REFUNDABLE_FEE | La tarifa de recurso reembolsable no fue suficiente para cubrir los recursos reembolsables consumidos, es decir, no suficiente para pagar los eventos emitidos o extensiones TTL. | La solución más sencilla es aumentar la tarifa de recurso de forma incondicional; las tarifas no gastadas se reembolsan. simulateTransaction estima tarifas reembolsables pero no puede predecir el costo real de las extensiones TTL debido a la volatilidad del estado del libro mayor. Por lo tanto, simulateTransaction no siempre puede predecir la tarifa que se cobrará realmente. |
INVOKE_HOST_FUNCTION_ENTRY_ARCHIVED | La transacción intenta acceder a una entrada archivada del libro mayor, por ejemplo, cuando la huella contiene una clave para una entrada persistente archivada de Soroban. Este fallo ocurre antes de que se cree el host de Soroban, por lo que no está relacionado con la lógica del contrato. | Restaura la entrada archivada utilizando la operación RestoreFootprintOp. simulateTransaction normalmente informa entradas archivadas, pero una entrada puede archivarse después de que ocurrió la simulación de la transacción. |
INVOKE_HOST_FUNCTION_TRAPPED , diagnostics: HostError(Storage, LimitExceeded). | La función host intentó acceder a una entrada del libro mayor fuera de la huella. Los eventos diagnósticos especifican la entrada faltante exacta. simulateTransaction normalmente debería devolver la huella válida, por lo que si se usa simulateTransaction , probablemente: a) el contrato genera claves no deterministas (ej., derivadas de RNG o secuencia del libro mayor), b) el contrato tiene lógica no determinista que resulta en el acceso a un conjunto diferente de entradas (ej., un contrato 'lotería' que transfiere de forma no determinista a la dirección A o a la direccion B). | Si no se usa simulateTransaction , corrige el código cliente para construir la huella correcta. Si usas simulateTransaction , corrige el contrato o la huella: evita claves no deterministas y añade todas las claves que puedan ser accedidas en cualquier escenario (ej., las entradas de saldo para A y B en el ejemplo del contrato 'lotería'). |
INVOKE_HOST_FUNCTION_TRAPPED , diagnostics: HostError(WasmVm, InvalidAction) | Fallo en un contrato Wasm, típicamente un panic!() . Los eventos diagnósticos pueden proporcionar información más detallada, pero no siempre, ya que los mensajes panic!() no se incluyen en las compilaciones Wasm. | Corrige la lógica del contrato. Considera usar panic_with_error!() y aumentar las ejecuciones de simulateTransaction y las pruebas unitarias. |
INVOKE_HOST_FUNCTION_TRAPPED , diagnostics: HostError(Auth, InvalidAction) "Llamada a función no autorizada para la dirección <'ADDRESS'>" | La transacción no tenía la carga de autorización necesaria para satisfacer la llamada a la función require_auth para una <’ADDRESS’> dada. Es poco probable que esto ocurra cuando se usa simulateTransaction , pero aún es posible si los argumentos de require_auth dependen del estado volátil del libro mayor (ej., si require_auth contiene el número de secuencia del libro mayor). | Adjunta la carga de autorización adecuada a la transacción, usualmente a través de simulateTransaction . Asegura que las cargas de autorización sean deterministas y dependan solo de los argumentos de invocación. |
INVOKE_HOST_FUNCTION_TRAPPED , diagnostics: HostError(Auth, <'error code'>) | Error de autenticación, como firma faltante/expirada/incorrecta o nonce reutilizado. Estos errores no siempre aparecen en la respuesta de simulateTransaction a menos que la carga de autorización firmada completa se use en la solicitud de simulateTransaction . Los eventos diagnósticos también tendrán una explicación más detallada del error. | Corrige la carga de autenticación de acuerdo con el error (ej., usa la firma adecuada, nonce nuevo, etc.). Considera ejecutar simulateTransaction con todas las firmas para una depuración más rápida. |
INVOKE_HOST_FUNCTION_TRAPPED , HostError(<'some other code'>) | Un error arbitrario de ejecución, como acceder a un valor fuera de los límites del contenedor, desbordamiento en aritmética i128, tipo de argumento de invocación incorrecto, etc. El código de error debería proporcionar una idea general de qué está fallando, pero consulta los eventos diagnósticos para más detalles. | Corrige la lógica del contrato o los argumentos de invocación. Se puede hacer una depuración adicional con más ejecuciones de simulateTransaction y pruebas unitarias. |