2

It seems that if we want to deploy a smart contract (let's call it Target) from another one (let's call it Deployer) in Solidity via new, we spend a gas amount linear in the size of the deployed contract twice. Example:

contract Target {}

contract Deployer {
  function deploy() external returns (Target) {
    return new Target();
  }
}

Here is why we pay for the code of Target twice:

  1. to deploy the Deployer smart contract, which contains the bytecode of Target
  2. to perform the actual transaction which does the deployment via new

Is there a pattern how we can we avoid this double cost? Let's assume the contract is deployed only once, so no costs can be amortized.

1

Depending on what you are trying to achieve exactly, there might be another method, using extcodecopy to copy a contract's code. This method would for example allow you to deploy one or several "template" smart contracts on their own, and then build and deploy a separate Deployer contract, which copies code from a template and uses it to deploy a copy. Here's an example from the docs of how to get the code into memory. https://solidity.readthedocs.io/en/latest/assembly.html#example

Whether this method is cheaper than the classic factory pattern, I don't know. It certainly is more flexible, and since it decouples the template from the deployer, the template can exploit the full allowed 24k for code, and the deployer can also be smarter.

0

An excellent question.

In short: I don't think this is possible currently.

Let's analyze the two scenarios in reverse order:

1) Deployment of Target with new: in order to deploy a new contract we have to have the bytecode somewhere. With existing contracts we only need to use an interface as the bytecode already exists on the blockchain but here we can't utilize an interface. So, as the Target doesn't exist yet on the blockchain the Deployer has to contain its bytecode. If one copy of it already exists on the blockchain and we just wanted to make a new copy of it I guess in theory it might be doable but I don't think there is a way to accomplish that (someone correct me if I'm wrong). With some googling I found a suggestion about it but it never took off: https://github.com/ethereum/solidity/issues/2296

2) Deployment of Deployer: Due to reasons stated above this deployment has to contain the bytecode for the Target contract.

  • OK that's great, but does this answer the question? Unless your answer is that this is impossible – Niklas B. Jul 7 at 12:40
  • Edited my answer to make it more clear. Yes, that is what I believe. – Lauri Peltonen Jul 7 at 13:15
  • One of your premises is that the bytecode has to be stored on-chain. But is this really the case? Can't it be part of the calldata, as is the case with a "regular" dedicated deployment transaction? For example an argument to the deploy() function? – Niklas B. Jul 7 at 14:01
  • If not, then what is the inherent difference between a transaction to address 0 and a smart contract function call which causes this disparity? – Niklas B. Jul 7 at 14:03
  • Code sent in calldata is costly too. You pay by the byte, with a different price depending on the the byte being 00 or not. I think the op is trying to setup an on-chain factory, which has properties that offchain code can't guarantee. – blackscale Jul 7 at 14:38
0

The pattern suggested by solidity docs for code reuse is using a library. If you abstract away some code into a library, you can then deploy that lib once, and call upon it from your contract. This means, once the library is deployed, that both your factory and the contracts it creates will be smaller to deploy, by about the size of the library each.

The main drawback is that library calls cost a little (or a lot) more gas than internal calls, depending on what it does and how. So your contract's functions might have a slightly or remarkably higher gas cost.

You will surely need to test and tune for your needs (i.e. put more or less stuff into the lib, into bigger or smaller functions, and test for gas costs in various scenarios). A long way of saying ymmv.

  • Good addition, about libraries. One extra downside is that they can't contain state. – Lauri Peltonen Jul 7 at 15:21
  • Thank you. If libraries were allowed to contain state, that state would be shared across all contracts using the lib, open the door to spaghetti-mode and hacker-paradise. For me "not holding state" is not a downside, it's what drives the decision of what to put into the library, and is a ctually a good architectural constraint. – blackscale Jul 7 at 16:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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