当前位置:网站首页>Solidity - 合约继承子合约包含构造函数时报错 及 一个合约调用另一合约view函数收取gas费用
Solidity - 合约继承子合约包含构造函数时报错 及 一个合约调用另一合约view函数收取gas费用
2022-06-26 18:20:00 【ling1998】
合约继承子合约包含构造函数时报错
错误信息
在写了一个业务合约时,发现被继承合约含有构造函数时报错,去掉被继承合约中构造函数正常,有些奇怪,于是写一个简单例子进行复现,合约代码如下:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
//基合约接囗
interface IcontractA {
function getMsg() external view returns(string memory);
}
//基合约实现
contract contractA is IcontractA {
string message;
//构造函数
constructor(string memory _message) {
message = _message;
}
function _getMsg() internal view returns (string memory) {
return message;
}
function getMsg() external override view returns(string memory) {
return _getMsg();
}
}
//子合约 - 继承基合约
contract contractB is contractA {
address admin;
//构造函数
constructor(string memory _message) {
admin = msg.sender;
}
//调用基合约函数
function callA() external view returns(string memory) {
return _getMsg();
}
}错误信息
TypeError: Contract "contractB" should be marked as abstract. --> Test/CallContract.sol:28:1: | 28 | contract contractB is contractA { | ^ (Relevant source part starts here and spans across multiple lines). Note: Missing implementation: --> Test/CallContract.sol:14:5: | 14 | constructor(string memory _message) { | ^ (Relevant source part starts here and spans across multiple lines).
Remix浏览器执行结果:

原因
当继承合约时,派生合约(子合约)需要提供基类构造函数需要的所有参数,参见 合约 — Solidity develop 文档
解决方案
在派生合约构造函数中添加基合约所需要的参数
32行调整如下:
constructor(string memory _message) contractA(_message) {
修正后合约代码如下:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
//基合约接囗
interface IcontractA {
function getMsg() external view returns(string memory);
}
//基合约实现
contract contractA is IcontractA {
string message;
//构造函数
constructor(string memory _message) {
message = _message;
}
function _getMsg() internal view returns (string memory) {
return message;
}
function getMsg() external override view returns(string memory) {
return _getMsg();
}
}
//子合约 - 继承基合约
contract contractB is contractA {
address admin;
//构造函数
constructor(string memory _message) contractA(_message) {
admin = msg.sender;
}
//调用基合约函数
function callA() external view returns(string memory) {
return _getMsg();
}
}如果基合约构造函数无参数,在派生合约中也需要提供基合约构造函数,只是无参而已,微调上面代码,基合约构造函数设置无参
32行调整如下:
constructor(string memory _message) contractA() {
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
//基合约接囗
interface IcontractA {
function getMsg() external view returns(string memory);
}
//基合约实现
contract contractA is IcontractA {
string message;
//构造函数
constructor() {
message = "_message";
}
function _getMsg() internal view returns (string memory) {
return message;
}
function getMsg() external override view returns(string memory) {
return _getMsg();
}
}
//子合约 - 继承基合约
contract contractB is contractA {
address admin;
//构造函数
constructor() contractA() {
admin = msg.sender;
}
//调用基合约函数
function callA() external view returns(string memory) {
return _getMsg();
}
}合约B中创建另一个合约A,调用合约A中view函数时,不能使用view
当子合约中创建一个基合约,通过新创建的基合约调用自己的查询函数(使用view修饰符)时,子合约中的函数不能使用view修饰符,合约代码如下:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
//基合约接囗
interface IcontractA {
function getMsg() external view returns(string memory);
}
//基合约实现
contract contractA is IcontractA {
string message;
//构造函数
constructor(string memory _message) {
message = _message;
}
function _getMsg() internal view returns (string memory) {
return message;
}
function getMsg() external override view returns (string memory) {
return _getMsg();
}
}
//子合约 - 继承基合约
contract contractB is contractA {
address admin;
//构造函数
constructor(string memory _message) contractA(_message) {
admin = msg.sender;
}
//调用基合约函数
function callA() external view returns (string memory) {
return _getMsg();
}
//创建基合约,调用函数
function callANewContract() external view returns (string memory) {
contractA contractAddr = new contractA("Hello, I am tracy");
return contractA(contractAddr).getMsg();
}
}错误信息如下:
TypeError: Function declared as view, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable. --> Test/CallContract.sol:43:34: | 43 | contractA contractAddr = new contractA("Hello, I am tracy"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

去除42行中的view修饰符,部署合约B,发现调用函数callANewContract()居然是收取gas费的函数(黄色背景标识为收取gas费函数),如下图所示:

边栏推荐
- Using recursion to find all gray codes with n bits
- 成功解决之Jenkins报错:The goal you specified requires a project to execute but there is no POM
- LeetCode 238 除自身以外数组的乘积
- Li Kou daily question - day 28 -566 Reshape matrix
- 深度学习之Numpy篇
- Binary search-1
- [QNX] Command
- wm_concat()和group_concat()函数
- LeetCode 128最长连续序列
- Leetcode 238 product of arrays other than itself
猜你喜欢

Dos et détails de la méthode d'attaque

Clion编译catkin_ws(ROS工作空间包的简称)加载CMakeLists.txt出现的问题

微信小程序 uniapp 左滑 删除 带删除icon

9. Intelligent transportation project (2)

CD-CompactDisk

MYSQL的下载与配置 mysql远程操控

Detailed explanation of asymmetric cryptosystem

idea中文插件chinese(simplified) language pack

RSA encryption and decryption details

行锁与隔离级别案例分析
随机推荐
成功解决之微服务@Value获取配置文件乱码问题
Vscode 基础必备 常用插件
In and exceptions, count (*) query optimization
JVM入個門(1)
sql中的几种删除操作
判断某个序列是否为栈的弹出序列
Numpy之matplotlib
Comparing the size relationship between two objects turns out to be so fancy
输入n个整数,输出出现次数大于等于数组长度一半的数
Padding percentage operation
Class inheritance of 25class
Soft test preparation multimedia system
Union, intersection and difference operations in SQL
Ethereum技术架构介绍
How pycharm modifies multiline annotation shortcuts
Decision tree and random forest
JVM入个门(1)
gdb安装
JNI的 静态注册与动态注册
Map and list < map > transfer to corresponding objects