Forkchoice Ethereum Mainnet

Address Contract Partially Verified

Address 0x259C2FF4e10e7e2B31A2045c93eD8513299c8E04
Balance 0 ETH
Nonce 1
Code Size 6982 bytes
Indexed Transactions 0 (1 on-chain, 1.7% indexed)
External Etherscan · Sourcify

Contract Bytecode

6982 bytes
Copy Bytecode
0x608060405234801561001057600080fd5b50600436106101425760003560e01c806398764d83116100b8578063b8c1db401161007c578063b8c1db401461036b578063d9197c321461037e578063ef7df66b14610387578063f2bc9e051461039a578063f2fde38b146103ad578063f8939e0c146103c057600080fd5b806398764d8314610278578063a4d1776d1461029b578063a5e7f9ea146102a4578063a6a2ee02146102ce578063ae3d5414146102e157600080fd5b80633bb624c21161010a5780633bb624c2146101fb578063582abd121461020e578063715018a614610239578063788cb4d9146102415780637b58c4bd146102545780638da5cb5b1461026757600080fd5b80630e58f7c314610147578063150b7a02146101885780631ecaef43146101c057806329a86c52146101d55780632ce8939a146101e8575b600080fd5b6101756101553660046114a0565b600090815260086020526040902054600160281b900464ffffffffff1690565b6040519081526020015b60405180910390f35b6101a7610196366004611516565b630a85bd0160e11b95945050505050565b6040516001600160e01b0319909116815260200161017f565b6101d36101ce366004611634565b6103d3565b005b6101d36101e336600461168f565b6104a5565b6101756101f63660046114a0565b6104cf565b6101d36102093660046114a0565b6104f0565b600554610221906001600160a01b031681565b6040516001600160a01b03909116815260200161017f565b6101d36104fd565b600254610221906001600160a01b031681565b6101d36102623660046116f5565b610511565b6000546001600160a01b0316610221565b61028b610286366004611760565b6105cf565b60405161017f94939291906117e3565b61017560065481565b6101756102b23660046114a0565b600090815260086020526040902054600160501b900460ff1690565b6101d36102dc366004611890565b61085d565b6103316102ef3660046114a0565b60086020526000908152604090205464ffffffffff80821691600160281b810490911690600160501b810460ff1690600160581b90046001600160a01b031684565b6040805164ffffffffff958616815294909316602085015260ff909116918301919091526001600160a01b0316606082015260800161017f565b600354610221906001600160a01b031681565b61017560045481565b6101d36103953660046114a0565b61087c565b6101d36103a836600461168f565b610889565b6101d36103bb36600461168f565b6108b3565b6101d36103ce3660046118cc565b61092c565b6103db610a9a565b6004548164ffffffffff1611156104315760405162461bcd60e51b8152602060048201526015602482015274109bdc99195c88191bd95cc81b9bdd08195e1a5cdd605a1b60448201526064015b60405180910390fd5b60005b82518110156104a05781600860008584815181106104545761045461198f565b6020026020010151815260200190815260200160002060000160056101000a81548164ffffffffff021916908364ffffffffff1602179055508080610498906119bb565b915050610434565b505050565b6104ad610a9a565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b600781815481106104df57600080fd5b600091825260209091200154905081565b6104f8610a9a565b600655565b610505610a9a565b61050f6000610af4565b565b610519610b44565b8281146105685760405162461bcd60e51b815260206004820152601e60248201527f417272617973206d757374206265207468652073616d65206c656e67746800006044820152606401610428565b60005b838110156105bf576105ad8585838181106105885761058861198f565b905060200201358484848181106105a1576105a161198f565b90506020020135610b9d565b806105b7816119bb565b91505061056b565b506105c960018055565b50505050565b60608080806000856001600160401b038111156105ee576105ee611584565b604051908082528060200260200182016040528015610617578160200160208202803683370190505b5090506000866001600160401b0381111561063457610634611584565b60405190808252806020026020018201604052801561065d578160200160208202803683370190505b5090506000876001600160401b0381111561067a5761067a611584565b6040519080825280602002602001820160405280156106a3578160200160208202803683370190505b5090506000886001600160401b038111156106c0576106c0611584565b6040519080825280602002602001820160405280156106e9578160200160208202803683370190505b50905060005b8981101561084c576000600860008d8d8581811061070f5761070f61198f565b602090810292909201358352508181019290925260409081016000208151608081018352905464ffffffffff808216808452600160281b830490911694830194909452600160501b810460ff1692820192909252600160581b9091046001600160a01b0316606082015287519092508790849081106107905761079061198f565b602002602001019064ffffffffff16908164ffffffffff168152505080602001518583815181106107c3576107c361198f565b602002602001019064ffffffffff16908164ffffffffff168152505080604001518483815181106107f6576107f661198f565b602002602001019060ff16908160ff168152505080606001518383815181106108215761082161198f565b6001600160a01b03909216602092830291909101909101525080610844816119bb565b9150506106ef565b509299919850965090945092505050565b610865610a9a565b8051610878906007906020840190611440565b5050565b610884610a9a565b600455565b610891610a9a565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6108bb610a9a565b6001600160a01b0381166109205760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610428565b61092981610af4565b50565b610934610b44565b8685146109835760405162461bcd60e51b815260206004820152601e60248201527f417272617973206d757374206265207468652073616d65206c656e67746800006044820152606401610428565b6000338989898989896040516020016109a297969594939291906119fd565b60408051601f1981840301815291905280516020909101206005549091506109d5906001600160a01b0316828585610d17565b610a155760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b6044820152606401610428565b60005b88811015610a8557610a738a8a83818110610a3557610a3561198f565b90506020020135898984818110610a4e57610a4e61198f565b90506020020135888885818110610a6757610a6761198f565b90506020020135610dcd565b80610a7d816119bb565b915050610a18565b5050610a9060018055565b5050505050505050565b6000546001600160a01b0316331461050f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610428565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600260015403610b965760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610428565b6002600155565b60008281526008602052604090206004548154600160281b900464ffffffffff1610610c0b5760405162461bcd60e51b815260206004820152601a60248201527f546f6b656e20697320616c7265616479206d61786564206f75740000000000006044820152606401610428565b600354604051632142170760e11b8152336004820152306024820152604481018590526001600160a01b03909116906342842e0e90606401600060405180830381600087803b158015610c5d57600080fd5b505af1158015610c71573d6000803e3d6000fd5b5050600254604051635209071360e01b8152600481018690523360248201526001600160a01b03909116925063520907139150604401600060405180830381600087803b158015610cc157600080fd5b505af1158015610cd5573d6000803e3d6000fd5b50508254600160581b33027fff0000000000000000000000000000000000000000ffffffffffff000000000090911664ffffffffff4216171790925550505050565b6000610daf610d73856040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061117892505050565b6001600160a01b0316856001600160a01b0316149050949350505050565b60008381526008602052604090208054600160581b90046001600160a01b03163314610e275760405162461bcd60e51b81526020600482015260096024820152682737ba1037bbb732b960b91b6044820152606401610428565b6006548154610e3d9064ffffffffff1642611a43565b1015610e8b5760405162461bcd60e51b815260206004820152601b60248201527f546f6b656e2063616e206e6f74206c65617665207761722079657400000000006044820152606401610428565b8054600160501b900460ff168214610ee55760405162461bcd60e51b815260206004820152601b60248201527f426174746c6520696e64657820646f6573206e6f74206d6174636800000000006044820152606401610428565b805464ffffffffff19168082556001908290600a90610f0f908490600160501b900460ff16611a56565b92506101000a81548160ff021916908360ff160217905550610f6b848460078460000160059054906101000a900464ffffffffff1664ffffffffff1681548110610f5b57610f5b61198f565b906000526020600020015461119e565b1561108857604080516001808252818301909252600091602080830190803683370190505090508481600081518110610fa657610fa661198f565b602090810291909101015281547fff0000000000000000000000000000000000000000ffffffffffffffffffffff16825560035460405163b80f55c960e01b81526001600160a01b039091169063b80f55c990611007908490600401611a6f565b600060405180830381600087803b15801561102157600080fd5b505af1158015611035573d6000803e3d6000fd5b5050835460408051898152600160281b90920464ffffffffff1660208301527f735b6ee0baa0e267b335b9cbe4a627617e13b2cd15bcf0382430f8c73f356a0e935001905060405180910390a1506105c9565b6003546040516323b872dd60e01b8152306004820152336024820152604481018690526001600160a01b03909116906323b872dd90606401600060405180830381600087803b1580156110da57600080fd5b505af11580156110ee573d6000803e3d6000fd5b5050825461110e9250600160281b900464ffffffffff1690506001611ab3565b815469ffffffffff00000000001916600160281b64ffffffffff928316810291909117808455604080518881529290910490921660208201527fc6e154d143a863e2cce9664b681e1abf3260e6350b653095c731bec6f16dccde910160405180910390a150505050565b600080600061118785856111ed565b9150915061119481611232565b5090505b92915050565b600080606485856040516020016111bf929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c6111e29190611ad8565b909211949350505050565b60008082516041036112235760208301516040840151606085015160001a6112178782858561137c565b9450945050505061122b565b506000905060025b9250929050565b600081600481111561124657611246611afa565b0361124e5750565b600181600481111561126257611262611afa565b036112af5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610428565b60028160048111156112c3576112c3611afa565b036113105760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610428565b600381600481111561132457611324611afa565b036109295760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610428565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156113b35750600090506003611437565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015611407573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661143057600060019250925050611437565b9150600090505b94509492505050565b82805482825590600052602060002090810192821561147b579160200282015b8281111561147b578251825591602001919060010190611460565b5061148792915061148b565b5090565b5b80821115611487576000815560010161148c565b6000602082840312156114b257600080fd5b5035919050565b80356001600160a01b03811681146114d057600080fd5b919050565b60008083601f8401126114e757600080fd5b5081356001600160401b038111156114fe57600080fd5b60208301915083602082850101111561122b57600080fd5b60008060008060006080868803121561152e57600080fd5b611537866114b9565b9450611545602087016114b9565b93506040860135925060608601356001600160401b0381111561156757600080fd5b611573888289016114d5565b969995985093965092949392505050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126115ab57600080fd5b813560206001600160401b03808311156115c7576115c7611584565b8260051b604051601f19603f830116810181811084821117156115ec576115ec611584565b60405293845285810183019383810192508785111561160a57600080fd5b83870191505b8482101561162957813583529183019190830190611610565b979650505050505050565b6000806040838503121561164757600080fd5b82356001600160401b0381111561165d57600080fd5b6116698582860161159a565b925050602083013564ffffffffff8116811461168457600080fd5b809150509250929050565b6000602082840312156116a157600080fd5b6116aa826114b9565b9392505050565b60008083601f8401126116c357600080fd5b5081356001600160401b038111156116da57600080fd5b6020830191508360208260051b850101111561122b57600080fd5b6000806000806040858703121561170b57600080fd5b84356001600160401b038082111561172257600080fd5b61172e888389016116b1565b9096509450602087013591508082111561174757600080fd5b50611754878288016116b1565b95989497509550505050565b6000806020838503121561177357600080fd5b82356001600160401b0381111561178957600080fd5b611795858286016116b1565b90969095509350505050565b600081518084526020808501945080840160005b838110156117d857815164ffffffffff16875295820195908201906001016117b5565b509495945050505050565b6080815260006117f660808301876117a1565b60208382038185015261180982886117a1565b8481036040860152865180825282880193509082019060005b8181101561184157845160ff1683529383019391830191600101611822565b50508481036060860152855180825290820192508186019060005b818110156118815782516001600160a01b03168552938301939183019160010161185c565b50929998505050505050505050565b6000602082840312156118a257600080fd5b81356001600160401b038111156118b857600080fd5b6118c48482850161159a565b949350505050565b6000806000806000806000806080898b0312156118e857600080fd5b88356001600160401b03808211156118ff57600080fd5b61190b8c838d016116b1565b909a50985060208b013591508082111561192457600080fd5b6119308c838d016116b1565b909850965060408b013591508082111561194957600080fd5b6119558c838d016116b1565b909650945060608b013591508082111561196e57600080fd5b5061197b8b828c016114d5565b999c989b5096995094979396929594505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016119cd576119cd6119a5565b5060010190565b60006001600160fb1b038311156119ea57600080fd5b8260051b80838637939093019392505050565b6bffffffffffffffffffffffff198860601b1681526000611a36611a2f611a28601485018a8c6119d4565b87896119d4565b84866119d4565b9998505050505050505050565b81810381811115611198576111986119a5565b60ff8181168382160190811115611198576111986119a5565b6020808252825182820181905260009190848201906040850190845b81811015611aa757835183529284019291840191600101611a8b565b50909695505050505050565b64ffffffffff818116838216019080821115611ad157611ad16119a5565b5092915050565b600082611af557634e487b7160e01b600052601260045260246000fd5b500690565b634e487b7160e01b600052602160045260246000fdfea264697066735822122098aae522cbae28e01038c27e9bd433dc46406e6e924aa60ef668dca3f2a2c14864736f6c63430008130033

