Incorrect logs decoding of errors in cross-contract calls

Contract B calls a method in contract A which fails an invariant. Both contracts have error-enum structs like so:

// contract A
pub enum Error {
    ContrABlah1: (),
    ContrABlah2: ()
}

// contract B
pub enum Error {
    ContrBBlah1: (),
    ContrBBlah2: ()
}

invariant in method in contract A fails:

// invariant in method in contract A
require(false, Error::ContrABlah2);

if I do the following:

// fn in contract B
contr_A.call_fn_that_fails_invariant();

the decoded logs in the TS SDK show that the decoded error is: ContrBBlah2 (even though this wasn’t the error message). Through tests, I have determined that if an error of index i in the enum definition as above in contract A is the failed message, the error of index i in the enum definition of contract B will be the one displayed.

Minimal example: callee-errors.sw · GitHub

Expected error message in decoded logs: CaleeError5
Actual error message in decoded logs: CallerError6940

This has been a bug in all the earlier versions of the TS SDK. I haven’t tested this for the Rust SDK yet.

@Dhaiwat10 @Nazeeh21 @IGI-111

Hey @theAusicist, thanks for reporting it. Let me confirm it with the team and get back to you.

1 Like

the exact error trace is:

 FuelError: The transaction reverted because a "require" statement has thrown "CallerError6940".
      at extractTxError (node_modules/@fuel-ts/account/src/providers/transaction-request/helpers.ts:43:5)
      at _Provider.extractDryRunError (node_modules/@fuel-ts/account/src/providers/provider.ts:1725:11)
      at _Provider.getTransactionCost (node_modules/@fuel-ts/account/src/providers/provider.ts:1136:7)
      at processTicksAndRejections (node:internal/process/task_queues:95:5)
      at FunctionInvocationScope.getTransactionCost (node_modules/@fuel-ts/program/src/functions/base-invocation-scope.ts:239:6)
      at FunctionInvocationScope.fundWithRequiredCoins (node_modules/@fuel-ts/program/src/functions/base-invocation-scope.ts:261:7)
      at FunctionInvocationScope.call (node_modules/@fuel-ts/program/src/functions/base-invocation-scope.ts:360:12)

TS SDK version: fuels v0.88.0

It appears that the functionInvocationScopes in BaseInvocationScopes doesn’t include the abis of contracts other than the calling contract

this line is where the main and otherContractsAbis abis are grabbed:

this.transactionRequest.abis = getAbisFromAllCalls(this.functionInvocationScopes);

// value of this.transactionRequest.abis.otherContractsAbis is {}

Here’s where the logs are decoded:

const interfaceToUse = new Interface(externalAbis[receipt.id] || mainAbi);

// since externalAbis is {}, it always defaults to "mainAbi"

I fixed this by using .addContracts to the function scope before calling the contract like so:

// In TS
await caller.functions.call_callee_that_fails(toContract(callee)).addContracts([callee]).call()

// yields the correct error: CalleeError5

this is a bug, no doubt. I shouldn’t have to use .addContracts for Fuel to be able to figure out where the error originated from.

Edit: Posted an issue in the fuels-ts Github