Constructors & Contract Lifecycle
Historically selfdestruct(recipient) deleted the contract's code and storage and sent its Ether.
15.1 Constructors
Runs exactly once, during deployment; its code is not part of the runtime bytecode.
During construction, address(this).code.length == 0 — so code.length checks cannot detect calls coming from a constructor.
Constructors have no visibility (removed in 0.7.0); to prevent deployment of a base contract, mark it abstract.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Base {
string public name;
constructor(string memory _name) { name = _name; }
}
// Two ways to pass arguments to base constructors
contract Child1 is Base("fixed name") {}
contract Child2 is Base {
uint256 public immutable created;
constructor(string memory n) payable Base(n) { // payable constructor can receive Ether at deployment
created = block.timestamp;
}
}15.2 Lifecycle
compile → deploy (creation tx runs init code + constructor) → runtime code stored at address
→ users call functions (forever) → optional: pause / migrate / upgrade via proxy15.3 selfdestruct (deprecated)
Historically selfdestruct(recipient) deleted the contract's code and storage and sent its Ether. Since the Cancun upgrade (EIP-6780, March 2024) it only transfers Ether unless called in the same transaction that created the contract. It is deprecated since 0.8.18 and emits a compiler warning. Do not design around it; use a pause flag or upgrade pattern instead.