Depurar Errores de Contrato
Para entender cómo depurar errores de Soroban, primero debemos entender cómo los errores están asociados con cada paso del flujo de transacción, y los errores probables y comunes en cada paso del flujo de transacción.
Flujo General de Transacción
El proceso típico de envío de transacciones se puede descomponer en los siguientes pasos secuenciales, excluyendo interacciones externas como las interacciones con billeteras. Cada paso tiene su propio conjunto de errores potenciales:
-
Preflight (opcional):
- Qué sucede: Este paso implica ejecutar una transacción en modo 'simulación', lo cual graba las entradas necesarias en el ledger, instrucciones de CPU, autorizaciones requeridas, etc.
- Fallas comunes: Preflight es similar a ejecutar transacciones en Core con recursos al máximo, acceso al ledger sin restricciones, y sin tarifas. Por lo tanto, los errores generalmente implican exceder el límite de la red o encontrar problemas de lógica de contrato.
-
Core Acepta la Transacción:
- Qué sucede: Core evalúa cada transacción para decidir si la acepta o la rechaza. Las transacciones rechazadas suelen ser inválidas o tienen tarifas insuficientes, especialmente durante períodos de alto tráfico.
- Fallas comunes: Transacciones inválidas, como aquellas con tarifas de recursos incorrectas o valores de recursos excesivamente altos, y huellas inválidas son rechazadas. Otros errores comunes incluyen firmas de transacción incorrectas o fondos insuficientes en la cuenta de origen. Las transacciones válidas solo pueden ser rechazadas debido a una baja tarifa de inclusión.
-
Core Incluye la Transacción en el Ledger:
- Qué sucede: Las transacciones aceptadas permanecen en la memoria de Core hasta que son incluidas en el ledger o son expulsadas.
- Fallas comunes: Las transacciones pueden no ser incluidas en el ledger si tienen una baja tarifa de inclusión y necesitan ser expulsadas durante picos de tráfico para acomodar más transacciones.
-
Core Aplica la Transacción al Ledger:
- Qué sucede: Core ejecuta la transacción incluida.
- Fallas comunes: Este paso tiene el rango más amplio de errores potenciales. Las fallas podrían incluir el acceso a entradas archivadas, agotamiento de recursos, acceso a entradas fuera de la huella especificada, o encontrar fallas de lógica dentro del contrato.
Para más información sobre tarifas, visita Tarifas, Límites de Recursos y Medición.
Errores de Soroban Detallados
1. Preflight
Los errores aquí son devueltos por el host y propagados a través de RPC. Esto no cubre otros posibles errores (p. ej. errores de red, errores en RPC, etc.)
Error | Explicación | Corregir |
---|---|---|
HostError(Budget, LimitExceeded) | Se ha excedido un límite de recurso definido por la red (ya sea instrucciones o memoria). Consulta los eventos de diagnóstico para verificar qué límite se ha excedido (99% de las veces esto será instrucciones). | Optimiza el contrato para consumir menos recursos. |
HostError(Storage, MissingValue) | Intentando acceder a una entrada de ledger que no existe. 99,9% de las veces esto significa que el contrato o el Wasm no existen en el ledger (los casos restantes solo pueden aparecer cuando no usas el SDK de Soroban para contratos). Los eventos de diagnóstico deberían indicar qué entrada falta. | Despliega el contrato o Wasm respectivo. |
HostError(WasmVm, InvalidAction) | Hubo una falla en algún contrato de Wasm, típicamente un panic!() . Los eventos de diagnóstico podrían proporcionar más información detallada, pero no siempre, ya que los mensajes de panic!() no están incluidos en las compilaciones de Wasm. | Corrige la lógica del contrato o los argumentos de invocación. Dado que la razón más típica para encontrar esto es panic!() , podría ser una buena idea usar panic_with_error!() en lugar de panic!() en todos lados. Se recomienda escribir más pruebas unitarias. |
HostError(<some other code>) | Un error de ejecución arbitrario, como acceder a un valor fuera de los límites del contenedor, un desbordamiento en aritméticas de i128, un tipo de argumento de invocación incorrecto, etc. El código de error debería ofrecer una idea general de qué está fallando, pero consulta los eventos de diagnóstico para obtener detalles. | Corrige la lógica del contrato o los argumentos de invocación. Se puede hacer depuración adicional a través de pruebas unitarias. |
2. Core Acepta la Transacción
El error es devuelto por Core inmediatamente como respuesta a la transacción enviada y se muestra al usuario a través de RPC. Hay algunos campos relacionados con errores en la respuesta de Core:
status
contiene uno de los pocos códigos gruesos: 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 XDR codificado que, en caso de estado “ERROR”, contendrá el código de error a nivel de transacción que comienza con “tx”, comotxMALFORMED
.- Los errores de transacción
txFAILED
en esta etapa corresponden a errores de validación específicos de la operación, por lo que se debería examinar el código de resultado de la operación. diagnostics
contendrá información adicional sobre el error en el formato de evento de diagnóstico de Soroban. Esto se devolverá típicamente para errores de transaccióntxSOROBAN_INVALID
, pero puede ser utilizado más extensamente en el futuro.
Error de Core | Explicación | Corregir |
---|---|---|
status: TRY_AGAIN_LATER | Ya hay una transacción de la misma cuenta fuente en memoria. La transacción ha sido rechazada debido a una tarifa de inclusión demasiado baja y ha sido re-enviada demasiado pronto. | Espera a que la transacción anterior se aplique y vuelve a enviar, o cambia a cuentas de canal si se necesita un mayor rendimiento. Espera más tiempo antes de volver a enviar 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 de Soroban no es la única operación en la transacción; falta la extensión de Soroban; La tarifa o la tarifa de recursos es negativa; La tarifa de recursos es mayor que la tarifa de transacción; Los recursos declarados son más altos que los límites en toda la red (p. ej., quiere usar 200M instrucciones, mientras que el límite global es solo 100M). | Asegúrate de que la transacción esté bien formada y que la tarifa total de la transacción sea lo suficientemente alta. |
status: ERROR , error: txINSUFFICIENT_FEE | Lo más probable: La tarifa de inclusión es demasiado baja durante el aumento de tráfico. Improbable: La tarifa de inclusión es menor que el mínimo de la red (es decir, menor que 100 stroops). | Aumenta la tarifa de transacción o espera hasta que haya menos tráfico. |
status: ERROR , error: txSOROBAN_INVALID , diagnostics: “transaction $RESOURCE_NAME resources exceed network config limit” or similar | Algún valor de recurso especificado en la transacción excede el límite de la red. Por ejemplo, esto desencadenaría si la transacción especifica 200M instrucciones, mientras que el límite de la red es solo 100M. Nota que esto no tiene nada que ver con lo que la transacción realmente hace. Solo se examinan las declaraciones de recursos en este momento. | Optimiza el contrato para ajustarse al límite de recursos y especifica el valor respectivo en la transacción (típicamente ejecutando preflight). En caso de que haya un ‘margen de seguridad’ demasiado grande para los recursos (p. ej. +20% dado que la transacción ya necesita el 90% del límite de la red), reduce la declaración de recursos para ajustarse al límite. |
status: ERROR , error: txSOROBAN_INVALID , diagnostics: mensaje relacionado con la huella | Hay varios requisitos de huella, como no debería contener claves duplicadas, no debería contener entradas no soportadas por Soroban, etc. El mensaje de diagnóstico especificará los detalles de qué requisito se ha violado. | Corrige la huella. Esto solo debería ocurrir si la huella ha sido construida o modificada manualmente; las huellas de preflight siempre deberían pasar todas las verificaciones. |
status: ERROR , error: txSOROBAN_INVALID , diagnostics: "transaction sorobanData.resourceFee is lower than the actual Soroban resource fee" | La tarifa de recursos especificada en la transacción no es suficiente para cubrir los recursos especificados en la transacción. Nota que esto no tiene nada que ver con lo que la transacción realmente hace. Solo se examinan las declaraciones de recursos en este momento. | Aumenta la tarifa de recursos. Esto normalmente solo debería ocurrir cuando los recursos se calculan o modifican manualmente. Preflight siempre calcula la tarifa de recursos suficiente. |
status: ERROR , error: txFAILED , operation error: EXTEND_FOOTPRINT_TTL_MALFORMED | Uno de los requisitos de huella para la operación ExtendFootprintTTL no se ha cumplido: - Solo las entradas de ledger de Soroban pueden ser extendidas. - Solo las huellas de solo lectura deberían estar pobladas. - 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. Preferiblemente, las bibliotecas del lado del cliente deberían asegurarse de que las transacciones de extensión TTL estén bien formadas. |
status: ERROR , error: txFAILED , operation error: RESTORE_FOOTPRINT_MALFORMED | Uno de los requisitos de huella para la operación RestoreFootprint no se ha cumplido: solo las entradas de ledger persistentes de Soroban pueden ser restauradas; solo las huellas de lectura y escritura deberían estar pobladas. | Asegúrate de que las huellas cumplan con los requisitos. Preferiblemente, las bibliotecas del lado del cliente deberían asegurarse de 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; estos incluyen errores como saldo de cuenta insuficiente, mal número de secuencia, etc. Estos errores generalmente son fáciles de interpretar según el nombre. | Corrige el problema correspondiente al código. Aquí no hay nada específico de Soroban. |
3. Core Incluye la Transacción en el Ledger
Hay instancias cuando Core no parece incluir la transacción en el ledger, se recomienda la siguiente práctica recomendada:
Error | Explicación | Corregir |
---|---|---|
La transacción parece 'atascada' y nunca se aplica | No hay un informe de error directo aquí porque la red no puede comunicar razonablemente qué transacción elimina (p. ej., Node A ha eliminado la transacción no significa necesariamente que algún otro Node B la ha eliminado). Al consultar contra un endpoint de datos, la transacción podría ser reportada como ‘pendiente’. | Introduce límites de tiempo de transacción del lado del cliente. Si una transacción no se ha aplicado dentro de 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 un límite de ledger. Tener un límite permite al desarrollador volver a enviar la transacción después de que se supere el límite de tiempo y aumentar opcionalmente la tarifa si persiste el error. |
Se recomienda encarecidamente que todas las transacciones incluyan un límite de tiempo o un límite de ledger.
4. Core Aplica la Transacción al Ledger
Los errores y eventos de diagnóstico se registran en el flujo de metadatos de transacción emitido por la instancia de Core cuando se está cerrando el ledger. Luego, el RPC ingesta los metadatos de la transacción (metadata tx) y permite a los desarrolladores consultar los metadatos tx.
Cuando ocurre un error, Core almacena algunos campos relacionados con errores en los metadatos del resultado de la transacción:
- El resultado de la transacción (error) será
txFAILED
para fracasos relacionados con Soroban (o cualquier falla de operación en general). A veces es posible obtener otros errorestx$ERROR
(comotxBAD_AUTH
), pero estos no están relacionados con Soroban y son más un caso extremo. - 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 los eventos de diagnóstico deberían ser utilizados típicamente para entender el error exacto. - Si la instancia de Core que produce metadatos tiene habilitados diagnósticos de Soroban (lo cual generalmente debería tener), los metadatos también contendrán eventos de diagnóstico con información de error más detallada.
- Ten en cuenta que puede haber algunas lagunas en la cobertura de eventos de diagnóstico. Dado que esto no es un cambio de protocolo, Core puede añadir más eventos de diagnóstico en futuras versiones.
Nota: $OPERATION se refiere a cualquiera de las operaciones de Soroban: INVOKE_HOST_FUNCTION
, RESTORE_FOOTPRINT
y EXTEND_FOOTPRINT_TTL
.
Errores y Diagnósticos | Explicación | Corregir |
---|---|---|
$OPERATION_RESOURCE_LIMIT_EXCEEDED , diagnostics: mensaje especificando qué límite de recurso se ha excedido | La transacción ha excedido el límite de recurso durante la ejecución. Para la mayoría de los recursos (instrucciones, bytes leídos, bytes escritos), esto no tiene nada que ver con el límite de la red; es el límite especificado por la transacción. Por ejemplo, una transacción tiene especificadas 10M instrucciones pero consume al menos 10M + 1 instrucción y falla inmediatamente. Los eventos de diagnóstico especifican qué límite se ha excedido y contienen tanto el límite mismo como el valor que la transacción intentó consumir. | Si se excede el límite especificado en la transacción, aumenta el respectivo recurso declarado en la transacción. Si la validación previa determinó los límites de recursos, la razón probable para excederlos es una lógica dependiente del estado volátil del ledger (por ejemplo, RNG o secuencia del ledger). Asegúrate de que la lógica esté suficientemente estimada por la validación previa. Si se superan los límites de la red (tamaño de entrada, memoria), modifica/optimiza el contrato. |
$OPERATION_INSUFFICIENT_REFUNDABLE_FEE | La tarifa de recursos reembolsable no fue suficiente para cubrir los recursos reembolsables consumidos, es decir, no hay suficiente para pagar por eventos emitidos o extensiones de TTL. | La solución más simple es aumentar la tarifa de recursos incondicionalmente; las tarifas no gastadas son reembolsadas. La validación previa estima las tarifas reembolsables, pero no puede predecir el costo real de las extensiones de TTL debido a la volatilidad del estado del ledger. Por lo tanto, la validación previa no siempre puede predecir la tarifa que realmente se cobrará. |
INVOKE_HOST_FUNCTION_ENTRY_ARCHIVED | La transacción intenta acceder a una entrada de ledger archivada, por ejemplo, cuando la huella contiene una clave de ledger para una entrada de ledger Soroban persistente archivada. Nota, esta falla ocurre antes de que el host de Soroban siquiera sea creado, por lo que esto no está relacionado con la lógica del contrato. | Restaura la entrada archivada utilizando la operación RestoreFootprintOp. La validación previa generalmente informa las entradas archivadas, pero una entrada puede ser archivada después de que se haya realizado la simulación de validación previa. |
INVOKE_HOST_FUNCTION_TRAPPED , diagnósticos: HostError(Storage, LimitExceeded). | La función del host intentó acceder a una entrada de ledger fuera de la huella. Los eventos de diagnóstico especifican la entrada exacta faltante. La validación previa normalmente debería devolver la huella válida, por lo que en el caso de que se esté utilizando la validación previa, es probable que: a) El contrato genera claves no determinísticas (por ejemplo, las deriva de RNG o de la secuencia del ledger), b) El contrato tiene lógica no determinística que resulta en el acceso a un conjunto de entradas diferente (por ejemplo, un contrato de ‘lotería’ que realiza transferencias no determinísticas a la dirección A o dirección B). | Si no se utiliza la validación previa, corrige el código del cliente para crear la huella correcta. Si se utiliza la validación previa, corrige el contrato o la huella: evita claves no determinísticas, y agrega todas las claves que se pueden acceder en cualquier escenario, (por ejemplo, entradas de balance para A y B en el ejemplo del contrato de ‘lotería’). |
INVOKE_HOST_FUNCTION_TRAPPED , diagnósticos: HostError(WasmVm, InvalidAction) | Fallo en un contrato Wasm, típicamente un panic!() . Los eventos de diagnóstico pueden proporcionar información más detallada, pero no siempre, ya que los mensajes de panic!() no se incluyen en las compilaciones de Wasm. | Corrige la lógica del contrato. Considera usar panic_with_error!() e incrementar las ejecuciones de validación previa y las pruebas unitarias. |
INVOKE_HOST_FUNCTION_TRAPPED , diagnósticos: HostError(Auth, InvalidAction) "Llamada a función no autorizada para la dirección <'ADDRESS'>" | La transacción no tenía una carga de autorización necesaria para satisfacer la llamada a la función del host require_auth para un dado <’ADDRESS’>. Es poco probable que esto ocurra cuando se utiliza la validación previa, pero aún puede ser posible si los argumentos require_auth dependen del estado volátil del ledger (por ejemplo, si require_auth contiene el número de secuencia del ledger) | Adjunta la carga de autorización adecuada a la transacción, generalmente a través de la validación previa. Asegúrate de que las cargas de autorización sean determinísticas y dependan solo de los argumentos de invocación. |
INVOKE_HOST_FUNCTION_TRAPPED , diagnósticos: HostError(Auth, <'error code'>) | Error de autenticación, como firma faltante/caducada/inválida o nonce reutilizado. Estos errores no siempre aparecerán en la validación previa a menos que toda la carga de autorización firmada se use en la solicitud de validación previa. Los eventos de diagnóstico también tendrán una explicación más detallada sobre cuál fue el error. | Corrige la carga de autenticación según el error (por ejemplo, usa la firma adecuada, un nuevo nonce, etc.). Considera usar la validación previa con todas las firmas para una depuración más rápida. |
INVOKE_HOST_FUNCTION_TRAPPED , HostError(<'some other code'>) | Un error de ejecución arbitrario, como acceder a un valor fuera de los límites del contenedor, desbordamiento en aritméticas i128, tipo de argumento de invocación incorrecto, etc. El código de error debe proporcionar una idea general de qué está fallando, pero consulta los eventos de diagnóstico para más detalles. | Corrige la lógica del contrato o los argumentos de invocación. La depuración adicional puede hacerse a través de más ejecuciones de validación previa y pruebas unitarias. |