From 2839a1b0bfc635ce56361033eea95f02b3346422 Mon Sep 17 00:00:00 2001
From: Djordje Mijovic <djordje.mijovic@gmail.com>
Date: Fri, 4 Dec 2020 14:17:52 +0100
Subject: [PATCH] [Sol->Yul] Documenting difference in initialization order in
 case of inheritance.

Co-authored-by: Leonardo <leo@ethereum.org>

Co-authored-by: Daniel Kirchner <daniel@ekpyron.org>
---
 docs/ir/ir-breaking-changes.rst               | 36 +++++++++++++++++++
 .../constructor_inheritance_init_order_3.sol  | 12 +++++++
 2 files changed, 48 insertions(+)
 create mode 100644 test/libsolidity/constructor_inheritance_init_order_3.sol

diff --git a/docs/ir/ir-breaking-changes.rst b/docs/ir/ir-breaking-changes.rst
index 7ffa49508..ec6126beb 100644
--- a/docs/ir/ir-breaking-changes.rst
+++ b/docs/ir/ir-breaking-changes.rst
@@ -33,3 +33,39 @@ Consequently, if the padding space within a struct is used to store data (e.g. i
     }
 
 We have the same behavior for implicit delete, for example when array of structs is shortened.
+
+ * The order of contract initialization has changed in case of inheritance.
+
+The order used to be:
+ - All state variables are zero-initialized at the beginning.
+ - Evaluate base constructor arguments from most derived to most base contract.
+ - Initialize all state variables in the whole inheritance hierarchy from most base to most derived.
+ - Run the constructor, if present, for all contracts in the linearized hierarchy from most base to most derived.
+
+New order:
+ - All state variables are zero-initialized at the beginning.
+ - Evaluate base constructor arguments from most derived to most base contract.
+ - For every contract in order from most base to most derived in the linearized hierarchy execute:
+     1. State variables are assigned value their initial values, if present at declaration.
+     2. Constructor, if present.
+
+This causes differences in some contracts, for example:
+::
+    // SPDX-License-Identifier: GPL-3.0
+    pragma solidity >0.7.0;
+
+    contract A {
+        uint x;
+        constructor() {
+            x = 42;
+        }
+        function f() public view returns(uint256) {
+            return x;
+        }
+    }
+    contract B is A {
+        uint public y = f();
+    }
+
+Previously, ``y`` would be set to 0. This is due to the fact that we would first initialize state variables: First, ``x`` is set to 0, and when initializing ``y``, ``f()`` would return 0 causing ``y`` to be 0 as well.
+With the new rules, ``y`` will be set to 42. We first initialize ``x`` to 0, then call A's constructor which sets ``x`` to 42. Finally, when initializing ``y``, ``f()`` returns 42 causing ``y`` to be 42.
diff --git a/test/libsolidity/constructor_inheritance_init_order_3.sol b/test/libsolidity/constructor_inheritance_init_order_3.sol
new file mode 100644
index 000000000..c9719a108
--- /dev/null
+++ b/test/libsolidity/constructor_inheritance_init_order_3.sol
@@ -0,0 +1,12 @@
+contract A {
+    uint public x;
+    constructor(uint) {}
+    function f() public { x = 4; }
+}
+contract B is A {
+    constructor() A(f()) {}
+}
+// ====
+// compileViaYul: also
+// ----
+// x() -> 4