1.. index:: ! inheritance, ! base class, ! contract;base, ! deriving 2 3*********** 4Inheritance 5*********** 6 7Solidity supports multiple inheritance including polymorphism. 8 9Polymorphism means that a function call (internal and external) 10always executes the function of the same name (and parameter types) 11in the most derived contract in the inheritance hierarchy. 12This has to be explicitly enabled on each function in the 13hierarchy using the ``virtual`` and ``override`` keywords. 14See :ref:`Function Overriding <function-overriding>` for more details. 15 16It is possible to call functions further up in the inheritance 17hierarchy internally by explicitly specifying the contract 18using ``ContractName.functionName()`` or using ``super.functionName()`` 19if you want to call the function one level higher up in 20the flattened inheritance hierarchy (see below). 21 22When a contract inherits from other contracts, only a single 23contract is created on the blockchain, and the code from all the base contracts 24is compiled into the created contract. This means that all internal calls 25to functions of base contracts also just use internal function calls 26(``super.f(..)`` will use JUMP and not a message call). 27 28State variable shadowing is considered as an error. A derived contract can 29only declare a state variable ``x``, if there is no visible state variable 30with the same name in any of its bases. 31 32The general inheritance system is very similar to 33`Python's <https://docs.python.org/3/tutorial/classes.html#inheritance>`_, 34especially concerning multiple inheritance, but there are also 35some :ref:`differences <multi-inheritance>`. 36 37Details are given in the following example. 38 39.. code-block:: solidity 40 41 // SPDX-License-Identifier: GPL-3.0 42 pragma solidity >=0.7.0 <0.9.0; 43 44 45 contract Owned { 46 constructor() { owner = payable(msg.sender); } 47 address payable owner; 48 } 49 50 51 // Use `is` to derive from another contract. Derived 52 // contracts can access all non-private members including 53 // internal functions and state variables. These cannot be 54 // accessed externally via `this`, though. 55 contract Destructible is Owned { 56 // The keyword `virtual` means that the function can change 57 // its behaviour in derived classes ("overriding"). 58 function destroy() virtual public { 59 if (msg.sender == owner) selfdestruct(owner); 60 } 61 } 62 63 64 // These abstract contracts are only provided to make the 65 // interface known to the compiler. Note the function 66 // without body. If a contract does not implement all 67 // functions it can only be used as an interface. 68 abstract contract Config { 69 function lookup(uint id) public virtual returns (address adr); 70 } 71 72 73 abstract contract NameReg { 74 function register(bytes32 name) public virtual; 75 function unregister() public virtual; 76 } 77 78 79 // Multiple inheritance is possible. Note that `owned` is 80 // also a base class of `Destructible`, yet there is only a single 81 // instance of `owned` (as for virtual inheritance in C++). 82 contract Named is Owned, Destructible { 83 constructor(bytes32 name) { 84 Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970); 85 NameReg(config.lookup(1)).register(name); 86 } 87 88 // Functions can be overridden by another function with the same name and 89 // the same number/types of inputs. If the overriding function has different 90 // types of output parameters, that causes an error. 91 // Both local and message-based function calls take these overrides 92 // into account. 93 // If you want the function to override, you need to use the 94 // `override` keyword. You need to specify the `virtual` keyword again 95 // if you want this function to be overridden again. 96 function destroy() public virtual override { 97 if (msg.sender == owner) { 98 Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970); 99 NameReg(config.lookup(1)).unregister(); 100 // It is still possible to call a specific 101 // overridden function. 102 Destructible.destroy(); 103 } 104 } 105 } 106 107 108 // If a constructor takes an argument, it needs to be 109 // provided in the header or modifier-invocation-style at 110 // the constructor of the derived contract (see below). 111 contract PriceFeed is Owned, Destructible, Named("GoldFeed") { 112 function updateInfo(uint newInfo) public { 113 if (msg.sender == owner) info = newInfo; 114 } 115 116 // Here, we only specify `override` and not `virtual`. 117 // This means that contracts deriving from `PriceFeed` 118 // cannot change the behaviour of `destroy` anymore. 119 function destroy() public override(Destructible, Named) { Named.destroy(); } 120 function get() public view returns(uint r) { return info; } 121 122 uint info; 123 } 124 125Note that above, we call ``Destructible.destroy()`` to "forward" the 126destruction request. The way this is done is problematic, as 127seen in the following example: 128 129.. code-block:: solidity 130 131 // SPDX-License-Identifier: GPL-3.0 132 pragma solidity >=0.7.0 <0.9.0; 133 134 contract owned { 135 constructor() { owner = payable(msg.sender); } 136 address payable owner; 137 } 138 139 contract Destructible is owned { 140 function destroy() public virtual { 141 if (msg.sender == owner) selfdestruct(owner); 142 } 143 } 144 145 contract Base1 is Destructible { 146 function destroy() public virtual override { /* do cleanup 1 */ Destructible.destroy(); } 147 } 148 149 contract Base2 is Destructible { 150 function destroy() public virtual override { /* do cleanup 2 */ Destructible.destroy(); } 151 } 152 153 contract Final is Base1, Base2 { 154 function destroy() public override(Base1, Base2) { Base2.destroy(); } 155 } 156 157A call to ``Final.destroy()`` will call ``Base2.destroy`` because we specify it 158explicitly in the final override, but this function will bypass 159``Base1.destroy``. The way around this is to use ``super``: 160 161.. code-block:: solidity 162 163 // SPDX-License-Identifier: GPL-3.0 164 pragma solidity >=0.7.0 <0.9.0; 165 166 contract owned { 167 constructor() { owner = payable(msg.sender); } 168 address payable owner; 169 } 170 171 contract Destructible is owned { 172 function destroy() virtual public { 173 if (msg.sender == owner) selfdestruct(owner); 174 } 175 } 176 177 contract Base1 is Destructible { 178 function destroy() public virtual override { /* do cleanup 1 */ super.destroy(); } 179 } 180 181 182 contract Base2 is Destructible { 183 function destroy() public virtual override { /* do cleanup 2 */ super.destroy(); } 184 } 185 186 contract Final is Base1, Base2 { 187 function destroy() public override(Base1, Base2) { super.destroy(); } 188 } 189 190If ``Base2`` calls a function of ``super``, it does not simply 191call this function on one of its base contracts. Rather, it 192calls this function on the next base contract in the final 193inheritance graph, so it will call ``Base1.destroy()`` (note that 194the final inheritance sequence is -- starting with the most 195derived contract: Final, Base2, Base1, Destructible, owned). 196The actual function that is called when using super is 197not known in the context of the class where it is used, 198although its type is known. This is similar for ordinary 199virtual method lookup. 200 201.. index:: ! overriding;function 202 203.. _function-overriding: 204 205Function Overriding 206=================== 207 208Base functions can be overridden by inheriting contracts to change their 209behavior if they are marked as ``virtual``. The overriding function must then 210use the ``override`` keyword in the function header. 211The overriding function may only change the visibility of the overridden function from ``external`` to ``public``. 212The mutability may be changed to a more strict one following the order: 213``nonpayable`` can be overridden by ``view`` and ``pure``. ``view`` can be overridden by ``pure``. 214``payable`` is an exception and cannot be changed to any other mutability. 215 216The following example demonstrates changing mutability and visibility: 217 218.. code-block:: solidity 219 220 // SPDX-License-Identifier: GPL-3.0 221 pragma solidity >=0.7.0 <0.9.0; 222 223 contract Base 224 { 225 function foo() virtual external view {} 226 } 227 228 contract Middle is Base {} 229 230 contract Inherited is Middle 231 { 232 function foo() override public pure {} 233 } 234 235For multiple inheritance, the most derived base contracts that define the same 236function must be specified explicitly after the ``override`` keyword. 237In other words, you have to specify all base contracts that define the same function 238and have not yet been overridden by another base contract (on some path through the inheritance graph). 239Additionally, if a contract inherits the same function from multiple (unrelated) 240bases, it has to explicitly override it: 241 242.. code-block:: solidity 243 244 // SPDX-License-Identifier: GPL-3.0 245 pragma solidity >=0.6.0 <0.9.0; 246 247 contract Base1 248 { 249 function foo() virtual public {} 250 } 251 252 contract Base2 253 { 254 function foo() virtual public {} 255 } 256 257 contract Inherited is Base1, Base2 258 { 259 // Derives from multiple bases defining foo(), so we must explicitly 260 // override it 261 function foo() public override(Base1, Base2) {} 262 } 263 264An explicit override specifier is not required if 265the function is defined in a common base contract 266or if there is a unique function in a common base contract 267that already overrides all other functions. 268 269.. code-block:: solidity 270 271 // SPDX-License-Identifier: GPL-3.0 272 pragma solidity >=0.6.0 <0.9.0; 273 274 contract A { function f() public pure{} } 275 contract B is A {} 276 contract C is A {} 277 // No explicit override required 278 contract D is B, C {} 279 280More formally, it is not required to override a function (directly or 281indirectly) inherited from multiple bases if there is a base contract 282that is part of all override paths for the signature, and (1) that 283base implements the function and no paths from the current contract 284to the base mentions a function with that signature or (2) that base 285does not implement the function and there is at most one mention of 286the function in all paths from the current contract to that base. 287 288In this sense, an override path for a signature is a path through 289the inheritance graph that starts at the contract under consideration 290and ends at a contract mentioning a function with that signature 291that does not override. 292 293If you do not mark a function that overrides as ``virtual``, derived 294contracts can no longer change the behaviour of that function. 295 296.. note:: 297 298 Functions with the ``private`` visibility cannot be ``virtual``. 299 300.. note:: 301 302 Functions without implementation have to be marked ``virtual`` 303 outside of interfaces. In interfaces, all functions are 304 automatically considered ``virtual``. 305 306.. note:: 307 308 Starting from Solidity 0.8.8, the ``override`` keyword is not 309 required when overriding an interface function, except for the 310 case where the function is defined in multiple bases. 311 312 313Public state variables can override external functions if the 314parameter and return types of the function matches the getter function 315of the variable: 316 317.. code-block:: solidity 318 319 // SPDX-License-Identifier: GPL-3.0 320 pragma solidity >=0.6.0 <0.9.0; 321 322 contract A 323 { 324 function f() external view virtual returns(uint) { return 5; } 325 } 326 327 contract B is A 328 { 329 uint public override f; 330 } 331 332.. note:: 333 334 While public state variables can override external functions, they themselves cannot 335 be overridden. 336 337.. index:: ! overriding;modifier 338 339.. _modifier-overriding: 340 341Modifier Overriding 342=================== 343 344Function modifiers can override each other. This works in the same way as 345:ref:`function overriding <function-overriding>` (except that there is no overloading for modifiers). The 346``virtual`` keyword must be used on the overridden modifier 347and the ``override`` keyword must be used in the overriding modifier: 348 349.. code-block:: solidity 350 351 // SPDX-License-Identifier: GPL-3.0 352 pragma solidity >=0.6.0 <0.9.0; 353 354 contract Base 355 { 356 modifier foo() virtual {_;} 357 } 358 359 contract Inherited is Base 360 { 361 modifier foo() override {_;} 362 } 363 364 365In case of multiple inheritance, all direct base contracts must be specified 366explicitly: 367 368.. code-block:: solidity 369 370 // SPDX-License-Identifier: GPL-3.0 371 pragma solidity >=0.6.0 <0.9.0; 372 373 contract Base1 374 { 375 modifier foo() virtual {_;} 376 } 377 378 contract Base2 379 { 380 modifier foo() virtual {_;} 381 } 382 383 contract Inherited is Base1, Base2 384 { 385 modifier foo() override(Base1, Base2) {_;} 386 } 387 388 389 390.. index:: ! constructor 391 392.. _constructor: 393 394Constructors 395============ 396 397A constructor is an optional function declared with the ``constructor`` keyword 398which is executed upon contract creation, and where you can run contract 399initialisation code. 400 401Before the constructor code is executed, state variables are initialised to 402their specified value if you initialise them inline, or their :ref:`default value<default-value>` if you do not. 403 404After the constructor has run, the final code of the contract is deployed 405to the blockchain. The deployment of 406the code costs additional gas linear to the length of the code. 407This code includes all functions that are part of the public interface 408and all functions that are reachable from there through function calls. 409It does not include the constructor code or internal functions that are 410only called from the constructor. 411 412If there is no 413constructor, the contract will assume the default constructor, which is 414equivalent to ``constructor() {}``. For example: 415 416.. code-block:: solidity 417 418 // SPDX-License-Identifier: GPL-3.0 419 pragma solidity >=0.7.0 <0.9.0; 420 421 abstract contract A { 422 uint public a; 423 424 constructor(uint _a) { 425 a = _a; 426 } 427 } 428 429 contract B is A(1) { 430 constructor() {} 431 } 432 433You can use internal parameters in a constructor (for example storage pointers). In this case, 434the contract has to be marked :ref:`abstract <abstract-contract>`, because these parameters 435cannot be assigned valid values from outside but only through the constructors of derived contracts. 436 437.. warning :: 438 Prior to version 0.4.22, constructors were defined as functions with the same name as the contract. 439 This syntax was deprecated and is not allowed anymore in version 0.5.0. 440 441.. warning :: 442 Prior to version 0.7.0, you had to specify the visibility of constructors as either 443 ``internal`` or ``public``. 444 445 446.. index:: ! base;constructor 447 448Arguments for Base Constructors 449=============================== 450 451The constructors of all the base contracts will be called following the 452linearization rules explained below. If the base constructors have arguments, 453derived contracts need to specify all of them. This can be done in two ways: 454 455.. code-block:: solidity 456 457 // SPDX-License-Identifier: GPL-3.0 458 pragma solidity >=0.7.0 <0.9.0; 459 460 contract Base { 461 uint x; 462 constructor(uint _x) { x = _x; } 463 } 464 465 // Either directly specify in the inheritance list... 466 contract Derived1 is Base(7) { 467 constructor() {} 468 } 469 470 // or through a "modifier" of the derived constructor. 471 contract Derived2 is Base { 472 constructor(uint _y) Base(_y * _y) {} 473 } 474 475One way is directly in the inheritance list (``is Base(7)``). The other is in 476the way a modifier is invoked as part of 477the derived constructor (``Base(_y * _y)``). The first way to 478do it is more convenient if the constructor argument is a 479constant and defines the behaviour of the contract or 480describes it. The second way has to be used if the 481constructor arguments of the base depend on those of the 482derived contract. Arguments have to be given either in the 483inheritance list or in modifier-style in the derived constructor. 484Specifying arguments in both places is an error. 485 486If a derived contract does not specify the arguments to all of its base 487contracts' constructors, it will be abstract. 488 489.. index:: ! inheritance;multiple, ! linearization, ! C3 linearization 490 491.. _multi-inheritance: 492 493Multiple Inheritance and Linearization 494====================================== 495 496Languages that allow multiple inheritance have to deal with 497several problems. One is the `Diamond Problem <https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem>`_. 498Solidity is similar to Python in that it uses "`C3 Linearization <https://en.wikipedia.org/wiki/C3_linearization>`_" 499to force a specific order in the directed acyclic graph (DAG) of base classes. This 500results in the desirable property of monotonicity but 501disallows some inheritance graphs. Especially, the order in 502which the base classes are given in the ``is`` directive is 503important: You have to list the direct base contracts 504in the order from "most base-like" to "most derived". 505Note that this order is the reverse of the one used in Python. 506 507Another simplifying way to explain this is that when a function is called that 508is defined multiple times in different contracts, the given bases 509are searched from right to left (left to right in Python) in a depth-first manner, 510stopping at the first match. If a base contract has already been searched, it is skipped. 511 512In the following code, Solidity will give the 513error "Linearization of inheritance graph impossible". 514 515.. code-block:: solidity 516 517 // SPDX-License-Identifier: GPL-3.0 518 pragma solidity >=0.4.0 <0.9.0; 519 520 contract X {} 521 contract A is X {} 522 // This will not compile 523 contract C is A, X {} 524 525The reason for this is that ``C`` requests ``X`` to override ``A`` 526(by specifying ``A, X`` in this order), but ``A`` itself 527requests to override ``X``, which is a contradiction that 528cannot be resolved. 529 530Due to the fact that you have to explicitly override a function 531that is inherited from multiple bases without a unique override, 532C3 linearization is not too important in practice. 533 534One area where inheritance linearization is especially important and perhaps not as clear is when there are multiple constructors in the inheritance hierarchy. The constructors will always be executed in the linearized order, regardless of the order in which their arguments are provided in the inheriting contract's constructor. For example: 535 536.. code-block:: solidity 537 538 // SPDX-License-Identifier: GPL-3.0 539 pragma solidity >=0.7.0 <0.9.0; 540 541 contract Base1 { 542 constructor() {} 543 } 544 545 contract Base2 { 546 constructor() {} 547 } 548 549 // Constructors are executed in the following order: 550 // 1 - Base1 551 // 2 - Base2 552 // 3 - Derived1 553 contract Derived1 is Base1, Base2 { 554 constructor() Base1() Base2() {} 555 } 556 557 // Constructors are executed in the following order: 558 // 1 - Base2 559 // 2 - Base1 560 // 3 - Derived2 561 contract Derived2 is Base2, Base1 { 562 constructor() Base2() Base1() {} 563 } 564 565 // Constructors are still executed in the following order: 566 // 1 - Base2 567 // 2 - Base1 568 // 3 - Derived3 569 contract Derived3 is Base2, Base1 { 570 constructor() Base1() Base2() {} 571 } 572 573 574Inheriting Different Kinds of Members of the Same Name 575====================================================== 576 577It is an error when any of the following pairs in a contract have the same name due to inheritance: 578 - a function and a modifier 579 - a function and an event 580 - an event and a modifier 581 582As an exception, a state variable getter can override an external function. 583