1. 区块与交易属性
solidity
function getBlockData() public view returns (
uint number,
uint timestamp,
uint gasLimit,
address miner
) {
return (
block.number, // 当前区块号
block.timestamp, // 区块时间戳(Unix秒)
block.gaslimit, // 当前区块的gas上限
block.coinbase // 矿工地址
);
}
function getTxData() public view returns (
uint gasPrice,
address origin
) {
return (
tx.gasprice, // 当前交易的gas价格
tx.origin // 原始交易发送者(慎用!)
);
}
2. 消息属性 (msg)
solidity
function processPayment() public payable {
// 获取调用信息
address sender = msg.sender;
uint value = msg.value;
bytes4 selector = msg.sig;
// 验证至少转账1 ETH
require(value >= 1 ether, "Minimum 1 ETH required");
// 记录交易
payments[sender] += value;
}
3. 地址操作
solidity
// 安全ETH转账
function sendEther(address payable to, uint amount) public {
// 检查合约余额
require(address(this).balance >= amount, "Insufficient balance");
// 使用call代替transfer/send (推荐)
(bool success, ) = to.call{value: amount}("");
require(success, "Transfer failed");
}
// 调用其他合约
function callExternalContract(
address contractAddr,
string memory funcSig,
uint param
) public {
bytes memory data = abi.encodeWithSignature(funcSig, param);
(bool success, bytes memory result) = contractAddr.call(data);
require(success, "External call failed");
// 处理返回结果...
}
// 检查合约余额
function checkBalance(address addr) public view returns (uint) {
return addr.balance; // 地址的ETH余额(wei)
}
4. ABI编码/解码
solidity
// 创建函数调用数据
function createTransferData(
address recipient,
uint amount
) public pure returns (bytes memory) {
return abi.encodeWithSignature(
"transfer(address,uint256)",
recipient,
amount
);
}
// 解析数据
function decodeData(
bytes memory data
) public pure returns (address, uint) {
(address recipient, uint amount) = abi.decode(
abi.decode(data[4:]), // 跳过函数选择器
(address, uint)
);
return (recipient, amount);
}
5. 数学与加密
solidity
// 创建唯一标识符
function createTokenId(
string memory name,
address owner
) public pure returns (bytes32) {
return keccak256(abi.encodePacked(name, owner));
}
// 签名验证
function verify(
bytes32 messageHash,
uint8 v,
bytes32 r,
bytes32 s
) public pure returns (address) {
return ecrecover(messageHash, v, r, s);
}
// 安全数学运算
function safeModAdd(
uint a,
uint b,
uint mod
) public pure returns (uint) {
return addmod(a, b, mod);
}
6. 错误处理
solidity
function withdraw(uint amount) public {
// 检查条件
require(
balances[msg.sender] >= amount,
"Insufficient balance"
);
// 更新状态
balances[msg.sender] -= amount;
// 执行转账
(bool success, ) = msg.sender.call{value: amount}("");
// 自定义错误处理
if (!success) {
revert WithdrawFailed(msg.sender, amount);
}
}
// 自定义错误类型
error WithdrawFailed(address sender, uint amount);
// 内部一致性检查
function validateState() public view {
assert(totalSupply == calculateTotalSupply());
}
7. 合约操作
solidity
// 获取合约信息
function getContractInfo() public view returns (
address contractAddress,
uint balance
) {
return (
address(this), // 当前合约地址
address(this).balance // 合约ETH余额
);
}
// 安全销毁合约
function destroyContract() public onlyOwner {
// 保存所有者地址
address owner = owner;
// 清除状态
delete owner;
// 销毁合约并发送余额
selfdestruct(payable(owner));
}
8. Gas 操作
solidity
function optimizeGas() public {
uint startGas = gasleft();
// 执行复杂操作...
for(uint i = 0; i < 100; i++) {
// 某些操作
}
uint gasUsed = startGas - gasleft();
emit GasConsumed(gasUsed);
}
9. 类型信息
solidity
// 获取接口ID (ERC-165)
function getERC721InterfaceId() public pure returns (bytes4) {
return type(IERC721).interfaceId;
}
// 检查合约支持的接口
function supportsInterface(
address contractAddr,
bytes4 interfaceId
) public view returns (bool) {
(bool success, bytes memory result) = contractAddr.staticcall(
abi.encodeWithSignature("supportsInterface(bytes4)", interfaceId)
);
return success && abi.decode(result, (bool));
}
关键实践建议
- 安全转账模式:
solidity
// 安全转账模板
function safeTransferETH(address to, uint value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, "ETH transfer failed");
}
- call vs delegatecall:
solidity
// 普通调用:在目标合约上下文中执行
contractA.call(abi.encodeWithSignature("func()"));
// 委托调用:在当前合约上下文中执行目标合约代码
contractB.delegatecall(abi.encodeWithSignature("func()"));
- 时间戳使用警告:
solidity
// 不安全的随机数生成(容易被矿工操纵)
uint badRandom = uint(keccak256(abi.encodePacked(block.timestamp)));
// 更安全的方案(但仍不完全安全)
uint betterRandom = uint(keccak256(abi.encodePacked(
block.timestamp,
block.difficulty,
msg.sender
)));
- ABI编码最佳实践:
solidity
// 安全:明确指定类型防止哈希碰撞
bytes32 safeHash = keccak256(abi.encode(
"Transfer(address,uint256)",
recipient,
amount
));
// 危险:紧密打包可能导致不同类型数据碰撞
bytes32 unsafeHash = keccak256(abi.encodePacked(
"Transfer",
recipient,
amount
));
这些全局属性和方法是 Solidity 智能合约开发的基石,正确理解和使用它们对于编写安全、高效的合约至关重要。在实际开发中,始终优先考虑安全性,特别是处理资金转账和外部调用时。