以太坊智能合约开发完全指南


文档摘要

以太坊智能合约开发完全指南 智能合约是区块链应用的核心,本文提供从入门到实战的完整开发指南。 Solidity基础 Hello World 数据类型 核心概念 事件和日志 修饰器 错误处理 常见模式 可升级合约 访问控制 暂停机制 ERC代币标准 ERC20代币 ERC721 NFT DeFi协议 去中心化交易所 借贷协议 安全最佳实践 重入攻击防护 整数溢出防护 开发工具链 Hardhat配置 测试 通过掌握Solidity和智能合约开发,可以构建去中心化应用,参与Web3生态系统建设。

以太坊智能合约开发完全指南

智能合约是区块链应用的核心,本文提供从入门到实战的完整开发指南。

1. Solidity基础

Hello World

// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract HelloWorld { string public message = "Hello, World!"; function setMessage(string memory newMessage) public { message = newMessage; } function getMessage() public view returns (string memory) { return message; } }

数据类型

contract DataTypes { // 值类型 bool public isActive = true; int256 public balance = -100; uint256 public amount = 1000; address public owner = msg.sender; bytes32 public hash = keccak256("test"); // 引用类型 uint256[] public numbers; mapping(address => uint256) public balances; // 结构体 struct User { string name; uint256 age; } User public user; // 枚举 enum State { Active, Inactive, Pending } State public state; }

2. 核心概念

事件和日志

contract Events { event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); function transfer(address to, uint256 amount) public { emit Transfer(msg.sender, to, amount); } }

修饰器

