ETH Price: $3,100.07 (-0.91%)

Contract

0xb3e910fa4D7cd33CC1eAF5351c34E526A566c2dC
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Redeem127794022021-07-07 9:05:211232 days ago1625648721IN
0xb3e910fa...6A566c2dC
0 ETH0.0162920531
Cancel Request F...114523632020-12-14 17:06:561436 days ago1607965616IN
0xb3e910fa...6A566c2dC
0.00131517 ETH0.0072080852
Request Investme...114372512020-12-12 9:18:581439 days ago1607764738IN
0xb3e910fa...6A566c2dC
0.01173888 ETH0.0059896322
Execute Request ...112656712020-11-16 0:27:191465 days ago1605486439IN
0xb3e910fa...6A566c2dC
0.00624717 ETH0.0238663121
Request Investme...112618362020-11-15 10:21:361466 days ago1605435696IN
0xb3e910fa...6A566c2dC
0.0114848 ETH0.0050679419.7
Cancel Request F...109107262020-09-22 6:31:581520 days ago1600756318IN
0xb3e910fa...6A566c2dC
0.00207156 ETH0.0117844885
Enable Investmen...109006492020-09-20 17:39:111521 days ago1600623551IN
0xb3e910fa...6A566c2dC
0 ETH0.0091114166
Request Investme...109000072020-09-20 15:18:541521 days ago1600615134IN
0xb3e910fa...6A566c2dC
0.01277061 ETH0.05659416197
Redeem99013922020-04-19 7:14:121676 days ago1587280452IN
0xb3e910fa...6A566c2dC
0 ETH0.005207265.5
Redeem99013842020-04-19 7:12:091676 days ago1587280329IN
0xb3e910fa...6A566c2dC
0 ETH0.002551095
Execute Request ...98825472020-04-16 8:59:441679 days ago1587027584IN
0xb3e910fa...6A566c2dC
0.00911329 ETH0.0127539414
Cancel Request F...98694392020-04-14 8:25:391681 days ago1586852739IN
0xb3e910fa...6A566c2dC
0.00217265 ETH0.000860435.7
Redeem Quantity98651562020-04-13 16:43:451681 days ago1586796225IN
0xb3e910fa...6A566c2dC
0 ETH0.002040045
Request Investme...98629042020-04-13 8:21:011682 days ago1586766061IN
0xb3e910fa...6A566c2dC
0.01296657 ETH0.001423055
Execute Request ...98628532020-04-13 8:10:071682 days ago1586765407IN
0xb3e910fa...6A566c2dC
0.00744764 ETH0.003387275
Execute Request ...98628502020-04-13 8:09:311682 days ago1586765371IN
0xb3e910fa...6A566c2dC
0.00796022 ETH0.004465536
Request Investme...98595902020-04-12 20:05:051682 days ago1586721905IN
0xb3e910fa...6A566c2dC
0.01271225 ETH0.000360191.4
Request Investme...98594502020-04-12 19:34:551682 days ago1586720095IN
0xb3e910fa...6A566c2dC
0.01286133 ETH0.001286285
Execute Request ...98594182020-04-12 19:26:141682 days ago1586719574IN
0xb3e910fa...6A566c2dC
0.00588696 ETH0.000567821.1
Request Investme...98594072020-04-12 19:22:321682 days ago1586719352IN
0xb3e910fa...6A566c2dC
0.01298418 ETH0.001422995

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
114523632020-12-14 17:06:561436 days ago1607965616
0xb3e910fa...6A566c2dC
0.00089351 ETH
114523632020-12-14 17:06:561436 days ago1607965616
0xb3e910fa...6A566c2dC
0.00042166 ETH
114523632020-12-14 17:06:561436 days ago1607965616
0xb3e910fa...6A566c2dC
0.01 ETH
114372512020-12-12 9:18:581439 days ago1607764738
0xb3e910fa...6A566c2dC
0.0009614 ETH
114372512020-12-12 9:18:581439 days ago1607764738
0xb3e910fa...6A566c2dC
0.00077747 ETH
112656712020-11-16 0:27:191465 days ago1605486439
0xb3e910fa...6A566c2dC
0.00123337 ETH
112656712020-11-16 0:27:191465 days ago1605486439
0xb3e910fa...6A566c2dC
0.0050138 ETH
112656712020-11-16 0:27:191465 days ago1605486439
0xb3e910fa...6A566c2dC
0.01 ETH
112618362020-11-15 10:21:361466 days ago1605435696
0xb3e910fa...6A566c2dC
0.00082093 ETH
112618362020-11-15 10:21:361466 days ago1605435696
0xb3e910fa...6A566c2dC
0.00066387 ETH
109107262020-09-22 6:31:581520 days ago1600756318
0xb3e910fa...6A566c2dC
0.00140746 ETH
109107262020-09-22 6:31:581520 days ago1600756318
0xb3e910fa...6A566c2dC
0.00066409 ETH
109107262020-09-22 6:31:581520 days ago1600756318
0xb3e910fa...6A566c2dC
0.01 ETH
109000072020-09-20 15:18:541521 days ago1600615134
0xb3e910fa...6A566c2dC
0.00153194 ETH
109000072020-09-20 15:18:541521 days ago1600615134
0xb3e910fa...6A566c2dC
0.00123866 ETH
98825472020-04-16 8:59:441679 days ago1587027584
0xb3e910fa...6A566c2dC
0.00202119 ETH
98825472020-04-16 8:59:441679 days ago1587027584
0xb3e910fa...6A566c2dC
0.00709209 ETH
98825472020-04-16 8:59:441679 days ago1587027584
0xb3e910fa...6A566c2dC
0.01 ETH
98761232020-04-15 9:15:281680 days ago1586942128
0xb3e910fa...6A566c2dC
0.00152702 ETH
98761232020-04-15 9:15:281680 days ago1586942128
0xb3e910fa...6A566c2dC
0.00121295 ETH
98761232020-04-15 9:15:281680 days ago1586942128
0xb3e910fa...6A566c2dC
0.01273997 ETH
98694392020-04-14 8:25:391681 days ago1586852739
0xb3e910fa...6A566c2dC
0.00140642 ETH
98694392020-04-14 8:25:391681 days ago1586852739
0xb3e910fa...6A566c2dC
0.00076622 ETH
98694392020-04-14 8:25:391681 days ago1586852739
0xb3e910fa...6A566c2dC
0.01 ETH
98629042020-04-13 8:21:011682 days ago1586766061
0xb3e910fa...6A566c2dC
0.0015836 ETH
View All Internal Transactions
Loading...
Loading

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

Contract Name:
Participation

Compiler Version
v0.6.1+commit.e6f7d5a4

Optimization Enabled:
Yes with 200 runs

Other Settings:
istanbul EvmVersion, None license
File 1 of 25 : Participation.sol
pragma solidity 0.6.1;

import "../vault/Vault.sol";
import "../shares/Shares.sol";
import "../policies/PolicyManager.sol";
import "../hub/Spoke.sol";
import "../accounting/Accounting.sol";
import "../../prices/IPriceSource.sol";
import "../../factory/Factory.sol";
import "../../engine/AmguConsumer.sol";
import "../../dependencies/token/IERC20.sol";
import "../../dependencies/DSMath.sol";
import "../../dependencies/TokenUser.sol";

/// @notice Entry and exit point for investors
contract Participation is TokenUser, AmguConsumer, Spoke {
    event EnableInvestment (address[] asset);
    event DisableInvestment (address[] assets);

    event InvestmentRequest (
        address indexed requestOwner,
        address indexed investmentAsset,
        uint requestedShares,
        uint investmentAmount
    );

    event RequestExecution (
        address indexed requestOwner,
        address indexed executor,
        address indexed investmentAsset,
        uint investmentAmount,
        uint requestedShares
    );

    event CancelRequest (
        address indexed requestOwner
    );

    event Redemption (
        address indexed redeemer,
        address[] assets,
        uint[] assetQuantities,
        uint redeemedShares
    );

    struct Request {
        address investmentAsset;
        uint investmentAmount;
        uint requestedShares;
        uint timestamp;
    }

    uint constant public SHARES_DECIMALS = 18;
    uint constant public REQUEST_LIFESPAN = 1 days;

    mapping (address => Request) public requests;
    mapping (address => bool) public investAllowed;
    mapping (address => bool) public hasInvested; // for information purposes only (read)

    address[] public historicalInvestors; // for information purposes only (read)

    constructor(address _hub, address[] memory _defaultAssets, address _registry)
        public
        Spoke(_hub)
    {
        routes.registry = _registry;
        _enableInvestment(_defaultAssets);
    }

    receive() external payable {}

    function _enableInvestment(address[] memory _assets) internal {
        for (uint i = 0; i < _assets.length; i++) {
            require(
                Registry(routes.registry).assetIsRegistered(_assets[i]),
                "Asset not registered"
            );
            investAllowed[_assets[i]] = true;
        }
        emit EnableInvestment(_assets);
    }

    function enableInvestment(address[] calldata _assets) external auth {
        _enableInvestment(_assets);
    }

    function disableInvestment(address[] calldata _assets) external auth {
        for (uint i = 0; i < _assets.length; i++) {
            investAllowed[_assets[i]] = false;
        }
        emit DisableInvestment(_assets);
    }

    function hasRequest(address _who) public view returns (bool) {
        return requests[_who].timestamp > 0;
    }

    function hasExpiredRequest(address _who) public view returns (bool) {
        return block.timestamp > add(requests[_who].timestamp, REQUEST_LIFESPAN);
    }

    /// @notice Whether request is OK and invest delay is being respected
    /// @dev Request valid if price update happened since request and not expired
    /// @dev If no shares exist and not expired, request can be executed immediately
    function hasValidRequest(address _who) public view returns (bool) {
        IPriceSource priceSource = IPriceSource(priceSource());
        bool delayRespectedOrNoShares = requests[_who].timestamp < priceSource.getLastUpdate() ||
            Shares(routes.shares).totalSupply() == 0;

        return hasRequest(_who) &&
            delayRespectedOrNoShares &&
            !hasExpiredRequest(_who) &&
            requests[_who].investmentAmount > 0 &&
            requests[_who].requestedShares > 0;
    }

    function requestInvestment(
        uint requestedShares,
        uint investmentAmount,
        address investmentAsset
    )
        external
        notShutDown
        payable
        amguPayable(true)
        onlyInitialized
    {
        PolicyManager(routes.policyManager).preValidate(
            msg.sig,
            [msg.sender, address(0), address(0), investmentAsset, address(0)],
            [uint(0), uint(0), uint(0)],
            bytes32(0)
        );
        require(
            investAllowed[investmentAsset],
            "Investment not allowed in this asset"
        );
        safeTransferFrom(
            investmentAsset, msg.sender, address(this), investmentAmount
        );
        require(
            requests[msg.sender].timestamp == 0,
            "Only one request can exist at a time"
        );
        requests[msg.sender] = Request({
            investmentAsset: investmentAsset,
            investmentAmount: investmentAmount,
            requestedShares: requestedShares,
            timestamp: block.timestamp
        });
        PolicyManager(routes.policyManager).postValidate(
            msg.sig,
            [msg.sender, address(0), address(0), investmentAsset, address(0)],
            [uint(0), uint(0), uint(0)],
            bytes32(0)
        );

        emit InvestmentRequest(
            msg.sender,
            investmentAsset,
            requestedShares,
            investmentAmount
        );
    }

    function _cancelRequestFor(address requestOwner) internal {
        require(hasRequest(requestOwner), "No request to cancel");
        IPriceSource priceSource = IPriceSource(priceSource());
        Request memory request = requests[requestOwner];
        require(
            !priceSource.hasValidPrice(request.investmentAsset) ||
            hasExpiredRequest(requestOwner) ||
            hub.isShutDown(),
            "No cancellation condition was met"
        );
        IERC20 investmentAsset = IERC20(request.investmentAsset);
        uint investmentAmount = request.investmentAmount;
        delete requests[requestOwner];
        msg.sender.transfer(Registry(routes.registry).incentive());
        safeTransfer(address(investmentAsset), requestOwner, investmentAmount);

        emit CancelRequest(requestOwner);
    }

    /// @notice Can only cancel when no price, request expired or fund shut down
    /// @dev Only request owner can cancel their request
    function cancelRequest() external payable amguPayable(false) {
        _cancelRequestFor(msg.sender);
    }

    function cancelRequestFor(address requestOwner)
        external
        payable
        amguPayable(false)
    {
        _cancelRequestFor(requestOwner);
    }

    function executeRequestFor(address requestOwner)
        external
        notShutDown
        amguPayable(false)
        payable
    {
        Request memory request = requests[requestOwner];
        require(
            hasValidRequest(requestOwner),
            "No valid request for this address"
        );

        FeeManager(routes.feeManager).rewardManagementFee();

        uint totalShareCostInInvestmentAsset = Accounting(routes.accounting)
            .getShareCostInAsset(
                request.requestedShares,
                request.investmentAsset
            );

        require(
            totalShareCostInInvestmentAsset <= request.investmentAmount,
            "Invested amount too low"
        );
        // send necessary amount of investmentAsset to vault
        safeTransfer(
            request.investmentAsset,
            routes.vault,
            totalShareCostInInvestmentAsset
        );

        uint investmentAssetChange = sub(
            request.investmentAmount,
            totalShareCostInInvestmentAsset
        );

        // return investmentAsset change to request owner
        if (investmentAssetChange > 0) {
            safeTransfer(
                request.investmentAsset,
                requestOwner,
                investmentAssetChange
            );
        }

        msg.sender.transfer(Registry(routes.registry).incentive());

        Shares(routes.shares).createFor(requestOwner, request.requestedShares);
        Accounting(routes.accounting).addAssetToOwnedAssets(request.investmentAsset);

        if (!hasInvested[requestOwner]) {
            hasInvested[requestOwner] = true;
            historicalInvestors.push(requestOwner);
        }

        emit RequestExecution(
            requestOwner,
            msg.sender,
            request.investmentAsset,
            request.investmentAmount,
            request.requestedShares
        );
        delete requests[requestOwner];
    }

    function getOwedPerformanceFees(uint shareQuantity)
        public
        returns (uint remainingShareQuantity)
    {
        Shares shares = Shares(routes.shares);

        uint totalPerformanceFee = FeeManager(routes.feeManager).performanceFeeAmount();
        // The denominator is augmented because performanceFeeAmount() accounts for inflation
        // Since shares are directly transferred, we don't need to account for inflation in this case
        uint performanceFeePortion = mul(
            totalPerformanceFee,
            shareQuantity
        ) / add(shares.totalSupply(), totalPerformanceFee);
        return performanceFeePortion;
    }

    /// @dev "Happy path" (no asset throws & quantity available)
    /// @notice Redeem all shares and across all assets
    function redeem() external {
        uint ownedShares = Shares(routes.shares).balanceOf(msg.sender);
        redeemQuantity(ownedShares);
    }

    /// @notice Redeem shareQuantity across all assets
    function redeemQuantity(uint shareQuantity) public {
        address[] memory assetList;
        assetList = Accounting(routes.accounting).getOwnedAssets();
        redeemWithConstraints(shareQuantity, assetList);
    }

    // TODO: reconsider the scenario where the user has enough funds to force shutdown on a large trade (any way around this?)
    /// @dev Redeem only selected assets (used only when an asset throws)
    function redeemWithConstraints(uint shareQuantity, address[] memory requestedAssets) public {
        Shares shares = Shares(routes.shares);
        require(
            shares.balanceOf(msg.sender) >= shareQuantity &&
            shares.balanceOf(msg.sender) > 0,
            "Sender does not have enough shares to fulfill request"
        );

        uint owedPerformanceFees = 0;
        if (
            IPriceSource(priceSource()).hasValidPrices(requestedAssets) &&
            msg.sender != hub.manager()
        ) {
            FeeManager(routes.feeManager).rewardManagementFee();
            owedPerformanceFees = getOwedPerformanceFees(shareQuantity);
            shares.destroyFor(msg.sender, owedPerformanceFees);
            shares.createFor(hub.manager(), owedPerformanceFees);
        }
        uint remainingShareQuantity = sub(shareQuantity, owedPerformanceFees);

        address ofAsset;
        uint[] memory ownershipQuantities = new uint[](requestedAssets.length);
        address[] memory redeemedAssets = new address[](requestedAssets.length);
        // Check whether enough assets held by fund
        Accounting accounting = Accounting(routes.accounting);
        for (uint i = 0; i < requestedAssets.length; ++i) {
            ofAsset = requestedAssets[i];
            require(
                accounting.isInAssetList(ofAsset),
                "Requested asset not in asset list"
            );
            for (uint j = 0; j < redeemedAssets.length; j++) {
                require(
                    ofAsset != redeemedAssets[j],
                    "Asset can only be redeemed once"
                );
            }
            redeemedAssets[i] = ofAsset;
            uint quantityHeld = accounting.assetHoldings(ofAsset);
            if (quantityHeld == 0) continue;

            // participant's ownership percentage of asset holdings
            ownershipQuantities[i] = mul(quantityHeld, remainingShareQuantity) / shares.totalSupply();
        }

        shares.destroyFor(msg.sender, remainingShareQuantity);

        // Transfer owned assets
        for (uint k = 0; k < requestedAssets.length; ++k) {
            ofAsset = requestedAssets[k];
            if (ownershipQuantities[k] == 0) {
                continue;
            } else {
                Vault(routes.vault).withdraw(ofAsset, ownershipQuantities[k]);
                safeTransfer(ofAsset, msg.sender, ownershipQuantities[k]);
            }
        }
        emit Redemption(
            msg.sender,
            requestedAssets,
            ownershipQuantities,
            remainingShareQuantity
        );
    }

    function getHistoricalInvestors() external view returns (address[] memory) {
        return historicalInvestors;
    }

    function engine() public view override(AmguConsumer, Spoke) returns (address) { return Spoke.engine(); }
    function mlnToken() public view override(AmguConsumer, Spoke) returns (address) { return Spoke.mlnToken(); }
    function priceSource() public view override(AmguConsumer, Spoke) returns (address) { return Spoke.priceSource(); }
    function registry() public view override(AmguConsumer, Spoke) returns (address) { return Spoke.registry(); }
}

contract ParticipationFactory is Factory {
    event NewInstance(
        address indexed hub,
        address indexed instance,
        address[] defaultAssets,
        address registry
    );

    function createInstance(address _hub, address[] calldata _defaultAssets, address _registry)
        external
        returns (address)
    {
        address participation = address(
            new Participation(_hub, _defaultAssets, _registry)
        );
        childExists[participation] = true;
        emit NewInstance(_hub, participation, _defaultAssets, _registry);
        return participation;
    }
}

File 2 of 25 : Vault.sol
pragma solidity 0.6.1;

import "../hub/Spoke.sol";
import "../../factory/Factory.sol";
import "../../dependencies/TokenUser.sol";

/// @notice Dumb custody component
contract Vault is TokenUser, Spoke {

    constructor(address _hub) public Spoke(_hub) {}

    function withdraw(address token, uint amount) external auth {
        safeTransfer(token, msg.sender, amount);
    }
}

contract VaultFactory is Factory {
    function createInstance(address _hub) external returns (address) {
        address vault = address(new Vault(_hub));
        childExists[vault] = true;
        emit NewInstance(_hub, vault);
        return vault;
    }
}

File 3 of 25 : Shares.sol
pragma solidity 0.6.1;

import "../hub/Spoke.sol";
import "../../dependencies/token/StandardToken.sol";
import "../../factory/Factory.sol";

contract Shares is Spoke, StandardToken {
    string public symbol;
    string public name;
    uint8 public decimals;

    constructor(address _hub) public Spoke(_hub) {
        name = hub.name();
        symbol = "MLNF";
        decimals = 18;
    }

    function createFor(address who, uint amount) public auth {
        _mint(who, amount);
    }

    function destroyFor(address who, uint amount) public auth {
        _burn(who, amount);
    }

    function transfer(address to, uint amount) public override returns (bool) {
        revert("Unimplemented");
    }

    function transferFrom(
        address from,
        address to,
        uint amount
    )
        public
        override
        returns (bool)
    {
        revert("Unimplemented");
    }

    function approve(address spender, uint amount) public override returns (bool) {
        revert("Unimplemented");
    }

    function increaseApproval(
        address spender,
        uint amount
    )
        public
        override
        returns (bool)
    {
        revert("Unimplemented");
    }

    function decreaseApproval(
        address spender,
        uint amount
    )
        public
        override
        returns (bool)
    {
        revert("Unimplemented");
    }
}

