Smart Contract Development
  • Introduction
    • What is a Transaction
    • Accounts and Signing
    • What is a smart contract
  • Learning Solidity
    • Introduction
    • Module 1
      • Variable Types
      • Variable Scope: State & Local variables
      • Global variables
      • Functions
        • View and Pure
        • Shadowing in Fuctions
      • Mapping
      • Require
      • Events
    • Project #1: Simple Registry
    • Module 2
      • Constructor
      • Data Location: Value & Reference
      • Interface
      • Import
        • Importing in Foundry
      • Inheritance
      • ERC-20
      • Checks-effect-interaction pattern
    • Project #2: Basic Vault
    • Module 3
      • Payable
      • Receive
      • Fallback
      • Returns
    • Project #3: ERC20+ETH Wrapper
    • Module 4
      • Immutable and Constant
      • Fixed-point Math
      • Abstract contracts
      • ERC-4626
      • Modifier + Inheritance +Ownable
      • Type
    • Project #4: Fractional Wrapper
    • Module 5
      • If-else
      • Libraries
        • TransferHelper
      • Chainlink Oracle
    • Project #5: Collateralized Vault
  • Compendium
    • Solidity Basics
      • Variable Types
      • Value Types
        • address
        • enum
      • Reference Types
        • strings
        • mappings
        • struct
        • Arrays
        • Multi-Dimensional arrays
      • Global Objects
      • Functions
        • Function types
        • Constructor Function
        • Transaction vs Call
        • Require, Revert, Assert
      • Function signature + selectors
      • Payable
        • Payable + withdraw
        • msg.value & payable functions
      • Receive
      • Fallback function (sol v 0.8)
        • Fallback function (sol v 0.6)
      • call, staticcall, delegatecall
    • Return & Events
    • Control Variable Visibility
    • Local Variables (Storage v Memory)
    • Data Location and Assignment Behaviors
    • Modifiers & Inheritance & Import
      • import styles
    • Interface & Abstract Contracts
    • ABI & Debugging
    • Libraries
    • Conditional(ternary) operators
    • Smart Contract Life-cycle
      • Pausing Smart Contracts
      • Destroying Smart Contracts
    • Merkle Trie and MPT
    • Merkle Tree Airdrop
  • Try & catch
  • Ethereum Signatures
  • EVM, Storage, Opcodes
    • EVM
    • Wei, Ether, Gas
    • Storage
    • ByteCode and Opcodes
    • Transaction costs & Execution costs
  • Reading txn input data
  • Data Representation
  • Yul
    • Yul
      • Intro
      • Basic operations
      • Storage Slots
      • Storage of Arrays and Mappings
      • Memory Operations
      • Memory: how solidity uses memory
      • Memory: Return, Require, Tuples and Keccak256
      • Memory: Logs and Events
      • Inter-contract calls
      • calldata
      • free memory pointer
    • Yul Exercises
      • read state variable
      • read mapping
      • iterate Array, Return Sum
    • memory-safe
  • Upgradable Contracts
    • Upgradability & Proxies
    • UUPS Example
    • Minimal Proxy Example
    • TPP Example
    • 🚧Diamond
      • On Storage
  • Gas Opt
    • Block Limit
    • gasLimit & min cost
    • Solidity Optimiser
    • Memory v calldata
    • Memory caching vs direct storage vs pointers
    • < vs <=
    • reverting early
    • X && Y, ||
    • constant and immutable
    • caching sload into mload
    • Syntactic Sugar
    • using unchecked w/o require
    • Compact Strings
    • Calling a view function
    • Custom errors over require
    • usage of this.
      • multiple address(this)
  • ERCs & EIPs
    • ERC-20.sol
      • Core functions
      • transfer()
      • transferFrom()
      • TLDR transfer vs transferFrom
    • Landing
      • ERC721.sol
      • EIP-721
        • LooksRare
        • Page 1
      • ERC-1271
      • EIP-2981
      • ERC-165
      • EIP-1167: Minimal Proxy Contract
    • VRFConsumerBase
    • UniswapV2Library
  • Yield Mentorship 2022
    • Projects
      • #1 Simple Registry
      • #2 Basic Vault
      • #3 ERC20+ETH Wrapper
        • setFailTransferTrue
      • #4 Fractional Wrapper
      • #5 Collateralized Vault
        • Process
        • Vault.sol
        • Testing
        • Chainlink Oracles
        • Pricing + Decimal scaling
        • Refactor for Simplicity
      • #9 Flash Loan Vault
        • Implementing ERC3156
        • Full code for lender
        • Ex-rate calculation
    • State Inheritance Testing
    • Testing w/ Mocks
    • Yield Style Guide
    • Github Actions
    • TransferHelper.sol
    • math logic + internal fn
    • Interfaces: IERC20
  • Foundry
    • Overview
    • Importing Contracts
    • Testing
      • stdError.arithmeticError
      • assume vs bound
      • Traces
      • label & console2
      • std-storage
  • Smart Contract Security
    • Damn Vulnerable Defi
      • 1. Unstoppable
      • 2. Naive receiver
      • 3. Truster
      • 4. Side Entrance
      • 5. The Rewarder
      • 6. Selfie
      • 7. Compromised
      • 8. Puppet
      • 9. Puppet V2
      • 10 - Free Rider
    • Merkle Tree: shortened proof attack
  • Fixed-Point Math
    • AMM Math
  • Solidity Patterns
    • checks-effects-interactions pattern
    • Router // batch
    • claimDelegate: stack unique owners
    • claimDelegate: cache previous user
  • Array: dup/ascending check
  • Deployment
    • Behind the Scenes
    • Interacting with External Contracts
    • Logging, Events, Solidity, Bloom Filter
  • Misc
    • Mnemonic Phrases
    • Bidul Ideas
  • Archive
    • Brownie Framework
      • Brownie basics
        • storing wallets in .env
        • Deployment to ganache
        • Interacting with contract
        • Unit Testing
        • Testnet deployment
        • Interacting w/ deployed contract
        • Brownie console
      • Brownie Advanced
        • Dependencies: import contracts
        • helpful_scripts.py
        • verify and publish
        • Forking and Mocking
        • Mocking
        • Forking
      • Testing
      • Scripts Framework
        • deploy.py
        • get_accounts
        • deploy_mocks()
        • fund_with_<token>()
      • Brownie Networks
    • Brownie Projects
      • SharedWallet
        • Multiple Beneficiaries
        • Common Code Contract
        • Adding Events
        • Renounce Ownership
        • Separate Files
      • Supply Chain
        • ItemManager()
        • Adding Events
        • Adding unique address to each item
      • Lottery
      • Aave - Lending and Borrowing
        • Approve & Deposit
        • Borrow
      • NFT
      • Advanced Collectible
        • adv_deploy() + Testing
        • Create Metadata
        • Setting the TokenURI
    • node npm
    • Ganache
    • Truffle
    • Remix
    • Installing Env
