OP Sepolia Testnet

Contract

0xbfd66fa5668612afDdAAf48F818665F0b34128C6

Overview

ETH Balance

0 ETH

Sponsored

Transaction Hash
Method
Block
From
To
Value
0x6080604075568412024-02-02 23:23:42141 days ago1706916222IN
 Contract Creation
0 ETH0.000000280.00010025

Advanced mode:
Parent Transaction Hash Block From To Value
View All Internal Transactions

Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0xfcb829EC...99BBd2A09
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
ImportableRewardEscrowV2Frozen

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 sepolia-optimm.etherscan.io on 2024-02-02
*/

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

* Synthetix: RewardEscrowV2Frozen/ImportableRewardEscrowV2Frozen.sol
*
* Latest source (may be newer): https://github.com/Synthetixio/synthetix/blob/master/contracts/RewardEscrowV2Frozen/ImportableRewardEscrowV2Frozen.sol
* Docs: https://docs.synthetix.io/contracts/RewardEscrowV2Frozen/ImportableRewardEscrowV2Frozen
*
* Contract Dependencies: 
*	- BaseRewardEscrowV2Frozen
*	- IAddressResolver
*	- Owned
* Libraries: 
*	- SafeDecimalMath
*	- SafeMath
*	- VestingEntries
*
* MIT License
* ===========
*
* Copyright (c) 2024 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;
pragma experimental ABIEncoderV2;

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

/// SIP-252: this is the interface for immutable V2 escrow (renamed with suffix Frozen).
/// These sources need to exist here and match on-chain frozen contracts for tests and reference.
/// the reason for the naming mess is that the immutable LiquidatorRewards expects a working
/// RewardEscrowV2 resolver entry for its getReward method, so the "new" (would be V3)
/// needs to be found at that entry for liq-rewards to function.
interface IRewardEscrowV2Frozen {
    // Views
    function balanceOf(address account) external view returns (uint);

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

    function totalEscrowedBalance() 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);

    function nextEntryId() external view returns (uint);

    function vestingSchedules(address account, uint256 entryId) external view returns (VestingEntries.VestingEntry memory);

    function accountVestingEntryIDs(address account, uint256 index) external view returns (uint);

    //function totalEscrowedAccountBalance(address account) external view returns (uint);
    //function totalVestedAccountBalance(address account) external view returns (uint);
}


// 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 allNetworksDebtInfo()
        external
        view
        returns (
            uint256 debt,
            uint256 sharesSupply,
            bool isStale
        );

    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 excludeOtherCollateral) external view returns (uint);

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

    function liquidationAmounts(address account, bool isSelfLiquidation)
        external
        view
        returns (
            uint totalRedeemed,
            uint debtToRemove,
            uint escrowToLiquidate,
            uint initialDebtBalance
        );

    // Restricted: used internally to Synthetix
    function addSynths(ISynth[] calldata synthsToAdd) external;

    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 burnForRedemption(
        address deprecatedSynthProxy,
        address account,
        uint balance
    ) external;

    function setCurrentPeriodId(uint128 periodId) external;

    function liquidateAccount(address account, bool isSelfLiquidation)
        external
        returns (
            uint totalRedeemed,
            uint debtRemoved,
            uint escrowToLiquidate
        );

    function issueSynthsWithoutDebt(
        bytes32 currencyKey,
        address to,
        uint amount
    ) external returns (bool rateInvalid);

    function burnSynthsWithoutDebt(
        bytes32 currencyKey,
        address to,
        uint amount
    ) external returns (bool rateInvalid);

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


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


// 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");
        _;
    }
}


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

    // Computes `a - b`, setting the value to 0 if b > a.
    function floorsub(uint a, uint b) internal pure returns (uint) {
        return b >= a ? 0 : a - b;
    }

    /* ---------- Utilities ---------- */
    /*
     * Absolute value of the input, returned as a signed number.
     */
    function signedAbs(int x) internal pure returns (int) {
        return x < 0 ? -x : x;
    }

    /*
     * Absolute value of the input, returned as an unsigned number.
     */
    function abs(int x) internal pure returns (uint) {
        return uint(signedAbs(x));
    }
}