contract SharesFactory is Factory {
    function createInstance(address _hub) external returns (address) {
        address shares = address(new Shares(_hub));
        childExists[shares] = true;
        emit NewInstance(_hub, shares);
        return shares;
    }
}

File 4 of 25 : PolicyManager.sol
pragma solidity 0.6.1;

import "../../factory/Factory.sol";
import "../hub/Spoke.sol";
import "./IPolicy.sol";

contract PolicyManager is Spoke {

    event Registration(
        bytes4 indexed sig,
        IPolicy.Applied position,
        address indexed policy
    );

    struct Entry {
        IPolicy[] pre;
        IPolicy[] post;
    }

    mapping(bytes4 => Entry) policies;

    constructor (address _hub) public Spoke(_hub) {}

    function register(bytes4 sig, address _policy) public auth {
        IPolicy.Applied position = IPolicy(_policy).position();
        if (position == IPolicy.Applied.pre) {
            policies[sig].pre.push(IPolicy(_policy));
        } else if (position == IPolicy.Applied.post) {
            policies[sig].post.push(IPolicy(_policy));
        } else {
            revert("Only pre and post allowed");
        }
        emit Registration(sig, position, _policy);
    }

    function batchRegister(bytes4[] memory sig, address[] memory _policies) public auth {
        require(sig.length == _policies.length, "Arrays lengths unequal");
        for (uint i = 0; i < sig.length; i++) {
            register(sig[i], _policies[i]);
        }
    }

    function PoliciesToAddresses(IPolicy[] storage _policies) internal view returns (address[] memory) {
        address[] memory res = new address[](_policies.length);
        for(uint i = 0; i < _policies.length; i++) {
            res[i] = address(_policies[i]);
        }
        return res;
    }

    function getPoliciesBySig(bytes4 sig) public view returns (address[] memory, address[] memory) {
        return (PoliciesToAddresses(policies[sig].pre), PoliciesToAddresses(policies[sig].post));
    }

    modifier isValidPolicyBySig(bytes4 sig, address[5] memory addresses, uint[3] memory values, bytes32 identifier) {
        preValidate(sig, addresses, values, identifier);
        _;
        postValidate(sig, addresses, values, identifier);
    }

    modifier isValidPolicy(address[5] memory addresses, uint[3] memory values, bytes32 identifier) {
        preValidate(msg.sig, addresses, values, identifier);
        _;
        postValidate(msg.sig, addresses, values, identifier);
    }

    function preValidate(bytes4 sig, address[5] memory addresses, uint[3] memory values, bytes32 identifier) public {
        validate(policies[sig].pre, sig, addresses, values, identifier);
    }

    function postValidate(bytes4 sig, address[5] memory addresses, uint[3] memory values, bytes32 identifier) public {
        validate(policies[sig].post, sig, addresses, values, identifier);
    }

    function validate(IPolicy[] storage aux, bytes4 sig, address[5] memory addresses, uint[3] memory values, bytes32 identifier) internal {
        for(uint i = 0; i < aux.length; i++) {
            require(
                aux[i].rule(sig, addresses, values, identifier),
                string(abi.encodePacked("Rule evaluated to false: ", aux[i].identifier()))
            );
        }
    }
}

contract PolicyManagerFactory is Factory {
    function createInstance(address _hub) external returns (address) {
        address policyManager = address(new PolicyManager(_hub));
        childExists[policyManager] = true;
        emit NewInstance(_hub, policyManager);
        return policyManager;
    }
}

File 5 of 25 : Spoke.sol
pragma solidity 0.6.1;

import "./Hub.sol";
import "../../dependencies/DSAuth.sol";

/// @notice Has one Hub
contract Spoke is DSAuth {
    Hub public hub;
    Hub.Routes public routes;
    bool public initialized;

    modifier onlyInitialized() {
        require(initialized, "Component not yet initialized");
        _;
    }

    modifier notShutDown() {
        require(!hub.isShutDown(), "Hub is shut down");
        _;
    }

    constructor(address _hub) public {
        hub = Hub(_hub);
        setAuthority(hub);
        setOwner(address(hub)); // temporary, to allow initialization
    }

    function initialize(address[11] calldata _spokes) external auth {
        require(msg.sender == address(hub));
        require(!initialized, "Already initialized");
        routes = Hub.Routes(
            _spokes[0],
            _spokes[1],
            _spokes[2],
            _spokes[3],
            _spokes[4],
            _spokes[5],
            _spokes[6],
            _spokes[7],
            _spokes[8],
            _spokes[9],
            _spokes[10]
        );
        initialized = true;
        setOwner(address(0));
    }

    function engine() public view virtual returns (address) { return routes.engine; }
    function mlnToken() public view virtual returns (address) { return routes.mlnToken; }
    function priceSource() public view virtual returns (address) { return hub.priceSource(); }
    function version() public view virtual returns (address) { return routes.version; }
    function registry() public view virtual returns (address) { return routes.registry; }
}

File 6 of 25 : Accounting.sol
pragma solidity 0.6.1;

import "../../dependencies/token/StandardToken.sol";
import "../../factory/Factory.sol";
import "../../prices/IPriceSource.sol";
import "../fees/FeeManager.sol";
import "../hub/Spoke.sol";
import "../shares/Shares.sol";
import "../trading/ITrading.sol";
import "../vault/Vault.sol";
import "../../engine/AmguConsumer.sol";

contract Accounting is AmguConsumer, Spoke {

    event AssetAddition(address indexed asset);
    event AssetRemoval(address indexed asset);

    struct Calculations {
        uint gav;
        uint nav;
        uint allocatedFees;
        uint totalSupply;
        uint timestamp;
    }

    uint constant public MAX_OWNED_ASSETS = 20;
    address[] public ownedAssets;
    mapping (address => bool) public isInAssetList;
    uint public constant SHARES_DECIMALS = 18;
    address public NATIVE_ASSET;
    address public DENOMINATION_ASSET;
    uint public DENOMINATION_ASSET_DECIMALS;
    uint public DEFAULT_SHARE_PRICE;
    Calculations public atLastAllocation;

    constructor(address _hub, address _denominationAsset, address _nativeAsset)
        public
        Spoke(_hub)
    {
        DENOMINATION_ASSET = _denominationAsset;
        NATIVE_ASSET = _nativeAsset;
        DENOMINATION_ASSET_DECIMALS = ERC20WithFields(DENOMINATION_ASSET).decimals();
        DEFAULT_SHARE_PRICE = 10 ** uint(DENOMINATION_ASSET_DECIMALS);
    }

    function getOwnedAssetsLength() external view returns (uint256) {
        return ownedAssets.length;
    }

    function getOwnedAssets() external view returns (address[] memory) {
        return ownedAssets;
    }

    function assetHoldings(address _asset) public returns (uint256) {
        return add(
            uint256(ERC20WithFields(_asset).balanceOf(routes.vault)),
            ITrading(routes.trading).updateAndGetQuantityBeingTraded(_asset)
        );
    }

    /// @dev Returns sparse array
    function getFundHoldings() external returns (uint[] memory, address[] memory) {
        uint[] memory _quantities = new uint[](ownedAssets.length);
        address[] memory _assets = new address[](ownedAssets.length);
        for (uint i = 0; i < ownedAssets.length; i++) {
            address ofAsset = ownedAssets[i];
            // assetHoldings formatting: mul(exchangeHoldings, 10 ** assetDecimal)
            uint quantityHeld = assetHoldings(ofAsset);
            _assets[i] = ofAsset;
            _quantities[i] = quantityHeld;
        }
        return (_quantities, _assets);
    }

    function calcAssetGAV(address _queryAsset) external returns (uint) {
        uint queryAssetQuantityHeld = assetHoldings(_queryAsset);
        return IPriceSource(priceSource()).convertQuantity(
            queryAssetQuantityHeld, _queryAsset, DENOMINATION_ASSET
        );
    }

    // prices are quoted in DENOMINATION_ASSET so they use denominationDecimals
    function calcGav() public returns (uint gav) {
        for (uint i = 0; i < ownedAssets.length; ++i) {
            address asset = ownedAssets[i];
            // assetHoldings formatting: mul(exchangeHoldings, 10 ** assetDecimals)
            uint quantityHeld = assetHoldings(asset);
            // Dont bother with the calculations if the balance of the asset is 0
            if (quantityHeld == 0) {
                continue;
            }
            // gav as sum of mul(assetHoldings, assetPrice) with formatting: mul(mul(exchangeHoldings, exchangePrice), 10 ** shareDecimals)
            gav = add(
                gav,
                IPriceSource(priceSource()).convertQuantity(
                    quantityHeld, asset, DENOMINATION_ASSET
                )
            );
        }
        return gav;
    }

    function calcNav(uint gav, uint unclaimedFeesInDenominationAsset) public pure returns (uint) {
        return sub(gav, unclaimedFeesInDenominationAsset);
    }

    function valuePerShare(uint totalValue, uint numShares) public pure returns (uint) {
        require(numShares > 0, "No shares to calculate value for");
        return (totalValue * 10 ** uint(SHARES_DECIMALS)) / numShares;
    }

    function performCalculations()
        public
        returns (
            uint gav,
            uint feesInDenominationAsset,  // unclaimed amount
            uint feesInShares,             // unclaimed amount
            uint nav,
            uint sharePrice,
            uint gavPerShareNetManagementFee
        )
    {
        gav = calcGav();
        uint totalSupply = Shares(routes.shares).totalSupply();
        feesInShares = FeeManager(routes.feeManager).totalFeeAmount();
        feesInDenominationAsset = (totalSupply == 0) ?
            0 :
            mul(feesInShares, gav) / add(totalSupply, feesInShares);
        nav = calcNav(gav, feesInDenominationAsset);

        // The total share supply including the value of feesInDenominationAsset, measured in shares of this fund
        uint totalSupplyAccountingForFees = add(totalSupply, feesInShares);
        sharePrice = (totalSupply > 0) ?
            valuePerShare(gav, totalSupplyAccountingForFees) :
            DEFAULT_SHARE_PRICE;
        gavPerShareNetManagementFee = (totalSupply > 0) ?
            valuePerShare(gav, add(totalSupply, FeeManager(routes.feeManager).managementFeeAmount())) :
            DEFAULT_SHARE_PRICE;
        return (gav, feesInDenominationAsset, feesInShares, nav, sharePrice, gavPerShareNetManagementFee);
    }

    function calcGavPerShareNetManagementFee()
        public
        returns (uint gavPerShareNetManagementFee)
    {
        (,,,,,gavPerShareNetManagementFee) = performCalculations();
        return gavPerShareNetManagementFee;
    }

    function getShareCostInAsset(uint _numShares, address _altAsset)
        external
        returns (uint)
    {
        uint denominationAssetQuantity = mul(
            _numShares,
            calcGavPerShareNetManagementFee()
        ) / 10 ** uint(SHARES_DECIMALS);
        return IPriceSource(priceSource()).convertQuantity(
            denominationAssetQuantity, DENOMINATION_ASSET, _altAsset
        );
    }

    /// @notice Reward all fees and perform some updates
    /// @dev Anyone can call this
    function triggerRewardAllFees()
        external
        amguPayable(false)
        payable
    {
        updateOwnedAssets();
        uint256 gav;
        uint256 feesInDenomination;
        uint256 feesInShares;
        uint256 nav;
        (gav, feesInDenomination, feesInShares, nav,,) = performCalculations();
        uint256 totalSupply = Shares(routes.shares).totalSupply();
        FeeManager(routes.feeManager).rewardAllFees();
        atLastAllocation = Calculations({
            gav: gav,
            nav: nav,
            allocatedFees: feesInDenomination,
            totalSupply: totalSupply,
            timestamp: block.timestamp
        });
    }

    /// @dev Check holdings for all assets, and adjust list
    function updateOwnedAssets() public {
        for (uint i = 0; i < ownedAssets.length; i++) {
            address asset = ownedAssets[i];
            if (
                assetHoldings(asset) == 0 &&
                !(asset == address(DENOMINATION_ASSET)) &&
                ITrading(routes.trading).getOpenMakeOrdersAgainstAsset(asset) == 0
            ) {
                _removeFromOwnedAssets(asset);
            }
        }
    }

    function addAssetToOwnedAssets(address _asset) external auth {
        _addAssetToOwnedAssets(_asset);
    }

    function removeFromOwnedAssets(address _asset) external auth {
        _removeFromOwnedAssets(_asset);
    }

    /// @dev Just pass if asset already in list
    function _addAssetToOwnedAssets(address _asset) internal {
        if (isInAssetList[_asset]) { return; }

        require(
            ownedAssets.length < MAX_OWNED_ASSETS,
            "Max owned asset limit reached"
        );
        isInAssetList[_asset] = true;
        ownedAssets.push(_asset);
        emit AssetAddition(_asset);
    }

    /// @dev Just pass if asset not in list
    function _removeFromOwnedAssets(address _asset) internal {
        if (!isInAssetList[_asset]) { return; }

        isInAssetList[_asset] = false;
        for (uint i; i < ownedAssets.length; i++) {
            if (ownedAssets[i] == _asset) {
                ownedAssets[i] = ownedAssets[ownedAssets.length - 1];
                ownedAssets.pop();
                break;
            }
        }
        emit AssetRemoval(_asset);
    }

    function engine() public view override(AmguConsumer, Spoke) returns (address) { return Spoke.engine(); }
    function mlnToken() public view override(AmguConsumer, Spoke) returns (address) { return Spoke.mlnToken(); }
    function priceSource() public view override(AmguConsumer, Spoke) returns (address) { return Spoke.priceSource(); }
    function registry() public view override(AmguConsumer, Spoke) returns (address) { return Spoke.registry(); }
}

contract AccountingFactory is Factory {
    event NewInstance(
        address indexed hub,
        address indexed instance,
        address denominationAsset,
        address nativeAsset
    );

    function createInstance(address _hub, address _denominationAsset, address _nativeAsset) external returns (address) {
        address accounting = address(new Accounting(_hub, _denominationAsset, _nativeAsset));
        childExists[accounting] = true;
        emit NewInstance(_hub, accounting, _denominationAsset, _nativeAsset);
        return accounting;
    }
}

File 7 of 25 : IPriceSource.sol
pragma solidity 0.6.1;

/// @notice Must return a value for an asset
interface IPriceSource {
    function getQuoteAsset() external view returns (address);
    function getLastUpdate() external view returns (uint);

    /// @notice Returns false if asset not applicable, or price not recent
    function hasValidPrice(address) external view returns (bool);
    function hasValidPrices(address[] calldata) external view returns (bool);

    /// @notice Return the last known price, and when it was issued
    function getPrice(address _asset) external view returns (uint price, uint timestamp);
    function getPrices(address[] calldata _assets) external view returns (uint[] memory prices, uint[] memory timestamps);

    /// @notice Get price info, and revert if not valid
    function getPriceInfo(address _asset) external view returns (uint price, uint decimals);
    function getInvertedPriceInfo(address ofAsset) external view returns (uint price, uint decimals);

    function getReferencePriceInfo(address _base, address _quote) external view returns (uint referencePrice, uint decimal);
    function getOrderPriceInfo(address sellAsset, uint sellQuantity, uint buyQuantity) external view returns (uint orderPrice);
    function existsPriceOnAssetPair(address sellAsset, address buyAsset) external view returns (bool isExistent);
    function convertQuantity(
        uint fromAssetQuantity,
        address fromAsset,
        address toAsset
    ) external view returns (uint);
}

File 8 of 25 : Factory.sol
pragma solidity 0.6.1;


contract Factory {
    mapping (address => bool) public childExists;

    event NewInstance(
        address indexed hub,
        address indexed instance
    );

    function isInstance(address _child) public view returns (bool) {
        return childExists[_child];
    }
}

File 9 of 25 : AmguConsumer.sol
pragma solidity 0.6.1;

import "../dependencies/DSMath.sol";
import "../dependencies/token/IERC20.sol";
import "../prices/IPriceSource.sol";
import "../version/IVersion.sol";
import "./IEngine.sol";
import "../version/Registry.sol";

/// @notice Abstract contracts
/// @notice inherit this to pay AMGU on a function call
abstract contract AmguConsumer is DSMath {

    /// @dev each of these must be implemented by the inheriting contract
    function engine() public view virtual returns (address);
    function mlnToken() public view virtual returns (address);
    function priceSource() public view virtual returns (address);
    function registry() public view virtual returns (address);
    event AmguPaid(address indexed payer, uint256 totalAmguPaidInEth, uint256 amguChargableGas, uint256 incentivePaid);

    /// bool deductIncentive is used when sending extra eth beyond amgu
    modifier amguPayable(bool deductIncentive) {
        uint preGas = gasleft();
        _;
        uint postGas = gasleft();

        uint mlnPerAmgu = IEngine(engine()).getAmguPrice();
        uint mlnQuantity = mul(
            mlnPerAmgu,
            sub(preGas, postGas)
        );
        address nativeAsset = Registry(registry()).nativeAsset();
        uint ethToPay = IPriceSource(priceSource()).convertQuantity(
            mlnQuantity,
            mlnToken(),
            nativeAsset
        );
        uint incentiveAmount;
        if (deductIncentive) {
            incentiveAmount = Registry(registry()).incentive();
        } else {
            incentiveAmount = 0;
        }
        require(
            msg.value >= add(ethToPay, incentiveAmount),
            "Insufficent AMGU and/or incentive"
        );
        IEngine(engine()).payAmguInEther.value(ethToPay)();

        require(
            msg.sender.send(
                sub(
                    sub(msg.value, ethToPay),
                    incentiveAmount
                )
            ),
            "Refund failed"
        );
        emit AmguPaid(msg.sender, ethToPay, sub(preGas, postGas), incentiveAmount);
    }
}

File 10 of 25 : IERC20.sol
pragma solidity 0.6.1;

/**
 * @title ERC20 interface
 * @dev see https://github.com/ethereum/EIPs/issues/20
 * Altered from https://github.com/OpenZeppelin/openzeppelin-solidity/blob/a466e76d26c394b1faa6e2797aefe34668566392/contracts/token/ERC20/ERC20.sol
 */
interface IERC20 {
  function totalSupply() external view returns (uint256);

  function balanceOf(address _who) external view returns (uint256);

  function allowance(address _owner, address _spender)
    external view returns (uint256);

  function transfer(address _to, uint256 _value) external returns (bool);

  function approve(address _spender, uint256 _value) external returns (bool);

  function transferFrom(address _from, address _to, uint256 _value) external returns (bool);

