以下代码展示了如何在ImToken中安全地与智能合约交互,涵盖授权、Gas费优化和交易确认等关键环节。代码基于Web3.js库,适用于以太坊网络。
初始化Web3连接
const Web3 = require('web3');
const web3 = new Web3(window.ethereum); // 使用ImToken注入的provider
// 检查网络ID确保连接正确网络
const checkNetwork = async () => {
const chainId = await web3.eth.getChainId();
if (chainId !== 1) throw new Error('请切换到以太坊主网');
};
安全授权ERC20代币
const approveToken = async (tokenAddress, spenderAddress, amount) => {
const tokenContract = new web3.eth.Contract(
[
{
constant: false,
inputs: [
{ name: "_spender", type: "address" },
{ name: "_value", type: "uint256" }
],
name: "approve",
outputs: [{ name: "", type: "bool" }],
type: "function"
}
],
tokenAddress
);
// 建议授权特定数量而非无限授权
const tx = tokenContract.methods.approve(
spenderAddress,
web3.utils.toWei(amount.toString(), 'ether')
);
// 添加Gas费缓冲(20%)
const gasEstimate = await tx.estimateGas({ from: window.ethereum.selectedAddress });
const gasPrice = await web3.eth.getGasPrice();
return tx.send({
from: window.ethereum.selectedAddress,
gas: Math.floor(gasEstimate * 1.2),
gasPrice: Math.floor(gasPrice * 1.1) // 10%溢价确保快速确认
});
};
带验证的合约调用
const safeContractCall = async (contractABI, contractAddress, methodName, params) => {
const contract = new web3.eth.Contract(contractABI, contractAddress);
// 验证合约是否已开源
const code = await web3.eth.getCode(contractAddress);
if (code === '0x') throw new Error('目标地址不是合约');
// 模拟调用预览结果
const result = await contract.methods[methodName](...params).call();
console.log('模拟调用结果:', result);
// 正式交易
return contract.methods[methodName](...params).send({
from: window.ethereum.selectedAddress
});
};
Gas费优化工具函数
const getOptimalGas = async () => {
const gasNow = await fetch('https://www.gasnow.org/api/v3/gas/price');
const { fast, rapid } = await gasNow.json();
// 根据网络状态选择建议值
return {
standard: fast,
fast: Math.min(rapid, fast * 1.3) // 限制最高溢价30%
};
};
关键安全实践
授权检查
调用approveToken()时应验证:
- 代币合约地址是否官方验证
- 授权金额是否精确匹配需求
- 授权目标地址是否可信
交易确认
所有交易应包含以下检查:
const verifyTx = async (txHash) => {
const receipt = await web3.eth.getTransactionReceipt(txHash);
if (!receipt.status) throw new Error('交易执行失败');
// 检查事件日志
const events = receipt.logs.map(log => web3.eth.abi.decodeLog(
contractABI,
log.data,
log.topics.slice(1)
));
return { receipt, events };
};
风险提示
- 避免在代码中硬编码私钥
- 所有用户输入需进行地址格式校验
- 关键操作前建议弹出二次确认对话框
以上代码需配合ImToken的DApp浏览器使用,实际部署时应添加更多错误处理和用户提示。建议配合Etherscan API实现合约验证功能,并定期检查授权状态。