How to decode the return values after executing forwarder.execute() in Defender?

In OpenZeppelin Defender, how can I retrieve the return values from the target business contract?

For example, in my registry.sol, I have added the getAllData() function, and in relay.js, I can see:

const res = await forwarder.execute(request, signature, { gasLimit });

How can I obtain the list of data returned by the getAllData() function?

In relay.js, the result returned after executing the forwarder.execute() function is as follows; is the result of the business contract call contained in the data field? How can it be decoded?

{
  gasPrice: BigNumber { _hex: '0x05f65e06', _isBigNumber: true },
  chainId: 11155111,
  hash: '0x7172f65ab5b0d6d2ccded5745f4d686ae4323e3c11971bcdb9067919f6e1138d',
  transactionId: '8d7036e6-4214-454a-96c9-a89cfdbd1288',
  value: BigNumber { _hex: '0x00', _isBigNumber: true },
  gasLimit: BigNumber { _hex: '0x100590', _isBigNumber: true },
  to: '0x170EbAFb7c0b4F88309C5067BB6dd64B8Dc77bDb',
  from: '0xb676ad369e95d86435dacd64097e6586b42ed015',
  data: '0x47153f820000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000014000000000000000000000000040d4cc1a0dcb9bfb0b717a1d822ae5cbeae316b6000000000000000000000000728fabce41646c80abcdab3eb361d014363ff135000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000042d10fa28000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041553c5f5d3d434c25986297a9af223ad7331635c59de1d21bb28edda92978ed2012bf84e7dfb8042468ee6bdc2a178b53d7bbd0d5f67b0ec72d16cec01aa283291b00000000000000000000000000000000000000000000000000000000000000',
  nonce: 35,
  status: 'sent',
  speed: 'fast',
  validUntil: '2023-12-04T10:44:11.302Z',
  createdAt: '2023-12-04T02:44:11.929Z',
  sentAt: '2023-12-04T02:44:11.929Z',
  pricedAt: '2023-12-04T02:44:11.929Z',
  isPrivate: false,
  wait: [Function (anonymous)]
}

Attached: The content of the registry.sol contract is as follows:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/metatx/ERC2771Context.sol";
import "@openzeppelin/contracts/metatx/MinimalForwarder.sol";

contract Registry is ERC2771Context {  
  event Registered(address indexed who, string name);

  mapping(address => string) public names;
  mapping(string => address) public owners;

  constructor(MinimalForwarder forwarder) // Initialize trusted forwarder
    ERC2771Context(address(forwarder)) {
  }

  function register(string memory name) external {
    require(owners[name] == address(0), "Name taken");
    address owner = _msgSender(); // Changed from msg.sender
    owners[name] = owner;
    names[owner] = name;
    emit Registered(owner, name);
  }
  
    string[] public users;

    function addString(string memory newValue) external {
        users.push(newValue);
    }

    function getArrayLength() external view returns (uint256) {
        return users.length;
    }

function getAllData() external view returns (string[] memory) {
    return users;
}

}

Hi! Not sure if I understood your issue. I think what you need is to instantiate Registry contract and call getAllData() funtion. But that seems out of the scope of Defender.

Thanks!

I had to do some digging into the very little information that you provided, but here it is...

First of all, what network does all of this take place on?

The chainId: 11155111 attribute in your transaction's receipt answers this question.

After googling it, the network turns out to be Ethereum sepolia testnet.

Then, I took the data attribute, and I split it into the function-selector (first 4 bytes) followed by sections of 64 bytes each:

47153f82
0000000000000000000000000000000000000000000000000000000000000040
0000000000000000000000000000000000000000000000000000000000000140
00000000000000000000000040d4cc1a0dcb9bfb0b717a1d822ae5cbeae316b6
000000000000000000000000728fabce41646c80abcdab3eb361d014363ff135
0000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000f4240
000000000000000000000000000000000000000000000000000000000000000a
00000000000000000000000000000000000000000000000000000000000000c0
0000000000000000000000000000000000000000000000000000000000000004
2d10fa2800000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000041
553c5f5d3d434c25986297a9af223ad7331635c59de1d21bb28edda92978ed20
12bf84e7dfb8042468ee6bdc2a178b53d7bbd0d5f67b0ec72d16cec01aa28329
1b00000000000000000000000000000000000000000000000000000000000000

The only information which seems immediately meaningful is in the following two sections:

00000000000000000000000040d4cc1a0dcb9bfb0b717a1d822ae5cbeae316b6
000000000000000000000000728fabce41646c80abcdab3eb361d014363ff135

Each of these sections potentially holds an address (the first 24 bytes are all zero, and the remaining 40 bytes are potentially an address).

Address 0x40d4cc1a0dcb9bfb0b717a1d822ae5cbeae316b6 is an externally-owned account.

Address 0x728fabce41646c80abcdab3eb361d014363ff135 is a smart-contract account.

The only transaction on the smart contract is its creation, executed by the externally-owned account.

This contract is not verified (its source code is not visible), so it is hard to say anything further.

Regardless of all of that, perhaps the remaining sections in the data field which I have listed above can shed some more light here, but you'll need to provide more context, such as the relevant part in your contract's code, and specifically that of function getAllData...

1 Like

Hi @barakman, I still don't see how this is related to Defender, I would suggest to ask this question to contracts team.

Thanks!

Dude, I'm not the one who asked this question, I just responded to it with a bit of insight which I've been able to dig out of the given information.

1 Like

@barakman Apologies, I thought you were the author, thanks so much for the answer :slight_smile:

1 Like