Files
interview/questions/14-Web3与区块链/智能合约安全.md

1258 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 智能合约安全
## 问题
1. 智能合约安全有哪些常见漏洞?
2. 什么是重入攻击Reentrancy如何防范
3. 什么是整数溢出/下溢Solidity 0.8+如何处理?
4. 什么是访问控制漏洞?如何设计权限管理?
5. 什么是前置交易Front-running如何防范
6. 什么是闪电贷攻击?如何防范?
7. 什么是跨链桥安全风险?
8. 智能合约如何进行安全审计?
9. 使用哪些工具进行安全检测?
10. 智能合约有哪些最佳实践?
---
## 标准答案
### 1. 常见智能合约漏洞
#### **OWASP Top 10 - Smart Contract**
```
1. 重入攻击Reentrancy
2. 整数溢出/下溢Arithmetic Issues
3. 访问控制失败Access Control
4. 未检查的低级调用Unchecked Low-Level Calls
5. 前置交易Front-running / TX Origin
6. 时间戳依赖Timestamp Manipulation
7. 逻辑错误Logic Errors
8. Gas限制和循环Gas Limit and Loops
9. 默认可见性Default Visibility
10. 竞态条件Race Conditions
```
---
### 2. 重入攻击Reentrancy
#### **原理**
攻击者在合约更新状态之前,递归调用提款函数,多次提取资金。
#### **经典案例The DAO攻击2016**
```
1. 攻击者存入ETH到DAO合约
2. 攻击者调用withdraw()
3. DAO合约发送ETH给攻击者
4. 攻击者的fallback函数再次调用withdraw()
5. DAO合约未更新余额再次发送ETH
6. 重复步骤3-5多次
7. 最终提取远超存款的ETH
损失360万 ETH当时价值约$7000万
```
#### **漏洞代码**
```solidity
// ❌ 易受攻击的合约
contract VulnerableBank {
mapping(address => uint256) public balances;
function deposit() public payable {
balances[msg.sender] += msg.value;
}
function withdraw(uint256 amount) public {
require(balances[msg.sender] >= amount, "Insufficient balance");
// ❌ 先转账,后更新状态(漏洞!)
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
// 更新状态(太晚了!)
balances[msg.sender] -= amount;
}
}
// 攻击合约
contract Attack {
VulnerableBank public bank;
constructor(address _bank) {
bank = VulnerableBank(_bank);
}
// 存入ETH
function attack() public payable {
bank.deposit{value: msg.value}();
bank.withdraw(msg.value);
}
// fallback函数递归调用
fallback() external payable {
if (address(bank).balance >= 1 ether) {
bank.withdraw(1 ether);
}
}
}
```
**攻击流程**
```
1. 攻击者调用attack()存入1 ETH
2. 调用withdraw(1 ether)
3. 合约检查balances[msg.sender] >= 1 ether ✓
4. 合约发送1 ETH给攻击者
5. 攻击者合约的fallback()被触发
6. fallback()再次调用withdraw(1 ether)
7. 合约检查balances[msg.sender]还是1 ether未更新
8. 合约再次发送1 ETH
9. 重复步骤5-8直到合约余额不足
```
---
#### **修复方案1检查-生效-交互模式CEI**
```solidity
// ✅ 安全的合约
contract SecureBank {
mapping(address => uint256) public balances;
function withdraw(uint256 amount) public {
require(balances[msg.sender] >= amount, "Insufficient balance");
// ✅ 先更新状态
balances[msg.sender] -= amount;
// ✅ 后交互(转账)
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
}
}
```
---
#### **修复方案2重入锁ReentrancyGuard**
```solidity
// OpenZeppelin ReentrancyGuard
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
// 使用ReentrancyGuard
contract SecureBankWithGuard is ReentrancyGuard {
mapping(address => uint256) public balances;
function withdraw(uint256 amount) public nonReentrant {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
}
}
```
---
#### **修复方案3Pull over Push模式**
```solidity
// ✅ 使用Pull模式
contract PullOverPush {
mapping(address => uint256) public balances;
mapping(address => uint256) public withdrawals;
function requestWithdraw(uint256 amount) public {
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
withdrawals[msg.sender] += amount;
}
// 用户主动提取
function withdraw() public {
uint256 amount = withdrawals[msg.sender];
require(amount > 0, "Nothing to withdraw");
withdrawals[msg.sender] = 0;
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
}
}
```
---
### 3. 整数溢出/下溢
#### **原理**
```
uint8 最大值255
uint8 最小值0
溢出:
255 + 1 = 0回绕
下溢:
0 - 1 = 255回绕
Solidity 0.8+ 自动检查溢出/下溢
旧版本需要使用SafeMath库
```
#### **漏洞代码**
```solidity
// ❌ Solidity 0.8之前
contract VulnerableToken {
uint8 public totalSupply = 255;
function mint(uint8 amount) public {
// 溢出255 + 1 = 0
totalSupply += amount;
}
}
// 攻击
// mint(1) → totalSupply = 0溢出
```
#### **修复方案**
**Solidity 0.8+**(自动检查):
```solidity
// ✅ Solidity 0.8+
contract SecureToken {
uint256 public totalSupply;
function mint(uint256 amount) public {
// ✅ 自动检查溢出失败会revert
totalSupply += amount;
}
}
```
**SafeMath库**(旧版本):
```solidity
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
}
contract SecureTokenWithSafeMath {
using SafeMath for uint256;
uint256 public totalSupply;
function mint(uint256 amount) public {
// ✅ 使用SafeMath检查溢出
totalSupply = totalSupply.add(amount);
}
}
```
---
### 4. 访问控制漏洞
#### **常见问题**
```
1. 函数未设置访问控制
2. 使用tx.origin认证中间人攻击
3. 权限提升漏洞
```
#### **漏洞代码1未保护的函数**
```solidity
// ❌ 任何人都可以调用
contract Vulnerable {
address public owner;
uint256 public price = 100;
function setPrice(uint256 _price) public {
// ❌ 没有权限检查
price = _price;
}
}
```
**修复**
```solidity
// ✅ 使用onlyOwner修饰符
contract Secure {
address public owner;
uint256 public price = 100;
constructor() {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
function setPrice(uint256 _price) public onlyOwner {
// ✅ 只有owner可以调用
price = _price;
}
}
```
---
#### **漏洞代码2tx.origin认证钓鱼攻击**
```solidity
// ❌ 易受钓鱼攻击
contract Wallet {
address public owner;
constructor() {
owner = msg.sender;
}
function withdraw() public {
// ❌ 使用tx.origin不安全
require(tx.origin == owner, "Not owner");
payable(msg.sender).transfer(address(this).balance);
}
}
// 攻击合约
contract AttackWallet {
Wallet public wallet;
constructor(address _wallet) {
wallet = Wallet(_wallet);
}
function attack() public {
// 诱导owner调用这个函数
wallet.withdraw();
}
fallback() external payable {
// 转账给攻击者
payable(msg.sender).transfer(msg.value);
}
}
```
**攻击流程**
```
1. 攻击者创建AttackWallet合约
2. 攻击者诱导owner调用AttackWallet.attack()
3. attack()调用Wallet.withdraw()
4. Wallet检查tx.origin == owner ✓owner是调用者
5. msg.sender是AttackWallet合约
6. 资金转给AttackWallet合约
7. AttackWallet的fallback()把资金转给攻击者
```
**修复**
```solidity
// ✅ 使用msg.sender
contract SecureWallet {
address public owner;
constructor() {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
function withdraw() public onlyOwner {
// ✅ 使用msg.sender
payable(msg.sender).transfer(address(this).balance);
}
}
```
---
#### **漏洞代码3权限提升**
```solidity
// ❌ 可以提升自己为管理员
contract AccessControl {
mapping(address => bool) public admins;
address public owner;
constructor() {
owner = msg.sender;
admins[owner] = true;
}
function addToAdmin(address _user) public {
// ❌ 没有检查调用者是否是admin
admins[_user] = true;
}
}
// 攻击
// 攻击者调用addToAdmin(攻击者地址)
// 攻击者成为管理员
```
**修复**
```solidity
// ✅ 检查调用者权限
contract SecureAccessControl {
mapping(address => bool) public admins;
address public owner;
constructor() {
owner = msg.sender;
admins[owner] = true;
}
modifier onlyAdmin() {
require(admins[msg.sender], "Not admin");
_;
}
function addToAdmin(address _user) public onlyAdmin {
// ✅ 只有admin可以添加新admin
admins[_user] = true;
}
}
```
---
### 5. 前置交易Front-running
#### **原理**
攻击者看到交易在内存池Mempool复制交易并设置更高的Gas Price让自己的交易先执行。
#### **示例场景**
```
1. 用户在DEX上用1 ETH买UNI价格$10
2. 攻击者看到这笔交易
3. 攻击者设置更高Gas Price抢先买入
4. 用户交易执行,价格被推高到$11
5. 攻击者立即卖出,获利
用户损失:原本应该花$10实际花了$11
攻击者获利:$1/UNI × 交易数量
```
#### **代码示例**
```solidity
// ❌ 易受前置交易攻击
contract VulnerableDEX {
mapping(address => uint256) public prices;
function setPrice(address token, uint256 price) public {
// ❌ 可以被抢先交易
prices[token] = price;
}
function trade(address token, uint256 amount) public {
uint256 price = prices[token];
// 使用price交易
}
}
```
#### **修复方案1提交-揭示模式Commit-Reveal**
```solidity
// ✅ 使用Commit-Reveal
contract CommitReveal {
struct Commitment {
bytes32 commitHash;
uint256 revealTime;
bool revealed;
}
mapping(address => Commitment) public commitments;
mapping(address => uint256) public revealedValues;
// 1. 提交哈希(隐藏真实值)
function commit(bytes32 commitHash) public {
commitments[msg.sender] = Commitment({
commitHash: commitHash,
revealTime: block.timestamp + 1 days,
revealed: false
});
}
// 2. 揭示真实值1天后
function reveal(uint256 value, uint256 salt) public {
Commitment storage c = commitments[msg.sender];
require(!c.revealed, "Already revealed");
require(block.timestamp >= c.revealTime, "Too early");
// 验证哈希
bytes32 computedHash = keccak256(abi.encodePacked(value, salt));
require(computedHash == c.commitHash, "Invalid reveal");
c.revealed = true;
revealedValues[msg.sender] = value;
}
}
```
---
#### **修复方案2批量交易**
```solidity
// ✅ 批量执行交易,减少前置交易
contract BatchTrade {
struct Trade {
address user;
address token;
uint256 amount;
uint256 price;
}
Trade[] public pendingTrades;
function submitTrade(address token, uint256 amount) public {
pendingTrades.push(Trade({
user: msg.sender,
token: token,
amount: amount,
price: 0 // 后续设置
}));
}
// 批量执行所有交易
function executeBatch() public {
for (uint256 i = 0; i < pendingTrades.length; i++) {
Trade memory t = pendingTrades[i];
// 使用平均价格执行所有交易
executeTrade(t);
}
delete pendingTrades;
}
}
```
---
### 6. 闪电贷攻击
#### **原理**
```
1. 攻击者闪电贷借入大量资金
2. 使用资金操纵市场如DEX价格
3. 利用被操纵的价格获利(如套利、清算)
4. 还款 + 手续费
5. 如果失败,交易回滚(无风险)
```
#### **攻击示例**
```solidity
// 闪电贷攻击DEX
contract FlashLoanAttack {
IUniswapV2Router public router;
IUniswapV2Pair public pair;
function attack() external {
// 1. 闪电贷借入10,000 ETH
flashLoan(10000 ether);
// 2. 在DEX上用10,000 ETH卖出代币
// → 价格被砸到极低
// 3. 在另一个DEX用低价买回代币
// → 赚取差价
// 4. 还款 10,000 ETH + 手续费
repayFlashLoan(10000 ether);
}
}
```
#### **防范措施**
```
1. 使用时间加权平均价格TWAP
- 链下预言机Chainlink
- 多个价格源聚合
2. 限制单笔交易规模
- 最大交易量限制
- 滑点保护
3. 闪电贷检测
- 单个区块内大额交易
- 可疑价格波动告警
4. 暂停机制
- 检测到攻击时暂停合约
- 多重签名恢复
```
**代码示例TWAP预言机**
```solidity
// ✅ 使用TWAP预言机
contract TWAPOracle {
uint256 public price;
uint256 public lastUpdateTime;
uint256 public constant PERIOD = 1 hours;
function updatePrice(uint256 newPrice) external {
if (block.timestamp >= lastUpdateTime + PERIOD) {
// 时间到了,可以更新
price = newPrice;
lastUpdateTime = block.timestamp;
} else {
// 未到期,使用加权平均
uint256 timeElapsed = block.timestamp - lastUpdateTime;
uint256 weight = timeElapsed * 100 / PERIOD;
price = (price * (100 - weight) + newPrice * weight) / 100;
}
}
}
```
---
### 7. 跨链桥安全风险
#### **常见攻击**
```
1. 验证节点私钥泄露
- Ronin Bridge$6.25亿被盗
- 攻击者控制了5/9个验证节点
2. 伪造签名
- Wormhole$3.2亿被盗
- 攻击者伪造了验证者签名
3. 智能合约漏洞
- Harmony Bridge$1亿被盗
- 漏洞允许绕过验证
4. 逻辑漏洞
- Nomad Bridge$1.9亿被盗
- 漏洞允许任何人伪造消息
```
#### **安全设计原则**
```solidity
// ✅ 安全的跨链桥设计
contract SecureBridge {
// 1. 多重签名验证
mapping(bytes32 => bool) public usedSignatures;
address[] public validators;
modifier validateSignature(bytes32 message, bytes memory signature) {
require(verifySignature(message, signature), "Invalid signature");
require(!usedSignatures[keccak256(signature)], "Signature used");
_;
}
// 2. 延迟提款(给用户时间取消)
mapping(address => uint256) public pendingWithdrawals;
uint256 public constant DELAY = 24 hours;
function requestWithdraw(address token, uint256 amount) public {
pendingWithdrawals[msg.sender] = block.timestamp;
emit WithdrawRequested(msg.sender, token, amount);
}
function executeWithdraw(address token, uint256 amount) public {
require(
block.timestamp >= pendingWithdrawals[msg.sender] + DELAY,
"Delay not met"
);
// 执行提款
}
// 3. 暂停机制
bool public paused;
modifier whenNotPaused() {
require(!paused, "Paused");
_;
}
function pause() public {
// 多重签名
paused = true;
}
}
```
---
### 8. 智能合约安全审计
#### **审计流程**
```
1. 文档审查
- 白皮书
- 技术文档
- 经济模型
2. 代码审查
- 手动代码审查
- 自动化工具扫描
- 测试覆盖率检查
3. 测试
- 单元测试
- 集成测试
- 模糊测试Fuzzing
4. 形式化验证
- 数学证明
- 不变量检查
5. 渗透测试
- 模拟攻击
- 红队演练
```
---
#### **审计清单**
```
✅ 访问控制
- 所有敏感函数都有访问控制
- 使用OpenZeppelin的AccessControl
✅ 重入保护
- 外部调用在状态更新之后
- 使用ReentrancyGuard
✅ 整数溢出
- 使用Solidity 0.8+
- 或使用SafeMath
✅ 外部调用
- 检查返回值
- 使用try-catch
✅ Gas优化
- 循环有限制
- 避免动态数组
✅ 测试
- 单元测试覆盖率 > 90%
- 集成测试
- 边界条件测试
✅ 文档
- NatSpec注释
- 清晰的函数说明
- 使用示例
```
---
### 9. 安全检测工具
#### **静态分析工具**
```
1. Slither
- Python开发
- 快速扫描
- 检测常见漏洞
安装:
pip install slither-analyzer
使用:
slither contract.sol
```
```bash
# Slither扫描示例
$ slither token.sol
...
INFO:Detectors:
Reentrancy in Token.withdraw(uint256) (token.sol#45-50):
External calls:
- msg.sender.call{value: amount}(gas()) (token.sol#48)
State variables written after the call(s):
- balances[msg.sender] -= amount (token.sol#49)
```
---
```
2. MythX
- 商业工具
- 深度分析
- 支持多种漏洞检测
使用:
mythx analyze contract.sol
```
---
```
3. Echidna
- 模糊测试工具
- 基于属性的测试
- 发现边缘情况
安装:
cargo install echidna
使用:
echidna-test contract.sol
```
**Echidna示例**
```solidity
// 测试不变量:总供应量 = 所有人余额之和
contract Token {
mapping(address => uint256) public balanceOf;
uint256 public totalSupply;
function transfer(address to, uint256 amount) public {
balanceOf[msg.sender] -= amount;
balanceOf[to] += amount;
}
}
// Echidna测试
contract TestToken is Token, Test {
function check_total_supply() public {
uint256 sum = 0;
// 计算所有余额(需要手动添加)
assert(totalSupply == sum);
}
}
```
---
```
4. Mythril
- 符号执行引擎
- 深度漏洞检测
- 支持攻击路径分析
安装:
pip install mythril
使用:
myth contract.sol
```
---
#### **动态分析工具**
```
1. Hardhat + Tenderly
- 交易模拟
- Gas分析
- 调试工具
2. Ganache
- 本地测试网络
- 快速部署测试
3. Fork测试
- Fork主网状态
- 在真实环境测试
```
**Fork测试示例**
```javascript
// hardhat.config.js
module.exports = {
networks: {
hardhat: {
forking: {
url: "https://eth-mainnet.alchemyapi.io/v2/YOUR-API-KEY",
blockNumber: 15000000, // Fork特定区块
},
},
},
};
// 测试
describe("Uniswap Fork Test", function () {
it("should swap on real Uniswap", async function () {
// 在主网Uniswap上交易不花真钱
const uniswap = await ethers.getContractAt("IUniswapV2Router", UNISWAP_ROUTER);
await uniswap.swapExactETHForTokens(...);
});
});
```
---
### 10. 智能合约最佳实践
#### **1. 使用OpenZeppelin库**
```solidity
// ✅ 不要重复造轮子
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract MyToken is ERC20, Ownable, ReentrancyGuard {
constructor() ERC20("My Token", "MTK") {}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
}
```
---
#### **2. 检查-生效-交互模式**
```solidity
// ✅ CEI模式
function withdraw(uint256 amount) public {
// 1. 检查Checks
require(balances[msg.sender] >= amount, "Insufficient");
// 2. 生效Effects
balances[msg.sender] -= amount;
// 3. 交互Interactions
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
}
```
---
#### **3. 使用SafeERC20**
```solidity
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
contract SafeTransfer {
using SafeERC20 for IERC20;
function transferToken(address token, address to, uint256 amount) public {
// ✅ 自动处理返回值
IERC20(token).safeTransfer(to, amount);
}
}
```
---
#### **4. 停止机制Emergency Pause**
```solidity
import "@openzeppelin/contracts/security/Pausable.sol";
contract PausableContract is Pausable, Ownable {
function deposit() public payable whenNotPaused {
// 正常逻辑
}
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
}
```
---
#### **5. 事件日志**
```solidity
contract LogEvents {
event Withdrawal(address indexed user, uint256 amount, uint256 timestamp);
function withdraw(uint256 amount) public {
// ✅ 记录所有重要操作
emit Withdrawal(msg.sender, amount, block.timestamp);
// 执行提款
payable(msg.sender).transfer(amount);
}
}
```
---
#### **6. 限流机制**
```solidity
contract RateLimiter {
mapping(address => uint256) public lastCallTime;
uint256 public constant COOLDOWN = 1 minutes;
modifier rateLimit() {
require(
block.timestamp >= lastCallTime[msg.sender] + COOLDOWN,
"Cooldown not met"
);
_;
lastCallTime[msg.sender] = block.timestamp;
}
function sensitiveOperation() public rateLimit {
// 限制每个用户每分钟只能调用一次
}
}
```
---
#### **7. 多重签名钱包**
```solidity
// ✅ 关键操作使用多签
contract MultiSigWallet {
address[] public owners;
uint256 public required;
mapping(uint256 => Transaction) public transactions;
mapping(uint256 => mapping(address => bool)) public confirmations;
struct Transaction {
address to;
uint256 value;
bytes data;
bool executed;
}
function submitTransaction(address to, uint256 value, bytes memory data)
public
{
uint256 txIndex = transactions.length;
transactions[txIndex] = Transaction({
to: to,
value: value,
data: data,
executed: false
});
confirmTransaction(txIndex);
}
function confirmTransaction(uint256 txIndex) public {
// 需要多个所有者确认
confirmations[txIndex][msg.sender] = true;
if (isConfirmed(txIndex)) {
executeTransaction(txIndex);
}
}
function isConfirmed(uint256 txIndex) public view returns (bool) {
uint256 count = 0;
for (uint256 i = 0; i < owners.length; i++) {
if (confirmations[txIndex][owners[i]]) {
count += 1;
}
}
return count >= required;
}
}
```
---
#### **8. 升级模式**
```solidity
// ✅ 使用代理模式升级
contract LogicV1 {
uint256 public value;
function setValue(uint256 _value) public {
value = _value;
}
}
contract LogicV2 {
uint256 public value;
uint256 public newValue;
function setValue(uint256 _value) public {
value = _value;
newValue = _value * 2;
}
}
// 使用OpenZeppelin Transparent Proxy
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
// 部署
// 1. 部署LogicV1
// 2. 部署Proxy指向LogicV1
// 3. 用户通过Proxy交互
// 4. 升级部署LogicV2调用Proxy.upgradeTo(LogicV2)
```
---
## 结合简历的面试题
### 1. 电商风控 vs DeFi安全
**面试官会问**
> "你在电商做过风控系统DeFi安全有什么异同"
**参考回答**
```
电商风控:
- 反欺诈:识别虚假订单、刷单
- 信用评估:用户信用评分
- 异常检测:异常交易行为
DeFi安全
- 智能合约审计:代码漏洞检测
- 链上监控:异常交易监控
- 价格预言机:防止价格操纵
- MEV保护防止三明治攻击
共同点:
- 需要实时监控系统
- 需要异常检测机制
- 需要快速响应机制
差异:
- 电商:中心化,可以人工介入
- DeFi去中心化只能通过智能合约
```
---
### 2. 高并发与Gas优化
**面试官会问**
> "你做过高并发系统智能合约如何优化Gas"
**参考回答**
```
Web2高并发
- 缓存热点数据
- 异步处理
- 数据库优化
Web3 Gas优化
1. 存储优化
- 使用打包类型uint256 vs uint8
- 使用短字符串
- 删除不需要的数据refund gas
2. 循环优化
- 限制循环次数
- 使用mapping代替array查找
3. 批量操作
- 批量转账
- 批量Mint
4. 链下计算
- Merkle Tree
- 零知识证明
示例:
// ❌ 高Gas
for (uint256 i = 0; i < 1000; i++) {
users[i].reward = calculateReward(i);
}
// ✅ 低Gas链下计算 + Merkle Proof
bytes32 public merkleRoot;
function claimReward(uint256 amount, bytes32[] memory proof) public {
require(verifyMerkleProof(msg.sender, amount, proof), "Invalid proof");
payable(msg.sender).transfer(amount);
}
```
---
## 智能合约安全面试加分项
### 1. 实战经验
- 参与过智能合约审计
- 发现过真实漏洞
- 有漏洞修复经验
- 熟悉常见攻击手法
### 2. 技术深度
- 理解EVM底层机制
- 熟悉汇编语言Yul
- 了解形式化验证
- 掌握Gas优化技巧
### 3. 工具使用
- 熟练使用Slither、MythX
- 会使用Foundry测试框架
- 会使用Tenderly调试
- 了解Fuzzing测试
### 4. 安全意识
- 防御性编程思维
- 最小权限原则
- 深度防御策略
- 持续学习最新漏洞