PaymentProcessor

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;

}

Tags:
addr:0x38a1d88dba11132b2353fd2bbc0f1c316528564a|verified:true|block:23419619|tx:0xec0e57bac08070c86a1c6d48816bc123f69413cfc1410b093c240420168d533e|first_check:1758558246

Submitted on: 2025-09-22 18:24:06

Comments

Log in to comment.

No comments yet.