  event Transfer(
    address indexed from,
    address indexed to,
    uint256 value
  );

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

/// @dev Just adds extra functions that we use elsewhere
abstract contract ERC20WithFields is IERC20 {
    string public symbol;
    string public name;
    uint8 public decimals;
}

File 11 of 25 : DSMath.sol
/// DSMath.sol -- mixin for inline numerical wizardry

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

pragma solidity >0.4.13;

contract DSMath {
    function add(uint x, uint y) internal pure returns (uint z) {
        require((z = x + y) >= x, "ds-math-add-overflow");
    }
    function sub(uint x, uint y) internal pure returns (uint z) {
        require((z = x - y) <= x, "ds-math-sub-underflow");
    }
    function mul(uint x, uint y) internal pure returns (uint z) {
        require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow");
    }

    function min(uint x, uint y) internal pure returns (uint z) {
        return x <= y ? x : y;
    }
    function max(uint x, uint y) internal pure returns (uint z) {
        return x >= y ? x : y;
    }
    function imin(int x, int y) internal pure returns (int z) {
        return x <= y ? x : y;
    }
    function imax(int x, int y) internal pure returns (int z) {
        return x >= y ? x : y;
    }

    uint constant WAD = 10 ** 18;
    uint constant RAY = 10 ** 27;

    function wmul(uint x, uint y) internal pure returns (uint z) {
        z = add(mul(x, y), WAD / 2) / WAD;
    }
    function rmul(uint x, uint y) internal pure returns (uint z) {
        z = add(mul(x, y), RAY / 2) / RAY;
    }
    function wdiv(uint x, uint y) internal pure returns (uint z) {
        z = add(mul(x, WAD), y / 2) / y;
    }
    function rdiv(uint x, uint y) internal pure returns (uint z) {
        z = add(mul(x, RAY), y / 2) / y;
    }

    // This famous algorithm is called "exponentiation by squaring"
    // and calculates x^n with x as fixed-point and n as regular unsigned.
    //
    // It's O(log n), instead of O(n) for naive repeated multiplication.
    //
    // These facts are why it works:
    //
    //  If n is even, then x^n = (x^2)^(n/2).
    //  If n is odd,  then x^n = x * x^(n-1),
    //   and applying the equation for even x gives
    //    x^n = x * (x^2)^((n-1) / 2).
    //
    //  Also, EVM division is flooring and
    //    floor[(n-1) / 2] = floor[n / 2].
    //
    function rpow(uint x, uint n) internal pure returns (uint z) {
        z = n % 2 != 0 ? x : RAY;

        for (n /= 2; n != 0; n /= 2) {
            x = rmul(x, x);

            if (n % 2 != 0) {
                z = rmul(z, x);
            }
        }
    }
}

File 12 of 25 : TokenUser.sol
pragma solidity 0.6.1;

import "./token/IERC20.sol";
import "./DSMath.sol";

/// @notice Wrapper to ensure tokens are received
contract TokenUser is DSMath {
    function safeTransfer(
        address _token,
        address _to,
        uint _value
    ) internal {
        uint receiverPreBalance = IERC20(_token).balanceOf(_to);
        IERC20(_token).transfer(_to, _value);
        uint receiverPostBalance = IERC20(_token).balanceOf(_to);
        require(
            add(receiverPreBalance, _value) == receiverPostBalance,
            "Receiver did not receive tokens in transfer"
        );
    }

    function safeTransferFrom(
        address _token,
        address _from,
        address _to,
        uint _value
    ) internal {
        uint receiverPreBalance = IERC20(_token).balanceOf(_to);
        IERC20(_token).transferFrom(_from, _to, _value);
        uint receiverPostBalance = IERC20(_token).balanceOf(_to);
        require(
            add(receiverPreBalance, _value) == receiverPostBalance,
            "Receiver did not receive tokens in transferFrom"
        );
    }
}

File 13 of 25 : StandardToken.sol
pragma solidity 0.6.1;

import "./IERC20.sol";
import "../SafeMath.sol";

/**
 * @title Standard ERC20 token
 *
 * @dev Implementation of the basic standard token.
 * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
 * Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
 * Modified from https://github.com/OpenZeppelin/openzeppelin-solidity/blob/a466e76d26c394b1faa6e2797aefe34668566392/contracts/token/ERC20/StandardToken.sol
 */
contract StandardToken is IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) balances;

    mapping (address => mapping (address => uint256)) allowed;

    uint256 totalSupply_;

    /**
     * @dev Total number of tokens in existence
     */
    function totalSupply() public view override returns (uint256) {
        return totalSupply_;
    }

    /**
     * @dev Gets the balance of the specified address.
     * @param _owner The address to query the the balance of.
     * @return An uint256 representing the amount owned by the passed address.
     */
    function balanceOf(address _owner) public view override returns (uint256) {
        return balances[_owner];
    }

    /**
     * @dev Function to check the amount of tokens that an owner allowed to a spender.
     * @param _owner address The address which owns the funds.
     * @param _spender address The address which will spend the funds.
     * @return A uint256 specifying the amount of tokens still available for the spender.
     */
    function allowance(
        address _owner,
        address _spender
    )
        public
        view
        override
        returns (uint256)
    {
        return allowed[_owner][_spender];
    }

    /**
    * @dev Transfer token for a specified address
    * @param _to The address to transfer to.
    * @param _value The amount to be transferred.
    */
    function transfer(address _to, uint256 _value) public virtual override returns (bool) {
        require(_value <= balances[msg.sender]);
        require(_to != address(0));

        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);
        emit Transfer(msg.sender, _to, _value);
        return true;
    }

    /**
    * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
    * Beware that changing an allowance with this method brings the risk that someone may use both the old
    * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
    * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
    * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
    * @param _spender The address which will spend the funds.
        * @param _value The amount of tokens to be spent.
        */
    function approve(address _spender, uint256 _value) public virtual override returns (bool) {
        allowed[msg.sender][_spender] = _value;
        emit Approval(msg.sender, _spender, _value);
        return true;
    }

    /**
    * @dev Transfer tokens from one address to another
    * @param _from address The address which you want to send tokens from
    * @param _to address The address which you want to transfer to
    * @param _value uint256 the amount of tokens to be transferred
    */
    function transferFrom(
        address _from,
        address _to,
        uint256 _value
    )
        public
        virtual
        override
        returns (bool)
    {
        require(_value <= balances[_from]);
        require(_value <= allowed[_from][msg.sender]);
        require(_to != address(0));

        balances[_from] = balances[_from].sub(_value);
        balances[_to] = balances[_to].add(_value);
        allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
        emit Approval(_from, msg.sender, allowed[_from][msg.sender]);
        emit Transfer(_from, _to, _value);
        return true;
    }

    /**
    * @dev Increase the amount of tokens that an owner allowed to a spender.
    * approve should be called when allowed[_spender] == 0. To increment
    * allowed value is better to use this function to avoid 2 calls (and wait until
    * the first transaction is mined)
    * From MonolithDAO Token.sol
    * @param _spender The address which will spend the funds.
    * @param _addedValue The amount of tokens to increase the allowance by.
    */
    function increaseApproval(
        address _spender,
        uint256 _addedValue
    )
        public
        virtual
        returns (bool)
    {
        allowed[msg.sender][_spender] = (allowed[msg.sender][_spender].add(_addedValue));
        emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
    }

    /**
     * @dev Decrease the amount of tokens that an owner allowed to a spender.
     * approve should be called when allowed[_spender] == 0. To decrement
     * allowed value is better to use this function to avoid 2 calls (and wait until
     * the first transaction is mined)
     * From MonolithDAO Token.sol
     * @param _spender The address which will spend the funds.
     * @param _subtractedValue The amount of tokens to decrease the allowance by.
     */
    function decreaseApproval(
        address _spender,
        uint256 _subtractedValue
    )
        public
        virtual
        returns (bool)
    {
        uint256 oldValue = allowed[msg.sender][_spender];
        if (_subtractedValue >= oldValue) {
            allowed[msg.sender][_spender] = 0;
        } else {
            allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
        }
        emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
        return true;
    }

    /**
    * @dev Internal function that mints an amount of the token and assigns it to
    * an account. This encapsulates the modification of balances such that the
    * proper events are emitted.
    * @param _account The account that will receive the created tokens.
    * @param _amount The amount that will be created.
     */
    function _mint(address _account, uint256 _amount) internal {
        require(_account != address(0));
        totalSupply_ = totalSupply_.add(_amount);
        balances[_account] = balances[_account].add(_amount);
        emit Transfer(address(0), _account, _amount);
    }

    /**
     * @dev Internal function that burns an amount of the token of a given
     * account.
     * @param _account The account whose tokens will be burnt.
     * @param _amount The amount that will be burnt.
     */
    function _burn(address _account, uint256 _amount) internal {
        require(_account != address(0));
        require(_amount <= balances[_account]);

        totalSupply_ = totalSupply_.sub(_amount);
        balances[_account] = balances[_account].sub(_amount);
        emit Transfer(_account, address(0), _amount);
    }

    /**
     * @dev Internal function that burns an amount of the token of a given
     * account, deducting from the sender's allowance for said account. Uses the
     * internal _burn function.
     * @param _account The account whose tokens will be burnt.
     * @param _amount The amount that will be burnt.
     */
    function _burnFrom(address _account, uint256 _amount) internal {
        require(_amount <= allowed[_account][msg.sender]);
        allowed[_account][msg.sender] = allowed[_account][msg.sender].sub(_amount);
        emit Approval(_account, msg.sender, allowed[_account][msg.sender]);
        _burn(_account, _amount);
    }
}

File 14 of 25 : IPolicy.sol
pragma solidity 0.6.1;

interface IPolicy {
    enum Applied { pre, post }

    // In Trading context:
    // addresses: Order maker, Order taker, Order maker asset, Order taker asset, Exchange address
    // values: Maker token quantity, Taker token quantity, Fill Taker Quantity

    // In Participation context:
    // address[0]: Investor address, address[3]: Investment asset
    function rule(bytes4 sig, address[5] calldata addresses, uint[3] calldata values, bytes32 identifier) external returns (bool);

    function position() external view returns (Applied);
    function identifier() external view returns (string memory);
}

File 15 of 25 : Hub.sol
pragma solidity 0.6.1;

import "../../dependencies/DSGuard.sol";
import "./Spoke.sol";
import "../../version/Registry.sol";

/// @notice Router for communication between components
/// @notice Has one or more Spokes
contract Hub is DSGuard {

    event FundShutDown();

    struct Routes {
        address accounting;
        address feeManager;
        address participation;
        address policyManager;
        address shares;
        address trading;
        address vault;
        address registry;
        address version;
        address engine;
        address mlnToken;
    }

    Routes public routes;
    address public manager;
    address public creator;
    string public name;
    bool public isShutDown;
    bool public fundInitialized;
    uint public creationTime;
    mapping (address => bool) public isSpoke;

    constructor(address _manager, string memory _name) public {
        creator = msg.sender;
        manager = _manager;
        name = _name;
        creationTime = block.timestamp;
    }

    modifier onlyCreator() {
        require(msg.sender == creator, "Only creator can do this");
        _;
    }

    function shutDownFund() external {
        require(msg.sender == routes.version);
        isShutDown = true;
        emit FundShutDown();
    }

    function initializeAndSetPermissions(address[11] calldata _spokes) external onlyCreator {
        require(!fundInitialized, "Fund is already initialized");
        for (uint i = 0; i < _spokes.length; i++) {
            isSpoke[_spokes[i]] = true;
        }
        routes.accounting = _spokes[0];
        routes.feeManager = _spokes[1];
        routes.participation = _spokes[2];
        routes.policyManager = _spokes[3];
        routes.shares = _spokes[4];
        routes.trading = _spokes[5];
        routes.vault = _spokes[6];
        routes.registry = _spokes[7];
        routes.version = _spokes[8];
        routes.engine = _spokes[9];
        routes.mlnToken = _spokes[10];

        Spoke(routes.accounting).initialize(_spokes);
        Spoke(routes.feeManager).initialize(_spokes);
        Spoke(routes.participation).initialize(_spokes);
        Spoke(routes.policyManager).initialize(_spokes);
        Spoke(routes.shares).initialize(_spokes);
        Spoke(routes.trading).initialize(_spokes);
        Spoke(routes.vault).initialize(_spokes);

        permit(routes.participation, routes.vault, bytes4(keccak256('withdraw(address,uint256)')));
        permit(routes.trading, routes.vault, bytes4(keccak256('withdraw(address,uint256)')));
        permit(routes.participation, routes.shares, bytes4(keccak256('createFor(address,uint256)')));
        permit(routes.participation, routes.shares, bytes4(keccak256('destroyFor(address,uint256)')));
        permit(routes.feeManager, routes.shares, bytes4(keccak256('createFor(address,uint256)')));
        permit(routes.participation, routes.accounting, bytes4(keccak256('addAssetToOwnedAssets(address)')));
        permit(routes.trading, routes.accounting, bytes4(keccak256('addAssetToOwnedAssets(address)')));
        permit(routes.trading, routes.accounting, bytes4(keccak256('removeFromOwnedAssets(address)')));
        permit(routes.accounting, routes.feeManager, bytes4(keccak256('rewardAllFees()')));
        permit(manager, routes.policyManager, bytes4(keccak256('register(bytes4,address)')));
        permit(manager, routes.policyManager, bytes4(keccak256('batchRegister(bytes4[],address[])')));
        permit(manager, routes.participation, bytes4(keccak256('enableInvestment(address[])')));
        permit(manager, routes.participation, bytes4(keccak256('disableInvestment(address[])')));
        permit(manager, routes.trading, bytes4(keccak256('addExchange(address,address)')));
        fundInitialized = true;
    }

    function vault() external view returns (address) { return routes.vault; }
    function accounting() external view returns (address) { return routes.accounting; }
    function priceSource() external view returns (address) { return Registry(routes.registry).priceSource(); }
    function participation() external view returns (address) { return routes.participation; }
    function trading() external view returns (address) { return routes.trading; }
    function shares() external view returns (address) { return routes.shares; }
    function registry() external view returns (address) { return routes.registry; }
    function version() external view returns (address) { return routes.version; }
    function policyManager() external view returns (address) { return routes.policyManager; }
}

File 16 of 25 : DSAuth.sol
/// @notice Modified from DappHub (https://git.io/fpwrq)

pragma solidity 0.6.1;

abstract contract DSAuthority {
    function canCall(
        address src, address dst, bytes4 sig
    ) public view virtual returns (bool);
}

contract DSAuthEvents {
    event LogSetAuthority (address indexed authority);
    event LogSetOwner     (address indexed owner);
}

contract DSAuth is DSAuthEvents {
    DSAuthority  public  authority;
    address      public  owner;

    constructor() public {
        owner = msg.sender;
        emit LogSetOwner(msg.sender);
    }

    function setOwner(address owner_)
        public
        auth
    {
        owner = owner_;
        emit LogSetOwner(owner);
    }

    function setAuthority(DSAuthority authority_)
        public
        auth
    {
        authority = authority_;
        emit LogSetAuthority(address(authority));
    }

    modifier auth {
        require(isAuthorized(msg.sender, msg.sig), "ds-auth-unauthorized");
        _;
    }

    function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
        if (src == address(this)) {
            return true;
        } else if (src == owner) {
            return true;
        } else if (authority == DSAuthority(0)) {
            return false;
        } else {
            return authority.canCall(src, address(this), sig);
        }
    }
}

File 17 of 25 : FeeManager.sol
pragma solidity 0.6.1;
pragma experimental ABIEncoderV2;

import "./IFee.sol";
import "../hub/Spoke.sol";
import "../shares/Shares.sol";
import "../../factory/Factory.sol";
import "../../version/Registry.sol";
import "../../dependencies/DSMath.sol";
import "./IFeeManager.sol";

/// @notice Manages and allocates fees for a particular fund
contract FeeManager is DSMath, Spoke {

    event FeeReward(uint shareQuantity);
    event FeeRegistration(address fee);

    struct FeeInfo {
        address feeAddress;
        uint feeRate;
        uint feePeriod;
    }

    IFee[] public fees;
    mapping (address => bool) public feeIsRegistered;

    constructor(address _hub, address _denominationAsset, address[] memory _fees, uint[] memory _rates, uint[] memory _periods, address _registry) Spoke(_hub) public {
        for (uint i = 0; i < _fees.length; i++) {
            require(
                Registry(_registry).isFeeRegistered(_fees[i]),
                "Fee must be known to Registry"
            );
            register(_fees[i], _rates[i], _periods[i], _denominationAsset);
        }
        if (fees.length > 0) {
            require(
                fees[0].identifier() == 0,
                "Management fee must be at 0 index"
            );
        }
        if (fees.length > 1) {
            require(
                fees[1].identifier() == 1,
                "Performance fee must be at 1 index"
            );
        }
    }

    function register(address feeAddress, uint feeRate, uint feePeriod, address denominationAsset) internal {
        require(!feeIsRegistered[feeAddress], "Fee already registered");
        feeIsRegistered[feeAddress] = true;
        fees.push(IFee(feeAddress));
        IFee(feeAddress).initializeForUser(feeRate, feePeriod, denominationAsset);  // initialize state
        emit FeeRegistration(feeAddress);
    }

    function totalFeeAmount() external returns (uint total) {
        for (uint i = 0; i < fees.length; i++) {
            total = add(total, fees[i].feeAmount());
        }
        return total;
    }

    /// @dev Shares to be inflated after update state
    function _rewardFee(IFee fee) internal {
        require(feeIsRegistered[address(fee)], "Fee is not registered");
        uint rewardShares = fee.feeAmount();
        fee.updateState();
        Shares(routes.shares).createFor(hub.manager(), rewardShares);
        emit FeeReward(rewardShares);
    }

    function _rewardAllFees() internal {
        for (uint i = 0; i < fees.length; i++) {
            _rewardFee(fees[i]);
        }
    }

    /// @dev Used when calling from other components
    function rewardAllFees() public auth { _rewardAllFees(); }

    /// @dev Convenience function; anyone can reward management fee any time
    /// @dev Convention that management fee is 0
    function rewardManagementFee() public {
        if (fees.length >= 1) _rewardFee(fees[0]);
    }

    /// @dev Convenience function
    /// @dev Convention that management fee is 0
    function managementFeeAmount() external returns (uint) {
        if (fees.length < 1) return 0;
        return fees[0].feeAmount();
    }

    /// @dev Convenience function
    /// @dev Convention that performace fee is 1
    function performanceFeeAmount() external returns (uint) {
        if (fees.length < 2) return 0;
        return fees[1].feeAmount();
    }
}

contract FeeManagerFactory is Factory {
    function createInstance(
        address _hub,
        address _denominationAsset,
        address[] memory _fees,
        uint[] memory _feeRates,
        uint[] memory _feePeriods,
        address _registry
    ) public returns (address) {
        address feeManager = address(
            new FeeManager(_hub, _denominationAsset, _fees, _feeRates, _feePeriods, _registry)
        );
        childExists[feeManager] = true;
        emit NewInstance(_hub, feeManager);
        return feeManager;
    }
}

File 18 of 25 : ITrading.sol
pragma solidity 0.6.1;

pragma experimental ABIEncoderV2;

// TODO: Restore indexed params

/// @notice Mediation between a Fund and exchanges
interface ITrading {
    function callOnExchange(
        uint exchangeIndex,
        string calldata methodSignature,
        address[8] calldata orderAddresses,
        uint[8] calldata orderValues,
        bytes[4] calldata orderData,
        bytes32 identifier,
        bytes calldata signature
    ) external;

    function addOpenMakeOrder(
        address ofExchange,
        address ofSellAsset,
        address ofBuyAsset,
        address ofFeeAsset,
        uint orderId,
        uint expiryTime
    ) external;

    function removeOpenMakeOrder(
        address ofExchange,
        address ofSellAsset
    ) external;

    function updateAndGetQuantityBeingTraded(address _asset) external returns (uint256);
    function getOpenMakeOrdersAgainstAsset(address _asset) external view returns (uint256);
}

interface ITradingFactory {
     function createInstance(
        address _hub,
        address[] calldata _exchanges,
        address[] calldata _adapters,
        address _registry
    ) external returns (address);
}

File 19 of 25 : IVersion.sol
pragma solidity 0.6.1;

interface IVersion {
    function shutDownFund(address) external;
}

File 20 of 25 : IEngine.sol
pragma solidity 0.6.1;


interface IEngine {
    function payAmguInEther() external payable;
    function getAmguPrice() external view returns (uint256);
}

File 21 of 25 : Registry.sol
pragma solidity 0.6.1;

import "../dependencies/DSAuth.sol";
import "../fund/hub/Hub.sol";
import "../dependencies/token/IERC20.sol";

