ETH Price: $1,903.02 (-0.44%)

Transaction Decoder

Block:
16753939 at Mar-04-2023 08:37:47 AM +UTC
Transaction Fee:
0.00134706 ETH $2.56
Gas Used:
44,902 Gas / 30 Gwei

Emitted Events:

5 GalaTreasureChestClaimFee.PaymentExecuted( refId=640303511fe0eb07700cb4f7, amount=1227650000000000, blockSigned=16753938 )

Account State Difference:

  Address   Before After State Difference Code
0.060738189149550868 Eth0.061234226578546834 Eth0.000496037428995966
0xc5aa18A9...Fb0356cAb
0.030091790842153126 Eth
Nonce: 36
0.027517080842153126 Eth
Nonce: 37
0.00257471
0xFD4492E7...a39b6F096 4.352735680288005593 Eth4.353963330288005593 Eth0.00122765

Execution Trace

ETH 0.00122765 GalaTreasureChestClaimFee.pay( refId=640303511fe0eb07700cb4f7, amount=1227650000000000, blockSigned=16753938, sig=0xB8B767B9C6C8F249F2DDA765F2B7A11DF9DE9C89CA23A06C2DF793AA78EC7CE85AE219E56EE120277BF7CE2F35E7A85299FED6CA1B367D250A35C65AF57A26561C )
  • Null: 0x000...001.02fd0610( )
  • ETH 0.00122765 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;
        }
    }