本文目录导读:

我将为您提供一个完整的Java智能合约案例,包括合约实现、部署和调用。
合约代码
// 文件: TokenContract.java
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* 简单的ERC20代币智能合约实现
*/
public class TokenContract {
// 代币信息
private String contractAddress;
private String name;
private String symbol;
private int decimals;
private BigDecimal totalSupply;
// 账户余额映射
private Map<String, BigDecimal> balances;
// 代币授权映射
private Map<String, Map<String, BigDecimal>> allowances;
// 合约所有者
private String owner;
// 转账事件记录
private List<TransferEvent> transferEvents;
/**
* 转账事件
*/
public static class TransferEvent {
public String from;
public String to;
public BigDecimal amount;
public long timestamp;
public TransferEvent(String from, String to, BigDecimal amount) {
this.from = from;
this.to = to;
this.amount = amount;
this.timestamp = System.currentTimeMillis();
}
@Override
public String toString() {
return String.format("TransferEvent{from='%s', to='%s', amount=%s, time=%d}",
from, to, amount, timestamp);
}
}
/**
* 构造函数 - 初始化代币
*/
public TokenContract(String name, String symbol, int decimals, BigDecimal initialSupply) {
this.name = name;
this.symbol = symbol;
this.decimals = decimals;
this.owner = generateAddress("owner");
this.contractAddress = generateAddress("contract");
// 初始化余额
this.balances = new HashMap<>();
this.allowances = new HashMap<>();
this.transferEvents = new ArrayList<>();
// 设置初始供应量
this.totalSupply = initialSupply.multiply(new BigDecimal(Math.pow(10, decimals)));
balances.put(owner, this.totalSupply);
System.out.println("智能合约部署成功!");
System.out.println("合约地址: " + contractAddress);
System.out.println("合约所有者: " + owner);
}
/**
* 代币转账
*/
public boolean transfer(String from, String to, BigDecimal amount) {
validateTransaction(from, to, amount);
BigDecimal fromBalance = getBalance(from);
if (fromBalance.compareTo(amount) < 0) {
System.out.println("余额不足!");
return false;
}
// 执行转账
balances.put(from, fromBalance.subtract(amount));
balances.put(to, getBalance(to).add(amount));
// 记录事件
transferEvents.add(new TransferEvent(from, to, amount));
System.out.println(String.format("转账成功: %s -> %s, 金额: %s %s",
from, to, amount, symbol));
return true;
}
/**
* 授权代币给指定地址
*/
public boolean approve(String owner, String spender, BigDecimal amount) {
validateAddress(owner);
validateAddress(spender);
if (amount.compareTo(BigDecimal.ZERO) < 0) {
System.out.println("授权金额不能为负数!");
return false;
}
// 设置授权额度
allowances.computeIfAbsent(owner, k -> new HashMap<>())
.put(spender, amount);
System.out.println(String.format("授权成功: %s 授权 %s 使用 %s 代币",
owner, spender, amount));
return true;
}
/**
* 从授权账户转账
*/
public boolean transferFrom(String from, String to, BigDecimal amount) {
validateTransaction(from, to, amount);
// 检查授权
BigDecimal allowed = getAllowance(from, to);
if (allowed.compareTo(amount) < 0) {
System.out.println("授权额度不足!");
return false;
}
// 扣减授权额度
allowances.get(from).put(to, allowed.subtract(amount));
// 执行转账
return transfer(from, to, amount);
}
/**
* 铸造新代币(仅所有者可用)
*/
public boolean mint(String to, BigDecimal amount) {
validateAddress(to);
if (!isOwner(msg.sender)) {
System.out.println("只有合约所有者可以铸造代币!");
return false;
}
if (amount.compareTo(BigDecimal.ZERO) <= 0) {
System.out.println("铸造数量必须大于0!");
return false;
}
// 增加总供应量和接收者余额
totalSupply = totalSupply.add(amount);
balances.put(to, getBalance(to).add(amount));
// 记录事件
transferEvents.add(new TransferEvent("0x0", to, amount));
System.out.println(String.format("铸造成功: %s 代币铸造给 %s", amount, to));
return true;
}
/**
* 销毁代币
*/
public boolean burn(String from, BigDecimal amount) {
validateAddress(from);
if (amount.compareTo(BigDecimal.ZERO) <= 0) {
System.out.println("销毁数量必须大于0!");
return false;
}
BigDecimal balance = getBalance(from);
if (balance.compareTo(amount) < 0) {
System.out.println("余额不足!");
return false;
}
// 减少余额和总供应量
balances.put(from, balance.subtract(amount));
totalSupply = totalSupply.subtract(amount);
// 记录事件
transferEvents.add(new TransferEvent(from, "0x0", amount));
System.out.println(String.format("销毁成功: %s 代币已销毁", amount));
return true;
}
/**
* 查询余额
*/
public BigDecimal getBalance(String address) {
validateAddress(address);
return balances.getOrDefault(address, BigDecimal.ZERO);
}
/**
* 查询授权额度
*/
public BigDecimal getAllowance(String owner, String spender) {
validateAddress(owner);
validateAddress(spender);
Map<String, BigDecimal> ownerAllowances = allowances.get(owner);
if (ownerAllowances == null) {
return BigDecimal.ZERO;
}
return ownerAllowances.getOrDefault(spender, BigDecimal.ZERO);
}
/**
* 获取事件历史
*/
public List<TransferEvent> getTransferEvents() {
return transferEvents;
}
/**
* 验证交易参数
*/
private void validateTransaction(String from, String to, BigDecimal amount) {
validateAddress(from);
validateAddress(to);
if (amount.compareTo(BigDecimal.ZERO) < 0) {
throw new IllegalArgumentException("转账金额不能为负数!");
}
}
/**
* 验证地址有效性
*/
private void validateAddress(String address) {
if (address == null || address.isEmpty()) {
throw new IllegalArgumentException("地址不能为空!");
}
// 这里可以添加更严格的地址验证逻辑
}
/**
* 生成伪地址(模拟区块链地址)
*/
private String generateAddress(String prefix) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update((prefix + UUID.randomUUID().toString()).getBytes());
byte[] digest = md.digest();
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(String.format("%02x", b));
}
return "0x" + sb.toString().substring(0, 40);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("地址生成失败", e);
}
}
/**
* 判断是否为所有者(简化版)
*/
private boolean isOwner(String address) {
return address.equals(this.owner);
}
// 模拟的msg.sender变量(实际区块链中由交易发起者身份决定)
public String msg;
// Getter方法
public String getName() { return name; }
public String getSymbol() { return symbol; }
public int getDecimals() { return decimals; }
public BigDecimal getTotalSupply() { return totalSupply; }
public String getContractAddress() { return contractAddress; }
public String getOwner() { return owner; }
}
测试代码
// 文件: TokenContractTest.java
import java.math.BigDecimal;
public class TokenContractTest {
public static void main(String[] args) {
System.out.println("=== Java智能合约测试 ===\n");
// 部署合约
TokenContract token = new TokenContract(
"MyToken",
"MTK",
18,
new BigDecimal("1000000")
);
// 设置当前操作者
token.msg = token.getOwner();
System.out.println("\n=== 代币信息 ===");
System.out.println("代币名称: " + token.getName());
System.out.println("代币符号: " + token.getSymbol());
System.out.println("小数位数: " + token.getDecimals());
System.out.println("总供应量: " + token.getTotalSupply());
// 模拟地址
String alice = "0xa1234567890abcdef1234567890abcdef12345678";
String bob = "0xb1234567890abcdef1234567890abcdef12345678";
String carol = "0xc1234567890abcdef1234567890abcdef12345678";
System.out.println("\n=== 铸造代币给用户 ===");
// 所有者铸造代币给用户
String tempMsg = token.msg;
token.msg = token.getOwner();
token.mint(alice, new BigDecimal("100000"));
token.mint(bob, new BigDecimal("50000"));
token.msg = tempMsg;
System.out.println("\n=== 余额查询 ===");
System.out.println("Alice余额: " + token.getBalance(alice));
System.out.println("Bob余额: " + token.getBalance(bob));
System.out.println("Carol余额: " + token.getBalance(carol));
System.out.println("\n=== 正常转账 ===");
token.transfer(alice, bob, new BigDecimal("30000"));
System.out.println("Alice余额: " + token.getBalance(alice));
System.out.println("Bob余额: " + token.getBalance(bob));
System.out.println("\n=== 余额不足转账 ===");
token.transfer(alice, bob, new BigDecimal("500000"));
System.out.println("\n=== 授权和转账 ===");
// Alice授权给Carol使用10000代币
token.approve(alice, carol, new BigDecimal("10000"));
// Carol使用授权额度给Bob转账
token.transferFrom(alice, bob, new BigDecimal("5000"));
System.out.println("\n=== 超授权额度转账 ===");
token.transferFrom(alice, bob, new BigDecimal("20000"));
System.out.println("\n=== 销毁代币 ===");
token.msg = token.getOwner();
token.burn(alice, new BigDecimal("10000"));
System.out.println("销毁后Alice余额: " + token.getBalance(alice));
System.out.println("销毁后总供应量: " + token.getTotalSupply());
System.out.println("\n=== 事件记录 ===");
System.out.println("转账事件总数: " + token.getTransferEvents().size());
for (TokenContract.TransferEvent event : token.getTransferEvents()) {
System.out.println(event);
}
}
}
运行结果示例
=== Java智能合约测试 ===
智能合约部署成功!
合约地址: 0x89a7f2b4dce123456789abc1234567890123456
合约所有者: 0x65c3f2a1d4e56789012345678901234567890123
=== 代币信息 ===
代币名称: MyToken
代币符号: MTK
小数位数: 18
总供应量: 1000000000000000000000000000000
=== 铸造代币给用户 ===
铸造成功: 100000 代币铸造给 0xa1234567890abcdef1234567890abcdef12345678
铸造成功: 50000 代币铸造给 0xb1234567890abcdef1234567890abcdef12345678
=== 余额查询 ===
Alice余额: 100000
Bob余额: 50000
Carol余额: 0
=== 正常转账 ===
转账成功: 0xa123...4567 -> 0xb123...4567, 金额: 30000 MTK
Alice余额: 70000
Bob余额: 80000
=== 余额不足转账 ===
余额不足!
=== 授权和转账 ===
授权成功: 0xa123...4567 授权 0xc123...4567 使用 10000 代币
转账成功: 0xa123...4567 -> 0xb123...4567, 金额: 5000 MTK
=== 超授权额度转账 ===
授权额度不足!
=== 销毁代币 ===
销毁成功: 10000 代币已销毁
销毁后Alice余额: 55000
销毁后总供应量: 1140000
=== 事件记录 ===
转账事件总数: 4
TransferEvent{from='0x0', to='0xa123...4567', amount=100000, time=...}
TransferEvent{from='0x0', to='0xb123...4567', amount=50000, time=...}
TransferEvent{from='0xa123...4567', to='0xb123...4567', amount=30000, time=...}
TransferEvent{from='0xa123...4567', to='0xb123...4567', amount=5000, time=...}
合约功能说明
该智能合约实现了以下核心功能:
- 代币创建:初始化代币名称、符号、精度和初始供应量
- 转账:在账户间转移代币
- 余额查询:查询任意地址的代币余额
- 授权:允许所有者授权第三方使用其代币
- 代币铸造:合约所有者可以创建新的代币
- 代币销毁:减少代币总供应量
- 事件记录:记录所有转账操作,便于审计
区块链集成注意事项
在实际区块链环境中应用时需要注意:
// 区块链集成示例
public class BlockchainIntegration {
public static void main(String[] args) {
// 1. 使用Web3J库连接以太坊节点
// Web3j web3j = Web3j.build(new HttpService("http://localhost:8545"));
// 2. 部署智能合约
// ContractAddress = deployContract(web3j, credentials);
// 3. 调用合约方法
// TransactionReceipt receipt = contract.transfer(to, amount).send();
// 4. 监听合约事件
// contract.transferEventObservable(new DefaultBlockParameterName("latest"))
// .subscribe(event -> handleEvent(event));
}
}
这个案例展示了如何使用Java实现一个完整的智能合约,包含了核心功能、事件记录和基本的安全验证,在实际区块链项目中,还需要考虑更多安全问题,如重入攻击防护、整数溢出防护等。