内联汇编 #
一、汇编概述 #
Solidity支持内联汇编(Yul语言),可以直接操作EVM,实现更底层的操作和Gas优化。
二、基本语法 #
2.1 assembly块 #
solidity
contract AssemblyBasic {
function add(uint256 a, uint256 b) public pure returns (uint256) {
uint256 result;
assembly {
result := add(a, b)
}
return result;
}
function multiply(uint256 a, uint256 b) public pure returns (uint256) {
uint256 result;
assembly {
result := mul(a, b)
}
return result;
}
}
2.2 变量访问 #
solidity
contract VariableAccess {
uint256 public value = 100;
function getValue() public view returns (uint256) {
uint256 result;
assembly {
result := sload(0) // 读取slot 0
}
return result;
}
function setValue(uint256 newValue) public {
assembly {
sstore(0, newValue) // 写入slot 0
}
}
}
三、常用操作码 #
3.1 算术运算 #
solidity
contract ArithmeticOps {
function add(uint256 a, uint256 b) public pure returns (uint256) {
assembly {
let result := add(a, b)
mstore(0, result)
return(0, 32)
}
}
function sub(uint256 a, uint256 b) public pure returns (uint256) {
assembly {
let result := sub(a, b)
mstore(0, result)
return(0, 32)
}
}
function mul(uint256 a, uint256 b) public pure returns (uint256) {
assembly {
let result := mul(a, b)
mstore(0, result)
return(0, 32)
}
}
function div(uint256 a, uint256 b) public pure returns (uint256) {
assembly {
let result := div(a, b)
mstore(0, result)
return(0, 32)
}
}
}
3.2 比较运算 #
solidity
contract ComparisonOps {
function eq(uint256 a, uint256 b) public pure returns (bool) {
assembly {
let result := eq(a, b)
mstore(0, result)
return(0, 32)
}
}
function lt(uint256 a, uint256 b) public pure returns (bool) {
assembly {
let result := lt(a, b)
mstore(0, result)
return(0, 32)
}
}
function gt(uint256 a, uint256 b) public pure returns (bool) {
assembly {
let result := gt(a, b)
mstore(0, result)
return(0, 32)
}
}
}
3.3 内存操作 #
solidity
contract MemoryOps {
function mstoreDemo(uint256 value) public pure returns (bytes32) {
assembly {
mstore(0x80, value) // 在内存位置0x80存储值
return(0x80, 32)
}
}
function mloadDemo() public pure returns (uint256) {
assembly {
let value := mload(0x40) // 读取空闲内存指针
mstore(0, value)
return(0, 32)
}
}
}
3.4 存储操作 #
solidity
contract StorageOps {
uint256 private value1;
uint256 private value2;
function readSlot(uint256 slot) public view returns (uint256) {
assembly {
let result := sload(slot)
mstore(0, result)
return(0, 32)
}
}
function writeSlot(uint256 slot, uint256 value) public {
assembly {
sstore(slot, value)
}
}
}
四、控制流 #
4.1 条件语句 #
solidity
contract AssemblyIf {
function max(uint256 a, uint256 b) public pure returns (uint256) {
assembly {
switch gt(a, b)
case 1 {
mstore(0, a)
}
default {
mstore(0, b)
}
return(0, 32)
}
}
function min(uint256 a, uint256 b) public pure returns (uint256) {
assembly {
switch lt(a, b)
case 1 {
mstore(0, a)
}
default {
mstore(0, b)
}
return(0, 32)
}
}
}
4.2 循环 #
solidity
contract AssemblyLoop {
function sum(uint256 n) public pure returns (uint256) {
assembly {
let total := 0
let i := 1
for {} lt(i, add(n, 1)) { i := add(i, 1) } {
total := add(total, i)
}
mstore(0, total)
return(0, 32)
}
}
}
五、实际应用示例 #
5.1 高效复制 #
solidity
contract EfficientCopy {
function copyBytes(
bytes memory source,
bytes memory destination
) public pure {
assembly {
let length := mload(source)
// 复制长度
mstore(destination, length)
// 复制数据
let src := add(source, 32)
let dst := add(destination, 32)
for { let i := 0 } lt(i, length) { i := add(i, 32) } {
mstore(add(dst, i), mload(add(src, i)))
}
}
}
}
5.2 签名恢复 #
solidity
contract SignatureRecover {
function recoverSigner(
bytes32 hash,
bytes memory signature
) public pure returns (address) {
assembly {
let r := mload(add(signature, 0x20))
let s := mload(add(signature, 0x40))
let v := byte(0, mload(add(signature, 0x60)))
// 调整v值
if lt(v, 27) { v := add(v, 27) }
// 恢复地址
let addr := ecrecover(hash, v, r, s)
mstore(0, addr)
return(0, 32)
}
}
}
5.3 代理合约 #
solidity
contract ProxyAssembly {
address public implementation;
constructor(address _implementation) {
implementation = _implementation;
}
fallback() external payable {
address impl = implementation;
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(
gas(),
impl,
0,
calldatasize(),
0,
0
)
returndatacopy(0, 0, returndatasize())
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
}
六、安全注意事项 #
6.1 边界检查 #
solidity
contract SafeAssembly {
function safeAdd(uint256 a, uint256 b) public pure returns (uint256) {
assembly {
let result := add(a, b)
// 检查溢出
if lt(result, a) {
revert(0, 0)
}
mstore(0, result)
return(0, 32)
}
}
}
6.2 内存安全 #
solidity
contract MemorySafety {
function safeAllocate(uint256 size) public pure returns (bytes memory) {
assembly {
// 获取空闲内存指针
let freePtr := mload(0x40)
// 分配内存
mstore(0x40, add(freePtr, add(size, 32)))
// 存储长度
mstore(freePtr, size)
return(freePtr, add(size, 32))
}
}
}
七、总结 #
汇编要点:
| 操作码 | 说明 |
|---|---|
| add/sub/mul/div | 算术运算 |
| eq/lt/gt | 比较运算 |
| mstore/mload | 内存操作 |
| sstore/sload | 存储操作 |
| call/delegatecall | 合约调用 |
使用建议:
- 仅在必要时使用汇编
- 注意边界检查
- 保持内存安全
- 充分测试
接下来,让我们学习安全性!
最后更新:2026-03-27