contract Modifiers { address public owner; constructor() { owner = msg.sender; } modifier onlyOwner() { require(msg.sender == owner, "Not owner"); _; // 继续执行函数 } modifier validAddress(address addr) { require(addr != address(0), "Invalid address"); _; } function criticalFunction() public onlyOwner validAddress(msg.sender) { // 只有owner才能调用 } }

错误处理

contract ErrorHandling { error InsufficientBalance(uint256 requested, uint256 available); function withdraw(uint256 amount) public { uint256 balance = getBalance(); if (amount > balance) { revert InsufficientBalance(amount, balance); } payable(msg.sender).transfer(amount); } function getBalance() public view returns (uint256) { return address(this).balance; } }

3. 常见模式

可升级合约

// 代理合约 contract Proxy { address public implementation; address public admin; constructor(address _implementation) { implementation = _implementation; admin = msg.sender; } 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()) } } } function upgrade(address newImplementation) external { require(msg.sender == admin, "Only admin"); implementation = newImplementation; } } // 逻辑合约 contract LogicV1 { uint256 public value; function setValue(uint256 _value) external { value = _value; } } contract LogicV2 { uint256 public value; uint256 public extraValue; function setValue(uint256 _value) external { value = _value * 2; // 修改后的逻辑 } function setExtraValue(uint256 _extraValue) external { extraValue = _extraValue; } }

访问控制

import "@openzeppelin/contracts/access/AccessControl.sol"; contract RoleBased is AccessControl { bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); bytes32 public constant USER_ROLE = keccak256("USER_ROLE"); constructor() { _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); _grantRole(ADMIN_ROLE, msg.sender); } function adminFunction() external onlyRole(ADMIN_ROLE) { // 只有admin可以调用 } function userFunction() external onlyRole(USER_ROLE) { // 有user role的都可以调用 } }

暂停机制

import "@openzeppelin/contracts/security/Pausable.sol"; contract PausableContract is Pausable { uint256 public value; function setValue(uint256 _value) external whenNotPaused { value = _value; } function pause() external onlyOwner { _pause(); } function unpause() external onlyOwner { _unpause(); } }

4. ERC代币标准

ERC20代币

import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract MyToken is ERC20 { constructor(uint256 initialSupply) ERC20("MyToken", "MTK") { _mint(msg.sender, initialSupply * 10**18); } function mint(address to, uint256 amount) public onlyOwner { _mint(to, amount * 10**18); } }

ERC721 NFT

import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; contract MyNFT is ERC721, ERC721URIStorage { uint256 private _tokenId; constructor() ERC721("MyNFT", "MNFT") {} function mintNFT(address recipient, string memory tokenURI) public returns (uint256) { _tokenId++; _mint(recipient, _tokenId); _setTokenURI(_tokenId, tokenURI); return _tokenId; } function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) { return super.tokenURI(tokenId); } }

5. DeFi协议

去中心化交易所

import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol"; import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol"; contract SimpleDEX { IUniswapV2Factory public factory; constructor(address _factory) { factory = IUniswapV2Factory(_factory); } function createPool(address tokenA, address tokenB) external { factory.createPair(tokenA, tokenB); } function addLiquidity( address pair, uint256 amountA, uint256 amountB ) external { IERC20(tokenA).transferFrom(msg.sender, pair, amountA); IERC20(tokenB).transferFrom(msg.sender, pair, amountB); IUniswapV2Pair(pair).mint(msg.sender); } function swap( address pair, uint256 amountIn, uint256 amountOutMin, address[] calldata path ) external { IERC20(path[0]).transferFrom(msg.sender, pair, amountIn); IUniswapV2Pair(pair).swap( amountOutMin, 0, msg.sender, block.timestamp ); } }

借贷协议

contract LendingProtocol { mapping(address => uint256) public deposits; mapping(address => uint256) public borrows; uint256 public constant COLLATERAL_RATIO = 150; // 150% function deposit(uint256 amount) external { IERC20(usdc).transferFrom(msg.sender, address(this), amount); deposits[msg.sender] += amount; } function borrow(uint256 amount) external { uint256 collateral = deposits[msg.sender]; uint256 maxBorrow = (collateral * 100) / COLLATERAL_RATIO; require(amount <= maxBorrow, "Insufficient collateral"); borrows[msg.sender] += amount; IERC20(usdc).transfer(msg.sender, amount); } function liquidate(address borrower) external { uint256 collateral = deposits[borrower]; uint256 borrowAmount = borrows[borrower]; uint256 maxBorrow = (collateral * 100) / COLLATERAL_RATIO; require(borrowAmount > maxBorrow, "Not liquidatable"); // 清算逻辑 uint256 repayAmount = borrowAmount * 105 / 100; // 5% 清算奖励 IERC20(usdc).transferFrom(msg.sender, address(this), repayAmount); borrows[borrower] = 0; deposits[borrower] = 0; IERC20(usdc).transfer(msg.sender, collateral); } }

6. 安全最佳实践

重入攻击防护

import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; contract SecureVault is ReentrancyGuard { mapping(address => uint256) public balances; function deposit() external payable { balances[msg.sender] += msg.value; } function withdraw(uint256 amount) external nonReentrant { require(balances[msg.sender] >= amount, "Insufficient balance"); // 检查-生效-交互模式 balances[msg.sender] -= amount; payable(msg.sender).transfer(amount); } }

整数溢出防护

import "@openzeppelin/contracts/utils/math/SafeMath.sol"; contract SafeMath { using SafeMath for uint256; function transfer(address to, uint256 amount) public { balances[msg.sender] = balances[msg.sender].sub(amount); balances[to] = balances[to].add(amount); } }

7. 开发工具链

Hardhat配置

// hardhat.config.js require("@nomicfoundation/hardhat-toolbox"); require("@openzeppelin/hardhat-upgrades"); module.exports = { solidity: { version: "0.8.20", settings: { optimizer: { enabled: true, runs: 200 } } }, networks: { hardhat: { forking: { url: "https://eth-mainnet.alchemyapi.io/v2/YOUR-API-KEY" } }, sepolia: { url: "https://eth-sepolia.alchemyapi.io/v2/YOUR-API-KEY", accounts: [PRIVATE_KEY] } }, etherscan: { apiKey: ETHERSCAN_API_KEY } };

测试

const { expect } = require("chai"); describe("Token Contract", function () { it("Should deploy with initial supply", async function () { const Token = await ethers.getContractFactory("MyToken"); const token = await Token.deploy(1000000); expect(await token.totalSupply()).to.equal(1000000 * 10**18); }); it("Should transfer tokens", async function () { const [owner, addr1] = await ethers.getSigners(); await token.transfer(addr1.address, 100); expect(await token.balanceOf(addr1.address)).to.equal(100); }); });

通过掌握Solidity和智能合约开发,可以构建去中心化应用,参与Web3生态系统建设。


发布者: 作者: 转发
评论区 (0)
U