contract Registry is DSAuth {

    // EVENTS
    event AssetUpsert (
        address indexed asset,
        string name,
        string symbol,
        uint decimals,
        string url,
        uint reserveMin,
        uint[] standards,
        bytes4[] sigs
    );

    event ExchangeAdapterUpsert (
        address indexed exchange,
        address indexed adapter,
        bool takesCustody,
        bytes4[] sigs
    );

    event AssetRemoval (address indexed asset);
    event EfxWrapperRegistryChange(address indexed registry);
    event EngineChange(address indexed engine);
    event ExchangeAdapterRemoval (address indexed exchange);
    event IncentiveChange(uint incentiveAmount);
    event MGMChange(address indexed MGM);
    event MlnTokenChange(address indexed mlnToken);
    event NativeAssetChange(address indexed nativeAsset);
    event PriceSourceChange(address indexed priceSource);
    event VersionRegistration(address indexed version);

    // TYPES
    struct Asset {
        bool exists;
        string name;
        string symbol;
        uint decimals;
        string url;
        uint reserveMin;
        uint[] standards;
        bytes4[] sigs;
    }

    struct Exchange {
        bool exists;
        address exchangeAddress;
        bool takesCustody;
        bytes4[] sigs;
    }

    struct Version {
        bool exists;
        bytes32 name;
    }

    // CONSTANTS
    uint public constant MAX_REGISTERED_ENTITIES = 20;
    uint public constant MAX_FUND_NAME_BYTES = 66;

    // FIELDS
    mapping (address => Asset) public assetInformation;
    address[] public registeredAssets;

    // Mapping from adapter address to exchange Information (Adapters are unique)
    mapping (address => Exchange) public exchangeInformation;
    address[] public registeredExchangeAdapters;

    mapping (address => Version) public versionInformation;
    address[] public registeredVersions;

    mapping (address => bool) public isFeeRegistered;

    mapping (address => address) public fundsToVersions;
    mapping (bytes32 => bool) public versionNameExists;
    mapping (bytes32 => address) public fundNameHashToOwner;


    uint public incentive = 10 finney;
    address public priceSource;
    address public mlnToken;
    address public nativeAsset;
    address public engine;
    address public ethfinexWrapperRegistry;
    address public MGM;

    modifier onlyVersion() {
        require(
            versionInformation[msg.sender].exists,
            "Only a Version can do this"
        );
        _;
    }

    // METHODS

    constructor(address _postDeployOwner) public {
        setOwner(_postDeployOwner);
    }

    // PUBLIC METHODS

    /// @notice Whether _name has only valid characters
    function isValidFundName(string memory _name) public pure returns (bool) {
        bytes memory b = bytes(_name);
        if (b.length > MAX_FUND_NAME_BYTES) return false;
        for (uint i; i < b.length; i++){
            bytes1 char = b[i];
            if(
                !(char >= 0x30 && char <= 0x39) && // 9-0
                !(char >= 0x41 && char <= 0x5A) && // A-Z
                !(char >= 0x61 && char <= 0x7A) && // a-z
                !(char == 0x20 || char == 0x2D) && // space, dash
                !(char == 0x2E || char == 0x5F) && // period, underscore
                !(char == 0x2A) // *
            ) {
                return false;
            }
        }
        return true;
    }

    /// @notice Whether _user can use _name for their fund
    function canUseFundName(address _user, string memory _name) public view returns (bool) {
        bytes32 nameHash = keccak256(bytes(_name));
        return (
            isValidFundName(_name) &&
            (
                fundNameHashToOwner[nameHash] == address(0) ||
                fundNameHashToOwner[nameHash] == _user
            )
        );
    }

    function reserveFundName(address _owner, string calldata _name)
        external
        onlyVersion
    {
        require(canUseFundName(_owner, _name), "Fund name cannot be used");
        fundNameHashToOwner[keccak256(bytes(_name))] = _owner;
    }

    function registerFund(address _fund, address _owner, string calldata _name)
        external
        onlyVersion
    {
        require(canUseFundName(_owner, _name), "Fund name cannot be used");
        fundsToVersions[_fund] = msg.sender;
    }

    /// @notice Registers an Asset information entry
    /// @dev Pre: Only registrar owner should be able to register
    /// @dev Post: Address _asset is registered
    /// @param _asset Address of asset to be registered
    /// @param _name Human-readable name of the Asset
    /// @param _symbol Human-readable symbol of the Asset
    /// @param _url Url for extended information of the asset
    /// @param _standards Integers of EIP standards this asset adheres to
    /// @param _sigs Function signatures for whitelisted asset functions
    function registerAsset(
        address _asset,
        string calldata _name,
        string calldata _symbol,
        string calldata _url,
        uint _reserveMin,
        uint[] calldata _standards,
        bytes4[] calldata _sigs
    ) external auth {
        require(registeredAssets.length < MAX_REGISTERED_ENTITIES);
        require(!assetInformation[_asset].exists);
        assetInformation[_asset].exists = true;
        registeredAssets.push(_asset);
        updateAsset(
            _asset,
            _name,
            _symbol,
            _url,
            _reserveMin,
            _standards,
            _sigs
        );
    }

    /// @notice Register an exchange information entry (A mapping from exchange adapter -> Exchange information)
    /// @dev Adapters are unique so are used as the mapping key. There may be different adapters for same exchange (0x / Ethfinex)
    /// @dev Pre: Only registrar owner should be able to register
    /// @dev Post: Address _exchange is registered
    /// @param _exchange Address of the exchange for the adapter
    /// @param _adapter Address of exchange adapter
    /// @param _takesCustody Whether this exchange takes custody of tokens before trading
    /// @param _sigs Function signatures for whitelisted exchange functions
    function registerExchangeAdapter(
        address _exchange,
        address _adapter,
        bool _takesCustody,
        bytes4[] calldata _sigs
    ) external auth {
        require(!exchangeInformation[_adapter].exists, "Adapter already exists");
        exchangeInformation[_adapter].exists = true;
        require(registeredExchangeAdapters.length < MAX_REGISTERED_ENTITIES, "Exchange limit reached");
        registeredExchangeAdapters.push(_adapter);
        updateExchangeAdapter(
            _exchange,
            _adapter,
            _takesCustody,
            _sigs
        );
    }

    /// @notice Versions cannot be removed from registry
    /// @param _version Address of the version contract
    /// @param _name Name of the version
    function registerVersion(
        address _version,
        bytes32 _name
    ) external auth {
        require(!versionInformation[_version].exists, "Version already exists");
        require(!versionNameExists[_name], "Version name already exists");
        versionInformation[_version].exists = true;
        versionNameExists[_name] = true;
        versionInformation[_version].name = _name;
        registeredVersions.push(_version);
        emit VersionRegistration(_version);
    }

    function setIncentive(uint _weiAmount) external auth {
        incentive = _weiAmount;
        emit IncentiveChange(_weiAmount);
    }

    function setPriceSource(address _priceSource) external auth {
        priceSource = _priceSource;
        emit PriceSourceChange(_priceSource);
    }

    function setMlnToken(address _mlnToken) external auth {
        mlnToken = _mlnToken;
        emit MlnTokenChange(_mlnToken);
    }

    function setNativeAsset(address _nativeAsset) external auth {
        nativeAsset = _nativeAsset;
        emit NativeAssetChange(_nativeAsset);
    }

    function setEngine(address _engine) external auth {
        engine = _engine;
        emit EngineChange(_engine);
    }

    function setMGM(address _MGM) external auth {
        MGM = _MGM;
        emit MGMChange(_MGM);
    }

    function setEthfinexWrapperRegistry(address _registry) external auth {
        ethfinexWrapperRegistry = _registry;
        emit EfxWrapperRegistryChange(_registry);
    }

    /// @notice Updates description information of a registered Asset
    /// @dev Pre: Owner can change an existing entry
    /// @dev Post: Changed Name, Symbol, URL and/or IPFSHash
    /// @param _asset Address of the asset to be updated
    /// @param _name Human-readable name of the Asset
    /// @param _symbol Human-readable symbol of the Asset
    /// @param _url Url for extended information of the asset
    function updateAsset(
        address _asset,
        string memory _name,
        string memory _symbol,
        string memory _url,
        uint _reserveMin,
        uint[] memory _standards,
        bytes4[] memory _sigs
    ) public auth {
        require(assetInformation[_asset].exists);
        Asset storage asset = assetInformation[_asset];
        asset.name = _name;
        asset.symbol = _symbol;
        asset.decimals = ERC20WithFields(_asset).decimals();
        asset.url = _url;
        asset.reserveMin = _reserveMin;
        asset.standards = _standards;
        asset.sigs = _sigs;
        emit AssetUpsert(
            _asset,
            _name,
            _symbol,
            asset.decimals,
            _url,
            _reserveMin,
            _standards,
            _sigs
        );
    }

    function updateExchangeAdapter(
        address _exchange,
        address _adapter,
        bool _takesCustody,
        bytes4[] memory _sigs
    ) public auth {
        require(exchangeInformation[_adapter].exists, "Exchange with adapter doesn't exist");
        Exchange storage exchange = exchangeInformation[_adapter];
        exchange.exchangeAddress = _exchange;
        exchange.takesCustody = _takesCustody;
        exchange.sigs = _sigs;
        emit ExchangeAdapterUpsert(
            _exchange,
            _adapter,
            _takesCustody,
            _sigs
        );
    }

    /// @notice Deletes an existing entry
    /// @dev Owner can delete an existing entry
    /// @param _asset address for which specific information is requested
    function removeAsset(
        address _asset,
        uint _assetIndex
    ) external auth {
        require(assetInformation[_asset].exists);
        require(registeredAssets[_assetIndex] == _asset);
        delete assetInformation[_asset];
        delete registeredAssets[_assetIndex];
        for (uint i = _assetIndex; i < registeredAssets.length-1; i++) {
            registeredAssets[i] = registeredAssets[i+1];
        }
        registeredAssets.pop();
        emit AssetRemoval(_asset);
    }

    /// @notice Deletes an existing entry
    /// @dev Owner can delete an existing entry
    /// @param _adapter address of the adapter of the exchange that is to be removed
    /// @param _adapterIndex index of the exchange in array
    function removeExchangeAdapter(
        address _adapter,
        uint _adapterIndex
    ) external auth {
        require(exchangeInformation[_adapter].exists, "Exchange with adapter doesn't exist");
        require(registeredExchangeAdapters[_adapterIndex] == _adapter, "Incorrect adapter index");
        delete exchangeInformation[_adapter];
        delete registeredExchangeAdapters[_adapterIndex];
        for (uint i = _adapterIndex; i < registeredExchangeAdapters.length-1; i++) {
            registeredExchangeAdapters[i] = registeredExchangeAdapters[i+1];
        }
        registeredExchangeAdapters.pop();
        emit ExchangeAdapterRemoval(_adapter);
    }

    function registerFees(address[] calldata _fees) external auth {
        for (uint i; i < _fees.length; i++) {
            isFeeRegistered[_fees[i]] = true;
        }
    }

    function deregisterFees(address[] calldata _fees) external auth {
        for (uint i; i < _fees.length; i++) {
            delete isFeeRegistered[_fees[i]];
        }
    }

    // PUBLIC VIEW METHODS

    // get asset specific information
    function getName(address _asset) external view returns (string memory) {
        return assetInformation[_asset].name;
    }
    function getSymbol(address _asset) external view returns (string memory) {
        return assetInformation[_asset].symbol;
    }
    function getDecimals(address _asset) external view returns (uint) {
        return assetInformation[_asset].decimals;
    }
    function getReserveMin(address _asset) external view returns (uint) {
        return assetInformation[_asset].reserveMin;
    }
    function assetIsRegistered(address _asset) external view returns (bool) {
        return assetInformation[_asset].exists;
    }
    function getRegisteredAssets() external view returns (address[] memory) {
        return registeredAssets;
    }
    function assetMethodIsAllowed(address _asset, bytes4 _sig)
        external
        view
        returns (bool)
    {
        bytes4[] memory signatures = assetInformation[_asset].sigs;
        for (uint i = 0; i < signatures.length; i++) {
            if (signatures[i] == _sig) {
                return true;
            }
        }
        return false;
    }

    // get exchange-specific information
    function exchangeAdapterIsRegistered(address _adapter) external view returns (bool) {
        return exchangeInformation[_adapter].exists;
    }
    function getRegisteredExchangeAdapters() external view returns (address[] memory) {
        return registeredExchangeAdapters;
    }
    function getExchangeInformation(address _adapter)
        public
        view
        returns (address, bool)
    {
        Exchange memory exchange = exchangeInformation[_adapter];
        return (
            exchange.exchangeAddress,
            exchange.takesCustody
        );
    }
    function exchangeForAdapter(address _adapter) external view returns (address) {
        Exchange memory exchange = exchangeInformation[_adapter];
        return exchange.exchangeAddress;
    }
    function getAdapterFunctionSignatures(address _adapter)
        public
        view
        returns (bytes4[] memory)
    {
        return exchangeInformation[_adapter].sigs;
    }
    function adapterMethodIsAllowed(
        address _adapter, bytes4 _sig
    )
        external
        view
        returns (bool)
    {
        bytes4[] memory signatures = exchangeInformation[_adapter].sigs;
        for (uint i = 0; i < signatures.length; i++) {
            if (signatures[i] == _sig) {
                return true;
            }
        }
        return false;
    }

    // get version and fund information
    function getRegisteredVersions() external view returns (address[] memory) {
        return registeredVersions;
    }

    function isFund(address _who) external view returns (bool) {
        if (fundsToVersions[_who] != address(0)) {
            return true; // directly from a hub
        } else {
            Hub hub = Hub(Spoke(_who).hub());
            require(
                hub.isSpoke(_who),
                "Call from either a spoke or hub"
            );
            return fundsToVersions[address(hub)] != address(0);
        }
    }

    function isFundFactory(address _who) external view returns (bool) {
        return versionInformation[_who].exists;
    }
}

File 22 of 25 : SafeMath.sol
pragma solidity 0.6.1;


/**
 * @title SafeMath
 * @dev Math operations with safety checks that revert on error
 */
library SafeMath {

  /**
  * @dev Multiplies two numbers, reverts on 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);

    return c;
  }

  /**
  * @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
  */
  function div(uint256 _a, uint256 _b) internal pure returns (uint256) {
    require(_b > 0); // Solidity only automatically asserts when dividing by 0
    uint256 c = _a / _b;
    // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold

    return c;
  }

  /**
  * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
  */
  function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
    require(_b <= _a);
    uint256 c = _a - _b;

    return c;
  }

  /**
  * @dev Adds two numbers, reverts on overflow.
  */
  function add(uint256 _a, uint256 _b) internal pure returns (uint256) {
    uint256 c = _a + _b;
    require(c >= _a);

    return c;
  }

  /**
  * @dev Divides two numbers and returns the remainder (unsigned integer modulo),
  * reverts when dividing by zero.
  */
  function mod(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b != 0);
    return a % b;
  }
}

File 23 of 25 : DSGuard.sol
/// @notice Retrieved from DappHub (https://git.io/fpwMi)

pragma solidity 0.6.1;

import "./DSAuth.sol";

contract DSGuardEvents {
    event LogPermit(
        bytes32 indexed src,
        bytes32 indexed dst,
        bytes32 indexed sig
    );

    event LogForbid(
        bytes32 indexed src,
        bytes32 indexed dst,
        bytes32 indexed sig
    );
}

contract DSGuard is DSAuth, DSAuthority, DSGuardEvents {
    bytes32 constant public ANY = bytes32(uint(-1));

    mapping (bytes32 => mapping (bytes32 => mapping (bytes32 => bool))) acl;

    function canCall(
        address src_, address dst_, bytes4 sig
    ) public view override returns (bool) {
        bytes32 src = bytes32(bytes20(src_));
        bytes32 dst = bytes32(bytes20(dst_));

        return acl[src][dst][sig]
            || acl[src][dst][ANY]
            || acl[src][ANY][sig]
            || acl[src][ANY][ANY]
            || acl[ANY][dst][sig]
            || acl[ANY][dst][ANY]
            || acl[ANY][ANY][sig]
            || acl[ANY][ANY][ANY];
    }

    function permit(bytes32 src, bytes32 dst, bytes32 sig) public auth {
        acl[src][dst][sig] = true;
        emit LogPermit(src, dst, sig);
    }

    function forbid(bytes32 src, bytes32 dst, bytes32 sig) public auth {
        acl[src][dst][sig] = false;
        emit LogForbid(src, dst, sig);
    }

    function permit(address src, address dst, bytes32 sig) public {
        permit(bytes32(bytes20(src)), bytes32(bytes20(dst)), sig);
    }
    function forbid(address src, address dst, bytes32 sig) public {
        forbid(bytes32(bytes20(src)), bytes32(bytes20(dst)), sig);
    }

}

contract DSGuardFactory {
    mapping (address => bool)  public  isGuard;

    function newGuard() public returns (DSGuard guard) {
        guard = new DSGuard();
        guard.setOwner(msg.sender);
        isGuard[address(guard)] = true;
    }
}

File 24 of 25 : IFee.sol
pragma solidity 0.6.1;

/// @dev Exposes "feeAmount", which maps fund state and fee state to uint
/// @dev Notice that "feeAmount" *may* change contract state
/// @dev Also exposes "updateState", which changes fee's internal state
interface IFee {
    function initializeForUser(uint feeRate, uint feePeriod, address denominationAsset) external;
    function feeAmount() external returns (uint);
    function updateState() external;

    /// @notice Used to enforce a convention
    function identifier() external view returns (uint);
}

File 25 of 25 : IFeeManager.sol
pragma solidity 0.6.1;

interface IFeeManagerFactory {
    function createInstance(
        address _hub,
        address _denominationAsset,
        address[] calldata _fees,
        uint[] calldata _feeRates,
        uint[] calldata _feePeriods,
        address _registry
    ) external returns (address);
}

Settings
{
  "remappings": [
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "evmVersion": "istanbul",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_hub","type":"address"},{"internalType":"address[]","name":"_defaultAssets","type":"address[]"},{"internalType":"address","name":"_registry","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"payer","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalAmguPaidInEth","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amguChargableGas","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"incentivePaid","type":"uint256"}],"name":"AmguPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requestOwner","type":"address"}],"name":"CancelRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"assets","type":"address[]"}],"name":"DisableInvestment","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"asset","type":"address[]"}],"name":"EnableInvestment","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requestOwner","type":"address"},{"indexed":true,"internalType":"address","name":"investmentAsset","type":"address"},{"indexed":false,"internalType":"uint256","name":"requestedShares","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"investmentAmount","type":"uint256"}],"name":"InvestmentRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"authority","type":"address"}],"name":"LogSetAuthority","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"LogSetOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"redeemer","type":"address"},{"indexed":false,"internalType":"address[]","name":"assets","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"assetQuantities","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"redeemedShares","type":"uint256"}],"name":"Redemption","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"requestOwner","type":"address"},{"indexed":true,"internalType":"address","name":"executor","type":"address"},{"indexed":true,"internalType":"address","name":"investmentAsset","type":"address"},{"indexed":false,"internalType":"uint256","name":"investmentAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"requestedShares","type":"uint256"}],"name":"RequestExecution","type":"event"},{"inputs":[],"name":"REQUEST_LIFESPAN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SHARES_DECIMALS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"authority","outputs":[{"internalType":"contract DSAuthority","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelRequest","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"requestOwner","type":"address"}],"name":"cancelRequestFor","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_assets","type":"address[]"}],"name":"disableInvestment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_assets","type":"address[]"}],"name":"enableInvestment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"engine","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"requestOwner","type":"address"}],"name":"executeRequestFor","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getHistoricalInvestors","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareQuantity","type":"uint256"}],"name":"getOwedPerformanceFees","outputs":[{"internalType":"uint256","name":"remainingShareQuantity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_who","type":"address"}],"name":"hasExpiredRequest","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"hasInvested","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_who","type":"address"}],"name":"hasRequest","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_who","type":"address"}],"name":"hasValidRequest","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"historicalInvestors","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"contract Hub","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[11]","name":"_spokes","type":"address[11]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"investAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mlnToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceSource","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareQuantity","type":"uint256"}],"name":"redeemQuantity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shareQuantity","type":"uint256"},{"internalType":"address[]","name":"requestedAssets","type":"address[]"}],"name":"redeemWithConstraints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestedShares","type":"uint256"},{"internalType":"uint256","name":"investmentAmount","type":"uint256"},{"internalType":"address","name":"investmentAsset","type":"address"}],"name":"requestInvestment","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"requests","outputs":[{"internalType":"address","name":"investmentAsset","type":"address"},{"internalType":"uint256","name":"investmentAmount","type":"uint256"},{"internalType":"uint256","name":"requestedShares","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"routes","outputs":[{"internalType":"address","name":"accounting","type":"address"},{"internalType":"address","name":"feeManager","type":"address"},{"internalType":"address","name":"participation","type":"address"},{"internalType":"address","name":"policyManager","type":"address"},{"internalType":"address","name":"shares","type":"address"},{"internalType":"address","name":"trading","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"registry","type":"address"},{"internalType":"address","name":"version","type":"address"},{"internalType":"address","name":"engine","type":"address"},{"internalType":"address","name":"mlnToken","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract DSAuthority","name":"authority_","type":"address"}],"name":"setAuthority","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

Deployed Bytecode

