Truffle: [Truffle-Decoder] Allow option to provide contract address

Created on 29 Dec 2018  路  26Comments  路  Source: trufflesuite/truffle

For my tests, I use truffle-compile to compile my contract (instead of using migrations) and the resulting artifact file does not have a networks property (and neither does compiling with solc-js). Instead of migrations, I use Web3.js to deploy my contract onto a Ganache instance running in-memory.

This means that line 134 of contract-decoder.ts will fail:

this.contractNetwork = Object.keys(this.contract.networks)[0];

The next line sets the contract address based on this:

this.contractAddress = this.contract.networks[this.contractNetwork].address;

Not everyone uses truffle migrations to deploy, but we should still allow them to use the decoder as well, I would think?

codec enhancement

Most helpful comment

Yes, he has the objects minus the networks property. I hate the networks property anyway. I'm going to propose later tonight an interface that should be the best of all worlds; you can then take that Harry and see if that works or you'd like to change it up. But long story short, what Adrian is asking is quite simple to implement. It's just deciding the right interface that is a little challenging.

All 26 comments

My current hack is to do the following:

artifact.networks = {
  "1234": { address: deployedAddress },
};

Not exactly sure what the best API is.

Moved this to new issues from icebox because i think this was created when the icebox column in zenhub got moved to the first column

Thanks @seesemichaelj!

Another reason why this PR is important is because it would allow you to decode and track state for contracts that you may not own (i.e. publicly available contracts with an open ABI).

The decoder needs more than just an open ABI; we need the compiler output which implies open source code.

I do think it's a good idea though!

Ah right, the AST as well!

Hm, so, wait, if we ignore the part about being able to decode contracts you don't have artifacts for, the original request should be possible, right? Like if I added an interface for it, so long as Ganache had the artifact it would be able to supply the artifact and address separately? (Does Ganache still only track state for contracts it can decode? Not sure if tracking state for undecoded contracts would have to come first.)

@haltman-at thanks for taking a look at this.

I am not sure how Ganache works, but I'm basing this off of how we're using it for Drizzle Utils.

The thing about artifacts is that you can use Truffle-Compile to generate one, while actually deploying the contract via other means. This means that the deployed address does not always reside with the artifact we have on hand.

In our Drizzle Utils tests, we do just that: we compile a contract using Truffle-Compile, and then separately use Web3 to deploy the contract. So yeah, all I'm asking for is the ability to pass those 2 things (i.e. artifact and deployed address) in separately.

Oh, does Drizzle also use the contract decoder? I didn't realize. I thought it was just Ganache, which is why I was asking to what extent Ganache would be able to use it if I implemented it. In any case yeah this seems like something I should do.

Yea, Drizzle-Utils (which is separate from Drizzle) uses it. Thanks!

FWIW, I believe this library will be used by several tools (both internal and external to Truffle Suite) in 2019

@seesemichaelj agreed.

OK. I guess the question I have then is about these Contract objects. Like, right now the contract decoder requires passing in Contract objects. Do you already have Contract objects you can pass in (that are just lacking addresses), in which case this will be really easy? Or am I going to have to construct them from scratch, from other passed-in artifact info? Not that that should be hard either, just I'll need to find out how to actually do that, because they seem to be imported from some JSON file rather than a JS or TS file...

Yes, he has the objects minus the networks property. I hate the networks property anyway. I'm going to propose later tonight an interface that should be the best of all worlds; you can then take that Harry and see if that works or you'd like to change it up. But long story short, what Adrian is asking is quite simple to implement. It's just deciding the right interface that is a little challenging.

this didn't happen when i was hoping. this is also far from complete. there is probably a handful of places to change things using this solution. the below would go in the lib/interfaces/index.ts file:

interface Contract {
  name: string;
  ast: Ast;
  abi: Abi;
}

interface ContractInstance extends Contract {
  address: string;
}

export function forGenericContract(contract: ContractInstance, relevantContracts: Contract[], provider: Provider): TruffleDecoder {
  return new TruffleDecoder(contract, relevantContracts, provider);
}

export function forTruffleContract(contract: ContractObject, relevantContracts: ContractObject[], provider: Provider): TruffleDecoder {
  let generalizedContract: ContractInstance = {
    name: contract.contractName,
    address: contract.networks[Object.keys(contract.networks)[0]].address,
    abi: contract.abi,
    ast: contract.ast
  };
  return forGenericContract(generalizedContract, relevantContracts, provider);
}

thats the train of thought that i'm going through, but it may be not worth while.

we could also change forContract(...) to have an optional address?: string parameter as the last argument that would be used if defined :man_shrugging:

we could also change forContract(...) to have an optional address?: string parameter as the last argument

This sounds like a much simpler solution. Also, do relevantContracts need to have addresses as well?

No they don't

(Also in favor of address as optional argument.)

That's great then, I vote for the address?: string parameter to forContract(...).

Oh, I see, the Contract object is literally just the artifact. Duh.

OK, so, looking through the contract-decoder code, it looks to me like we can just get by with just inserting a given address, and we don't have to fake up a whole networks object, right? There's nothing that would go wrong if we just skipped that step? This is actually just as simple as inserting the specified address?

Yes, that is my understanding.

Great! Guess I'll do that then. :)

OK, just PR'd #1812 to address this.

Thanks!

Just found this still open for some reason. Closing.

Was this page helpful?
0 / 5 - 0 ratings