智能合约 ✅ 验证通过
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
contract Calculator {
uint256 public lastResult;
event Calc(string op, uint256 result);
function add(uint256 a, uint256 b) external returns (uint256) {
lastResult = a + b; emit Calc("add", lastResult); return lastResult;
}
function mul(uint256 a, uint256 b) external returns (uint256) {
lastResult = a * b; emit Calc("mul", lastResult); return lastResult;
}
receive() external payable {}
}
interface ICalc {
function add(uint256, uint256) external returns (uint256);
}
contract Caller {
function callDirect(address c, uint256 a, uint256 b) public returns (uint256) {
return Calculator(c).add(a, b);
}
function callInterface(address c, uint256 a, uint256 b) public returns (uint256) {
return ICalc(c).add(a, b);
}
function callLowLevel(address c, uint256 a, uint256 b) public returns (bool, uint256) {
bytes memory d = abi.encodeWithSignature("add(uint256,uint256)", a, b);
(bool ok, bytes memory r) = c.call(d);
uint256 res = ok && r.length >= 32 ? abi.decode(r, (uint256)) : 0;
return (ok, res);
}
function callWithETH(address t) public payable returns (bool) {
(bool s, ) = t.call{value: msg.value}("");
require(s); return s;
}
}
// ✅ 验证通过
contract SimpleProxy {
address public impl;
address public admin;
uint256 public ver;
constructor(address i) { impl = i; admin = msg.sender; ver = 1; }
fallback() external payable {
address i = impl;
assembly {
calldatacopy(0, 0, calldatasize())
let r := delegatecall(gas(), i, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch r case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}
}
receive() external payable {}
function upgrade(address n) public {
require(msg.sender == admin); impl = n; ver++;
}
}
contract LogicV1 { uint256 public count; function inc() public { count += 1; } }
contract LogicV2 { uint256 public count; uint256 public total; function inc() public { count += 2; total++; } }
// ✅ 验证通过 ⚠️存储布局必须对齐!
// ❌ 存在重入漏洞!
contract Vulnerable {
mapping(address => uint256) public balances;
function withdraw() public {
uint256 b = balances[msg.sender];
(bool s, ) = msg.sender.call{value: b}(""); // 先转账
require(s);
balances[msg.sender] = 0; // 后更新(太晚!)
}
}
// ✅ CEI模式 (Checks-Effects-Interactions)
contract Secure {
mapping(address => uint256) public balances;
bool private _locked;
modifier nonReentrant() {
require(!_locked, "Reentrancy"); _locked = true; _; _locked = false;
}
function withdraw() public nonReentrant {
uint256 b = balances[msg.sender];
require(b > 0);
balances[msg.sender] = 0; // 先更新(Effects)
(bool s, ) = msg.sender.call{value: b}(""); // 后交互(Interactions)
require(s);
}
}
// ✅ 验证通过
delegatecall vs call?
CEI正确顺序?
重入根因?
代理升级最重要?
低级call风险?
contract ReceiveFallback {
event Received(address from, uint256 amount, bytes data);
// ✅ 接收纯ETH转账(无calldata)
receive() external payable {
emit Received(msg.sender, msg.value, "");
}
// ✅ 处理不匹配的函数调用(有calldata)
fallback() external payable {
emit Received(msg.sender, msg.value, msg.data);
}
// 调用优先级:
// 有data → fallback | 无data → receive(如果存在)
// 只有fallback → 所有情况都走fallback
}
// ✅ 验证通过
contract Factory {
// CREATE: 地址 = keccak256(rlp([sender, nonce]))
function create(bytes memory bytecode) public returns (address) {
address addr;
assembly { addr := create(0, add(bytecode, 0x20), mload(bytecode)) }
require(addr != address(0)); return addr;
}
// CREATE2: 地址 = keccak256(0xff, sender, salt, keccak256(bytecode))
// ✅ 可预先计算部署地址! 反事实部署基础
function create2(bytes memory bytecode, uint256 salt) public returns (address) {
address addr;
assembly { addr := create2(0, add(bytecode, 0x20), mload(bytecode), salt) }
require(addr != address(0)); return addr;
}
// 预计算地址(不实际部署)
function getAddress(bytes memory bytecode, uint256 salt) public view returns (address) {
return address(uint160(uint256(keccak256(abi.encodePacked(
bytes1(0xff), address(this), salt, keccak256(bytecode)
)))));
}
}
// ✅ 验证通过
contract MultiSigWallet {
event Deposit(address indexed sender, uint256 amount);
event SubmitTransaction(address indexed owner, uint256 txIndex, address to, uint256 value, bytes data);
event ConfirmTransaction(address indexed owner, uint256 txIndex);
event ExecuteTransaction(address indexed owner, uint256 txIndex);
address[] public owners;
mapping(address => bool) public isOwner;
uint256 public required; // 需要多少确认
struct Transaction { address to; uint256 value; bytes data; bool executed; }
Transaction[] public transactions;
mapping(uint256 => mapping(address => bool)) public isConfirmed;
modifier onlyOwner() { require(isOwner[msg.sender]); _; }
modifier txExists(uint256 i) { require(i < transactions.length); _; }
modifier notExecuted(uint256 i) { require(!transactions[i].executed); _; }
modifier notConfirmed(uint256 i) { require(!isConfirmed[i][msg.sender]); _; }
constructor(address[] memory _owners, uint256 _required) {
require(_owners.length >= _required && _required > 0);
for (uint i = 0; i < _owners.length; i++) {
require(!isOwner[_owners[i]] && _owners[i] != address(0));
isOwner[_owners[i]] = true; owners.push(_owners[i]);
}
required = _required;
}
function submitTransaction(address to, uint256 value, bytes memory data) public onlyOwner returns (uint256) {
transactions.push(Transaction(to, value, data, false));
emit SubmitTransaction(msg.sender, transactions.length - 1, to, value, data);
return transactions.length - 1;
}
function confirmTransaction(uint256 i) public onlyOwner txExists(i) notExecuted(i) notConfirmed(i) {
isConfirmed[i][msg.sender] = true;
emit ConfirmTransaction(msg.sender, i);
}
function executeTransaction(uint256 i) public onlyOwner txExists(i) notExecuted(i) {
uint256 count = 0;
for (uint j = 0; j < owners.length; j++) if (isConfirmed[i][owners[j]]) count++;
require(count >= required, "Not enough confirmations");
Transaction storage t = transactions[i]; t.executed = true;
(bool s, ) = t.to.call{value: t.value}(t.data);
require(s, "tx failed"); emit ExecuteTransaction(msg.sender, i);
}
receive() external payable { emit Deposit(msg.sender, msg.value); }
}
// ✅ 验证通过
// ✅ 合约组合: 通过继承和接口组合功能
contract ReentrancyGuard {
bool private _locked;
modifier nonReentrant() {
require(!_locked, "Reentrancy"); _locked = true; _;
_locked = false;
}
}
contract Ownable {
address public owner;
modifier onlyOwner() { require(msg.sender == owner); _; }
constructor() { owner = msg.sender; }
}
contract Pausable {
bool public paused;
modifier whenNotPaused() { require(!paused); _; }
function togglePause() public virtual { paused = !paused; }
}
// ✅ 组合继承
contract DeFiVault is Ownable, ReentrancyGuard, Pausable {
mapping(address => uint256) public deposits;
function deposit() public payable whenNotPaused nonReentrant {
deposits[msg.sender] += msg.value;
}
function withdraw(uint256 amt) public whenNotPaused nonReentrant {
require(deposits[msg.sender] >= amt);
deposits[msg.sender] -= amt;
(bool s, ) = msg.sender.call{value: amt}("");
require(s);
}
function togglePause() public override onlyOwner { super.togglePause(); }
}
// ✅ 验证通过
你已掌握合约间通信与安全——调用/代理/重入防护!
✅ 调用方式 ✅ 代理模式 ✅ 重入防护 ✅ CEI模式