编译器
0.8.27+commit.40a35a09
文件 1 的 6:Context.sol
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;
}
}
文件 2 的 6:Errors.sol
pragma solidity =0.8.27;
library Errors {
error InvalidAddress();
error InvalidAmount();
error InvalidIndex();
error InvalidPayment();
error Unauthorized();
error PrematureExecution();
error InsufficientFunds();
error Unavailable();
}
文件 3 的 6:FeeHandler.sol
pragma solidity =0.8.27;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "contracts/lib/Errors.sol";
import "contracts/utils/SafeETHTransfer.sol";
contract FeeHandler is Ownable, ReentrancyGuard, SafeETHTransfer {
address public receiver;
event ReceiverUpdated(address receiver);
event Payment(address indexed from, uint256 value);
constructor(address _multiSig, address _receiver) Ownable(_multiSig) {
_setReceiver(_receiver);
}
function setReceiver(address _receiver) external onlyOwner {
_setReceiver(_receiver);
}
function pay() external payable nonReentrant {
if (msg.value > 0) {
_safeETHTransfer(receiver, msg.value);
emit Payment(msg.sender, msg.value);
}
}
function _setReceiver(address _receiver) private {
if (_receiver == address(0)) revert Errors.InvalidAddress();
receiver = _receiver;
emit ReceiverUpdated(_receiver);
}
}
文件 4 的 6:Ownable.sol
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
error OwnableUnauthorizedAccount(address account);
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 5 的 6:ReentrancyGuard.sol
pragma solidity ^0.8.20;
abstract contract ReentrancyGuard {
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
_status = ENTERED;
}
function _nonReentrantAfter() private {
_status = NOT_ENTERED;
}
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}
文件 6 的 6:SafeETHTransfer.sol
pragma solidity =0.8.27;
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "contracts/lib/Errors.sol";
contract SafeETHTransfer is ReentrancyGuard {
mapping(address => uint256) private _stuckETH;
error TransferFailed(address account, uint256 amount);
error NothingStuck();
event StuckETHClaimed(address indexed account, address indexed receiver, uint256 amount);
event ETHTransferFailed(address indexed account, uint256 amount);
function claimStuckETH(address _receiver) external nonReentrant {
if (_receiver == address(0)) revert Errors.InvalidAddress();
uint256 amount = _stuckETH[msg.sender];
if (amount == 0) revert NothingStuck();
_stuckETH[msg.sender] = 0;
_safeETHTransferWithRevert(_receiver, amount);
emit StuckETHClaimed(msg.sender, _receiver, amount);
}
function getStuckETHTokens(address _address) external view returns (uint256) {
if (_address == address(0)) revert Errors.InvalidAddress();
return _stuckETH[_address];
}
function _safeETHTransfer(address _account, uint256 _amount) internal {
(bool success, ) = _account.call{value: _amount}("");
if (!success) {
_stuckETH[_account] += _amount;
emit ETHTransferFailed(_account, _amount);
}
}
function _safeETHTransferWithRevert(address _account, uint256 _amount) internal {
(bool success, ) = _account.call{value: _amount}("");
if (!success) revert TransferFailed(_account, _amount);
}
}
{
"compilationTarget": {
"contracts/fee/FeeHandler.sol": "FeeHandler"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_multiSig","type":"address"},{"internalType":"address","name":"_receiver","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"NothingStuck","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ETHTransferFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Payment","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"receiver","type":"address"}],"name":"ReceiverUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StuckETHClaimed","type":"event"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"}],"name":"claimStuckETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getStuckETHTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pay","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"receiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"}],"name":"setReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]