Contract 0x64ac15AB583fFfA6a7401B83E3aA5cf4Ad1aA92A

Contract Overview

Balance:
0 Ether

Token:
Txn Hash
Method
Block
From
To
Value
0x477dc8a652f03d5ae5b3c1f9c4fadf10f07d98fc43ffd2594f9178942039203eMigrate Vesting ...319347282022-06-01 0:04:3634 days 1 hr ago0xfe3068c4c65ec3cb53b3864aa19c19d21df13840 IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.00013297 2.5
0x48a3f5984f7c8e98e8c1fef616bf53ee339fffdbeb9a38a6622b10e595f663b7Migrate Vesting ...307369552022-03-31 0:30:4096 days 1 hr ago0xfe3068c4c65ec3cb53b3864aa19c19d21df13840 IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.00009222 1.73385376
0x9eb4c2f3b2e8391dad67f7ad792fd08e661b68cb89d43e66940cc800ee4f795eMigrate Vesting ...307159682022-03-30 0:29:3297 days 1 hr ago0xfe3068c4c65ec3cb53b3864aa19c19d21df13840 IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.00013297 2.5
0x1ac7a6379e7c50164998710084c58de443d67856829570a925edf8779758ecb4Migrate Vesting ...307159562022-03-30 0:28:4497 days 1 hr ago0xfe3068c4c65ec3cb53b3864aa19c19d21df13840 IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.00007203 2.738019
0x3294594beeba8575157235a2ee84b73808b73254d4e3520ddf327fe2e722a0b3Migrate Vesting ...307159462022-03-30 0:28:0497 days 1 hr ago0xfe3068c4c65ec3cb53b3864aa19c19d21df13840 IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.00014563 2.738019
0xc3eb8e80eed0e4f62af6a442040921751a04e56d24fc96155ea66e127fa9cffbNominate New Own...292665542022-01-15 3:15:20170 days 22 hrs ago0x73570075092502472e4b61a7058df1a4a1db12f2 IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.00004752 1
0x0146a9987569db74eadfb8ce4a0018ad35e13a906ff3770fd7ce20a561f8dc6dMigrate Vesting ...284893212021-11-22 3:52:36224 days 21 hrs ago0xfe3068c4c65ec3cb53b3864aa19c19d21df13840 IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.00007974 1.5
0x049b77733f027c0564d96a6f675ba31afe9281be5044e71a9946eae2138681b5Migrate Vesting ...284892992021-11-22 3:50:24224 days 21 hrs ago0xfe3068c4c65ec3cb53b3864aa19c19d21df13840 IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.00007974 1.5
0x703138be2b127a9cb35580a606fd12797a4f8ae250c9110041e78c40ab70822bMigrate Vesting ...284892882021-11-22 3:49:16224 days 21 hrs ago0xfe3068c4c65ec3cb53b3864aa19c19d21df13840 IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.00007974 1.5
0x086700fdf6a2dbdd9346cc3aafa440b1b0f85c21330c1282b9b80b7dee7f97faMigrate Vesting ...275372082021-10-06 14:59:28271 days 10 hrs ago0xee34e8298e388fabaa0deb85b54f0f64e7aea88c IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.00005316 1
0xf518ce8024c2caab55b6d9a82d2e5cbd0b6f6c7145f2c84f71519722d860890bMigrate Vesting ...275371802021-10-06 14:57:36271 days 10 hrs ago0xee34e8298e388fabaa0deb85b54f0f64e7aea88c IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.00005316 1
0xf933a22828f0fd66fc036274f2cb86a0e06998d6e2c6c724217db81576a26e13Vest261319432021-07-15 1:51:40354 days 23 hrs ago0x205036893e1fe4f620626623592a6c4ab6436d26 IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.0042626242
0xfb9ecf377b9f7786c36edd1d8876f680190a0f5cbe1e0b19a68cef013e93f9a0Create Escrow En...260069132021-07-09 6:51:44360 days 18 hrs ago0xdfebadbc6d06af717ceed15dbed22e6db680bfcb IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.00124776
0x979211251f3b9360166e832db69b6f3f44f987bddeb139a40dc2792e449cd849Vest260068912021-07-09 6:50:16360 days 18 hrs ago0xdfebadbc6d06af717ceed15dbed22e6db680bfcb IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.0033464730
0x7719dae5a6508da2d748cc979b4d69f1afd807e4742f2fae473d9e49c5d5c603Vest260067282021-07-09 6:39:24360 days 18 hrs ago0xdfebadbc6d06af717ceed15dbed22e6db680bfcb IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.0014129130
0x4a15ddf4cf8530bbd74df18db07c51e60392f20b6515ae1ae1105dd91cf6a36bCreate Escrow En...260039802021-07-09 3:36:08360 days 21 hrs ago0xdfebadbc6d06af717ceed15dbed22e6db680bfcb IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.00124776
0x9845a7124eeb5ecee9c0aac577a59db50cb6b62e14c207ddf92616ac3c7d6febVest260039662021-07-09 3:35:12360 days 21 hrs ago0xdfebadbc6d06af717ceed15dbed22e6db680bfcb IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.0031506232
0xd2a9dd2a5218d918c90c20d34749a341f2bd63ee900f6644806dee8f6a9e29d4Create Escrow En...260039422021-07-09 3:33:36360 days 22 hrs ago0xdfebadbc6d06af717ceed15dbed22e6db680bfcb IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.00136856
0x25044bdaa9e31ced45847f2bf246b1e9dff392e8d57aa4eb76a68369a8c99083Create Escrow En...260039182021-07-09 3:32:00360 days 22 hrs ago0xdfebadbc6d06af717ceed15dbed22e6db680bfcb IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.000399616
0x0f083d6de3a5197281e695480b3db0379ffa23199fec765e361a389794ce1983Create Escrow En...260036262021-07-09 3:12:32360 days 22 hrs ago0xdfebadbc6d06af717ceed15dbed22e6db680bfcb IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.000399756
0x7725317768e796f647437d2328f591474606139b5b5a9d15f283e4222d4121efCreate Escrow En...260035992021-07-09 3:10:44360 days 22 hrs ago0xdfebadbc6d06af717ceed15dbed22e6db680bfcb IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.000399616
0x05380cbc48c8e019550eb5df51c1a89a9fe53f624a227fe039be8baba3b05fa1Create Escrow En...260035822021-07-09 3:09:36360 days 22 hrs ago0xdfebadbc6d06af717ceed15dbed22e6db680bfcb IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.000399686
0x757b890c5708c0069f950196ac524b5e1ac52bb1ad4a7154609336f31a2bb012Create Escrow En...260035662021-07-09 3:08:32360 days 22 hrs ago0xdfebadbc6d06af717ceed15dbed22e6db680bfcb IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.000399686
0x517bf1190614d67df29a86d8d939e85b453a1bea860a292c2513082154c36204Create Escrow En...260034492021-07-09 3:00:44360 days 22 hrs ago0xdfebadbc6d06af717ceed15dbed22e6db680bfcb IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.000399546
0x80bca70a2c72dcaa97c795a59525043d595db9fe3550c890e9effb99ca022ee2Create Escrow En...260034282021-07-09 2:59:20360 days 22 hrs ago0xdfebadbc6d06af717ceed15dbed22e6db680bfcb IN  0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether0.000399256
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x297a498e9fe1fbaef79be0fbd42d304c380f4b8e72f47458d754f157c702596f323440892022-06-24 1:30:3611 days 3 mins ago 0x61c427e53c8eaf052b6bf590f7e6cba3ee2fdec7 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether
0x4c13eb1e62d2ca1e73a5920adba98081b98ed99553b047adcf373503898c9cd7323423422022-06-23 23:00:3611 days 2 hrs ago 0x61c427e53c8eaf052b6bf590f7e6cba3ee2fdec7 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether
0x23f5d6be731cf522f9d992e391332b4e2f82c4bef4f5c420527f6aad7d9bf191323423282022-06-23 22:59:2411 days 2 hrs ago 0x61c427e53c8eaf052b6bf590f7e6cba3ee2fdec7 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether
0x1e4c1d25882534c52ffde65701318a0a1d7b1060d967a225f6698ffa5c97b27c323422672022-06-23 22:54:0011 days 2 hrs ago 0x61c427e53c8eaf052b6bf590f7e6cba3ee2fdec7 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether
0x2cc91d3dc5e9a0d7900b034dc0a521ea614e280fcec7f48be157b31ce57adde3323422072022-06-23 22:48:3211 days 2 hrs ago 0x61c427e53c8eaf052b6bf590f7e6cba3ee2fdec7 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether
0xc03b183c2b510c76dd47cff4ab517c8d1bdeafb0af1caacb253adf9f94926f0d323421842022-06-23 22:46:4011 days 2 hrs ago 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a 0x6377ed477e80df86e111593d67ba184d9a9c8ae30 Ether
0xc03b183c2b510c76dd47cff4ab517c8d1bdeafb0af1caacb253adf9f94926f0d323421842022-06-23 22:46:4011 days 2 hrs ago 0x42b340961496731b0c4337e2a600087a2368dfcf 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether
0xc03b183c2b510c76dd47cff4ab517c8d1bdeafb0af1caacb253adf9f94926f0d323421842022-06-23 22:46:4011 days 2 hrs ago 0x61c427e53c8eaf052b6bf590f7e6cba3ee2fdec7 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether
0xec56411232928c69f84a4ff45cb4d7ed91cf2c35b7013572914a24115dbef297323345572022-06-23 12:27:2411 days 13 hrs ago 0x61c427e53c8eaf052b6bf590f7e6cba3ee2fdec7 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether
0x64686a954b3aa1ee4bd7d451fa7c2c8e45fc3367924a2cf11f9b8934aa23087d323293642022-06-23 6:05:4011 days 19 hrs ago 0x61c427e53c8eaf052b6bf590f7e6cba3ee2fdec7 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether
0xfaea452a030137aa6112434cc66875a82460b51bb5b8ae71ea8853b5caa3f471323239932022-06-22 22:44:0012 days 2 hrs ago 0x61c427e53c8eaf052b6bf590f7e6cba3ee2fdec7 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether
0x84cee51b761c77bdca37119cd9fd893240a81a6e9695dfcdd8db39a8d11862b7323239352022-06-22 22:38:4812 days 2 hrs ago 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a 0x6377ed477e80df86e111593d67ba184d9a9c8ae30 Ether
0x84cee51b761c77bdca37119cd9fd893240a81a6e9695dfcdd8db39a8d11862b7323239352022-06-22 22:38:4812 days 2 hrs ago 0x42b340961496731b0c4337e2a600087a2368dfcf 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether
0x84cee51b761c77bdca37119cd9fd893240a81a6e9695dfcdd8db39a8d11862b7323239352022-06-22 22:38:4812 days 2 hrs ago 0x61c427e53c8eaf052b6bf590f7e6cba3ee2fdec7 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether
0x6bf099377e7de48e1f5eeb89ead3e713d986d27ab945bb89e0cadb7a345acd62323238572022-06-22 22:32:0012 days 3 hrs ago 0x61c427e53c8eaf052b6bf590f7e6cba3ee2fdec7 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether
0xe8d1d13df510b781f735e234bc37235ed4e1e82626a174c0deb1ffb8f35d45b6323199542022-06-22 17:13:2812 days 8 hrs ago 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a 0x242a3df52c375bee81b1c668741d7c63af68fdd20 Ether
0xe8d1d13df510b781f735e234bc37235ed4e1e82626a174c0deb1ffb8f35d45b6323199542022-06-22 17:13:2812 days 8 hrs ago 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a 0x242a3df52c375bee81b1c668741d7c63af68fdd20 Ether
0xe8d1d13df510b781f735e234bc37235ed4e1e82626a174c0deb1ffb8f35d45b6323199542022-06-22 17:13:2812 days 8 hrs ago 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a 0x242a3df52c375bee81b1c668741d7c63af68fdd20 Ether
0xe8d1d13df510b781f735e234bc37235ed4e1e82626a174c0deb1ffb8f35d45b6323199542022-06-22 17:13:2812 days 8 hrs ago 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a 0x242a3df52c375bee81b1c668741d7c63af68fdd20 Ether
0xe8d1d13df510b781f735e234bc37235ed4e1e82626a174c0deb1ffb8f35d45b6323199542022-06-22 17:13:2812 days 8 hrs ago 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a 0x242a3df52c375bee81b1c668741d7c63af68fdd20 Ether
0xe8d1d13df510b781f735e234bc37235ed4e1e82626a174c0deb1ffb8f35d45b6323199542022-06-22 17:13:2812 days 8 hrs ago 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a 0x242a3df52c375bee81b1c668741d7c63af68fdd20 Ether
0xe8d1d13df510b781f735e234bc37235ed4e1e82626a174c0deb1ffb8f35d45b6323199542022-06-22 17:13:2812 days 8 hrs ago 0x84f87e3636aa9cc1080c07e6c61adfdcc23c0db6 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether
0x38b7d72628f4bf565420d368fe5e7b6c83dab72747dc5f8707c1c60df49bcacb322728142022-06-20 3:18:2414 days 22 hrs ago 0xb5741f2887e52af151e8d2fe8a3046179bc57dbb 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether
0xcdf6377164960a4f1fb677776ecfe1e563f6a86d7635c1e3a39bac4ae6de3b70322246262022-06-17 5:16:4017 days 20 hrs ago 0xb5741f2887e52af151e8d2fe8a3046179bc57dbb 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether
0x463660ba709c7b9fafa1cab590417e9ca6d5fe193ded01dbb483141473696f00322068472022-06-16 6:50:5618 days 18 hrs ago 0xb5741f2887e52af151e8d2fe8a3046179bc57dbb 0x64ac15ab583fffa6a7401b83e3aa5cf4ad1aa92a0 Ether
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
RewardEscrowV2

