1

We are running a safe indexing service using the graph protocol and are indexing all the safes created in gnosis chain since block 17265698 (which is meaningful to our particular needs). As part of this we perform an eth_call at the block the safe was created to find out its owners (as well as listen for owner change events to update the safe's owners in our subgraph). We ran into a very unusual situation, there is a specific safe, 0x3af12EcC0A8Ef31cc935E0B25ea445249207d21A on gnosis chain that was created in transaction 0xbd72451723d4a9cc3a039db3501ac105b3eba0f1deb4d4efb9ffd7c3408b6d83 in block 21735473 that will revert if you call getOwners() on it. We are very confused as to why this would ever happen since the getOwners() contains no require(). Many blocks after this safe was created, there was a subsequent transaction to assign owners to this safe, so that in the latest block, calling getOwners() no longer reverts. However, when building up our index, our subgraph queries a each new safe for its owners at the time of creation so we have a historical record of who owned the safe. The revert encountered when calling getOwners() at block 21735473 on gnosis chain breaks our subgraph's indexing process. Could you help us to understand why this happens? it looks like this safe initially didn't have any owners. That is a very unusual situation, but certainly calling getOwners() on a safe that has no owners should not cause a revert, right?

Using a gnosis chain archive node you can see this here: (0x14BA831 is 21735473)

POST https://xdai-archive-df.xdaichain.com/
{
    "jsonrpc": "2.0",
    "method": "eth_call",
    "params": [{
      "to": "0x3af12EcC0A8Ef31cc935E0B25ea445249207d21A",
      "data": "0xa0e67e2b"
    }, "0x14BA831"],
    "id": 1
}

returns

{
    "jsonrpc": "2.0",
    "error": {
        "code": -32015,
        "message": "VM execution error.",
        "data": "Reverted 0x"
    },
    "id": 1
}

And if you use the latest block you can see it works, and if you use a block earlier you can see that the contract doesn't exist yet. but between block 21735473 and 21738156 for some reason this call reverts. Notably this did happen a few hundred blocks after the latest Gnosis chain hard fork--maybe related?

Any idea what might be going on here and is there a bug in the Gnosis Safe contract that could be causing this?

1 Answer 1

0

setup was not called until block 21738156: https://blockscout.com/xdai/mainnet/tx/0xdf352729d9ecc1ae13d0beda603bfdb7edc2c2304268e3fecbf101630a558e79 so getOwners() it's expected to fail.

2
  • So generally it seems that the setup() function is called via the calldata that is passed to the proxy factory's createProxy(). This is the first time I've encountered a safe that didn't call setup() as part of the createProxy(). So it seems that these types of safes are in an awkward state, i.e. there are certain things you are not allowed to ask it, like it's owners. Is there a reason why safes are allowed to exist in this state? Couldn't anyone actually claim ownership of a safe in such a state? Apr 22, 2022 at 14:15
  • It looks like in the OwnerManager.sol we leverage a mapping to represent a linked list of owners for the safe, and in getOwners() we build up an array from this mapping by following that linked list. The logic, though, does not seem to work when there are no owners. The while loop that drives this gets stuck in a never ending loop. could we just return an empty array when the ownerCount is 0? Apr 22, 2022 at 14:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.