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.0;
interface IERC20 {
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
}
contract PaymentProcessor {
address public owner;
// Supported tokens mapping
mapping(address => bool) public supportedTokens;
mapping(address => uint256) public tokenBalances; // Track contract's token balances
// Events
event PaymentReceived(address indexed from, uint256 amount, bytes32 paymentId, string currency);
event TokenAdded(address indexed token, string symbol);
event TokenRemoved(address indexed token);
event Withdrawn(address indexed token, uint256 amount, string currency);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
// Modifiers
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
constructor() {
owner = msg.sender;
}
// Receive ETH
receive() external payable {
// Allow direct ETH transfers
}
// Pay with ETH
function payWithETH(bytes32 paymentId) external payable {
require(!processedPayments[paymentId], "Payment already processed");
require(msg.value > 0, "No ETH sent");
processedPayments[paymentId] = true;
emit PaymentReceived(msg.sender, msg.value, paymentId, "ETH");
}
// Pay with any supported ERC20 token
function payWithToken(address token, uint256 amount, bytes32 paymentId) external {
require(!processedPayments[paymentId], "Payment already processed");
require(amount > 0, "No tokens sent");
require(supportedTokens[token], "Token not supported");
// Track balance before transfer
uint256 balanceBefore = IERC20(token).balanceOf(address(this));
// Transfer tokens from user to contract
require(IERC20(token).transferFrom(msg.sender, address(this), amount), "Transfer failed");
// Verify the transfer actually happened
uint256 balanceAfter = IERC20(token).balanceOf(address(this));
require(balanceAfter >= balanceBefore + amount, "Insufficient tokens received");
// Update tracked balance
tokenBalances[token] += amount;
processedPayments[paymentId] = true;
emit PaymentReceived(msg.sender, amount, paymentId, getTokenSymbol(token));
}
// Add a new token for payments
function addToken(address token, string memory symbol) external onlyOwner {
require(token != address(0), "Invalid token address");
require(!supportedTokens[token], "Token already supported");
supportedTokens[token] = true;
emit TokenAdded(token, symbol);
}
// Remove a token
function removeToken(address token) external onlyOwner {
require(supportedTokens[token], "Token not supported");
supportedTokens[token] = false;
emit TokenRemoved(token);
}
// Withdraw ETH
function withdrawETH(uint256 amount) external onlyOwner {
require(amount <= address(this).balance, "Insufficient ETH balance");
require(amount > 0, "Amount must be greater than 0");
payable(owner).transfer(amount);
emit Withdrawn(address(0), amount, "ETH");
}
// Withdraw ERC20 tokens
function withdrawToken(address token, uint256 amount) external onlyOwner {
require(supportedTokens[token], "Token not supported");
require(amount <= tokenBalances[token], "Insufficient token balance");
require(amount > 0, "Amount must be greater than 0");
tokenBalances[token] -= amount;
require(IERC20(token).transfer(owner, amount), "Transfer failed");
emit Withdrawn(token, amount, getTokenSymbol(token));
}
// Withdraw all ETH
function withdrawAllETH() external onlyOwner {
uint256 balance = address(this).balance;
if (balance > 0) {
payable(owner).transfer(balance);
emit Withdrawn(address(0), balance, "ETH");
}
}
// Withdraw all of a specific token
function withdrawAllToken(address token) external onlyOwner {
require(supportedTokens[token], "Token not supported");
uint256 balance = tokenBalances[token];
if (balance > 0) {
tokenBalances[token] = 0;
require(IERC20(token).transfer(owner, balance), "Transfer failed");
emit Withdrawn(token, balance, getTokenSymbol(token));
}
}
// Check if token is supported
function isTokenSupported(address token) external view returns (bool) {
return supportedTokens[token];
}
// Transfer ownership
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "New owner cannot be zero address");
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
// Emergency function to recover any ERC20 tokens sent to contract accidentally
function emergencyWithdraw(address token, uint256 amount) external onlyOwner {
require(token != address(0), "Invalid token");
require(IERC20(token).transfer(owner, amount), "Transfer failed");
emit Withdrawn(token, amount, "EMERGENCY");
}
// Internal function to get token symbol (simplified)
function getTokenSymbol(address token) internal pure returns (string memory) {
if (token == address(0)) return "ETH";
// You can extend this to map specific token addresses to symbols
// For now, return generic "TOKEN"
return "TOKEN";
}
// Track processed payments
mapping(bytes32 => bool) private processedPayments;
}
Submitted on: 2025-09-22 18:24:06
Comments
Log in to comment.
No comments yet.