Transaction Hash:
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 | ||
---|---|---|---|---|---|
0x1f9090aa...8e676c326
Miner
| 3.298088292267901255 Eth | 3.298636515768980223 Eth | 0.000548223501078968 | ||
0xa8c45F9B...6B4164d31 |
0.016132722799556782 Eth
Nonce: 356
|
0.013234922799556782 Eth
Nonce: 357
| 0.0028978 | ||
0xFD4492E7...a39b6F096 | 14.483197064697851 Eth | 14.484747804697851 Eth | 0.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; } }