ETH Price: $1,614.97 (+1.66%)
Gas: 0.33 Gwei

Transaction Decoder

Block:
18432231 at Oct-26-2023 05:12:47 AM +UTC
Transaction Fee:
0.00134706 ETH $2.18
Gas Used:
44,902 Gas / 30 Gwei

Emitted Events:

75 GalaTreasureChestClaimFee.PaymentExecuted( refId=6539f547f2da8889f4551dbe, amount=1550740000000000, blockSigned=18432230 )

Account State Difference:

  Address   Before After State Difference Code
3.298088292267901255 Eth3.298636515768980223 Eth0.000548223501078968
0xa8c45F9B...6B4164d31
0.016132722799556782 Eth
Nonce: 356
0.013234922799556782 Eth
Nonce: 357
0.0028978
0xFD4492E7...a39b6F096 14.483197064697851 Eth14.484747804697851 Eth0.00155074

Execution Trace

ETH 0.00155074 GalaTreasureChestClaimFee.pay( refId=6539f547f2da8889f4551dbe, amount=1550740000000000, blockSigned=18432230, sig=0x9CF94958B90426F91519D8C72707FB4DC7DA854709DDFE7C9F56CF9821729E2F115FE11200FAA69FB57CFD1DF4F141CA040E62D35A572B8A64A08475EE39D0CB1B )
  • Null: 0x000...001.43a6cbee( )
  • ETH 0.00155074 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;
        }
    }