Transaction Hash:
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 | ||
---|---|---|---|---|---|
0xBaF6dC2E...Cd66C5e19
Miner
| (MEV Builder: 0xBaF...e19) | 3.630141572428228394 Eth | 3.631458874649136824 Eth | 0.00131730222090843 | |
0xF26eCF25...A9fb7E902 |
0.008334165 Eth
Nonce: 25
|
0.005219095655863988 Eth
Nonce: 26
| 0.003115069344136012 | ||
0xFD4492E7...a39b6F096 | 5.71903145607268109 Eth | 5.72015645607268109 Eth | 0.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; } }