第一个Solidity合约 #

一、Hello World合约 #

1.1 完整代码 #

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract HelloWorld {
    string public greet = "Hello, World!";

    function setGreet(string memory _greet) public {
        greet = _greet;
    }

    function getGreet() public view returns (string memory) {
        return greet;
    }
}

1.2 代码解析 #

1. SPDX许可证声明

solidity
// SPDX-License-Identifier: MIT
  • 每个Solidity文件必须以SPDX许可证声明开头
  • MIT是最常用的开源许可证
  • 如果不想指定,可以使用UNLICENSED

2. 编译器版本声明

solidity
pragma solidity ^0.8.0;
  • pragma:指示编译器如何处理代码
  • ^0.8.0:使用0.8.x版本(不包含0.9.0)
  • 推荐使用最新稳定版本

3. 合约定义

solidity
contract HelloWorld {
    // 合约内容
}
  • contract:关键字,定义一个合约
  • HelloWorld:合约名称
  • 合约类似于面向对象语言中的类

4. 状态变量

solidity
string public greet = "Hello, World!";
  • string:数据类型,字符串
  • public:可见性修饰符,公开可访问
  • greet:变量名
  • 状态变量永久存储在区块链上

5. 函数定义

solidity
function setGreet(string memory _greet) public {
    greet = _greet;
}
  • function:函数关键字
  • setGreet:函数名
  • string memory _greet:参数,memory表示临时存储
  • public:公开可调用

6. view函数

solidity
function getGreet() public view returns (string memory) {
    return greet;
}
  • view:只读函数,不修改状态
  • returns:返回值类型声明

二、合约结构详解 #

2.1 完整合约结构 #

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ContractName {
    // 1. 状态变量
    uint256 public count;
    address public owner;
    
    // 2. 事件
    event CountChanged(uint256 newCount);
    
    // 3. 修饰器
    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }
    
    // 4. 构造函数
    constructor() {
        owner = msg.sender;
    }
    
    // 5. 函数
    function increment() public {
        count++;
        emit CountChanged(count);
    }
    
    // 6. 接收函数
    receive() external payable {}
    
    // 7. 回退函数
    fallback() external payable {}
}

2.2 各部分说明 #

组成部分 说明 示例
SPDX声明 许可证标识 // SPDX-License-Identifier: MIT
pragma 编译器版本 pragma solidity ^0.8.0;
import 导入其他文件 import "./Other.sol";
状态变量 永久存储数据 uint256 public count;
事件 日志记录 event Transfer(...);
修饰器 函数修饰 modifier onlyOwner() {...}
构造函数 初始化执行 constructor() {...}
函数 业务逻辑 function foo() {...}
接收函数 接收ETH receive() external payable {}
回退函数 未知调用 fallback() external payable {}

三、在Remix中部署 #

3.1 创建文件 #

  1. 打开 https://remix.ethereum.org
  2. 点击左侧文件浏览器中的"Create New File"
  3. 命名为HelloWorld.sol
  4. 粘贴合约代码

3.2 编译合约 #

  1. 点击左侧"SOLIDITY COMPILER"图标
  2. 选择编译器版本0.8.x
  3. 点击"Compile HelloWorld.sol"
  4. 确认编译成功(绿色勾号)

3.3 部署合约 #

  1. 点击左侧"DEPLOY & RUN TRANSACTIONS"图标
  2. 选择环境:
    • Remix VM:本地虚拟机,快速测试
    • Injected Provider:连接MetaMask钱包
    • Hardhat Provider:连接Hardhat节点
  3. 点击"Deploy"按钮
  4. 等待部署完成

3.4 交互测试 #

部署成功后:

  1. 展开"Deployed Contracts"
  2. 点击greet按钮查看值
  3. setGreet输入框输入新值
  4. 点击setGreet按钮
  5. 再次点击greet查看更新后的值

四、在Hardhat中部署 #

4.1 项目设置 #

bash
mkdir hello-hardhat
cd hello-hardhat
npm init -y
npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox
npx hardhat init

4.2 编写合约 #

创建contracts/HelloWorld.sol

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract HelloWorld {
    string public greet = "Hello, World!";

    function setGreet(string memory _greet) public {
        greet = _greet;
    }

    function getGreet() public view returns (string memory) {
        return greet;
    }
}

4.3 编译合约 #

bash
npx hardhat compile

4.4 编写部署脚本 #