Compiler Version
v0.5.16+commit.9c3226ce

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-01-14
*/

/*
   ____            __   __        __   _
  / __/__ __ ___  / /_ / /  ___  / /_ (_)__ __
 _\ \ / // // _ \/ __// _ \/ -_)/ __// / \ \ /
/___/ \_, //_//_/\__//_//_/\__/ \__//_/ /_\_\
     /___/

* Synthetix: RewardEscrowV2.sol
*
* Latest source (may be newer): https://github.com/Synthetixio/synthetix/blob/master/contracts/RewardEscrowV2.sol
* Docs: https://docs.synthetix.io/contracts/RewardEscrowV2
*
* Contract Dependencies: 
*	- BaseRewardEscrowV2
*	- IAddressResolver
*	- Owned
* Libraries: 
*	- SafeDecimalMath
*	- SafeMath
*	- VestingEntries
*
* MIT License
* ===========
*
* Copyright (c) 2021 Synthetix
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
*/



pragma solidity ^0.5.16;


// https://docs.synthetix.io/contracts/source/contracts/owned
contract Owned {
    address public owner;
    address public nominatedOwner;

    constructor(address _owner) public {
        require(_owner != address(0), "Owner address cannot be 0");
        owner = _owner;
        emit OwnerChanged(address(0), _owner);
    }

    function nominateNewOwner(address _owner) external onlyOwner {
        nominatedOwner = _owner;
        emit OwnerNominated(_owner);
    }

    function acceptOwnership() external {
        require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership");
        emit OwnerChanged(owner, nominatedOwner);
        owner = nominatedOwner;
        nominatedOwner = address(0);
    }

    modifier onlyOwner {
        _onlyOwner();
        _;
    }

    function _onlyOwner() private view {
        require(msg.sender == owner, "Only the contract owner may perform this action");
    }

    event OwnerNominated(address newOwner);
    event OwnerChanged(address oldOwner, address newOwner);
}


// https://docs.synthetix.io/contracts/source/interfaces/iaddressresolver
interface IAddressResolver {
    function getAddress(bytes32 name) external view returns (address);

    function getSynth(bytes32 key) external view returns (address);

    function requireAndGetAddress(bytes32 name, string calldata reason) external view returns (address);
}


// https://docs.synthetix.io/contracts/source/interfaces/isynth
interface ISynth {
    // Views
    function currencyKey() external view returns (bytes32);

    function transferableSynths(address account) external view returns (uint);

    // Mutative functions
    function transferAndSettle(address to, uint value) external returns (bool);

    function transferFromAndSettle(
        address from,
        address to,
        uint value
    ) external returns (bool);

    // Restricted: used internally to Synthetix
    function burn(address account, uint amount) external;

    function issue(address account, uint amount) external;
}


// https://docs.synthetix.io/contracts/source/interfaces/iissuer
interface IIssuer {
    // Views
    function anySynthOrSNXRateIsInvalid() external view returns (bool anyRateInvalid);

    function availableCurrencyKeys() external view returns (bytes32[] memory);

    function availableSynthCount() external view returns (uint);

    function availableSynths(uint index) external view returns (ISynth);

    function canBurnSynths(address account) external view returns (bool);

    function collateral(address account) external view returns (uint);

    function collateralisationRatio(address issuer) external view returns (uint);

    function collateralisationRatioAndAnyRatesInvalid(address _issuer)
        external
        view
        returns (uint cratio, bool anyRateIsInvalid);

    function debtBalanceOf(address issuer, bytes32 currencyKey) external view returns (uint debtBalance);

    function issuanceRatio() external view returns (uint);

    function lastIssueEvent(address account) external view returns (uint);

    function maxIssuableSynths(address issuer) external view returns (uint maxIssuable);

    function minimumStakeTime() external view returns (uint);

    function remainingIssuableSynths(address issuer)
        external
        view
        returns (
            uint maxIssuable,
            uint alreadyIssued,
            uint totalSystemDebt
        );

    function synths(bytes32 currencyKey) external view returns (ISynth);

    function getSynths(bytes32[] calldata currencyKeys) external view returns (ISynth[] memory);

    function synthsByAddress(address synthAddress) external view returns (bytes32);

    function totalIssuedSynths(bytes32 currencyKey, bool excludeEtherCollateral) external view returns (uint);

    function transferableSynthetixAndAnyRateIsInvalid(address account, uint balance)
        external
        view
        returns (uint transferable, bool anyRateIsInvalid);

    // Restricted: used internally to Synthetix
    function issueSynths(address from, uint amount) external;

    function issueSynthsOnBehalf(
        address issueFor,
        address from,
        uint amount
    ) external;

    function issueMaxSynths(address from) external;

    function issueMaxSynthsOnBehalf(address issueFor, address from) external;

    function burnSynths(address from, uint amount) external;

    function burnSynthsOnBehalf(
        address burnForAddress,
        address from,
        uint amount
    ) external;

    function burnSynthsToTarget(address from) external;

    function burnSynthsToTargetOnBehalf(address burnForAddress, address from) external;

    function liquidateDelinquentAccount(
        address account,
        uint susdAmount,
        address liquidator
    ) external returns (uint totalRedeemed, uint amountToLiquidate);
}


// Inheritance


// Internal references


// https://docs.synthetix.io/contracts/source/contracts/addressresolver
contract AddressResolver is Owned, IAddressResolver {
    mapping(bytes32 => address) public repository;

    constructor(address _owner) public Owned(_owner) {}

    /* ========== RESTRICTED FUNCTIONS ========== */

    function importAddresses(bytes32[] calldata names, address[] calldata destinations) external onlyOwner {
        require(names.length == destinations.length, "Input lengths must match");

        for (uint i = 0; i < names.length; i++) {
            bytes32 name = names[i];
            address destination = destinations[i];
            repository[name] = destination;
            emit AddressImported(name, destination);
        }
    }

    /* ========= PUBLIC FUNCTIONS ========== */

    function rebuildCaches(MixinResolver[] calldata destinations) external {
        for (uint i = 0; i < destinations.length; i++) {
            destinations[i].rebuildCache();
        }
    }

    /* ========== VIEWS ========== */

    function areAddressesImported(bytes32[] calldata names, address[] calldata destinations) external view returns (bool) {
        for (uint i = 0; i < names.length; i++) {
            if (repository[names[i]] != destinations[i]) {
                return false;
            }
        }
        return true;
    }

    function getAddress(bytes32 name) external view returns (address) {
        return repository[name];
    }

    function requireAndGetAddress(bytes32 name, string calldata reason) external view returns (address) {
        address _foundAddress = repository[name];
        require(_foundAddress != address(0), reason);
        return _foundAddress;
    }

    function getSynth(bytes32 key) external view returns (address) {
        IIssuer issuer = IIssuer(repository["Issuer"]);
        require(address(issuer) != address(0), "Cannot find Issuer address");
        return address(issuer.synths(key));
    }

    /* ========== EVENTS ========== */

    event AddressImported(bytes32 name, address destination);
}


// solhint-disable payable-fallback

// https://docs.synthetix.io/contracts/source/contracts/readproxy
contract ReadProxy is Owned {
    address public target;

    constructor(address _owner) public Owned(_owner) {}

    function setTarget(address _target) external onlyOwner {
        target = _target;
        emit TargetUpdated(target);
    }

    function() external {
        // The basics of a proxy read call
        // Note that msg.sender in the underlying will always be the address of this contract.
        assembly {
            calldatacopy(0, 0, calldatasize)

            // Use of staticcall - this will revert if the underlying function mutates state
            let result := staticcall(gas, sload(target_slot), 0, calldatasize, 0, 0)
            returndatacopy(0, 0, returndatasize)

            if iszero(result) {
                revert(0, returndatasize)
            }
            return(0, returndatasize)
        }
    }

    event TargetUpdated(address newTarget);
}


// Inheritance


// Internal references


// https://docs.synthetix.io/contracts/source/contracts/mixinresolver
contract MixinResolver {
    AddressResolver public resolver;

    mapping(bytes32 => address) private addressCache;

    constructor(address _resolver) internal {
        resolver = AddressResolver(_resolver);
    }

    /* ========== INTERNAL FUNCTIONS ========== */

    function combineArrays(bytes32[] memory first, bytes32[] memory second)
        internal
        pure
        returns (bytes32[] memory combination)
    {
        combination = new bytes32[](first.length + second.length);

        for (uint i = 0; i < first.length; i++) {
            combination[i] = first[i];
        }

        for (uint j = 0; j < second.length; j++) {
            combination[first.length + j] = second[j];
        }
    }

    /* ========== PUBLIC FUNCTIONS ========== */

    // Note: this function is public not external in order for it to be overridden and invoked via super in subclasses
    function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {}

    function rebuildCache() public {
        bytes32[] memory requiredAddresses = resolverAddressesRequired();
        // The resolver must call this function whenver it updates its state
        for (uint i = 0; i < requiredAddresses.length; i++) {
            bytes32 name = requiredAddresses[i];
            // Note: can only be invoked once the resolver has all the targets needed added
            address destination = resolver.requireAndGetAddress(
                name,
                string(abi.encodePacked("Resolver missing target: ", name))
            );
            addressCache[name] = destination;
            emit CacheUpdated(name, destination);
        }
    }

    /* ========== VIEWS ========== */

    function isResolverCached() external view returns (bool) {
        bytes32[] memory requiredAddresses = resolverAddressesRequired();
        for (uint i = 0; i < requiredAddresses.length; i++) {
            bytes32 name = requiredAddresses[i];
            // false if our cache is invalid or if the resolver doesn't have the required address
            if (resolver.getAddress(name) != addressCache[name] || addressCache[name] == address(0)) {
                return false;
            }
        }

        return true;
    }

    /* ========== INTERNAL FUNCTIONS ========== */

    function requireAndGetAddress(bytes32 name) internal view returns (address) {
        address _foundAddress = addressCache[name];
        require(_foundAddress != address(0), string(abi.encodePacked("Missing address: ", name)));
        return _foundAddress;
    }

    /* ========== EVENTS ========== */

    event CacheUpdated(bytes32 name, address destination);
}


// https://docs.synthetix.io/contracts/source/contracts/limitedsetup
contract LimitedSetup {
    uint public setupExpiryTime;

    /**
     * @dev LimitedSetup Constructor.
     * @param setupDuration The time the setup period will last for.
     */
    constructor(uint setupDuration) internal {
        setupExpiryTime = now + setupDuration;
    }

    modifier onlyDuringSetup {
        require(now < setupExpiryTime, "Can only perform this action during setup");
        _;
    }
}


pragma experimental ABIEncoderV2;


library VestingEntries {
    struct VestingEntry {
        uint64 endTime;
        uint256 escrowAmount;
    }
    struct VestingEntryWithID {
        uint64 endTime;
        uint256 escrowAmount;
        uint256 entryID;
    }
}


interface IRewardEscrowV2 {
    // Views
    function balanceOf(address account) external view returns (uint);

    function numVestingEntries(address account) external view returns (uint);

    function totalEscrowedAccountBalance(address account) external view returns (uint);

    function totalVestedAccountBalance(address account) external view returns (uint);

    function getVestingQuantity(address account, uint256[] calldata entryIDs) external view returns (uint);

    function getVestingSchedules(
        address account,
        uint256 index,
        uint256 pageSize
    ) external view returns (VestingEntries.VestingEntryWithID[] memory);

    function getAccountVestingEntryIDs(
        address account,
        uint256 index,
        uint256 pageSize
    ) external view returns (uint256[] memory);

    function getVestingEntryClaimable(address account, uint256 entryID) external view returns (uint);

    function getVestingEntry(address account, uint256 entryID) external view returns (uint64, uint256);

    // Mutative functions
    function vest(uint256[] calldata entryIDs) external;

    function createEscrowEntry(
        address beneficiary,
        uint256 deposit,
        uint256 duration
    ) external;

    function appendVestingEntry(
        address account,
        uint256 quantity,
        uint256 duration
    ) external;

