Smart Contracts – Discover How To Create Them Directly and Indirectly!

4.7/5 - (3 votes)
Smart Contracts - Discover How To Create Them Directly and Indirectly!

In this article, we’ll take a closer look at how contracts are created, both directly, i.e. while being implicitly deployed on the blockchain, and indirectly, i.e. when their creation is triggered by another contract.

It’s part of our long-standing tradition to make this (and other) articles a faithful companion, or a supplement to the official Solidity documentation.

Creation Process of a Smart Contract

We went through many various aspects of Solidity, Ethereum Virtual Machine (known by its shorter and well-established acronym EVM), and blockchain.

However, as we’re going deeper into the mechanics and closer to the core of this fascinating technology, we should also say a few more words on the contract creation itself.

As we have already got ourselves familiar with many previous examples, a smart contract’s lifecycle starts with its source code.

The source code defines two dimensions of a smart contract: its state and its behavior.

  • The state of a contract is contained in its state variables, i.e. simple and custom data types, etc.
  • The behavior of the contract is determined by its functions, either the ones defined in the contract, the ones inherited from some other contract, or used by a utility library.

Once our contract is complete, we can put it to work and watch how our diligently invested time, energy, and knowledge come to life. The process of putting our contract to work is generally known by the term contract deployment.

💡 Note: Since our smart contract is, in fact, a piece of software, there’s a nice and succinct definition of what software deployment is: “Software deployment is the process of making software available to be used on a system by users and other programs.” (IBM)

Regardless of the tool, we’re using to develop and/or deploy our smart contract, the process is most often fairly easy and simple. It starts by taking the source code of the contract and ends with the machine code of the contract being run on the blockchain in an EVM.

💡 Reminder: Before continuing with the specific steps, let’s review the contract creation-relevant information: a transaction is a message sent from its source (origin) to its destination, i.e. from one account to the other (or the same account, or even without a destination). A message sent in the transaction can include binary data, also known as payload, and the currency Ether. If the message destination is empty, i.e. the destination account is not set or the destination is set to null, the transaction will create a new contract. The address of the contract is derived from the source address and the number of transactions sent, known as the “nonce”. The payload of the message is interpreted as the EVM bytecode and executed when arrives at its destination (a derived address). The result of executing the bytecode will produce the final, permanent smart contract code, stored at the derived destination address.

To prime our understanding of what comes in the next few paragraphs, let’s extract the specific steps from the reminder above and see how a smart contract source code is transmuted into a working, live smart contract.

  1. A smart contract source code is compiled by the Solidity compiler solc (you’ll easily remember that article where several different methods for compiler installation were listed in detail). The result of compiling the smart contract source code is a bytecode-represented version of the smart contract.
  2. The smart contract bytecode is sent inside a message to an address derived from the source address and the nonce.
  3. Since the destination address is not set (it’s a derived address) and there’s a payload, i.e. bytecode in the message, the bytecode is executed and the contract code is produced.
  4. The smart contract machine/EVM code is stored at the derived address.

Now that we have outlined all the steps, let’s focus on step 3 since it’s the one relevant to our subject.

Implicit Creation via a Constructor (The Direct Way)

Smart contracts may have a specified sequence of initialization operations during their construction, i.e. while their bytecode is in execution. Solidity supports the specification of such operations by an optional function called constructor, as in the example below:

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

contract ConstructorExample {

Both state variables are initialized to 0.

    uint public x = 0;
    uint public y = 0;

The constructor overwrites the state variable x with a construction parameter a.

    constructor(uint a) {
        x = a;

Before running the constructor, smart contract state variables are initialized (set) either with their assigned values via the inline initialization (as in the example below) or with their default (type-dependent) value.

Now, the constructor code is executed. If there is no constructor, a default, implicit (invisible) constructor will be used, which is equivalent to the constructor() {}.

After running the constructor, the rest of the smart contract code, now in the form of machine code, is deployed to the blockchain at the derived address. The resulting machine code excludes the constructor code and the internal functions that are called only from the constructor; the rest of the code remains.

Triggered Creation via the new Keyword (The Indirect Way)

After explaining how a smart contract is constructed, let’s focus our attention on our second objective: seeing how a smart contract construction can be initiated indirectly.

To create other smart contracts, our smart contract uses the new keyword. During the intermediary step, i.e., compiling the bytecode of the smart contract, the entire source code of the smart contract must be well-defined and known, meaning that it’s not possible to have recursive creation dependencies.

In other words, the contract won’t be able to reference itself, like by using this keyword in the constructor body.

In the example below, we’ll analyze each line and explain what it does.

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;

Declares contract D, along with its constructor.

contract D {

Declares a state variable x and implicitly initializes it with its default value 0.

    uint public x;

Defines a parametrized smart contract constructor that assigns the parameter value to the state variable x.

    constructor(uint a) payable {
        x = a;

Declares contract C, without a constructor (an implicit constructor will be called during the smart contract construction).

contract C {

Declares a state variable dVar of type D, and assigns it with a newly created smart contract of type D, constructed with an argument 4. The argument is assigned to the state variable of dVar.x.

    D dVar = new D(4); // will be executed as part of C's constructor

Declares a contract-creating function createD(...).

    function createD(uint arg) public returns (uint) {

Declares a local variable newDVar of type D, and assigns it with a newly created smart contract of type D, constructed with a forwarded argument arg. The argument is assigned to the state variable newDVar.x.

        D newDVar = new D(arg);

Returns the state variable newDVar.x of the local variable newDVar via the implicitly created getter function x().

        return newDVar.x();

💡 Reminder: Solidity compiler implicitly creates getter methods for public state variables, such as x.

Defines a contract-creating and Ether-sending function createAndEndowD(...).

    function createAndEndowD(uint arg, uint amount) public payable {

Sends Ether during the contract creation (payable keyword) by setting the amount via a special option (not a recommended approach).

        D newDVar = new D{value: amount}(arg);

Gets (but doesn’t return) the state variable newDVar.x of the local variable newDVar via the implicitly created getter function x().


The example above shows an indirect creation and assignment of a contract to the state and local variables. Although we can send Ether to an indirectly created contract D via the special option value, we cannot limit the amount of Gas. In case the contract creation fails for any cause, it will throw an exception.


In this article, we learned about the process of direct and indirect smart contract creation.

First, we reminded ourselves of the details of smart contract creation.

Second, we saw how implicit smart contract creation works.

Third, we broadened and completed our view by introducing the new keyword for indirect smart contract creation.

What’s Next?

This tutorial is part of our extended Solidity documentation with videos and more accessible examples and explanations. You can navigate the series here (all links open in a new tab):