FeeGateway

Description:

Multi-signature wallet contract requiring multiple confirmations for transaction execution.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

/**
 * @title FeeGateway
 * @dev Tollbooth for collecting fees on a SHADOW Agent user journey.
 * Fees are transferred immediately to the SHADOW treasury. 
 */
contract FeeGateway is Ownable {
    address public immutable TREASURY = 0x73e8CB7362045572Aa525817429ceC092a06Be94;

    mapping(uint256 => uint256) public fees; // chainId => fee in wei

    event FeePaid(address indexed user, uint256 chainId, uint256 amount, bytes32 nonce);

    constructor() Ownable(msg.sender) {
        // ETH Mainnet (1): 0.003 ETH
        fees[1] = 0.003 ether;
        // Base Mainnet (8453): 0.003 ETH
        fees[8453] = 0.003 ether;
        // BSC Mainnet (56): 0.01 BNB
        fees[56] = 0.01 ether;
    }

    /**
     * @dev Pay the chain-specific fee and receive a pass (nonce) for downstream operations.
     * Immediately transfers the full msg.value to treasury.
     * @param user - The agent's address.
     * @param nonce - A unique nonce for this pass.
     */
    function payAndPass(address user, bytes32 nonce) external payable {
        uint256 chain = block.chainid;
        uint256 requiredFee = fees[chain];
        require(msg.value >= requiredFee, "Insufficient fee");
        require(nonce != bytes32(0), "Invalid nonce");

        // Immediately transfer full amount to treasury
        payable(TREASURY).transfer(msg.value);

        emit FeePaid(user, chain, msg.value, nonce);
    }

    /**
     * @dev Rescue stuck ETH.
     */
    function rescue() external onlyOwner {
        payable(owner()).transfer(address(this).balance);
    }

    receive() external payable {}
}

Tags:
Multisig, Multi-Signature, Factory|addr:0x08db140854aab90463f6b61eb6f346c29bfb02ea|verified:true|block:23685587|tx:0x7532d093f9d118c5d8592b71235641bcdeeae3ec095dbb74f790b9cf2d9db75f|first_check:1761820159

Submitted on: 2025-10-30 11:29:22

Comments

Log in to comment.

No comments yet.