    function migrateVestingSchedule(address _addressToMigrate) external;

    function migrateAccountEscrowBalances(
        address[] calldata accounts,
        uint256[] calldata escrowBalances,
        uint256[] calldata vestedBalances
    ) external;

    // Account Merging
    function startMergingWindow() external;

    function mergeAccount(address accountToMerge, uint256[] calldata entryIDs) external;

    function nominateAccountToMerge(address account) external;

    function accountMergingIsOpen() external view returns (bool);

    // L2 Migration
    function importVestingEntries(
        address account,
        uint256 escrowedAmount,
        VestingEntries.VestingEntry[] calldata vestingEntries
    ) external;

    // Return amount of SNX transfered to SynthetixBridgeToOptimism deposit contract
    function burnForMigration(address account, uint256[] calldata entryIDs)
        external
        returns (uint256 escrowedAccountBalance, VestingEntries.VestingEntry[] memory vestingEntries);
}


/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, "SafeMath: division by zero");
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0, "SafeMath: modulo by zero");
        return a % b;
    }
}


// Libraries


// https://docs.synthetix.io/contracts/source/libraries/safedecimalmath
library SafeDecimalMath {
    using SafeMath for uint;

    /* Number of decimal places in the representations. */
    uint8 public constant decimals = 18;
    uint8 public constant highPrecisionDecimals = 27;

    /* The number representing 1.0. */
    uint public constant UNIT = 10**uint(decimals);

    /* The number representing 1.0 for higher fidelity numbers. */
    uint public constant PRECISE_UNIT = 10**uint(highPrecisionDecimals);
    uint private constant UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR = 10**uint(highPrecisionDecimals - decimals);

    /**
     * @return Provides an interface to UNIT.
     */
    function unit() external pure returns (uint) {
        return UNIT;
    }

    /**
     * @return Provides an interface to PRECISE_UNIT.
     */
    function preciseUnit() external pure returns (uint) {
        return PRECISE_UNIT;
    }

    /**
     * @return The result of multiplying x and y, interpreting the operands as fixed-point
     * decimals.
     *
     * @dev A unit factor is divided out after the product of x and y is evaluated,
     * so that product must be less than 2**256. As this is an integer division,
     * the internal division always rounds down. This helps save on gas. Rounding
     * is more expensive on gas.
     */
    function multiplyDecimal(uint x, uint y) internal pure returns (uint) {
        /* Divide by UNIT to remove the extra factor introduced by the product. */
        return x.mul(y) / UNIT;
    }

    /**
     * @return The result of safely multiplying x and y, interpreting the operands
     * as fixed-point decimals of the specified precision unit.
     *
     * @dev The operands should be in the form of a the specified unit factor which will be
     * divided out after the product of x and y is evaluated, so that product must be
     * less than 2**256.
     *
     * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
     * Rounding is useful when you need to retain fidelity for small decimal numbers
     * (eg. small fractions or percentages).
     */
    function _multiplyDecimalRound(
        uint x,
        uint y,
        uint precisionUnit
    ) private pure returns (uint) {
        /* Divide by UNIT to remove the extra factor introduced by the product. */
        uint quotientTimesTen = x.mul(y) / (precisionUnit / 10);

        if (quotientTimesTen % 10 >= 5) {
            quotientTimesTen += 10;
        }

        return quotientTimesTen / 10;
    }

    /**
     * @return The result of safely multiplying x and y, interpreting the operands
     * as fixed-point decimals of a precise unit.
     *
     * @dev The operands should be in the precise unit factor which will be
     * divided out after the product of x and y is evaluated, so that product must be
     * less than 2**256.
     *
     * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
     * Rounding is useful when you need to retain fidelity for small decimal numbers
     * (eg. small fractions or percentages).
     */
    function multiplyDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) {
        return _multiplyDecimalRound(x, y, PRECISE_UNIT);
    }

    /**
     * @return The result of safely multiplying x and y, interpreting the operands
     * as fixed-point decimals of a standard unit.
     *
     * @dev The operands should be in the standard unit factor which will be
     * divided out after the product of x and y is evaluated, so that product must be
     * less than 2**256.
     *
     * Unlike multiplyDecimal, this function rounds the result to the nearest increment.
     * Rounding is useful when you need to retain fidelity for small decimal numbers
     * (eg. small fractions or percentages).
     */
    function multiplyDecimalRound(uint x, uint y) internal pure returns (uint) {
        return _multiplyDecimalRound(x, y, UNIT);
    }

    /**
     * @return The result of safely dividing x and y. The return value is a high
     * precision decimal.
     *
     * @dev y is divided after the product of x and the standard precision unit
     * is evaluated, so the product of x and UNIT must be less than 2**256. As
     * this is an integer division, the result is always rounded down.
     * This helps save on gas. Rounding is more expensive on gas.
     */
    function divideDecimal(uint x, uint y) internal pure returns (uint) {
        /* Reintroduce the UNIT factor that will be divided out by y. */
        return x.mul(UNIT).div(y);
    }

    /**
     * @return The result of safely dividing x and y. The return value is as a rounded
     * decimal in the precision unit specified in the parameter.
     *
     * @dev y is divided after the product of x and the specified precision unit
     * is evaluated, so the product of x and the specified precision unit must
     * be less than 2**256. The result is rounded to the nearest increment.
     */
    function _divideDecimalRound(
        uint x,
        uint y,
        uint precisionUnit
    ) private pure returns (uint) {
        uint resultTimesTen = x.mul(precisionUnit * 10).div(y);

        if (resultTimesTen % 10 >= 5) {
            resultTimesTen += 10;
        }

        return resultTimesTen / 10;
    }

    /**
     * @return The result of safely dividing x and y. The return value is as a rounded
     * standard precision decimal.
     *
     * @dev y is divided after the product of x and the standard precision unit
     * is evaluated, so the product of x and the standard precision unit must
     * be less than 2**256. The result is rounded to the nearest increment.
     */
    function divideDecimalRound(uint x, uint y) internal pure returns (uint) {
        return _divideDecimalRound(x, y, UNIT);
    }

    /**
     * @return The result of safely dividing x and y. The return value is as a rounded
     * high precision decimal.
     *
     * @dev y is divided after the product of x and the high precision unit
     * is evaluated, so the product of x and the high precision unit must
     * be less than 2**256. The result is rounded to the nearest increment.
     */
    function divideDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) {
        return _divideDecimalRound(x, y, PRECISE_UNIT);
    }

    /**
     * @dev Convert a standard decimal representation to a high precision one.
     */
    function decimalToPreciseDecimal(uint i) internal pure returns (uint) {
        return i.mul(UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR);
    }

    /**
     * @dev Convert a high precision decimal to a standard decimal representation.
     */
    function preciseDecimalToDecimal(uint i) internal pure returns (uint) {
        uint quotientTimesTen = i / (UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR / 10);

        if (quotientTimesTen % 10 >= 5) {
            quotientTimesTen += 10;
        }

        return quotientTimesTen / 10;
    }
}


// https://docs.synthetix.io/contracts/source/interfaces/ierc20
interface IERC20 {
    // ERC20 Optional Views
    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);

    // Views
    function totalSupply() external view returns (uint);

    function balanceOf(address owner) external view returns (uint);

    function allowance(address owner, address spender) external view returns (uint);

    // Mutative functions
    function transfer(address to, uint value) external returns (bool);

    function approve(address spender, uint value) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint value
    ) external returns (bool);

    // Events
    event Transfer(address indexed from, address indexed to, uint value);

    event Approval(address indexed owner, address indexed spender, uint value);
}


// https://docs.synthetix.io/contracts/source/interfaces/ifeepool
interface IFeePool {
    // Views

    // solhint-disable-next-line func-name-mixedcase
    function FEE_ADDRESS() external view returns (address);

    function feesAvailable(address account) external view returns (uint, uint);

    function feePeriodDuration() external view returns (uint);

    function isFeesClaimable(address account) external view returns (bool);

    function targetThreshold() external view returns (uint);

    function totalFeesAvailable() external view returns (uint);

    function totalRewardsAvailable() external view returns (uint);

    // Mutative Functions
    function claimFees() external returns (bool);

    function claimOnBehalf(address claimingForAddress) external returns (bool);

    function closeCurrentFeePeriod() external;

    // Restricted: used internally to Synthetix
    function appendAccountIssuanceRecord(
        address account,
        uint lockedAmount,
        uint debtEntryIndex
    ) external;

    function recordFeePaid(uint sUSDAmount) external;

    function setRewardsToDistribute(uint amount) external;
}


interface IVirtualSynth {
    // Views
    function balanceOfUnderlying(address account) external view returns (uint);

    function rate() external view returns (uint);

    function readyToSettle() external view returns (bool);

    function secsLeftInWaitingPeriod() external view returns (uint);

    function settled() external view returns (bool);

    function synth() external view returns (ISynth);

    // Mutative functions
    function settle(address account) external;
}


// https://docs.synthetix.io/contracts/source/interfaces/isynthetix
interface ISynthetix {
    // Views
    function anySynthOrSNXRateIsInvalid() external view returns (bool anyRateInvalid);

    function availableCurrencyKeys() external view returns (bytes32[] memory);

    function availableSynthCount() external view returns (uint);

    function availableSynths(uint index) external view returns (ISynth);

    function collateral(address account) external view returns (uint);

    function collateralisationRatio(address issuer) external view returns (uint);

    function debtBalanceOf(address issuer, bytes32 currencyKey) external view returns (uint);

    function isWaitingPeriod(bytes32 currencyKey) external view returns (bool);

    function maxIssuableSynths(address issuer) external view returns (uint maxIssuable);

    function remainingIssuableSynths(address issuer)
        external
        view
        returns (
            uint maxIssuable,
            uint alreadyIssued,
            uint totalSystemDebt
        );

    function synths(bytes32 currencyKey) external view returns (ISynth);

    function synthsByAddress(address synthAddress) external view returns (bytes32);

    function totalIssuedSynths(bytes32 currencyKey) external view returns (uint);

    function totalIssuedSynthsExcludeEtherCollateral(bytes32 currencyKey) external view returns (uint);

    function transferableSynthetix(address account) external view returns (uint transferable);

    // Mutative Functions
    function burnSynths(uint amount) external;

    function burnSynthsOnBehalf(address burnForAddress, uint amount) external;

    function burnSynthsToTarget() external;

    function burnSynthsToTargetOnBehalf(address burnForAddress) external;

    function exchange(
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey
    ) external returns (uint amountReceived);

    function exchangeOnBehalf(
        address exchangeForAddress,
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey
    ) external returns (uint amountReceived);

    function exchangeWithTracking(
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey,
        address originator,
        bytes32 trackingCode
    ) external returns (uint amountReceived);

    function exchangeOnBehalfWithTracking(
        address exchangeForAddress,
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey,
        address originator,
        bytes32 trackingCode
    ) external returns (uint amountReceived);

    function exchangeWithVirtual(
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey,
        bytes32 trackingCode
    ) external returns (uint amountReceived, IVirtualSynth vSynth);

    function issueMaxSynths() external;

    function issueMaxSynthsOnBehalf(address issueForAddress) external;

    function issueSynths(uint amount) external;

    function issueSynthsOnBehalf(address issueForAddress, uint amount) external;

    function mint() external returns (bool);

    function settle(bytes32 currencyKey)
        external
        returns (
            uint reclaimed,
            uint refunded,
            uint numEntries
        );

    // Liquidations
    function liquidateDelinquentAccount(address account, uint susdAmount) external returns (bool);

    // Restricted Functions

    function mintSecondary(address account, uint amount) external;

    function mintSecondaryRewards(uint amount) external;

    function burnSecondary(address account, uint amount) external;
}


// Inheritance


// Libraries


// Internal references