0x6080604052600436106101f25760003560e01c8063643466af1161010d578063b1ffd471116100a0578063c9d4623f1161006f578063c9d4623f146107a6578063e216ea2b146107bb578063ec622892146107ee578063edb9a5c014610869578063f16ab6dc1461089c576101f9565b8063b1ffd471146106d0578063be040fb014610752578063bec6146214610767578063bf7e214f14610791576101f9565b80637baf5929116100dc5780637baf592914610678578063851b16f51461069e5780638a471df9146106a65780638da5cb5b146106bb576101f9565b8063643466af1461056857806374adad1d146105cd5780637a9e5e4b146106305780637b10399914610663576101f9565b806344ed98dd1161018557806354c3b8c51161015457806354c3b8c51461043957806354fd4d501461046c5780635810a54c146104815780635d58287014610536576101f9565b806344ed98dd146103a0578063474e19f2146103dc57806349837b5e146103f15780634a248e2714610406576101f9565b806320531bc9116101c157806320531bc9146102ac578063212f6066146102dd578063365a86fc14610358578063429f41a71461036d576101f9565b80630b797141146101fe5780630d2485b11461022a57806313af403514610250578063158ef93e14610283576101f9565b366101f957005b600080fd5b34801561020a57600080fd5b506102286004803603602081101561022157600080fd5b50356108c6565b005b6102286004803603602081101561024057600080fd5b50356001600160a01b03166109e2565b34801561025c57600080fd5b506102286004803603602081101561027357600080fd5b50356001600160a01b0316610d94565b34801561028f57600080fd5b50610298610e42565b604080519115158252519081900360200190f35b3480156102b857600080fd5b506102c1610e4b565b604080516001600160a01b039092168252519081900360200190f35b3480156102e957600080fd5b506102286004803603602081101561030057600080fd5b810190602081018135600160201b81111561031a57600080fd5b82018360208201111561032c57600080fd5b803590602001918460208302840111600160201b8311171561034d57600080fd5b509092509050610e5a565b34801561036457600080fd5b506102c1610ef4565b34801561037957600080fd5b506102986004803603602081101561039057600080fd5b50356001600160a01b0316610f03565b3480156103ac57600080fd5b506103ca600480360360208110156103c357600080fd5b5035611087565b60408051918252519081900360200190f35b3480156103e857600080fd5b506103ca611199565b3480156103fd57600080fd5b506103ca61119e565b34801561041257600080fd5b506102986004803603602081101561042957600080fd5b50356001600160a01b03166111a5565b34801561044557600080fd5b506102986004803603602081101561045c57600080fd5b50356001600160a01b03166111d6565b34801561047857600080fd5b506102c16111eb565b34801561048d57600080fd5b50610228600480360360408110156104a457600080fd5b81359190810190604081016020820135600160201b8111156104c557600080fd5b8201836020820111156104d757600080fd5b803590602001918460208302840111600160201b831117156104f857600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506111fa945050505050565b6102286004803603606081101561054c57600080fd5b50803590602081013590604001356001600160a01b0316611b9a565b34801561057457600080fd5b5061057d6123d1565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156105b95781810151838201526020016105a1565b505050509050019250505060405180910390f35b3480156105d957600080fd5b50610600600480360360208110156105f057600080fd5b50356001600160a01b0316612433565b604080516001600160a01b0390951685526020850193909352838301919091526060830152519081900360800190f35b34801561063c57600080fd5b506102286004803603602081101561065357600080fd5b50356001600160a01b0316612464565b34801561066f57600080fd5b506102c161250e565b6102286004803603602081101561068e57600080fd5b50356001600160a01b0316612518565b610228612aaa565b3480156106b257600080fd5b506102c1612e50565b3480156106c757600080fd5b506102c1612e5a565b3480156106dc57600080fd5b506106e5612e69565b604080516001600160a01b039c8d1681529a8c1660208c0152988b168a8a0152968a1660608a0152948916608089015292881660a088015290871660c0870152861660e0860152851661010085015284166101208401529092166101408201529051908190036101600190f35b34801561075e57600080fd5b50610228612ebe565b34801561077357600080fd5b50610228600480360361016081101561078b57600080fd5b50612f43565b34801561079d57600080fd5b506102c161326f565b3480156107b257600080fd5b506102c161327e565b3480156107c757600080fd5b50610298600480360360208110156107de57600080fd5b50356001600160a01b0316613288565b3480156107fa57600080fd5b506102286004803603602081101561081157600080fd5b810190602081018135600160201b81111561082b57600080fd5b82018360208201111561083d57600080fd5b803590602001918460208302840111600160201b8311171561085e57600080fd5b5090925090506132a8565b34801561087557600080fd5b506102986004803603602081101561088c57600080fd5b50356001600160a01b03166133c4565b3480156108a857600080fd5b506102c1600480360360208110156108bf57600080fd5b50356133d9565b60035460408051630a616f2560e21b815290516060926001600160a01b031691632985bc94916004808301926000929190829003018186803b15801561090b57600080fd5b505afa15801561091f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561094857600080fd5b8101908080516040519392919084600160201b82111561096757600080fd5b90830190602082018581111561097c57600080fd5b82518660208202830111600160201b8211171561099857600080fd5b82525081516020918201928201910280838360005b838110156109c55781810151838201526020016109ad565b5050505090500160405250505090506109de82826111fa565b5050565b6000805a90506109f183613400565b60005a90506000610a0061327e565b6001600160a01b031663709bb5676040518163ffffffff1660e01b815260040160206040518083038186803b158015610a3857600080fd5b505afa158015610a4c573d6000803e3d6000fd5b505050506040513d6020811015610a6257600080fd5b505190506000610a7b82610a768686613703565b613759565b90506000610a8761250e565b6001600160a01b03166374d32ad46040518163ffffffff1660e01b815260040160206040518083038186803b158015610abf57600080fd5b505afa158015610ad3573d6000803e3d6000fd5b505050506040513d6020811015610ae957600080fd5b505190506000610af7610e4b565b6001600160a01b0316637e3bfc2f84610b0e612e50565b856040518463ffffffff1660e01b815260040180848152602001836001600160a01b03166001600160a01b03168152602001826001600160a01b03166001600160a01b03168152602001935050505060206040518083038186803b158015610b7557600080fd5b505afa158015610b89573d6000803e3d6000fd5b505050506040513d6020811015610b9f57600080fd5b5051905060008715610c1e57610bb361250e565b6001600160a01b0316631d4632ac6040518163ffffffff1660e01b815260040160206040518083038186803b158015610beb57600080fd5b505afa158015610bff573d6000803e3d6000fd5b505050506040513d6020811015610c1557600080fd5b50519050610c22565b5060005b610c2c82826137bc565b341015610c6a5760405162461bcd60e51b81526004018080602001828103825260218152602001806140366021913960400191505060405180910390fd5b610c7261327e565b6001600160a01b0316635ce1fb54836040518263ffffffff1660e01b81526004016000604051808303818588803b158015610cac57600080fd5b505af1158015610cc0573d6000803e3d6000fd5b5050505050336001600160a01b03166108fc610ce5610cdf3486613703565b84613703565b6040518115909202916000818181858888f19350505050610d3d576040805162461bcd60e51b815260206004820152600d60248201526c1499599d5b990819985a5b1959609a1b604482015290519081900360640190fd5b337f0fa722789511f8feef9c02f613ad3ad10699034c1725894b9e7040552af4ffb983610d6a8a8a613703565b604080519283526020830191909152818101859052519081900360600190a2505050505050505050565b610daa336000356001600160e01b03191661380b565b610df2576040805162461bcd60e51b8152602060048201526014602482015273191ccb585d5d1a0b5d5b985d5d1a1bdc9a5e995960621b604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0383811691909117918290556040519116907fce241d7ca1f669fee44b6fc00b8eba2df3bb514eed0f6f668f8f89096e81ed9490600090a250565b600e5460ff1681565b6000610e556138f2565b905090565b610e70336000356001600160e01b03191661380b565b610eb8576040805162461bcd60e51b8152602060048201526014602482015273191ccb585d5d1a0b5d5b985d5d1a1bdc9a5e995960621b604482015290519081900360640190fd5b6109de82828080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061396892505050565b6002546001600160a01b031681565b600080610f0e610e4b565b90506000816001600160a01b0316634c89867f6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f4b57600080fd5b505afa158015610f5f573d6000803e3d6000fd5b505050506040513d6020811015610f7557600080fd5b50516001600160a01b0385166000908152600f6020526040902060030154108061100d5750600754604080516318160ddd60e01b815290516001600160a01b03909216916318160ddd91600481810192602092909190829003018186803b158015610fdf57600080fd5b505afa158015610ff3573d6000803e3d6000fd5b505050506040513d602081101561100957600080fd5b5051155b905061101884613288565b80156110215750805b80156110335750611031846111a5565b155b801561105957506001600160a01b0384166000908152600f602052604090206001015415155b801561107f57506001600160a01b0384166000908152600f602052604090206002015415155b949350505050565b60075460048054604080516335ff1bb760e01b815290516000946001600160a01b03908116948694909116926335ff1bb7928183019260209282900301818787803b1580156110d557600080fd5b505af11580156110e9573d6000803e3d6000fd5b505050506040513d60208110156110ff57600080fd5b5051604080516318160ddd60e01b8152905191925060009161117e916001600160a01b038616916318160ddd91600480820192602092909190829003018186803b15801561114c57600080fd5b505afa158015611160573d6000803e3d6000fd5b505050506040513d602081101561117657600080fd5b5051836137bc565b6111888387613759565b8161118f57fe5b0495945050505050565b601281565b6201518081565b6001600160a01b0381166000908152600f60205260408120600301546111ce90620151806137bc565b421192915050565b60106020526000908152604090205460ff1681565b600b546001600160a01b031690565b600754604080516370a0823160e01b815233600482015290516001600160a01b0390921691849183916370a0823191602480820192602092909190829003018186803b15801561124957600080fd5b505afa15801561125d573d6000803e3d6000fd5b505050506040513d602081101561127357600080fd5b5051108015906112f65750604080516370a0823160e01b815233600482015290516000916001600160a01b038416916370a0823191602480820192602092909190829003018186803b1580156112c857600080fd5b505afa1580156112dc573d6000803e3d6000fd5b505050506040513d60208110156112f257600080fd5b5051115b6113315760405162461bcd60e51b8152600401808060200182810382526035815260200180613fb16035913960400191505060405180910390fd5b600061133b610e4b565b6001600160a01b03166380971a36846040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019060200280838360005b83811015611399578181015183820152602001611381565b505050509050019250505060206040518083038186803b1580156113bc57600080fd5b505afa1580156113d0573d6000803e3d6000fd5b505050506040513d60208110156113e657600080fd5b505180156114765750600260009054906101000a90046001600160a01b03166001600160a01b031663481c6a756040518163ffffffff1660e01b815260040160206040518083038186803b15801561143d57600080fd5b505afa158015611451573d6000803e3d6000fd5b505050506040513d602081101561146757600080fd5b50516001600160a01b03163314155b15611638576004805460408051631bb7381160e31b815290516001600160a01b039092169263ddb9c08892828201926000929082900301818387803b1580156114be57600080fd5b505af11580156114d2573d6000803e3d6000fd5b505050506114df84611087565b604080516366bde28b60e11b81523360048201526024810183905290519192506001600160a01b0384169163cd7bc5169160448082019260009290919082900301818387803b15801561153157600080fd5b505af1158015611545573d6000803e3d6000fd5b50505050816001600160a01b0316631d48946c600260009054906101000a90046001600160a01b03166001600160a01b031663481c6a756040518163ffffffff1660e01b815260040160206040518083038186803b1580156115a657600080fd5b505afa1580156115ba573d6000803e3d6000fd5b505050506040513d60208110156115d057600080fd5b5051604080516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820185905251604480830192600092919082900301818387803b15801561161f57600080fd5b505af1158015611633573d6000803e3d6000fd5b505050505b60006116448583613703565b9050600060608551604051908082528060200260200182016040528015611675578160200160208202803883390190505b509050606086516040519080825280602002602001820160405280156116a5578160200160208202803883390190505b506003549091506001600160a01b031660005b885181101561195c578881815181106116cd57fe5b60200260200101519450816001600160a01b0316630e7a2d4e866040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561172d57600080fd5b505afa158015611741573d6000803e3d6000fd5b505050506040513d602081101561175757600080fd5b50516117945760405162461bcd60e51b8152600401808060200182810382526021815260200180613f6f6021913960400191505060405180910390fd5b60005b8351811015611822578381815181106117ac57fe5b60200260200101516001600160a01b0316866001600160a01b0316141561181a576040805162461bcd60e51b815260206004820152601f60248201527f41737365742063616e206f6e6c792062652072656465656d6564206f6e636500604482015290519081900360640190fd5b600101611797565b508483828151811061183057fe5b6001600160a01b039283166020918202929092018101919091526040805163ca334fe560e01b81528884166004820152905160009386169263ca334fe5926024808201939182900301818787803b15801561188a57600080fd5b505af115801561189e573d6000803e3d6000fd5b505050506040513d60208110156118b457600080fd5b50519050806118c35750611954565b886001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156118fc57600080fd5b505afa158015611910573d6000803e3d6000fd5b505050506040513d602081101561192657600080fd5b50516119328289613759565b8161193957fe5b0485838151811061194657fe5b602002602001018181525050505b6001016116b8565b50604080516366bde28b60e11b81523360048201526024810187905290516001600160a01b0389169163cd7bc51691604480830192600092919082900301818387803b1580156119ab57600080fd5b505af11580156119bf573d6000803e3d6000fd5b506000925050505b8851811015611ac1578881815181106119dc57fe5b602002602001015194508381815181106119f257fe5b602002602001015160001415611a0757611ab9565b60095484516001600160a01b039091169063f3fef3a3908790879085908110611a2c57fe5b60200260200101516040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611a8357600080fd5b505af1158015611a97573d6000803e3d6000fd5b50505050611ab98533868481518110611aac57fe5b6020026020010151613b1e565b6001016119c7565b50336001600160a01b03167f976b5f495b9d6400bbe35e173a78de5e77ffd728e55e900f45a495dec4143e17898588604051808060200180602001848152602001838103835286818151815260200191508051906020019060200280838360005b83811015611b3a578181015183820152602001611b22565b50505050905001838103825285818151815260200191508051906020019060200280838360005b83811015611b79578181015183820152602001611b61565b505050509050019550505050505060405180910390a2505050505050505050565b600260009054906101000a90046001600160a01b03166001600160a01b031663ff9475256040518163ffffffff1660e01b815260040160206040518083038186803b158015611be857600080fd5b505afa158015611bfc573d6000803e3d6000fd5b505050506040513d6020811015611c1257600080fd5b505115611c59576040805162461bcd60e51b815260206004820152601060248201526f243ab11034b99039b43aba103237bbb760811b604482015290519081900360640190fd5b600160005a600e5490915060ff16611cb8576040805162461bcd60e51b815260206004820152601d60248201527f436f6d706f6e656e74206e6f742079657420696e697469616c697a6564000000604482015290519081900360640190fd5b6006546040805160a08082018352338252600060208084018290528385018290526001600160a01b038981166060808701919091526080860184905286519081018752838152918201839052818601839052945163da6670d360e01b81526001600160e01b031983351660048201818152969097169663da6670d3969095949293929091602401908590808383875b83811015611d5f578181015183820152602001611d47565b5050505090500183600360200280838360005b83811015611d8a578181015183820152602001611d72565b50505050905001828152602001945050505050600060405180830381600087803b158015611db757600080fd5b505af1158015611dcb573d6000803e3d6000fd5b505050506001600160a01b03831660009081526010602052604090205460ff16611e265760405162461bcd60e51b81526004018080602001828103825260248152602001806140576024913960400191505060405180910390fd5b611e3283333087613ceb565b336000908152600f602052604090206003015415611e815760405162461bcd60e51b8152600401808060200182810382526024815260200180613f4b6024913960400191505060405180910390fd5b60408051608080820183526001600160a01b0386811680845260208085018a81528587018c8152426060808901918252336000818152600f87528b81209a518b546001600160a01b031916908a16178b55945160018b0155925160028a01559051600390980197909755600654885160a08082018b52928152808501849052808a018490528089019590955295840182905287519687018852818752918601819052858701819052955163185f31cf60e31b815286356001600160e01b03191660048201818152959094169663c2f98e7896949593949390929091602401908590808383875b83811015611f7f578181015183820152602001611f67565b5050505090500183600360200280838360005b83811015611faa578181015183820152602001611f92565b50505050905001828152602001945050505050600060405180830381600087803b158015611fd757600080fd5b505af1158015611feb573d6000803e3d6000fd5b5050604080518881526020810188905281516001600160a01b03881694503393507f7ac4e9fa94c85b700a3c05a368f0cbc8503fba59158d3e01cc96f608c82bb202929181900390910190a360005a9050600061204661327e565b6001600160a01b031663709bb5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561207e57600080fd5b505afa158015612092573d6000803e3d6000fd5b505050506040513d60208110156120a857600080fd5b5051905060006120bc82610a768686613703565b905060006120c861250e565b6001600160a01b03166374d32ad46040518163ffffffff1660e01b815260040160206040518083038186803b15801561210057600080fd5b505afa158015612114573d6000803e3d6000fd5b505050506040513d602081101561212a57600080fd5b505190506000612138610e4b565b6001600160a01b0316637e3bfc2f8461214f612e50565b856040518463ffffffff1660e01b815260040180848152602001836001600160a01b03166001600160a01b03168152602001826001600160a01b03166001600160a01b03168152602001935050505060206040518083038186803b1580156121b657600080fd5b505afa1580156121ca573d6000803e3d6000fd5b505050506040513d60208110156121e057600080fd5b505190506000871561225f576121f461250e565b6001600160a01b0316631d4632ac6040518163ffffffff1660e01b815260040160206040518083038186803b15801561222c57600080fd5b505afa158015612240573d6000803e3d6000fd5b505050506040513d602081101561225657600080fd5b50519050612263565b5060005b61226d82826137bc565b3410156122ab5760405162461bcd60e51b81526004018080602001828103825260218152602001806140366021913960400191505060405180910390fd5b6122b361327e565b6001600160a01b0316635ce1fb54836040518263ffffffff1660e01b81526004016000604051808303818588803b1580156122ed57600080fd5b505af1158015612301573d6000803e3d6000fd5b5050505050336001600160a01b03166108fc612320610cdf3486613703565b6040518115909202916000818181858888f19350505050612378576040805162461bcd60e51b815260206004820152600d60248201526c1499599d5b990819985a5b1959609a1b604482015290519081900360640190fd5b337f0fa722789511f8feef9c02f613ad3ad10699034c1725894b9e7040552af4ffb9836123a58a8a613703565b604080519283526020830191909152818101859052519081900360600190a25050505050505050505050565b6060601280548060200260200160405190810160405280929190818152602001828054801561242957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161240b575b5050505050905090565b600f6020526000908152604090208054600182015460028301546003909301546001600160a01b0390921692909184565b61247a336000356001600160e01b03191661380b565b6124c2576040805162461bcd60e51b8152602060048201526014602482015273191ccb585d5d1a0b5d5b985d5d1a1bdc9a5e995960621b604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b03838116919091178083556040519116917f1abebea81bfa2637f28358c371278fb15ede7ea8dd28d2e03b112ff6d936ada491a250565b6000610e55613ec1565b600260009054906101000a90046001600160a01b03166001600160a01b031663ff9475256040518163ffffffff1660e01b815260040160206040518083038186803b15801561256657600080fd5b505afa15801561257a573d6000803e3d6000fd5b505050506040513d602081101561259057600080fd5b5051156125d7576040805162461bcd60e51b815260206004820152601060248201526f243ab11034b99039b43aba103237bbb760811b604482015290519081900360640190fd5b6000805a90506125e5613eee565b506001600160a01b038084166000908152600f602090815260409182902082516080810184528154909416845260018101549184019190915260028101549183019190915260030154606082015261263c84610f03565b6126775760405162461bcd60e51b81526004018080602001828103825260218152602001806140156021913960400191505060405180910390fd5b6004805460408051631bb7381160e31b815290516001600160a01b039092169263ddb9c08892828201926000929082900301818387803b1580156126ba57600080fd5b505af11580156126ce573d6000803e3d6000fd5b50506003546040808501518551825163896aad5360e01b815260048101929092526001600160a01b03908116602483015291516000955091909216925063896aad539160448082019260209290919082900301818787803b15801561273257600080fd5b505af1158015612746573d6000803e3d6000fd5b505050506040513d602081101561275c57600080fd5b505160208301519091508111156127ba576040805162461bcd60e51b815260206004820152601760248201527f496e76657374656420616d6f756e7420746f6f206c6f77000000000000000000604482015290519081900360640190fd5b81516009546127d391906001600160a01b031683613b1e565b60006127e3836020015183613703565b905080156127f85782516127f8908783613b1e565b600a54604080516307518cab60e21b8152905133926108fc926001600160a01b0390911691631d4632ac91600480820192602092909190829003018186803b15801561284357600080fd5b505afa158015612857573d6000803e3d6000fd5b505050506040513d602081101561286d57600080fd5b50516040518115909202916000818181858888f19350505050158015612897573d6000803e3d6000fd5b506007546040808501518151630752251b60e21b81526001600160a01b038a8116600483015260248201929092529151921691631d48946c9160448082019260009290919082900301818387803b1580156128f157600080fd5b505af1158015612905573d6000803e3d6000fd5b50506003548551604080516301ebef9d60e21b81526001600160a01b03928316600482015290519190921693506307afbe749250602480830192600092919082900301818387803b15801561295957600080fd5b505af115801561296d573d6000803e3d6000fd5b505050506001600160a01b03861660009081526011602052604090205460ff166129f7576001600160a01b0386166000818152601160205260408120805460ff191660019081179091556012805491820181559091527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34440180546001600160a01b03191690911790555b82600001516001600160a01b0316336001600160a01b0316876001600160a01b03167fd826cdb072fceaa49209a7f9dc6283914ae87fb72f26cc328c67f8b54599957b86602001518760400151604051808381526020018281526020019250505060405180910390a45050506001600160a01b0383166000908152600f6020526040812080546001600160a01b031916815560018101829055600281018290556003018190555a90506000610a0061327e565b6000805a9050612ab933613400565b60005a90506000612ac861327e565b6001600160a01b031663709bb5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612b0057600080fd5b505afa158015612b14573d6000803e3d6000fd5b505050506040513d6020811015612b2a57600080fd5b505190506000612b3e82610a768686613703565b90506000612b4a61250e565b6001600160a01b03166374d32ad46040518163ffffffff1660e01b815260040160206040518083038186803b158015612b8257600080fd5b505afa158015612b96573d6000803e3d6000fd5b505050506040513d6020811015612bac57600080fd5b505190506000612bba610e4b565b6001600160a01b0316637e3bfc2f84612bd1612e50565b856040518463ffffffff1660e01b815260040180848152602001836001600160a01b03166001600160a01b03168152602001826001600160a01b03166001600160a01b03168152602001935050505060206040518083038186803b158015612c3857600080fd5b505afa158015612c4c573d6000803e3d6000fd5b505050506040513d6020811015612c6257600080fd5b5051905060008715612ce157612c7661250e565b6001600160a01b0316631d4632ac6040518163ffffffff1660e01b815260040160206040518083038186803b158015612cae57600080fd5b505afa158015612cc2573d6000803e3d6000fd5b505050506040513d6020811015612cd857600080fd5b50519050612ce5565b5060005b612cef82826137bc565b341015612d2d5760405162461bcd60e51b81526004018080602001828103825260218152602001806140366021913960400191505060405180910390fd5b612d3561327e565b6001600160a01b0316635ce1fb54836040518263ffffffff1660e01b81526004016000604051808303818588803b158015612d6f57600080fd5b505af1158015612d83573d6000803e3d6000fd5b5050505050336001600160a01b03166108fc612da2610cdf3486613703565b6040518115909202916000818181858888f19350505050612dfa576040805162461bcd60e51b815260206004820152600d60248201526c1499599d5b990819985a5b1959609a1b604482015290519081900360640190fd5b337f0fa722789511f8feef9c02f613ad3ad10699034c1725894b9e7040552af4ffb983612e278a8a613703565b604080519283526020830191909152818101859052519081900360600190a25050505050505050565b6000610e55613ed0565b6001546001600160a01b031681565b600354600454600554600654600754600854600954600a54600b54600c54600d546001600160a01b039a8b169a998a16999889169897881697968716969586169594851694938416939283169291821691168b565b600754604080516370a0823160e01b815233600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015612f0957600080fd5b505afa158015612f1d573d6000803e3d6000fd5b505050506040513d6020811015612f3357600080fd5b50519050612f40816108c6565b50565b612f59336000356001600160e01b03191661380b565b612fa1576040805162461bcd60e51b8152602060048201526014602482015273191ccb585d5d1a0b5d5b985d5d1a1bdc9a5e995960621b604482015290519081900360640190fd5b6002546001600160a01b03163314612fb857600080fd5b600e5460ff1615613006576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015290519081900360640190fd5b60408051610160810182526001600160a01b038335811682526020808501358216908301528383013516918101919091526060810182600360200201356001600160a01b03166001600160a01b03168152602001826004600b811061306757fe5b60200201356001600160a01b03166001600160a01b03168152602001826005600b811061309057fe5b60200201356001600160a01b03166001600160a01b03168152602001826006600b81106130b957fe5b60200201356001600160a01b03166001600160a01b03168152602001826007600b81106130e257fe5b60200201356001600160a01b03166001600160a01b03168152602001826008600b811061310b57fe5b60200201356001600160a01b03166001600160a01b03168152602001826009600b811061313457fe5b60200201356001600160a01b03166001600160a01b0316815260200182600a600b811061315d57fe5b602090810291909101356001600160a01b039081169092528251600380546001600160a01b03199081169285169290921790559083015160048054831691841691909117905560408301516005805483169184169190911790556060830151600680548316918416919091179055608083015160078054831691841691909117905560a083015160088054831691841691909117905560c083015160098054831691841691909117905560e0830151600a80548316918416919091179055610100830151600b80548316918416919091179055610120830151600c8054831691841691909117905561014090920151600d80549093169116179055600e805460ff19166001179055612f406000610d94565b6000546001600160a01b031681565b6000610e55613edf565b6001600160a01b03166000908152600f6020526040902060030154151590565b6132be336000356001600160e01b03191661380b565b613306576040805162461bcd60e51b8152602060048201526014602482015273191ccb585d5d1a0b5d5b985d5d1a1bdc9a5e995960621b604482015290519081900360640190fd5b60005b8181101561335c5760006010600085858581811061332357fe5b602090810292909201356001600160a01b0316835250810191909152604001600020805460ff1916911515919091179055600101613309565b507f3dc6367c991e43485e267da6f765655c7afd64b44b9414b04ff80de370cf5121828260405180806020018281038252848482818152602001925060200280828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b60116020526000908152604090205460ff1681565b601281815481106133e657fe5b6000918252602090912001546001600160a01b0316905081565b61340981613288565b613451576040805162461bcd60e51b8152602060048201526014602482015273139bc81c995c5d595cdd081d1bc818d85b98d95b60621b604482015290519081900360640190fd5b600061345b610e4b565b9050613465613eee565b506001600160a01b038083166000908152600f6020908152604091829020825160808101845281548516808252600183015482850152600283015482860152600390920154606082015283516313533b5560e01b81526004810192909252925192938516926313533b5592602480840193919291829003018186803b1580156134ed57600080fd5b505afa158015613501573d6000803e3d6000fd5b505050506040513d602081101561351757600080fd5b505115806135295750613529836111a5565b806135aa5750600260009054906101000a90046001600160a01b03166001600160a01b031663ff9475256040518163ffffffff1660e01b815260040160206040518083038186803b15801561357d57600080fd5b505afa158015613591573d6000803e3d6000fd5b505050506040513d60208110156135a757600080fd5b50515b6135e55760405162461bcd60e51b8152600401808060200182810382526021815260200180613f906021913960400191505060405180910390fd5b80516020808301516001600160a01b038087166000908152600f8452604080822080546001600160a01b0319168155600181018390556002810183905560030191909155600a5481516307518cab60e21b81529151939433946108fc949290921692631d4632ac9260048083019392829003018186803b15801561366857600080fd5b505afa15801561367c573d6000803e3d6000fd5b505050506040513d602081101561369257600080fd5b50516040518115909202916000818181858888f193505050501580156136bc573d6000803e3d6000fd5b506136c8828683613b1e565b6040516001600160a01b038616907f8a46aebe3d6766257a923c4a998b5fd32d693bd7877df2e25ea7b7099310da2b90600090a25050505050565b80820382811115613753576040805162461bcd60e51b815260206004820152601560248201527464732d6d6174682d7375622d756e646572666c6f7760581b604482015290519081900360640190fd5b92915050565b60008115806137745750508082028282828161377157fe5b04145b613753576040805162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6d756c2d6f766572666c6f7760601b604482015290519081900360640190fd5b80820182811015613753576040805162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6164642d6f766572666c6f7760601b604482015290519081900360640190fd5b60006001600160a01b03831630141561382657506001613753565b6001546001600160a01b038481169116141561384457506001613753565b6000546001600160a01b031661385c57506000613753565b6000546040805163b700961360e01b81526001600160a01b0386811660048301523060248301526001600160e01b0319861660448301529151919092169163b7009613916064808301926020929190829003018186803b1580156138bf57600080fd5b505afa1580156138d3573d6000803e3d6000fd5b505050506040513d60208110156138e957600080fd5b50519050613753565b600254604080516320531bc960e01b815290516000926001600160a01b0316916320531bc9916004808301926020929190829003018186803b15801561393757600080fd5b505afa15801561394b573d6000803e3d6000fd5b505050506040513d602081101561396157600080fd5b5051905090565b60005b8151811015613aa557600a5482516001600160a01b0390911690631f8d99a99084908490811061399757fe5b60200260200101516040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156139e557600080fd5b505afa1580156139f9573d6000803e3d6000fd5b505050506040513d6020811015613a0f57600080fd5b5051613a59576040805162461bcd60e51b8152602060048201526014602482015273105cdcd95d081b9bdd081c9959da5cdd195c995960621b604482015290519081900360640190fd5b600160106000848481518110613a6b57fe5b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905560010161396b565b507f144a61ed164a4708d46e9929ca93ac8226b76226e0ceb5182c6eaa4d9cdc3429816040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015613b08578181015183820152602001613af0565b505050509050019250505060405180910390a150565b6000836001600160a01b03166370a08231846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015613b7657600080fd5b505afa158015613b8a573d6000803e3d6000fd5b505050506040513d6020811015613ba057600080fd5b50516040805163a9059cbb60e01b81526001600160a01b0386811660048301526024820186905291519293509086169163a9059cbb916044808201926020929091908290030181600087803b158015613bf857600080fd5b505af1158015613c0c573d6000803e3d6000fd5b505050506040513d6020811015613c2257600080fd5b5050604080516370a0823160e01b81526001600160a01b03858116600483015291516000928716916370a08231916024808301926020929190829003018186803b158015613c6f57600080fd5b505afa158015613c83573d6000803e3d6000fd5b505050506040513d6020811015613c9957600080fd5b5051905080613ca883856137bc565b14613ce45760405162461bcd60e51b815260040180806020018281038252602b815260200180613f20602b913960400191505060405180910390fd5b5050505050565b6000846001600160a01b03166370a08231846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015613d4357600080fd5b505afa158015613d57573d6000803e3d6000fd5b505050506040513d6020811015613d6d57600080fd5b5051604080516323b872dd60e01b81526001600160a01b0387811660048301528681166024830152604482018690529151929350908716916323b872dd916064808201926020929091908290030181600087803b158015613dcd57600080fd5b505af1158015613de1573d6000803e3d6000fd5b505050506040513d6020811015613df757600080fd5b5050604080516370a0823160e01b81526001600160a01b03858116600483015291516000928816916370a08231916024808301926020929190829003018186803b158015613e4457600080fd5b505afa158015613e58573d6000803e3d6000fd5b505050506040513d6020811015613e6e57600080fd5b5051905080613e7d83856137bc565b14613eb95760405162461bcd60e51b815260040180806020018281038252602f815260200180613fe6602f913960400191505060405180910390fd5b505050505050565b600a546001600160a01b031690565b600d546001600160a01b031690565b600c546001600160a01b031690565b604051806080016040528060006001600160a01b03168152602001600081526020016000815260200160008152509056fe526563656976657220646964206e6f74207265636569766520746f6b656e7320696e207472616e736665724f6e6c79206f6e6520726571756573742063616e20657869737420617420612074696d65526571756573746564206173736574206e6f7420696e206173736574206c6973744e6f2063616e63656c6c6174696f6e20636f6e646974696f6e20776173206d657453656e64657220646f6573206e6f74206861766520656e6f7567682073686172657320746f2066756c66696c6c2072657175657374526563656976657220646964206e6f74207265636569766520746f6b656e7320696e207472616e7366657246726f6d4e6f2076616c6964207265717565737420666f7220746869732061646472657373496e737566666963656e7420414d475520616e642f6f7220696e63656e74697665496e766573746d656e74206e6f7420616c6c6f77656420696e2074686973206173736574a2646970667358221220c8c881c31bf73e6260fa333441b2a86f898fe182daeacbdee21155d2d6683c2d64736f6c63430006010033

