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 {}
}
Submitted on: 2025-10-30 11:29:22
Comments
Log in to comment.
No comments yet.