pragma solidity 0.8.25;
import {IERC20SendAndCallReceiver} from "../interfaces/IERC20SendAndCallReceiver.sol";
import {SafeERC20TransferFrom} from "../utils/SafeERC20TransferFrom.sol";
import {SafeERC20} from "@openzeppelin/contracts@5.0.2/token/ERC20/utils/SafeERC20.sol";
import {IERC20} from "@openzeppelin/contracts@5.0.2/token/ERC20/IERC20.sol";
import {Context} from "@openzeppelin/contracts@5.0.2/utils/Context.sol";
/**
* THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.
* DO NOT USE THIS CODE IN PRODUCTION.
*/
/**
* @notice This is mock implementation of {receiveTokens} to be used in tests.
* This contract DOES NOT provide a mechanism for accessing the tokens transfered to it.
* Real implementations must ensure that tokens are properly handled and not incorrectly locked.
*/
contract MockERC20SendAndCallReceiver is Context, IERC20SendAndCallReceiver {
using SafeERC20 for IERC20;
mapping(bytes32 blockchainID => mapping(address senderAddress => bool blocked)) public
blockedSenders;
/**
* @dev Emitted when receiveTokens is called.
*/
event TokensReceived(
bytes32 indexed sourceBlockchainID,
address indexed originTokenTransferrerAddress,
address indexed originSenderAddress,
address token,
uint256 amount,
bytes payload
);
/**
* @dev See {IERC20SendAndCallReceiver-receiveTokens}
*/
function receiveTokens(
bytes32 sourceBlockchainID,
address originTokenTransferrerAddress,
address originSenderAddress,
address token,
uint256 amount,
bytes calldata payload
) external {
require(
!blockedSenders[sourceBlockchainID][originSenderAddress],
"MockERC20SendAndCallReceiver: sender blocked"
);
emit TokensReceived({
sourceBlockchainID: sourceBlockchainID,
originTokenTransferrerAddress: originTokenTransferrerAddress,
originSenderAddress: originSenderAddress,
token: token,
amount: amount,
payload: payload
});
require(payload.length > 0, "MockERC20SendAndCallReceiver: empty payload");
SafeERC20TransferFrom.safeTransferFrom(IERC20(token), _msgSender(), amount);
}
/**
* @notice Block a sender from sending tokens to this contract.
* @param blockchainID The blockchain ID of the sender.
* @param senderAddress The address of the sender.
*/
function blockSender(bytes32 blockchainID, address senderAddress) external {
blockedSenders[blockchainID][senderAddress] = true;
}
}