// https://docs.synthetix.io/contracts/RewardEscrow
contract BaseRewardEscrowV2 is Owned, IRewardEscrowV2, LimitedSetup(4 weeks), MixinResolver {
    using SafeMath for uint;
    using SafeDecimalMath for uint;

    mapping(address => mapping(uint256 => VestingEntries.VestingEntry)) public vestingSchedules;

    mapping(address => uint256[]) public accountVestingEntryIDs;

    /*Counter for new vesting entry ids. */
    uint256 public nextEntryId;

    /* An account's total escrowed synthetix balance to save recomputing this for fee extraction purposes. */
    mapping(address => uint256) public totalEscrowedAccountBalance;

    /* An account's total vested reward synthetix. */
    mapping(address => uint256) public totalVestedAccountBalance;

    /* Mapping of nominated address to recieve account merging */
    mapping(address => address) public nominatedReceiver;

    /* The total remaining escrowed balance, for verifying the actual synthetix balance of this contract against. */
    uint256 public totalEscrowedBalance;

    /* Max escrow duration */
    uint public max_duration = 2 * 52 weeks; // Default max 2 years duration

    /* Max account merging duration */
    uint public maxAccountMergingDuration = 4 weeks; // Default 4 weeks is max

    /* ========== ACCOUNT MERGING CONFIGURATION ========== */

    uint public accountMergingDuration = 1 weeks;

    uint public accountMergingStartTime;

    /* ========== ADDRESS RESOLVER CONFIGURATION ========== */

    bytes32 private constant CONTRACT_SYNTHETIX = "Synthetix";
    bytes32 private constant CONTRACT_ISSUER = "Issuer";
    bytes32 private constant CONTRACT_FEEPOOL = "FeePool";

    /* ========== CONSTRUCTOR ========== */

    constructor(address _owner, address _resolver) public Owned(_owner) MixinResolver(_resolver) {
        nextEntryId = 1;
    }

    /* ========== VIEWS ======================= */

    function feePool() internal view returns (IFeePool) {
        return IFeePool(requireAndGetAddress(CONTRACT_FEEPOOL));
    }

    function synthetix() internal view returns (ISynthetix) {
        return ISynthetix(requireAndGetAddress(CONTRACT_SYNTHETIX));
    }

    function issuer() internal view returns (IIssuer) {
        return IIssuer(requireAndGetAddress(CONTRACT_ISSUER));
    }

    function _notImplemented() internal pure {
        revert("Cannot be run on this layer");
    }

    /* ========== VIEW FUNCTIONS ========== */

    // Note: use public visibility so that it can be invoked in a subclass
    function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
        addresses = new bytes32[](3);
        addresses[0] = CONTRACT_SYNTHETIX;
        addresses[1] = CONTRACT_FEEPOOL;
        addresses[2] = CONTRACT_ISSUER;
    }

    /**
     * @notice A simple alias to totalEscrowedAccountBalance: provides ERC20 balance integration.
     */
    function balanceOf(address account) public view returns (uint) {
        return totalEscrowedAccountBalance[account];
    }

    /**
     * @notice The number of vesting dates in an account's schedule.
     */
    function numVestingEntries(address account) external view returns (uint) {
        return accountVestingEntryIDs[account].length;
    }

    /**
     * @notice Get a particular schedule entry for an account.
     * @return The vesting entry object and rate per second emission.
     */
    function getVestingEntry(address account, uint256 entryID) external view returns (uint64 endTime, uint256 escrowAmount) {
        endTime = vestingSchedules[account][entryID].endTime;
        escrowAmount = vestingSchedules[account][entryID].escrowAmount;
    }

    function getVestingSchedules(
        address account,
        uint256 index,
        uint256 pageSize
    ) external view returns (VestingEntries.VestingEntryWithID[] memory) {
        uint256 endIndex = index + pageSize;

        // If index starts after the endIndex return no results
        if (endIndex <= index) {
            return new VestingEntries.VestingEntryWithID[](0);
        }

        // If the page extends past the end of the accountVestingEntryIDs, truncate it.
        if (endIndex > accountVestingEntryIDs[account].length) {
            endIndex = accountVestingEntryIDs[account].length;
        }

        uint256 n = endIndex - index;
        VestingEntries.VestingEntryWithID[] memory vestingEntries = new VestingEntries.VestingEntryWithID[](n);
        for (uint256 i; i < n; i++) {
            uint256 entryID = accountVestingEntryIDs[account][i + index];

            VestingEntries.VestingEntry memory entry = vestingSchedules[account][entryID];

            vestingEntries[i] = VestingEntries.VestingEntryWithID({
                endTime: uint64(entry.endTime),
                escrowAmount: entry.escrowAmount,
                entryID: entryID
            });
        }
        return vestingEntries;
    }

    function getAccountVestingEntryIDs(
        address account,
        uint256 index,
        uint256 pageSize
    ) external view returns (uint256[] memory) {
        uint256 endIndex = index + pageSize;

        // If the page extends past the end of the accountVestingEntryIDs, truncate it.
        if (endIndex > accountVestingEntryIDs[account].length) {
            endIndex = accountVestingEntryIDs[account].length;
        }
        if (endIndex <= index) {
            return new uint256[](0);
        }

        uint256 n = endIndex - index;
        uint256[] memory page = new uint256[](n);
        for (uint256 i; i < n; i++) {
            page[i] = accountVestingEntryIDs[account][i + index];
        }
        return page;
    }

    function getVestingQuantity(address account, uint256[] calldata entryIDs) external view returns (uint total) {
        for (uint i = 0; i < entryIDs.length; i++) {
            VestingEntries.VestingEntry memory entry = vestingSchedules[account][entryIDs[i]];

            /* Skip entry if escrowAmount == 0 */
            if (entry.escrowAmount != 0) {
                uint256 quantity = _claimableAmount(entry);

                /* add quantity to total */
                total = total.add(quantity);
            }
        }
    }

    function getVestingEntryClaimable(address account, uint256 entryID) external view returns (uint) {
        VestingEntries.VestingEntry memory entry = vestingSchedules[account][entryID];
        return _claimableAmount(entry);
    }

    /* ========== MUTATIVE FUNCTIONS ========== */

    /**
     * Vest escrowed amounts that are claimable
     * Allows users to vest their vesting entries based on msg.sender
     */

    function vest(uint256[] calldata entryIDs) external {
        uint256 total;
        for (uint i = 0; i < entryIDs.length; i++) {
            VestingEntries.VestingEntry storage entry = vestingSchedules[msg.sender][entryIDs[i]];

            /* Skip entry if escrowAmount == 0 already vested */
            if (entry.escrowAmount != 0) {
                uint256 quantity = _claimableAmount(entry);

                /* update entry to remove escrowAmount */
                if (quantity > 0) {
                    entry.escrowAmount = 0;
                }

                /* add quantity to total */
                total = total.add(quantity);
            }
        }

        /* Transfer vested tokens. Will revert if total > totalEscrowedAccountBalance */
        if (total != 0) {
            _transferVestedTokens(msg.sender, total);
        }
    }

    function _claimableAmount(VestingEntries.VestingEntry memory _entry) internal view returns (uint256) {
        uint256 quantity;
        if (_entry.escrowAmount != 0) {
            /* Escrow amounts claimable if block.timestamp equal to or after entry endTime */
            quantity = block.timestamp > _entry.endTime ? _entry.escrowAmount : 0;
        }
        return quantity;
    }

    /**
     * @notice Create an escrow entry to lock SNX for a given duration in seconds
     * @dev This call expects that the depositor (msg.sender) has already approved the Reward escrow contract
     to spend the the amount being escrowed.
     */
    function createEscrowEntry(
        address beneficiary,
        uint256 deposit,
        uint256 duration
    ) external {
        require(beneficiary != address(0), "Cannot create escrow with address(0)");

        /* Transfer SNX from msg.sender */
        require(IERC20(address(synthetix())).transferFrom(msg.sender, address(this), deposit), "token transfer failed");

        /* Append vesting entry for the beneficiary address */
        _appendVestingEntry(beneficiary, deposit, duration);
    }

    /**
     * @notice Add a new vesting entry at a given time and quantity to an account's schedule.
     * @dev A call to this should accompany a previous successful call to synthetix.transfer(rewardEscrow, amount),
     * to ensure that when the funds are withdrawn, there is enough balance.
     * @param account The account to append a new vesting entry to.
     * @param quantity The quantity of SNX that will be escrowed.
     * @param duration The duration that SNX will be emitted.
     */
    function appendVestingEntry(
        address account,
        uint256 quantity,
        uint256 duration
    ) external onlyFeePool {
        _appendVestingEntry(account, quantity, duration);
    }

    /* Transfer vested tokens and update totalEscrowedAccountBalance, totalVestedAccountBalance */
    function _transferVestedTokens(address _account, uint256 _amount) internal {
        _reduceAccountEscrowBalances(_account, _amount);
        totalVestedAccountBalance[_account] = totalVestedAccountBalance[_account].add(_amount);
        IERC20(address(synthetix())).transfer(_account, _amount);
        emit Vested(_account, block.timestamp, _amount);
    }

    function _reduceAccountEscrowBalances(address _account, uint256 _amount) internal {
        // Reverts if amount being vested is greater than the account's existing totalEscrowedAccountBalance
        totalEscrowedBalance = totalEscrowedBalance.sub(_amount);
        totalEscrowedAccountBalance[_account] = totalEscrowedAccountBalance[_account].sub(_amount);
    }

    /* ========== ACCOUNT MERGING ========== */

    function accountMergingIsOpen() public view returns (bool) {
        return accountMergingStartTime.add(accountMergingDuration) > block.timestamp;
    }

    function startMergingWindow() external onlyOwner {
        accountMergingStartTime = block.timestamp;
        emit AccountMergingStarted(accountMergingStartTime, accountMergingStartTime.add(accountMergingDuration));
    }

    function setAccountMergingDuration(uint256 duration) external onlyOwner {
        require(duration <= maxAccountMergingDuration, "exceeds max merging duration");
        accountMergingDuration = duration;
        emit AccountMergingDurationUpdated(duration);
    }

    function setMaxAccountMergingWindow(uint256 duration) external onlyOwner {
        maxAccountMergingDuration = duration;
        emit MaxAccountMergingDurationUpdated(duration);
    }

    function setMaxEscrowDuration(uint256 duration) external onlyOwner {
        max_duration = duration;
        emit MaxEscrowDurationUpdated(duration);
    }

    /* Nominate an account to merge escrow and vesting schedule */
    function nominateAccountToMerge(address account) external {
        require(account != msg.sender, "Cannot nominate own account to merge");
        require(accountMergingIsOpen(), "Account merging has ended");
        require(issuer().debtBalanceOf(msg.sender, "sUSD") == 0, "Cannot merge accounts with debt");
        nominatedReceiver[msg.sender] = account;
        emit NominateAccountToMerge(msg.sender, account);
    }

    function mergeAccount(address accountToMerge, uint256[] calldata entryIDs) external {
        require(accountMergingIsOpen(), "Account merging has ended");
        require(issuer().debtBalanceOf(accountToMerge, "sUSD") == 0, "Cannot merge accounts with debt");
        require(nominatedReceiver[accountToMerge] == msg.sender, "Address is not nominated to merge");

        uint256 totalEscrowAmountMerged;
        for (uint i = 0; i < entryIDs.length; i++) {
            // retrieve entry
            VestingEntries.VestingEntry memory entry = vestingSchedules[accountToMerge][entryIDs[i]];

            /* ignore vesting entries with zero escrowAmount */
            if (entry.escrowAmount != 0) {
                /* copy entry to msg.sender (destination address) */
                vestingSchedules[msg.sender][entryIDs[i]] = entry;

                /* Add the escrowAmount of entry to the totalEscrowAmountMerged */
                totalEscrowAmountMerged = totalEscrowAmountMerged.add(entry.escrowAmount);

                /* append entryID to list of entries for account */
                accountVestingEntryIDs[msg.sender].push(entryIDs[i]);

                /* Delete entry from accountToMerge */
                delete vestingSchedules[accountToMerge][entryIDs[i]];
            }
        }

        /* update totalEscrowedAccountBalance for merged account and accountToMerge */
        totalEscrowedAccountBalance[accountToMerge] = totalEscrowedAccountBalance[accountToMerge].sub(
            totalEscrowAmountMerged
        );
        totalEscrowedAccountBalance[msg.sender] = totalEscrowedAccountBalance[msg.sender].add(totalEscrowAmountMerged);

        emit AccountMerged(accountToMerge, msg.sender, totalEscrowAmountMerged, entryIDs, block.timestamp);
    }

    /* Internal function for importing vesting entry and creating new entry for escrow liquidations */
    function _addVestingEntry(address account, VestingEntries.VestingEntry memory entry) internal returns (uint) {
        uint entryID = nextEntryId;
        vestingSchedules[account][entryID] = entry;

        /* append entryID to list of entries for account */
        accountVestingEntryIDs[account].push(entryID);

        /* Increment the next entry id. */
        nextEntryId = nextEntryId.add(1);

        return entryID;
    }

    /* ========== MIGRATION OLD ESCROW ========== */

    function migrateVestingSchedule(address) external {
        _notImplemented();
    }

    function migrateAccountEscrowBalances(
        address[] calldata,
        uint256[] calldata,
        uint256[] calldata
    ) external {
        _notImplemented();
    }

    /* ========== L2 MIGRATION ========== */

    function burnForMigration(address, uint[] calldata) external returns (uint256, VestingEntries.VestingEntry[] memory) {
        _notImplemented();
    }

    function importVestingEntries(
        address,
        uint256,
        VestingEntries.VestingEntry[] calldata
    ) external {
        _notImplemented();
    }

    /* ========== INTERNALS ========== */

    function _appendVestingEntry(
        address account,
        uint256 quantity,
        uint256 duration
    ) internal {
        /* No empty or already-passed vesting entries allowed. */
        require(quantity != 0, "Quantity cannot be zero");
        require(duration > 0 && duration <= max_duration, "Cannot escrow with 0 duration OR above max_duration");

        /* There must be enough balance in the contract to provide for the vesting entry. */
        totalEscrowedBalance = totalEscrowedBalance.add(quantity);

        require(
            totalEscrowedBalance <= IERC20(address(synthetix())).balanceOf(address(this)),
            "Must be enough balance in the contract to provide for the vesting entry"
        );

        /* Escrow the tokens for duration. */
        uint endTime = block.timestamp + duration;

        /* Add quantity to account's escrowed balance */
        totalEscrowedAccountBalance[account] = totalEscrowedAccountBalance[account].add(quantity);

        uint entryID = nextEntryId;
        vestingSchedules[account][entryID] = VestingEntries.VestingEntry({endTime: uint64(endTime), escrowAmount: quantity});

        accountVestingEntryIDs[account].push(entryID);

        /* Increment the next entry id. */
        nextEntryId = nextEntryId.add(1);

        emit VestingEntryCreated(account, block.timestamp, quantity, duration, entryID);
    }

    /* ========== MODIFIERS ========== */
    modifier onlyFeePool() {
        require(msg.sender == address(feePool()), "Only the FeePool can perform this action");
        _;
    }

    /* ========== EVENTS ========== */
    event Vested(address indexed beneficiary, uint time, uint value);
    event VestingEntryCreated(address indexed beneficiary, uint time, uint value, uint duration, uint entryID);
    event MaxEscrowDurationUpdated(uint newDuration);
    event MaxAccountMergingDurationUpdated(uint newDuration);
    event AccountMergingDurationUpdated(uint newDuration);
    event AccountMergingStarted(uint time, uint endTime);
    event AccountMerged(
        address indexed accountToMerge,
        address destinationAddress,
        uint escrowAmountMerged,
        uint[] entryIDs,
        uint time
    );
    event NominateAccountToMerge(address indexed account, address destination);
}