Verified Source Code Partial Match

Compiler: v0.8.19+commit.7dd6d404 EVM: paris Optimization: Yes (200 runs)
WarStaking.sol 1076 lines
// SPDX-License-Identifier: MIT

// War by ATS. Written by NiftyLabs (https://niftylabs.dev/).

//,,,,,,******,*************////*********,,,,*************//**///////((((((((((((((((((((((((((((((((#
//***********,,,,,************///*************************//////((((((((((########################%#%#
//,,,,,,,,,,,,,,,,,,,,,,**************************,******///((((((((((((((####((((###############%%%%%
//,,,,,,,,,,,,,,,,,,,,,,,/*************,**********************//(((((((((((((((((((((############%%%%%
//,,,,,,,,,,,,,,,,,,,,(##.#**************,,,,,,,,,,,*,,,*********/////((((((((((((((############%%%%%%
//.,,,,,,,,,,,,,,,,,,,,,(#,#,#(/*********,,,,,#%%%%%%%%%(,,**********////(((((((((((##################
//..,,,,,,,,,,,,,,,,,,,,, */,.####********,,/%#%%%%%%%%%%%***********///((//(((((((###############%%%%
//.....,,,,,,,,,,,,,,,,,,,*/.#(*/#(##,******%%%%%%%%%%%%%%%%***/////(((/////////(((############%#%%%%%
//........,,,,,,,,,,,,,,,,,,,,,#(##(###******%%%%%%%%%%%%%%#*******//////////////((((##########%%%%%%%
//..........,,,,,,,,,,,,,,,,,,,,,,,  ######*#%%%%%%%%%%%%%%%%%%%%/*****////////////((((##########%%%%%
//............,,,,,,,,,,,,,,,,,,,,,,##########%%%%%%%%%%%%%%%%%%%%%%%(***/////(((((((((((##########%%%
//.............,,,,,,,,,,,,,,,,,###############%%%%%%%%%%%%%%%%%%%%%%%&%////////((((((((((((((#####%%%
//..............,,,,,,,,,,,,,,,,,,,*##########%#%%%%%%%%%%%%%%%%%%%%%%%&&*/////////////////((((#######
//................,,,,,,,,,,,,,,,,,#############%##%%%%%%%%%%%%%%%%%%%%&&&#*////////(((((((((((((((###
//.................,,,,,,,,,,,,,,,############%%%%%%%%%%%%%%%%%%%%%%%%%&&&&&(//////////(((((/((((###((
//....................,,,,,,,,,,*#############%%%%%%%%%%%%#%%%%%%%%%%%&&&&&&&&*////////(((((((((#####(
//.........................,,,,,(#############%%%%%%%%%%%%%%%%%%%%%%%%&&&&&&&&&*/////////(((((((((((((
//........................,,,,,(((##############%%%%%%%%%%%%%%%%%%%%%%%&&&&&&&&%/(((((((((((#######(((
//........................,,,,(((#######,*#######%%%%%%%%%%%%%%%%%%%**%&&&&&&&&&&///(((((((((((######(
//..........................(((((#####(,,(#####%%%%%%%%%%%%%%%%%%%%%%***%&&&&&&&&&%///(((((((((((###(#
//........................,((((((#####*,,,########%%%%%%%%%%%%%%%%%(%%%**%&&&&&&&&&#///(((((((((((####
//........................*(((((((###/,,,,,#####%%%#%%%%%%%%%%%%%%%%%%&&%/&&&&&&&&&&%//(((((((((((((##
//........................((((((((##*,,,,,,,#######%%%%%%%%%%%%%%%%%%%%%%&&&&&&&&&&&&///((((((((((#(((
//.......................,/(((((((#,,,,,,,,,######%%%%%%%%%%%%%%%%%%#**(/**/&&&&&&&&&///((((//((((((((
//.......................///(((((*.,,,,,,,,,,####%%#%%%%%%%%%%%%%%%%%***/***/&&&&&&&&////((((((((((#((
//.......................///((((..,,,,,,,,,,*#####%%%%%%%%%%%%%%%%%&&**///////&&&&&&#//(((((((((((###(
//.......................///((/..,,,,,,,,,,,#####%%%%%%%%%%%%%%%%%%%&%*///////&&&&&&%(((((((((((((####
//.......................///((.,,,,,,,,,,,,####%%%%%%%%%%%%%%%%%%%%%&&#//////&&&&&&&&((((((((((((#####
//......................,///((.,,,,,,,,,,,#####%%%%%%%%%%%%%%%%%%%%&&&&/////&&/&&&&&&(((((((((((######
//......................////(*(/,,,,,,,,,/#####%%%%%%%%#***%%%%%%%%&&&&%///////&&&&&&((((((((#########
//.......................////((,,,,,,,,,,#######%%%%%%*****%%%%%%&%%&&&%/////((&&&&&&&(((##(##########
//.......................*,.,..,,,,,,,,,,######%%%%%%*******%%%%%%&&&&&///(((((&&&&&&%(###############
//.. .................././.*../,,,,,,,,,,###%%%%%%%%*********%&&&&&&&&&//((((((%(&&&&(################
//....................*/*,,/(((((((#,,,,,/##%%%%%%%%******////&&&&&&&&&/((((((((&#&###################
//....................,,,,,,,((((((#,,,,,*##%%%%%%%%%***//////%&&&&&&&&%(((((((######################%
//...................../**/*((((((####*****%%%%%%%%%%(////////%&&&&&&&&#(((((####################%%%%%
//..................,,,,,,,,,,,,,*#####*****%%%%%%%%%%////////&&&&&&&&&((((######################%%%%%
//................,,,,,,,,,,,,,*************/%%%%%%%%&/////((((&&&&&&&&#(######################%%%%%%%
//..........,.,,,,,,,,,,,,,******/*/**/*//**(#%%%%%&%&/%((((((#%&&&&&&&##%##(################%%%%%%%%%
//*//*////,*/((/#,(/**/(#**(##(%#%%%%%%%%%%&%&&&&&&&&&&&&&&%&&&&&@&&@@@&@&&&&@&@&@&&@@&&&&&&%&%%%%&%&%
//(##############%%%%%%%#%%%%%%%&%&&&&&&&&&&&&&&&&&@&&&@&@&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//%%%%%%%%%%%%%%%%%%%&&&&&&&&&&&&&&&&&&&&&&&@&&&@@&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//%%%%%%%%%%%&&%&&&&&&&&&&&&&&&&&&&&&&&@&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