Powered by GitBook
On this page
  • How to define a constructor in Solidity?
  • Public vs Internal Constructors
  • Abstract contracts
  • Constructors’ parameters and inheritance
  • Payable Constructor
  1. Compendium
  2. Solidity Basics
  3. Functions

Constructor Function

https://docs.soliditylang.org/en/v0.8.12/contracts.html

PreviousFunction typesNextTransaction vs Call

Last updated 2 years ago

Constructors are a common concept in OOP. In many programming languages, when defining classes, you can also define a magic method that will run once, at the time a new instance of the object is created.

In the case of Solidity, the code defined inside the constructor will run only once, at the time the contract is created and deployed in the network.

An important point to mention is the following:

The bytecode deployed on the network does not contain the constructor code, since the constructor code runs only once, on deployment.

:

The constructor code is part of the creation code, not part of the runtime code.

Deployment

After the constructor has executed, the final code of the contract is stored on the blockchain. This code includes all public and external functions and all functions that are reachable from there through function calls. The deployed code does not include the constructor code or internal functions only called from the constructor.

How to define a constructor in Solidity?

You define a constructor in Solidity with the keyword constructor() followed by parentheses. Note that you do not need to add function keyword, since it is a special function.

pragma solidity 0.8.0;

contract Animal {
    
    uint feet;
    bool canSwim;
    
    constructor(uint _feet, bool _canSwim) {
        feet = _feet;
        canSwim = _canSwim;
    }
}

Before deployment, you have to provide the values for feet and canSwim

Prior to version 0.4.22 of Solidity, constructors were defined as functions with the same name as the contract (like in JAVA?). This syntax was deprecated and is not allowed anymore since version 0.5.0.

Public vs Internal Constructors

Prior to Solidity 0.7.0, contract’s constructors in Solidity could be defined with the following 2 visibilities: public (default) or internal.

From Solidity 0.7. onward:

  • Visibility (public / internal) is not needed for constructors anymore: To prevent a contract from being created, it can be marked abstract.

  • This makes the visibility concept for constructors obsolete.

Abstract contracts

An abstract contract enables the child contract that inherits from it to setup some default logic on deployment (specific to the abstract contract). This initial deployment logic can be dynamic, by declaring the constructor with parameters.

  • manner of inheritance ( i think: wen you want to inherit the logic, but define the init values for constructor)

Constructors’ parameters and inheritance

If a base contract has arguments, derived contracts need to specify all of them. This can be done in 2 ways:

Directly in the inheritance list

pragma solidity 0.8.0;

contract Animal {
    
    uint feet;
    bool canSwim;
    
    constructor(uint _feet, bool _canSwim) {
        feet = _feet;
        canSwim = _canSwim;
    }
}

contract Lion is Animal(4, true) {
}

If a derived contract does not specify the arguments to all of its base contracts’ constructors, it will be abstract.

Through the derived constructor, like a “modifier”

contract Animal {
    
    string name;
    uint feet;
    bool canSwim;
    
    constructor(string memory _name, uint _feet, bool _canSwim) {
        name = _name;
        feet = _feet;
        canSwim = _canSwim;
    }
}
contract Lion is Animal {
    
    constructor(string memory _name)
        Animal(_name, 4, true)
    {
        // ...
    }
}

This way can be used if the constructor arguments of the base contract depend on those of the derived contract.

Payable Constructor

Constructors can accept Ethers. In this case, they should be mentioned with the keyword “payable”. In the Remix IDE, the “deploy” button will change color (shown in red) if the constructor accept ether.

If you try to add ether when deploying a contract defined with a non payable constructor, it will throw you an exception and revert.

The difference between a payable and non payable constructor is also reflected in the creation code.

If the constructor is non-payable, the creation code contains 8 low-levels instructions (in EVM assembly), that check if some ethers has been sent to the contract once it has been deployed. If it is the case, the check fails and the contract reverts.

If the constructor is defined as payable , this 8 EVM instructions are removed and not present.

You can see the example here:

OpenZeppelin explains the idea more precisely in the second part of their article series “Deconstructing a Solidity Contract”
https://medium.com/upstate-interactive/solidity-how-to-know-when-to-use-abstract-contracts-vs-interfaces-874cab860c56
https://blog.openzeppelin.com/deconstructing-a-solidity-contract-part-ii-creation-vs-runtime-6b9d60ecb44c/