// https://docs.synthetix.io/contracts/source/interfaces/irewardescrow
interface IRewardEscrow {
    // Views
    function balanceOf(address account) external view returns (uint);

    function numVestingEntries(address account) external view returns (uint);

    function totalEscrowedAccountBalance(address account) external view returns (uint);

    function totalVestedAccountBalance(address account) external view returns (uint);

    function getVestingScheduleEntry(address account, uint index) external view returns (uint[2] memory);

    function getNextVestingIndex(address account) external view returns (uint);

    // Mutative functions
    function appendVestingEntry(address account, uint quantity) external;

    function vest() external;
}


// https://docs.synthetix.io/contracts/source/interfaces/isystemstatus
interface ISystemStatus {
    struct Status {
        bool canSuspend;
        bool canResume;
    }

    struct Suspension {
        bool suspended;
        // reason is an integer code,
        // 0 => no reason, 1 => upgrading, 2+ => defined by system usage
        uint248 reason;
    }

    // Views
    function accessControl(bytes32 section, address account) external view returns (bool canSuspend, bool canResume);

    function requireSystemActive() external view;

    function requireIssuanceActive() external view;

    function requireExchangeActive() external view;

    function requireSynthActive(bytes32 currencyKey) external view;

    function requireSynthsActive(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) external view;

    function synthSuspension(bytes32 currencyKey) external view returns (bool suspended, uint248 reason);

    // Restricted functions
    function suspendSynth(bytes32 currencyKey, uint256 reason) external;

    function updateAccessControl(
        bytes32 section,
        address account,
        bool canSuspend,
        bool canResume
    ) external;
}


// Inheritance


// Internal references


