ETH Price: $2,178.70 (+3.63%)

Transaction Decoder

Block:
18096768 at Sep-09-2023 05:30:59 AM +UTC
Transaction Fee:
0.000751174047269912 ETH $1.64
Gas Used:
85,816 Gas / 8.753309957 Gwei

Emitted Events:

169 War3.Transfer( from=0x0000000000000000000000000000000000000000, to=[Sender] 0xce48ecfaae76dd93aa8de3eed853ab18ba2aafe2, value=2447710778494413100148086502 )

Account State Difference:

  Address   Before After State Difference Code
0x36d7aA5c...9Ba7689B8
(Fee Recipient: 0xa8...377)
6.742235981758521874 Eth6.742240272558521874 Eth0.0000042908
0xcE48ECFa...8ba2aafe2
0.002986514121066 Eth
Nonce: 30
0.002235340073796088 Eth
Nonce: 31
0.000751174047269912

Execution Trace

War3.claim( messageHash=A494FBB86ABA0D343C6F918DD2EDC240FD8CF00F4A41E6DD859915F80BEC9983, signature=0x5B8E733BA0A839C42ED760D07CB3DDE18CA3501FF202A60B76BB35D7B38394117D49771A625D39D1CD55F6A1213D7A5C7CEA9A85522032542B14B9D63B4717781B )
  • Null: 0x000...001.79d748fe( )
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.13;
    import "openzeppelin/token/ERC20/ERC20.sol";
    import "solady/src/utils/ECDSA.sol";
    import "solmate/auth/Owned.sol";
    // You didn't listen, so we chose violence 
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒▒▓▓▓▓▓▒▓▓▓▓▓▓▒▒▒▒▓▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒▓▓▓▓▓▓▒▒▒▓▒▓▒█▓▓▓▓▒▒▒▒▒▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓▒▓▓▓▓▒▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▓▒▓▓▓▓█▓▓▓▓█▓▓▓▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▓█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▓█▓█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██████▓██▓▓▓▓▓▓▓▓▓▓▓▓█▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒██████▓███▓▓▓▓▓▓▓███████▓▓▓▓▓█▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓█████▓█████▓▓▓▓▓████▓▓▓▓▓▓▓▓▓▓▓██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒█████▓███████████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█████▓▓▓▓▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░▒▒▒▒░░░░░░░░░░░░▓███████████████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓████▓▓▓█████████▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░▓▒░▒▒░░░░░░░░░░░▓████████████▓▓▓▓▓▓▓▓▓▓▓███▓▓▓▓▓▓▓▓▓▓▓▓███▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░▒▓▓▒▓░░░░░░░░░░░▓███████████▓▓▓▓▓▓▓▓▓▓███▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓█▓▓▓▒▒▒▒▒▒▒█▓▒▓█▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░▓▒▒▒░░░░░░░░░░░▒▓▓▓▓██████▓▓▓▓▓▓█▓██▓▓▓▓▒▒▒░░░▒▓█▒▒▓▓▓▓▓▓▓████████▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░▓▒▒▒░░░▒░░░░░░░░░░░▓███▓▓▓▓▓▓▓▓▓█████▓▓▓▓▓█████▓▓▓▓▓▓███▓███████▓█▓██▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░▒▓▒▒▒▓▓▒▓░░░░░░░░░▒███▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓███▓███▓█▓▓▓▓▓▓█████████▓▓▓▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░▒▓▒▓▒▓▓░░░░░░░░░░████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓███████████▓█▓▓▓▓▓▓████▓▓▓▓█▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░▓▓▓▒█░░░░░░░░░░░████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██████████▓▓▓▓▓█████████▓▓▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░▓▓▓▓▓▓░░░░░░░░░▒████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░▓▓▓▓▓▓░░░░░░░░████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓█▓█▓███████▓▓▓▓█▓▓▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░▒▓▓▓▓▓▓░░░░░░▓████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██████▓▓▓████▓▓▓▓█▓▓▓█▓▓▓▓▓▓█▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░▒▓▓▓▓▒▓░░░░░▓████▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓█▓▓▓▓▒▒▒▓▒▒▒▓▒▒▒▓░░░▓░░░▒░░▓░▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▓▓▒▒▓░░░░▓████▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓█▓░░▓░▒▒▓▒▒▒▓▒▒▒▓▒▒▒▓▒▒▒▓▒▒▓▓▓▓▓▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▓▓▓▓▒▓▓▒░████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██▓▓▓▓▓░░░▓░░░▓░░░▓░░░▓░░░▒▒▓▓▓▓▓▓░░░░░▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▓▒▓▓▓▒▓▒▓████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██▓▓█▓▒▒▓░░░▓░░░▓░▒▒▓▒▒▓█▓▓▓▓▓▒░░░░░▒░░▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▓▒▓▒▒▓▓▓▒▓▒▓█████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓████████████████████████▓▒░░░░░░░▓░░░░▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░▒▓▒▓▓▒▒▓▒▒▓▓▒▒▓▓▒▓█████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██████████▓▓▓▓▓▓▓▓▒░░░░░░░░▓▒░░░░░▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░▓▒▒▓▒▒▒▓▒▒▓▓▒▒▓█▒▒▓▓░░▓██████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒░░░░░░░░░▓▒▒░░░░░▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░▓▓▓▓▒▒▒▒▓▒▒▓▓▓▓▓█░▓▓▓▓██████████████████▓▓▓▓▓▓▓▓▓▓▓▓▓█████▓▒░░░░░░░░░░░░▓▓▒▒▒▒▒▒▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░▓▓▓▓▓▓▓▓▒▓▓▓▓▓▓▓▓▓█████▓▓▓▓▓▓▓▓▓▓▓▓███████████████▓▓▓▓▓▓▓▓▓▒░░░░░░░░░░░░░█▓▓▓▒▒░▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░▒░░░░░▓▓▓█▓▓█▓▓███▓██▓▓▓▓▓▓▓▒▒▓▒▒▒▓▓▓▓▓▒▓▓▓▓▓▒▓▓▒▓▓▒▒▒▓▓▓▒▒▒░░░░░░░░░░░░█▓▓▒░▒▒░▓░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▓▓▓▓▒▓██▓▓▓▒▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▓▓▓▓▒▓▓▓▓▒▒▒▓▓▓▓▓▒▒▓▒▒▒▒░░░░░░░░░░█▓▒░▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▒▒▒▓▓▓▓▒▒▒░░▒▓▓▓▓▓▒▓▓▒▓▓▓▓▓▓▒▓▒▒▒▒▒▒▒▓▓▓▓▒▒▓▓▓▓▒▓▒▒▒▒▓▒░░░░░░░░▒▓▓▒░▒▒▒▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▓░▓▒▒▒▒░░░░▒▓▓▓▓▓▓▓▒▓▓▒▓▒▒▓▒▒▒▒▒▓▓▓▓▓▓▓▓▒▓▒▓▒▓▓▓▓▓▒▒▓▒░░░░░░░▓▒▒▓░░▒▒▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░▒▓▒▒▒▒▓▒░▒▒▓▓▓░▒▒░░▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▓▒▓▒▒▒▒▓▓▓▓▓▓▓▓▓▒▒▒▓▓▒▒▒▒▓░░░░░░░▓▒▒▓▓░░░▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░▓▒▓▒░░░▓▒▒▓▒░▒▒░░▓▓▓▓▒▓▓▓▓▓▓▓▒▒▒▒▒▒▒▓▓▒▒▒▓▓▓▒▓▓▒▓▓▓▒▒▓▓▓▓▒▒▒▓░░░░░▓▓▓▓▓▓▒▒▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▓▓▒▒▒░░░░▒▓▓▓▓▓█▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓▒▓▒▓▒▒▓▒▓▓▓▓▓▒▒▓▓▓▓▓▓▒▓▒▒▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓██▓▓▓▒▒▓▓▓▓▓▒▒▒▓█▓▓▓▓▓▓▓▓▓▓▒▓▒▓▓▓▓▓▓▓▓▓▒▓▓▒▒▒▒▓▓▓▓▓▓▒▒▒███▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓████▓▓▓▓▓▓▓▓▒▒▒▓█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓███▓▓▓▓▓▓▓▓▓▓▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓█████▓▓▓▓▓▓▓▓▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓█▓▓▓▓▓▓▒▒▓█▓▓▓▓▓▓▓███▓▓▓▓▓▓▓▓▓▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓████▓█▓▓▓▓▓▓▒▒▒▓█▓▓▓▓▓▓▓▓▓▓▓▓▓▓███▓▓█▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓███▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓████▓▓▓▓▓▓▓▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓▓▓▓▓▓▓███▓▓▓▓▓█████▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▓███▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓▓▒▓▓▒▒▓▒▓▓▓▓▓▓▒▒▒▒▒▒▓▓▓▓███████▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓██▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓▓▓▓▓▓▓▒▓▓▒▒█▓▒▒▒▒▒▒▓▓▓▒▓▒▓▓████▓▓▓▓▓▒▒▒▒▒░░░▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▓▓█▓▓▓▓▓▓▓▓▓▓██▓█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓█░░░▒█▓▓▓▓▓▓▒▒▒▒▒░░░▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓███▓▓▓▓▓█▓▓▓█▓▓▓▓▓▓▓▓▓▓▓▒▒▒▓▓▓▒▓▓▓▓▓▓▒▓▓▓▒▓▒▓▓░░░░▒▓███▓▓▓▒▓▒░▒▒░▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒▒▒▒░░▓▓▓▓▓█▓▓▓▓▓▓▓▓▓▒▓▓▓▓▒▒▓▓▒▒▓▓▓▓▒▓▓▓▓▓▓▓▒░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓████▓▓▓▓▓▓▓▓▓▒▓▓▓▓▓▒▒▒▒█▓▓▒▒▓▒▓▓▓▒▓▓▓▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓████▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░█▓▒▓▒▒▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▒▒███▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░▓██▓▓▓▓█▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▓░███▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓█████▓▓▓▓▓▓▓▓▓█▓▓▒▒▒▓░███▓▓▓▓▓█▓▓▓▓██▓▓▓▓▒▒▒▒▒▒▒▒▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓███▓▓▓▓▓▓▓▓▒▒▒▒▒▓▓▒▓▒░▓██▓▓▓▓▓▓█▓▓█▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▓▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ▒▒▒▒▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓███▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▓▓░░▓███▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
    // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░░▓████▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▓▓▒▓███▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
    // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓█████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▓▓▒█████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
    // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒███████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒███████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
    // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒███████▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
    // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒░░▓▓▒▒▒▓▓▓▓▒▒▒▒▒▒▒▒▒▒░░░░░░▒▒▒▒▒░░▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
    // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▓▓▓▒▒░░░▒▒▒▒░░░░▒▓▓▒▒▓▓▓▓▓▓▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
    // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▒▒▓▒▒▒▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
    // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
    // ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
    contract War3 is ERC20, Owned { 
        using ECDSA for bytes32;
        address public signerAddress;
        address public lpAddress;
        uint public maxSupply = 1000000000000000e18;
        bool public claimFinished;
        mapping(address => bool) public hasClaimed;
        constructor(address _signerAddress) ERC20("Web War 3", "WAR3") Owned(msg.sender) {
            signerAddress = _signerAddress;
        }
        
        function claim(
            bytes32 messageHash,
            bytes calldata signature
        ) external {
            require(!claimFinished, "Claim is finished!");
            require(!hasClaimed[msg.sender], "Already claimed!");
            require(
                hashMessage(
                    msg.sender,
                    address(this),
                    bytes4(abi.encodePacked("claim"))
                ) == messageHash, "Wrong message hash!"
            );
            require(verifyAddressSigner(messageHash, signature), "Invalid address signer");
            uint claimAmount = maxSupply * 20 / 100 / 81709;
            hasClaimed[msg.sender] = true;
            _mint(msg.sender, claimAmount);
        }
        function mintRemaining() external onlyOwner {
            uint remainder = maxSupply * 80 / 100;
            require(remainder + totalSupply() <= maxSupply);
            _mint(msg.sender, remainder);
        }
        function endClaim() external onlyOwner {
            claimFinished = true;
        }
        function setLPAddress(address _lpAddress) external onlyOwner {
            lpAddress = _lpAddress;
        }
        function transferFromLP(address to, uint256 amount) external onlyOwner {
            _transfer(lpAddress, to, amount);
        }
        function verifyAddressSigner(bytes32 messageHash, bytes calldata signature) private view returns (bool) {
            address recovery = messageHash.toEthSignedMessageHash().recover(signature);
            return signerAddress == recovery;
        }
        function hashMessage(address sender, address thisContract, bytes4 functionNameSig) public pure returns (bytes32) {
            return keccak256(abi.encodePacked(sender, thisContract, functionNameSig));
        }
    }
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)
    pragma solidity ^0.8.0;
    import "./IERC20.sol";
    import "./extensions/IERC20Metadata.sol";
    import "../../utils/Context.sol";
    /**
     * @dev Implementation of the {IERC20} interface.
     *
     * This implementation is agnostic to the way tokens are created. This means
     * that a supply mechanism has to be added in a derived contract using {_mint}.
     * For a generic mechanism see {ERC20PresetMinterPauser}.
     *
     * TIP: For a detailed writeup see our guide
     * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
     * to implement supply mechanisms].
     *
     * The default value of {decimals} is 18. To change this, you should override
     * this function so it returns a different value.
     *
     * We have followed general OpenZeppelin Contracts guidelines: functions revert
     * instead returning `false` on failure. This behavior is nonetheless
     * conventional and does not conflict with the expectations of ERC20
     * applications.
     *
     * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
     * This allows applications to reconstruct the allowance for all accounts just
     * by listening to said events. Other implementations of the EIP may not emit
     * these events, as it isn't required by the specification.
     *
     * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
     * functions have been added to mitigate the well-known issues around setting
     * allowances. See {IERC20-approve}.
     */
    contract ERC20 is Context, IERC20, IERC20Metadata {
        mapping(address => uint256) private _balances;
        mapping(address => mapping(address => uint256)) private _allowances;
        uint256 private _totalSupply;
        string private _name;
        string private _symbol;
        /**
         * @dev Sets the values for {name} and {symbol}.
         *
         * All two of these values are immutable: they can only be set once during
         * construction.
         */
        constructor(string memory name_, string memory symbol_) {
            _name = name_;
            _symbol = symbol_;
        }
        /**
         * @dev Returns the name of the token.
         */
        function name() public view virtual override returns (string memory) {
            return _name;
        }
        /**
         * @dev Returns the symbol of the token, usually a shorter version of the
         * name.
         */
        function symbol() public view virtual override returns (string memory) {
            return _symbol;
        }
        /**
         * @dev Returns the number of decimals used to get its user representation.
         * For example, if `decimals` equals `2`, a balance of `505` tokens should
         * be displayed to a user as `5.05` (`505 / 10 ** 2`).
         *
         * Tokens usually opt for a value of 18, imitating the relationship between
         * Ether and Wei. This is the default value returned by this function, unless
         * it's overridden.
         *
         * NOTE: This information is only used for _display_ purposes: it in
         * no way affects any of the arithmetic of the contract, including
         * {IERC20-balanceOf} and {IERC20-transfer}.
         */
        function decimals() public view virtual override returns (uint8) {
            return 18;
        }
        /**
         * @dev See {IERC20-totalSupply}.
         */
        function totalSupply() public view virtual override returns (uint256) {
            return _totalSupply;
        }
        /**
         * @dev See {IERC20-balanceOf}.
         */
        function balanceOf(address account) public view virtual override returns (uint256) {
            return _balances[account];
        }
        /**
         * @dev See {IERC20-transfer}.
         *
         * Requirements:
         *
         * - `to` cannot be the zero address.
         * - the caller must have a balance of at least `amount`.
         */
        function transfer(address to, uint256 amount) public virtual override returns (bool) {
            address owner = _msgSender();
            _transfer(owner, to, amount);
            return true;
        }
        /**
         * @dev See {IERC20-allowance}.
         */
        function allowance(address owner, address spender) public view virtual override returns (uint256) {
            return _allowances[owner][spender];
        }
        /**
         * @dev See {IERC20-approve}.
         *
         * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
         * `transferFrom`. This is semantically equivalent to an infinite approval.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         */
        function approve(address spender, uint256 amount) public virtual override returns (bool) {
            address owner = _msgSender();
            _approve(owner, spender, amount);
            return true;
        }
        /**
         * @dev See {IERC20-transferFrom}.
         *
         * Emits an {Approval} event indicating the updated allowance. This is not
         * required by the EIP. See the note at the beginning of {ERC20}.
         *
         * NOTE: Does not update the allowance if the current allowance
         * is the maximum `uint256`.
         *
         * Requirements:
         *
         * - `from` and `to` cannot be the zero address.
         * - `from` must have a balance of at least `amount`.
         * - the caller must have allowance for ``from``'s tokens of at least
         * `amount`.
         */
        function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
            address spender = _msgSender();
            _spendAllowance(from, spender, amount);
            _transfer(from, to, amount);
            return true;
        }
        /**
         * @dev Atomically increases the allowance granted to `spender` by the caller.
         *
         * This is an alternative to {approve} that can be used as a mitigation for
         * problems described in {IERC20-approve}.
         *
         * Emits an {Approval} event indicating the updated allowance.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         */
        function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
            address owner = _msgSender();
            _approve(owner, spender, allowance(owner, spender) + addedValue);
            return true;
        }
        /**
         * @dev Atomically decreases the allowance granted to `spender` by the caller.
         *
         * This is an alternative to {approve} that can be used as a mitigation for
         * problems described in {IERC20-approve}.
         *
         * Emits an {Approval} event indicating the updated allowance.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         * - `spender` must have allowance for the caller of at least
         * `subtractedValue`.
         */
        function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
            address owner = _msgSender();
            uint256 currentAllowance = allowance(owner, spender);
            require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
            unchecked {
                _approve(owner, spender, currentAllowance - subtractedValue);
            }
            return true;
        }
        /**
         * @dev Moves `amount` of tokens from `from` to `to`.
         *
         * This internal function is equivalent to {transfer}, and can be used to
         * e.g. implement automatic token fees, slashing mechanisms, etc.
         *
         * Emits a {Transfer} event.
         *
         * Requirements:
         *
         * - `from` cannot be the zero address.
         * - `to` cannot be the zero address.
         * - `from` must have a balance of at least `amount`.
         */
        function _transfer(address from, address to, uint256 amount) internal virtual {
            require(from != address(0), "ERC20: transfer from the zero address");
            require(to != address(0), "ERC20: transfer to the zero address");
            _beforeTokenTransfer(from, to, amount);
            uint256 fromBalance = _balances[from];
            require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
            unchecked {
                _balances[from] = fromBalance - amount;
                // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
                // decrementing then incrementing.
                _balances[to] += amount;
            }
            emit Transfer(from, to, amount);
            _afterTokenTransfer(from, to, amount);
        }
        /** @dev Creates `amount` tokens and assigns them to `account`, increasing
         * the total supply.
         *
         * Emits a {Transfer} event with `from` set to the zero address.
         *
         * Requirements:
         *
         * - `account` cannot be the zero address.
         */
        function _mint(address account, uint256 amount) internal virtual {
            require(account != address(0), "ERC20: mint to the zero address");
            _beforeTokenTransfer(address(0), account, amount);
            _totalSupply += amount;
            unchecked {
                // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
                _balances[account] += amount;
            }
            emit Transfer(address(0), account, amount);
            _afterTokenTransfer(address(0), account, amount);
        }
        /**
         * @dev Destroys `amount` tokens from `account`, reducing the
         * total supply.
         *
         * Emits a {Transfer} event with `to` set to the zero address.
         *
         * Requirements:
         *
         * - `account` cannot be the zero address.
         * - `account` must have at least `amount` tokens.
         */
        function _burn(address account, uint256 amount) internal virtual {
            require(account != address(0), "ERC20: burn from the zero address");
            _beforeTokenTransfer(account, address(0), amount);
            uint256 accountBalance = _balances[account];
            require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
            unchecked {
                _balances[account] = accountBalance - amount;
                // Overflow not possible: amount <= accountBalance <= totalSupply.
                _totalSupply -= amount;
            }
            emit Transfer(account, address(0), amount);
            _afterTokenTransfer(account, address(0), amount);
        }
        /**
         * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
         *
         * This internal function is equivalent to `approve`, and can be used to
         * e.g. set automatic allowances for certain subsystems, etc.
         *
         * Emits an {Approval} event.
         *
         * Requirements:
         *
         * - `owner` cannot be the zero address.
         * - `spender` cannot be the zero address.
         */
        function _approve(address owner, address spender, uint256 amount) internal virtual {
            require(owner != address(0), "ERC20: approve from the zero address");
            require(spender != address(0), "ERC20: approve to the zero address");
            _allowances[owner][spender] = amount;
            emit Approval(owner, spender, amount);
        }
        /**
         * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
         *
         * Does not update the allowance amount in case of infinite allowance.
         * Revert if not enough allowance is available.
         *
         * Might emit an {Approval} event.
         */
        function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
            uint256 currentAllowance = allowance(owner, spender);
            if (currentAllowance != type(uint256).max) {
                require(currentAllowance >= amount, "ERC20: insufficient allowance");
                unchecked {
                    _approve(owner, spender, currentAllowance - amount);
                }
            }
        }
        /**
         * @dev Hook that is called before any transfer of tokens. This includes
         * minting and burning.
         *
         * Calling conditions:
         *
         * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
         * will be transferred to `to`.
         * - when `from` is zero, `amount` tokens will be minted for `to`.
         * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
         * - `from` and `to` are never both zero.
         *
         * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
         */
        function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
        /**
         * @dev Hook that is called after any transfer of tokens. This includes
         * minting and burning.
         *
         * Calling conditions:
         *
         * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
         * has been transferred to `to`.
         * - when `from` is zero, `amount` tokens have been minted for `to`.
         * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
         * - `from` and `to` are never both zero.
         *
         * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
         */
        function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
    }
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.4;
    /// @notice Gas optimized ECDSA wrapper.
    /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol)
    /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol)
    /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol)
    ///
    /// WARNING! Do NOT use signatures as unique identifiers.
    /// Please use EIP712 with a nonce included in the digest to prevent replay attacks.
    /// This implementation does NOT check if a signature is non-malleable.
    library ECDSA {
        /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
        /*                        CUSTOM ERRORS                       */
        /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
        /// @dev The signature is invalid.
        error InvalidSignature();
        /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
        /*                    RECOVERY OPERATIONS                     */
        /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
        // Note: as of Solady version 0.0.68, these functions will
        // revert upon recovery failure for more safety by default.
        /// @dev Recovers the signer's address from a message digest `hash`,
        /// and the `signature`.
        ///
        /// This function does NOT accept EIP-2098 short form signatures.
        /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098
        /// short form signatures instead.
        function recover(bytes32 hash, bytes memory signature) internal view returns (address result) {
            /// @solidity memory-safe-assembly
            assembly {
                let m := mload(0x40) // Cache the free memory pointer.
                let signatureLength := mload(signature)
                mstore(0x00, hash)
                mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                mstore(0x40, mload(add(signature, 0x20))) // `r`.
                mstore(0x60, mload(add(signature, 0x40))) // `s`.
                result :=
                    mload(
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            eq(signatureLength, 65), // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x01, // Start of output.
                            0x20 // Size of output.
                        )
                    )
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                if iszero(returndatasize()) {
                    mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                    revert(0x1c, 0x04)
                }
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.
            }
        }
        /// @dev Recovers the signer's address from a message digest `hash`,
        /// and the `signature`.
        ///
        /// This function does NOT accept EIP-2098 short form signatures.
        /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098
        /// short form signatures instead.
        function recoverCalldata(bytes32 hash, bytes calldata signature)
            internal
            view
            returns (address result)
        {
            /// @solidity memory-safe-assembly
            assembly {
                let m := mload(0x40) // Cache the free memory pointer.
                mstore(0x00, hash)
                mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
                calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
                result :=
                    mload(
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            eq(signature.length, 65), // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x01, // Start of output.
                            0x20 // Size of output.
                        )
                    )
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                if iszero(returndatasize()) {
                    mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                    revert(0x1c, 0x04)
                }
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.
            }
        }
        /// @dev Recovers the signer's address from a message digest `hash`,
        /// and the EIP-2098 short form signature defined by `r` and `vs`.
        ///
        /// This function only accepts EIP-2098 short form signatures.
        /// See: https://eips.ethereum.org/EIPS/eip-2098
        function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) {
            /// @solidity memory-safe-assembly
            assembly {
                let m := mload(0x40) // Cache the free memory pointer.
                mstore(0x00, hash)
                mstore(0x20, add(shr(255, vs), 27)) // `v`.
                mstore(0x40, r)
                mstore(0x60, shr(1, shl(1, vs))) // `s`.
                result :=
                    mload(
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            1, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x01, // Start of output.
                            0x20 // Size of output.
                        )
                    )
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                if iszero(returndatasize()) {
                    mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                    revert(0x1c, 0x04)
                }
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.
            }
        }
        /// @dev Recovers the signer's address from a message digest `hash`,
        /// and the signature defined by `v`, `r`, `s`.
        function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
            internal
            view
            returns (address result)
        {
            /// @solidity memory-safe-assembly
            assembly {
                let m := mload(0x40) // Cache the free memory pointer.
                mstore(0x00, hash)
                mstore(0x20, and(v, 0xff))
                mstore(0x40, r)
                mstore(0x60, s)
                result :=
                    mload(
                        staticcall(
                            gas(), // Amount of gas left for the transaction.
                            1, // Address of `ecrecover`.
                            0x00, // Start of input.
                            0x80, // Size of input.
                            0x01, // Start of output.
                            0x20 // Size of output.
                        )
                    )
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                if iszero(returndatasize()) {
                    mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
                    revert(0x1c, 0x04)
                }
                mstore(0x60, 0) // Restore the zero slot.
                mstore(0x40, m) // Restore the free memory pointer.
            }
        }
        /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
        /*                   TRY-RECOVER OPERATIONS                   */
        /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
        // WARNING!
        // These functions will NOT revert upon recovery failure.
        // Instead, they will return the zero address upon recovery failure.
        // It is critical that the returned address is NEVER compared against
        // a zero address (e.g. an uninitialized address variable).
        /// @dev Recovers the signer's address from a message digest `hash`,
        /// and the `signature`.
        ///
        /// This function does NOT accept EIP-2098 short form signatures.
        /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098
        /// short form signatures instead.
        function tryRecover(bytes32 hash, bytes memory signature)
            internal
            view
            returns (address result)
        {
            /// @solidity memory-safe-assembly
            assembly {
                let m := mload(0x40) // Cache the free memory pointer.
                let signatureLength := mload(signature)
                mstore(0x00, hash)
                mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
                mstore(0x40, mload(add(signature, 0x20))) // `r`.
                mstore(0x60, mload(add(signature, 0x40))) // `s`.
                pop(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        eq(signatureLength, 65), // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x40, // Start of output.
                        0x20 // Size of output.
                    )
                )
                mstore(0x60, 0) // Restore the zero slot.
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                result := mload(xor(0x60, returndatasize()))
                mstore(0x40, m) // Restore the free memory pointer.
            }
        }
        /// @dev Recovers the signer's address from a message digest `hash`,
        /// and the `signature`.
        ///
        /// This function does NOT accept EIP-2098 short form signatures.
        /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098
        /// short form signatures instead.
        function tryRecoverCalldata(bytes32 hash, bytes calldata signature)
            internal
            view
            returns (address result)
        {
            /// @solidity memory-safe-assembly
            assembly {
                let m := mload(0x40) // Cache the free memory pointer.
                mstore(0x00, hash)
                mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
                calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
                pop(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        eq(signature.length, 65), // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x40, // Start of output.
                        0x20 // Size of output.
                    )
                )
                mstore(0x60, 0) // Restore the zero slot.
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                result := mload(xor(0x60, returndatasize()))
                mstore(0x40, m) // Restore the free memory pointer.
            }
        }
        /// @dev Recovers the signer's address from a message digest `hash`,
        /// and the EIP-2098 short form signature defined by `r` and `vs`.
        ///
        /// This function only accepts EIP-2098 short form signatures.
        /// See: https://eips.ethereum.org/EIPS/eip-2098
        function tryRecover(bytes32 hash, bytes32 r, bytes32 vs)
            internal
            view
            returns (address result)
        {
            /// @solidity memory-safe-assembly
            assembly {
                let m := mload(0x40) // Cache the free memory pointer.
                mstore(0x00, hash)
                mstore(0x20, add(shr(255, vs), 27)) // `v`.
                mstore(0x40, r)
                mstore(0x60, shr(1, shl(1, vs))) // `s`.
                pop(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        1, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x40, // Start of output.
                        0x20 // Size of output.
                    )
                )
                mstore(0x60, 0) // Restore the zero slot.
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                result := mload(xor(0x60, returndatasize()))
                mstore(0x40, m) // Restore the free memory pointer.
            }
        }
        /// @dev Recovers the signer's address from a message digest `hash`,
        /// and the signature defined by `v`, `r`, `s`.
        function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
            internal
            view
            returns (address result)
        {
            /// @solidity memory-safe-assembly
            assembly {
                let m := mload(0x40) // Cache the free memory pointer.
                mstore(0x00, hash)
                mstore(0x20, and(v, 0xff))
                mstore(0x40, r)
                mstore(0x60, s)
                pop(
                    staticcall(
                        gas(), // Amount of gas left for the transaction.
                        1, // Address of `ecrecover`.
                        0x00, // Start of input.
                        0x80, // Size of input.
                        0x40, // Start of output.
                        0x20 // Size of output.
                    )
                )
                mstore(0x60, 0) // Restore the zero slot.
                // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
                result := mload(xor(0x60, returndatasize()))
                mstore(0x40, m) // Restore the free memory pointer.
            }
        }
        /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
        /*                     HASHING OPERATIONS                     */
        /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
        /// @dev Returns an Ethereum Signed Message, created from a `hash`.
        /// This produces a hash corresponding to the one signed with the
        /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
        /// JSON-RPC method as part of EIP-191.
        function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {
            /// @solidity memory-safe-assembly
            assembly {
                mstore(0x20, hash) // Store into scratch space for keccak256.
                mstore(0x00, "\\x00\\x00\\x00\\x00\\x19Ethereum Signed Message:\
    32") // 28 bytes.
                result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.
            }
        }
        /// @dev Returns an Ethereum Signed Message, created from `s`.
        /// This produces a hash corresponding to the one signed with the
        /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)
        /// JSON-RPC method as part of EIP-191.
        /// Note: Supports lengths of `s` up to 999999 bytes.
        function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
            /// @solidity memory-safe-assembly
            assembly {
                let sLength := mload(s)
                let o := 0x20
                mstore(o, "\\x19Ethereum Signed Message:\
    ") // 26 bytes, zero-right-padded.
                mstore(0x00, 0x00)
                // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.
                for { let temp := sLength } 1 {} {
                    o := sub(o, 1)
                    mstore8(o, add(48, mod(temp, 10)))
                    temp := div(temp, 10)
                    if iszero(temp) { break }
                }
                let n := sub(0x3a, o) // Header length: `26 + 32 - o`.
                // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.
                returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))
                mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.
                result := keccak256(add(s, sub(0x20, n)), add(n, sLength))
                mstore(s, sLength) // Restore the length.
            }
        }
        /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
        /*                   EMPTY CALLDATA HELPERS                   */
        /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
        /// @dev Returns an empty calldata bytes.
        function emptySignature() internal pure returns (bytes calldata signature) {
            /// @solidity memory-safe-assembly
            assembly {
                signature.length := 0
            }
        }
    }
    // SPDX-License-Identifier: AGPL-3.0-only
    pragma solidity >=0.8.0;
    /// @notice Simple single owner authorization mixin.
    /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
    abstract contract Owned {
        /*//////////////////////////////////////////////////////////////
                                     EVENTS
        //////////////////////////////////////////////////////////////*/
        event OwnershipTransferred(address indexed user, address indexed newOwner);
        /*//////////////////////////////////////////////////////////////
                                OWNERSHIP STORAGE
        //////////////////////////////////////////////////////////////*/
        address public owner;
        modifier onlyOwner() virtual {
            require(msg.sender == owner, "UNAUTHORIZED");
            _;
        }
        /*//////////////////////////////////////////////////////////////
                                   CONSTRUCTOR
        //////////////////////////////////////////////////////////////*/
        constructor(address _owner) {
            owner = _owner;
            emit OwnershipTransferred(address(0), _owner);
        }
        /*//////////////////////////////////////////////////////////////
                                 OWNERSHIP LOGIC
        //////////////////////////////////////////////////////////////*/
        function transferOwnership(address newOwner) public virtual onlyOwner {
            owner = newOwner;
            emit OwnershipTransferred(msg.sender, newOwner);
        }
    }
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
    pragma solidity ^0.8.0;
    /**
     * @dev Interface of the ERC20 standard as defined in the EIP.
     */
    interface IERC20 {
        /**
         * @dev Emitted when `value` tokens are moved from one account (`from`) to
         * another (`to`).
         *
         * Note that `value` may be zero.
         */
        event Transfer(address indexed from, address indexed to, uint256 value);
        /**
         * @dev Emitted when the allowance of a `spender` for an `owner` is set by
         * a call to {approve}. `value` is the new allowance.
         */
        event Approval(address indexed owner, address indexed spender, uint256 value);
        /**
         * @dev Returns the amount of tokens in existence.
         */
        function totalSupply() external view returns (uint256);
        /**
         * @dev Returns the amount of tokens owned by `account`.
         */
        function balanceOf(address account) external view returns (uint256);
        /**
         * @dev Moves `amount` tokens from the caller's account to `to`.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a {Transfer} event.
         */
        function transfer(address to, uint256 amount) external returns (bool);
        /**
         * @dev Returns the remaining number of tokens that `spender` will be
         * allowed to spend on behalf of `owner` through {transferFrom}. This is
         * zero by default.
         *
         * This value changes when {approve} or {transferFrom} are called.
         */
        function allowance(address owner, address spender) external view returns (uint256);
        /**
         * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * IMPORTANT: Beware that changing an allowance with this method brings the risk
         * that someone may use both the old and the new allowance by unfortunate
         * transaction ordering. One possible solution to mitigate this race
         * condition is to first reduce the spender's allowance to 0 and set the
         * desired value afterwards:
         * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
         *
         * Emits an {Approval} event.
         */
        function approve(address spender, uint256 amount) external returns (bool);
        /**
         * @dev Moves `amount` tokens from `from` to `to` using the
         * allowance mechanism. `amount` is then deducted from the caller's
         * allowance.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a {Transfer} event.
         */
        function transferFrom(address from, address to, uint256 amount) external returns (bool);
    }
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
    pragma solidity ^0.8.0;
    import "../IERC20.sol";
    /**
     * @dev Interface for the optional metadata functions from the ERC20 standard.
     *
     * _Available since v4.1._
     */
    interface IERC20Metadata is IERC20 {
        /**
         * @dev Returns the name of the token.
         */
        function name() external view returns (string memory);
        /**
         * @dev Returns the symbol of the token.
         */
        function symbol() external view returns (string memory);
        /**
         * @dev Returns the decimals places of the token.
         */
        function decimals() external view returns (uint8);
    }
    // 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;
        }
    }