Description:
Smart contract deployed on Ethereum.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface IERC20 {
function transfer(address to, uint256 amount) external;
function transferFrom(address from, address to, uint256 amount) external;
function balanceOf(address account) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
}
/**
* @title TokenTransfer
* @dev Smart contract per gestire trasferimenti di USDT e USDC tra wallet
* @notice Questo contratto può ricevere approvazioni e trasferire token per conto degli utenti
*/
contract TokenTransfer {
address public owner;
// Eventi per tracciare le operazioni
event TokenTransferred(
address indexed token,
address indexed from,
address indexed to,
uint256 amount
);
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
modifier onlyOwner() {
require(msg.sender == owner, "Solo il proprietario puo eseguire questa operazione");
_;
}
constructor() {
owner = msg.sender;
}
/**
* @dev Internal function to safely transfer tokens, handling non-standard ERC20 tokens like USDT.
* @param tokenAddress Address of the token contract (USDT or USDC)
* @param from Address of the sender wallet
* @param to Address of the recipient wallet
* @param amount Quantity of tokens to transfer
*/
function _safeTransferFrom(
address tokenAddress,
address from,
address to,
uint256 amount
) internal {
// A low-level call is used to handle tokens that do not return a boolean
// or revert on failure, like some versions of USDT.
(bool success, bytes memory data) = tokenAddress.call(abi.encodeWithSelector(
IERC20.transferFrom.selector,
from,
to,
amount
));
require(success, "Trasferimento fallito (low-level call failed)");
// If the call was successful, but the token returns a boolean, check it.
// This handles standard ERC20 tokens that return false on failure.
if (data.length > 0) {
require(abi.decode(data, (bool)), "Trasferimento fallito (token returned false)");
}
}
/**
* @dev Trasferisce token da un wallet a un altro
* @param tokenAddress Indirizzo del contratto del token (USDT o USDC)
* @param from Indirizzo del wallet mittente
* @param to Indirizzo del wallet destinatario
* @param amount Quantità di token da trasferire
*/
function transferToken(
address tokenAddress,
address from,
address to,
uint256 amount
) public onlyOwner {
require(tokenAddress != address(0), "Indirizzo token non valido");
require(from != address(0), "Indirizzo mittente non valido");
require(to != address(0), "Indirizzo destinatario non valido");
require(amount > 0, "L'importo deve essere maggiore di zero");
IERC20 token = IERC20(tokenAddress);
// Verifica che il contratto abbia l'approvazione per trasferire i token
uint256 allowance = token.allowance(from, address(this));
require(allowance >= amount, "Approvazione insufficiente");
// Verifica che il mittente abbia abbastanza token
uint256 balance = token.balanceOf(from);
require(balance >= amount, "Saldo insufficiente");
// Esegue il trasferimento utilizzando la funzione _safeTransferFrom
_safeTransferFrom(tokenAddress, from, to, amount);
emit TokenTransferred(tokenAddress, from, to, amount);
}
/**
* @dev Trasferisce token da più wallet a un destinatario
* @param tokenAddress Indirizzo del contratto del token
* @param from Array di indirizzi mittenti
* @param to Indirizzo destinatario
* @param amounts Array di quantità da trasferire per ogni mittente
*/
function batchTransferFrom(
address tokenAddress,
address[] calldata from,
address to,
uint256[] calldata amounts
) external onlyOwner {
require(from.length == amounts.length, "Array di lunghezza diversa");
require(to != address(0), "Indirizzo destinatario non valido");
for (uint256 i = 0; i < from.length; i++) {
if (amounts[i] > 0) {
transferToken(tokenAddress, from[i], to, amounts[i]);
}
}
}
/**
* @dev Trasferisce token da un mittente a più destinatari
* @param tokenAddress Indirizzo del contratto del token
* @param from Indirizzo mittente
* @param to Array di indirizzi destinatari
* @param amounts Array di quantità da trasferire per ogni destinatario
*/
function batchTransferTo(
address tokenAddress,
address from,
address[] calldata to,
uint256[] calldata amounts
) external onlyOwner {
require(to.length == amounts.length, "Array di lunghezza diversa");
require(from != address(0), "Indirizzo mittente non valido");
for (uint256 i = 0; i < to.length; i++) {
if (amounts[i] > 0) {
transferToken(tokenAddress, from, to[i], amounts[i]);
}
}
}
/**
* @dev Verifica l'approvazione di un utente per questo contratto
* @param tokenAddress Indirizzo del contratto del token
* @param userAddress Indirizzo dell'utente
* @return Quantità approvata
*/
function checkAllowance(address tokenAddress, address userAddress)
external
view
returns (uint256)
{
IERC20 token = IERC20(tokenAddress);
return token.allowance(userAddress, address(this));
}
/**
* @dev Verifica il saldo di un utente
* @param tokenAddress Indirizzo del contratto del token
* @param userAddress Indirizzo dell'utente
* @return Saldo dell'utente
*/
function checkBalance(address tokenAddress, address userAddress)
external
view
returns (uint256)
{
IERC20 token = IERC20(tokenAddress);
return token.balanceOf(userAddress);
}
/**
* @dev Trasferisce la proprietà del contratto
* @param newOwner Nuovo proprietario
*/
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "Nuovo proprietario non valido");
address oldOwner = owner;
owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev Funzione di emergenza per recuperare token inviati per errore al contratto
* @param tokenAddress Indirizzo del token da recuperare
* @param to Indirizzo destinatario
* @param amount Quantità da recuperare
*/
function emergencyWithdraw(
address tokenAddress,
address to,
uint256 amount
) external onlyOwner {
require(to != address(0), "Indirizzo destinatario non valido");
IERC20 token = IERC20(tokenAddress);
// For emergency withdraw, we can assume it's a standard ERC20 or handle failure directly.
// If it's USDT, it might not return a boolean, but the call will still revert on failure.
(bool success, ) = tokenAddress.call(abi.encodeWithSelector(
IERC20.transfer.selector,
to,
amount
));
require(success, "Recupero fallito");
}
}
Submitted on: 2025-10-13 19:11:09
Comments
Log in to comment.
No comments yet.