pragma solidity ^0.8.0;



interface IMint{
    function mint(address to, uint256 id, uint256 amount, bytes memory data) external;
}

contract Stake is Ownable{
    struct StakeInfo{
        uint32 stakeTime;
        uint32 unstakeTime;
        uint192 claimedReward;
    }
    IERC721Enumerable immutable public stakeNFT;
    IMint immutable public rewardNFT;
    bytes public powers = hex"72646e6481646e727384646e646464646464707e737064766464647372726e80706e6e70727272727064727064727a7d706e647c6473647d827c64647a64767c817a6464706472756464736464706e6464736464647373647c6e736e64647064646472646473726464646478826e886470716e76646464737364647f646470646e6472647e7072727264727264817c64647d72738064647a73727270646464727664647f70726480707364646e6472736473647281707c646e6464646473847f64766e72647064827f76727c7d836464647072646e6e6e6e6e6464647364647e6e646e647d647278646e707864646e6470736e6e7c737364647a6e7d6473707e7c7a648073706e6464647064767876646464646e64737264647c648b7a7664646e646e727e7372736e7264736e7664646472646464806464757270717d64827a64726e6464726e6464758164646e64646e6464726464647f707e64727c70737264647d6e64647281706473647c6470647064646e88647373707e6464716470707072727e70646e70806464736e8272646470847c7d7070647c646e7c64756464646e647e73646e76647f7270646e73726e7d6e7d64647064707064647f646473646e6464646e64707f6464728a6e647270726473726e647c7064726472646e64736472646e6464727372646e647a64648c707f76766e64646e767f7271648e7a647d72647a7264647f737d7273767f6e646472826e706e7e72646473647370647c64728773726e64646e64727072647664727670647573737c646464737373646482647f6e736470707c707c64646464726464646473646464646464646e6e7c64707e7d7271646464706476647072706e6488647f6e6464647364646e70646473736464768964647d64647364736473707c647364647d6e72647364646e707264646e64646470738f6464737064648a647c767e6e7364706464646e7264647a64646472648064736476646464738c6464736464646e72646e6e7d64647d647264646e647364646e6472647072647370647f737d7c6471647f7071707e647d7e648a64728170646e7c70647f72647c706472706e6485647264736464706e6e64647b6e647364647672707d7c6482737570646464647376646464647078706464816473647064707078766e7b64646e6e6471726473647373647671766e76707280646464706e6e6464717e736e6464726e64647673766e647664647872757164647d646e73726e646e786e72646e706473646e647264726e73726e7f647e73726e7f73716464727072647064786e6e646e646e8e64647670706464646464646464646e6e7e706464647064807f757e7273726e84646e6470647c6e70858a6e7a707673646e72647376706464726470646e7c76737f6e6e64647c827672737364646464726464726464706e7f6464646464647064707b646464886464646e64736464716e766472717364646464736e6e64646e737f7f64727e6470706464727f7a736e806e6464646464646e6e646e7c7a717f6473648b7664647364716482646e707d8d7f64736e64727064646475646e6e7f727c647d64706e7c6464737c726464647c64736e82708c706e647073646e6e707364646e647264646e646e6464646e76647870646464717264647364646464736473646e7270727064647d6464646e64646e647264766e6e647d70856e736470646464646e707064646e7f728264766476647a7064646e646476647378727164817f7e737c7073646e7364726464646e647c6e6e73647264646e646464887c6e647876767f707664646464766e756e6464736e64726e647c826464647273646473707064767f7a646e72647d6470726e8164727273647364647264706e7264647d7273896e648164647b64647072647a737373756e727073646464646e64646470877c7d7c7d736472647064807c6464647c64727070766e727e827d647d647f64827c6e70736e6e73727264726e647273647c70646464647e72726e64646e7164647073646464646470646e646464756e8264646e7d736483646e64766e6464646e6464737f6e736464647270706e8164727264768372707175646e7c76726e646464707d7a767d6464647670646464646e647d707264646482736e646e647664647364647264646e64706464706e6e7a7064727370646464646464647d6473646473736e708164736485837c6464708264646464646464727c707070737384827364726476726464706e85647672647c7164647d707672846e6e6e726e7e6464706e76706e71737e707172646470646472646472766464647281766464646e877c6e64646e647b7364646e73648064726464736e6e7364857c6e6e6e7273727b726464738164727264726e70726e64646470707372647e737c6e647673727271647264646464707c6472736470646e648164766464646e64806464646476646e7176726464646e646e6e766e646473726e7c6e6464647f6e64707072717d6e6e647072827264647070727664707064646e8c7276647d72807a647364647f64647373706464647c647f64756e727d736e646e64646e6464736481647e7264647c736e70648a767e646464646e647c6e8264816464647364736464726470648b716473647864647e647264647c7c7e7264737075726470706e64647272736464647d7664737a727c706e64727c646e726473646464726476647064707c647664726470646e6e76646473646470647672707e6e7a72646473706e7f6e64707072647364727e646e64648c64647e7f72737e6472646e646e76737064646464736476646e7064646e6472646464736464646472706e6464727d646e73646e6472646464647c70647064736464647e6e91767e647264647073646e6476707f7f6470726e7c6e7e7072647672647e85648264646464647d707c7364736481736472766473647d7c646e73646e647c6e64826e647e736e726e7c8564646e6e827f7e6e8f73646473647d7f64646464768864647c7a6e766464647375716e78646464706e827872648073647d70756e727064648364737264647c7270826472786e64647c706e6e64766473646464717676727364727b6e647f646e64707670647264647c73767364646e6e64767c6472707e647e6e647c7264736470646e647e646464646473727064766464647a7564647081786472816470737f646e707a646e706470737364736e64646e73726464727564646e6464646464646470757c64767f6e737f646464647d7064646e64807d7264737c6464647a6464647e64647a6472647082646e83737364646e64646e646e76706e647064646e7072646e726e73647f6e766e6e6464647e72807c646e72737082767f64647164646472736464646e64646e737e76856e647287726472767f6e647270646464706e726e64716e73646e6472646476646464647d6464647064647064727e6470757f70646464646464646e7e6473807c6472646e6e64766e73646e728a64647264736e7e726464647272646e73726464736464646e6e646e72707371647c707d897f6e646e7664646e64726476767164646e7f646464647e6e6e7264737370647f72646e6e646e646e6e7064727f6e647c7f646e72706e76646e70647373827664647172646470726e73647f6e7a64646e70646e7a64726e70648264646464646e73646e646e72706472646470729064766472647264736470736473647284646464736e646e7d647076706e6464647c736464727f737e7f727372647264647c6e7364727264648164646472726476726e708e6486647f64647664726464646472737c708064646e646464828c7b646e7281766473647364707387646480646e64647264647070766e646464647c8e6470646464647b6e82766481817f646e6470787064726464837d7c70646464736e7064816464736473646475727873736472706464706e6e6464706464737373717373737d64646e6473727e6470726e646e6472877c646e73646e64806476737d6e73756e6e6464647a717264736e6464707c646e826464647d647e6e647870736472716e647276727264646464648172736e6e647d6e707364647164707e647f7064646464647264646464726e736473646476736464727364736e647270646e7e80706e6e64646464726473646464646e6e647d646e80646470646464646e6e7c6e646470646464647264706e64707e646e726e6464737c64646e7f7f736470707264757e737864727f647373647a64646e6e6e646e72707f647373648276646e7c6e64647f7264646e64647d7272646e72727f7573646e6e6e7c72647e646464707383646e647d64767b707c70726470646470648872647264737c706e647d70727373706e786e647364647f647364708264727270646e647e64648c7864726472707064716472736464737370736472737064826464646e736e76646e646e646e64646e7e738072646480646e70646e64646464646464648173646e646e72706470707164646472737064766e766464646464646464647e7d7064737b64647f646472646488646476707f646e826e7381646464647064726e72726464736e64736e727082727a738b707a6e646464756476647264646e73647c836464806464817c7c647264806470647e6484646e64646e647e64807272727070646473646e64647564726e766e7c6e648764647264646464726473737573737e7d726e647c647276647c6e7d7072726470707a6e64647172647076646e64647a706464647073766473647d7a707264737e647f6464736e7373826e736e6e757873647d736473646478646464646e7075647264647c6470647f64736e7f7364767a647d6e7370727c6e646472807d7364846e646e64726e6e7d7664646484707a646473736464737c706e73706473646464647c647d7c646e646472646464647272646464647871647e6464737d6464646464647b72726464707080717b6e7d6e7064647c7364727c707064646e6472647c64728264717f6e7073646464646e6e646e6e6e8464646470647e7370737373646e867273646e64646e6473646e727d727276646464707d806470647264647c6e64736e88646464647d6e7d6e648776766e76646464806464647e64646e6e64647f64727364646464647064737064647264647c6464646464646472707c726e647f766473877c646472646464766470647c73646476646e70647d6e768e726e708b7f6464647876716472646e64897e6464736e647f8264646470647f7272646464706e6e8c646475647273646e737270727d6e6e73646464736e6464768a8f70647370736e64646e647c72706470736472646464646e72647264736e646470826464646464646e7c6464806464736482707e647d7e646e707f76736481647c647f6e6464646464647364826e7c64706464646e646473757178646e64647664768264646473647f7f64737664646464727364646e7a706464646464647c6e646473708864707272646464736e6470726464646e7a6e6e7e7364706e6e64647e64828070756e646e7264646e7364647372726e647c64706e726e647264646473646e646e7664646470647c6470707872726464646e7f6e6e706e64648164648064647e64646e706e6472646464647d82646e70646e70646e646e72646464737c647c7e647d64647c6476737d826464756470647f6e70766e64647064647270646482807c7f7e6464647664726e64726e6e7d64646473856e6e7d646464817364726473726e6470726473646e646470646e76647d7373726e707d64647264706e64646e6489646e64646464647e64707364646e736e736e646464737264646e80647e7c647064646e7082646e64647a6475736e64826472646464727f737364726e716e8d7d646470646464646464646483647c647564646e647c6e647e7064766464647e6464646e648564706e6e64706e64707370707064647e8f81647f647564736e736472707073727c6472647681646481647282716e6472807064727f706e6e73647a646e82647f646e7270767c6472646e7f6464646470647a647070646470647e647f6e647264646464646464646e647264706e646472766e7d76647e70727a736464737c6480707664736e78737c646464646464827a646464706e646482726e646473646471726e7e737c7064647664726464737e727c6e82647070646e707a64647c737873706e8b646e7376647f807364706464856e6464736464727372738464646e6e646464706e6464707c7264707f6e7f707564646e647064706e64646464766464646e8264736464767664647673647a76646e726e7f647064766e6471648b64646e8c6e6e7c76736e647c8364726e647c7c646470736e6e6476727364646e646e8271646e76647070707a64647270646464707070646470646470708175706e6e6e728c73726476736476706464647d64647064647070646e647064646e648264646e64647c7e7676647e6e64646e6e6e64647264706464646e6e7382647c7a6464737c6e647a76647375707364647c6464646e646e6e737f7d6e6470646e646e737a6470646464707a726e7572706475646e6e72646464647264647c64646e646464646464646e7c6464726e6464727e727e646e7d726488646e64708e7073647572727c6e6e7f6472647076736e64647e647364736e64646e6e6464646464736e726e6e73646e72826e7f6472647364647c6470707364647c6464706464646464647264646470646e646472726e646e64706464646464736464707f7f647a6e6e6464706464646e756464646e7a64726e707e6e6e6e716e647f7d737f707364647c6e787273707f64727264647070766464646e70647c7364647d6475646e707e7c7370766e6e7071647c8470646470726464766464706e7e727f64867364728970648064727c64647264647e6e7c64737c6472716e6464727d6e7f647070647c727075736471736482646476707264646e64647e7370707070648a7b7264646e736e647c6480646472707372907271646e8573647370706e7e7273647d70726e7080766464816e6476646464647c7373736464706e7276647673646e707d6464647d6e726e737c6e64647c7d6e647c7370647d64727c707f6476646464806e6e64736e646464648b7c7f646e646e80768173647373726e827e7f707273646e646e64727f64646e646e6e6e717d826e646481647d7f6e64647864647264728164646473647c706e7d647273726e7d646e64728070646470726464646e6470827c7a648264646e6e646464647d6464647f766464647f73726e64706470647f707a646464646464707d7f648c8972706473726e6464647e6e73706e64648364727384646471646470706472646e64647c646e827e7364706e64707d6e646e646e737d7c7c6e6464766e7364646464726473726476646475647b647172707c6e6464647d647f73707d647e807d646464767c737864647a6464647c647364647164646e6482646e64646e72806e6464726472646464756473647c72726473647d64717f7e64736464647f64646473706e64706464707d736473737c647664766464726e6e7685646464646480647c64647d726e6e7a7d6e7d64647c6482726e647e70707c6e647672808a816e7264727c64886464648164736472647273726e6470706e647364707f7f646e647d6e7064736e646e70826e706464787e6470727e7364648164706464737c6e70646473827c7d737364728172647264647364647270727e726e64646e7d7264646e70706e6e6e70786464706472647e6464646e7064646476647264736e6480647e6464647c707c7285736e766464726e7064726464647264736e6e7064647f646e6464646476646e647d6e6470757d646464707a647f7264646e70647d6464647f7364856464726464736e6464646e646464647d73648b6e70646e6473727d6e737373726e7d647e6e6464647c646464786e64726473707c646e7c64726464766472727e8a64647d826464737c716472716e7d73646470648272726464646e7e6476806464877f64646e647a647b78707f6e706e70706464706e7264726464766464646e6e72907273646464736e736464646472837f7e73647e7176647264816e647073646e736464646489726e646e7c6464647e64907d64646478706e646464737d646e6e7c64736e64647064726e76647f64706e70646464647073646e646e6e736e6470706e646e6e737a706e646e6464707d70646e72726e7064766e7f727e727264727a646464646e64726e6464727264707c7f6472706473646476707a648473728664727c727c64646e7264706e64646482646e64646e647e737364646e6e646464648264647c6e7064646e707c726e7d64727d64767c70647f7c64706e6464766470707270726472647a6e6464737d8b6464646e646e64716464736e6e736464707d647276646472646464917d64737676646464648c7264826e736464706e64717264647d64736e646464646464737264647d647d646480646e73727071886464766e6e6e64646473726470646464648e648b73646470757664646e6e6464737273736472726e726e7b736472726e647073647083887c646464706464646473646464736e647c6464646464647d7f706e7f648464647b646e7e64647c647664646e6e647076737c64648364647064726464646e7373707f646e70647d7c647c75646e64646464646472727c736464646e7264646e737264767a648064707c646e64646e6e6e73647f64646e7c6464736475646e70737a646e647e84646470647d6472707c7073647264736e6e7c706464727c6e647070646470727d726476707276706472707080646e7064737c7d737f64647e646e646e6e7c76726464648264737264646472646473647064647d6e646e647f646e6e647f6e706e6e6470726e64737064737f646e646e726e646e646e70727c646472726e6e646e64647a6e73736464646464827064647d726464646e646e646470646e64896e6464756e6464646464706470647f7064646464647064647364646e6e736472646472736e646464646e737b64646481726e646e647c6472707070646e6464647d64737664647375647370646476647e6470646464646e7164726e6e64648c64646e647f64647664726464647064647d647a7664767d6e72756e647273646e64648f7272727080726e6e70646464647071727c7a8064717c8e6e6e757572646e64736473707f737a64707373647264767d647273647670736e73706e64646e846464646e7372646476647e72647f7e647f64737a647c646472727f647d766e648b646470727d647d64707e6e737070646464706e73707c6476647d64736464726e7264737364727264646e647070706e64736e70646464766e7670767264707c647064647264647664646464647376646473646e856472646e64646480647373647264726464767d6e6e647086648276756e6472706e6e887f64646e7a70647364717f727376726e646e70646e64647d708a646464647d64647664646e846473646e6e7a6e737c756464647d7364646e647d707376646e64646464647f6470646e7c7364707264706473646464646473647c6481727664766476647e6470646470736464647064646e72708364646470706e8064726464727c6464857d6e706e7d826464706e737064646e646464707664646e72648a646464646e64647164646470707f647264647671646e6464727f7e7370736464647c646464706e64647f64707c71646e72646472787d7364646464736470726464648a647a647d706473736e64647272646476647d647e646e736e736e64706e6e72726e87647c647064646e727864707272736e64736464717064648a646e64707e827264736470736e64646464736e7a7a7e816e8972706e647672646470647d646e64766470896472646e646e7d72736e64807264648064727673647064647c64646e64707e646e64708664727078647064786e6e736485646473736476646473717070706e646e7f8972727c6e7d71646e64646e647c6e6475707c646e6464647d726464727d64737081646464646e647d7d7a826e6e64646472736e7f6464647f64707e6e647d70646470706464647c64737f707370826e64647064726470647b6e647264767c646e6e6e737f6e6464786e82647c6476646e7f707364647e7d73646e64707284646e64646e647f6464706464727064648564806e72727f6470647e647676646e646e7e646e646e646e64716e64808f73646464646464646e6472736e64646464736e6e646e736e64736464707e64737d646470808f64726473646e64647375706e64646e64736464646e64647064726464646e73736473647d6e70707e8c647f646464727d726480646464647c707372646e75706476646e826464767e647c647e7d727264767c6464727e737c64716e647d738064647c6464827f72646e8264726e7280706e6464647a7c7c6e6e64646476646e6e6464727c647d727c73726e6464737082766464707070647f7276646e717384708b646464736478647064647f64647e6e647c7a7c767e64737e64727364646471647a72706e6e6473646464646464647364826473726464767272647d7270646464716e647e647164737388646e647373646464646464707c706472647c726e64727264647e6e64647364807264646e6472646e726e70647c6464646464646464646464736e647c7378647c6e706464737c7b646464647c726481707664646e72876476647c71646471648570646470646e7c6e64707e64737c7f646e6e7d6e7564706464647f7a73647e836471646e6464726473647c6e706e7f6482727a6e646e64726e717f8e64766464646464767264737f6476736e647f64646473736472866e728064647676647c64646488646464757a7e64647178646e6e6e646472646e72647264646464646470647c647364646e64727c71707b6e647c75707372726e7c6473829173646e646473706e766464647a81827e647164646e6464736e72646e64647676647072646e7d64706e7f727272726e7c646464706464646464737e73727064648b78647664647664706464727272646487728e7e7364646464647264647e6e6475737f646e736473737264737064646e6464706e6470647e8e64726e706464886e73646478646473707e7064766e6e647c70647e7d81646464646e73646e7c647270647e7264706e646482647064646e7d64816473887d647370706464647372737264726464737564646464646e7e646464646470647b7264806470646e646e64646e6464648264647064647364646476647c72737c807e6464727d7c6464647c736e7d64646e7c70647d647e64646e6488646e646464736464646e708264766e6464647273726470647282646e7364706e648d737e70647d7272646472646e75806476647064706464736e64707664816464646472726482707e737f647d6472706e646e64646e6464647080647e7264736464766e70837c646471736e736464647c64727064707c73646480726e6e7364646464737664647364708273736e64706464706e64706464837276646e6464826e8b6e70646464646464646473817a71646e646482646473736470737e8c70647f6e6464647264646464646e70876e647d6e70727f7f826470647370786e647d6464707f6e647f7064646e647264647a647364646e6476647d7e7c767272727f72646482737264708c76726464647c646e64736e646e727c708064647073646e646472737664737f647c756e64646e7d646e6e64736464646e736e73646473736464646e73646e646472727c7f826e76647364788c6e736e647e6e64706e72706e646e70646464647d727364646464756475646473766e7f76706e6473706475737a7a767d6e647382706464736e64726e647e6464736e707364706e7e6472726e646e816e646e648364646470646464706472736473766472737e647e64647e828964647d736e70736e7c7f827375738071647f70646e786464646e6464647f6e6e7f64737d827c6476647a6470737e7c6464807d647864737d6464646464648b64726e70727673647c64737c64647370646464736e6e6e6464817c756473647c6e6472737364896e7376737264736464726464647f6e73646e6e64707c647664706464646e64647364646464647276647373647364736e6464736e7164646e7c7d736e7c73647273767070726464646e647f64806e6e6470647d7170647a6464647b64648564647064647270648b6473706e647c736e6e6e7076707280646470807080648464647f71727264646e756e72646464647064647c846e707273646e7270736464647270646464646464648b647f7364707e736e64647e8d6e6464647172726e64706464726e70647a706464648d766464826e8d7072646472647064736e7364707075646e647a64737370767e8e64726e6e64727c70767364757a7b7264827364706e646e706e826464648f648d7f6464647a64648a7e7270706480647270726e706464647064727a647c736464736e6475646471647270736e7f646473727f646480727f7264646e64647264726473737264726470826e6e64647f6e7164726464646464726e64647064647c73716473647073646e6472647b6472646e73646e7673646e6e6470706464826e73647e646476646464737c7d6464728d726e7c737264737b647e7e6e7864646464646e64737864646464646470726e6e647664647364738b727064726464767283727f646464727164646e646e736464646e7c8264646e64736e70706e6464647d816e646e6e6464646e646e8f70646e76646e6e70646464827c7073726464646e7b6e6464647270646e6e64827370716470647e64646e64736e7673646e707e64646e6e6464647364756e647c7064646480646e72877d6464706e706464707064647172648e73646464647c646470646473717270716464646e707072836473646464736464647364727264736473857c6464646e646e64647c717073646e6464647170647f6472647e64646464727c64647d70737c646464906e647d646e73806e8b64827f7f707c647e6e706464707064646e73737380646e647f76707089647f64646464647c646e73767d647d707a646476727070706476646470646e757085646e6e7e6e786e646471728270646470726e73726473647c647c757678647676647270647373736470647c64646470706472706464718364766473816e766e7e647c71647c64647c72726464646478768164647264647d6473807064646e646e64727c7e73646464707f6472707e6e646e647f7264646464646464647073726473707664646464646464646470737c647c728e7a6472706e7073646e7370736e726464766e6473646464647c6472707264647c73706e727664647d7264717364726e6464646464766464727070727e6e7f64647e736472646464646e64646464836e64646e70766473706472646464647e767a646e64857d7364647a7e6470646e6e64646e64707f6e646e75707364826464767f8a82706464766473646e648164766e646464646e72647264726e7682737373736e6464646480646464857c7270646e76727364647671647d6464646482727f7a646464646464647670736e7d647c64727073647c6464646e7672766e64737064727664766464647d70646473707264869164646464646e817272646464648e6e7c6e6472766473728e72736464726e7278757c64647270707d7664816464707e72647c70817364646e646472707d6e64706e7d64647064647064646464647073647f726e";
    uint256 public baseReward = 1e16;
    bool public stakeOpen = true;
    uint8[] public rewardPerDay = [0,2,4,6,10,14,18,22,28,34,40,46,52,60,68,76,84,92,100,10];
    mapping(address => uint192) public rewards;
    mapping(uint256 => StakeInfo) public stakeInfos;
    uint256 private oneday = 1 days;
    uint32 public lockTime = 3 days;
    mapping(uint256 => bool) public blackTokens;
    
    constructor(IERC721Enumerable _stakeNFT, IMint _rewardNFT){
        stakeNFT = _stakeNFT;
        rewardNFT = _rewardNFT;
    }
    
    modifier check(uint256 tokenId, bool isStake){
        require(stakeNFT.ownerOf(tokenId) == msg.sender, "Stake:notOwner");
        require((stakeInfos[tokenId].stakeTime > 0) == isStake, "Stake:stakeStatus");
        _;
    }
    
    modifier onlyOpen(){
        require(stakeOpen, "Stake:notOpen");
        _;
    }
    
    function _stake(uint256 tokenId) internal check(tokenId, false){
        stakeInfos[tokenId] = StakeInfo(uint32(block.timestamp), 0, 0);
    }
    
    function stake(uint16 tokenId) external onlyOpen{
        _stake(tokenId);
    }
    
    function batchStake(uint16[] calldata tokenIds) external onlyOpen{
        for(uint256 i = 0; i < tokenIds.length; i++){
            _stake(tokenIds[i]);
        }
    }
    
    function _unstake(uint256 tokenId) internal check(tokenId, true) returns(uint192 reward){
        uint192 allReward = getReward(tokenId);
        reward = allReward - stakeInfos[tokenId].claimedReward;
        stakeInfos[tokenId] = StakeInfo(0, uint32(block.timestamp), 0);
    }
    
    function unstake(uint16 tokenId) external{
        rewards[msg.sender] += _unstake(tokenId);
    }
    
    function batchUnstake(uint16[] calldata tokenIds) external{
        uint192 reward;
        for(uint256 i = 0; i < tokenIds.length; i++){
            reward += _unstake(tokenIds[i]);
        }
        rewards[msg.sender] += reward;
    }
    
    function _claimReward(uint256 tokenId) internal check(tokenId, true) returns(uint192 reward){
        uint192 allReward = getReward(tokenId);
        reward = allReward - stakeInfos[tokenId].claimedReward;
        stakeInfos[tokenId].claimedReward = allReward;
    }
    
    function _claim(uint192 reward) internal {
        uint192 amount = reward / 1e18;
        require(amount > 0, "Stake:notEnoughReward");
        rewards[msg.sender] = reward % 1e18;
        rewardNFT.mint(msg.sender, 0, amount, "");
    }
    
    function claim(uint16 tokenId) external{
        uint192 reward = _claimReward(tokenId) + rewards[msg.sender];
        _claim(reward);
    }
    
    function batchClaim(uint16[] calldata tokenIds) external{
        uint192 reward = rewards[msg.sender];
        for(uint256 i = 0; i < tokenIds.length; i++){
            reward += _claimReward(tokenIds[i]);
        }
        _claim(reward);
    }
    
    function getPower(uint16 tokenId) external view returns(uint8){
        return uint8(powers[tokenId]);
    }
    
    function getReward(uint256 stakeTime, uint256 unstakeTime, uint256 power) public view returns(uint192){
        uint256 day = (unstakeTime - stakeTime) / oneday;
        uint256 len = rewardPerDay.length-1;
        uint256 multiple = day < len ? rewardPerDay[day] : rewardPerDay[len-1] + (day-len+1)*rewardPerDay[len];
        return uint192(baseReward*multiple*power/100);
    }
    
    function getReward(uint256 tokenId) public view returns(uint192){
        if(blackTokens[tokenId]) return 0;
        StakeInfo memory stakeInfo = stakeInfos[tokenId];
        if(stakeInfo.stakeTime == 0) return 0;
        return getReward(stakeInfo.stakeTime, block.timestamp, uint8(powers[tokenId]));
    }
    
    function nestingTransfer(uint256 tokenId) external view returns(bool){
        StakeInfo memory stakeInfo = stakeInfos[tokenId];
        return stakeInfo.stakeTime == 0 && (stakeInfo.unstakeTime == 0 || block.timestamp > stakeInfo.unstakeTime + lockTime);
    }
    
    function setStakeOpen(bool enable) external onlyOwner{
        stakeOpen = enable;
    }
    
    function setBaseReward(uint256 _baseReward) external onlyOwner{
        baseReward = _baseReward;
    }
    
    function setRewardPerDay(uint8[] memory _rewardPerDay) external onlyOwner{
        require(_rewardPerDay.length >= 2 && _rewardPerDay[0] == 0, "Stake:invalid rewardPerDay");
        rewardPerDay = _rewardPerDay;
    }
    
    function setPowers(bytes calldata _powers) external onlyOwner{
        powers = _powers;
    }
    
    function setPower(uint16[] calldata indexes, bytes calldata _powers) external onlyOwner{
        require(indexes.length == _powers.length, "Stake:arrayNotMatch");
        for(uint256 i = 0; i < indexes.length; i++){
            powers[indexes[i]] = _powers[i];
        }
    }
    
    function setLockTime(uint32 _lockTime) external onlyOwner{
        lockTime = _lockTime;
    }
    
    function setBlackToken(bool isBlack, uint256[] calldata tokenIds) external onlyOwner{
        for(uint256 i = 0; i < tokenIds.length; i++){
            blackTokens[tokenIds[i]] = isBlack;
        }
    }
    
    function tokenIdsWithStakeInfo(address account, uint256 pageStart, uint256 pageSize) external view returns(uint256 len, uint256[] memory tokenIds, StakeInfo[] memory _stakeInfos, uint192[] memory _totalRewards){
        len = stakeNFT.balanceOf(account);
        uint256 size;
        if(pageStart < len){
            size = len - pageStart;
            if(size > pageSize) size = pageSize;
        }
        tokenIds = new uint256[](size);
        _stakeInfos = new StakeInfo[](size);
        _totalRewards = new uint192[](size);
        for(uint256 i = 0; i < size; i++){
            uint256 tokenId = stakeNFT.tokenOfOwnerByIndex(account, pageStart+i);
            tokenIds[i] = tokenId;
            _stakeInfos[i] = stakeInfos[tokenId];
            _totalRewards[i] = getReward(tokenId);
        }
    }
}
[{"inputs":[{"internalType":"contract IERC721Enumerable","name":"_stakeNFT","type":"address"},{"internalType":"contract IMint","name":"_rewardNFT","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"baseReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16[]","name":"tokenIds","type":"uint16[]"}],"name":"batchClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16[]","name":"tokenIds","type":"uint16[]"}],"name":"batchStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16[]","name":"tokenIds","type":"uint16[]"}],"name":"batchUnstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"blackTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"tokenId","type":"uint16"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"tokenId","type":"uint16"}],"name":"getPower","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"stakeTime","type":"uint256"},{"internalType":"uint256","name":"unstakeTime","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"}],"name":"getReward","outputs":[{"internalType":"uint192","name":"","type":"uint192"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getReward","outputs":[{"internalType":"uint192","name":"","type":"uint192"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockTime","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"nestingTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"powers","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardNFT","outputs":[{"internalType":"contract IMint","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewardPerDay","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewards","outputs":[{"internalType":"uint192","name":"","type":"uint192"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_baseReward","type":"uint256"}],"name":"setBaseReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isBlack","type":"bool"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"setBlackToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_lockTime","type":"uint32"}],"name":"setLockTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16[]","name":"indexes","type":"uint16[]"},{"internalType":"bytes","name":"_powers","type":"bytes"}],"name":"setPower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_powers","type":"bytes"}],"name":"setPowers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8[]","name":"_rewardPerDay","type":"uint8[]"}],"name":"setRewardPerDay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enable","type":"bool"}],"name":"setStakeOpen","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"tokenId","type":"uint16"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakeInfos","outputs":[{"internalType":"uint32","name":"stakeTime","type":"uint32"},{"internalType":"uint32","name":"unstakeTime","type":"uint32"},{"internalType":"uint192","name":"claimedReward","type":"uint192"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakeNFT","outputs":[{"internalType":"contract IERC721Enumerable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakeOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"pageStart","type":"uint256"},{"internalType":"uint256","name":"pageSize","type":"uint256"}],"name":"tokenIdsWithStakeInfo","outputs":[{"internalType":"uint256","name":"len","type":"uint256"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"components":[{"internalType":"uint32","name":"stakeTime","type":"uint32"},{"internalType":"uint32","name":"unstakeTime","type":"uint32"},{"internalType":"uint192","name":"claimedReward","type":"uint192"}],"internalType":"struct Stake.StakeInfo[]","name":"_stakeInfos","type":"tuple[]"},{"internalType":"uint192[]","name":"_totalRewards","type":"uint192[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"tokenId","type":"uint16"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"}]