如何在测试网测试ERC20合约?附Solidity代码优化咨询
关于USDT存提合约测试与代码优化的问题
1. 如何使用测试USDT测试合约?
- 先给合约授权:测试账户调用测试USDT合约的
approve方法,授权合约可划转的USDT额度,数值需大于等于你要存入的金额。 - 执行存入操作:调用合约的
depositUSDT方法,传入存入数量(注意USDT是6位小数,比如存1个USDT要传1000000)。 - 验证提取逻辑:调用所有者专属的提取方法(需先优化合约代码),传入目标用户地址和提取金额,确认USDT是否成功转到所有者钱包。
2. 可在哪些环境测试?
- Remix本地模拟链(Remix VM):自己部署一个测试版USDT合约(用OpenZeppelin的ERC20模板,设置6位小数),替换原合约中的USDT地址,再调用测试USDT的
mint方法给自己发币测试。 - 公链测试网:比如Sepolia、Polygon Mumbai等,这些网络有对应测试版的USDT合约,直接部署你的合约到对应测试网即可。
- 本地私有链:用Hardhat或Foundry搭建本地测试链,部署测试USDT和你的合约,还能写自动化测试脚本批量验证逻辑。
3. 如何获取测试网USDT?
- 测试网水龙头:部分公链测试网有官方或第三方水龙头,可直接申请测试USDT。
- 自行部署测试代币:在测试网部署一个ERC20合约,设置小数为6,调用
mint给自己的测试账户发币,完全可控。 - 开发者社群互助:在web3开发者社群里找其他开发者索要少量测试USDT。
4. 合约代码优化建议
原合约未实现「所有者提取用户USDT」的核心需求,还存在冗余代码,优化后的代码如下:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract USDTManager { address public immutable owner; address public immutable usdtToken; mapping(address => uint256) public userBalances; uint256 public constant MIN_DEPOSIT = 1e6; // 对应1个USDT(6位小数) event USDTDeposited(address indexed user, uint256 amount); event USDTWithdrawnByOwner(address indexed owner, address indexed user, uint256 amount); modifier onlyOwner() { require(msg.sender == owner, "Only owner allowed"); _; } constructor(address _usdtToken) { owner = msg.sender; usdtToken = _usdtToken; require(_usdtToken != address(0), "Invalid USDT address"); } // 用户存入USDT function depositUSDT(uint256 _amount) external { require(_amount >= MIN_DEPOSIT, "Deposit amount too small"); require(IERC20(usdtToken).transferFrom(msg.sender, address(this), _amount), "Transfer failed"); userBalances[msg.sender] += _amount; emit USDTDeposited(msg.sender, _amount); } // 所有者提取指定用户的USDT到自己钱包 function withdrawUserUSDT(address _user, uint256 _amount) external onlyOwner { require(_amount > 0, "Invalid withdrawal amount"); uint256 userBalance = userBalances[_user]; require(userBalance >= _amount, "User balance insufficient"); userBalances[_user] -= _amount; require(IERC20(usdtToken).transfer(owner, _amount), "Transfer failed"); emit USDTWithdrawnByOwner(msg.sender, _user, _amount); } // 查看合约当前USDT总余额 function getContractUSDTBalance() external view returns (uint256) { return IERC20(usdtToken).balanceOf(address(this)); } }
优化点说明:
- 移除
SafeMath:Solidity 0.8.x版本内置溢出/下溢检查,无需额外引入。 - 修正核心逻辑:新增
withdrawUserUSDT方法,实现所有者提取指定用户USDT的需求。 - 使用
immutable:修饰owner和USDT地址,部署后不可修改,节省gas消耗。 - 公开状态变量:
userBalances和usdtToken设为public,方便外部查询状态。 - 调整最小存入额:USDT是6位小数,原
MIN_DEPOSIT_AMOUNT=1实际为0.000001 USDT,改为1e6对应1个USDT,更符合实际场景。 - 增加转账校验:
transferFrom和transfer返回bool值,用require确保转账成功。 - 删除无用代码:移除未使用的
fromAddressList、MAX_UINT以及ETH相关事件。 - 构造函数传参:USDT地址通过构造函数传入,避免硬编码,方便切换不同网络。
内容的提问来源于stack exchange,提问作者godisgay
相关产品推荐
相关产品推荐

