ETH Price: $2,255.58 (+0.56%)

Transaction Decoder

Block:
17532156 at Jun-22-2023 02:19:59 AM +UTC
Transaction Fee:
0.001990069344136012 ETH $4.49
Gas Used:
44,914 Gas / 44.308441558 Gwei

Emitted Events:

84 GalaTreasureChestClaimFee.PaymentExecuted( refId=6493afc69bdcf64224a1f59e, amount=1125000000000000, blockSigned=17532155 )

Account State Difference:

  Address   Before After State Difference Code
(MEV Builder: 0xBaF...e19)
3.630141572428228394 Eth3.631458874649136824 Eth0.00131730222090843
0xF26eCF25...A9fb7E902
0.008334165 Eth
Nonce: 25
0.005219095655863988 Eth
Nonce: 26
0.003115069344136012
0xFD4492E7...a39b6F096 5.71903145607268109 Eth5.72015645607268109 Eth0.001125

Execution Trace

ETH 0.001125 GalaTreasureChestClaimFee.pay( refId=6493afc69bdcf64224a1f59e, amount=1125000000000000, blockSigned=17532155, sig=0xE8B4AE83B1922097BEAA42D2EF572DEABB2C0369D5FB3038B7E2314470A7B9496D8CCB75F7A1B077BA9DB97F8E04C48D9A257AED16151DFB8D1DF27079189F271C )
  • Null: 0x000...001.144167ce( )
  • ETH 0.001125 0xfd4492e70df97a6155c6d244f5ec5b5a39b6f096.CALL( )
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.9;
    import './MessageValidator.sol';
    contract GalaTreasureChestClaimFee is MessageValidator {
        event PaymentExecuted(string refId, uint256 amount, uint256 blockSigned);
        constructor(address _signer) {
            setSignerAddress(_signer);
        }
        function pay(
            string memory refId,
            uint256 amount,
            uint256 blockSigned,
            bytes memory sig
        )
            public
            payable
            isValidMessage(refId, amount, blockSigned, sig, msg.value)
        {
            payable(address(signerAddress)).transfer(msg.value);
            emit PaymentExecuted(refId, msg.value, blockSigned);
        }
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.9;
    import '@openzeppelin/contracts/access/Ownable.sol';
    contract MessageValidator is Ownable {
        address public signerAddress;
        uint256 public blockMaxThreshold = 10;
        function setSignerAddress(address _signer) public onlyOwner {
            signerAddress = _signer;
        }
        modifier isValidMessage(
            string memory refId,
            uint256 amount,
            uint256 blockSigned,
            bytes memory sig,
            uint256 value
        ) {
            bytes32 message = keccak256(
                abi.encodePacked(refId, amount, blockSigned)
            );
            require(
                recoverSigner(message, sig) == signerAddress,
                'Invalid signature'
            );
            require(
                (block.number - blockSigned) <= blockMaxThreshold,
                'Signature expired'
            );
            require(value >= amount, 'Invalid amount');
            _;
        }
        function recoverSigner(bytes32 message, bytes memory sig)
            internal
            pure
            returns (address)
        {
            uint8 v;
            bytes32 r;
            bytes32 s;
            (v, r, s) = splitSignature(sig);
            return ecrecover(message, v, r, s);
        }
        function splitSignature(bytes memory sig)
            internal
            pure
            returns (
                uint8,
                bytes32,
                bytes32
            )
        {
            require(sig.length == 65, 'Signature must be 65 bytes long');
            bytes32 r;
            bytes32 s;
            uint8 v;
            assembly {
                // first 32 bytes, after the length prefix
                r := mload(add(sig, 32))
                // second 32 bytes
                s := mload(add(sig, 64))
                // final byte (first byte of the next 32 bytes)
                v := byte(0, mload(add(sig, 96)))
            }
            return (v, r, s);
        }
        function setBlockMaxThreshold(uint256 _blockThreshold) public onlyOwner {
            blockMaxThreshold = _blockThreshold;
        }
    }
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)
    pragma solidity ^0.8.0;
    import "../utils/Context.sol";
    /**
     * @dev Contract module which provides a basic access control mechanism, where
     * there is an account (an owner) that can be granted exclusive access to
     * specific functions.
     *
     * By default, the owner account will be the one that deploys the contract. This
     * can later be changed with {transferOwnership}.
     *
     * This module is used through inheritance. It will make available the modifier
     * `onlyOwner`, which can be applied to your functions to restrict their use to
     * the owner.
     */
    abstract contract Ownable is Context {
        address private _owner;
        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
        /**
         * @dev Initializes the contract setting the deployer as the initial owner.
         */
        constructor() {
            _transferOwnership(_msgSender());
        }
        /**
         * @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 {
            require(owner() == _msgSender(), "Ownable: caller is not the owner");
        }
        /**
         * @dev Leaves the contract without owner. It will not be possible to call
         * `onlyOwner` functions anymore. Can only be called by the current owner.
         *
         * NOTE: Renouncing ownership will leave the contract without an owner,
         * thereby removing 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 {
            require(newOwner != address(0), "Ownable: new owner is the zero address");
            _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);
        }
    }
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
    pragma solidity ^0.8.0;
    /**
     * @dev Provides information about the current execution context, including the
     * sender of the transaction and its data. While these are generally available
     * via msg.sender and msg.data, they should not be accessed in such a direct
     * manner, since when dealing with meta-transactions the account sending and
     * paying for execution may not be the actual sender (as far as an application
     * is concerned).
     *
     * This contract is only required for intermediate, library-like contracts.
     */
    abstract contract Context {
        function _msgSender() internal view virtual returns (address) {
            return msg.sender;
        }
        function _msgData() internal view virtual returns (bytes calldata) {
            return msg.data;
        }
    }