// https://docs.synthetix.io/contracts/RewardEscrow
contract RewardEscrowV2 is BaseRewardEscrowV2 {
    mapping(address => uint256) public totalBalancePendingMigration;

    uint public migrateEntriesThresholdAmount = SafeDecimalMath.unit() * 1000; // Default 1000 SNX

    /* ========== ADDRESS RESOLVER CONFIGURATION ========== */

    bytes32 private constant CONTRACT_SYNTHETIX_BRIDGE_OPTIMISM = "SynthetixBridgeToOptimism";
    bytes32 private constant CONTRACT_REWARD_ESCROW = "RewardEscrow";
    bytes32 private constant CONTRACT_SYSTEMSTATUS = "SystemStatus";

    /* ========== CONSTRUCTOR ========== */

    constructor(address _owner, address _resolver) public BaseRewardEscrowV2(_owner, _resolver) {}

    /* ========== VIEWS ======================= */

    function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
        bytes32[] memory existingAddresses = BaseRewardEscrowV2.resolverAddressesRequired();
        bytes32[] memory newAddresses = new bytes32[](3);
        newAddresses[0] = CONTRACT_SYNTHETIX_BRIDGE_OPTIMISM;
        newAddresses[1] = CONTRACT_REWARD_ESCROW;
        newAddresses[2] = CONTRACT_SYSTEMSTATUS;
        return combineArrays(existingAddresses, newAddresses);
    }

    function synthetixBridgeToOptimism() internal view returns (address) {
        return requireAndGetAddress(CONTRACT_SYNTHETIX_BRIDGE_OPTIMISM);
    }

    function oldRewardEscrow() internal view returns (IRewardEscrow) {
        return IRewardEscrow(requireAndGetAddress(CONTRACT_REWARD_ESCROW));
    }

    function systemStatus() internal view returns (ISystemStatus) {
        return ISystemStatus(requireAndGetAddress(CONTRACT_SYSTEMSTATUS));
    }

    /* ========== OLD ESCROW LOOKUP ========== */

    uint internal constant TIME_INDEX = 0;
    uint internal constant QUANTITY_INDEX = 1;

    /* ========== MIGRATION OLD ESCROW ========== */

    /* Threshold amount for migrating escrow entries from old RewardEscrow */
    function setMigrateEntriesThresholdAmount(uint amount) external onlyOwner {
        migrateEntriesThresholdAmount = amount;
        emit MigrateEntriesThresholdAmountUpdated(amount);
    }

    /* Function to allow any address to migrate vesting entries from previous reward escrow */
    function migrateVestingSchedule(address addressToMigrate) external systemActive {
        /* Ensure account escrow balance pending migration is not zero */
        /* Ensure account escrowed balance is not zero - should have been migrated */
        require(totalBalancePendingMigration[addressToMigrate] > 0, "No escrow migration pending");
        require(totalEscrowedAccountBalance[addressToMigrate] > 0, "Address escrow balance is 0");

        /* Add a vestable entry for addresses with totalBalancePendingMigration <= migrateEntriesThreshold amount of SNX */
        if (totalBalancePendingMigration[addressToMigrate] <= migrateEntriesThresholdAmount) {
            _importVestingEntry(
                addressToMigrate,
                VestingEntries.VestingEntry({
                    endTime: uint64(block.timestamp),
                    escrowAmount: totalBalancePendingMigration[addressToMigrate]
                })
            );

            /* Remove totalBalancePendingMigration[addressToMigrate] */
            delete totalBalancePendingMigration[addressToMigrate];
        } else {
            uint numEntries = oldRewardEscrow().numVestingEntries(addressToMigrate);

            /* iterate and migrate old escrow schedules from rewardEscrow.vestingSchedules
             * starting from the last entry in each staker's vestingSchedules
             */
            for (uint i = 1; i <= numEntries; i++) {
                uint[2] memory vestingSchedule = oldRewardEscrow().getVestingScheduleEntry(addressToMigrate, numEntries - i);

                uint time = vestingSchedule[TIME_INDEX];
                uint amount = vestingSchedule[QUANTITY_INDEX];

                /* The list is sorted, when we reach the first entry that can be vested stop */
                if (time < block.timestamp) {
                    break;
                }

                /* import vesting entry */
                _importVestingEntry(
                    addressToMigrate,
                    VestingEntries.VestingEntry({endTime: uint64(time), escrowAmount: amount})
                );

                /* subtract amount from totalBalancePendingMigration - reverts if insufficient */
                totalBalancePendingMigration[addressToMigrate] = totalBalancePendingMigration[addressToMigrate].sub(amount);
            }
        }
    }

    /**
     * Import function for owner to import vesting schedule
     * All entries imported should have past their vesting timestamp and will be ready to be vested
     * Addresses with totalEscrowedAccountBalance == 0 will not be migrated as they have all vested
     */
    function importVestingSchedule(address[] calldata accounts, uint256[] calldata escrowAmounts)
        external
        onlyDuringSetup
        onlyOwner
    {
        require(accounts.length == escrowAmounts.length, "Account and escrowAmounts Length mismatch");

        for (uint i = 0; i < accounts.length; i++) {
            address addressToMigrate = accounts[i];
            uint256 escrowAmount = escrowAmounts[i];

            // ensure account have escrow migration pending
            require(totalEscrowedAccountBalance[addressToMigrate] > 0, "Address escrow balance is 0");
            require(totalBalancePendingMigration[addressToMigrate] > 0, "No escrow migration pending");

            /* Import vesting entry with endTime as block.timestamp and escrowAmount */
            _importVestingEntry(
                addressToMigrate,
                VestingEntries.VestingEntry({endTime: uint64(block.timestamp), escrowAmount: escrowAmount})
            );

            /* update totalBalancePendingMigration - reverts if escrowAmount > remaining balance to migrate */
            totalBalancePendingMigration[addressToMigrate] = totalBalancePendingMigration[addressToMigrate].sub(
                escrowAmount
            );

            emit ImportedVestingSchedule(addressToMigrate, block.timestamp, escrowAmount);
        }
    }

    /**
     * Migration for owner to migrate escrowed and vested account balances
     * Addresses with totalEscrowedAccountBalance == 0 will not be migrated as they have all vested
     */
    function migrateAccountEscrowBalances(
        address[] calldata accounts,
        uint256[] calldata escrowBalances,
        uint256[] calldata vestedBalances
    ) external onlyDuringSetup onlyOwner {
        require(accounts.length == escrowBalances.length, "Number of accounts and balances don't match");
        require(accounts.length == vestedBalances.length, "Number of accounts and vestedBalances don't match");

        for (uint i = 0; i < accounts.length; i++) {
            address account = accounts[i];
            uint escrowedAmount = escrowBalances[i];
            uint vestedAmount = vestedBalances[i];

            // ensure account doesn't have escrow migration pending / being imported more than once
            require(totalBalancePendingMigration[account] == 0, "Account migration is pending already");

            /* Update totalEscrowedBalance for tracking the Synthetix balance of this contract. */
            totalEscrowedBalance = totalEscrowedBalance.add(escrowedAmount);

            /* Update totalEscrowedAccountBalance and totalVestedAccountBalance for each account */
            totalEscrowedAccountBalance[account] = totalEscrowedAccountBalance[account].add(escrowedAmount);
            totalVestedAccountBalance[account] = totalVestedAccountBalance[account].add(vestedAmount);

            /* update totalBalancePendingMigration for account */
            totalBalancePendingMigration[account] = escrowedAmount;

            emit MigratedAccountEscrow(account, escrowedAmount, vestedAmount, now);
        }
    }

    /* Internal function to add entry to vestingSchedules and emit event */
    function _importVestingEntry(address account, VestingEntries.VestingEntry memory entry) internal {
        /* add vesting entry to account and assign an entryID to it */
        uint entryID = BaseRewardEscrowV2._addVestingEntry(account, entry);

        emit ImportedVestingEntry(account, entryID, entry.escrowAmount, entry.endTime);
    }

    /* ========== L2 MIGRATION ========== */

    function burnForMigration(address account, uint[] calldata entryIDs)
        external
        onlySynthetixBridge
        returns (uint256 escrowedAccountBalance, VestingEntries.VestingEntry[] memory vestingEntries)
    {
        require(entryIDs.length > 0, "Entry IDs required");

        vestingEntries = new VestingEntries.VestingEntry[](entryIDs.length);

        for (uint i = 0; i < entryIDs.length; i++) {
            VestingEntries.VestingEntry storage entry = vestingSchedules[account][entryIDs[i]];

            if (entry.escrowAmount > 0) {
                vestingEntries[i] = entry;

                /* add the escrow amount to escrowedAccountBalance */
                escrowedAccountBalance = escrowedAccountBalance.add(entry.escrowAmount);

                /* Delete the vesting entry being migrated */
                delete vestingSchedules[account][entryIDs[i]];
            }
        }

        /**
         *  update account total escrow balances for migration
         *  transfer the escrowed SNX being migrated to the L2 deposit contract
         */
        if (escrowedAccountBalance > 0) {
            _reduceAccountEscrowBalances(account, escrowedAccountBalance);
            IERC20(address(synthetix())).transfer(synthetixBridgeToOptimism(), escrowedAccountBalance);
        }

        emit BurnedForMigrationToL2(account, entryIDs, escrowedAccountBalance, block.timestamp);

        return (escrowedAccountBalance, vestingEntries);
    }

    /* ========== MODIFIERS ========== */

    modifier onlySynthetixBridge() {
        require(msg.sender == synthetixBridgeToOptimism(), "Can only be invoked by SynthetixBridgeToOptimism contract");
        _;
    }

    modifier systemActive() {
        systemStatus().requireSystemActive();
        _;
    }

    /* ========== EVENTS ========== */
    event MigratedAccountEscrow(address indexed account, uint escrowedAmount, uint vestedAmount, uint time);
    event ImportedVestingSchedule(address indexed account, uint time, uint escrowAmount);
    event BurnedForMigrationToL2(address indexed account, uint[] entryIDs, uint escrowedAmountMigrated, uint time);
    event ImportedVestingEntry(address indexed account, uint entryID, uint escrowAmount, uint endTime);
    event MigrateEntriesThresholdAmountUpdated(uint newAmount);
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_resolver","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"accountToMerge","type":"address"},{"indexed":false,"internalType":"address","name":"destinationAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"escrowAmountMerged","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"entryIDs","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"AccountMerged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newDuration","type":"uint256"}],"name":"AccountMergingDurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"AccountMergingStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"entryIDs","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"escrowedAmountMigrated","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"BurnedForMigrationToL2","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"name","type":"bytes32"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"CacheUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"entryID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"escrowAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"ImportedVestingEntry","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"escrowAmount","type":"uint256"}],"name":"ImportedVestingSchedule","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newDuration","type":"uint256"}],"name":"MaxAccountMergingDurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newDuration","type":"uint256"}],"name":"MaxEscrowDurationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newAmount","type":"uint256"}],"name":"MigrateEntriesThresholdAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"escrowedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vestedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"MigratedAccountEscrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"NominateAccountToMerge","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Vested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"entryID","type":"uint256"}],"name":"VestingEntryCreated","type":"event"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"accountMergingDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"accountMergingIsOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"accountMergingStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"accountVestingEntryIDs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"appendVestingEntry","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256[]","name":"entryIDs","type":"uint256[]"}],"name":"burnForMigration","outputs":[{"internalType":"uint256","name":"escrowedAccountBalance","type":"uint256"},{"components":[{"internalType":"uint64","name":"endTime","type":"uint64"},{"internalType":"uint256","name":"escrowAmount","type":"uint256"}],"internalType":"struct VestingEntries.VestingEntry[]","name":"vestingEntries","type":"tuple[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint256","name":"deposit","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"createEscrowEntry","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"pageSize","type":"uint256"}],"name":"getAccountVestingEntryIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"entryID","type":"uint256"}],"name":"getVestingEntry","outputs":[{"internalType":"uint64","name":"endTime","type":"uint64"},{"internalType":"uint256","name":"escrowAmount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"entryID","type":"uint256"}],"name":"getVestingEntryClaimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256[]","name":"entryIDs","type":"uint256[]"}],"name":"getVestingQuantity","outputs":[{"internalType":"uint256","name":"total","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"pageSize","type":"uint256"}],"name":"getVestingSchedules","outputs":[{"components":[{"internalType":"uint64","name":"endTime","type":"uint64"},{"internalType":"uint256","name":"escrowAmount","type":"uint256"},{"internalType":"uint256","name":"entryID","type":"uint256"}],"internalType":"struct VestingEntries.VestingEntryWithID[]","name":"","type":"tuple[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"components":[{"internalType":"uint64","name":"endTime","type":"uint64"},{"internalType":"uint256","name":"escrowAmount","type":"uint256"}],"internalType":"struct VestingEntries.VestingEntry[]","name":"","type":"tuple[]"}],"name":"importVestingEntries","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"escrowAmounts","type":"uint256[]"}],"name":"importVestingSchedule","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isResolverCached","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxAccountMergingDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"max_duration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"accountToMerge","type":"address"},{"internalType":"uint256[]","name":"entryIDs","type":"uint256[]"}],"name":"mergeAccount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"escrowBalances","type":"uint256[]"},{"internalType":"uint256[]","name":"vestedBalances","type":"uint256[]"}],"name":"migrateAccountEscrowBalances","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"migrateEntriesThresholdAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"addressToMigrate","type":"address"}],"name":"migrateVestingSchedule","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"nextEntryId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"nominateAccountToMerge","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nominatedReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"numVestingEntries","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"rebuildCache","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"resolver","outputs":[{"internalType":"contract AddressResolver","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"resolverAddressesRequired","outputs":[{"internalType":"bytes32[]","name":"addresses","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"setAccountMergingDuration","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"setMaxAccountMergingWindow","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"setMaxEscrowDuration","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setMigrateEntriesThresholdAmount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"setupExpiryTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"startMergingWindow","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalBalancePendingMigration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalEscrowedAccountBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalEscrowedBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalVestedAccountBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256[]","name":"entryIDs","type":"uint256[]"}],"name":"vest","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"vestingSchedules","outputs":[{"internalType":"uint64","name":"endTime","type":"uint64"},{"internalType":"uint256","name":"escrowAmount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]

608060408190526303bfc400600c556224ea00600d5562093a80600e55630241ebdb60e61b8152731a60e2e2a8be0bc2b6381dd31fd3fd5f9a28de4c9063907af6c09060849060209060048186803b1580156200005b57600080fd5b505af415801562000070573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620000969190810190620001f1565b6103e802601155348015620000aa57600080fd5b5060405162003ead38038062003ead833981016040819052620000cd91620001b2565b8181806224ea00836001600160a01b038116620001075760405162461bcd60e51b8152600401620000fe9062000297565b60405180910390fd5b600080546001600160a01b0319166001600160a01b0383161781556040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c916200015491849062000271565b60405180910390a1504201600255600380546001600160a01b0319166001600160a01b03929092169190911790555050600160075550620003009050565b80516200019f81620002db565b92915050565b80516200019f81620002f5565b60008060408385031215620001c657600080fd5b6000620001d4858562000192565b9250506020620001e78582860162000192565b9150509250929050565b6000602082840312156200020457600080fd5b6000620002128484620001a5565b949350505050565b6200022581620002c7565b82525050565b6200022581620002b2565b600062000245601983620002a9565b7f4f776e657220616464726573732063616e6e6f74206265203000000000000000815260200192915050565b604081016200028182856200021a565b6200029060208301846200022b565b9392505050565b602080825281016200019f8162000236565b90815260200190565b60006001600160a01b0382166200019f565b90565b60006200019f8260006200019f82620002b2565b620002e681620002b2565b8114620002f257600080fd5b50565b620002e681620002c4565b613b9d80620003106000396000f3fe608060405234801561001057600080fd5b506004361061027f5760003560e01c806370a082311161015c5780638da5cb5b116100ce578063b95375bd11610087578063b95375bd1461052e578063cd7b43dd14610541578063d621a16914610554578063e6b2cf6c14610567578063eac624891461056f578063f0b882ba1461058f5761027f565b80638da5cb5b146104dd578063910a326d146104e55780639ad6a7e5146104ed578063a0416ed3146104f5578063ae58254914610508578063b0fd59631461051b5761027f565b80637839b92f116101205780637839b92f146104665780637993e6991461047957806379ba50971461048c5780637cc1d7561461049457806380d46f58146104a7578063899ffef4146104c85761027f565b806370a082311461041057806371e780f31461042357806373307e401461042b578063741853601461043e578063773ab39f146104465761027f565b8063326a3cfb116101f557806346ba2d90116101b957806346ba2d90146103b257806353a47bb7146103ba5780635b85c200146103cf5780635eb8cf25146103e25780636154c343146103ea5780636dc05bd3146103fd5761027f565b8063326a3cfb1461035057806334c7fec91461036357806337088ffc146103765780634525aabc1461037e57806345626bd6146103915761027f565b8063178c565511610247578063178c5655146102f45780631bb47b44146102fc578063204b676a1461030f578063227d517a146103225780632af64bd31461033557806330104c5f1461033d5761027f565b8063018c6c551461028457806304f3bcec1461029957806305662986146102b75780630fcdefb7146102cc5780631627540c146102e1575b600080fd5b610297610292366004612c1e565b6105a2565b005b6102a16105ea565b6040516102ae91906137ef565b60405180910390f35b6102bf6105f9565b6040516102ae91906137a5565b6102d461061a565b6040516102ae91906137b3565b6102976102ef366004612922565b610620565b610297610673565b61029761030a366004612a54565b6106d0565b6102d461031d366004612922565b610721565b6102d4610330366004612922565b61073c565b6102bf61074e565b6102d461034b3660046129b3565b610865565b6102d461035e366004612922565b6108c4565b610297610371366004612bbf565b6108d6565b6102d461098c565b61029761038c366004612c1e565b610992565b6103a461039f3660046129b3565b6109cf565b6040516102ae929190613a44565b6102d46109ff565b6103c2610a05565b6040516102ae9190613658565b6102976103dd366004612c1e565b610a14565b6102d4610a51565b6103a46103f83660046129b3565b610a57565b6102d461040b36600461295e565b610a91565b6102d461041e366004612922565b610b3e565b6102d4610b59565b6103c2610439366004612922565b610b5f565b610297610b7a565b610459610454366004612a54565b610cd0565b6040516102ae919061374c565b610297610474366004612922565b610e70565b610297610487366004612c1e565b61116e565b6102976111cd565b6102976104a2366004612922565b611269565b6104ba6104b536600461295e565b6113b9565b6040516102ae92919061399e565b6104d0611642565b6040516102ae919061373b565b6103c261170c565b6102d461171b565b6102d4611721565b610297610503366004612a54565b611727565b6102d46105163660046129b3565b6117f2565b6102d4610529366004612922565b611820565b61029761053c366004612b03565b611832565b61029761054f3660046129ed565b611a1d565b610297610562366004612aa1565b611a2b565b6102d4611bec565b61058261057d366004612a54565b611bf2565b6040516102ae9190613794565b61029761059d36600461295e565b611cde565b6105aa61201a565b600d8190556040517fe829efae5d8a2f7163f46c23a8190bf14625c1e446561ca0f5cf279ab7c8015e906105df9083906137b3565b60405180910390a150565b6003546001600160a01b031681565b600042610613600e54600f5461204690919063ffffffff16565b1190505b90565b600f5481565b61062861201a565b600180546001600160a01b0319166001600160a01b0383161790556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22906105df908390613658565b61067b61201a565b42600f819055600e547fceade2b9bc02350b17075c94bb699508b89ed2752f501ea42024b1bb5fd3444591906106b890829063ffffffff61204616565b6040516106c69291906139be565b60405180910390a1565b6106d861206b565b6001600160a01b0316336001600160a01b0316146107115760405162461bcd60e51b81526004016107089061395e565b60405180910390fd5b61071c838383612085565b505050565b6001600160a01b031660009081526006602052604090205490565b60096020526000908152604090205481565b6000606061075a611642565b905060005b815181101561085c57600082828151811061077657fe5b60209081029190910181015160008181526004928390526040908190205460035491516321f8a72160e01b81529294506001600160a01b03908116939116916321f8a721916107c7918691016137b3565b60206040518083038186803b1580156107df57600080fd5b505afa1580156107f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108179190810190612940565b6001600160a01b031614158061084257506000818152600460205260409020546001600160a01b0316155b156108535760009350505050610617565b5060010161075f565b50600191505090565b600061086f612793565b506001600160a01b0383166000908152600560209081526040808320858452825291829020825180840190935280546001600160401b0316835260010154908201526108ba8161229d565b9150505b92915050565b60086020526000908152604090205481565b6000805b8281101561097b57336000908152600560205260408120818686858181106108fe57fe5b90506020020135815260200190815260200160002090508060010154600014610972576040805180820190915281546001600160401b031681526001820154602082015260009061094e9061229d565b9050801561095e57600060018301555b61096e848263ffffffff61204616565b9350505b506001016108da565b50801561071c5761071c33826122cd565b600d5481565b61099a61201a565b600c8190556040517f6b92bd20c4b2e6861047ba7209ddc78d538419aae187d0df46716b827b8997a4906105df9083906137b3565b6005602090815260009283526040808420909152908252902080546001909101546001600160401b039091169082565b60025481565b6001546001600160a01b031681565b610a1c61201a565b60118190556040517f7829b48ec37298e3e9b1cb2971e47abc072159681eaf558f8649a25d66ef8672906105df9083906137b3565b600c5481565b6001600160a01b039190911660009081526005602090815260408083209383529290522080546001909101546001600160401b0390911691565b6000805b82811015610b3657610aa5612793565b6001600160a01b038616600090815260056020526040812090868685818110610aca57fe5b60209081029290920135835250818101929092526040908101600020815180830190925280546001600160401b0316825260010154918101829052915015610b2d576000610b178261229d565b9050610b29848263ffffffff61204616565b9350505b50600101610a95565b509392505050565b6001600160a01b031660009081526008602052604090205490565b600b5481565b600a602052600090815260409020546001600160a01b031681565b6060610b84611642565b905060005b8151811015610ccc576000828281518110610ba057fe5b602002602001015190506000600360009054906101000a90046001600160a01b03166001600160a01b031663dacb2d018384604051602001610be2919061364d565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610c0e9291906137cf565b60206040518083038186803b158015610c2657600080fd5b505afa158015610c3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610c5e9190810190612940565b6000838152600460205260409081902080546001600160a01b0319166001600160a01b038416179055519091507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa6890610cba90849084906137c1565b60405180910390a15050600101610b89565b5050565b6060828201838111610d16576040805160008082526020820190925290610d0d565b610cfa6127aa565b815260200190600190039081610cf25790505b50915050610e69565b6001600160a01b038516600090815260066020526040902054811115610d5157506001600160a01b0384166000908152600660205260409020545b604080518583038082526020808202830101909252606090828015610d9057816020015b610d7d6127aa565b815260200190600190039081610d755790505b50905060005b82811015610e63576001600160a01b03881660009081526006602052604081208054838a01908110610dc457fe5b90600052602060002001549050610dd9612793565b506001600160a01b03891660009081526005602090815260408083208484528252918290208251808401845281546001600160401b03908116825260019092015481840190815284516060810186528251909316835251928201929092529182018390528451909190859085908110610e4e57fe5b60209081029190910101525050600101610d96565b50925050505b9392505050565b610e786123e8565b6001600160a01b031663086dabd16040518163ffffffff1660e01b815260040160006040518083038186803b158015610eb057600080fd5b505afa158015610ec4573d6000803e3d6000fd5b505050506001600160a01b038116600090815260106020526040902054610efd5760405162461bcd60e51b81526004016107089061388e565b6001600160a01b038116600090815260086020526040902054610f325760405162461bcd60e51b81526004016107089061397e565b6011546001600160a01b03821660009081526010602052604090205411610fbd57610f9f816040518060400160405280426001600160401b0316815260200160106000866001600160a01b03166001600160a01b0316815260200190815260200160002054815250612402565b6001600160a01b03811660009081526010602052604081205561116b565b6000610fc7612460565b6001600160a01b031663204b676a836040518263ffffffff1660e01b8152600401610ff29190613658565b60206040518083038186803b15801561100a57600080fd5b505afa15801561101e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506110429190810190612c3c565b905060015b81811161071c576110566127d4565b61105e612460565b6001600160a01b031663da7bd3e9858486036040518363ffffffff1660e01b815260040161108d929190613720565b604080518083038186803b1580156110a457600080fd5b505afa1580156110b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506110dc9190810190612ba1565b8051602082015191925090428210156110f75750505061071c565b61111e866040518060400160405280856001600160401b0316815260200184815250612402565b6001600160a01b038616600090815260106020526040902054611147908263ffffffff61247a16565b6001600160a01b038716600090815260106020526040902055505050600101611047565b50565b61117661201a565b600d548111156111985760405162461bcd60e51b81526004016107089061394e565b600e8190556040517f723c43349da7aeae47190396f2e2fbe6bedb46b9e9705bc5b908d65bc7a1e0e6906105df9083906137b3565b6001546001600160a01b031633146111f75760405162461bcd60e51b81526004016107089061380e565b6000546001546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9261123a926001600160a01b03918216929116906136f7565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b6001600160a01b0381163314156112925760405162461bcd60e51b8152600401610708906138ee565b61129a6105f9565b6112b65760405162461bcd60e51b8152600401610708906138be565b6112be6124a2565b6001600160a01b031663d37c4d8b336040518263ffffffff1660e01b81526004016112e99190613696565b60206040518083038186803b15801561130157600080fd5b505afa158015611315573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506113399190810190612c3c565b156113565760405162461bcd60e51b81526004016107089061398e565b336000818152600a60205260409081902080546001600160a01b0319166001600160a01b038516179055517fcf51776bb16e5780edcca2e64a9ba8a9c7d5d00a6699cbd7606e465361ba4852906113ae908490613658565b60405180910390a250565b600060606113c56124b6565b6001600160a01b0316336001600160a01b0316146113f55760405162461bcd60e51b8152600401610708906138de565b826114125760405162461bcd60e51b8152600401610708906138fe565b60408051848152602080860282010190915283801561144b57816020015b611438612793565b8152602001906001900390816114305790505b50905060005b83811015611552576001600160a01b03861660009081526005602052604081208187878581811061147e57fe5b9050602002013581526020019081526020016000209050600081600101541115611549576040805180820190915281546001600160401b031681526001820154602082015283518490849081106114d157fe5b60200260200101819052506114f381600101548561204690919063ffffffff16565b6001600160a01b038816600090815260056020526040812091955087878581811061151a57fe5b602090810292909201358352508101919091526040016000908120805467ffffffffffffffff19168155600101555b50600101611451565b5081156115f35761156385836124dd565b61156b61253c565b6001600160a01b031663a9059cbb6115816124b6565b846040518363ffffffff1660e01b815260040161159f929190613720565b602060405180830381600087803b1580156115b957600080fd5b505af11580156115cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506115f19190810190612c00565b505b846001600160a01b03167f929c8a2a06883affd05f43baf52398dbbfb6930730ce1bdb2cfe413cd44b107c85858542604051611632949392919061375d565b60405180910390a2935093915050565b60608061164d612553565b60408051600380825260808201909252919250606091906020820183803883390190505090507853796e746865746978427269646765546f4f7074696d69736d60381b8160008151811061169d57fe5b6020026020010181815250506b526577617264457363726f7760a01b816001815181106116c657fe5b6020026020010181815250506b53797374656d53746174757360a01b816002815181106116ef57fe5b60200260200101818152505061170582826125e5565b9250505090565b6000546001600160a01b031681565b600e5481565b60115481565b6001600160a01b03831661174d5760405162461bcd60e51b81526004016107089061384e565b61175561253c565b6001600160a01b03166323b872dd3330856040518463ffffffff1660e01b815260040161178493929190613666565b602060405180830381600087803b15801561179e57600080fd5b505af11580156117b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506117d69190810190612c00565b6107115760405162461bcd60e51b8152600401610708906138ce565b6006602052816000526040600020818154811061180b57fe5b90600052602060002001600091509150505481565b60106020526000908152604090205481565b60025442106118535760405162461bcd60e51b81526004016107089061393e565b61185b61201a565b84831461187a5760405162461bcd60e51b81526004016107089061396e565b8481146118995760405162461bcd60e51b81526004016107089061387e565b60005b85811015611a145760008787838181106118b257fe5b90506020020160206118c79190810190612922565b905060008686848181106118d757fe5b90506020020135905060008585858181106118ee57fe5b6001600160a01b03861660009081526010602090815260409091205491029290920135925050156119315760405162461bcd60e51b81526004016107089061381e565b600b54611944908363ffffffff61204616565b600b556001600160a01b038316600090815260086020526040902054611970908363ffffffff61204616565b6001600160a01b0384166000908152600860209081526040808320939093556009905220546119a5908263ffffffff61204616565b6001600160a01b0384166000818152600960209081526040808320949094556010905282902084905590517fa2a5ac2d2500e30aea994fc4bc99ef5535241c79d428e43c3fe204862f2874d690611a01908590859042906139cc565b60405180910390a250505060010161189c565b50505050505050565b611a256126a1565b50505050565b6002544210611a4c5760405162461bcd60e51b81526004016107089061393e565b611a5461201a565b828114611a735760405162461bcd60e51b81526004016107089061392e565b60005b83811015611be5576000858583818110611a8c57fe5b9050602002016020611aa19190810190612922565b90506000848484818110611ab157fe5b905060200201359050600060086000846001600160a01b03166001600160a01b031681526020019081526020016000205411611aff5760405162461bcd60e51b81526004016107089061397e565b6001600160a01b038216600090815260106020526040902054611b345760405162461bcd60e51b81526004016107089061388e565b611b5b826040518060400160405280426001600160401b0316815260200184815250612402565b6001600160a01b038216600090815260106020526040902054611b84908263ffffffff61247a16565b6001600160a01b038316600081815260106020526040908190209290925590517f73cefcb01ff86c575a4fbf40317a93c37b7312e0b294e588ee24b312e4f97cc490611bd390429085906139be565b60405180910390a25050600101611a76565b5050505050565b60075481565b6001600160a01b03831660009081526006602052604090205460609083830190811115611c3457506001600160a01b0384166000908152600660205260409020545b838111611c51576040805160008082526020820190925290610d0d565b604080518583038082526020808202830101909252606090828015611c80578160200160208202803883390190505b50905060005b82811015610e63576001600160a01b03881660009081526006602052604090208054828901908110611cb457fe5b9060005260206000200154828281518110611ccb57fe5b6020908102919091010152600101611c86565b611ce66105f9565b611d025760405162461bcd60e51b8152600401610708906138be565b611d0a6124a2565b6001600160a01b031663d37c4d8b846040518263ffffffff1660e01b8152600401611d359190613712565b60206040518083038186803b158015611d4d57600080fd5b505afa158015611d61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611d859190810190612c3c565b15611da25760405162461bcd60e51b81526004016107089061398e565b6001600160a01b038381166000908152600a6020526040902054163314611ddb5760405162461bcd60e51b81526004016107089061391e565b6000805b82811015611f5a57611def612793565b6001600160a01b038616600090815260056020526040812090868685818110611e1457fe5b60209081029290920135835250818101929092526040908101600020815180830190925280546001600160401b0316825260010154918101829052915015611f51573360009081526005602052604081208291878786818110611e7357fe5b60209081029290920135835250818101929092526040016000208251815467ffffffffffffffff19166001600160401b0390911617815591810151600190920191909155810151611ec5908490612046565b336000908152600660205260409020909350858584818110611ee357fe5b8354600181018555600094855260208086209281029490940135910155506001600160a01b0388168252600590526040812090868685818110611f2257fe5b602090810292909201358352508101919091526040016000908120805467ffffffffffffffff19168155600101555b50600101611ddf565b506001600160a01b038416600090815260086020526040902054611f84908263ffffffff61247a16565b6001600160a01b038516600090815260086020526040808220929092553381522054611fb6908263ffffffff61204616565b33600081815260086020526040908190209290925590516001600160a01b038616917f48d567deaa7db90f8a443344e519ca8906521ffe118e1df43e89a3c257963f7c9161200c919085908890889042906136b0565b60405180910390a250505050565b6000546001600160a01b031633146120445760405162461bcd60e51b81526004016107089061390e565b565b600082820183811015610e695760405162461bcd60e51b81526004016107089061382e565b600061208066119959541bdbdb60ca1b6126b9565b905090565b816120a25760405162461bcd60e51b81526004016107089061389e565b6000811180156120b45750600c548111155b6120d05760405162461bcd60e51b81526004016107089061383e565b600b546120e3908363ffffffff61204616565b600b556120ee61253c565b6001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016121199190613658565b60206040518083038186803b15801561213157600080fd5b505afa158015612145573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506121699190810190612c3c565b600b54111561218a5760405162461bcd60e51b8152600401610708906138ae565b6001600160a01b038316600090815260086020526040902054428201906121b7908463ffffffff61204616565b6001600160a01b03851660008181526008602090815260408083209490945560078054855180870187526001600160401b0388811682528185018b81528787526005865288872084885286528887209251835467ffffffffffffffff1916921691909117825551600191820155948452600683529483208054808601825590845291909220018390555461224a91612046565b6007556040516001600160a01b038616907f2cc016694185d38abbe28d9e9baea2e9d95a321ae43475e5ea7b643756840bc09061228e9042908890889087906139e7565b60405180910390a25050505050565b60008082602001516000146108be5782516001600160401b031642116122c4576000610e69565b50506020015190565b6122d782826124dd565b6001600160a01b038216600090815260096020526040902054612300908263ffffffff61204616565b6001600160a01b03831660009081526009602052604090205561232161253c565b6001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040161234e929190613720565b602060405180830381600087803b15801561236857600080fd5b505af115801561237c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506123a09190810190612c00565b50816001600160a01b03167ffbeff59d2bfda0d79ea8a29f8c57c66d48c7a13eabbdb90908d9115ec41c9dc642836040516123dc9291906139be565b60405180910390a25050565b60006120806b53797374656d53746174757360a01b6126b9565b600061240e8383612716565b602083015183516040519293506001600160a01b038616927fa0ba170b0a148bd927eafc64518e6c9d92eba1ea1fdf703dd8cfee6d329012bb92612453928692613a1c565b60405180910390a2505050565b60006120806b526577617264457363726f7760a01b6126b9565b60008282111561249c5760405162461bcd60e51b81526004016107089061385e565b50900390565b60006120806524b9b9bab2b960d11b6126b9565b60006120807853796e746865746978427269646765546f4f7074696d69736d60381b6126b9565b600b546124f0908263ffffffff61247a16565b600b556001600160a01b03821660009081526008602052604090205461251c908263ffffffff61247a16565b6001600160a01b0390921660009081526008602052604090209190915550565b6000612080680a6f2dce8d0cae8d2f60bb1b6126b9565b60408051600380825260808201909252606091602082018380388339019050509050680a6f2dce8d0cae8d2f60bb1b8160008151811061258f57fe5b60200260200101818152505066119959541bdbdb60ca1b816001815181106125b357fe5b6020026020010181815250506524b9b9bab2b960d11b816002815181106125d657fe5b60200260200101818152505090565b60608151835101604051908082528060200260200182016040528015612615578160200160208202803883390190505b50905060005b83518110156126575783818151811061263057fe5b602002602001015182828151811061264457fe5b602090810291909101015260010161261b565b5060005b825181101561269a5782818151811061267057fe5b602002602001015182828651018151811061268757fe5b602090810291909101015260010161265b565b5092915050565b60405162461bcd60e51b81526004016107089061386e565b60008181526004602090815260408083205490516001600160a01b0390911691821515916126e99186910161362d565b6040516020818303038152906040529061269a5760405162461bcd60e51b815260040161070891906137fd565b600780546001600160a01b038416600081815260056020908152604080832085845282528083208751815467ffffffffffffffff19166001600160401b03909116178155878301516001918201559383526006825282208054808501825590835290822001839055925461278991612046565b6007559392505050565b604080518082019091526000808252602082015290565b604051806060016040528060006001600160401b0316815260200160008152602001600081525090565b60405180604001604052806002906020820280388339509192915050565b80356108be81613b34565b80516108be81613b34565b60008083601f84011261281a57600080fd5b5081356001600160401b0381111561283157600080fd5b60208301915083602082028301111561284957600080fd5b9250929050565b60008083601f84011261286257600080fd5b5081356001600160401b0381111561287957600080fd5b60208301915083604082028301111561284957600080fd5b600082601f8301126128a257600080fd5b60026128b56128b082613a78565b613a52565b915081838560208402820111156128cb57600080fd5b60005b838110156128f757816128e18882612917565b84525060209283019291909101906001016128ce565b5050505092915050565b80516108be81613b48565b80356108be81613b51565b80516108be81613b51565b60006020828403121561293457600080fd5b60006108ba84846127f2565b60006020828403121561295257600080fd5b60006108ba84846127fd565b60008060006040848603121561297357600080fd5b600061297f86866127f2565b93505060208401356001600160401b0381111561299b57600080fd5b6129a786828701612808565b92509250509250925092565b600080604083850312156129c657600080fd5b60006129d285856127f2565b92505060206129e38582860161290c565b9150509250929050565b60008060008060608587031215612a0357600080fd5b6000612a0f87876127f2565b9450506020612a208782880161290c565b93505060408501356001600160401b03811115612a3c57600080fd5b612a4887828801612850565b95989497509550505050565b600080600060608486031215612a6957600080fd5b6000612a7586866127f2565b9350506020612a868682870161290c565b9250506040612a978682870161290c565b9150509250925092565b60008060008060408587031215612ab757600080fd5b84356001600160401b03811115612acd57600080fd5b612ad987828801612808565b945094505060208501356001600160401b03811115612af757600080fd5b612a4887828801612808565b60008060008060008060608789031215612b1c57600080fd5b86356001600160401b03811115612b3257600080fd5b612b3e89828a01612808565b965096505060208701356001600160401b03811115612b5c57600080fd5b612b6889828a01612808565b945094505060408701356001600160401b03811115612b8657600080fd5b612b9289828a01612808565b92509250509295509295509295565b600060408284031215612bb357600080fd5b60006108ba8484612891565b60008060208385031215612bd257600080fd5b82356001600160401b03811115612be857600080fd5b612bf485828601612808565b92509250509250929050565b600060208284031215612c1257600080fd5b60006108ba8484612901565b600060208284031215612c3057600080fd5b60006108ba848461290c565b600060208284031215612c4e57600080fd5b60006108ba8484612917565b6000612c668383612e33565b505060200190565b6000612c7a83836135c0565b505060600190565b6000612c8e83836135f7565b505060400190565b612c9f81613ad5565b82525050565b612c9f81613aad565b6000612cb982613a9b565b612cc38185613a9f565b9350612cce83613a95565b8060005b83811015612cfc578151612ce68882612c5a565b9750612cf183613a95565b925050600101612cd2565b509495945050505050565b6000612d1282613a9b565b612d1c8185613a9f565b9350612d2783613a95565b8060005b83811015612cfc578151612d3f8882612c6e565b9750612d4a83613a95565b925050600101612d2b565b6000612d6082613a9b565b612d6a8185613a9f565b9350612d7583613a95565b8060005b83811015612cfc578151612d8d8882612c82565b9750612d9883613a95565b925050600101612d79565b6000612daf8385613a9f565b93506001600160fb1b03831115612dc557600080fd5b602083029250612dd6838584613af2565b50500190565b6000612de782613a9b565b612df18185613a9f565b9350612dfc83613a95565b8060005b83811015612cfc578151612e148882612c5a565b9750612e1f83613a95565b925050600101612e00565b612c9f81613ab8565b612c9f81610617565b612c9f612e4882610617565b610617565b612c9f81613adc565b6000612e6182613a9b565b612e6b8185613a9f565b9350612e7b818560208601613afe565b612e8481613b2a565b9093019392505050565b6000612e9b603583613a9f565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7581527402063616e20616363657074206f776e65727368697605c1b602082015260400192915050565b6000612ef2602483613a9f565b7f4163636f756e74206d6967726174696f6e2069732070656e64696e6720616c728152636561647960e01b602082015260400192915050565b6000612f38601b83613a9f565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b6000612f71603383613a9f565b7f43616e6e6f7420657363726f7720776974682030206475726174696f6e204f528152721030b137bb329036b0bc2fb23ab930ba34b7b760691b602082015260400192915050565b6000612fc6602483613a9f565b7f43616e6e6f742063726561746520657363726f772077697468206164647265738152637328302960e01b602082015260400192915050565b600061300c601e83613a9f565b7f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815260200192915050565b6000613045601b83613a9f565b7f43616e6e6f742062652072756e206f6e2074686973206c617965720000000000815260200192915050565b600061307e603183613a9f565b7f4e756d626572206f66206163636f756e747320616e642076657374656442616c8152700c2dcc6cae640c8dedc4ee840dac2e8c6d607b1b602082015260400192915050565b60006130d1601b83613a9f565b7f4e6f20657363726f77206d6967726174696f6e2070656e64696e670000000000815260200192915050565b600061310a601183613aa8565b70026b4b9b9b4b7339030b2323932b9b99d1607d1b815260110192915050565b6000613137601783613a9f565b7f5175616e746974792063616e6e6f74206265207a65726f000000000000000000815260200192915050565b6000613170604783613a9f565b7f4d75737420626520656e6f7567682062616c616e636520696e2074686520636f81527f6e747261637420746f2070726f7669646520666f72207468652076657374696e6020820152666720656e74727960c81b604082015260600192915050565b60006131df601983613a9f565b7f4163636f756e74206d657267696e672068617320656e64656400000000000000815260200192915050565b6000613218601583613a9f565b741d1bdad95b881d1c985b9cd9995c8819985a5b1959605a1b815260200192915050565b6000613249603983613a9f565b7f43616e206f6e6c7920626520696e766f6b65642062792053796e74686574697881527f427269646765546f4f7074696d69736d20636f6e747261637400000000000000602082015260400192915050565b60006132a8602483613a9f565b7f43616e6e6f74206e6f6d696e617465206f776e206163636f756e7420746f206d8152636572676560e01b602082015260400192915050565b60006132ee601283613a9f565b71115b9d1c9e4812511cc81c995c5d5a5c995960721b815260200192915050565b600061331c602f83613a9f565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726681526e37b936903a3434b99030b1ba34b7b760891b602082015260400192915050565b631cd554d160e21b9052565b6000613379602183613a9f565b7f41646472657373206973206e6f74206e6f6d696e6174656420746f206d6572678152606560f81b602082015260400192915050565b60006133bc602983613a9f565b7f4163636f756e7420616e6420657363726f77416d6f756e7473204c656e677468815268040dad2e6dac2e8c6d60bb1b602082015260400192915050565b6000613407602983613a9f565b7f43616e206f6e6c7920706572666f726d207468697320616374696f6e206475728152680696e672073657475760bc1b602082015260400192915050565b6000613452601c83613a9f565b7f65786365656473206d6178206d657267696e67206475726174696f6e00000000815260200192915050565b600061348b601983613aa8565b7f5265736f6c766572206d697373696e67207461726765743a2000000000000000815260190192915050565b60006134c4602883613a9f565b7f4f6e6c792074686520466565506f6f6c2063616e20706572666f726d20746869815267399030b1ba34b7b760c11b602082015260400192915050565b600061350e602b83613a9f565b7f4e756d626572206f66206163636f756e747320616e642062616c616e6365732081526a0c8dedc4ee840dac2e8c6d60ab1b602082015260400192915050565b600061355b601b83613a9f565b7f4164647265737320657363726f772062616c616e636520697320300000000000815260200192915050565b6000613594601f83613a9f565b7f43616e6e6f74206d65726765206163636f756e74732077697468206465627400815260200192915050565b805160608301906135d18482613624565b5060208201516135e46020850182612e33565b506040820151611a256040850182612e33565b805160408301906136088482613624565b506020820151611a256020850182612e33565b612c9f81613ae7565b612c9f81613ac9565b6000613638826130fd565b91506136448284612e3c565b50602001919050565b60006136388261347e565b602081016108be8284612ca5565b606081016136748286612c96565b6136816020830185612ca5565b61368e6040830184612e33565b949350505050565b604081016136a48284612c96565b6108be60208301613360565b608081016136be8288612c96565b6136cb6020830187612e33565b81810360408301526136de818587612da3565b90506136ed6060830184612e33565b9695505050505050565b604081016137058285612ca5565b610e696020830184612ca5565b604081016136a48284612ca5565b6040810161372e8285612ca5565b610e696020830184612e33565b60208082528101610e698184612cae565b60208082528101610e698184612d07565b6060808252810161376f818688612da3565b905061377e6020830185612e33565b61378b6040830184612e33565b95945050505050565b60208082528101610e698184612ddc565b602081016108be8284612e2a565b602081016108be8284612e33565b604081016137058285612e33565b604081016137dd8285612e33565b818103602083015261368e8184612e56565b602081016108be8284612e4d565b60208082528101610e698184612e56565b602080825281016108be81612e8e565b602080825281016108be81612ee5565b602080825281016108be81612f2b565b602080825281016108be81612f64565b602080825281016108be81612fb9565b602080825281016108be81612fff565b602080825281016108be81613038565b602080825281016108be81613071565b602080825281016108be816130c4565b602080825281016108be8161312a565b602080825281016108be81613163565b602080825281016108be816131d2565b602080825281016108be8161320b565b602080825281016108be8161323c565b602080825281016108be8161329b565b602080825281016108be816132e1565b602080825281016108be8161330f565b602080825281016108be8161336c565b602080825281016108be816133af565b602080825281016108be816133fa565b602080825281016108be81613445565b602080825281016108be816134b7565b602080825281016108be81613501565b602080825281016108be8161354e565b602080825281016108be81613587565b604081016139ac8285612e33565b818103602083015261368e8184612d55565b6040810161372e8285612e33565b606081016139da8286612e33565b6136816020830185612e33565b608081016139f58287612e33565b613a026020830186612e33565b613a0f6040830185612e33565b61378b6060830184612e33565b60608101613a2a8286612e33565b613a376020830185612e33565b61368e604083018461361b565b6040810161372e8285613624565b6040518181016001600160401b0381118282101715613a7057600080fd5b604052919050565b60006001600160401b03821115613a8e57600080fd5b5060200290565b60200190565b5190565b90815260200190565b919050565b60006108be82613abd565b151590565b6001600160a01b031690565b6001600160401b031690565b60006108be825b60006108be82613aad565b60006108be82613ac9565b82818337506000910152565b60005b83811015613b19578181015183820152602001613b01565b83811115611a255750506000910152565b601f01601f191690565b613b3d81613aad565b811461116b57600080fd5b613b3d81613ab8565b613b3d8161061756fea365627a7a7231582039a56045b6bf760d8bf527fe78d2326d226ae63ab32f8abad0f368f4d85eb2bd6c6578706572696d656e74616cf564736f6c63430005100040000000000000000000000000b64ff7a4a33acdf48d97dab0d764afd0f6176882000000000000000000000000242a3df52c375bee81b1c668741d7c63af68fdd2

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000b64ff7a4a33acdf48d97dab0d764afd0f6176882000000000000000000000000242a3df52c375bee81b1c668741d7c63af68fdd2

-----Decoded View---------------
Arg [0] : _owner (address): 0xb64ff7a4a33acdf48d97dab0d764afd0f6176882
Arg [1] : _resolver (address): 0x242a3df52c375bee81b1c668741d7c63af68fdd2

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000b64ff7a4a33acdf48d97dab0d764afd0f6176882
Arg [1] : 000000000000000000000000242a3df52c375bee81b1c668741d7c63af68fdd2


Libraries Used


Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.