19

I have a contract with numerous complex structs. Is it possible for a second contract to iterate over this data directly?

I can't really use public accessor/getter methods as it's not possible to use structs externally, so I would have to flatten the data structure (probably make expensive copies of it too).

eth
  • 85,679
  • 53
  • 285
  • 406
slothbag
  • 433
  • 3
  • 10

2 Answers2

21

A contract cannot access another contract's storage directly.

Given contracts C1 and C2, C1 can only access the storage of C2 by invoking a method on C2 that returns data from C2's storage.

Since you are writing C2, you can access its storage from C1 and can make progress. A more specific question may help provide a more specific answer about designing your contracts (structs, flattening, copies...).


Related, there are 3 things that a contract can access from another contract: balance, code, code size.

The underlying mechanisms for doing so are the following EVM opcodes, from the Yellow Paper:

BALANCE: Get balance of the given account

EXTCODECOPY: Copy an account’s code to memory.

EXTCODESIZE: Get size of an account’s code.

Per Paul's comment, address.balance works in Solidity.

eth
  • 85,679
  • 53
  • 285
  • 406
  • 1
    minor nit: You can access another contract's balance. address.balance works AFAICT. – Paul S Feb 16 '16 at 00:59
  • Upvoted, thanks for the reminder and I'll update answer since there's EXTCODECOPY too... – eth Feb 17 '16 at 02:56
  • 1
    @eth What if 2nd contract is contunation of first contract i.e. contract A{struct egStruct{uint number;bool value;//....}mapping (uint => egStruct) structMapping;//...code...}`

    contract b is A { //...code }

    In this case also, is it not possible to access a mapping (which is not public). Actually my specific question would be, If in this case I want to access the struct trough mapping of contract A from contract b of, then can I do it? (I tried and I am getting blank values for all)

    – 11t Mar 28 '17 at 22:03
  • 1
    @Rajat Write an accessor in A and you might be able to call it in b like super.nameOfAccessor(). This would be different from b accessing the storage of A directly. – eth Mar 31 '17 at 08:38
  • We cannot change the storage of a mapping variable of another contract right? – alper Jan 20 '24 at 14:32
  • @alper You're right except if the other contract had a "setter" function, then it could be done by calling the setter? – eth Jan 22 '24 at 07:40
  • @eth Like you mentioned I think that would be the only way through calling the setter of the other contract that will update the storage of the mapping variable – alper Jan 22 '24 at 12:15
4

Technically, all data available to any contract has to be publically available, because anyone can run a node and reproduce the entire lifetime of the contract. This means that yes, it is strictly possible for one contract to access the internal data of another, even if there is no built in way to do it.

The first answer that comes to mind is to create an oracle service with an exposed method you can call that accept the contract id and the data you want, re-runs or reads the blockchain to get it, and returns it to the caller.

I don't know if anyone has created something like this yet, but if it's vitally important for you to be able to read another contract's data, you could certainly do it.

TL;DR Yes you can, but it requires you to create a separate oracle service to do it for you, as there is no built-in method to allow it.

Benubird
  • 193
  • 6