(二)solidity内置对象及函数

(二)solidity内置对象及函数

viEcho Lv5

1.solidity多继承

solidity 通过is关键字实现合约多重继承,例如contract H is G,F,表示H合约继承自G和F合约,多重继承的顺序是按照从左到右的顺序。

2.immutable关键字

immutable 是一种特殊的状态变量修饰符,用于定义在合约部署后不可修改的变量

immutable变量的值在编译时确定,不能在构造函数中赋值,并且不能在函数中修改。

与普通状态变量不同,immutable 变量的值直接写入合约字节码,不占用存储插槽(Storage Slot),因此Gas成本更低

3.msg,address,block内置对象 balance内置属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//msg 是内置对象,包含 sender、value 等属性。
//block 是内置对象,包含 timestamp、number 等属性。
//balance 仅依附于地址类型,不构成独立对象
contract Payable{
address payable public owner;
constructor (){
owner = payable (msg.sender);
}
function deposit() external payable{
//空函数体:发送的以太币会自动存入合约地址的余额中,无需额外逻辑
}
function getBalance() external view returns(uint){
require(msg.sender == owner,"only the owner can getBalance");
return address(this).balance;
}
}

4.fallback 和receive内置函数

1
2
3
4
5
6
7
8
9
10
11
contract Fallback {
event Log(string func,address sender,uint value,bytes data);

fallback() external payable {
emit Log("fallback",msg.sender,msg.value,msg.data);
}
receive() external payable{
emit Log("Receive",msg.sender,msg.value,"");
}
}

fallback 和 receive 是 Solidity 语言中预定义的特殊函数,必须严格使用固定的名称和语法结构,不能修改名称或参数

receive():用于处理纯以太币转账(无数据),必须声明为 external payable,且无参数和返回值。

fallback():处理不匹配的函数调用或附带数据的以太币转账,声明方式为 external payable(若需接收以太币)

改名无效性: 若修改函数名称(如 myReceive),Solidity 编译器将无法识别其为特殊函数,导致合约无法正确处理以太币转账或未匹配的调用

4.1.自动分发机制

Solidity 根据以下规则自动触发 receive 或 fallback 函数,无需开发者手动指定

纯以太币转账(无数据) → 优先触发 receive 函数。

附带数据的以太币转账 → 触发 fallback 函数。

调用不存在函数(无论是否有以太币) → 触发 fallback 函数
纯以太转账(无数据)且合约里没有显示声明receive函数 → 触发fallback函数

5.transfer,send, call

Solidity中的 transfer 、 send 和 call 是三种ETH转账方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// transfer特点:
// - 固定2300 gas限制
// - 转账失败自动revert
// - 最安全但gas有限
recipient.transfer(amount);

// send特点:
// - 固定2300 gas限制
// - 返回bool而不自动revert
// - 需要手动检查返回值
bool success = recipient.send(amount);
require(success, "Send failed");

// call特点:
// - 可自定义gas
// - 可附带data调用函数
// - 需要严格的安全检查
(bool success,) = recipient.call{value: amount, gas: 100000}("");
require(success, "Call failed");

使用建议:

  • 简单转账 → 优先用 transfer
  • 需要兼容旧合约 → 用 send +手动检查
  • 需要复杂交互 → 用 call +严格gas和安全性检查

6.call 、 delegatecall 和 staticcall

Solidity中的 call 、 delegatecall 和 staticcall 是三种不同的低级调用方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// call特点:
// - 最常用的调用方式
// - 会切换msg.sender为当前合约
// - 可以发送ETH(通过value参数)
// - 修改被调用合约的状态
(bool success, bytes memory data) = addr.call{value: 1 ether}("");

// solidity特点:
// - 保持原始msg.sender不变
// - 使用调用者的存储空间
// - 不能发送ETH(value参数无效)
// - 常用于代理合约模式
(bool success, bytes memory data) = addr.delegatecall(abi.encodeWithSignature("func()"));

// staticcall特点:
// - 只读调用(禁止状态修改)
// - 保持msg.sender不变
// - 不能发送ETH
// - 常用于视图函数调用
(bool success, bytes memory data) = addr.staticcall(abi.encodeWithSignature("getInfo()"));

使用场景建议:

  • 普通合约交互 → call
  • 代理合约/库合约 → delegatecall
  • 只读查询 → staticcall

7.编译器规范

如下图所示,即使不是内置函数;编译器也会要求,局部变量命名和参数命名不能相同
修改前

建议:直接赋值给返回值,不显式声明return;或者显式声明return,对应的参数命名和返回值名不同,统一返回值命名或参数命名加上res前缀代表返回值即可
修改后

8.状态可变性规则

Solidity 要求所有未修改合约状态的函数必须显式声明为 viewpure。若函数仅读取状态变量(如查询数据)而未修改任何状态(如写入变量、触发事件等),则必须标记为 view。若函数既不读也不写状态,则标记为 pure

  • Title: (二)solidity内置对象及函数
  • Author: viEcho
  • Created at : 2025-05-01 13:59:26
  • Updated at : 2025-05-11 16:35:06
  • Link: https://viecho.github.io/2025/0501/solidity-inner-object-and-function.html
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments