以太坊作为全球最大的智能合约平台,其强大的功能离不开丰富多样的智能合约函数,无论是代币发行、DeFi协议,还是NFT应用、DAO治理,都离不开这些函数的支撑,本文将系统梳理以太坊智能合约中的核心函数,涵盖基础类型操作、状态管理、事件交互、安全控制等关键领域,帮助开发者快速掌握智能合约开发的核心技能。
基础数据类型与转换函数
智能合约的基础是数据类型,而类型转换是数据处理的前提,以太坊Solidity语言支持多种数据类型,并提供了相应的转换函数。
值类型转换
- uint/int类型转换:不同位数的uint(如uint8、uint256)或int之间可通过显式转换,但需注意溢出风险。
uint256(8)将8转换为uint256类型。
- bool与uint转换:bool可转为uint(false→0,true→1),反之亦然:
uint256(true)结果为1,bool(1)结果为true。 - address与uint160转换:address本质是uint160,可通过
address(uint160(0x123...))将uint160转为address,或uint160(0x123...)将address转为uint160。
引用类型转换
- bytes与string转换:string需转为bytes才能操作,可通过
bytes(string)转换,反之需通过string(bytes)(注意string需长度已知)。 - 数组与切片转换:固定长度数组可转为动态数组,动态数组可通过切片访问部分元素,如
bytes memory b = new bytes(3); b[0] = 0x01;后可通过b.slice(0, 2)获取前两个字节(需使用OpenZeppelin库)。
状态变量管理函数
状态变量存储在合约存储中,是智能合约的核心数据载体,Solidity通过内置语法直接操作状态变量,无需额外函数。
状态变量声明与赋值
uint256 public totalSupply; // 公开状态变量,自动生成getter函数
mapping(address => uint256) public balances; // 地址到余额的映射
string private contractName; // 私有变量,仅合约内部可访问
// 构造函数中初始化状态变量
constructor(string memory _name) {
contractName = _name;
totalSupply = 1000000 * 1e18; // 假设代币精度为18位小数
}
内置getter函数
声明为public的状态变量会自动生成getter函数,可通过contract.totalSupply() 或 contract.balances(address) 直接调用。
核心合约函数
构造函数(Constructor)
用于初始化合约状态,仅在合约部署时执行一次,注意:Solidity 0.8.0+中构造函数需使用constructor关键字,旧版本可通过与合约同名的函数实现。
contract MyToken {
string public name;
constructor(string memory _name) {
name = _name;
}
}
普通业务函数
实现合约核心逻辑,可修改状态变量或仅读取数据。
// 转账函数:修改状态变量
function transfer(address recipient, uint256 amount) external returns (bool) {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
balances[recipient] += amount;
return true;
}
// 查询函数:仅读取状态变量(view/pure函数不消耗gas)
function balanceOf(address account) external view returns (uint256) {
return balances[account];
}
修饰符(Modifier)
用于函数条件检查,减少重复代码,常见修饰符包括:
onlyOwner:仅允许合约调用者执行whenNotPaused:在合约未暂停时执行reentrancyGuard:防止重入攻击
address public owner;
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_; // 执行函数主体
}
function setOwner(address _newOwner) external onlyOwner {
owner = _newOwner;
}
事件(Event)与日志函数
事件是智能合约与外部交互的重要方式,可将数据记录在以太坊区块链的日志中,供前端应用或索引服务监听。
事件声明与触发
// 事件声明:indexed参数可被过滤
event Transfer(address indexed from, address indexed to, uint256 value);
// 在函数中触发事件
function transfer(address recipient, uint256 amount) external returns (bool) {
balances[msg.sender] -= amount;
balances[recipient] += amount;
emit Transfer(msg.sender, recipient, amount); // 触发Transfer事件
return true;
}
常见事件类型
- 代币事件:
Transfer(转账)、Approval(授权) - DeFi事件:
Deposit(存款)、Withdraw(提款)、Swap(交换) - NFT事件:
Transfer(NFT转移)、Approval(授权操作)
地址(Address)相关函数
地址是以太坊中账户的标识,合约提供了丰富的地址操作函数,分为普通地址(address)和合约地址(address payable,支持转账)。
地址属性查询
address public addr = 0x1234567890123456789012345678901234567890;
// 查询地址余额(单位:wei)
function getBalance() external view returns (uint256) {
return addr.balance;
}
// 检查地址是否为合约地址
function isContract() external view returns (bool) {
uint256 size;
assembly {
size := extcodesize(addr) // 通过内联汇编获取合约代码大小
}
return size > 0;
}
地址转账与调用
// 转账(仅address payable支持)
function sendMoney() external payable {
address payable recipient = payable(0x123...);
recipient.transfer(1000000000000000000); // 转账1 ETH(单位:wei)
}
// 调用其他合约函数(低级调用)
function callOtherContract(address _contract, bytes memory _data) external returns (bool, bytes memory) {
(bool success, bytes memory data) = _contract.call(_data);
return (success, data);
}
授权与委托调用(DelegateCall)
// 授权:允许其他地址消耗你的代币
function approve(address spender, uint256 amount) external returns (bool) {
allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
// 委托调用:在调用方上下文执行目标合约代码(需谨慎使用)
function delegateCall(address _contract, bytes memory _data) external returns (bool, bytes memory) {
(bool success, bytes memory data) = _contract.delegatecall(_data);
return (success, data);
}
数学与安全函数
安全数学运算
Solidity 0.8.0+内置了溢出检查,但旧版本需使用SafeMath库(OpenZeppelin提供)。
// Solidity 0.8.0+ 内置溢出检查 uint256 a = 100; uint256 b = type(uint256).max; uint256 c = a + b; // 自动抛出溢出错误 // 旧版本使用SafeMath uint256 c = a.add(b); // 需引入SafeMath库
位运算函数
uint256 mask = 0xff; // 低8位掩码 uint256 value = 0x1234; // 与运算:取低8位 uint256 lowBits = value & mask; // 结果:0x34 // 或运算:设置指定位 uint256 newValue = value | 0x100; // 结果:0x1334 // 左移运算:乘以2的n次方 uint256 shifted = value << 8; // 结果:0x123400
数组与映射操作函数
数组函数
uint256[] public numbers;
// 添加元素
function addNumber(uint256 _num) external {
numbers.push(_num); // 动态数组添加到末尾
}
// 获取长度
function getLength() external view returns (uint256) {
return numbers.length;
}
// 删除元素(最后一个元素填充,长度减1)
function removeLast() external {
numbers.pop();
}
// 固定长度数组操作
uint256[3] public fixedArray = [