以太坊作为全球最大的智能合约平台,其强大的功能离不开丰富多样的智能合约函数,无论是代币发行、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 = [