// 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 feesBurned(address account) external view returns (uint);

    function feesToBurn(address account) external view returns (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 totalFeesBurned() 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;

    function closeSecondary(uint snxBackedDebt, uint debtShareSupply) 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 totalIssuedSynthsExcludeOtherCollateral(bytes32 currencyKey) external view returns (uint);

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

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

    // 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 rewardAddress,
        bytes32 trackingCode
    ) external returns (uint amountReceived);

    function exchangeWithTrackingForInitiator(
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey,
        address rewardAddress,
        bytes32 trackingCode
    ) external returns (uint amountReceived);

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

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

    function exchangeAtomically(
        bytes32 sourceCurrencyKey,
        uint sourceAmount,
        bytes32 destinationCurrencyKey,
        bytes32 trackingCode,
        uint minAmount
    ) external returns (uint amountReceived);

    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) external returns (bool);

    function liquidateDelinquentAccountEscrowIndex(address account, uint escrowStartIndex) external returns (bool);

    function liquidateSelf() external returns (bool);

    // Restricted Functions

    function mintSecondary(address account, uint amount) external;

    function mintSecondaryRewards(uint amount) external;

    function burnSecondary(address account, uint amount) external;

    function revokeAllEscrow(address account) external;

    function migrateAccountBalances(address account) external returns (uint totalEscrowRevoked, uint totalLiquidBalance);
}


// Inheritance


// Libraries


// Internal references


// https://docs.synthetix.io/contracts/RewardEscrow
/// SIP-252: this is the source for the base of immutable V2 escrow (renamed with suffix Frozen).
/// These sources need to exist here and match on-chain frozen contracts for tests and reference.
/// The reason for the naming mess is that the immutable LiquidatorRewards expects a working
/// RewardEscrowV2 resolver entry for its getReward method, so the "new" (would be V3)
/// needs to be found at that entry for liq-rewards to function.
contract BaseRewardEscrowV2Frozen is Owned, IRewardEscrowV2Frozen, LimitedSetup(8 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);
    }

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

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

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


// Inheritance


