// Contract: NEST36Update
// Target function: function transferDaoAssets() public onlyOwner
dC34f0718009925c1867cB,
                0x221657776846890989a759BA2973e427DfF5C9bB,
                0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c,
                0x1a23a6BfBAdB59fa563008c0fB7cf96dfCF34Ea1,
                0x57Ab1ec28D129707052df4dF418D58a2D46d5f51,
                0x6B3595068778DD592e39A122f4f5a5cF09C90fE2,
                0x9AFb950948c2370975fb91a441F36FDC02737cD4,
                0x4Fabb145d64652a948d72533023f6E7A623C7C53,
                0x8dAEBADE922dF735c38C80C7eBD708Af50815fAa,
                0x14007c545e6664C8370F27fa6B99DC830e6510a6,
                0xB64ef51C888972c908CFacf59B47C1AfBC0Ab8aC,
                0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC,
                0x0Ae055097C6d159879521C384F1D2123D1f195e6,
                0x2c000c0093dE75a8fA2FccD3d97b314e20b431C3,
                0x3845badAde8e6dFF049820680d1F14bD3903a5d0,
                0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C];
    }

    function _ntokenList() private pure returns (address[TOKEN_COUNT] memory) {
        // ntoken列表
        return [0x04abEdA201850aC0124161F037Efd70c74ddC74C,
                0x1F832091fAf289Ed4f50FE7418cFbD2611225d46,
                0x55B9D8475bd87c4eD47D0C161999EEab4d330C4F,
                0xe5A153bD9270973F9dE557c60D819be7EC62E066,
                0xE4EcBca33c5e29d34263400912157d4ddb26b49d,
                0xA7cB028F4194EaCE616CE6605387a335Ae95ED7f,
                0xEd14feC6fB1a04DD6e04F04A7b5030BB06f86918,
                0x88Eb85C4dB7e955875a990D2488De57F2D524eF0,
                0x017E701B153d63e4eE96f1CdEb6930dBa060CED9,
                0xC4ee960700323AA22D0040A68ce915E1735b7048,
                0x5E17a41c59007abC492dB7C4C65B85eE26dc5Fcd,
                0xC85877048e34edf317fa6C151760CDbbE705c7a4,
                0xb7fF97D631bA9aEeb48a953eD27cC5F6C0C42Be3,
                0x24fCfB935b731C1b312F31324eBBDA7CEbcaC57e,
                0x387f14A4C43Ea1E694CBA3a30638073222ec33b5,
                0x3D4fe58F7A3203c168504fEf624820898Fb56E4B,
                0x75Cb85F01B9436483F3B8f8bcaFB89e07e6B87ff,
                0x10fD3fbE5BE41748be8fd4B514A4219E5F079bbd,
                0x386E91E810ECE2B28C9e36F33B69cD19a63d5603,
                0x60c1386fbD6239e5cb430a984476DF80CC59F177,
                0xF529dcD5dDcD8E15084d6066602a63c776608d37,
                0xC0681693Fb25DB0cA72082aAdc407FBeC84b6F8A,
                0x731cFd398e89573e246A10712F213902839FBB50,
                0x1Ec8b1D7Ad6f53096fE6686313Beef3394D8D73d,
                0x798f8677a322B86A5A9201d00A6C0E69699D6e57,
                0xd0Ecd1c2895F178fF0d461d5fb89CE2b21C8cE31,
                0x1E5922f4EF1c30E0780Dc017A83c5E9b3C26c857,
                0xa1a8aC9E3BfE5E45EF88b09AC6f8694859A0fe9f,
                0x0670eeC3b57ceCD88DA0835A1349212f51B0BC45,
                0x432b009284d36e57A79C8a07a06C44db44213762,
                0xFcc2e387d7caD4B599A69fb160c098028FB7015d,
                0x075190c6130EA0a3A7E40802F1D77F4Ea8f38fE2,
                0xb27B5c073436A6a1D2b08b5aDad0CB72249Ca5a1,
                0x73869e38DEEb35bD39C268F89FFAC2F31ab4aC06,
                0x71DB8019EF642bc79650045b261740705F052fd8,
                0x532e4dC827D0D0d391B731a64F01E76f9F32698a,
                0xc3AdD44372d250d59Ea211C7E13b8B5Ee58eB3bF,
                0x6F3f42EA2c2DB04399F98b93d038f198E933ad08,
                0xE4ebA4a66486c057b0Bc9A85676e4e1d61d37680,
                0xe58645f0416e503FBD362eDBfE3558994048d87B,
                0x4A244Fe3735DDE065E7C3eBF54D389b46cdE457a,
                0x4F417Ed67006e67396C43574a0B1eC1A999aA25B,
                0xd6Dd90DdA11B471434ae1fe580cF7574CbD15336,
                0x60d9Af8F7EA58D2906B01994a8e16D3C16cC390c,
                0x98d3205D307032B26e6dbAA0bFC4C4fe526ad822,
                0xa347DAD4CD014e70165085fbaEa6F9cCa9AE9316,
                0x00DB9600F13f8DC4D003b7fDE4e9587527209b2A,
                0x2cB3766dA1E21bd5b21EcdaEA3c3A879A7c5a410,
                0x8a0F90A072b98E87d31D6e90754B1c0dc3fB34B8,
                0xcA2a63756da62882832E77A5B2EbBAec1Bb019AC,
                0xBc6f3E053D014B1AD89B2918ccb97baE87a1250a,
                0xd7811b4dbe1610fa806f2CBEe98d88aA0FabA985,
                0x18abB1b83F5f50EA668Be64625fbBf1D1ba69a8E,
                0xAd674D7D751c384C10E4DAEE96D2650b88180cfd,
                0xd4d82783D38994ba462730F4098A9c183221Ea5F,
                0x6f92D1e8165658D0C3897F9859615ca73d54F3Cd,
                0x72fBDc8e67b1Cee84332Eadf2F8aD1E02A0Bd768,
                0x8444F4b634b0726166272d5F9A62184b04421C95];
    }

    // 管理员
    address _owner;
    
    constructor() {
        _owner = msg.sender;
    }
    
    // 更新
    function update() public {

        // 1.转移NEST
        transferNest();
        // 2.转移DAO资产
        transferDaoAssets();
        // 3.更新nToken和NN的映射合约
        changeMap();
        // 4.恢复3.5管理员
        setGov35();
    }
    
    // 恢复3.5管理员
    function setGov35() public onlyOwner {
        INestPool(NEST_POOL_ADDRESS).setGovernance(address(_owner));
        INestDAO(NEST_DAO_ADDRESS).loadGovernance();
    }
    
    // 设置ntoken映射-可以提前操作
    function setNToken() public onlyOwner {
        
        address[TOKEN_COUNT] memory tokenList = _tokenList();
        address[TOKEN_COUNT] memory ntokenList = _ntokenList();
        for(uint i = 0; i < TOKEN_COUNT; i++) {
            INTokenController(NTOKEN_CONTROLLER_ADDRESS).setNTokenMapping(tokenList[i], ntokenList[i], 1);
        }
    }
    
    //================================
    
    // 转移NEST
    function transferNest() public onlyOwner {

        // 0. 验证目标地址
        require(INestMining(NEST_MINING_ADDRESS).getAccountCount() == 1, "!NEST_MINING_ADDRESS");

        INestLedger(NEST_LEDGER_ADDRESS).totalETHRewards(NEST_TOKEN_ADDRESS);
        require(INestLedger(NEST_LEDGER_ADDRESS).checkApplication(NEST_REDEEMING_ADDRESS) == 1, "!NEST_LEDGER_ADDRESS");
        
        // 设置NN最新区块
        uint latestMinedHeight = INestMining35(NEST_MINING35_ADDRESS).latestMinedHeight();
        INNIncome(NN_INCOME_ADDRESS).setBlockCursor(latestMinedHeight);
        INNIncome(NN_INCOME_ADDRESS).increment();
        require(INNIncome(NN_INCOME_ADDRESS).getBlockCursor() == latestMinedHeight, "!NN_INCOME_ADDRESS");

        // 1. 从3.5的NestPool取出矿池的nest
        uint nestGov_front = INestPool(NEST_POOL_ADDRESS).getMinerNest(address(this));
        INestPool(NEST_POOL_ADDRESS).drainNest(address(this), nestGov_front, address(this));
        require(IERC20(NEST_TOKEN_ADDRESS).balanceOf(address(this)) == nestGov_front, "!nestGov_front");
        // 管理员nest置空
        INestPool(NEST_POOL_ADDRESS).setGovernance(address(this));
        
        // 2. 80%分给nest挖矿合约 
        uint nestMiningAmount_front = IERC20(NEST_TOKEN_ADDRESS).balanceOf(address(NEST_MINING_ADDRESS));
        uint nestMiningAmount = nestGov_front * 80 / 100;
        require(IERC20(NEST_TOKEN_ADDRESS).transfer(NEST_MINING_ADDRESS, nestMiningAmount), "transfer:nestMiningAmount");
        require(IERC20(NEST_TOKEN_ADDRESS).balanceOf(address(NEST_MINING_ADDRESS)) == nestMiningAmount_front + nestMiningAmount, "!NEST_MINING_ADDRESS");
        
        // 3. 5%分给DAO账本
        uint nestLedgerAmount_front = IERC20(NEST_TOKEN_ADDRESS).balanceOf(address(NEST_LEDGER_ADDRESS));
        uint nestLedgerAmount = nestGov_front * 5 / 100;
        require(IERC20(NEST_TOKEN_ADDRESS).transfer(NEST_LEDGER_ADDRESS, nestLedgerAmount), "transfer:nestLedgerAmount");
        require(IERC20(NEST_TOKEN_ADDRESS).balanceOf(address(NEST_LEDGER_ADDRESS)) == nestLedgerAmount_front + nestLedgerAmount, "!NEST_LEDGER_ADDRESS");

        // 4. 15%分给NN挖矿合约
        uint NNIncomeAmount_front = IERC20(NEST_TOKEN_ADDRESS).balanceOf(address(NN_INCOME_ADDRESS));
        uint NNIncomeAmount = nestGov_front * 15 / 100;
        require(IERC20(NEST_TOKEN_ADDRESS).transfer(NN_INCOME_ADDRESS, NNIncomeAmount), "transfer:NNIncomeAmount");
        require(IERC20(NEST_TOKEN_ADDRESS).balanceOf(address(NN_INCOME_ADDRESS)) == NNIncomeAmount_front + NNIncomeAmount, "!NN_INCOME_ADDRESS");
        
    }