// File: @openzeppelin/contracts/utils/math/Math.sol

// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10**64) {
                value /= 10**64;
                result += 64;
            }
            if (value >= 10**32) {
                value /= 10**32;
                result += 32;
            }
            if (value >= 10**16) {
                value /= 10**16;
                result += 16;
            }
            if (value >= 10**8) {
                value /= 10**8;
                result += 8;
            }
            if (value >= 10**4) {
                value /= 10**4;
                result += 4;
            }
            if (value >= 10**2) {
                value /= 10**2;
                result += 2;
            }
            if (value >= 10**1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
        }
    }
}

// File: @openzeppelin/contracts/utils/Strings.sol


// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)

pragma solidity ^0.8.0;


/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}

// File: @openzeppelin/contracts/utils/cryptography/ECDSA.sol


// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;


/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV // Deprecated in v4.8
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol


// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

// File: @openzeppelin/contracts/security/ReentrancyGuard.sol


// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

// File: @openzeppelin/contracts/utils/Context.sol


// 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;
    }
}

// File: @openzeppelin/contracts/access/Ownable.sol


// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;


/**
 * @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);
    }
}

// File: War.sol

pragma solidity ^0.8.18;

interface WarBonds {
    function burnForAddress(uint256 _id, address _address) external;
}

interface Rota {
    function ownerOf(uint256 tokenId) external view returns (address);
    function safeTransferFrom(address from,  address to, uint256 tokenId) external payable;
    function transferFrom(address from,  address to, uint256 tokenId) external payable;
    function burn(uint256[] memory tokenIds) external;
    function setApprovalForAll(address operator, bool _approved) external;
    function getApproved(uint256 tokenId) external view returns (address operator);
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

contract WarStaking is Ownable, IERC721Receiver, ReentrancyGuard {

    address public WARBONDS_CONTRACT = 0xcAcb0a5bb1f52F00a14bDA0dc85dE81392B2892B;
    address public ROTA_CONTRACT = 0xDfB29501b42f63A947Ddc5249F185D6BcBE6986f;
    uint256 public MAX_TYPE = 4;
    address public SIGNER = 0x2f2A13462f6d4aF64954ee84641D265932849b64;

    uint256 public warTime = 48 hours;
    uint256[] public burnRates = [15, 30, 45, 60, 60];

    struct TokenData {
        uint40 time;
        uint40 border;
        uint8 battlesCompleted;
        address owner;
    }

    mapping(uint256 => TokenData) public tokenToData;

    event WarLost(uint256 tokenId, uint256 valueAtBurn);
    event WarWon(uint256 tokenId, uint256 newValue);

    function goToWar(uint256[] calldata tokenIds, uint256[] calldata warBondIds) external nonReentrant {
        require(tokenIds.length == warBondIds.length, "Arrays must be the same length");

        for(uint256 i = 0; i < tokenIds.length; i++)
            _goToWar(tokenIds[i], warBondIds[i]);
    }

    function _goToWar(uint256 tokenId, uint256 warBondId) internal {
        TokenData storage data = tokenToData[tokenId];

        require(data.border < MAX_TYPE, "Token is already maxed out");

        Rota(ROTA_CONTRACT).safeTransferFrom(msg.sender, address(this), tokenId);

        WarBonds(WARBONDS_CONTRACT).burnForAddress(warBondId, msg.sender);

        data.time = uint40(block.timestamp);
        data.owner = msg.sender;
    }

    function leaveWar(uint256[] calldata tokenIds, uint256[] calldata randomNumbers, uint256[] calldata battleIndices, bytes calldata signature) external nonReentrant {

        require(tokenIds.length == randomNumbers.length, "Arrays must be the same length");

        bytes32 hash = keccak256(abi.encodePacked(msg.sender, tokenIds, randomNumbers, battleIndices));
        require(_verifySignature(SIGNER, hash, signature), "Invalid signature");

        for(uint256 i = 0; i < tokenIds.length; i++)
            _leaveWar(tokenIds[i], randomNumbers[i], battleIndices[i]);

    }

    function _leaveWar(uint256 tokenId, uint256 randomNumber, uint256 battleIndex) internal {

        TokenData storage data = tokenToData[tokenId];

        require(msg.sender == data.owner, "Not owner");
        require(block.timestamp - data.time >= warTime, "Token can not leave war yet");
        require(battleIndex == data.battlesCompleted, "Battle index does not match");

        data.time = 0;

        data.battlesCompleted += 1;

        if(diedAtWar(tokenId, randomNumber, burnRates[data.border])) {

            uint256[] memory tokenIds = new uint256[](1);
            tokenIds[0] = tokenId;

            data.owner = address(0);

            Rota(ROTA_CONTRACT).burn(tokenIds);

            emit WarLost(tokenId, data.border);
        
        } else {

            Rota(ROTA_CONTRACT).transferFrom(address(this), msg.sender, tokenId); 

            data.border = data.border + 1;

            emit WarWon(tokenId, data.border);
        }
    }

    function _verifySignature(address _signer, bytes32 _hash, bytes calldata _signature) internal pure returns (bool) {
        return _signer == ECDSA.recover(ECDSA.toEthSignedMessageHash(_hash), _signature);
    }

    function diedAtWar(uint256 tokenId, uint256 random, uint256 burnRate) internal pure returns (bool) {
        uint256 randomNumber = uint256(keccak256(abi.encodePacked(tokenId, random))) % 100;
        return randomNumber < burnRate;
    }

    function getBorderNumber(uint256 tokenId) public view returns (uint256) {
        TokenData storage data = tokenToData[tokenId];
        return data.border;
    }

    function getNumberOfBattles(uint256 tokenId) public view returns (uint256) {
        TokenData storage data = tokenToData[tokenId];
        return data.battlesCompleted;
    }

    function getTokenDataFor(uint256[] calldata tokenIds) public view returns (uint40[] memory, uint40[] memory, uint8[] memory, address[] memory) {
        uint40[] memory times = new uint40[](tokenIds.length);
        uint40[] memory borders = new uint40[](tokenIds.length);
        uint8[] memory battlesCompleted = new uint8[](tokenIds.length);
        address[] memory owners = new address[](tokenIds.length);

        for(uint256 i = 0; i < tokenIds.length; i++) {
            TokenData memory data = tokenToData[tokenIds[i]];
            times[i] = data.time;
            borders[i] = data.border;
            battlesCompleted[i] = data.battlesCompleted;
            owners[i] = data.owner;
        }

        return (times, borders, battlesCompleted, owners);
    }

    function changeWarTime(uint256 _time) public onlyOwner {
        warTime = _time;
    }

    function overrideBorder(uint256[] memory tokenId, uint40 _border) public onlyOwner {
        require(_border <= MAX_TYPE, "Border does not exist");

         for(uint256 i = 0; i < tokenId.length; i++)
            tokenToData[tokenId[i]].border = _border;
         
    }

    function setBurnRates(uint256[] memory _rates) public onlyOwner {
        burnRates = _rates;
    }

    function setRotaContract(address _addr) public onlyOwner {
        ROTA_CONTRACT = _addr;
    }

    function setWarBondsContract(address _addr) public onlyOwner {
        WARBONDS_CONTRACT = _addr;
    }

    function setMaxWarType(uint256 _max) public onlyOwner {
        MAX_TYPE = _max;
    }

    function onERC721Received(
        address,
        address,
        uint256,
        bytes calldata
    ) external pure override returns (bytes4) {
        return IERC721Receiver.onERC721Received.selector;
    }

}

Read Contract

MAX_TYPE 0xd9197c32 → uint256
ROTA_CONTRACT 0xb8c1db40 → address
SIGNER 0x582abd12 → address
WARBONDS_CONTRACT 0x788cb4d9 → address
burnRates 0x2ce8939a → uint256
getBorderNumber 0x0e58f7c3 → uint256
getNumberOfBattles 0xa5e7f9ea → uint256
getTokenDataFor 0x98764d83 → uint40[], uint40[], uint8[], address[]
onERC721Received 0x150b7a02 → bytes4
owner 0x8da5cb5b → address
tokenToData 0xae3d5414 → uint40, uint40, uint8, address
warTime 0xa4d1776d → uint256

Write Contract 10 functions

These functions modify contract state and require a wallet transaction to execute.

changeWarTime 0x3bb624c2
uint256 _time
goToWar 0x7b58c4bd
uint256[] tokenIds
uint256[] warBondIds
leaveWar 0xf8939e0c
uint256[] tokenIds
uint256[] randomNumbers
uint256[] battleIndices
bytes signature
overrideBorder 0x1ecaef43
uint256[] tokenId
uint40 _border
renounceOwnership 0x715018a6
No parameters
setBurnRates 0xa6a2ee02
uint256[] _rates
setMaxWarType 0xef7df66b
uint256 _max
setRotaContract 0x29a86c52
address _addr
setWarBondsContract 0xf2bc9e05
address _addr
transferOwnership 0xf2fde38b
address newOwner

Recent Transactions

This address has 1 on-chain transactions, but only 1.7% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →