智能合约 ✅ 验证通过
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
contract MultiReturn {
struct Order { uint256 id; address buyer; uint256 amount; bool done; }
mapping(uint256 => Order) public orders;
uint256 public count;
// ✅ 多返回值
function getInfo(uint256 id) public view
returns (address buyer, uint256 amount, bool done) {
Order storage o = orders[id];
return (o.buyer, o.amount, o.done);
}
// ✅ 命名返回值(可直接赋值,无需return)
function getInfo2(uint256 id) public view
returns (address buyer, uint256 amount, bool done) {
Order storage o = orders[id];
buyer = o.buyer; amount = o.amount; done = o.done;
}
// ✅ 解构调用(跳过不需要的返回值)
function getBuyer(uint256 id) public view returns (address) {
(address b, , ) = getInfo(id);
return b;
}
// ✅ 函数重载(同名不同参数)
function create(uint256 amt) public returns (uint256) {
count++; orders[count] = Order(count, msg.sender, amt, false);
return count;
}
function create(address buyer, uint256 amt) public returns (uint256) {
count++; orders[count] = Order(count, buyer, amt, false);
return count;
}
}
// ✅ 验证通过
contract Modifiers {
address public owner;
bool public paused;
mapping(address => bool) public blacklist;
modifier onlyOwner() { require(msg.sender == owner, "Not owner"); _; }
modifier whenNotPaused() { require(!paused, "Paused"); _; }
modifier notBlacklisted(address a) { require(!blacklist[a], "Blacklisted"); _; }
modifier minAmt(uint256 n) { require(n >= 100, "Too small"); _; }
// ✅ 多修饰符组合(按声明顺序执行)
function withdraw(uint256 amt) public onlyOwner whenNotPaused
notBlacklisted(msg.sender) minAmt(amt) {
payable(msg.sender).transfer(amt);
}
// ✅ 重入锁(防重入攻击)
bool private _locked;
modifier nonReentrant() {
require(!_locked, "ReentrancyGuard: reentrant call");
_locked = true; _; _locked = false;
}
// ✅ 限流修饰符
mapping(address => uint256) public lastCall;
modifier rateLimit(uint256 cooldown) {
require(block.timestamp >= lastCall[msg.sender] + cooldown, "Rate limit");
lastCall[msg.sender] = block.timestamp; _;
}
// ✅ 修饰符中_;前后的代码都会执行
modifier logGas() {
uint256 start = gasleft(); _;
require(start - gasleft() < 200000, "Too much gas");
}
}
// ✅ 验证通过
contract Errors {
mapping(address => uint256) public balances;
// ✅ 自定义错误(Solidity 0.8.4+) — 比require字符串省Gas!
error InsufficientBalance(uint256 have, uint256 need);
error TransferFailed(address to, uint256 amt);
error Unauthorized(address caller);
function withdraw(uint256 amt) public {
uint256 bal = balances[msg.sender];
if (bal < amt) revert InsufficientBalance(bal, amt);
balances[msg.sender] -= amt;
(bool s, ) = msg.sender.call{value: amt}("");
if (!s) revert TransferFailed(msg.sender, amt);
}
function deposit(uint256 amt) public {
require(amt > 0, "Amount must be positive");
require(balances[msg.sender] + amt >= balances[msg.sender], "Overflow");
balances[msg.sender] += amt;
}
function check(uint256 age, bool lic) public pure {
if (age < 18) revert("Too young");
if (!lic) revert("No license");
}
// assert — 检查内部不变量
function safeDiv(uint256 a, uint256 b) public pure returns (uint256) {
require(b != 0, "Div by zero");
uint256 c = a / b;
assert(a == c * b + a % b);
return c;
}
}
// ✅ 验证通过
| 方式 | 用途 | Gas退还 | 说明 |
|---|---|---|---|
| require | 输入/外部条件验证 | ✅ 退还 | 最常用 |
| revert | 复杂条件/自定义错误 | ✅ 退还 | 灵活 |
| assert | 内部不变量检查 | ✅ 退还 | 防御性编程 |
| 自定义错误 | 结构化错误信息 | ✅ 退还 | 最省Gas |
contract ABIDemo {
function encode(address to, uint256 amt) public pure returns (bytes memory) {
return abi.encodeWithSignature("transfer(address,uint256)", to, amt);
}
function execute(address token, address to, uint256 amt) public returns (bool) {
bytes memory d = abi.encodeWithSignature("transfer(address,uint256)", to, amt);
(bool s, ) = token.call(d);
require(s, "Call failed"); return s;
}
function decodeResult(bytes memory data) public pure returns (bool) {
return abi.decode(data, (bool));
}
}
// ✅ 验证通过
require vs assert?
自定义错误优势?
函数选择器?
多修饰符执行顺序?
命名返回值特点?
| 可见性 | 合约内 | 继承合约 | 外部 | 说明 |
|---|---|---|---|---|
| public | ✅ | ✅ | ✅ | 默认,最宽松 |
| external | ❌ | ❌ | ✅ | 仅外部,可calldata |
| internal | ✅ | ✅ | ❌ | 默认状态变量 |
| private | ✅ | ❌ | ❌ | 最严格 |
contract OverloadDemo {
// ✅ 同名不同参数 → 不同selector
function process(uint256 x) public pure returns (uint256) { return x * 2; }
function process(address a) public pure returns (address) { return a; }
function process(uint256 x, uint256 y) public pure returns (uint256) { return x + y; }
// ⚠️ 重载与继承的冲突
// 父合约和子合约同名函数不是重载,而是覆盖!
// 如果需要重载,两个版本必须在同一合约中
}
// ✅ 验证通过
// 接口: 所有函数都是abstract,无实现,无构造函数,无状态变量
interface IToken {
function transfer(address to, uint256 amount) external returns (bool);
function balanceOf(address account) external view returns (uint256);
}
// 抽象合约: 至少一个未实现的函数,可以有状态变量和已实现函数
abstract contract BaseToken is IToken {
mapping(address => uint256) public balances;
function balanceOf(address account) external view returns (uint256) {
return balances[account]; // ✅ 提供部分实现
}
// transfer仍为abstract,子合约必须实现
}
// ✅ 验证通过
contract FunctionalPatterns {
uint256[] public data;
// ✅ 纯函数模式: 无副作用
function _calcFee(uint256 amt) internal pure returns (uint256) {
return amt > 1000 ? amt * 3 / 1000 : 0;
}
// ✅ 检查-效果-交互(CEI)在函数中的体现
function safeWithdraw(uint256 amt) public {
// Check
require(balances[msg.sender] >= amt, "Insufficient");
// Effect
balances[msg.sender] -= amt;
// Interaction
(bool s, ) = msg.sender.call{value: amt}("");
require(s);
}
// ✅ Guard模式: 早期返回/回滚
function process(uint256 x) public pure returns (uint256) {
require(x > 0, "Zero input");
require(x < 1000, "Too large");
uint256 result = x * 2 + 1;
require(result > x, "Overflow"); // 不变量检查
return result;
}
mapping(address => uint256) public balances;
}
// ✅ 验证通过
你已深入函数系统——多返回值/修饰符/错误处理/ABI编码!
✅ 多返回值 ✅ 修饰符模式 ✅ 自定义错误 ✅ ABI编码