Solidity 多重继承 C3算法

 

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.10;

contract A {
    event Log(string message);

    function bar() public virtual {
        emit Log("A.bar called");
    }
}

contract B is A {

    function bar() public virtual override {
        emit Log("B.bar called");
        super.bar();
    }
}

contract C is A {

    function bar() public virtual override {
        emit Log("C.bar called");
        super.bar();
    }
}

contract D is B, C {

    function bar() public override(B, C) {
        super.bar();
    }
}

执行D.bar的结果

[
	{
		"from": "0xd8b934580fcE35a11B58C6D73aDeE468a2833fa8",
		"topic": "0xcf34ef537ac33ee1ac626ca1587a0a7e8e51561e5514f8cb36afa1c5102b3bab",
		"event": "Log",
		"args": {
			"0": "C.bar called",
			"message": "C.bar called"
		}
	},
	{
		"from": "0xd8b934580fcE35a11B58C6D73aDeE468a2833fa8",
		"topic": "0xcf34ef537ac33ee1ac626ca1587a0a7e8e51561e5514f8cb36afa1c5102b3bab",
		"event": "Log",
		"args": {
			"0": "B.bar called",
			"message": "B.bar called"
		}
	},
	{
		"from": "0xd8b934580fcE35a11B58C6D73aDeE468a2833fa8",
		"topic": "0xcf34ef537ac33ee1ac626ca1587a0a7e8e51561e5514f8cb36afa1c5102b3bab",
		"event": "Log",
		"args": {
			"0": "A.bar called",
			"message": "A.bar called"
		}
	}
]

执行顺序

  • 最右C.bar
  • C里有 super.bar,执行的是b里的 bar
  • B里的 super.bar 执行的是a里的bar

具体原因是:

Solidity Diamond Inheritance - Guides and Tutorials - OpenZeppelin Forum

solidity和python一样采用C3 继承算法

去掉代码里的 super.bar,结果就变成

[
	{
		"from": "0xd2a5bC10698FD955D1Fe6cb468a17809A08fd005",
		"topic": "0xcf34ef537ac33ee1ac626ca1587a0a7e8e51561e5514f8cb36afa1c5102b3bab",
		"event": "Log",
		"args": {
			"0": "C.bar called",
			"message": "C.bar called"
		}
	}
]