trufflesuite / truffle-compile

Compiler helper and artifact manager
22 stars 46 forks source link

Support multiple compilers #69

Open cgewecke opened 6 years ago

thomaseizinger commented 6 years ago

Is this ticket intended to track adding support for specifying the language parameter of the solc-js input object?

https://github.com/trufflesuite/truffle-compile/blob/aae0fb1e66bbeaf70bf9450bae2888cf109b1c82/index.js#L73

cgewecke commented 6 years ago

@thomaseizinger Yes, it's intent is that we should make it possible to target multiple languages. Do you have a language in mind?

thomaseizinger commented 6 years ago

Yes, it would be really great if truffle would support assembly input to test contracts that are written in pure assembly code.

However, solc-js only supports Solidity for now AFAIK so it is kind of an upstream blocker.

cgewecke commented 6 years ago

@thomaseizinger Have looked into this a bit and would like your advice. . .

We can add the ability make truffle compile run assembly compilation (via docker or native solc) and collect this data, but what should Truffle do with it? How are you using these outputs / what would you like Truffle to make possible here?

thomaseizinger commented 6 years ago

I got the same error message when trying to compile with assembly and solc-js. I think solc-js is limited to compiling Solidity code at the moment.

Currently, we are doing what you did - use the native solc and call it via a docker container to compile our assembly contracts.

What you are experienced is on purpose. There is no ABI if you write assembly code. If you look at the documentation of --assemble you can see that all other arguments are ignored. You could think of those contracts as "single function contracts".

The truffle integration I anticipate would be to use all the infrastructure that is there (stuff you get with truffle init) and the overall process of truffle compile/migrate/test but just having assembly contracts instead of Soliditiy ones.

Interaction with those contracts is done by sending regular transactions to it (as there is no ABI). That could be done by using the existing sendTransaction.

cgewecke commented 6 years ago

@thomaseizinger Excellent thank you.

If the interface was as basic as the following, would that be enough for your use case?

const AssemblyRoutine = artifacts.require('AssemblyRoutine');

const instance = await AssemblyRoutine.new() // This should be possible.

await instance.sendTransaction({
  data: ... // Advanced encoding knowledge necessary. 
}) 
thomaseizinger commented 6 years ago

Yeah looks good to me!

Would the new() function deploy the contract?

cgewecke commented 6 years ago

@thomaseizinger Yes new deploys. Can you think of any other conveniences that would be helpful?

thomaseizinger commented 6 years ago

Is there any reason for not going with the current deployed notation?

I am not sure where or even if there should be a difference in terms of the test setup. I guess truffle could automatically detect, whether a contract is written in Solidity or EVM-Assembly (maybe based on the file extension?). So from the users perspective, I don't see the need for a different notation than deployed().

I would expect things to work the same as with Solidity contracts. Interaction is of course different as there is no ABI but that should obvious anyway if one is using assembly contracts :)

cgewecke commented 6 years ago

@thomaseizinger Ah yes, deployed would also be there, apologies. You can new any TruffleContract (that's how the instance referenced by deployed is created).

One thing that would be helpful from an implementation standpoint on this end is to have an example contract to deploy, an example transaction to send to it, and maybe some way of verifying that everything worked (like a broadcast event).

It's a little opaque to me how these assembly programs consume the messages sent to them.

thomaseizinger commented 6 years ago

Sure thing :)

Here is a contract that upon invocation (no data needed) selfdestructs to a given address:

{
    0x1000000000000000000000000000000000000001
    selfdestruct
}

1000000000000000000000000000000000000001 is the address the contract will send the money to upon self-destruct. Just replace that with whatever address you would like to use during testing.

In order to check if things worked out, I'd verify the account's balance after the invocation. Just make sure you send ether to the contract upon creation ;-)

In order to deploy this contract, a deploy header is needed. Unfortunately, solc cannot do this at the moment because it ignores all the other parameters (one of them being --bin-runtime which would do that). I opened a ticket for that: https://github.com/ethereum/solidity/issues/3870.

For now, you could compute the deploy header yourself. Here is a go program that does that.

This link may also be useful to get a deeper understanding: https://github.com/CoinCulture/evm-tools/blob/master/analysis/guide.md

cgewecke commented 6 years ago

@thomaseizinger Perfect! Excited to try this out, thank you.

axic commented 6 years ago

The plan is to support Yul (the intermediate language of Solidity) and perhaps LLL. Also it seems the Vyper team is on board to support the same JSON format with having Vyper as a value for the language.