// https://docs.synthetix.io/contracts/RewardEscrow
/// SIP-252: this is the source for immutable V2 escrow on L2 (renamed with suffix Frozen).
/// These sources need to exist here and match on-chain frozen contracts for tests and reference.
/// The reason for the naming mess is that the immutable LiquidatorRewards expects a working
/// RewardEscrowV2 resolver entry for its getReward method, so the "new" (would be V3)
/// needs to be found at that entry for liq-rewards to function.
contract ImportableRewardEscrowV2Frozen is BaseRewardEscrowV2Frozen {
    /* ========== ADDRESS RESOLVER CONFIGURATION ========== */
    bytes32 private constant CONTRACT_SYNTHETIX_BRIDGE_BASE = "SynthetixBridgeToBase";

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

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

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

    function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
        bytes32[] memory existingAddresses = BaseRewardEscrowV2Frozen.resolverAddressesRequired();
        bytes32[] memory newAddresses = new bytes32[](1);
        newAddresses[0] = CONTRACT_SYNTHETIX_BRIDGE_BASE;
        return combineArrays(existingAddresses, newAddresses);
    }

    function synthetixBridgeToBase() internal view returns (address) {
        return requireAndGetAddress(CONTRACT_SYNTHETIX_BRIDGE_BASE);
    }

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

    function importVestingEntries(
        address account,
        uint256 escrowedAmount,
        VestingEntries.VestingEntry[] calldata vestingEntries
    ) external onlySynthetixBridge {
        // There must be enough balance in the contract to provide for the escrowed balance.
        totalEscrowedBalance = totalEscrowedBalance.add(escrowedAmount);
        require(
            totalEscrowedBalance <= IERC20(address(synthetix())).balanceOf(address(this)),
            "Insufficient balance in the contract to provide for escrowed balance"
        );

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

        for (uint i = 0; i < vestingEntries.length; i++) {
            _importVestingEntry(account, vestingEntries[i]);
        }
    }

    function _importVestingEntry(address account, VestingEntries.VestingEntry memory entry) internal {
        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);
    }

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

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":false,"internalType":"bytes32","name":"name","type":"bytes32"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"CacheUpdated","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":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":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"name":"burnForMigration","outputs":[{"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[]"}],"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":"account","type":"address"},{"internalType":"uint256","name":"escrowedAmount","type":"uint256"},{"components":[{"internalType":"uint64","name":"endTime","type":"uint64"},{"internalType":"uint256","name":"escrowAmount","type":"uint256"}],"internalType":"struct VestingEntries.VestingEntry[]","name":"vestingEntries","type":"tuple[]"}],"name":"importVestingEntries","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":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"name":"migrateAccountEscrowBalances","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"","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":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":"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"}]

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102535760003560e01c80636dc05bd31161014657806380d46f58116100c3578063ae58254911610087578063ae582549146104c1578063b95375bd146104d4578063cd7b43dd146104e7578063e6b2cf6c146104fa578063eac6248914610502578063f0b882ba1461052257610253565b806380d46f5814610468578063899ffef4146104895780638da5cb5b1461049e578063910a326d146104a6578063a0416ed3146104ae57610253565b8063773ab39f1161010a578063773ab39f146104075780637839b92f146104275780637993e6991461043a57806379ba50971461044d5780637cc1d7561461045557610253565b80636dc05bd3146103be57806370a08231146103d157806371e780f3146103e457806373307e40146103ec57806374185360146103ff57610253565b806330104c5f116101d457806345626bd61161019857806345626bd61461036557806346ba2d901461038657806353a47bb71461038e5780635eb8cf25146103a35780636154c343146103ab57610253565b806330104c5f14610311578063326a3cfb1461032457806334c7fec91461033757806337088ffc1461034a5780634525aabc1461035257610253565b8063178c56551161021b578063178c5655146102c85780631bb47b44146102d0578063204b676a146102e3578063227d517a146102f65780632af64bd31461030957610253565b8063018c6c551461025857806304f3bcec1461026d578063056629861461028b5780630fcdefb7146102a05780631627540c146102b5575b600080fd5b61026b61026636600461223b565b610535565b005b61027561057d565b6040516102829190612c1a565b60405180910390f35b61029361058c565b6040516102829190612bd0565b6102a86105ad565b6040516102829190612bde565b61026b6102c3366004611fa1565b6105b3565b61026b610606565b61026b6102de3660046120d3565b610663565b6102a86102f1366004611fa1565b6106b4565b6102a8610304366004611fa1565b6106cf565b6102936106e1565b6102a861031f366004612032565b6107f8565b6102a8610332366004611fa1565b610857565b61026b6103453660046121be565b610869565b6102a861091f565b61026b61036036600461223b565b610925565b610378610373366004612032565b610962565b604051610282929190612dc5565b6102a8610992565b610396610998565b6040516102829190612aba565b6102a86109a7565b6103786103b9366004612032565b6109ad565b6102a86103cc366004611fdd565b6109e7565b6102a86103df366004611fa1565b610a94565b6102a8610aaf565b6103966103fa366004611fa1565b610ab5565b61026b610ad0565b61041a6104153660046120d3565b610c26565b6040516102829190612bae565b61026b610435366004611fa1565b610dc6565b61026b61044836600461223b565b610dd1565b61026b610e30565b61026b610463366004611fa1565b610ecc565b61047b610476366004611fdd565b61101c565b604051610282929190612d59565b610491611030565b6040516102829190612b9d565b6103966110a4565b6102a86110b3565b61026b6104bc3660046120d3565b6110b9565b6102a86104cf366004612032565b611184565b61026b6104e2366004612120565b6111b2565b61026b6104f536600461206c565b6111c2565b6102a861133c565b6105156105103660046120d3565b611342565b6040516102829190612bbf565b61026b610530366004611fdd565b61142e565b61053d61176a565b600d8190556040517fe829efae5d8a2f7163f46c23a8190bf14625c1e446561ca0f5cf279ab7c8015e90610572908390612bde565b60405180910390a150565b6003546001600160a01b031681565b6000426105a6600e54600f5461179690919063ffffffff16565b1190505b90565b600f5481565b6105bb61176a565b600180546001600160a01b0319166001600160a01b0383161790556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290610572908390612aba565b61060e61176a565b42600f819055600e547fceade2b9bc02350b17075c94bb699508b89ed2752f501ea42024b1bb5fd34445919061064b90829063ffffffff61179616565b604051610659929190612d79565b60405180910390a1565b61066b6117bb565b6001600160a01b0316336001600160a01b0316146106a45760405162461bcd60e51b815260040161069b90612d29565b60405180910390fd5b6106af8383836117d5565b505050565b6001600160a01b031660009081526006602052604090205490565b60096020526000908152604090205481565b600060606106ed611030565b905060005b81518110156107ef57600082828151811061070957fe5b60209081029190910181015160008181526004928390526040908190205460035491516321f8a72160e01b81529294506001600160a01b03908116939116916321f8a7219161075a91869101612bde565b60206040518083038186803b15801561077257600080fd5b505afa158015610786573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506107aa9190810190611fbf565b6001600160a01b03161415806107d557506000818152600460205260409020546001600160a01b0316155b156107e657600093505050506105aa565b506001016106f2565b50600191505090565b6000610802611e4e565b506001600160a01b0383166000908152600560209081526040808320858452825291829020825180840190935280546001600160401b03168352600101549082015261084d816119ed565b9150505b92915050565b60086020526000908152604090205481565b6000805b8281101561090e573360009081526005602052604081208186868581811061089157fe5b90506020020135815260200190815260200160002090508060010154600014610905576040805180820190915281546001600160401b03168152600182015460208201526000906108e1906119ed565b905080156108f157600060018301555b610901848263ffffffff61179616565b9350505b5060010161086d565b5080156106af576106af3382611a1e565b600d5481565b61092d61176a565b600c8190556040517f6b92bd20c4b2e6861047ba7209ddc78d538419aae187d0df46716b827b8997a490610572908390612bde565b6005602090815260009283526040808420909152908252902080546001909101546001600160401b039091169082565b60025481565b6001546001600160a01b031681565b600c5481565b6001600160a01b039190911660009081526005602090815260408083209383529290522080546001909101546001600160401b0390911691565b6000805b82811015610a8c576109fb611e4e565b6001600160a01b038616600090815260056020526040812090868685818110610a2057fe5b60209081029290920135835250818101929092526040908101600020815180830190925280546001600160401b0316825260010154918101829052915015610a83576000610a6d826119ed565b9050610a7f848263ffffffff61179616565b9350505b506001016109eb565b509392505050565b6001600160a01b031660009081526008602052604090205490565b600b5481565b600a602052600090815260409020546001600160a01b031681565b6060610ada611030565b905060005b8151811015610c22576000828281518110610af657fe5b602002602001015190506000600360009054906101000a90046001600160a01b03166001600160a01b031663dacb2d018384604051602001610b389190612aaf565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610b64929190612bfa565b60206040518083038186803b158015610b7c57600080fd5b505afa158015610b90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610bb49190810190611fbf565b6000838152600460205260409081902080546001600160a01b0319166001600160a01b038416179055519091507f88a93678a3692f6789d9546fc621bf7234b101ddb7d4fe479455112831b8aa6890610c109084908490612bec565b60405180910390a15050600101610adf565b5050565b6060828201838111610c6c576040805160008082526020820190925290610c63565b610c50611e65565b815260200190600190039081610c485790505b50915050610dbf565b6001600160a01b038516600090815260066020526040902054811115610ca757506001600160a01b0384166000908152600660205260409020545b604080518583038082526020808202830101909252606090828015610ce657816020015b610cd3611e65565b815260200190600190039081610ccb5790505b50905060005b82811015610db9576001600160a01b03881660009081526006602052604081208054838a01908110610d1a57fe5b90600052602060002001549050610d2f611e4e565b506001600160a01b03891660009081526005602090815260408083208484528252918290208251808401845281546001600160401b03908116825260019092015481840190815284516060810186528251909316835251928201929092529182018390528451909190859085908110610da457fe5b60209081029190910101525050600101610cec565b50925050505b9392505050565b610dce611b39565b50565b610dd961176a565b600d54811115610dfb5760405162461bcd60e51b815260040161069b90612d19565b600e8190556040517f723c43349da7aeae47190396f2e2fbe6bedb46b9e9705bc5b908d65bc7a1e0e690610572908390612bde565b6001546001600160a01b03163314610e5a5760405162461bcd60e51b815260040161069b90612c39565b6000546001546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c92610e9d926001600160a01b0391821692911690612b59565b60405180910390a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b6001600160a01b038116331415610ef55760405162461bcd60e51b815260040161069b90612ce9565b610efd61058c565b610f195760405162461bcd60e51b815260040161069b90612cc9565b610f21611b51565b6001600160a01b031663d37c4d8b336040518263ffffffff1660e01b8152600401610f4c9190612af8565b60206040518083038186803b158015610f6457600080fd5b505afa158015610f78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610f9c9190810190612259565b15610fb95760405162461bcd60e51b815260040161069b90612d49565b336000818152600a60205260409081902080546001600160a01b0319166001600160a01b038516179055517fcf51776bb16e5780edcca2e64a9ba8a9c7d5d00a6699cbd7606e465361ba485290611011908490612aba565b60405180910390a250565b60006060611028611b39565b935093915050565b60608061103b611b65565b60408051600180825281830190925291925060609190602080830190803883390190505090507453796e746865746978427269646765546f4261736560581b8160008151811061108757fe5b60200260200101818152505061109d8282611bf7565b9250505090565b6000546001600160a01b031681565b600e5481565b6001600160a01b0383166110df5760405162461bcd60e51b815260040161069b90612c69565b6110e7611cb3565b6001600160a01b03166323b872dd3330856040518463ffffffff1660e01b815260040161111693929190612ac8565b602060405180830381600087803b15801561113057600080fd5b505af1158015611144573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061116891908101906121ff565b6106a45760405162461bcd60e51b815260040161069b90612cd9565b6006602052816000526040600020818154811061119d57fe5b90600052602060002001600091509150505481565b6111ba611b39565b505050505050565b6111ca611cca565b6001600160a01b0316336001600160a01b0316146111fa5760405162461bcd60e51b815260040161069b90612c79565b600b5461120d908463ffffffff61179616565b600b55611218611cb3565b6001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016112439190612aba565b60206040518083038186803b15801561125b57600080fd5b505afa15801561126f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506112939190810190612259565b600b5411156112b45760405162461bcd60e51b815260040161069b90612d39565b6001600160a01b0384166000908152600860205260409020546112dd908463ffffffff61179616565b6001600160a01b0385166000908152600860205260408120919091555b818110156113355761132d8584848481811061131257fe5b905060400201803603611328919081019061221d565b611ced565b6001016112fa565b5050505050565b60075481565b6001600160a01b0383166000908152600660205260409020546060908383019081111561138457506001600160a01b0384166000908152600660205260409020545b8381116113a1576040805160008082526020820190925290610c63565b6040805185830380825260208082028301019092526060908280156113d0578160200160208202803883390190505b50905060005b82811015610db9576001600160a01b0388166000908152600660205260409020805482890190811061140457fe5b906000526020600020015482828151811061141b57fe5b60209081029190910101526001016113d6565b61143661058c565b6114525760405162461bcd60e51b815260040161069b90612cc9565b61145a611b51565b6001600160a01b031663d37c4d8b846040518263ffffffff1660e01b81526004016114859190612b74565b60206040518083038186803b15801561149d57600080fd5b505afa1580156114b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506114d59190810190612259565b156114f25760405162461bcd60e51b815260040161069b90612d49565b6001600160a01b038381166000908152600a602052604090205416331461152b5760405162461bcd60e51b815260040161069b90612d09565b6000805b828110156116aa5761153f611e4e565b6001600160a01b03861660009081526005602052604081209086868581811061156457fe5b60209081029290920135835250818101929092526040908101600020815180830190925280546001600160401b03168252600101549181018290529150156116a15733600090815260056020526040812082918787868181106115c357fe5b60209081029290920135835250818101929092526040016000208251815467ffffffffffffffff19166001600160401b0390911617815591810151600190920191909155810151611615908490611796565b33600090815260066020526040902090935085858481811061163357fe5b8354600181018555600094855260208086209281029490940135910155506001600160a01b038816825260059052604081209086868581811061167257fe5b602090810292909201358352508101919091526040016000908120805467ffffffffffffffff19168155600101555b5060010161152f565b506001600160a01b0384166000908152600860205260409020546116d4908263ffffffff611d6a16565b6001600160a01b038516600090815260086020526040808220929092553381522054611706908263ffffffff61179616565b33600081815260086020526040908190209290925590516001600160a01b038616917f48d567deaa7db90f8a443344e519ca8906521ffe118e1df43e89a3c257963f7c9161175c91908590889088904290612b12565b60405180910390a250505050565b6000546001600160a01b031633146117945760405162461bcd60e51b815260040161069b90612cf9565b565b600082820183811015610dbf5760405162461bcd60e51b815260040161069b90612c49565b60006117d066119959541bdbdb60ca1b611d92565b905090565b816117f25760405162461bcd60e51b815260040161069b90612ca9565b6000811180156118045750600c548111155b6118205760405162461bcd60e51b815260040161069b90612c59565b600b54611833908363ffffffff61179616565b600b5561183e611cb3565b6001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016118699190612aba565b60206040518083038186803b15801561188157600080fd5b505afa158015611895573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506118b99190810190612259565b600b5411156118da5760405162461bcd60e51b815260040161069b90612cb9565b6001600160a01b03831660009081526008602052604090205442820190611907908463ffffffff61179616565b6001600160a01b03851660008181526008602090815260408083209490945560078054855180870187526001600160401b0388811682528185018b81528787526005865288872084885286528887209251835467ffffffffffffffff1916921691909117825551600191820155948452600683529483208054808601825590845291909220018390555461199a91611796565b6007556040516001600160a01b038616907f2cc016694185d38abbe28d9e9baea2e9d95a321ae43475e5ea7b643756840bc0906119de904290889088908790612d87565b60405180910390a25050505050565b60008082602001516000146108515782516001600160401b0316421015611a15576000610dbf565b50506020015190565b611a288282611def565b6001600160a01b038216600090815260096020526040902054611a51908263ffffffff61179616565b6001600160a01b038316600090815260096020526040902055611a72611cb3565b6001600160a01b031663a9059cbb83836040518363ffffffff1660e01b8152600401611a9f929190612b82565b602060405180830381600087803b158015611ab957600080fd5b505af1158015611acd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611af191908101906121ff565b50816001600160a01b03167ffbeff59d2bfda0d79ea8a29f8c57c66d48c7a13eabbdb90908d9115ec41c9dc64283604051611b2d929190612d79565b60405180910390a25050565b60405162461bcd60e51b815260040161069b90612c99565b60006117d06524b9b9bab2b960d11b611d92565b60408051600380825260808201909252606091602082018380388339019050509050680a6f2dce8d0cae8d2f60bb1b81600081518110611ba157fe5b60200260200101818152505066119959541bdbdb60ca1b81600181518110611bc557fe5b6020026020010181815250506524b9b9bab2b960d11b81600281518110611be857fe5b60200260200101818152505090565b60608151835101604051908082528060200260200182016040528015611c27578160200160208202803883390190505b50905060005b8351811015611c6957838181518110611c4257fe5b6020026020010151828281518110611c5657fe5b6020908102919091010152600101611c2d565b5060005b8251811015611cac57828181518110611c8257fe5b6020026020010151828286510181518110611c9957fe5b6020908102919091010152600101611c6d565b5092915050565b60006117d0680a6f2dce8d0cae8d2f60bb1b611d92565b60006117d07453796e746865746978427269646765546f4261736560581b611d92565b600780546001600160a01b038416600081815260056020908152604080832085845282528083208751815467ffffffffffffffff19166001600160401b03909116178155878301516001918201559383526006825282208054808501825590835291200182905591549091611d629190611796565b600755505050565b600082821115611d8c5760405162461bcd60e51b815260040161069b90612c89565b50900390565b60008181526004602090815260408083205490516001600160a01b039091169182151591611dc291869101612a8f565b60405160208183030381529060405290611cac5760405162461bcd60e51b815260040161069b9190612c28565b600b54611e02908263ffffffff611d6a16565b600b556001600160a01b038216600090815260086020526040902054611e2e908263ffffffff611d6a16565b6001600160a01b0390921660009081526008602052604090209190915550565b604080518082019091526000808252602082015290565b604051806060016040528060006001600160401b0316815260200160008152602001600081525090565b803561085181612e8d565b805161085181612e8d565b60008083601f840112611eb757600080fd5b5081356001600160401b03811115611ece57600080fd5b602083019150836020820283011115611ee657600080fd5b9250929050565b60008083601f840112611eff57600080fd5b5081356001600160401b03811115611f1657600080fd5b602083019150836040820283011115611ee657600080fd5b805161085181612ea1565b600060408284031215611f4b57600080fd5b611f556040612dd3565b90506000611f638484611f96565b8252506020611f7484848301611f80565b60208301525092915050565b803561085181612eaa565b805161085181612eaa565b803561085181612eb3565b600060208284031215611fb357600080fd5b600061084d8484611e8f565b600060208284031215611fd157600080fd5b600061084d8484611e9a565b600080600060408486031215611ff257600080fd5b6000611ffe8686611e8f565b93505060208401356001600160401b0381111561201a57600080fd5b61202686828701611ea5565b92509250509250925092565b6000806040838503121561204557600080fd5b60006120518585611e8f565b925050602061206285828601611f80565b9150509250929050565b6000806000806060858703121561208257600080fd5b600061208e8787611e8f565b945050602061209f87828801611f80565b93505060408501356001600160401b038111156120bb57600080fd5b6120c787828801611eed565b95989497509550505050565b6000806000606084860312156120e857600080fd5b60006120f48686611e8f565b935050602061210586828701611f80565b925050604061211686828701611f80565b9150509250925092565b6000806000806000806060878903121561213957600080fd5b86356001600160401b0381111561214f57600080fd5b61215b89828a01611ea5565b965096505060208701356001600160401b0381111561217957600080fd5b61218589828a01611ea5565b945094505060408701356001600160401b038111156121a357600080fd5b6121af89828a01611ea5565b92509250509295509295509295565b600080602083850312156121d157600080fd5b82356001600160401b038111156121e757600080fd5b6121f385828601611ea5565b92509250509250929050565b60006020828403121561221157600080fd5b600061084d8484611f2e565b60006040828403121561222f57600080fd5b600061084d8484611f39565b60006020828403121561224d57600080fd5b600061084d8484611f80565b60006020828403121561226b57600080fd5b600061084d8484611f8b565b60006122838383612450565b505060200190565b60006122978383612a25565b505060600190565b60006122ab8383612a62565b505060400190565b6122bc81612e39565b82525050565b6122bc81612e11565b60006122d682612dff565b6122e08185612e03565b93506122eb83612df9565b8060005b838110156123195781516123038882612277565b975061230e83612df9565b9250506001016122ef565b509495945050505050565b600061232f82612dff565b6123398185612e03565b935061234483612df9565b8060005b8381101561231957815161235c888261228b565b975061236783612df9565b925050600101612348565b600061237d82612dff565b6123878185612e03565b935061239283612df9565b8060005b838110156123195781516123aa888261229f565b97506123b583612df9565b925050600101612396565b60006123cc8385612e03565b93506001600160fb1b038311156123e257600080fd5b6020830292506123f3838584612e4b565b50500190565b600061240482612dff565b61240e8185612e03565b935061241983612df9565b8060005b838110156123195781516124318882612277565b975061243c83612df9565b92505060010161241d565b6122bc81612e1c565b6122bc816105aa565b6122bc612465826105aa565b6105aa565b6122bc81612e40565b600061247e82612dff565b6124888185612e03565b9350612498818560208601612e57565b6124a181612e83565b9093019392505050565b60006124b8603583612e03565b7f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7581527402063616e20616363657074206f776e65727368697605c1b602082015260400192915050565b600061250f601b83612e03565b7f536166654d6174683a206164646974696f6e206f766572666c6f770000000000815260200192915050565b6000612548603383612e03565b7f43616e6e6f7420657363726f7720776974682030206475726174696f6e204f528152721030b137bb329036b0bc2fb23ab930ba34b7b760691b602082015260400192915050565b600061259d602483612e03565b7f43616e6e6f742063726561746520657363726f772077697468206164647265738152637328302960e01b602082015260400192915050565b60006125e3603583612e03565b7f43616e206f6e6c7920626520696e766f6b65642062792053796e746865746978815274109c9a5919d9551bd0985cd94818dbdb9d1c9858dd605a1b602082015260400192915050565b600061263a601e83612e03565b7f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815260200192915050565b6000612673601b83612e03565b7f43616e6e6f742062652072756e206f6e2074686973206c617965720000000000815260200192915050565b60006126ac601183612e0c565b70026b4b9b9b4b7339030b2323932b9b99d1607d1b815260110192915050565b60006126d9601783612e03565b7f5175616e746974792063616e6e6f74206265207a65726f000000000000000000815260200192915050565b6000612712604783612e03565b7f4d75737420626520656e6f7567682062616c616e636520696e2074686520636f81527f6e747261637420746f2070726f7669646520666f72207468652076657374696e6020820152666720656e74727960c81b604082015260600192915050565b6000612781601983612e03565b7f4163636f756e74206d657267696e672068617320656e64656400000000000000815260200192915050565b60006127ba601583612e03565b741d1bdad95b881d1c985b9cd9995c8819985a5b1959605a1b815260200192915050565b60006127eb602483612e03565b7f43616e6e6f74206e6f6d696e617465206f776e206163636f756e7420746f206d8152636572676560e01b602082015260400192915050565b6000612831602f83612e03565b7f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726681526e37b936903a3434b99030b1ba34b7b760891b602082015260400192915050565b631cd554d160e21b9052565b600061288e602183612e03565b7f41646472657373206973206e6f74206e6f6d696e6174656420746f206d6572678152606560f81b602082015260400192915050565b60006128d1601c83612e03565b7f65786365656473206d6178206d657267696e67206475726174696f6e00000000815260200192915050565b600061290a601983612e0c565b7f5265736f6c766572206d697373696e67207461726765743a2000000000000000815260190192915050565b6000612943602883612e03565b7f4f6e6c792074686520466565506f6f6c2063616e20706572666f726d20746869815267399030b1ba34b7b760c11b602082015260400192915050565b600061298d604483612e03565b7f496e73756666696369656e742062616c616e636520696e2074686520636f6e7481527f7261637420746f2070726f7669646520666f7220657363726f7765642062616c602082015263616e636560e01b604082015260600192915050565b60006129f9601f83612e03565b7f43616e6e6f74206d65726765206163636f756e74732077697468206465627400815260200192915050565b80516060830190612a368482612a86565b506020820151612a496020850182612450565b506040820151612a5c6040850182612450565b50505050565b80516040830190612a738482612a86565b506020820151612a5c6020850182612450565b6122bc81612e2d565b6000612a9a8261269f565b9150612aa68284612459565b50602001919050565b6000612a9a826128fd565b6020810161085182846122c2565b60608101612ad682866122b3565b612ae360208301856122c2565b612af06040830184612450565b949350505050565b60408101612b0682846122b3565b61085160208301612875565b60808101612b2082886122b3565b612b2d6020830187612450565b8181036040830152612b408185876123c0565b9050612b4f6060830184612450565b9695505050505050565b60408101612b6782856122c2565b610dbf60208301846122c2565b60408101612b0682846122c2565b60408101612b9082856122c2565b610dbf6020830184612450565b60208082528101610dbf81846122cb565b60208082528101610dbf8184612324565b60208082528101610dbf81846123f9565b602081016108518284612447565b602081016108518284612450565b60408101612b678285612450565b60408101612c088285612450565b8181036020830152612af08184612473565b60208101610851828461246a565b60208082528101610dbf8184612473565b60208082528101610851816124ab565b6020808252810161085181612502565b602080825281016108518161253b565b6020808252810161085181612590565b60208082528101610851816125d6565b602080825281016108518161262d565b6020808252810161085181612666565b60208082528101610851816126cc565b6020808252810161085181612705565b6020808252810161085181612774565b60208082528101610851816127ad565b60208082528101610851816127de565b6020808252810161085181612824565b6020808252810161085181612881565b60208082528101610851816128c4565b6020808252810161085181612936565b6020808252810161085181612980565b60208082528101610851816129ec565b60408101612d678285612450565b8181036020830152612af08184612372565b60408101612b908285612450565b60808101612d958287612450565b612da26020830186612450565b612daf6040830185612450565b612dbc6060830184612450565b95945050505050565b60408101612b908285612a86565b6040518181016001600160401b0381118282101715612df157600080fd5b604052919050565b60200190565b5190565b90815260200190565b919050565b600061085182612e21565b151590565b6001600160a01b031690565b6001600160401b031690565b6000610851825b600061085182612e11565b82818337506000910152565b60005b83811015612e72578181015183820152602001612e5a565b83811115612a5c5750506000910152565b601f01601f191690565b612e9681612e11565b8114610dce57600080fd5b612e9681612e1c565b612e96816105aa565b612e9681612e2d56fea365627a7a72315820c7f566e2c4649f5b6c8dad13daf576bdc64f351038dc6f17a47c39f5b6fd33546c6578706572696d656e74616cf564736f6c63430005100040

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

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.