创建scripts/deploy.js

javascript
const hre = require("hardhat");

async function main() {
  const HelloWorld = await hre.ethers.getContractFactory("HelloWorld");
  const hello = await HelloWorld.deploy();
  await hello.deployed();
  console.log("HelloWorld deployed to:", hello.address);
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

4.5 部署到本地网络 #

bash
# 终端1:启动本地节点
npx hardhat node

# 终端2:部署合约
npx hardhat run scripts/deploy.js --network localhost

4.6 部署到测试网 #

修改hardhat.config.js

javascript
require("@nomicfoundation/hardhat-toolbox");

module.exports = {
  solidity: "0.8.20",
  networks: {
    sepolia: {
      url: "https://sepolia.infura.io/v3/YOUR_INFURA_KEY",
      accounts: ["YOUR_PRIVATE_KEY"]
    }
  }
};

部署命令:

bash
npx hardhat run scripts/deploy.js --network sepolia

五、在Foundry中部署 #

5.1 创建项目 #

bash
forge init hello-foundry
cd hello-foundry

5.2 编写合约 #

创建src/HelloWorld.sol

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract HelloWorld {
    string public greet = "Hello, World!";

    function setGreet(string memory _greet) public {
        greet = _greet;
    }

    function getGreet() public view returns (string memory) {
        return greet;
    }
}

5.3 编写测试 #

创建test/HelloWorld.t.sol

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "forge-std/Test.sol";
import "../src/HelloWorld.sol";

contract HelloWorldTest is Test {
    HelloWorld hello;

    function setUp() public {
        hello = new HelloWorld();
    }

    function testInitialGreet() public {
        assertEq(hello.greet(), "Hello, World!");
    }

    function testSetGreet() public {
        hello.setGreet("Hello, Foundry!");
        assertEq(hello.greet(), "Hello, Foundry!");
    }
}

5.4 运行测试 #

bash
forge test

输出:

text
Running 2 tests for test/HelloWorld.t.sol:HelloWorldTest
[PASS] testInitialGreet() (gas: 5234)
[PASS] testSetGreet() (gas: 12345)
Test result: ok. 2 passed; 0 failed; finished in 1.23s

5.5 部署合约 #

bash
forge create src/HelloWorld.sol:HelloWorld --rpc-url $RPC_URL --private-key $PRIVATE_KEY

六、Gas与交易 #

6.1 Gas概念 #

Gas是以太坊上执行操作的计算单位:

概念 说明
Gas 计算单位
Gas Price 每单位Gas的价格(Gwei)
Gas Limit 交易最大Gas消耗
Gas Used 实际消耗的Gas

6.2 查看Gas消耗 #

在Remix中:

  1. 展开交易详情
  2. 查看"transaction cost"和"execution cost"
solidity
// Gas消耗示例
function setGreet(string memory _greet) public {
    greet = _greet;  // SSTORE操作,消耗Gas
}

6.3 Gas优化建议 #

solidity
// 优化前:每次都存储
contract Bad {
    string public greet;
    
    function setGreet(string memory _greet) public {
        greet = _greet;  // 每次都消耗Gas
    }
}

// 优化后:使用事件记录
contract Good {
    string public greet;
    event GreetChanged(string newGreet);
    
    function setGreet(string memory _greet) public {
        greet = _greet;
        emit GreetChanged(_greet);  // 事件更便宜
    }
}

七、常见问题 #

7.1 编译错误 #

问题:版本不匹配

text
Error: Source file requires different compiler version

解决:确保pragma声明与编译器版本一致。

问题:语法错误

text
Error: Expected ';' but got '}'

解决:检查语法,确保每个语句以分号结尾。

7.2 部署错误 #

问题:Gas不足

text
Error: Transaction ran out of gas

解决:增加Gas Limit。

问题:网络连接失败

text
Error: could not detect network

解决:检查网络配置和RPC URL。

7.3 运行时错误 #

问题:调用失败

text
Error: call revert exception

解决:检查require条件和函数逻辑。

八、总结 #

第一个合约要点:

要点 说明
SPDX声明 必须的许可证标识
pragma 指定编译器版本
contract 定义合约
状态变量 链上永久存储
函数 业务逻辑实现

开发流程:

text
编写合约 → 编译 → 测试 → 部署 → 交互

下一步,让我们学习Solidity基础语法!

最后更新:2026-03-27