Deployed Bytecode Sourcemap

483:12567:16:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9426:219;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9426:219:16;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;9426:219:16;;:::i;:::-;;6314:160;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;6314:160:16;-1:-1:-1;;;;;6314:160:16;;:::i;566:130:0:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;566:130:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;566:130:0;-1:-1:-1;;;;;566:130:0;;:::i;190:23:15:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;190:23:15;;;:::i;:::-;;;;;;;;;;;;;;;;;;12821:114:16;;8:9:-1;5:2;;;30:1;27;20:12;5:2;12821:114:16;;;:::i;:::-;;;;-1:-1:-1;;;;;12821:114:16;;;;;;;;;;;;;;2388:111;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2388:111:16;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;2388:111:16;;;;;;;;-1:-1:-1;5:28;;2:2;;;46:1;43;36:12;2:2;2388:111:16;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;2388:111:16;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;2388:111:16;;-1:-1:-1;2388:111:16;-1:-1:-1;2388:111:16;:::i;140:14:15:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;140:14:15;;;:::i;3260:504:16:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3260:504:16;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3260:504:16;-1:-1:-1;;;;;3260:504:16;;:::i;8439:656::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;8439:656:16;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;8439:656:16;;:::i;:::-;;;;;;;;;;;;;;;;1396:41;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1396:41:16;;;:::i;1443:46::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1443:46:16;;;:::i;2856:157::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2856:157:16;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;2856:157:16;-1:-1:-1;;;;;2856:157:16;;:::i;1546:46::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1546:46:16;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1546:46:16;-1:-1:-1;;;;;1546:46:16;;:::i;1414:83:15:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1414:83:15;;;:::i;9852:2617:16:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9852:2617:16;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;9852:2617:16;;;;;;;;;;;;;;-1:-1:-1;5:28;;2:2;;;46:1;43;36:12;2:2;9852:2617:16;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;9852:2617:16;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;9852:2617:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;9852:2617:16;;-1:-1:-1;9852:2617:16;;-1:-1:-1;;;;;9852:2617:16:i;3770:1454::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3770:1454:16;;;;;;;;;;;-1:-1:-1;;;;;3770:1454:16;;:::i;12475:118::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;12475:118:16;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;12475:118:16;;;;;;;;;;;;;;;;;1496:44;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1496:44:16;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1496:44:16;-1:-1:-1;;;;;1496:44:16;;:::i;:::-;;;;-1:-1:-1;;;;;1496:44:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;702:167:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;702:167:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;702:167:0;-1:-1:-1;;;;;702:167:0;;:::i;12940:108:16:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;12940:108:16;;;:::i;6480:1953::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;6480:1953:16;-1:-1:-1;;;;;6480:1953:16;;:::i;6201:107::-;;;:::i;12708:108::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;12708:108:16;;;:::i;433:26:0:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;433:26:0;;;:::i;160:24:15:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;160:24:15;;;:::i;:::-;;;;-1:-1:-1;;;;;160:24:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;160:24:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9222:143:16;;8:9:-1;5:2;;;30:1;27;20:12;5:2;9222:143:16;;;:::i;605:532:15:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;605:532:15;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;605:532:15;:::i;397:30:0:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;397:30:0;;;:::i;12599:104:16:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;12599:104:16;;;:::i;2737:113::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2737:113:16;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;2737:113:16;-1:-1:-1;;;;;2737:113:16;;:::i;2505:226::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2505:226:16;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;2505:226:16;;;;;;;;-1:-1:-1;5:28;;2:2;;;46:1;43;36:12;2:2;2505:226:16;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;2505:226:16;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;2505:226:16;;-1:-1:-1;2505:226:16;-1:-1:-1;2505:226:16;:::i;1598:44::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1598:44:16;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1598:44:16;-1:-1:-1;;;;;1598:44:16;;:::i;1689:36::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1689:36:16;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1689:36:16;;:::i;9426:219::-;9546:6;:17;9535:46;;;-1:-1:-1;;;9535:46:16;;;;9487:26;;-1:-1:-1;;;;;9546:17:16;;9535:44;;:46;;;;;9546:17;;9535:46;;;;;;;9546:17;9535:46;;;5:2:-1;;;;30:1;27;20:12;5:2;9535:46:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;9535:46:16;;;;;;39:16:-1;36:1;17:17;2:54;101:4;9535:46:16;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;9535:46:16;;;;;;;;;;;;;-1:-1:-1;11:20;;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;213:10;;-1:-1;244:29;;325:2;307:21;;285:44;;282:59;-1:-1;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;9535:46:16;;421:4:-1;412:14;;;;9535:46:16;;;;;412:14:-1;9535:46:16;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;9535:46:16;;;;;;;;;;;9523:58;;9591:47;9613:13;9628:9;9591:21;:47::i;:::-;9426:219;;:::o;6314:160::-;6415:5;942:11:7;956:9;942:23;;6436:31:16::1;6454:12;6436:17;:31::i;:::-;986:12:7::0;1001:9;986:24;;1021:15;1047:8;:6;:8::i;:::-;-1:-1:-1;;;;;1039:30:7;;:32;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1039:32:7;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1039:32:7;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1039:32:7;;-1:-1:-1;1081:16:7;1100:71;1039:32;1141:20;1145:6;1153:7;1141:3;:20::i;:::-;1100:3;:71::i;:::-;1081:90;;1181:19;1212:10;:8;:10::i;:::-;-1:-1:-1;;;;;1203:32:7;;:34;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1203:34:7;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1203:34:7;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1203:34:7;;-1:-1:-1;1247:13:7;1276;:11;:13::i;:::-;-1:-1:-1;;;;;1263:43:7;;1320:11;1345:10;:8;:10::i;:::-;1263:127;;;-1:-1:-1;;;;;;1263:127:7;;;;;;;;;;;;;;-1:-1:-1;;;;;1263:127:7;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:2:-1;;;;30:1;27;20:12;5:2;1263:127:7;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1263:127:7;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1263:127:7;;-1:-1:-1;1400:20:7;1430:146;;;;1492:10;:8;:10::i;:::-;-1:-1:-1;;;;;1483:30:7;;:32;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1483:32:7;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1483:32:7;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1483:32:7;;-1:-1:-1;1430:146:7;;;-1:-1:-1;1564:1:7;1430:146;1619:30;1623:8;1633:15;1619:3;:30::i;:::-;1606:9;:43;;1585:123;;;;-1:-1:-1;;;1585:123:7;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1726:8;:6;:8::i;:::-;-1:-1:-1;;;;;1718:32:7;;1757:8;1718:50;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1718:50:7;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;1800:10:7;;-1:-1:-1;1800:151:7;;-1:-1:-1;1833:104:7;;-1:-1:-1;1858:24:7;;-1:-1:-1;1862:9:7;1873:8;1858:3;:24::i;:::-;1904:15;1833:3;:104::i;:::-;1800:151;;;;;;;;;;;;;;;;;;;;;1779:211;;;;;-1:-1:-1;;;1779:211:7;;;;;;;;;;;;-1:-1:-1;;;1779:211:7;;;;;;;;;;;;;;;2014:10;2005:69;2026:8;2036:20;2040:6;2048:7;2036:3;:20::i;:::-;2005:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;6314:160:16;;;;;;;;;:::o;566:130:0:-;907:33;920:10;-1:-1:-1;;;;;;932:7:0;;;907:12;:33::i;:::-;899:66;;;;;-1:-1:-1;;;899:66:0;;;;;;;;;;;;-1:-1:-1;;;899:66:0;;;;;;;;;;;;;;;642:5:::1;:14:::0;;-1:-1:-1;;;;;;642:14:0::1;-1:-1:-1::0;;;;;642:14:0;;::::1;::::0;;;::::1;::::0;;;;671:18:::1;::::0;683:5;::::1;::::0;671:18:::1;::::0;-1:-1:-1;;671:18:0::1;566:130:::0;:::o;190:23:15:-;;;;;;:::o;12821:114:16:-;12895:7;12913:19;:17;:19::i;:::-;12906:26;;12821:114;:::o;2388:111::-;907:33:0;920:10;-1:-1:-1;;;;;;932:7:0;;;907:12;:33::i;:::-;899:66;;;;;-1:-1:-1;;;899:66:0;;;;;;;;;;;;-1:-1:-1;;;899:66:0;;;;;;;;;;;;;;;2466:26:16::1;2484:7;;2466:26;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16:::0;::::1;74:27:::0;;;;-1:-1;2466:17:16::1;::::0;-1:-1:-1;;;2466:26:16:i:1;140:14:15:-:0;;;-1:-1:-1;;;;;140:14:15;;:::o;3260:504:16:-;3320:4;3336:24;3376:13;:11;:13::i;:::-;3336:54;;3400:29;3459:11;-1:-1:-1;;;;;3459:25:16;;:27;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3459:27:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3459:27:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3459:27:16;-1:-1:-1;;;;;3432:14:16;;;;;;:8;3459:27;3432:14;;;;:24;;;:54;;:110;;-1:-1:-1;3509:13:16;;3502:35;;;-1:-1:-1;;;3502:35:16;;;;-1:-1:-1;;;;;3509:13:16;;;;-1:-1:-1;;3509:13:16;3502:35;;;;;;;;;;;;;;3509:13;3502:35;;;5:2:-1;;;;30:1;27;20:12;5:2;3502:35:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;3502:35:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3502:35:16;:40;3432:110;3400:142;;3560:16;3571:4;3560:10;:16::i;:::-;:56;;;;;3592:24;3560:56;:96;;;;;3633:23;3651:4;3633:17;:23::i;:::-;3632:24;3560:96;:147;;;;-1:-1:-1;;;;;;3672:14:16;;3706:1;3672:14;;;:8;:14;;;;;-1:-1:-1;3672:31:16;;:35;;3560:147;:197;;;;-1:-1:-1;;;;;;3723:14:16;;3756:1;3723:14;;;:8;:14;;;;;:30;;;:34;;3560:197;3553:204;3260:504;-1:-1:-1;;;;3260:504:16:o;8439:656::-;8589:13;;;8652:17;;8641:52;;;-1:-1:-1;;;8641:52:16;;;;8523:27;;-1:-1:-1;;;;;8589:13:16;;;;8523:27;;8652:17;;;;;-1:-1:-1;;8641:52:16;;;;;;;;;;;8523:27;8652:17;8641:52;;;5:2:-1;;;;30:1;27;20:12;5:2;8641:52:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;8641:52:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;8641:52:16;9008:20;;;-1:-1:-1;;;9008:20:16;;;;8641:52;;-1:-1:-1;8899:26:16;;9004:46;;-1:-1:-1;;;;;9008:18:16;;;-1:-1:-1;;9008:20:16;;;;;8641:52;;9008:20;;;;;;;;:18;:20;;;5:2:-1;;;;30:1;27;20:12;5:2;9008:20:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;9008:20:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;9008:20:16;9030:19;9004:3;:46::i;:::-;8928:73;8945:19;8978:13;8928:3;:73::i;:::-;:122;;;;;;;8439:656;-1:-1:-1;;;;;8439:656:16:o;1396:41::-;1435:2;1396:41;:::o;1443:46::-;1483:6;1443:46;:::o;2856:157::-;-1:-1:-1;;;;;2963:14:16;;2918:4;2963:14;;;:8;:14;;;;;:24;;;2959:47;;1483:6;2959:3;:47::i;:::-;2941:15;:65;;2856:157;-1:-1:-1;;2856:157:16:o;1546:46::-;;;;;;;;;;;;;;;:::o;1414:83:15:-;1480:14;;-1:-1:-1;;;;;1480:14:15;;1414:83::o;9852:2617:16:-;9977:13;;10022:28;;;-1:-1:-1;;;10022:28:16;;10039:10;9977:13;10022:28;;;;;-1:-1:-1;;;;;9977:13:16;;;;10054;;9977;;-1:-1:-1;;10022:28:16;;;;;;;;;;;;;;;9977:13;10022:28;;;5:2:-1;;;;30:1;27;20:12;5:2;10022:28:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10022:28:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10022:28:16;:45;;;;:93;;-1:-1:-1;10083:28:16;;;-1:-1:-1;;;10083:28:16;;10100:10;10083:28;;;;;;-1:-1:-1;;;;;;;10083:16:16;;;-1:-1:-1;;10083:28:16;;;;;;;;;;;;;;;:16;:28;;;5:2:-1;;;;30:1;27;20:12;5:2;10083:28:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10083:28:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10083:28:16;:32;10022:93;10001:193;;;;-1:-1:-1;;;10001:193:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10205:24;10273:13;:11;:13::i;:::-;10260:59;;-1:-1:-1;;;10260:59:16;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;10260:42:16;;;;;;;10303:15;;10260:59;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;10260:59:16;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;10260:59:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10260:59:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10260:59:16;:102;;;;-1:-1:-1;10349:3:16;;:13;;;-1:-1:-1;;;10349:13:16;;;;-1:-1:-1;;;;;10349:3:16;;;;:11;;:13;;;;;;;;;;;;;;;:3;:13;;;5:2:-1;;;;30:1;27;20:12;5:2;10349:13:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10349:13:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10349:13:16;-1:-1:-1;;;;;10335:27:16;:10;:27;;10260:102;10243:409;;;10398:17;;;10387:51;;;-1:-1:-1;;;10387:51:16;;;;-1:-1:-1;;;;;10398:17:16;;;;10387:49;;:51;;;;10398:17;;10387:51;;;;;;10398:17;;10387:51;;;5:2:-1;;;;30:1;27;20:12;5:2;10387:51:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10387:51:16;;;;10474:37;10497:13;10474:22;:37::i;:::-;10525:50;;;-1:-1:-1;;;10525:50:16;;10543:10;10525:50;;;;;;;;;;;;;;-1:-1:-1;;;;;;10525:17:16;;;;;:50;;;;;-1:-1:-1;;10525:50:16;;;;;;;;-1:-1:-1;10525:17:16;:50;;;5:2:-1;;;;30:1;27;20:12;5:2;10525:50:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;10606:3:16;;:13;;;-1:-1:-1;;;10606:13:16;;;;-1:-1:-1;;;;;10589:16:16;;;;-1:-1:-1;10589:16:16;;-1:-1:-1;10606:3:16;;;;:11;;:13;;;;;;;;;;;;;;;:3;:13;;;5:2:-1;;;;30:1;27;20:12;5:2;10606:13:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10606:13:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10606:13:16;10589:52;;;-1:-1:-1;10589:52:16;;;-1:-1:-1;;;;;;10589:52:16;;;-1:-1:-1;;;;;10589:52:16;;;;;;;;;;;;;;;;;;;-1:-1:-1;;10589:52:16;;;;;;;-1:-1:-1;10589:52:16;;;;5:2:-1;;;;30:1;27;20:12;5:2;10589:52:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10589:52:16;;;;10243:409;10661:27;10691:39;10695:13;10710:19;10691:3;:39::i;:::-;10661:69;;10741:15;10766:33;10813:15;:22;10802:34;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;10802:34:16;;10766:70;;10846:31;10894:15;:22;10880:37;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;10880:37:16;-1:-1:-1;11014:6:16;:17;10846:71;;-1:-1:-1;;;;;;11014:17:16;10979:21;11042:792;11063:15;:22;11059:1;:26;11042:792;;;11116:15;11132:1;11116:18;;;;;;;;;;;;;;;;;;;11173:33;;;-1:-1:-1;;;11173:33:16;;-1:-1:-1;;;;;11173:33:16;;;;;;;;;11116:18;;-1:-1:-1;11173:24:16;;;;;;:33;;;;;;;;;;:24;:33;;;5:2:-1;;;;30:1;27;20:12;5:2;11173:33:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;11173:33:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;11173:33:16;11148:125;;;;-1:-1:-1;;;11148:125:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11292:6;11287:212;11308:14;:21;11304:1;:25;11287:212;;;11394:14;11409:1;11394:17;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;11383:28:16;;;;;;;11354:130;;;;;-1:-1:-1;;;11354:130:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;11331:3;;11287:212;;;;11532:7;11512:14;11527:1;11512:17;;;;;;;;-1:-1:-1;;;;;11512:27:16;;;:17;;;;;;;;;;:27;;;;11573:33;;;-1:-1:-1;;;11573:33:16;;;;;;;;;;;-1:-1:-1;;11573:24:16;;;-1:-1:-1;;11573:33:16;;;;;;;;;;;-1:-1:-1;11573:24:16;:33;;;5:2:-1;;;;30:1;27;20:12;5:2;11573:33:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;11573:33:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;11573:33:16;;-1:-1:-1;11624:17:16;11620:31;;11643:8;;;11620:31;11803:6;-1:-1:-1;;;;;11803:18:16;;:20;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11803:20:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;11803:20:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;11803:20:16;11759:41;11763:12;11777:22;11759:3;:41::i;:::-;:64;;;;;;11734:19;11754:1;11734:22;;;;;;;;;;;;;:89;;;;;11042:792;;11087:3;;11042:792;;;-1:-1:-1;11844:53:16;;;-1:-1:-1;;;11844:53:16;;11862:10;11844:53;;;;;;;;;;;;-1:-1:-1;;;;;11844:17:16;;;;;:53;;;;;-1:-1:-1;;11844:53:16;;;;;;;-1:-1:-1;11844:17:16;:53;;;5:2:-1;;;;30:1;27;20:12;5:2;11844:53:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;11946:6:16;;-1:-1:-1;;;11941:365:16;11962:15;:22;11958:1;:26;11941:365;;;12015:15;12031:1;12015:18;;;;;;;;;;;;;;12005:28;;12051:19;12071:1;12051:22;;;;;;;;;;;;;;12077:1;12051:27;12047:249;;;12098:8;;12047:249;12151:12;;12183:22;;-1:-1:-1;;;;;12151:12:16;;;;12145:28;;12174:7;;12183:22;;12203:1;;12183:22;;;;;;;;;;;;12145:61;;;;;;;;;;;;;-1:-1:-1;;;;;12145:61:16;-1:-1:-1;;;;;12145:61:16;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;12145:61:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;12145:61:16;;;;12224:57;12237:7;12246:10;12258:19;12278:1;12258:22;;;;;;;;;;;;;;12224:12;:57::i;:::-;11986:3;;11941:365;;;;12344:10;-1:-1:-1;;;;;12320:142:16;;12368:15;12397:19;12430:22;12320:142;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;12320:142:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;12320:142:16;;;;;;;;;;;;;;;;;;;;9852:2617;;;;;;;;;:::o;3770:1454::-;376:3:15;;:16;;;-1:-1:-1;;;;;;376:16:15;;;;-1:-1:-1;;;;;376:3:15;;;;:14;;:16;;;;;;;;;;;;;;;:3;:16;;;5:2:-1;;;;30:1;27;20:12;5:2;376:16:15;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;376:16:15;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;376:16:15;375:17;367:46;;;;;-1:-1:-1;;;367:46:15;;;;;;;;;;;;-1:-1:-1;;;367:46:15;;;;;;;;;;;;;;;3970:4:16::1;942:11:7;956:9;265:11:15::2;::::0;942:23:7;;-1:-1:-1;265:11:15::2;;257:53;;;::::0;;-1:-1:-1;;;257:53:15;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;4028:20:16::0;;4014:222:::3;::::0;;::::3;::::0;;::::3;::::0;;4097:10:::3;4014:222:::0;;-1:-1:-1;4014:222:16::3;::::0;;::::3;::::0;;;;;;;;;-1:-1:-1;;;;;4014:222:16;;::::3;::::0;;;;;;;;;;;;;;;;;;::::3;::::0;;;;;;;::::3;::::0;;;;;;;;;;;-1:-1:-1;;;4014:222:16;;4075:7;::::3;-1:-1:-1::0;;;;;;4075:7:16::3;4014:222;::::0;::::3;::::0;;;4028:20;;;::::3;::::0;-1:-1:-1;;4075:7:16;;4014:222;;;-1:-1:-1;4014:222:16;;;;;;;;;;-1:-1:-1;8:100:::3;33:3;30:1;27:10;8:100;;;90:11:::0;;::::3;84:18:::0;71:11;;::::3;64:39:::0;52:2:::3;45:10;8:100;;;12:14;4014:222:16;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11:::0;;::::3;84:18:::0;71:11;;::::3;64:39:::0;52:2:::3;45:10;8:100;;;12:14;4014:222:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27::::0;20:12:::3;5:2;4014:222:16;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::3;77:16;74:1;67:27;5:2;-1:-1:::0;;;;;;;;;4267:30:16;::::3;;::::0;;;:13:::3;:30;::::0;;;;;::::3;;4246:113;;;;-1:-1:-1::0;;;4246:113:16::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4369:100;4399:15;4416:10;4436:4;4443:16;4369;:100::i;:::-;4509:10;4500:20;::::0;;;:8:::3;:20;::::0;;;;:30:::3;;::::0;:35;4479:118:::3;;;;-1:-1:-1::0;;;4479:118:16::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4630:199;::::0;;::::3;::::0;;::::3;::::0;;-1:-1:-1;;;;;4630:199:16;;::::3;::::0;;;::::3;::::0;;::::3;::::0;;;;;;;;;4803:15:::3;4630:199:::0;;;;;;;4616:10:::3;-1:-1:-1::0;4607:20:16;;;:8:::3;:20:::0;;;;;:222;;;;-1:-1:-1;;;;;;4607:222:16::3;::::0;;::::3;;::::0;;;;-1:-1:-1;4607:222:16;::::3;::::0;;;::::3;::::0;::::3;::::0;;;::::3;::::0;;::::3;::::0;;;;4853:20;;4839:223;;-1:-1:-1;4839:223:16;;::::3;::::0;;;;;;;::::3;::::0;;;;;;;;;;;;;;;;;;;;;;;;;;::::3;::::0;;;;;;;::::3;::::0;;;;;;;;;;;-1:-1:-1;;;4839:223:16;;4901:7;::::3;-1:-1:-1::0;;;;;;4901:7:16::3;4839:223;::::0;::::3;::::0;;;4853:20;;;::::3;::::0;4839:48:::3;::::0;4901:7;;4839:223;;;-1:-1:-1;;4839:223:16;;;;;;;-1:-1:-1;4839:223:16;;-1:-1:-1;8:100:::3;33:3;30:1;27:10;8:100;;;90:11:::0;;::::3;84:18:::0;71:11;;::::3;64:39:::0;52:2:::3;45:10;8:100;;;12:14;4839:223:16;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11:::0;;::::3;84:18:::0;71:11;;::::3;64:39:::0;52:2:::3;45:10;8:100;;;12:14;4839:223:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27::::0;20:12:::3;5:2;4839:223:16;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::3;77:16;74:1;67:27;5:2;-1:-1:::0;;5078:139:16::3;::::0;;;;;::::3;::::0;::::3;::::0;;;;;-1:-1:-1;;;;;5078:139:16;::::3;::::0;-1:-1:-1;5109:10:16::3;::::0;-1:-1:-1;5078:139:16::3;::::0;;;;;;;;;::::3;986:12:7::1;1001:9;986:24;;1021:15;1047:8;:6;:8::i;:::-;-1:-1:-1::0;;;;;1039:30:7::1;;:32;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27::::0;20:12:::1;5:2;1039:32:7;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;1039:32:7;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26::::0;19:12:::1;2:2;-1:-1:::0;1039:32:7;;-1:-1:-1;1081:16:7::1;1100:71;1039:32:::0;1141:20:::1;1145:6:::0;1153:7;1141:3:::1;:20::i;1100:71::-;1081:90;;1181:19;1212:10;:8;:10::i;:::-;-1:-1:-1::0;;;;;1203:32:7::1;;:34;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27::::0;20:12:::1;5:2;1203:34:7;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;1203:34:7;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26::::0;19:12:::1;2:2;-1:-1:::0;1203:34:7;;-1:-1:-1;1247:13:7::1;1276;:11;:13::i;:::-;-1:-1:-1::0;;;;;1263:43:7::1;;1320:11:::0;1345:10:::1;:8;:10::i;:::-;1263:127;::::0;;-1:-1:-1;;;;;;1263:127:7::1;::::0;;;;;;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;1263:127:7;;::::1;::::0;;;;;;::::1;::::0;;;;;;;;;;::::1;::::0;;;;;;;;;;::::1;;5:2:-1::0;::::1;;;30:1;27::::0;20:12:::1;5:2;1263:127:7;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;1263:127:7;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26::::0;19:12:::1;2:2;-1:-1:::0;1263:127:7;;-1:-1:-1;1400:20:7::1;1430:146:::0;::::1;;;1492:10;:8;:10::i;:::-;-1:-1:-1::0;;;;;1483:30:7::1;;:32;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27::::0;20:12:::1;5:2;1483:32:7;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;1483:32:7;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26::::0;19:12:::1;2:2;-1:-1:::0;1483:32:7;;-1:-1:-1;1430:146:7::1;;;-1:-1:-1::0;1564:1:7::1;1430:146;1619:30;1623:8;1633:15;1619:3;:30::i;:::-;1606:9;:43;;1585:123;;;;-1:-1:-1::0;;;1585:123:7::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1726:8;:6;:8::i;:::-;-1:-1:-1::0;;;;;1718:32:7::1;;1757:8;1718:50;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27::::0;20:12:::1;5:2;1718:50:7;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;-1:-1:::0;1800:10:7::1;::::0;-1:-1:-1;1800:151:7::1;::::0;-1:-1:-1;1833:104:7::1;::::0;-1:-1:-1;1858:24:7::1;::::0;-1:-1:-1;1862:9:7::1;1873:8:::0;1858:3:::1;:24::i;1833:104::-;1800:151;::::0;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;::::1;;;;;;1779:211;;;::::0;;-1:-1:-1;;;1779:211:7;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;1779:211:7;;;;;;;;;;;;;::::1;;2014:10;2005:69;2026:8:::0;2036:20:::1;2040:6:::0;2048:7;2036:3:::1;:20::i;:::-;2005:69;::::0;;;;;::::1;::::0;::::1;::::0;;;;;;;;;;;;;;;;;;::::1;423:1:15;;;;;;;;3770:1454:16::0;;;:::o;12475:118::-;12532:16;12567:19;12560:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;12560:26:16;;;-1:-1:-1;12560:26:16;;;;;;;;;;;;;;;;;;;12475:118;:::o;1496:44::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1496:44:16;;;;;;;:::o;702:167:0:-;907:33;920:10;-1:-1:-1;;;;;;932:7:0;;;907:12;:33::i;:::-;899:66;;;;;-1:-1:-1;;;899:66:0;;;;;;;;;;;;-1:-1:-1;;;899:66:0;;;;;;;;;;;;;;;790:9:::1;:22:::0;;-1:-1:-1;;;;;;790:22:0::1;-1:-1:-1::0;;;;;790:22:0;;::::1;::::0;;;::::1;::::0;;;827:35:::1;::::0;851:9;::::1;::::0;827:35:::1;::::0;::::1;702:167:::0;:::o;12940:108:16:-;13011:7;13029:16;:14;:16::i;6480:1953::-;376:3:15;;:16;;;-1:-1:-1;;;;;;376:16:15;;;;-1:-1:-1;;;;;376:3:15;;;;:14;;:16;;;;;;;;;;;;;;;:3;:16;;;5:2:-1;;;;30:1;27;20:12;5:2;376:16:15;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;376:16:15;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;376:16:15;375:17;367:46;;;;;-1:-1:-1;;;367:46:15;;;;;;;;;;;;-1:-1:-1;;;367:46:15;;;;;;;;;;;;;;;6586:5:16::1;942:11:7::0;956:9:::1;942:23;;6623:22:16::2;;:::i;:::-;-1:-1:-1::0;;;;;;6648:22:16;;::::2;;::::0;;;:8:::2;:22;::::0;;;;;;;;6623:47;;::::2;::::0;::::2;::::0;;;;;;::::2;::::0;;-1:-1:-1;6623:47:16;::::2;::::0;;;::::2;::::0;;;;::::2;::::0;::::2;::::0;;;;;;;;::::2;;::::0;;;;;6701:29:::2;6648:22:::0;6701:15:::2;:29::i;:::-;6680:109;;;;-1:-1:-1::0;;;6680:109:16::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6811:17:::0;;;6800:51:::2;::::0;;-1:-1:-1;;;6800:51:16;;;;-1:-1:-1;;;;;6811:17:16;;::::2;::::0;6800:49:::2;::::0;:51;;::::2;::::0;6811:17:::2;::::0;6800:51;;;;;;6811:17;;6800:51;::::2;;5:2:-1::0;::::2;;;30:1;27::::0;20:12:::2;5:2;6800:51:16;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::2;77:16;74:1;67:27;5:2;-1:-1:::0;;6912:6:16::2;:17:::0;6981:23:::2;::::0;;::::2;::::0;7022;;6901:158;;-1:-1:-1;;;6901:158:16;;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;;;6901:158:16;;::::2;::::0;;;;;;-1:-1:-1;;;6912:17:16;;;::::2;::::0;-1:-1:-1;;;6901:158:16;;;;;::::2;::::0;;;;;;;;;-1:-1:-1;6912:17:16;6901:158;::::2;;5:2:-1::0;::::2;;;30:1;27::::0;20:12:::2;5:2;6901:158:16;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::2;77:16;74:1;67:27;5:2;6901:158:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26::::0;19:12:::2;2:2;-1:-1:::0;6901:158:16;::::2;7126:24:::0;::::2;::::0;6901:158;;-1:-1:-1;7091:59:16;::::2;;7070:129;;;::::0;;-1:-1:-1;;;7070:129:16;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;7296:23:::0;;7333:12;;7270:130:::2;::::0;7296:23;-1:-1:-1;;;;;7333:12:16::2;7359:31:::0;7270:12:::2;:130::i;:::-;7411:26;7440:96;7457:7;:24;;;7495:31;7440:3;:96::i;:::-;7411:125:::0;-1:-1:-1;7609:25:16;;7605:192:::2;;7680:23:::0;;7650:136:::2;::::0;7721:12;7751:21;7650:12:::2;:136::i;:::-;7836:15:::0;;7827:37:::2;::::0;;-1:-1:-1;;;7827:37:16;;;;7807:10:::2;::::0;:58:::2;::::0;-1:-1:-1;;;;;7836:15:16;;::::2;::::0;7827:35:::2;::::0;:37:::2;::::0;;::::2;::::0;::::2;::::0;;;;;;;;;7836:15;7827:37;::::2;;5:2:-1::0;::::2;;;30:1;27::::0;20:12:::2;5:2;7827:37:16;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::2;77:16;74:1;67:27;5:2;7827:37:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26::::0;19:12:::2;2:2;-1:-1:::0;7827:37:16;7807:58:::2;::::0;;::::2;::::0;;::::2;::::0;::::2;::::0;;;7827:37;7807:58;;::::2;;;;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::2;77:16;74:1;67:27;5:2;-1:-1:::0;7883:13:16;;7922:23:::2;::::0;;::::2;::::0;7876:70;;-1:-1:-1;;;7876:70:16;;-1:-1:-1;;;;;7876:70:16;;::::2;7883:13;7876:70:::0;::::2;::::0;;;;;;;;;;7883:13;::::2;::::0;7876:31:::2;::::0;:70;;;;;-1:-1:-1;;7876:70:16;;;;;;;;-1:-1:-1;7883:13:16;7876:70;::::2;;5:2:-1::0;::::2;;;30:1;27::::0;20:12:::2;5:2;7876:70:16;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::2;77:16;74:1;67:27;5:2;-1:-1:::0;;7967:6:16::2;:17:::0;8008:23;;7956:76:::2;::::0;;-1:-1:-1;;;7956:76:16;;-1:-1:-1;;;;;7956:76:16;;::::2;;::::0;::::2;::::0;;;7967:17;;;::::2;::::0;-1:-1:-1;7956:51:16::2;::::0;-1:-1:-1;7956:76:16;;;;;-1:-1:-1;;7956:76:16;;;;;;;-1:-1:-1;7967:17:16;7956:76;::::2;;5:2:-1::0;::::2;;;30:1;27::::0;20:12:::2;5:2;7956:76:16;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::2;77:16;74:1;67:27;5:2;-1:-1:::0;;;;;;;;;8048:25:16;::::2;;::::0;;;:11:::2;:25;::::0;;;;;::::2;;8043:141;;-1:-1:-1::0;;;;;8089:25:16;::::2;;::::0;;;:11:::2;:25;::::0;;;;:32;;-1:-1:-1;;8089:32:16::2;-1:-1:-1::0;8089:32:16;;::::2;::::0;;;8135:19:::2;27:10:-1::0;;23:18;;::::2;45:23:::0;;8135:38:16;;;;::::2;::::0;;-1:-1:-1;;;;;;8135:38:16::2;::::0;;::::2;::::0;;8043:141:::2;8279:23:::0;;8316:24:::2;::::0;;::::2;::::0;8354:23:::2;::::0;;::::2;::::0;8199:188;;;;;;;::::2;::::0;;;;;;-1:-1:-1;;;;;8199:188:16;;::::2;::::0;8255:10:::2;::::0;8199:188;;::::2;::::0;::::2;::::0;;;;;;;;;::::2;-1:-1:-1::0;;;;;;;;8404:22:16;::::2;;::::0;;;:8:::2;:22;::::0;;;;8397:29;;-1:-1:-1;;;;;;8397:29:16::2;::::0;;-1:-1:-1;8397:29:16;::::2;::::0;;;::::2;::::0;::::2;::::0;;;::::2;;::::0;;;1001:9:7::1;986:24;;1021:15;1047:8;:6;:8::i;6201:107:16:-:0;6255:5;942:11:7;956:9;942:23;;6272:29:16::1;6290:10;6272:17;:29::i;:::-;986:12:7::0;1001:9;986:24;;1021:15;1047:8;:6;:8::i;:::-;-1:-1:-1;;;;;1039:30:7;;:32;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1039:32:7;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1039:32:7;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1039:32:7;;-1:-1:-1;1081:16:7;1100:71;1039:32;1141:20;1145:6;1153:7;1141:3;:20::i;1100:71::-;1081:90;;1181:19;1212:10;:8;:10::i;:::-;-1:-1:-1;;;;;1203:32:7;;:34;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1203:34:7;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1203:34:7;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1203:34:7;;-1:-1:-1;1247:13:7;1276;:11;:13::i;:::-;-1:-1:-1;;;;;1263:43:7;;1320:11;1345:10;:8;:10::i;:::-;1263:127;;;-1:-1:-1;;;;;;1263:127:7;;;;;;;;;;;;;;-1:-1:-1;;;;;1263:127:7;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:2:-1;;;;30:1;27;20:12;5:2;1263:127:7;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1263:127:7;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1263:127:7;;-1:-1:-1;1400:20:7;1430:146;;;;1492:10;:8;:10::i;:::-;-1:-1:-1;;;;;1483:30:7;;:32;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1483:32:7;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1483:32:7;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1483:32:7;;-1:-1:-1;1430:146:7;;;-1:-1:-1;1564:1:7;1430:146;1619:30;1623:8;1633:15;1619:3;:30::i;:::-;1606:9;:43;;1585:123;;;;-1:-1:-1;;;1585:123:7;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1726:8;:6;:8::i;:::-;-1:-1:-1;;;;;1718:32:7;;1757:8;1718:50;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1718:50:7;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;1800:10:7;;-1:-1:-1;1800:151:7;;-1:-1:-1;1833:104:7;;-1:-1:-1;1858:24:7;;-1:-1:-1;1862:9:7;1873:8;1858:3;:24::i;1833:104::-;1800:151;;;;;;;;;;;;;;;;;;;;;1779:211;;;;;-1:-1:-1;;;1779:211:7;;;;;;;;;;;;-1:-1:-1;;;1779:211:7;;;;;;;;;;;;;;;2014:10;2005:69;2026:8;2036:20;2040:6;2048:7;2036:3;:20::i;:::-;2005:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;6201:107:16;;;;;;;;:::o;12708:108::-;12779:7;12797:16;:14;:16::i;433:26:0:-;;;-1:-1:-1;;;;;433:26:0;;:::o;160:24:15:-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;160:24:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;9222:143:16:-;9285:13;;9278:43;;;-1:-1:-1;;;9278:43:16;;9310:10;9285:13;9278:43;;;;;-1:-1:-1;;;;;;;9285:13:16;;-1:-1:-1;;9278:43:16;;;;;;;;;;;;;;9285:13;9278:43;;;5:2:-1;;;;30:1;27;20:12;5:2;9278:43:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;9278:43:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;9278:43:16;;-1:-1:-1;9331:27:16;9278:43;9331:14;:27::i;:::-;9222:143;:::o;605:532:15:-;907:33:0;920:10;-1:-1:-1;;;;;;932:7:0;;;907:12;:33::i;:::-;899:66;;;;;-1:-1:-1;;;899:66:0;;;;;;;;;;;;-1:-1:-1;;;899:66:0;;;;;;;;;;;;;;;709:3:15::1;::::0;-1:-1:-1;;;;;709:3:15::1;687:10;:26;679:35;;;::::0;::::1;;733:11;::::0;::::1;;732:12;724:44;;;::::0;;-1:-1:-1;;;724:44:15;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;724:44:15;;;;;;;;;;;;;::::1;;787:285;::::0;;::::1;::::0;::::1;::::0;;-1:-1:-1;;;;;811:10:15;::::1;::::0;::::1;787:285:::0;;;811:10:::1;835::::0;;::::1;;::::0;::::1;787:285:::0;;::::1;::::0;;;859:10;;::::1;;::::0;::::1;787:285:::0;;;;;;;883:10;;::::1;;::::0;::::1;787:285:::0;;;;;;;907:10;;::::1;;::::0;::::1;787:285:::0;;;;;;;931:10;;::::1;;::::0;::::1;787:285:::0;;;;;;;955:10;;::::1;;::::0;::::1;787:285:::0;;;;;;;979:10;;::::1;;::::0;::::1;787:285:::0;;;;;;;1003:10;;::::1;;::::0;::::1;787:285:::0;;;;;;;1027:10;;::::1;;::::0;::::1;787:285:::0;;;;;;;1051:11;;::::1;;::::0;;::::1;787:285:::0;;;;;;;778:6:::1;:294:::0;;-1:-1:-1;;;;;;778:294:15;;::::1;::::0;;::::1;::::0;;915:1:::1;778:294:::0;;;::::1;::::0;;::::1;::::0;;;939:1:::1;778:294:::0;;;::::1;::::0;;::::1;::::0;;;963:1:::1;778:294:::0;;;::::1;::::0;;::::1;::::0;;;987:1:::1;778:294:::0;;;::::1;::::0;;::::1;::::0;;;1011:1:::1;778:294:::0;;;::::1;::::0;;::::1;::::0;;1035:1:::1;778:294:::0;;;::::1;::::0;;::::1;::::0;;1059:2:::1;778:294:::0;;;::::1;::::0;;::::1;::::0;;;;;;;::::1;::::0;;::::1;::::0;;;;;;;::::1;::::0;;::::1;::::0;;;;;;;;::::1;;::::0;;1082:11:::1;:18:::0;;-1:-1:-1;;1082:18:15::1;-1:-1:-1::0;1082:18:15::1;::::0;;1110:20:::1;-1:-1:-1::0;1110:8:15::1;:20::i;397:30:0:-:0;;;-1:-1:-1;;;;;397:30:0;;:::o;12599:104:16:-;12668:7;12686:14;:12;:14::i;2737:113::-;-1:-1:-1;;;;;2815:14:16;2792:4;2815:14;;;:8;:14;;;;;:24;;;:28;;;2737:113::o;2505:226::-;907:33:0;920:10;-1:-1:-1;;;;;;932:7:0;;;907:12;:33::i;:::-;899:66;;;;;-1:-1:-1;;;899:66:0;;;;;;;;;;;;-1:-1:-1;;;899:66:0;;;;;;;;;;;;;;;2589:6:16::1;2584:100;2601:18:::0;;::::1;2584:100;;;2668:5;2640:13;:25;2654:7;;2662:1;2654:10;;;;;;;;::::0;;::::1;::::0;;;::::1;;-1:-1:-1::0;;;;;2654:10:16::1;2640:25:::0;;-1:-1:-1;2640:25:16;::::1;::::0;;;;;;-1:-1:-1;2640:25:16;:33;;-1:-1:-1;;2640:33:16::1;::::0;::::1;;::::0;;;::::1;::::0;;-1:-1:-1;2621:3:16::1;2584:100;;;;2698:26;2716:7;;2698:26;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16:::0;;::::1;74:27:::0;2698:26:16::1;::::0;137:4:-1::1;117:14:::0;;::::1;-1:-1:::0;;113:30:::1;157:16:::0;;::::1;2698:26:16::0;;::::1;::::0;-1:-1:-1;2698:26:16;;-1:-1:-1;;;;2698:26:16::1;2505:226:::0;;:::o;1598:44::-;;;;;;;;;;;;;;;:::o;1689:36::-;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1689:36:16;;-1:-1:-1;1689:36:16;:::o;5230:827::-;5306:24;5317:12;5306:10;:24::i;:::-;5298:57;;;;;-1:-1:-1;;;5298:57:16;;;;;;;;;;;;-1:-1:-1;;;5298:57:16;;;;;;;;;;;;;;;5365:24;5405:13;:11;:13::i;:::-;5365:54;;5429:22;;:::i;:::-;-1:-1:-1;;;;;;5454:22:16;;;;;;;:8;:22;;;;;;;;;5429:47;;;;;;;;;;;;;;-1:-1:-1;5429:47:16;;;;;;;;;;;;;;;;;;;;;;;;5508:50;;-1:-1:-1;;;5508:50:16;;;;;;;;;;;5429:47;;5508:25;;;-1:-1:-1;;5508:50:16;;;;;5454:22;;5508:50;;;;;;:25;:50;;;5:2:-1;;;;30:1;27;20:12;5:2;5508:50:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5508:50:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5508:50:16;5507:51;;:98;;;5574:31;5592:12;5574:17;:31::i;:::-;5507:130;;;-1:-1:-1;5621:3:16;;:16;;;-1:-1:-1;;;;;;5621:16:16;;;;-1:-1:-1;;;;;5621:3:16;;;;:14;;:16;;;;;;;;;;;;;;;:3;:16;;;5:2:-1;;;;30:1;27;20:12;5:2;5621:16:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5621:16:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5621:16:16;5507:130;5486:210;;;;-1:-1:-1;;;5486:210:16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5738:23;;5796:24;;;;;-1:-1:-1;;;;;5837:22:16;;;5706;5837;;;:8;:22;;;;;;5830:29;;-1:-1:-1;;;;;;5830:29:16;;;-1:-1:-1;5830:29:16;;;;;;;;;;;;;;;;;5898:15;;5889:37;;-1:-1:-1;;;5889:37:16;;;;5796:24;;5869:10;;:58;;5898:15;;;;;5889:35;;:37;;;;;5796:24;5889:37;;;;;5898:15;5889:37;;;5:2:-1;;;;30:1;27;20:12;5:2;5889:37:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5889:37:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5889:37:16;5869:58;;;;;;;;;;;;5889:37;5869:58;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5869:58:16;5937:70;5958:15;5976:12;5990:16;5937:12;:70::i;:::-;6023:27;;-1:-1:-1;;;;;6023:27:16;;;;;;;;5230:827;;;;;:::o;877:127:2:-;960:5;;;955:16;;;;947:50;;;;;-1:-1:-1;;;947:50:2;;;;;;;;;;;;-1:-1:-1;;;947:50:2;;;;;;;;;;;;;;;877:127;;;;:::o;1009:140::-;1061:6;1087;;;:30;;-1:-1:-1;;1102:5:2;;;1116:1;1111;1102:5;1111:1;1097:15;;;;;:20;1087:30;1079:63;;;;;-1:-1:-1;;;1079:63:2;;;;;;;;;;;;-1:-1:-1;;;1079:63:2;;;;;;;;;;;;;;746:126;829:5;;;824:16;;;;816:49;;;;;-1:-1:-1;;;816:49:2;;;;;;;;;;;;-1:-1:-1;;;816:49:2;;;;;;;;;;;;;;989:370:0;1059:4;1094;-1:-1:-1;;;;;1079:20:0;;;1075:278;;;-1:-1:-1;1122:4:0;1115:11;;1075:278;1154:5;;-1:-1:-1;;;;;1147:12:0;;;1154:5;;1147:12;1143:210;;;-1:-1:-1;1182:4:0;1175:11;;1143:210;1232:1;1207:9;-1:-1:-1;;;;;1207:9:0;1203:150;;-1:-1:-1;1257:5:0;1250:12;;1203:150;1300:9;;:42;;;-1:-1:-1;;;1300:42:0;;-1:-1:-1;;;;;1300:42:0;;;;;;;1331:4;1300:42;;;;-1:-1:-1;;;;;;1300:42:0;;;;;;;;:9;;;;;-1:-1:-1;;1300:42:0;;;;;;;;;;;;;;:9;:42;;;5:2:-1;;;;30:1;27;20:12;5:2;1300:42:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1300:42:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1300:42:0;;-1:-1:-1;1293:49:0;;1319:90:15;1389:3;;:17;;;-1:-1:-1;;;1389:17:15;;;;1371:7;;-1:-1:-1;;;;;1389:3:15;;-1:-1:-1;;1389:17:15;;;;;;;;;;;;;;:3;:17;;;5:2:-1;;;;30:1;27;20:12;5:2;1389:17:15;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1389:17:15;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1389:17:15;;-1:-1:-1;1319:90:15;:::o;2017:365:16:-;2094:6;2089:247;2110:7;:14;2106:1;:18;2089:247;;;2179:15;;2214:10;;-1:-1:-1;;;;;2179:15:16;;;;2170:43;;2214:10;;2222:1;;2214:10;;;;;;;;;;;;;;;;;2170:55;;;-1:-1:-1;;;;;;2170:55:16;;;;;;;-1:-1:-1;;;;;2170:55:16;;;;;;;;;;;;;2214:10;2170:55;;;;;;;;;5:2:-1;;;;30:1;27;20:12;5:2;2170:55:16;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2170:55:16;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;2170:55:16;2145:134;;;;;-1:-1:-1;;;2145:134:16;;;;;;;;;;;;-1:-1:-1;;;2145:134:16;;;;;;;;;;;;;;;2321:4;2293:13;:25;2307:7;2315:1;2307:10;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2293:25:16;;;;;;;;;;;-1:-1:-1;2293:25:16;:32;;-1:-1:-1;;2293:32:16;;;;;;;;;;-1:-1:-1;2126:3:16;2089:247;;;;2350:25;2367:7;2350:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;2350:25:16;;;;;;;;;;;;;;;;;2017:365;:::o;162:441:4:-;301:29;;;-1:-1:-1;;;301:29:4;;-1:-1:-1;;;;;301:29:4;;;;;;;;;275:23;;301:24;;;;;:29;;;;;;;;;;;;;;:24;:29;;;5:2:-1;;;;30:1;27;20:12;5:2;301:29:4;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;301:29:4;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;301:29:4;340:36;;;-1:-1:-1;;;340:36:4;;-1:-1:-1;;;;;340:36:4;;;;;;;;;;;;;;;301:29;;-1:-1:-1;340:23:4;;;;-1:-1:-1;;340:36:4;;;;;301:29;;340:36;;;;;;;;-1:-1:-1;340:23:4;:36;;;5:2:-1;;;;30:1;27;20:12;5:2;340:36:4;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;340:36:4;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;413:29:4;;;-1:-1:-1;;;413:29:4;;-1:-1:-1;;;;;413:29:4;;;;;;;;;-1:-1:-1;;413:24:4;;;-1:-1:-1;;413:29:4;;;;;340:36;;413:29;;;;;;;:24;:29;;;5:2:-1;;;;30:1;27;20:12;5:2;413:29:4;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;413:29:4;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;413:29:4;;-1:-1:-1;413:29:4;473:31;477:18;497:6;473:3;:31::i;:::-;:54;452:144;;;;-1:-1:-1;;;452:144:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;162:441;;;;;:::o;609:483::-;775:29;;;-1:-1:-1;;;775:29:4;;-1:-1:-1;;;;;775:29:4;;;;;;;;;749:23;;775:24;;;;;:29;;;;;;;;;;;;;;:24;:29;;;5:2:-1;;;;30:1;27;20:12;5:2;775:29:4;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;775:29:4;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;775:29:4;814:47;;;-1:-1:-1;;;814:47:4;;-1:-1:-1;;;;;814:47:4;;;;;;;;;;;;;;;;;;;;;;775:29;;-1:-1:-1;814:27:4;;;;-1:-1:-1;;814:47:4;;;;;775:29;;814:47;;;;;;;;-1:-1:-1;814:27:4;:47;;;5:2:-1;;;;30:1;27;20:12;5:2;814:47:4;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;814:47:4;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;898:29:4;;;-1:-1:-1;;;898:29:4;;-1:-1:-1;;;;;898:29:4;;;;;;;;;-1:-1:-1;;898:24:4;;;-1:-1:-1;;898:29:4;;;;;814:47;;898:29;;;;;;;:24;:29;;;5:2:-1;;;;30:1;27;20:12;5:2;898:29:4;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;898:29:4;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;898:29:4;;-1:-1:-1;898:29:4;958:31;962:18;982:6;958:3;:31::i;:::-;:54;937:148;;;;-1:-1:-1;;;937:148:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;609:483;;;;;;:::o;1502:85:15:-;1569:15;;-1:-1:-1;;;;;1569:15:15;;1502:85::o;1229:::-;1296:15;;-1:-1:-1;;;;;1296:15:15;;1229:85::o;1143:81::-;1208:13;;-1:-1:-1;;;;;1208:13:15;;1143:81::o;483:12567:16:-;;;;;;;;;-1:-1:-1;483:12567:16;;;;;;;;;;;;;;;;;;;;;;;:::o

Swarm Source

ipfs://c8c881c31bf73e6260fa333441b2a86f898fe182daeacbdee21155d2d6683c2d

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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
Loading...
Loading
[ Download: CSV Export  ]
[ 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.