内联汇编 #

一、汇编概述 #

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