以太坊作为全球领先的智能合约平台,不仅支持加密货币 Ether (ETH) 的交易,更重要的是,它允许开发者通过智能合约创建和发布自己的代币(Token),这些代币可以代表各种资产,从稳定币、 utility 代币到治理代币等,虽然 Solidity 是以太坊智能合约开发的主流语言,但对于许多熟悉 Java 的开发者来说,使用

准备工作:环境搭建与依赖
在开始之前,你需要准备以下环境和工具:
- Java 开发环境 (JDK):推荐 JDK 8 或更高版本。
- 构建工具 (Maven 或 Gradle):用于管理项目依赖,本文以 Maven 为例。
- 以太坊节点接入:
- 本地节点:运行自己的以太坊客户端(如 Geth 或 Parity),但需要同步区块,资源消耗大。
- Infura 或 Alchemy 等服务:提供远程节点 API,无需同步全节点,适合开发和测试,注册后可获得节点 URL。
- MetaMask 钱包:用于管理账户、私钥,并与测试网交互。
- 测试网 ETH:在以太坊测试网(如 Ropsten, Goerli, Sepolia)上部署智能合约需要消耗 ETH,你需要从测试网水龙头获取一些测试 ETH。
核心依赖:Web3j
Web3j 是一个轻量级的、响应式的 Java 库,用于与以太坊节点进行交互,它允许你发送交易、部署智能合约、调用合约方法以及监听事件等。
在你的 Maven 项目的 pom.xml 文件中添加 Web3j 依赖:
<dependencies>
<!-- Web3j Core -->
<dependency>
<groupId>org.web3j</groupId>
<artifactId>core</artifactId>
<version>4.9.8</version> <!-- 请使用最新版本 -->
</dependency>
<!-- 其他可选依赖,如用于生成合约代码的 solidity Maven 插件 -->
<dependency>
<groupId>org.web3j</groupId>
<artifactId>solidity-maven-plugin</artifactId>
<version>0.9.16</version> <!-- 请使用最新版本 -->
</dependency>
</dependencies>
智能合约:ERC20 标准
ERC20 是以太坊上最流行的代币标准,定义了一组接口和规则,确保代币之间的互操作性,你可以:
- 编写自己的 ERC20 合约:使用 Solidity 语言编写,包含
name,symbol,decimals,totalSupply,balanceOf,transfer,transferFrom,approve,allowance等标准函数。 - 使用现成的 ERC20 合约:对于简单的代币,可以直接使用 OpenZeppelin 等库提供的经过审计的 ERC20 合约模板,这更安全可靠。
假设我们已经有一个编译好的 ERC20 合约的 ABI (Application Binary Interface) 和字节码 (Bytecode),ABI 是合约与外界交互的接口描述,字节码是部署到以太坊虚拟机 (EVM) 的代码。
使用 Java 部署 ERC20 代币合约
部署智能合约是发布代币的关键步骤,以下是使用 Web3j 部署 ERC20 合约的 Java 代码示例:
-
加载合约二进制文件:
import org.web3j.abi.ContractABI; import org.web3j.protocol.Web3j; import org.web3j.protocol.core.RemoteCall; import org.web3j.protocol.core.methods.response.TransactionReceipt; import org.web3j.protocol.http.HttpService; import org.web3j.tx.Contract; import org.web3j.tx.gas.DefaultGasProvider; import java.math.BigInteger; import java.io.IOException; import java.util.concurrent.ExecutionException; public class TokenDeployer { private static final String INFURA_URL = "https://sepolia.infura.io/v3/YOUR_INFURA_PROJECT_ID"; // 替换为你的 Infura URL private static final String PRIVATE_KEY = "YOUR_ACCOUNT_PRIVATE_KEY"; // 替换为你的部署账户私钥(测试网) private static final String WALLET_ADDRESS = "YOUR_DEPLOYMENT_ADDRESS"; // 部署账户地址 public static void main(String[] args) throws IOException, ExecutionException, InterruptedException { // 1. 初始化 Web3j 客户端 Web3j web3j = Web3j.build(new HttpService(INFURA_URL)); // 2. 加载合约的 ABI 和字节码 // 假设你已经将 ABI 和 Bytecode 分别保存到 abi.json 和 bin 文件中 String abi = ContractABI.getERC20ABI(); // 或者从文件读取: new String(Files.readAllBytes(Paths.get("path/to/your/Token.abi"))); String bytecode = "0x..." + 你的合约字节码; // 或者从文件读取: new String(Files.readAllBytes(Paths.get("path/to/your/Token.bin"))); // 3. 创建合约部署的远程调用对象 // 这里假设你的 ERC20 合约构造函数接收 name, symbol, decimals, initialSupply 参数 RemoteCall<ERC20> deployERC20 = ERC20.deploy( web3j, Credentials.create(PRIVATE_KEY), DefaultGasProvider.GAS_PRICE, DefaultGasProvider.GAS_LIMIT, bytecode, // 合约字节码 "My Java Token", // 代币名称 "MJT", // 代币符号 BigInteger.valueOf(18), // 小数位数 BigInteger.valueOf(1000000) // 初始供应量 ); // 4. 执行部署,获取合约实例 System.out.println("正在部署代币合约..."); ERC20 tokenContract = deployERC20.send(); String contractAddress = tokenContract.getContractAddress(); System.out.println("代币合约部署成功!合约地址: " + contractAddress); // 5. 可选:获取部署交易回执 TransactionReceipt transactionReceipt = tokenContract.getTransactionReceipt().get(); System.out.println("交易哈希: " + transactionReceipt.getTransactionHash()); System.out.println("区块号: " + transactionReceipt.getBlockNumber()); // 关闭 Web3j 连接 web3j.shutdown(); } }
注意:
- 安全性:切勿在生产环境或代码中硬编码私钥,应使用环境变量、配置文件或硬件钱包等方式安全管理。
- Gas:部署合约需要消耗 Gas,确保你的账户有足够的测试网 ETH。
DefaultGasProvider提供了默认的 Gas 价格和限制,你也可以根据网络状况调整。 - 合约代码:上述代码中的
ERC20是 Web3j 根据标准 ABI 生成的合约包装类,如果你使用自定义的合约,需要使用 Web3j 的SolidityFunctionWrapper或相关工具生成对应的 Java 类。
与已部署的代币合约交互
部署成功后,你可以通过 Java 代码与代币合约进行交互,例如查询代币信息、转账等。
// 假设 contractAddress 是已部署的代币合约地址
ERC20 tokenContract = ERC20.load(contractAddress, web3j, Credentials.create(PRIVATE_KEY), DefaultGasProvider.GAS_PRICE, DefaultGasProvider.GAS_LIMIT);
// 1. 查询代币名称
String tokenName = tokenContract.name().send();
System.out.println("代币名称: " + tokenName);
// 2. 查询代币符号
String tokenSymbol = tokenContract.symbol().send();
System.out.println("代币符号: " + tokenSymbol);
// 3. 查询指定地址的代币余额
String someAddress = "0x...";
BigInteger balance = tokenContract.balanceOf(someAddress).send();
System.out.println("地址 " + someAddress + " 的代币余额: " + balance);
// 4. 转账代币
String recipientAddress = "0x...";
BigInteger transferAmount = BigInteger.valueOf(100);
TransactionReceipt transferReceipt = tokenContract.transfer(recipientAddress, transferAmount).send();
System.out.println("转账成功!交易哈希: " + transferReceipt.getTransactionHash());
测试与主网部署
- 测试网部署:在将合约部署到主网之前,务必在以太坊测试网(如 Sepolia)上进行充分测试,确保合约逻辑正确,Gas 费用合理。
- 主网部署:测试无误后,你可以将
INFURA_URL切换到主网节点,使用主网账户的私钥和足够的 ETH 进行部署。**请务必再三确认私钥和网络