Address Details
contract

0x5C0c304e06De3647e938A2288C3BE20271b53488

Contract Name
Governance
Creator
0x0cc59e–f1502d at 0x9cd22b–72bcff
Balance
0 CELO
Locked CELO Balance
0.00 CELO
Voting CELO Balance
0.00 CELO
Pending Unlocked Gold
0.00 CELO
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
2159433
Contract name:
Governance




Optimization enabled
false
Compiler version
v0.5.8+commit.23d335f2




Verified at
2020-08-11T19:13:53.167214Z

Contract source code

pragma solidity ^0.5.3;


contract Context {
    
    
    constructor () internal { }
    

    function _msgSender() internal view returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view returns (bytes memory) {
        this; 
        return msg.data;
    }
}

contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    
    constructor () internal {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    
    function owner() public view returns (address) {
        return _owner;
    }

    
    modifier onlyOwner() {
        require(isOwner(), "Ownable: caller is not the owner");
        _;
    }

    
    function isOwner() public view returns (bool) {
        return _msgSender() == _owner;
    }

    
    function renounceOwnership() public onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    
    function transferOwnership(address newOwner) public onlyOwner {
        _transferOwnership(newOwner);
    }

    
    function _transferOwnership(address newOwner) internal {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

library Math {
    
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }
}

library SafeMath {
    
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        
        
        
        if (a == 0) {
            return 0;
        }

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

        return c;
    }

    
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        
        require(b > 0, errorMessage);
        uint256 c = a / b;
        

        return c;
    }

    
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

interface IGovernance {
  function isVoting(address) external view returns (bool);
}

library Address {
    
    function isContract(address account) internal view returns (bool) {
        
        
        
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        
        assembly { codehash := extcodehash(account) }
        return (codehash != accountHash && codehash != 0x0);
    }

    
    function toPayable(address account) internal pure returns (address payable) {
        return address(uint160(account));
    }

    
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        
        (bool success, ) = recipient.call.value(amount)("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }
}

library BytesLib {
    function concat(
        bytes memory _preBytes,
        bytes memory _postBytes
    )
        internal
        pure
        returns (bytes memory)
    {
        bytes memory tempBytes;

        assembly {
            
            
            tempBytes := mload(0x40)

            
            
            let length := mload(_preBytes)
            mstore(tempBytes, length)

            
            
            
            let mc := add(tempBytes, 0x20)
            
            
            let end := add(mc, length)

            for {
                
                
                let cc := add(_preBytes, 0x20)
            } lt(mc, end) {
                
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                
                
                mstore(mc, mload(cc))
            }

            
            
            
            length := mload(_postBytes)
            mstore(tempBytes, add(length, mload(tempBytes)))

            
            
            mc := end
            
            
            end := add(mc, length)

            for {
                let cc := add(_postBytes, 0x20)
            } lt(mc, end) {
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                mstore(mc, mload(cc))
            }

            
            
            
            
            
            mstore(0x40, and(
              add(add(end, iszero(add(length, mload(_preBytes)))), 31),
              not(31) 
            ))
        }

        return tempBytes;
    }

    function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
        assembly {
            
            
            
            let fslot := sload(_preBytes_slot)
            
            
            
            
            
            
            
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)
            let newlength := add(slength, mlength)
            
            
            
            switch add(lt(slength, 32), lt(newlength, 32))
            case 2 {
                
                
                
                sstore(
                    _preBytes_slot,
                    
                    
                    add(
                        
                        
                        fslot,
                        add(
                            mul(
                                div(
                                    
                                    mload(add(_postBytes, 0x20)),
                                    
                                    exp(0x100, sub(32, mlength))
                                ),
                                
                                
                                exp(0x100, sub(32, newlength))
                            ),
                            
                            
                            mul(mlength, 2)
                        )
                    )
                )
            }
            case 1 {
                
                
                
                mstore(0x0, _preBytes_slot)
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                
                sstore(_preBytes_slot, add(mul(newlength, 2), 1))

                
                
                
                
                
                
                
                

                let submod := sub(32, slength)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(
                    sc,
                    add(
                        and(
                            fslot,
                            0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
                        ),
                        and(mload(mc), mask)
                    )
                )

                for {
                    mc := add(mc, 0x20)
                    sc := add(sc, 1)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
            default {
                
                mstore(0x0, _preBytes_slot)
                
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                
                sstore(_preBytes_slot, add(mul(newlength, 2), 1))

                
                
                let slengthmod := mod(slength, 32)
                let mlengthmod := mod(mlength, 32)
                let submod := sub(32, slengthmod)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(sc, add(sload(sc), and(mload(mc), mask)))
                
                for { 
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
        }
    }

    function slice(
        bytes memory _bytes,
        uint _start,
        uint _length
    )
        internal
        pure
        returns (bytes memory)
    {
        require(_bytes.length >= (_start + _length));

        bytes memory tempBytes;

        assembly {
            switch iszero(_length)
            case 0 {
                
                
                tempBytes := mload(0x40)

                
                
                
                
                
                
                
                
                let lengthmod := and(_length, 31)

                
                
                
                
                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                let end := add(mc, _length)

                for {
                    
                    
                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
                } lt(mc, end) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    mstore(mc, mload(cc))
                }

                mstore(tempBytes, _length)

                
                
                mstore(0x40, and(add(mc, 31), not(31)))
            }
            
            default {
                tempBytes := mload(0x40)

                mstore(0x40, add(tempBytes, 0x20))
            }
        }

        return tempBytes;
    }

    function toAddress(bytes memory _bytes, uint _start) internal  pure returns (address) {
        require(_bytes.length >= (_start + 20));
        address tempAddress;

        assembly {
            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
        }

        return tempAddress;
    }

    function toUint8(bytes memory _bytes, uint _start) internal  pure returns (uint8) {
        require(_bytes.length >= (_start + 1));
        uint8 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x1), _start))
        }

        return tempUint;
    }

    function toUint16(bytes memory _bytes, uint _start) internal  pure returns (uint16) {
        require(_bytes.length >= (_start + 2));
        uint16 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x2), _start))
        }

        return tempUint;
    }

    function toUint32(bytes memory _bytes, uint _start) internal  pure returns (uint32) {
        require(_bytes.length >= (_start + 4));
        uint32 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x4), _start))
        }

        return tempUint;
    }

    function toUint(bytes memory _bytes, uint _start) internal  pure returns (uint256) {
        require(_bytes.length >= (_start + 32));
        uint256 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x20), _start))
        }

        return tempUint;
    }

    function toBytes32(bytes memory _bytes, uint _start) internal  pure returns (bytes32) {
        require(_bytes.length >= (_start + 32));
        bytes32 tempBytes32;

        assembly {
            tempBytes32 := mload(add(add(_bytes, 0x20), _start))
        }

        return tempBytes32;
    }

    function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
        bool success = true;

        assembly {
            let length := mload(_preBytes)

            
            switch eq(length, mload(_postBytes))
            case 1 {
                
                
                
                
                let cb := 1

                let mc := add(_preBytes, 0x20)
                let end := add(mc, length)

                for {
                    let cc := add(_postBytes, 0x20)
                
                
                } eq(add(lt(mc, end), cb), 2) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    
                    if iszero(eq(mload(mc), mload(cc))) {
                        
                        success := 0
                        cb := 0
                    }
                }
            }
            default {
                
                success := 0
            }
        }

        return success;
    }

    function equalStorage(
        bytes storage _preBytes,
        bytes memory _postBytes
    )
        internal
        view
        returns (bool)
    {
        bool success = true;

        assembly {
            
            let fslot := sload(_preBytes_slot)
            
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)

            
            switch eq(slength, mlength)
            case 1 {
                
                
                
                if iszero(iszero(slength)) {
                    switch lt(slength, 32)
                    case 1 {
                        
                        fslot := mul(div(fslot, 0x100), 0x100)

                        if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
                            
                            success := 0
                        }
                    }
                    default {
                        
                        
                        
                        
                        let cb := 1

                        
                        mstore(0x0, _preBytes_slot)
                        let sc := keccak256(0x0, 0x20)

                        let mc := add(_postBytes, 0x20)
                        let end := add(mc, mlength)

                        
                        
                        for {} eq(add(lt(mc, end), cb), 2) {
                            sc := add(sc, 1)
                            mc := add(mc, 0x20)
                        } {
                            if iszero(eq(sload(sc), mload(mc))) {
                                
                                success := 0
                                cb := 0
                            }
                        }
                    }
                }
            }
            default {
                
                success := 0
            }
        }

        return success;
    }
}

library FixidityLib {
  struct Fraction {
    uint256 value;
  }

  
  function digits() internal pure returns (uint8) {
    return 24;
  }

  uint256 private constant FIXED1_UINT = 1000000000000000000000000;

  
  function fixed1() internal pure returns (Fraction memory) {
    return Fraction(FIXED1_UINT);
  }

  
  function wrap(uint256 x) internal pure returns (Fraction memory) {
    return Fraction(x);
  }

  
  function unwrap(Fraction memory x) internal pure returns (uint256) {
    return x.value;
  }

  
  function mulPrecision() internal pure returns (uint256) {
    return 1000000000000;
  }

  
  function maxNewFixed() internal pure returns (uint256) {
    return 115792089237316195423570985008687907853269984665640564;
  }

  
  function newFixed(uint256 x) internal pure returns (Fraction memory) {
    require(x <= maxNewFixed(), "can't create fixidity number larger than maxNewFixed()");
    return Fraction(x * FIXED1_UINT);
  }

  
  function fromFixed(Fraction memory x) internal pure returns (uint256) {
    return x.value / FIXED1_UINT;
  }

  
  function newFixedFraction(uint256 numerator, uint256 denominator)
    internal
    pure
    returns (Fraction memory)
  {
    Fraction memory convertedNumerator = newFixed(numerator);
    Fraction memory convertedDenominator = newFixed(denominator);
    return divide(convertedNumerator, convertedDenominator);
  }

  
  function integer(Fraction memory x) internal pure returns (Fraction memory) {
    return Fraction((x.value / FIXED1_UINT) * FIXED1_UINT); 
  }

  
  function fractional(Fraction memory x) internal pure returns (Fraction memory) {
    return Fraction(x.value - (x.value / FIXED1_UINT) * FIXED1_UINT); 
  }

  
  function add(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
    uint256 z = x.value + y.value;
    require(z >= x.value, "add overflow detected");
    return Fraction(z);
  }

  
  function subtract(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
    require(x.value >= y.value, "substraction underflow detected");
    return Fraction(x.value - y.value);
  }

  
  function multiply(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
    if (x.value == 0 || y.value == 0) return Fraction(0);
    if (y.value == FIXED1_UINT) return x;
    if (x.value == FIXED1_UINT) return y;

    
    
    uint256 x1 = integer(x).value / FIXED1_UINT;
    uint256 x2 = fractional(x).value;
    uint256 y1 = integer(y).value / FIXED1_UINT;
    uint256 y2 = fractional(y).value;

    
    uint256 x1y1 = x1 * y1;
    if (x1 != 0) require(x1y1 / x1 == y1, "overflow x1y1 detected");

    
    
    uint256 fixed_x1y1 = x1y1 * FIXED1_UINT;
    if (x1y1 != 0) require(fixed_x1y1 / x1y1 == FIXED1_UINT, "overflow x1y1 * fixed1 detected");
    x1y1 = fixed_x1y1;

    uint256 x2y1 = x2 * y1;
    if (x2 != 0) require(x2y1 / x2 == y1, "overflow x2y1 detected");

    uint256 x1y2 = x1 * y2;
    if (x1 != 0) require(x1y2 / x1 == y2, "overflow x1y2 detected");

    x2 = x2 / mulPrecision();
    y2 = y2 / mulPrecision();
    uint256 x2y2 = x2 * y2;
    if (x2 != 0) require(x2y2 / x2 == y2, "overflow x2y2 detected");

    
    Fraction memory result = Fraction(x1y1);
    result = add(result, Fraction(x2y1)); 
    result = add(result, Fraction(x1y2)); 
    result = add(result, Fraction(x2y2)); 
    return result;
  }

  
  function reciprocal(Fraction memory x) internal pure returns (Fraction memory) {
    require(x.value != 0, "can't call reciprocal(0)");
    return Fraction((FIXED1_UINT * FIXED1_UINT) / x.value); 
  }

  
  function divide(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
    require(y.value != 0, "can't divide by 0");
    uint256 X = x.value * FIXED1_UINT;
    require(X / FIXED1_UINT == x.value, "overflow at divide");
    return Fraction(X / y.value);
  }

  
  function gt(Fraction memory x, Fraction memory y) internal pure returns (bool) {
    return x.value > y.value;
  }

  
  function gte(Fraction memory x, Fraction memory y) internal pure returns (bool) {
    return x.value >= y.value;
  }

  
  function lt(Fraction memory x, Fraction memory y) internal pure returns (bool) {
    return x.value < y.value;
  }

  
  function lte(Fraction memory x, Fraction memory y) internal pure returns (bool) {
    return x.value <= y.value;
  }

  
  function equals(Fraction memory x, Fraction memory y) internal pure returns (bool) {
    return x.value == y.value;
  }

  
  function isProperFraction(Fraction memory x) internal pure returns (bool) {
    return lte(x, fixed1());
  }
}

library Proposals {
  using FixidityLib for FixidityLib.Fraction;
  using SafeMath for uint256;
  using BytesLib for bytes;

  enum Stage { None, Queued, Approval, Referendum, Execution, Expiration }

  enum VoteValue { None, Abstain, No, Yes }

  struct StageDurations {
    uint256 approval;
    uint256 referendum;
    uint256 execution;
  }

  
  struct VoteTotals {
    uint256 yes;
    uint256 no;
    uint256 abstain;
  }

  struct Transaction {
    uint256 value;
    address destination;
    bytes data;
  }

  struct Proposal {
    address proposer;
    uint256 deposit;
    uint256 timestamp;
    VoteTotals votes;
    Transaction[] transactions;
    bool approved;
    uint256 networkWeight;
    string descriptionUrl;
  }

  
  function make(
    Proposal storage proposal,
    uint256[] memory values,
    address[] memory destinations,
    bytes memory data,
    uint256[] memory dataLengths,
    address proposer,
    uint256 deposit
  ) public {
    require(
      values.length == destinations.length && destinations.length == dataLengths.length,
      "Array length mismatch"
    );
    uint256 transactionCount = values.length;

    proposal.proposer = proposer;
    proposal.deposit = deposit;
    
    proposal.timestamp = now;

    uint256 dataPosition = 0;
    delete proposal.transactions;
    for (uint256 i = 0; i < transactionCount; i = i.add(1)) {
      proposal.transactions.push(
        Transaction(values[i], destinations[i], data.slice(dataPosition, dataLengths[i]))
      );
      dataPosition = dataPosition.add(dataLengths[i]);
    }
  }

  function setDescriptionUrl(Proposal storage proposal, string memory descriptionUrl) internal {
    require(bytes(descriptionUrl).length != 0, "Description url must have non-zero length");
    proposal.descriptionUrl = descriptionUrl;
  }

  
  function makeMem(
    uint256[] memory values,
    address[] memory destinations,
    bytes memory data,
    uint256[] memory dataLengths,
    address proposer,
    uint256 deposit
  ) internal view returns (Proposal memory) {
    require(
      values.length == destinations.length && destinations.length == dataLengths.length,
      "Array length mismatch"
    );
    uint256 transactionCount = values.length;

    Proposal memory proposal;
    proposal.proposer = proposer;
    proposal.deposit = deposit;
    
    proposal.timestamp = now;

    uint256 dataPosition = 0;
    proposal.transactions = new Transaction[](transactionCount);
    for (uint256 i = 0; i < transactionCount; i = i.add(1)) {
      proposal.transactions[i] = Transaction(
        values[i],
        destinations[i],
        data.slice(dataPosition, dataLengths[i])
      );
      dataPosition = dataPosition.add(dataLengths[i]);
    }
    return proposal;
  }

  
  function updateVote(
    Proposal storage proposal,
    uint256 previousWeight,
    uint256 currentWeight,
    VoteValue previousVote,
    VoteValue currentVote
  ) public {
    
    if (previousVote == VoteValue.Abstain) {
      proposal.votes.abstain = proposal.votes.abstain.sub(previousWeight);
    } else if (previousVote == VoteValue.Yes) {
      proposal.votes.yes = proposal.votes.yes.sub(previousWeight);
    } else if (previousVote == VoteValue.No) {
      proposal.votes.no = proposal.votes.no.sub(previousWeight);
    }

    
    if (currentVote == VoteValue.Abstain) {
      proposal.votes.abstain = proposal.votes.abstain.add(currentWeight);
    } else if (currentVote == VoteValue.Yes) {
      proposal.votes.yes = proposal.votes.yes.add(currentWeight);
    } else if (currentVote == VoteValue.No) {
      proposal.votes.no = proposal.votes.no.add(currentWeight);
    }
  }

  
  function execute(Proposal storage proposal) public {
    executeTransactions(proposal.transactions);
  }

  
  function executeMem(Proposal memory proposal) internal {
    executeTransactions(proposal.transactions);
  }

  function executeTransactions(Transaction[] memory transactions) internal {
    for (uint256 i = 0; i < transactions.length; i = i.add(1)) {
      require(
        externalCall(
          transactions[i].destination,
          transactions[i].value,
          transactions[i].data.length,
          transactions[i].data
        ),
        "Proposal execution failed"
      );
    }
  }

  
  function getSupportWithQuorumPadding(
    Proposal storage proposal,
    FixidityLib.Fraction memory quorum
  ) internal view returns (FixidityLib.Fraction memory) {
    uint256 yesVotes = proposal.votes.yes;
    if (yesVotes == 0) {
      return FixidityLib.newFixed(0);
    }
    uint256 noVotes = proposal.votes.no;
    uint256 totalVotes = yesVotes.add(noVotes).add(proposal.votes.abstain);
    uint256 requiredVotes = quorum
      .multiply(FixidityLib.newFixed(proposal.networkWeight))
      .fromFixed();
    if (requiredVotes > totalVotes) {
      noVotes = noVotes.add(requiredVotes.sub(totalVotes));
    }
    return FixidityLib.newFixedFraction(yesVotes, yesVotes.add(noVotes));
  }

  
  function getDequeuedStage(Proposal storage proposal, StageDurations storage stageDurations)
    internal
    view
    returns (Stage)
  {
    uint256 stageStartTime = proposal
      .timestamp
      .add(stageDurations.approval)
      .add(stageDurations.referendum)
      .add(stageDurations.execution);
    
    if (now >= stageStartTime) {
      return Stage.Expiration;
    }
    stageStartTime = stageStartTime.sub(stageDurations.execution);
    
    if (now >= stageStartTime) {
      return Stage.Execution;
    }
    stageStartTime = stageStartTime.sub(stageDurations.referendum);
    
    if (now >= stageStartTime) {
      return Stage.Referendum;
    }
    return Stage.Approval;
  }

  
  function getParticipation(Proposal storage proposal)
    internal
    view
    returns (FixidityLib.Fraction memory)
  {
    uint256 totalVotes = proposal.votes.yes.add(proposal.votes.no).add(proposal.votes.abstain);
    return FixidityLib.newFixedFraction(totalVotes, proposal.networkWeight);
  }

  
  function getTransaction(Proposal storage proposal, uint256 index)
    public
    view
    returns (uint256, address, bytes memory)
  {
    require(index < proposal.transactions.length, "getTransaction: bad index");
    Transaction storage transaction = proposal.transactions[index];
    return (transaction.value, transaction.destination, transaction.data);
  }

  
  function unpack(Proposal storage proposal)
    internal
    view
    returns (address, uint256, uint256, uint256, string storage)
  {
    return (
      proposal.proposer,
      proposal.deposit,
      proposal.timestamp,
      proposal.transactions.length,
      proposal.descriptionUrl
    );
  }

  
  function getVoteTotals(Proposal storage proposal)
    internal
    view
    returns (uint256, uint256, uint256)
  {
    return (proposal.votes.yes, proposal.votes.no, proposal.votes.abstain);
  }

  
  function isApproved(Proposal storage proposal) internal view returns (bool) {
    return proposal.approved;
  }

  
  function exists(Proposal storage proposal) internal view returns (bool) {
    return proposal.timestamp > 0;
  }

  
  
  
  function externalCall(address destination, uint256 value, uint256 dataLength, bytes memory data)
    private
    returns (bool)
  {
    bool result;

    if (dataLength > 0) require(Address.isContract(destination), "Invalid contract address");

    
    assembly {
      
      let x := mload(0x40) 
      let d := add(data, 32) 
      result := call(
        sub(gas, 34710), 
        
        
        destination,
        value,
        d,
        dataLength, 
        x,
        0 
      )
      
    }
    
    return result;
  }
}

interface IAccounts {
  function isAccount(address) external view returns (bool);
  function voteSignerToAccount(address) external view returns (address);
  function validatorSignerToAccount(address) external view returns (address);
  function attestationSignerToAccount(address) external view returns (address);
  function signerToAccount(address) external view returns (address);
  function getAttestationSigner(address) external view returns (address);
  function getValidatorSigner(address) external view returns (address);
  function getVoteSigner(address) external view returns (address);
  function hasAuthorizedVoteSigner(address) external view returns (bool);
  function hasAuthorizedValidatorSigner(address) external view returns (bool);
  function hasAuthorizedAttestationSigner(address) external view returns (bool);

  function setAccountDataEncryptionKey(bytes calldata) external;
  function setMetadataURL(string calldata) external;
  function setName(string calldata) external;
  function setWalletAddress(address, uint8, bytes32, bytes32) external;
  function setAccount(string calldata, bytes calldata, address, uint8, bytes32, bytes32) external;

  function getDataEncryptionKey(address) external view returns (bytes memory);
  function getWalletAddress(address) external view returns (address);
  function getMetadataURL(address) external view returns (string memory);
  function batchGetMetadataURL(address[] calldata)
    external
    view
    returns (uint256[] memory, bytes memory);
  function getName(address) external view returns (string memory);

  function authorizeVoteSigner(address, uint8, bytes32, bytes32) external;
  function authorizeValidatorSigner(address, uint8, bytes32, bytes32) external;
  function authorizeValidatorSignerWithPublicKey(address, uint8, bytes32, bytes32, bytes calldata)
    external;
  function authorizeValidatorSignerWithKeys(
    address,
    uint8,
    bytes32,
    bytes32,
    bytes calldata,
    bytes calldata,
    bytes calldata
  ) external;
  function authorizeAttestationSigner(address, uint8, bytes32, bytes32) external;
  function createAccount() external returns (bool);
}

library ExtractFunctionSignature {
  
  function extractFunctionSignature(bytes memory input) internal pure returns (bytes4) {
    return (bytes4(input[0]) |
      (bytes4(input[1]) >> 8) |
      (bytes4(input[2]) >> 16) |
      (bytes4(input[3]) >> 24));
  }
}

contract Initializable {
  bool public initialized;

  modifier initializer() {
    require(!initialized, "contract already initialized");
    initialized = true;
    _;
  }
}

library LinkedList {
  using SafeMath for uint256;

  struct Element {
    bytes32 previousKey;
    bytes32 nextKey;
    bool exists;
  }

  struct List {
    bytes32 head;
    bytes32 tail;
    uint256 numElements;
    mapping(bytes32 => Element) elements;
  }

  
  function insert(List storage list, bytes32 key, bytes32 previousKey, bytes32 nextKey) public {
    require(key != bytes32(0), "Key must be defined");
    require(!contains(list, key), "Can't insert an existing element");
    require(
      previousKey != key && nextKey != key,
      "Key cannot be the same as previousKey or nextKey"
    );

    Element storage element = list.elements[key];
    element.exists = true;

    if (list.numElements == 0) {
      list.tail = key;
      list.head = key;
    } else {
      require(
        previousKey != bytes32(0) || nextKey != bytes32(0),
        "Either previousKey or nextKey must be defined"
      );

      element.previousKey = previousKey;
      element.nextKey = nextKey;

      if (previousKey != bytes32(0)) {
        require(
          contains(list, previousKey),
          "If previousKey is defined, it must exist in the list"
        );
        Element storage previousElement = list.elements[previousKey];
        require(previousElement.nextKey == nextKey, "previousKey must be adjacent to nextKey");
        previousElement.nextKey = key;
      } else {
        list.tail = key;
      }

      if (nextKey != bytes32(0)) {
        require(contains(list, nextKey), "If nextKey is defined, it must exist in the list");
        Element storage nextElement = list.elements[nextKey];
        require(nextElement.previousKey == previousKey, "previousKey must be adjacent to nextKey");
        nextElement.previousKey = key;
      } else {
        list.head = key;
      }
    }

    list.numElements = list.numElements.add(1);
  }

  
  function push(List storage list, bytes32 key) public {
    insert(list, key, bytes32(0), list.tail);
  }

  
  function remove(List storage list, bytes32 key) public {
    Element storage element = list.elements[key];
    require(key != bytes32(0) && contains(list, key), "key not in list");
    if (element.previousKey != bytes32(0)) {
      Element storage previousElement = list.elements[element.previousKey];
      previousElement.nextKey = element.nextKey;
    } else {
      list.tail = element.nextKey;
    }

    if (element.nextKey != bytes32(0)) {
      Element storage nextElement = list.elements[element.nextKey];
      nextElement.previousKey = element.previousKey;
    } else {
      list.head = element.previousKey;
    }

    delete list.elements[key];
    list.numElements = list.numElements.sub(1);
  }

  
  function update(List storage list, bytes32 key, bytes32 previousKey, bytes32 nextKey) public {
    require(
      key != bytes32(0) && key != previousKey && key != nextKey && contains(list, key),
      "key on in list"
    );
    remove(list, key);
    insert(list, key, previousKey, nextKey);
  }

  
  function contains(List storage list, bytes32 key) public view returns (bool) {
    return list.elements[key].exists;
  }

  
  function headN(List storage list, uint256 n) public view returns (bytes32[] memory) {
    require(n <= list.numElements, "not enough elements");
    bytes32[] memory keys = new bytes32[](n);
    bytes32 key = list.head;
    for (uint256 i = 0; i < n; i = i.add(1)) {
      keys[i] = key;
      key = list.elements[key].previousKey;
    }
    return keys;
  }

  
  function getKeys(List storage list) public view returns (bytes32[] memory) {
    return headN(list, list.numElements);
  }
}

library SortedLinkedList {
  using SafeMath for uint256;
  using LinkedList for LinkedList.List;

  struct List {
    LinkedList.List list;
    mapping(bytes32 => uint256) values;
  }

  
  function insert(
    List storage list,
    bytes32 key,
    uint256 value,
    bytes32 lesserKey,
    bytes32 greaterKey
  ) public {
    require(
      key != bytes32(0) && key != lesserKey && key != greaterKey && !contains(list, key),
      "invalid key"
    );
    require(
      (lesserKey != bytes32(0) || greaterKey != bytes32(0)) || list.list.numElements == 0,
      "greater and lesser key zero"
    );
    require(contains(list, lesserKey) || lesserKey == bytes32(0), "invalid lesser key");
    require(contains(list, greaterKey) || greaterKey == bytes32(0), "invalid greater key");
    (lesserKey, greaterKey) = getLesserAndGreater(list, value, lesserKey, greaterKey);
    list.list.insert(key, lesserKey, greaterKey);
    list.values[key] = value;
  }

  
  function remove(List storage list, bytes32 key) public {
    list.list.remove(key);
    list.values[key] = 0;
  }

  
  function update(
    List storage list,
    bytes32 key,
    uint256 value,
    bytes32 lesserKey,
    bytes32 greaterKey
  ) public {
    
    
    
    remove(list, key);
    insert(list, key, value, lesserKey, greaterKey);
  }

  
  function push(List storage list, bytes32 key) public {
    insert(list, key, 0, bytes32(0), list.list.tail);
  }

  
  function popN(List storage list, uint256 n) public returns (bytes32[] memory) {
    require(n <= list.list.numElements, "not enough elements");
    bytes32[] memory keys = new bytes32[](n);
    for (uint256 i = 0; i < n; i = i.add(1)) {
      bytes32 key = list.list.head;
      keys[i] = key;
      remove(list, key);
    }
    return keys;
  }

  
  function contains(List storage list, bytes32 key) public view returns (bool) {
    return list.list.contains(key);
  }

  
  function getValue(List storage list, bytes32 key) public view returns (uint256) {
    return list.values[key];
  }

  
  function getElements(List storage list) public view returns (bytes32[] memory, uint256[] memory) {
    bytes32[] memory keys = getKeys(list);
    uint256[] memory values = new uint256[](keys.length);
    for (uint256 i = 0; i < keys.length; i = i.add(1)) {
      values[i] = list.values[keys[i]];
    }
    return (keys, values);
  }

  
  function getKeys(List storage list) public view returns (bytes32[] memory) {
    return list.list.getKeys();
  }

  
  function headN(List storage list, uint256 n) public view returns (bytes32[] memory) {
    return list.list.headN(n);
  }

  
  
  function getLesserAndGreater(
    List storage list,
    uint256 value,
    bytes32 lesserKey,
    bytes32 greaterKey
  ) private view returns (bytes32, bytes32) {
    
    
    
    
    
    if (lesserKey == bytes32(0) && isValueBetween(list, value, lesserKey, list.list.tail)) {
      return (lesserKey, list.list.tail);
    } else if (
      greaterKey == bytes32(0) && isValueBetween(list, value, list.list.head, greaterKey)
    ) {
      return (list.list.head, greaterKey);
    } else if (
      lesserKey != bytes32(0) &&
      isValueBetween(list, value, lesserKey, list.list.elements[lesserKey].nextKey)
    ) {
      return (lesserKey, list.list.elements[lesserKey].nextKey);
    } else if (
      greaterKey != bytes32(0) &&
      isValueBetween(list, value, list.list.elements[greaterKey].previousKey, greaterKey)
    ) {
      return (list.list.elements[greaterKey].previousKey, greaterKey);
    } else {
      require(false, "get lesser and greater failure");
    }
  }

  
  function isValueBetween(List storage list, uint256 value, bytes32 lesserKey, bytes32 greaterKey)
    private
    view
    returns (bool)
  {
    bool isLesser = lesserKey == bytes32(0) || list.values[lesserKey] <= value;
    bool isGreater = greaterKey == bytes32(0) || list.values[greaterKey] >= value;
    return isLesser && isGreater;
  }
}

library IntegerSortedLinkedList {
  using SafeMath for uint256;
  using SortedLinkedList for SortedLinkedList.List;

  
  function insert(
    SortedLinkedList.List storage list,
    uint256 key,
    uint256 value,
    uint256 lesserKey,
    uint256 greaterKey
  ) public {
    list.insert(bytes32(key), value, bytes32(lesserKey), bytes32(greaterKey));
  }

  
  function remove(SortedLinkedList.List storage list, uint256 key) public {
    list.remove(bytes32(key));
  }

  
  function update(
    SortedLinkedList.List storage list,
    uint256 key,
    uint256 value,
    uint256 lesserKey,
    uint256 greaterKey
  ) public {
    list.update(bytes32(key), value, bytes32(lesserKey), bytes32(greaterKey));
  }

  
  function push(SortedLinkedList.List storage list, uint256 key) public {
    list.push(bytes32(key));
  }

  
  function popN(SortedLinkedList.List storage list, uint256 n) public returns (uint256[] memory) {
    bytes32[] memory byteKeys = list.popN(n);
    uint256[] memory keys = new uint256[](byteKeys.length);
    for (uint256 i = 0; i < byteKeys.length; i = i.add(1)) {
      keys[i] = uint256(byteKeys[i]);
    }
    return keys;
  }

  
  function contains(SortedLinkedList.List storage list, uint256 key) public view returns (bool) {
    return list.contains(bytes32(key));
  }

  
  function getValue(SortedLinkedList.List storage list, uint256 key) public view returns (uint256) {
    return list.getValue(bytes32(key));
  }

  
  function getElements(SortedLinkedList.List storage list)
    public
    view
    returns (uint256[] memory, uint256[] memory)
  {
    bytes32[] memory byteKeys = list.getKeys();
    uint256[] memory keys = new uint256[](byteKeys.length);
    uint256[] memory values = new uint256[](byteKeys.length);
    for (uint256 i = 0; i < byteKeys.length; i = i.add(1)) {
      keys[i] = uint256(byteKeys[i]);
      values[i] = list.values[byteKeys[i]];
    }
    return (keys, values);
  }
}

interface IERC20 {
    
    function totalSupply() external view returns (uint256);

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

    
    function transfer(address recipient, uint256 amount) external returns (bool);

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

    
    function approve(address spender, uint256 amount) external returns (bool);

    
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

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

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

interface IFeeCurrencyWhitelist {
  function addToken(address) external;
  function getWhitelist() external view returns (address[] memory);
}

interface IFreezer {
  function isFrozen(address) external view returns (bool);
}

interface IRegistry {
  function setAddressFor(string calldata, address) external;
  function getAddressForOrDie(bytes32) external view returns (address);
  function getAddressFor(bytes32) external view returns (address);
  function isOneOf(bytes32[] calldata, address) external view returns (bool);
}

interface IElection {
  function getTotalVotes() external view returns (uint256);
  function getActiveVotes() external view returns (uint256);
  function getTotalVotesByAccount(address) external view returns (uint256);
  function markGroupIneligible(address) external;
  function markGroupEligible(address, address, address) external;
  function electValidatorSigners() external view returns (address[] memory);
  function vote(address, uint256, address, address) external returns (bool);
  function activate(address) external returns (bool);
  function revokeActive(address, uint256, address, address, uint256) external returns (bool);
  function revokeAllActive(address, address, address, uint256) external returns (bool);
  function revokePending(address, uint256, address, address, uint256) external returns (bool);
  function forceDecrementVotes(
    address,
    uint256,
    address[] calldata,
    address[] calldata,
    uint256[] calldata
  ) external returns (uint256);
}

interface ILockedGold {
  function incrementNonvotingAccountBalance(address, uint256) external;
  function decrementNonvotingAccountBalance(address, uint256) external;
  function getAccountTotalLockedGold(address) external view returns (uint256);
  function getTotalLockedGold() external view returns (uint256);
  function getPendingWithdrawals(address)
    external
    view
    returns (uint256[] memory, uint256[] memory);
  function getTotalPendingWithdrawals(address) external view returns (uint256);
  function lock() external payable;
  function unlock(uint256) external;
  function relock(uint256, uint256) external;
  function withdraw(uint256) external;
  function slash(
    address account,
    uint256 penalty,
    address reporter,
    uint256 reward,
    address[] calldata lessers,
    address[] calldata greaters,
    uint256[] calldata indices
  ) external;
  function isSlasher(address) external view returns (bool);
}

interface IValidators {
  function getAccountLockedGoldRequirement(address) external view returns (uint256);
  function meetsAccountLockedGoldRequirements(address) external view returns (bool);
  function getGroupNumMembers(address) external view returns (uint256);
  function getGroupsNumMembers(address[] calldata) external view returns (uint256[] memory);
  function getNumRegisteredValidators() external view returns (uint256);
  function getTopGroupValidators(address, uint256) external view returns (address[] memory);
  function updateEcdsaPublicKey(address, address, bytes calldata) external returns (bool);
  function updatePublicKeys(address, address, bytes calldata, bytes calldata, bytes calldata)
    external
    returns (bool);
  function isValidator(address) external view returns (bool);
  function isValidatorGroup(address) external view returns (bool);
  function calculateGroupEpochScore(uint256[] calldata uptimes) external view returns (uint256);
  function groupMembershipInEpoch(address account, uint256 epochNumber, uint256 index)
    external
    view
    returns (address);
  function halveSlashingMultiplier(address group) external;
  function forceDeaffiliateIfValidator(address validator) external;
  function getValidatorGroupSlashingMultiplier(address) external view returns (uint256);
  function affiliate(address group) external returns (bool);
}

interface IRandom {
  function revealAndCommit(bytes32, bytes32, address) external;
  function randomnessBlockRetentionWindow() external view returns (uint256);
  function random() external view returns (bytes32);
  function getBlockRandomness(uint256) external view returns (bytes32);
}

interface IAttestations {
  function setAttestationRequestFee(address, uint256) external;
  function request(bytes32, uint256, address) external;
  function selectIssuers(bytes32) external;
  function complete(bytes32, uint8, bytes32, bytes32) external;
  function revoke(bytes32, uint256) external;
  function withdraw(address) external;

  function setAttestationExpiryBlocks(uint256) external;

  function getMaxAttestations() external view returns (uint256);

  function getUnselectedRequest(bytes32, address) external view returns (uint32, uint32, address);
  function getAttestationRequestFee(address) external view returns (uint256);

  function lookupAccountsForIdentifier(bytes32) external view returns (address[] memory);

  function getAttestationStats(bytes32, address) external view returns (uint32, uint32);

  function getAttestationState(bytes32, address, address)
    external
    view
    returns (uint8, uint32, address);
  function getCompletableAttestations(bytes32, address)
    external
    view
    returns (uint32[] memory, address[] memory, uint256[] memory, bytes memory);
}

interface IExchange {
  function exchange(uint256, uint256, bool) external returns (uint256);
  function setUpdateFrequency(uint256) external;
  function getBuyTokenAmount(uint256, bool) external view returns (uint256);
  function getSellTokenAmount(uint256, bool) external view returns (uint256);
  function getBuyAndSellBuckets(bool) external view returns (uint256, uint256);
}

interface IReserve {
  function setTobinTaxStalenessThreshold(uint256) external;
  function addToken(address) external returns (bool);
  function removeToken(address, uint256) external returns (bool);
  function transferGold(address payable, uint256) external returns (bool);
  function transferExchangeGold(address payable, uint256) external returns (bool);
  function getReserveGoldBalance() external view returns (uint256);
  function getUnfrozenReserveGoldBalance() external view returns (uint256);
  function getOrComputeTobinTax() external returns (uint256, uint256);
  function getTokens() external view returns (address[] memory);
  function getReserveRatio() external view returns (uint256);
}

interface ISortedOracles {
  function addOracle(address, address) external;
  function removeOracle(address, address, uint256) external;
  function report(address, uint256, address, address) external;
  function removeExpiredReports(address, uint256) external;
  function isOldestReportExpired(address token) external view returns (bool, address);
  function numRates(address) external view returns (uint256);
  function medianRate(address) external view returns (uint256, uint256);
  function numTimestamps(address) external view returns (uint256);
  function medianTimestamp(address) external view returns (uint256);
}

interface IStableToken {
  function mint(address, uint256) external returns (bool);
  function burn(uint256) external returns (bool);
  function setInflationParameters(uint256, uint256) external;
  function valueToUnits(uint256) external view returns (uint256);
  function unitsToValue(uint256) external view returns (uint256);
  function getInflationParameters() external view returns (uint256, uint256, uint256, uint256);

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

contract UsingRegistry is Ownable {
  event RegistrySet(address indexed registryAddress);

  
  bytes32 constant ACCOUNTS_REGISTRY_ID = keccak256(abi.encodePacked("Accounts"));
  bytes32 constant ATTESTATIONS_REGISTRY_ID = keccak256(abi.encodePacked("Attestations"));
  bytes32 constant DOWNTIME_SLASHER_REGISTRY_ID = keccak256(abi.encodePacked("DowntimeSlasher"));
  bytes32 constant DOUBLE_SIGNING_SLASHER_REGISTRY_ID = keccak256(
    abi.encodePacked("DoubleSigningSlasher")
  );
  bytes32 constant ELECTION_REGISTRY_ID = keccak256(abi.encodePacked("Election"));
  bytes32 constant EXCHANGE_REGISTRY_ID = keccak256(abi.encodePacked("Exchange"));
  bytes32 constant FEE_CURRENCY_WHITELIST_REGISTRY_ID = keccak256(
    abi.encodePacked("FeeCurrencyWhitelist")
  );
  bytes32 constant FREEZER_REGISTRY_ID = keccak256(abi.encodePacked("Freezer"));
  bytes32 constant GOLD_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("GoldToken"));
  bytes32 constant GOVERNANCE_REGISTRY_ID = keccak256(abi.encodePacked("Governance"));
  bytes32 constant GOVERNANCE_SLASHER_REGISTRY_ID = keccak256(
    abi.encodePacked("GovernanceSlasher")
  );
  bytes32 constant LOCKED_GOLD_REGISTRY_ID = keccak256(abi.encodePacked("LockedGold"));
  bytes32 constant RESERVE_REGISTRY_ID = keccak256(abi.encodePacked("Reserve"));
  bytes32 constant RANDOM_REGISTRY_ID = keccak256(abi.encodePacked("Random"));
  bytes32 constant SORTED_ORACLES_REGISTRY_ID = keccak256(abi.encodePacked("SortedOracles"));
  bytes32 constant STABLE_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("StableToken"));
  bytes32 constant VALIDATORS_REGISTRY_ID = keccak256(abi.encodePacked("Validators"));
  

  IRegistry public registry;

  modifier onlyRegisteredContract(bytes32 identifierHash) {
    require(registry.getAddressForOrDie(identifierHash) == msg.sender, "only registered contract");
    _;
  }

  modifier onlyRegisteredContracts(bytes32[] memory identifierHashes) {
    require(registry.isOneOf(identifierHashes, msg.sender), "only registered contracts");
    _;
  }

  
  function setRegistry(address registryAddress) public onlyOwner {
    require(registryAddress != address(0), "Cannot register the null address");
    registry = IRegistry(registryAddress);
    emit RegistrySet(registryAddress);
  }

  function getAccounts() internal view returns (IAccounts) {
    return IAccounts(registry.getAddressForOrDie(ACCOUNTS_REGISTRY_ID));
  }

  function getAttestations() internal view returns (IAttestations) {
    return IAttestations(registry.getAddressForOrDie(ATTESTATIONS_REGISTRY_ID));
  }

  function getElection() internal view returns (IElection) {
    return IElection(registry.getAddressForOrDie(ELECTION_REGISTRY_ID));
  }

  function getExchange() internal view returns (IExchange) {
    return IExchange(registry.getAddressForOrDie(EXCHANGE_REGISTRY_ID));
  }

  function getFeeCurrencyWhitelistRegistry() internal view returns (IFeeCurrencyWhitelist) {
    return IFeeCurrencyWhitelist(registry.getAddressForOrDie(FEE_CURRENCY_WHITELIST_REGISTRY_ID));
  }

  function getFreezer() internal view returns (IFreezer) {
    return IFreezer(registry.getAddressForOrDie(FREEZER_REGISTRY_ID));
  }

  function getGoldToken() internal view returns (IERC20) {
    return IERC20(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID));
  }

  function getGovernance() internal view returns (IGovernance) {
    return IGovernance(registry.getAddressForOrDie(GOVERNANCE_REGISTRY_ID));
  }

  function getLockedGold() internal view returns (ILockedGold) {
    return ILockedGold(registry.getAddressForOrDie(LOCKED_GOLD_REGISTRY_ID));
  }

  function getRandom() internal view returns (IRandom) {
    return IRandom(registry.getAddressForOrDie(RANDOM_REGISTRY_ID));
  }

  function getReserve() internal view returns (IReserve) {
    return IReserve(registry.getAddressForOrDie(RESERVE_REGISTRY_ID));
  }

  function getSortedOracles() internal view returns (ISortedOracles) {
    return ISortedOracles(registry.getAddressForOrDie(SORTED_ORACLES_REGISTRY_ID));
  }

  function getStableToken() internal view returns (IStableToken) {
    return IStableToken(registry.getAddressForOrDie(STABLE_TOKEN_REGISTRY_ID));
  }

  function getValidators() internal view returns (IValidators) {
    return IValidators(registry.getAddressForOrDie(VALIDATORS_REGISTRY_ID));
  }
}

contract UsingPrecompiles {
  using SafeMath for uint256;

  address constant TRANSFER = address(0xff - 2);
  address constant FRACTION_MUL = address(0xff - 3);
  address constant PROOF_OF_POSSESSION = address(0xff - 4);
  address constant GET_VALIDATOR = address(0xff - 5);
  address constant NUMBER_VALIDATORS = address(0xff - 6);
  address constant EPOCH_SIZE = address(0xff - 7);
  address constant BLOCK_NUMBER_FROM_HEADER = address(0xff - 8);
  address constant HASH_HEADER = address(0xff - 9);
  address constant GET_PARENT_SEAL_BITMAP = address(0xff - 10);
  address constant GET_VERIFIED_SEAL_BITMAP = address(0xff - 11);

  
  function fractionMulExp(
    uint256 aNumerator,
    uint256 aDenominator,
    uint256 bNumerator,
    uint256 bDenominator,
    uint256 exponent,
    uint256 _decimals
  ) public view returns (uint256, uint256) {
    require(aDenominator != 0 && bDenominator != 0, "a denominator is zero");
    uint256 returnNumerator;
    uint256 returnDenominator;
    bool success;
    bytes memory out;
    (success, out) = FRACTION_MUL.staticcall(
      abi.encodePacked(aNumerator, aDenominator, bNumerator, bDenominator, exponent, _decimals)
    );
    require(success, "error calling fractionMulExp precompile");
    returnNumerator = getUint256FromBytes(out, 0);
    returnDenominator = getUint256FromBytes(out, 32);
    return (returnNumerator, returnDenominator);
  }

  
  function getEpochSize() public view returns (uint256) {
    bytes memory out;
    bool success;
    (success, out) = EPOCH_SIZE.staticcall(abi.encodePacked());
    require(success, "error calling getEpochSize precompile");
    return getUint256FromBytes(out, 0);
  }

  
  function getEpochNumberOfBlock(uint256 blockNumber) public view returns (uint256) {
    return epochNumberOfBlock(blockNumber, getEpochSize());
  }

  
  function getEpochNumber() public view returns (uint256) {
    return getEpochNumberOfBlock(block.number);
  }

  
  function epochNumberOfBlock(uint256 blockNumber, uint256 epochSize)
    internal
    pure
    returns (uint256)
  {
    
    uint256 epochNumber = blockNumber / epochSize;
    if (blockNumber % epochSize == 0) {
      return epochNumber;
    } else {
      return epochNumber + 1;
    }
  }

  
  function validatorSignerAddressFromCurrentSet(uint256 index) public view returns (address) {
    bytes memory out;
    bool success;
    (success, out) = GET_VALIDATOR.staticcall(abi.encodePacked(index, uint256(block.number)));
    require(success, "error calling validatorSignerAddressFromCurrentSet precompile");
    return address(getUint256FromBytes(out, 0));
  }

  
  function validatorSignerAddressFromSet(uint256 index, uint256 blockNumber)
    public
    view
    returns (address)
  {
    bytes memory out;
    bool success;
    (success, out) = GET_VALIDATOR.staticcall(abi.encodePacked(index, blockNumber));
    require(success, "error calling validatorSignerAddressFromSet precompile");
    return address(getUint256FromBytes(out, 0));
  }

  
  function numberValidatorsInCurrentSet() public view returns (uint256) {
    bytes memory out;
    bool success;
    (success, out) = NUMBER_VALIDATORS.staticcall(abi.encodePacked(uint256(block.number)));
    require(success, "error calling numberValidatorsInCurrentSet precompile");
    return getUint256FromBytes(out, 0);
  }

  
  function numberValidatorsInSet(uint256 blockNumber) public view returns (uint256) {
    bytes memory out;
    bool success;
    (success, out) = NUMBER_VALIDATORS.staticcall(abi.encodePacked(blockNumber));
    require(success, "error calling numberValidatorsInSet precompile");
    return getUint256FromBytes(out, 0);
  }

  
  function checkProofOfPossession(address sender, bytes memory blsKey, bytes memory blsPop)
    public
    view
    returns (bool)
  {
    bool success;
    (success, ) = PROOF_OF_POSSESSION.staticcall(abi.encodePacked(sender, blsKey, blsPop));
    return success;
  }

  
  function getBlockNumberFromHeader(bytes memory header) public view returns (uint256) {
    bytes memory out;
    bool success;
    (success, out) = BLOCK_NUMBER_FROM_HEADER.staticcall(abi.encodePacked(header));
    require(success, "error calling getBlockNumberFromHeader precompile");
    return getUint256FromBytes(out, 0);
  }

  
  function hashHeader(bytes memory header) public view returns (bytes32) {
    bytes memory out;
    bool success;
    (success, out) = HASH_HEADER.staticcall(abi.encodePacked(header));
    require(success, "error calling hashHeader precompile");
    return getBytes32FromBytes(out, 0);
  }

  
  function getParentSealBitmap(uint256 blockNumber) public view returns (bytes32) {
    bytes memory out;
    bool success;
    (success, out) = GET_PARENT_SEAL_BITMAP.staticcall(abi.encodePacked(blockNumber));
    require(success, "error calling getParentSealBitmap precompile");
    return getBytes32FromBytes(out, 0);
  }

  
  function getVerifiedSealBitmapFromHeader(bytes memory header) public view returns (bytes32) {
    bytes memory out;
    bool success;
    (success, out) = GET_VERIFIED_SEAL_BITMAP.staticcall(abi.encodePacked(header));
    require(success, "error calling getVerifiedSealBitmapFromHeader precompile");
    return getBytes32FromBytes(out, 0);
  }

  
  function getUint256FromBytes(bytes memory bs, uint256 start) internal pure returns (uint256) {
    return uint256(getBytes32FromBytes(bs, start));
  }

  
  function getBytes32FromBytes(bytes memory bs, uint256 start) internal pure returns (bytes32) {
    require(bs.length >= start + 32, "slicing out of range");
    bytes32 x;
    assembly {
      x := mload(add(bs, add(start, 32)))
    }
    return x;
  }

  
  function minQuorumSize(uint256 blockNumber) public view returns (uint256) {
    return numberValidatorsInSet(blockNumber).mul(2).add(2).div(3);
  }

  
  function minQuorumSizeInCurrentSet() public view returns (uint256) {
    return minQuorumSize(block.number);
  }

}

contract ReentrancyGuard {
  
  uint256 private _guardCounter;

  constructor() internal {
    
    
    _guardCounter = 1;
  }

  
  modifier nonReentrant() {
    _guardCounter += 1;
    uint256 localCounter = _guardCounter;
    _;
    require(localCounter == _guardCounter, "reentrant call");
  }
}

contract Governance is
  IGovernance,
  Ownable,
  Initializable,
  ReentrancyGuard,
  UsingRegistry,
  UsingPrecompiles
{
  using Proposals for Proposals.Proposal;
  using FixidityLib for FixidityLib.Fraction;
  using SafeMath for uint256;
  using IntegerSortedLinkedList for SortedLinkedList.List;
  using BytesLib for bytes;

  uint256 private constant FIXED_HALF = 500000000000000000000000;

  enum VoteValue { None, Abstain, No, Yes }

  struct UpvoteRecord {
    uint256 proposalId;
    uint256 weight;
  }

  struct VoteRecord {
    Proposals.VoteValue value;
    uint256 proposalId;
    uint256 weight;
  }

  struct Voter {
    
    UpvoteRecord upvote;
    uint256 mostRecentReferendumProposal;
    
    mapping(uint256 => VoteRecord) referendumVotes;
  }

  struct ContractConstitution {
    FixidityLib.Fraction defaultThreshold;
    
    mapping(bytes4 => FixidityLib.Fraction) functionThresholds;
  }

  struct HotfixRecord {
    bool executed;
    bool approved;
    uint256 preparedEpoch;
    mapping(address => bool) whitelisted;
  }

  
  
  struct ParticipationParameters {
    
    FixidityLib.Fraction baseline;
    
    FixidityLib.Fraction baselineFloor;
    
    FixidityLib.Fraction baselineUpdateFactor;
    
    FixidityLib.Fraction baselineQuorumFactor;
  }

  Proposals.StageDurations public stageDurations;
  uint256 public queueExpiry;
  uint256 public dequeueFrequency;
  address public approver;
  uint256 public lastDequeue;
  uint256 public concurrentProposals;
  uint256 public proposalCount;
  uint256 public minDeposit;
  mapping(address => uint256) public refundedDeposits;
  mapping(address => ContractConstitution) private constitution;
  mapping(uint256 => Proposals.Proposal) private proposals;
  mapping(address => Voter) private voters;
  mapping(bytes32 => HotfixRecord) public hotfixes;
  SortedLinkedList.List private queue;
  uint256[] public dequeued;
  uint256[] public emptyIndices;
  ParticipationParameters private participationParameters;

  event ApproverSet(address indexed approver);

  event ConcurrentProposalsSet(uint256 concurrentProposals);

  event MinDepositSet(uint256 minDeposit);

  event QueueExpirySet(uint256 queueExpiry);

  event DequeueFrequencySet(uint256 dequeueFrequency);

  event ApprovalStageDurationSet(uint256 approvalStageDuration);

  event ReferendumStageDurationSet(uint256 referendumStageDuration);

  event ExecutionStageDurationSet(uint256 executionStageDuration);

  event ConstitutionSet(address indexed destination, bytes4 indexed functionId, uint256 threshold);

  event ProposalQueued(
    uint256 indexed proposalId,
    address indexed proposer,
    uint256 transactionCount,
    uint256 deposit,
    uint256 timestamp
  );

  event ProposalUpvoted(uint256 indexed proposalId, address indexed account, uint256 upvotes);

  event ProposalUpvoteRevoked(
    uint256 indexed proposalId,
    address indexed account,
    uint256 revokedUpvotes
  );

  event ProposalDequeued(uint256 indexed proposalId, uint256 timestamp);

  event ProposalApproved(uint256 indexed proposalId);

  event ProposalVoted(
    uint256 indexed proposalId,
    address indexed account,
    uint256 value,
    uint256 weight
  );

  event ProposalExecuted(uint256 indexed proposalId);

  event ProposalExpired(uint256 indexed proposalId);

  event ParticipationBaselineUpdated(uint256 participationBaseline);

  event ParticipationFloorSet(uint256 participationFloor);

  event ParticipationBaselineUpdateFactorSet(uint256 baselineUpdateFactor);

  event ParticipationBaselineQuorumFactorSet(uint256 baselineQuorumFactor);

  event HotfixWhitelisted(bytes32 indexed hash, address whitelister);

  event HotfixApproved(bytes32 indexed hash);

  event HotfixPrepared(bytes32 indexed hash, uint256 indexed epoch);

  event HotfixExecuted(bytes32 indexed hash);

  modifier hotfixNotExecuted(bytes32 hash) {
    require(!hotfixes[hash].executed, "hotfix already executed");
    _;
  }

  modifier onlyApprover() {
    require(msg.sender == approver, "msg.sender not approver");
    _;
  }

  function() external payable {
    require(msg.data.length == 0, "unknown method");
  }

  
  function initialize(
    address registryAddress,
    address _approver,
    uint256 _concurrentProposals,
    uint256 _minDeposit,
    uint256 _queueExpiry,
    uint256 _dequeueFrequency,
    uint256 approvalStageDuration,
    uint256 referendumStageDuration,
    uint256 executionStageDuration,
    uint256 participationBaseline,
    uint256 participationFloor,
    uint256 baselineUpdateFactor,
    uint256 baselineQuorumFactor
  ) external initializer {
    _transferOwnership(msg.sender);
    setRegistry(registryAddress);
    setApprover(_approver);
    setConcurrentProposals(_concurrentProposals);
    setMinDeposit(_minDeposit);
    setQueueExpiry(_queueExpiry);
    setDequeueFrequency(_dequeueFrequency);
    setApprovalStageDuration(approvalStageDuration);
    setReferendumStageDuration(referendumStageDuration);
    setExecutionStageDuration(executionStageDuration);
    setParticipationBaseline(participationBaseline);
    setParticipationFloor(participationFloor);
    setBaselineUpdateFactor(baselineUpdateFactor);
    setBaselineQuorumFactor(baselineQuorumFactor);
    
    lastDequeue = now;
  }

  
  function setApprover(address _approver) public onlyOwner {
    require(_approver != address(0), "Approver cannot be 0");
    require(_approver != approver, "Approver unchanged");
    approver = _approver;
    emit ApproverSet(_approver);
  }

  
  function setConcurrentProposals(uint256 _concurrentProposals) public onlyOwner {
    require(_concurrentProposals > 0, "Number of proposals must be larger than zero");
    require(_concurrentProposals != concurrentProposals, "Number of proposals unchanged");
    concurrentProposals = _concurrentProposals;
    emit ConcurrentProposalsSet(_concurrentProposals);
  }

  
  function setMinDeposit(uint256 _minDeposit) public onlyOwner {
    require(_minDeposit > 0, "minDeposit must be larger than 0");
    require(_minDeposit != minDeposit, "Minimum deposit unchanged");
    minDeposit = _minDeposit;
    emit MinDepositSet(_minDeposit);
  }

  
  function setQueueExpiry(uint256 _queueExpiry) public onlyOwner {
    require(_queueExpiry > 0, "QueueExpiry must be larger than 0");
    require(_queueExpiry != queueExpiry, "QueueExpiry unchanged");
    queueExpiry = _queueExpiry;
    emit QueueExpirySet(_queueExpiry);
  }

  
  function setDequeueFrequency(uint256 _dequeueFrequency) public onlyOwner {
    require(_dequeueFrequency > 0, "dequeueFrequency must be larger than 0");
    require(_dequeueFrequency != dequeueFrequency, "dequeueFrequency unchanged");
    dequeueFrequency = _dequeueFrequency;
    emit DequeueFrequencySet(_dequeueFrequency);
  }

  
  function setApprovalStageDuration(uint256 approvalStageDuration) public onlyOwner {
    require(approvalStageDuration > 0, "Duration must be larger than 0");
    require(approvalStageDuration != stageDurations.approval, "Duration unchanged");
    stageDurations.approval = approvalStageDuration;
    emit ApprovalStageDurationSet(approvalStageDuration);
  }

  
  function setReferendumStageDuration(uint256 referendumStageDuration) public onlyOwner {
    require(referendumStageDuration > 0, "Duration must be larger than 0");
    require(referendumStageDuration != stageDurations.referendum, "Duration unchanged");
    stageDurations.referendum = referendumStageDuration;
    emit ReferendumStageDurationSet(referendumStageDuration);
  }

  
  function setExecutionStageDuration(uint256 executionStageDuration) public onlyOwner {
    require(executionStageDuration > 0, "Duration must be larger than 0");
    require(executionStageDuration != stageDurations.execution, "Duration unchanged");
    stageDurations.execution = executionStageDuration;
    emit ExecutionStageDurationSet(executionStageDuration);
  }

  
  function setParticipationBaseline(uint256 participationBaseline) public onlyOwner {
    FixidityLib.Fraction memory participationBaselineFrac = FixidityLib.wrap(participationBaseline);
    require(
      FixidityLib.isProperFraction(participationBaselineFrac),
      "Participation baseline greater than one"
    );
    require(
      !participationBaselineFrac.equals(participationParameters.baseline),
      "Participation baseline unchanged"
    );
    participationParameters.baseline = participationBaselineFrac;
    emit ParticipationBaselineUpdated(participationBaseline);
  }

  
  function setParticipationFloor(uint256 participationFloor) public onlyOwner {
    FixidityLib.Fraction memory participationFloorFrac = FixidityLib.wrap(participationFloor);
    require(
      FixidityLib.isProperFraction(participationFloorFrac),
      "Participation floor greater than one"
    );
    require(
      !participationFloorFrac.equals(participationParameters.baselineFloor),
      "Participation baseline floor unchanged"
    );
    participationParameters.baselineFloor = participationFloorFrac;
    emit ParticipationFloorSet(participationFloor);
  }

  
  function setBaselineUpdateFactor(uint256 baselineUpdateFactor) public onlyOwner {
    FixidityLib.Fraction memory baselineUpdateFactorFrac = FixidityLib.wrap(baselineUpdateFactor);
    require(
      FixidityLib.isProperFraction(baselineUpdateFactorFrac),
      "Baseline update factor greater than one"
    );
    require(
      !baselineUpdateFactorFrac.equals(participationParameters.baselineUpdateFactor),
      "Baseline update factor unchanged"
    );
    participationParameters.baselineUpdateFactor = baselineUpdateFactorFrac;
    emit ParticipationBaselineUpdateFactorSet(baselineUpdateFactor);
  }

  
  function setBaselineQuorumFactor(uint256 baselineQuorumFactor) public onlyOwner {
    FixidityLib.Fraction memory baselineQuorumFactorFrac = FixidityLib.wrap(baselineQuorumFactor);
    require(
      FixidityLib.isProperFraction(baselineQuorumFactorFrac),
      "Baseline quorum factor greater than one"
    );
    require(
      !baselineQuorumFactorFrac.equals(participationParameters.baselineQuorumFactor),
      "Baseline quorum factor unchanged"
    );
    participationParameters.baselineQuorumFactor = baselineQuorumFactorFrac;
    emit ParticipationBaselineQuorumFactorSet(baselineQuorumFactor);
  }

  
  function setConstitution(address destination, bytes4 functionId, uint256 threshold)
    external
    onlyOwner
  {
    require(destination != address(0), "Destination cannot be zero");
    require(
      threshold > FIXED_HALF && threshold <= FixidityLib.fixed1().unwrap(),
      "Threshold has to be greater than majority and not greater than unanimity"
    );
    if (functionId == 0) {
      constitution[destination].defaultThreshold = FixidityLib.wrap(threshold);
    } else {
      constitution[destination].functionThresholds[functionId] = FixidityLib.wrap(threshold);
    }
    emit ConstitutionSet(destination, functionId, threshold);
  }

  
  function propose(
    uint256[] calldata values,
    address[] calldata destinations,
    bytes calldata data,
    uint256[] calldata dataLengths,
    string calldata descriptionUrl
  ) external payable returns (uint256) {
    dequeueProposalsIfReady();
    require(msg.value >= minDeposit, "Too small deposit");

    proposalCount = proposalCount.add(1);
    Proposals.Proposal storage proposal = proposals[proposalCount];
    proposal.make(values, destinations, data, dataLengths, msg.sender, msg.value);
    proposal.setDescriptionUrl(descriptionUrl);
    queue.push(proposalCount);
    
    emit ProposalQueued(proposalCount, msg.sender, proposal.transactions.length, msg.value, now);
    return proposalCount;
  }

  
  function removeIfQueuedAndExpired(uint256 proposalId) private returns (bool) {
    bool expired = queue.contains(proposalId) && isQueuedProposalExpired(proposalId);
    if (expired) {
      queue.remove(proposalId);
      emit ProposalExpired(proposalId);
    }
    return expired;
  }

  
  function requireDequeuedAndDeleteExpired(uint256 proposalId, uint256 index)
    private
    returns (Proposals.Proposal storage, Proposals.Stage)
  {
    Proposals.Proposal storage proposal = proposals[proposalId];
    require(_isDequeuedProposal(proposal, proposalId, index), "Proposal not dequeued");
    Proposals.Stage stage = proposal.getDequeuedStage(stageDurations);
    if (_isDequeuedProposalExpired(proposal, stage)) {
      deleteDequeuedProposal(proposal, proposalId, index);
    }
    return (proposal, stage);
  }

  
  function upvote(uint256 proposalId, uint256 lesser, uint256 greater)
    external
    nonReentrant
    returns (bool)
  {
    
    
    dequeueProposalsIfReady();
    
    if (removeIfQueuedAndExpired(proposalId)) {
      return false;
    }

    address account = getAccounts().voteSignerToAccount(msg.sender);
    Voter storage voter = voters[account];
    removeIfQueuedAndExpired(voter.upvote.proposalId);

    
    uint256 weight = getLockedGold().getAccountTotalLockedGold(account);
    require(weight > 0, "cannot upvote without locking gold");
    require(queue.contains(proposalId), "cannot upvote a proposal not in the queue");
    require(
      voter.upvote.proposalId == 0 || !queue.contains(voter.upvote.proposalId),
      "cannot upvote more than one queued proposal"
    );
    uint256 upvotes = queue.getValue(proposalId).add(weight);
    queue.update(proposalId, upvotes, lesser, greater);
    voter.upvote = UpvoteRecord(proposalId, weight);
    emit ProposalUpvoted(proposalId, account, weight);
    return true;
  }

  
  function getProposalStage(uint256 proposalId) external view returns (Proposals.Stage) {
    if (proposalId == 0 || proposalId > proposalCount) {
      return Proposals.Stage.None;
    } else if (isQueued(proposalId)) {
      return Proposals.Stage.Queued;
    } else {
      return proposals[proposalId].getDequeuedStage(stageDurations);
    }
  }

  
  function revokeUpvote(uint256 lesser, uint256 greater) external nonReentrant returns (bool) {
    dequeueProposalsIfReady();
    address account = getAccounts().voteSignerToAccount(msg.sender);
    Voter storage voter = voters[account];
    uint256 proposalId = voter.upvote.proposalId;
    
    require(proposalId != 0, "Account has no historical upvote");
    removeIfQueuedAndExpired(proposalId);
    if (queue.contains(proposalId)) {
      queue.update(
        proposalId,
        queue.getValue(proposalId).sub(voter.upvote.weight),
        lesser,
        greater
      );
      emit ProposalUpvoteRevoked(proposalId, account, voter.upvote.weight);
    }
    voter.upvote = UpvoteRecord(0, 0);
    return true;
  }

  
  
  
  function approve(uint256 proposalId, uint256 index) external onlyApprover returns (bool) {
    dequeueProposalsIfReady();
    (Proposals.Proposal storage proposal, Proposals.Stage stage) = requireDequeuedAndDeleteExpired(
      proposalId,
      index
    );
    if (!proposal.exists()) {
      return false;
    }

    require(!proposal.isApproved(), "Proposal already approved");
    require(stage == Proposals.Stage.Approval, "Proposal not in approval stage");
    proposal.approved = true;
    
    proposal.networkWeight = getLockedGold().getTotalLockedGold();
    emit ProposalApproved(proposalId);
    return true;
  }

  
  
  function vote(uint256 proposalId, uint256 index, Proposals.VoteValue value)
    external
    nonReentrant
    returns (bool)
  {
    dequeueProposalsIfReady();
    (Proposals.Proposal storage proposal, Proposals.Stage stage) = requireDequeuedAndDeleteExpired(
      proposalId,
      index
    );
    if (!proposal.exists()) {
      return false;
    }

    address account = getAccounts().voteSignerToAccount(msg.sender);
    Voter storage voter = voters[account];
    uint256 weight = getLockedGold().getAccountTotalLockedGold(account);
    require(proposal.isApproved(), "Proposal not approved");
    require(stage == Proposals.Stage.Referendum, "Incorrect proposal state");
    require(value != Proposals.VoteValue.None, "Vote value unset");
    require(weight > 0, "Voter weight zero");
    VoteRecord storage voteRecord = voter.referendumVotes[index];
    proposal.updateVote(
      voteRecord.weight,
      weight,
      (voteRecord.proposalId == proposalId) ? voteRecord.value : Proposals.VoteValue.None,
      value
    );
    proposal.networkWeight = getLockedGold().getTotalLockedGold();
    voter.referendumVotes[index] = VoteRecord(value, proposalId, weight);
    if (proposal.timestamp > voter.mostRecentReferendumProposal) {
      voter.mostRecentReferendumProposal = proposalId;
    }
    emit ProposalVoted(proposalId, account, uint256(value), weight);
    return true;
  }
  

  
  function execute(uint256 proposalId, uint256 index) external nonReentrant returns (bool) {
    dequeueProposalsIfReady();
    (Proposals.Proposal storage proposal, Proposals.Stage stage) = requireDequeuedAndDeleteExpired(
      proposalId,
      index
    );
    bool notExpired = proposal.exists();
    if (notExpired) {
      require(
        stage == Proposals.Stage.Execution && _isProposalPassing(proposal),
        "Proposal not in execution stage or not passing"
      );
      proposal.execute();
      emit ProposalExecuted(proposalId);
      deleteDequeuedProposal(proposal, proposalId, index);
    }
    return notExpired;
  }

  
  function approveHotfix(bytes32 hash) external hotfixNotExecuted(hash) onlyApprover {
    hotfixes[hash].approved = true;
    emit HotfixApproved(hash);
  }

  
  function isHotfixWhitelistedBy(bytes32 hash, address whitelister) public view returns (bool) {
    return hotfixes[hash].whitelisted[whitelister];
  }

  
  function whitelistHotfix(bytes32 hash) external hotfixNotExecuted(hash) {
    hotfixes[hash].whitelisted[msg.sender] = true;
    emit HotfixWhitelisted(hash, msg.sender);
  }

  
  function prepareHotfix(bytes32 hash) external hotfixNotExecuted(hash) {
    require(isHotfixPassing(hash), "hotfix not whitelisted by 2f+1 validators");
    uint256 epoch = getEpochNumber();
    require(hotfixes[hash].preparedEpoch < epoch, "hotfix already prepared for this epoch");
    hotfixes[hash].preparedEpoch = epoch;
    emit HotfixPrepared(hash, epoch);
  }

  
  function executeHotfix(
    uint256[] calldata values,
    address[] calldata destinations,
    bytes calldata data,
    uint256[] calldata dataLengths,
    bytes32 salt
  ) external {
    bytes32 hash = keccak256(abi.encode(values, destinations, data, dataLengths, salt));

    (bool approved, bool executed, uint256 preparedEpoch) = getHotfixRecord(hash);
    require(!executed, "hotfix already executed");
    require(approved, "hotfix not approved");
    require(preparedEpoch == getEpochNumber(), "hotfix must be prepared for this epoch");

    Proposals.makeMem(values, destinations, data, dataLengths, msg.sender, 0).executeMem();

    hotfixes[hash].executed = true;
    emit HotfixExecuted(hash);
  }

  
  function withdraw() external nonReentrant returns (bool) {
    uint256 value = refundedDeposits[msg.sender];
    require(value > 0, "Nothing to withdraw");
    require(value <= address(this).balance, "Inconsistent balance");
    refundedDeposits[msg.sender] = 0;
    msg.sender.transfer(value);
    return true;
  }

  
  function isVoting(address account) external view returns (bool) {
    Voter storage voter = voters[account];
    uint256 upvotedProposal = voter.upvote.proposalId;
    bool isVotingQueue = upvotedProposal != 0 && isQueued(upvotedProposal);
    Proposals.Proposal storage proposal = proposals[voter.mostRecentReferendumProposal];
    bool isVotingReferendum = (proposal.getDequeuedStage(stageDurations) ==
      Proposals.Stage.Referendum);
    return isVotingQueue || isVotingReferendum;
  }

  
  function getApprovalStageDuration() external view returns (uint256) {
    return stageDurations.approval;
  }

  
  function getReferendumStageDuration() external view returns (uint256) {
    return stageDurations.referendum;
  }

  
  function getExecutionStageDuration() external view returns (uint256) {
    return stageDurations.execution;
  }

  
  function getParticipationParameters() external view returns (uint256, uint256, uint256, uint256) {
    return (
      participationParameters.baseline.unwrap(),
      participationParameters.baselineFloor.unwrap(),
      participationParameters.baselineUpdateFactor.unwrap(),
      participationParameters.baselineQuorumFactor.unwrap()
    );
  }

  
  function proposalExists(uint256 proposalId) external view returns (bool) {
    return proposals[proposalId].exists();
  }

  
  function getProposal(uint256 proposalId)
    external
    view
    returns (address, uint256, uint256, uint256, string memory)
  {
    return proposals[proposalId].unpack();
  }

  
  function getProposalTransaction(uint256 proposalId, uint256 index)
    external
    view
    returns (uint256, address, bytes memory)
  {
    return proposals[proposalId].getTransaction(index);
  }

  
  function isApproved(uint256 proposalId) external view returns (bool) {
    return proposals[proposalId].isApproved();
  }

  
  function getVoteTotals(uint256 proposalId) external view returns (uint256, uint256, uint256) {
    return proposals[proposalId].getVoteTotals();
  }

  
  function getVoteRecord(address account, uint256 index) external view returns (uint256, uint256) {
    VoteRecord storage record = voters[account].referendumVotes[index];
    return (record.proposalId, uint256(record.value));
  }

  
  function getQueueLength() external view returns (uint256) {
    return queue.list.numElements;
  }

  
  function getUpvotes(uint256 proposalId) external view returns (uint256) {
    require(isQueued(proposalId), "Proposal not queued");
    return queue.getValue(proposalId);
  }

  
  function getQueue() external view returns (uint256[] memory, uint256[] memory) {
    return queue.getElements();
  }

  
  function getDequeue() external view returns (uint256[] memory) {
    return dequeued;
  }

  
  function getUpvoteRecord(address account) external view returns (uint256, uint256) {
    UpvoteRecord memory upvoteRecord = voters[account].upvote;
    return (upvoteRecord.proposalId, upvoteRecord.weight);
  }

  
  function getMostRecentReferendumProposal(address account) external view returns (uint256) {
    return voters[account].mostRecentReferendumProposal;
  }

  
  function hotfixWhitelistValidatorTally(bytes32 hash) public view returns (uint256) {
    uint256 tally = 0;
    uint256 n = numberValidatorsInCurrentSet();
    IAccounts accounts = getAccounts();
    for (uint256 i = 0; i < n; i = i.add(1)) {
      address validatorSigner = validatorSignerAddressFromCurrentSet(i);
      address validatorAccount = accounts.signerToAccount(validatorSigner);
      if (
        isHotfixWhitelistedBy(hash, validatorSigner) ||
        isHotfixWhitelistedBy(hash, validatorAccount)
      ) {
        tally = tally.add(1);
      }
    }
    return tally;
  }

  
  function isHotfixPassing(bytes32 hash) public view returns (bool) {
    return hotfixWhitelistValidatorTally(hash) >= minQuorumSizeInCurrentSet();
  }

  
  function getHotfixRecord(bytes32 hash) public view returns (bool, bool, uint256) {
    return (hotfixes[hash].approved, hotfixes[hash].executed, hotfixes[hash].preparedEpoch);
  }

  
  function dequeueProposalsIfReady() public {
    
    if (now >= lastDequeue.add(dequeueFrequency)) {
      uint256 numProposalsToDequeue = Math.min(concurrentProposals, queue.list.numElements);
      uint256[] memory dequeuedIds = queue.popN(numProposalsToDequeue);
      for (uint256 i = 0; i < numProposalsToDequeue; i = i.add(1)) {
        uint256 proposalId = dequeuedIds[i];
        Proposals.Proposal storage proposal = proposals[proposalId];
        if (_isQueuedProposalExpired(proposal)) {
          emit ProposalExpired(proposalId);
          continue;
        }
        refundedDeposits[proposal.proposer] = refundedDeposits[proposal.proposer].add(
          proposal.deposit
        );
        
        proposal.timestamp = now;
        if (emptyIndices.length > 0) {
          uint256 indexOfLastEmptyIndex = emptyIndices.length.sub(1);
          dequeued[emptyIndices[indexOfLastEmptyIndex]] = proposalId;
          
          delete emptyIndices[indexOfLastEmptyIndex];
          emptyIndices.length = indexOfLastEmptyIndex;
        } else {
          dequeued.push(proposalId);
        }
        
        emit ProposalDequeued(proposalId, now);
      }
      
      lastDequeue = now;
    }
  }

  
  function isQueued(uint256 proposalId) public view returns (bool) {
    return queue.contains(proposalId) && !isQueuedProposalExpired(proposalId);
  }

  
  function isProposalPassing(uint256 proposalId) external view returns (bool) {
    return _isProposalPassing(proposals[proposalId]);
  }

  
  function _isProposalPassing(Proposals.Proposal storage proposal) private view returns (bool) {
    FixidityLib.Fraction memory support = proposal.getSupportWithQuorumPadding(
      participationParameters.baseline.multiply(participationParameters.baselineQuorumFactor)
    );
    for (uint256 i = 0; i < proposal.transactions.length; i = i.add(1)) {
      bytes4 functionId = ExtractFunctionSignature.extractFunctionSignature(
        proposal.transactions[i].data
      );
      FixidityLib.Fraction memory threshold = _getConstitution(
        proposal.transactions[i].destination,
        functionId
      );
      if (support.lte(threshold)) {
        return false;
      }
    }
    return true;
  }

  
  function isDequeuedProposal(uint256 proposalId, uint256 index) external view returns (bool) {
    return _isDequeuedProposal(proposals[proposalId], proposalId, index);
  }

  
  function _isDequeuedProposal(
    Proposals.Proposal storage proposal,
    uint256 proposalId,
    uint256 index
  ) private view returns (bool) {
    require(index < dequeued.length, "Provided index greater than dequeue length.");
    return proposal.exists() && dequeued[index] == proposalId;
  }

  
  function isDequeuedProposalExpired(uint256 proposalId) external view returns (bool) {
    Proposals.Proposal storage proposal = proposals[proposalId];
    return _isDequeuedProposalExpired(proposal, proposal.getDequeuedStage(stageDurations));

  }

  
  function _isDequeuedProposalExpired(Proposals.Proposal storage proposal, Proposals.Stage stage)
    private
    view
    returns (bool)
  {
    
    
    
    
    return ((stage > Proposals.Stage.Execution) ||
      (stage > Proposals.Stage.Referendum && !_isProposalPassing(proposal)) ||
      (stage > Proposals.Stage.Approval && !proposal.isApproved()));
  }

  
  function isQueuedProposalExpired(uint256 proposalId) public view returns (bool) {
    return _isQueuedProposalExpired(proposals[proposalId]);
  }

  
  function _isQueuedProposalExpired(Proposals.Proposal storage proposal)
    private
    view
    returns (bool)
  {
    
    return now >= proposal.timestamp.add(queueExpiry);
  }

  
  function deleteDequeuedProposal(
    Proposals.Proposal storage proposal,
    uint256 proposalId,
    uint256 index
  ) private {
    if (proposal.isApproved() && proposal.networkWeight > 0) {
      updateParticipationBaseline(proposal);
    }
    dequeued[index] = 0;
    emptyIndices.push(index);
    delete proposals[proposalId];
  }

  
  function updateParticipationBaseline(Proposals.Proposal storage proposal) private {
    FixidityLib.Fraction memory participation = proposal.getParticipation();
    FixidityLib.Fraction memory participationComponent = participation.multiply(
      participationParameters.baselineUpdateFactor
    );
    FixidityLib.Fraction memory baselineComponent = participationParameters.baseline.multiply(
      FixidityLib.fixed1().subtract(participationParameters.baselineUpdateFactor)
    );
    participationParameters.baseline = participationComponent.add(baselineComponent);
    if (participationParameters.baseline.lt(participationParameters.baselineFloor)) {
      participationParameters.baseline = participationParameters.baselineFloor;
    }
    emit ParticipationBaselineUpdated(participationParameters.baseline.unwrap());
  }

  
  function getConstitution(address destination, bytes4 functionId) external view returns (uint256) {
    return _getConstitution(destination, functionId).unwrap();
  }

  function _getConstitution(address destination, bytes4 functionId)
    internal
    view
    returns (FixidityLib.Fraction memory)
  {
    
    FixidityLib.Fraction memory threshold = FixidityLib.wrap(FIXED_HALF);
    if (constitution[destination].functionThresholds[functionId].unwrap() != 0) {
      threshold = constitution[destination].functionThresholds[functionId];
    } else if (constitution[destination].defaultThreshold.unwrap() != 0) {
      threshold = constitution[destination].defaultThreshold;
    }
    return threshold;
  }
}
        

Contract ABI

[{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256[]","name":""},{"type":"uint256[]","name":""}],"name":"getQueue","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setBaselineQuorumFactor","inputs":[{"type":"uint256","name":"baselineQuorumFactor"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""},{"type":"bool","name":""},{"type":"uint256","name":""}],"name":"getHotfixRecord","inputs":[{"type":"bytes32","name":"hash"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"approval"},{"type":"uint256","name":"referendum"},{"type":"uint256","name":"execution"}],"name":"stageDurations","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"concurrentProposals","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"validatorSignerAddressFromCurrentSet","inputs":[{"type":"uint256","name":"index"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"proposalExists","inputs":[{"type":"uint256","name":"proposalId"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"approver","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isDequeuedProposal","inputs":[{"type":"uint256","name":"proposalId"},{"type":"uint256","name":"index"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"initialized","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setParticipationFloor","inputs":[{"type":"uint256","name":"participationFloor"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"checkProofOfPossession","inputs":[{"type":"address","name":"sender"},{"type":"bytes","name":"blsKey"},{"type":"bytes","name":"blsPop"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isProposalPassing","inputs":[{"type":"uint256","name":"proposalId"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getMostRecentReferendumProposal","inputs":[{"type":"address","name":"account"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setQueueExpiry","inputs":[{"type":"uint256","name":"_queueExpiry"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getExecutionStageDuration","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setApprover","inputs":[{"type":"address","name":"_approver"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isHotfixPassing","inputs":[{"type":"bytes32","name":"hash"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getEpochNumberOfBlock","inputs":[{"type":"uint256","name":"blockNumber"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"dequeueProposalsIfReady","inputs":[],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":""}],"name":"withdraw","inputs":[],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setParticipationBaseline","inputs":[{"type":"uint256","name":"participationBaseline"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isHotfixWhitelistedBy","inputs":[{"type":"bytes32","name":"hash"},{"type":"address","name":"whitelister"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"minDeposit","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"executed"},{"type":"bool","name":"approved"},{"type":"uint256","name":"preparedEpoch"}],"name":"hotfixes","inputs":[{"type":"bytes32","name":""}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bytes32","name":""}],"name":"getVerifiedSealBitmapFromHeader","inputs":[{"type":"bytes","name":"header"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":""}],"name":"execute","inputs":[{"type":"uint256","name":"proposalId"},{"type":"uint256","name":"index"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":""}],"name":"upvote","inputs":[{"type":"uint256","name":"proposalId"},{"type":"uint256","name":"lesser"},{"type":"uint256","name":"greater"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint8","name":""}],"name":"getProposalStage","inputs":[{"type":"uint256","name":"proposalId"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setBaselineUpdateFactor","inputs":[{"type":"uint256","name":"baselineUpdateFactor"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"validatorSignerAddressFromSet","inputs":[{"type":"uint256","name":"index"},{"type":"uint256","name":"blockNumber"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":""}],"name":"approve","inputs":[{"type":"uint256","name":"proposalId"},{"type":"uint256","name":"index"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""},{"type":"uint256","name":""}],"name":"getVoteRecord","inputs":[{"type":"address","name":"account"},{"type":"uint256","name":"index"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isVoting","inputs":[{"type":"address","name":"account"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"refundedDeposits","inputs":[{"type":"address","name":""}],"constant":true},{"type":"function","stateMutability":"payable","payable":true,"outputs":[{"type":"uint256","name":""}],"name":"propose","inputs":[{"type":"uint256[]","name":"values"},{"type":"address[]","name":"destinations"},{"type":"bytes","name":"data"},{"type":"uint256[]","name":"dataLengths"},{"type":"string","name":"descriptionUrl"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setExecutionStageDuration","inputs":[{"type":"uint256","name":"executionStageDuration"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bytes32","name":""}],"name":"hashHeader","inputs":[{"type":"bytes","name":"header"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256[]","name":""}],"name":"getDequeue","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isDequeuedProposalExpired","inputs":[{"type":"uint256","name":"proposalId"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"renounceOwnership","inputs":[],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"minQuorumSizeInCurrentSet","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"dequeueFrequency","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isApproved","inputs":[{"type":"uint256","name":"proposalId"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"registry","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setDequeueFrequency","inputs":[{"type":"uint256","name":"_dequeueFrequency"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"hotfixWhitelistValidatorTally","inputs":[{"type":"bytes32","name":"hash"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"numberValidatorsInCurrentSet","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getBlockNumberFromHeader","inputs":[{"type":"bytes","name":"header"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"owner","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"queueExpiry","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isOwner","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setMinDeposit","inputs":[{"type":"uint256","name":"_minDeposit"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getConstitution","inputs":[{"type":"address","name":"destination"},{"type":"bytes4","name":"functionId"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getUpvotes","inputs":[{"type":"uint256","name":"proposalId"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setApprovalStageDuration","inputs":[{"type":"uint256","name":"approvalStageDuration"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getEpochNumber","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"numberValidatorsInSet","inputs":[{"type":"uint256","name":"blockNumber"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"prepareHotfix","inputs":[{"type":"bytes32","name":"hash"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setRegistry","inputs":[{"type":"address","name":"registryAddress"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"emptyIndices","inputs":[{"type":"uint256","name":""}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getReferendumStageDuration","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"dequeued","inputs":[{"type":"uint256","name":""}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":""}],"name":"revokeUpvote","inputs":[{"type":"uint256","name":"lesser"},{"type":"uint256","name":"greater"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"approveHotfix","inputs":[{"type":"bytes32","name":"hash"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"whitelistHotfix","inputs":[{"type":"bytes32","name":"hash"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getQueueLength","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":""}],"name":"vote","inputs":[{"type":"uint256","name":"proposalId"},{"type":"uint256","name":"index"},{"type":"uint8","name":"value"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"lastDequeue","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isQueuedProposalExpired","inputs":[{"type":"uint256","name":"proposalId"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"initialize","inputs":[{"type":"address","name":"registryAddress"},{"type":"address","name":"_approver"},{"type":"uint256","name":"_concurrentProposals"},{"type":"uint256","name":"_minDeposit"},{"type":"uint256","name":"_queueExpiry"},{"type":"uint256","name":"_dequeueFrequency"},{"type":"uint256","name":"approvalStageDuration"},{"type":"uint256","name":"referendumStageDuration"},{"type":"uint256","name":"executionStageDuration"},{"type":"uint256","name":"participationBaseline"},{"type":"uint256","name":"participationFloor"},{"type":"uint256","name":"baselineUpdateFactor"},{"type":"uint256","name":"baselineQuorumFactor"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"isQueued","inputs":[{"type":"uint256","name":"proposalId"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""},{"type":"uint256","name":""},{"type":"uint256","name":""},{"type":"uint256","name":""},{"type":"string","name":""}],"name":"getProposal","inputs":[{"type":"uint256","name":"proposalId"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""},{"type":"uint256","name":""},{"type":"uint256","name":""},{"type":"uint256","name":""}],"name":"getParticipationParameters","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setConcurrentProposals","inputs":[{"type":"uint256","name":"_concurrentProposals"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""},{"type":"uint256","name":""}],"name":"getUpvoteRecord","inputs":[{"type":"address","name":"account"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setReferendumStageDuration","inputs":[{"type":"uint256","name":"referendumStageDuration"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"executeHotfix","inputs":[{"type":"uint256[]","name":"values"},{"type":"address[]","name":"destinations"},{"type":"bytes","name":"data"},{"type":"uint256[]","name":"dataLengths"},{"type":"bytes32","name":"salt"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""},{"type":"address","name":""},{"type":"bytes","name":""}],"name":"getProposalTransaction","inputs":[{"type":"uint256","name":"proposalId"},{"type":"uint256","name":"index"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"proposalCount","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getEpochSize","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""},{"type":"uint256","name":""},{"type":"uint256","name":""}],"name":"getVoteTotals","inputs":[{"type":"uint256","name":"proposalId"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"minQuorumSize","inputs":[{"type":"uint256","name":"blockNumber"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""},{"type":"uint256","name":""}],"name":"fractionMulExp","inputs":[{"type":"uint256","name":"aNumerator"},{"type":"uint256","name":"aDenominator"},{"type":"uint256","name":"bNumerator"},{"type":"uint256","name":"bDenominator"},{"type":"uint256","name":"exponent"},{"type":"uint256","name":"_decimals"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setConstitution","inputs":[{"type":"address","name":"destination"},{"type":"bytes4","name":"functionId"},{"type":"uint256","name":"threshold"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bytes32","name":""}],"name":"getParentSealBitmap","inputs":[{"type":"uint256","name":"blockNumber"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"getApprovalStageDuration","inputs":[],"constant":true},{"type":"fallback","stateMutability":"payable","payable":true},{"type":"event","name":"ApproverSet","inputs":[{"type":"address","name":"approver","indexed":true}],"anonymous":false},{"type":"event","name":"ConcurrentProposalsSet","inputs":[{"type":"uint256","name":"concurrentProposals","indexed":false}],"anonymous":false},{"type":"event","name":"MinDepositSet","inputs":[{"type":"uint256","name":"minDeposit","indexed":false}],"anonymous":false},{"type":"event","name":"QueueExpirySet","inputs":[{"type":"uint256","name":"queueExpiry","indexed":false}],"anonymous":false},{"type":"event","name":"DequeueFrequencySet","inputs":[{"type":"uint256","name":"dequeueFrequency","indexed":false}],"anonymous":false},{"type":"event","name":"ApprovalStageDurationSet","inputs":[{"type":"uint256","name":"approvalStageDuration","indexed":false}],"anonymous":false},{"type":"event","name":"ReferendumStageDurationSet","inputs":[{"type":"uint256","name":"referendumStageDuration","indexed":false}],"anonymous":false},{"type":"event","name":"ExecutionStageDurationSet","inputs":[{"type":"uint256","name":"executionStageDuration","indexed":false}],"anonymous":false},{"type":"event","name":"ConstitutionSet","inputs":[{"type":"address","name":"destination","indexed":true},{"type":"bytes4","name":"functionId","indexed":true},{"type":"uint256","name":"threshold","indexed":false}],"anonymous":false},{"type":"event","name":"ProposalQueued","inputs":[{"type":"uint256","name":"proposalId","indexed":true},{"type":"address","name":"proposer","indexed":true},{"type":"uint256","name":"transactionCount","indexed":false},{"type":"uint256","name":"deposit","indexed":false},{"type":"uint256","name":"timestamp","indexed":false}],"anonymous":false},{"type":"event","name":"ProposalUpvoted","inputs":[{"type":"uint256","name":"proposalId","indexed":true},{"type":"address","name":"account","indexed":true},{"type":"uint256","name":"upvotes","indexed":false}],"anonymous":false},{"type":"event","name":"ProposalUpvoteRevoked","inputs":[{"type":"uint256","name":"proposalId","indexed":true},{"type":"address","name":"account","indexed":true},{"type":"uint256","name":"revokedUpvotes","indexed":false}],"anonymous":false},{"type":"event","name":"ProposalDequeued","inputs":[{"type":"uint256","name":"proposalId","indexed":true},{"type":"uint256","name":"timestamp","indexed":false}],"anonymous":false},{"type":"event","name":"ProposalApproved","inputs":[{"type":"uint256","name":"proposalId","indexed":true}],"anonymous":false},{"type":"event","name":"ProposalVoted","inputs":[{"type":"uint256","name":"proposalId","indexed":true},{"type":"address","name":"account","indexed":true},{"type":"uint256","name":"value","indexed":false},{"type":"uint256","name":"weight","indexed":false}],"anonymous":false},{"type":"event","name":"ProposalExecuted","inputs":[{"type":"uint256","name":"proposalId","indexed":true}],"anonymous":false},{"type":"event","name":"ProposalExpired","inputs":[{"type":"uint256","name":"proposalId","indexed":true}],"anonymous":false},{"type":"event","name":"ParticipationBaselineUpdated","inputs":[{"type":"uint256","name":"participationBaseline","indexed":false}],"anonymous":false},{"type":"event","name":"ParticipationFloorSet","inputs":[{"type":"uint256","name":"participationFloor","indexed":false}],"anonymous":false},{"type":"event","name":"ParticipationBaselineUpdateFactorSet","inputs":[{"type":"uint256","name":"baselineUpdateFactor","indexed":false}],"anonymous":false},{"type":"event","name":"ParticipationBaselineQuorumFactorSet","inputs":[{"type":"uint256","name":"baselineQuorumFactor","indexed":false}],"anonymous":false},{"type":"event","name":"HotfixWhitelisted","inputs":[{"type":"bytes32","name":"hash","indexed":true},{"type":"address","name":"whitelister","indexed":false}],"anonymous":false},{"type":"event","name":"HotfixApproved","inputs":[{"type":"bytes32","name":"hash","indexed":true}],"anonymous":false},{"type":"event","name":"HotfixPrepared","inputs":[{"type":"bytes32","name":"hash","indexed":true},{"type":"uint256","name":"epoch","indexed":true}],"anonymous":false},{"type":"event","name":"HotfixExecuted","inputs":[{"type":"bytes32","name":"hash","indexed":true}],"anonymous":false},{"type":"event","name":"RegistrySet","inputs":[{"type":"address","name":"registryAddress","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","indexed":true},{"type":"address","name":"newOwner","indexed":true}],"anonymous":false}]
              

Contract Creation Code

0x6080604052600062000016620000c160201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35060018081905550620000c9565b600033905090565b61b8ac80620000d96000396000f3fe6080604052600436106104cb5760003560e01c80637b10399911610276578063b8f770051161014f578063cf48eb94116100c1578063e50e652d11610085578063e50e652d14612517578063ec68307214612566578063ed385274146125ee578063f2fde38b14612672578063fae8db0a146126c3578063ffea74c014612712576104cb565b8063cf48eb94146121dd578063d704f0c51461236c578063da35c66414612464578063df4da4611461248f578063e41db455146124ba576104cb565b8063c73a6d7811610113578063c73a6d7814611f6c578063c7f758a814611fbf578063c805956d146120bb578063c8d8d2b5146120fb578063cd845a7614612136578063cea69e74146121a2576104cb565b8063b8f7700514611d79578063bbb2eab914611da4578063c0aee5f414611e0e578063c134b2fc14611e39578063c1939b2014611e8c576104cb565b80639a6c3d83116101e8578063aa2feb83116101ac578063aa2feb8314611bdd578063ad78c10914611c2c578063add004df14611c57578063af108a0e14611ca6578063b0f9984214611d03578063b15f0f5814611d3e576104cb565b80639a6c3d8314611a9c5780639a7b3be714611ad75780639b2b592f14611b025780639cb02dfc14611b51578063a91ee0dc14611b8c576104cb565b80638da5cb5b1161023a5780638da5cb5b146118d35780638e905ed61461192a5780638f32d59b146119555780638fcc9cfb1461198457806397b9eba6146119bf57806398f4270214611a4d576104cb565b80637b103999146116eb5780638018556e1461174257806381d4728d1461177d57806387ee8a0f146117cc5780638a883626146117f7576104cb565b80633fa5fed0116103a85780635f8dd6491161031a5780636de8a63b116102de5780636de8a63b1461156c5780636f2ab693146115d8578063715018a61461162b5780637385e5da1461164257806377d26a2a1461166d5780637910867b14611698576104cb565b80635f8dd649146111a657806360b4d34d1461120f57806365bbdaa0146112745780636643ac581461145557806367960e9114611490576104cb565b8063573339781161036c5780635733397814610f4f578063582ae53b14610fb65780635c759394146110135780635d180adb1461104e5780635d35a3d9146110d35780635f115a8514611130576104cb565b80633fa5fed014610d1357806341b3d18514610d8657806345a7849914610db15780634b2c2f4414610e165780635601eaea14610ef2576104cb565b806323f0ab65116104415780633156560e116104055780633156560e14610b9f578063344944cf14610bf05780633b1eb4bf14610c435780633bb0ed2b14610c925780633ccfd60b14610ca95780633db9dd9a14610cd8576104cb565b806323f0ab65146108ea5780632762132114610a81578063283aaefb14610ad45780632c05235514610b3957806330a095d014610b74576104cb565b8063123633ea11610493578063123633ea146106fe5780631374b22d14610779578063141a8dd8146107cc578063152b483414610823578063158ef93e146108805780631c65bc61146108af576104cb565b806301fce27e1461054657806304acaec9146105fa5780630e0b78ae146106355780630f717e421461069a5780631201a0fb146106d3575b60008036905014610544576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f756e6b6e6f776e206d6574686f6400000000000000000000000000000000000081525060200191505060405180910390fd5b005b34801561055257600080fd5b5061055b61273d565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156105a2578082015181840152602081019050610587565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156105e45780820151818401526020810190506105c9565b5050505090500194505050505060405180910390f35b34801561060657600080fd5b506106336004803603602081101561061d57600080fd5b810190808035906020019092919050505061287a565b005b34801561064157600080fd5b5061066e6004803603602081101561065857600080fd5b8101908080359060200190929190505050612a52565b604051808415151515815260200183151515158152602001828152602001935050505060405180910390f35b3480156106a657600080fd5b506106af612ac3565b60405180848152602001838152602001828152602001935050505060405180910390f35b3480156106df57600080fd5b506106e8612adb565b6040518082815260200191505060405180910390f35b34801561070a57600080fd5b506107376004803603602081101561072157600080fd5b8101908080359060200190929190505050612ae1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561078557600080fd5b506107b26004803603602081101561079c57600080fd5b8101908080359060200190929190505050612c32565b604051808215151515815260200191505060405180910390f35b3480156107d857600080fd5b506107e1612c56565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561082f57600080fd5b506108666004803603604081101561084657600080fd5b810190808035906020019092919080359060200190929190505050612c7c565b604051808215151515815260200191505060405180910390f35b34801561088c57600080fd5b50610895612ca3565b604051808215151515815260200191505060405180910390f35b3480156108bb57600080fd5b506108e8600480360360208110156108d257600080fd5b8101908080359060200190929190505050612cb6565b005b3480156108f657600080fd5b50610a676004803603606081101561090d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561094a57600080fd5b82018360208201111561095c57600080fd5b8035906020019184600183028401116401000000008311171561097e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803590602001906401000000008111156109e157600080fd5b8201836020820111156109f357600080fd5b80359060200191846001830284011164010000000083111715610a1557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612e71565b604051808215151515815260200191505060405180910390f35b348015610a8d57600080fd5b50610aba60048036036020811015610aa457600080fd5b810190808035906020019092919050505061302a565b604051808215151515815260200191505060405180910390f35b348015610ae057600080fd5b50610b2360048036036020811015610af757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061304e565b6040518082815260200191505060405180910390f35b348015610b4557600080fd5b50610b7260048036036020811015610b5c57600080fd5b810190808035906020019092919050505061309a565b005b348015610b8057600080fd5b50610b89613226565b6040518082815260200191505060405180910390f35b348015610bab57600080fd5b50610bee60048036036020811015610bc257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613233565b005b348015610bfc57600080fd5b50610c2960048036036020811015610c1357600080fd5b810190808035906020019092919050505061349b565b604051808215151515815260200191505060405180910390f35b348015610c4f57600080fd5b50610c7c60048036036020811015610c6657600080fd5b81019080803590602001909291905050506134b7565b6040518082815260200191505060405180910390f35b348015610c9e57600080fd5b50610ca76134d1565b005b348015610cb557600080fd5b50610cbe61387c565b604051808215151515815260200191505060405180910390f35b348015610ce457600080fd5b50610d1160048036036020811015610cfb57600080fd5b8101908080359060200190929190505050613ae8565b005b348015610d1f57600080fd5b50610d6c60048036036040811015610d3657600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613cc0565b604051808215151515815260200191505060405180910390f35b348015610d9257600080fd5b50610d9b613d2b565b6040518082815260200191505060405180910390f35b348015610dbd57600080fd5b50610dea60048036036020811015610dd457600080fd5b8101908080359060200190929190505050613d31565b604051808415151515815260200183151515158152602001828152602001935050505060405180910390f35b348015610e2257600080fd5b50610edc60048036036020811015610e3957600080fd5b8101908080359060200190640100000000811115610e5657600080fd5b820183602082011115610e6857600080fd5b80359060200191846001830284011164010000000083111715610e8a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050613d75565b6040518082815260200191505060405180910390f35b348015610efe57600080fd5b50610f3560048036036040811015610f1557600080fd5b810190808035906020019092919080359060200190929190505050613f09565b604051808215151515815260200191505060405180910390f35b348015610f5b57600080fd5b50610f9c60048036036060811015610f7257600080fd5b810190808035906020019092919080359060200190929190803590602001909291905050506140f4565b604051808215151515815260200191505060405180910390f35b348015610fc257600080fd5b50610fef60048036036020811015610fd957600080fd5b8101908080359060200190929190505050614789565b60405180826005811115610fff57fe5b60ff16815260200191505060405180910390f35b34801561101f57600080fd5b5061104c6004803603602081101561103657600080fd5b81019080803590602001909291905050506147ed565b005b34801561105a57600080fd5b506110916004803603604081101561107157600080fd5b8101908080359060200190929190803590602001909291905050506149c5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156110df57600080fd5b50611116600480360360408110156110f657600080fd5b810190808035906020019092919080359060200190929190505050614b17565b604051808215151515815260200191505060405180910390f35b34801561113c57600080fd5b506111896004803603604081101561115357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050614dfc565b604051808381526020018281526020019250505060405180910390f35b3480156111b257600080fd5b506111f5600480360360208110156111c957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614e84565b604051808215151515815260200191505060405180910390f35b34801561121b57600080fd5b5061125e6004803603602081101561123257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614f4e565b6040518082815260200191505060405180910390f35b61143f600480360360a081101561128a57600080fd5b81019080803590602001906401000000008111156112a757600080fd5b8201836020820111156112b957600080fd5b803590602001918460208302840111640100000000831117156112db57600080fd5b9091929391929390803590602001906401000000008111156112fc57600080fd5b82018360208201111561130e57600080fd5b8035906020019184602083028401116401000000008311171561133057600080fd5b90919293919293908035906020019064010000000081111561135157600080fd5b82018360208201111561136357600080fd5b8035906020019184600183028401116401000000008311171561138557600080fd5b9091929391929390803590602001906401000000008111156113a657600080fd5b8201836020820111156113b857600080fd5b803590602001918460208302840111640100000000831117156113da57600080fd5b9091929391929390803590602001906401000000008111156113fb57600080fd5b82018360208201111561140d57600080fd5b8035906020019184600183028401116401000000008311171561142f57600080fd5b9091929391929390505050614f66565b6040518082815260200191505060405180910390f35b34801561146157600080fd5b5061148e6004803603602081101561147857600080fd5b81019080803590602001909291905050506152e2565b005b34801561149c57600080fd5b50611556600480360360208110156114b357600080fd5b81019080803590602001906401000000008111156114d057600080fd5b8201836020820111156114e257600080fd5b8035906020019184600183028401116401000000008311171561150457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050615491565b6040518082815260200191505060405180910390f35b34801561157857600080fd5b50611581615625565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156115c45780820151818401526020810190506115a9565b505050509050019250505060405180910390f35b3480156115e457600080fd5b50611611600480360360208110156115fb57600080fd5b810190808035906020019092919050505061567d565b604051808215151515815260200191505060405180910390f35b34801561163757600080fd5b506116406156ba565b005b34801561164e57600080fd5b506116576157f3565b6040518082815260200191505060405180910390f35b34801561167957600080fd5b50611682615803565b6040518082815260200191505060405180910390f35b3480156116a457600080fd5b506116d1600480360360208110156116bb57600080fd5b8101908080359060200190929190505050615809565b604051808215151515815260200191505060405180910390f35b3480156116f757600080fd5b5061170061582d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561174e57600080fd5b5061177b6004803603602081101561176557600080fd5b8101908080359060200190929190505050615853565b005b34801561178957600080fd5b506117b6600480360360208110156117a057600080fd5b81019080803590602001909291905050506159df565b6040518082815260200191505060405180910390f35b3480156117d857600080fd5b506117e1615b35565b6040518082815260200191505060405180910390f35b34801561180357600080fd5b506118bd6004803603602081101561181a57600080fd5b810190808035906020019064010000000081111561183757600080fd5b82018360208201111561184957600080fd5b8035906020019184600183028401116401000000008311171561186b57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050615c7c565b6040518082815260200191505060405180910390f35b3480156118df57600080fd5b506118e8615e10565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561193657600080fd5b5061193f615e39565b6040518082815260200191505060405180910390f35b34801561196157600080fd5b5061196a615e3f565b604051808215151515815260200191505060405180910390f35b34801561199057600080fd5b506119bd600480360360208110156119a757600080fd5b8101908080359060200190929190505050615e9d565b005b3480156119cb57600080fd5b50611a37600480360360408110156119e257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050616046565b6040518082815260200191505060405180910390f35b348015611a5957600080fd5b50611a8660048036036020811015611a7057600080fd5b8101908080359060200190929190505050616062565b6040518082815260200191505060405180910390f35b348015611aa857600080fd5b50611ad560048036036020811015611abf57600080fd5b810190808035906020019092919050505061617b565b005b348015611ae357600080fd5b50611aec61632a565b6040518082815260200191505060405180910390f35b348015611b0e57600080fd5b50611b3b60048036036020811015611b2557600080fd5b810190808035906020019092919050505061633a565b6040518082815260200191505060405180910390f35b348015611b5d57600080fd5b50611b8a60048036036020811015611b7457600080fd5b8101908080359060200190929190505050616483565b005b348015611b9857600080fd5b50611bdb60048036036020811015611baf57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050616641565b005b348015611be957600080fd5b50611c1660048036036020811015611c0057600080fd5b81019080803590602001909291905050506167e5565b6040518082815260200191505060405180910390f35b348015611c3857600080fd5b50611c41616806565b6040518082815260200191505060405180910390f35b348015611c6357600080fd5b50611c9060048036036020811015611c7a57600080fd5b8101908080359060200190929190505050616813565b6040518082815260200191505060405180910390f35b348015611cb257600080fd5b50611ce960048036036040811015611cc957600080fd5b810190808035906020019092919080359060200190929190505050616834565b604051808215151515815260200191505060405180910390f35b348015611d0f57600080fd5b50611d3c60048036036020811015611d2657600080fd5b8101908080359060200190929190505050616cc7565b005b348015611d4a57600080fd5b50611d7760048036036020811015611d6157600080fd5b8101908080359060200190929190505050616e82565b005b348015611d8557600080fd5b50611d8e616fee565b6040518082815260200191505060405180910390f35b348015611db057600080fd5b50611df460048036036060811015611dc757600080fd5b810190808035906020019092919080359060200190929190803560ff169060200190929190505050616ffe565b604051808215151515815260200191505060405180910390f35b348015611e1a57600080fd5b50611e23617712565b6040518082815260200191505060405180910390f35b348015611e4557600080fd5b50611e7260048036036020811015611e5c57600080fd5b8101908080359060200190929190505050617718565b604051808215151515815260200191505060405180910390f35b348015611e9857600080fd5b50611f6a60048036036101a0811015611eb057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919050505061773c565b005b348015611f7857600080fd5b50611fa560048036036020811015611f8f57600080fd5b810190808035906020019092919050505061786e565b604051808215151515815260200191505060405180910390f35b348015611fcb57600080fd5b50611ff860048036036020811015611fe257600080fd5b810190808035906020019092919050505061791e565b604051808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200185815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561207c578082015181840152602081019050612061565b50505050905090810190601f1680156120a95780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b3480156120c757600080fd5b506120d06179f0565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b34801561210757600080fd5b506121346004803603602081101561211e57600080fd5b8101908080359060200190929190505050617a8c565b005b34801561214257600080fd5b506121856004803603602081101561215957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050617c18565b604051808381526020018281526020019250505060405180910390f35b3480156121ae57600080fd5b506121db600480360360208110156121c557600080fd5b8101908080359060200190929190505050617c9a565b005b3480156121e957600080fd5b5061236a600480360360a081101561220057600080fd5b810190808035906020019064010000000081111561221d57600080fd5b82018360208201111561222f57600080fd5b8035906020019184602083028401116401000000008311171561225157600080fd5b90919293919293908035906020019064010000000081111561227257600080fd5b82018360208201111561228457600080fd5b803590602001918460208302840111640100000000831117156122a657600080fd5b9091929391929390803590602001906401000000008111156122c757600080fd5b8201836020820111156122d957600080fd5b803590602001918460018302840111640100000000831117156122fb57600080fd5b90919293919293908035906020019064010000000081111561231c57600080fd5b82018360208201111561232e57600080fd5b8035906020019184602083028401116401000000008311171561235057600080fd5b909192939192939080359060200190929190505050617e49565b005b34801561237857600080fd5b506123af6004803603604081101561238f57600080fd5b810190808035906020019092919080359060200190929190505050618230565b604051808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561242757808201518184015260208101905061240c565b50505050905090810190601f1680156124545780820380516001836020036101000a031916815260200191505b5094505050505060405180910390f35b34801561247057600080fd5b50612479618352565b6040518082815260200191505060405180910390f35b34801561249b57600080fd5b506124a4618358565b6040518082815260200191505060405180910390f35b3480156124c657600080fd5b506124f3600480360360208110156124dd57600080fd5b8101908080359060200190929190505050618494565b60405180848152602001838152602001828152602001935050505060405180910390f35b34801561252357600080fd5b506125506004803603602081101561253a57600080fd5b81019080803590602001909291905050506184c1565b6040518082815260200191505060405180910390f35b34801561257257600080fd5b506125d1600480360360c081101561258957600080fd5b8101908080359060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919050505061850c565b604051808381526020018281526020019250505060405180910390f35b3480156125fa57600080fd5b506126706004803603606081101561261157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919080359060200190929190505050618720565b005b34801561267e57600080fd5b506126c16004803603602081101561269557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050618a5d565b005b3480156126cf57600080fd5b506126fc600480360360208110156126e657600080fd5b8101908080359060200190929190505050618ae3565b6040518082815260200191505060405180910390f35b34801561271e57600080fd5b50612727618c2c565b6040518082815260200191505060405180910390f35b606080601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd6369b317e390916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b15801561279257600080fd5b505af41580156127a6573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060408110156127d057600080fd5b8101908080516401000000008111156127e857600080fd5b828101905060208101848111156127fe57600080fd5b815185602082028301116401000000008211171561281b57600080fd5b5050929190602001805164010000000081111561283757600080fd5b8281019050602081018481111561284d57600080fd5b815185602082028301116401000000008211171561286a57600080fd5b5050929190505050915091509091565b612882615e3f565b6128f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6128fc61b077565b61290582618c39565b905061291081618c57565b612965576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061b45a6027913960400191505060405180910390fd5b612991601960030160405180602001604052908160008201548152505082618c7190919063ffffffff16565b15612a04576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f426173656c696e652071756f72756d20666163746f7220756e6368616e67656481525060200191505060405180910390fd5b806019600301600082015181600001559050507fddfdbe55eaaa70fe2b8bc82a9b0734c25cabe7cb6f1457f9644019f0b5ff91fc826040518082815260200191505060405180910390a15050565b60008060006011600085815260200190815260200160002060000160019054906101000a900460ff166011600086815260200190815260200160002060000160009054906101000a900460ff1660116000878152602001908152602001600020600101549250925092509193909250565b60038060000154908060010154908060020154905083565b600a5481565b60006060600060fa73ffffffffffffffffffffffffffffffffffffffff16844360405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310612b5a5780518252602082019150602081019050602083039250612b37565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114612bba576040519150601f19603f3d011682016040523d82523d6000602084013e612bbf565b606091505b50809350819250505080612c1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603d81526020018061b5ad603d913960400191505060405180910390fd5b612c29826000618c86565b92505050919050565b6000612c4f600f6000848152602001908152602001600020618c9d565b9050919050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000612c9b600f60008581526020019081526020016000208484618cad565b905092915050565b600060149054906101000a900460ff1681565b612cbe615e3f565b612d30576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b612d3861b077565b612d4182618c39565b9050612d4c81618c57565b612da1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061b7876024913960400191505060405180910390fd5b612dcd601960010160405180602001604052908160008201548152505082618c7190919063ffffffff16565b15612e23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061b4c96026913960400191505060405180910390fd5b806019600101600082015181600001559050507f122a37b609e0f758b6a23c43506cb567017a4d18b21fa91312fb42b44975a5b5826040518082815260200191505060405180910390a15050565b60008060fb73ffffffffffffffffffffffffffffffffffffffff16858585604051602001808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140183805190602001908083835b60208310612efa5780518252602082019150602081019050602083039250612ed7565b6001836020036101000a03801982511681845116808217855250505050505090500182805190602001908083835b60208310612f4b5780518252602082019150602081019050602083039250612f28565b6001836020036101000a03801982511681845116808217855250505050505090500193505050506040516020818303038152906040526040518082805190602001908083835b60208310612fb45780518252602082019150602081019050602083039250612f91565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613014576040519150601f19603f3d011682016040523d82523d6000602084013e613019565b606091505b505080915050809150509392505050565b6000613047600f6000848152602001908152602001600020618d40565b9050919050565b6000601060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201549050919050565b6130a2615e3f565b613114576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000811161316d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061b3696021913960400191505060405180910390fd5b6006548114156131e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f517565756545787069727920756e6368616e676564000000000000000000000081525060200191505060405180910390fd5b806006819055507f4ecbf0bb0701615e2d6f9b0a0996056c959fe359ce76aa7ce06c5f1d57dae4d7816040518082815260200191505060405180910390a150565b6000600360020154905090565b61323b615e3f565b6132ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613350576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f417070726f7665722063616e6e6f74206265203000000000000000000000000081525060200191505060405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613414576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f417070726f76657220756e6368616e676564000000000000000000000000000081525060200191505060405180910390fd5b80600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fa03757d836cb0b61c0fbba2147f5d51d6071ff3dd5bf6963beb55563d64878e160405160405180910390a250565b60006134a56157f3565b6134ae836159df565b10159050919050565b60006134ca826134c5618358565b618f1f565b9050919050565b6134e8600754600954618f5790919063ffffffff16565b421061387a576000613504600a54601260000160020154618fdf565b90506060601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd6377b024799091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b15801561356257600080fd5b505af4158015613576573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156135a057600080fd5b8101908080516401000000008111156135b857600080fd5b828101905060208101848111156135ce57600080fd5b81518560208202830111640100000000821117156135eb57600080fd5b5050929190505050905060008090505b8281101561386f57600082828151811061361157fe5b602002602001015190506000600f6000838152602001908152602001600020905061363b81618ff8565b1561367457817f88e53c486703527139dfc8d97a1e559d9bd93d3f9d52cda4e06564111e7a264360405160405180910390a25050613854565b6136ee8160010154600d60008460000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054618f5790919063ffffffff16565b600d60008360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550428160020181905550600060188054905011156137ec576000613787600160188054905061901d90919063ffffffff16565b90508260176018838154811061379957fe5b9060005260206000200154815481106137ae57fe5b9060005260206000200181905550601881815481106137c957fe5b9060005260206000200160009055806018816137e5919061b08a565b5050613819565b60178290806001815401808255809150509060018203906000526020600020016000909192909190915055505b817f3e069fb74dcf5fbc07740b0d40d7f7fc48e9c0ca5dc3d19eb34d2e05d74c5543426040518082815260200191505060405180910390a250505b613868600182618f5790919063ffffffff16565b90506135fb565b504260098190555050505b565b600060018060008282540192505081905550600060015490506000600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000811161394f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f4e6f7468696e6720746f2077697468647261770000000000000000000000000081525060200191505060405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16318111156139dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f496e636f6e73697374656e742062616c616e636500000000000000000000000081525060200191505060405180910390fd5b6000600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015613a67573d6000803e3d6000fd5b5060019250506001548114613ae4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5090565b613af0615e3f565b613b62576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b613b6a61b077565b613b7382618c39565b9050613b7e81618c57565b613bd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061b3b86027913960400191505060405180910390fd5b613bff601960000160405180602001604052908160008201548152505082618c7190919063ffffffff16565b15613c72576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f50617274696369706174696f6e20626173656c696e6520756e6368616e67656481525060200191505060405180910390fd5b806019600001600082015181600001559050507f51131d2820f04a6b6edd20e22a07d5bf847e265a3906e85256fca7d6043417c5826040518082815260200191505060405180910390a15050565b60006011600084815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600c5481565b60116020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900460ff16908060010154905083565b60006060600060f473ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b60208310613dca5780518252602082019150602081019050602083039250613da7565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310613e315780518252602082019150602081019050602083039250613e0e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613e91576040519150601f19603f3d011682016040523d82523d6000602084013e613e96565b606091505b50809350819250505080613ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603881526020018061b5166038913960400191505060405180910390fd5b613f00826000619067565b92505050919050565b60006001806000828254019250508190555060006001549050613f2a6134d1565b600080613f3786866190f8565b915091506000613f4683618c9d565b905080156140705760046005811115613f5b57fe5b826005811115613f6757fe5b148015613f795750613f7883618d40565b5b613fce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018061b655602e913960400191505060405180910390fd5b82735d3739f939b974ebeb80afd8f69764e8d78d79dc63c67e7b4b90916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b15801561401f57600080fd5b505af4158015614033573d6000803e3d6000fd5b50505050867f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f60405160405180910390a261406f8388886191d1565b5b80945050505060015481146140ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5092915050565b600060018060008282540192505081905550600060015490506141156134d1565b61411e856192ef565b1561412c576000915061470a565b6000614136619449565b73ffffffffffffffffffffffffffffffffffffffff16636642d594336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156141b257600080fd5b505afa1580156141c6573d6000803e3d6000fd5b505050506040513d60208110156141dc57600080fd5b810190808051906020019092919050505090506000601060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905061424281600001600001546192ef565b50600061424d619544565b73ffffffffffffffffffffffffffffffffffffffff166330ec70f5846040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156142c957600080fd5b505afa1580156142dd573d6000803e3d6000fd5b505050506040513d60208110156142f357600080fd5b810190808051906020019092919050505090506000811161435f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061b6f36022913960400191505060405180910390fd5b601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63bfc5163890918a6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156143b957600080fd5b505af41580156143cd573d6000803e3d6000fd5b505050506040513d60208110156143e357600080fd5b8101908080519060200190929190505050614449576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061b5846029913960400191505060405180910390fd5b6000826000016000015414806144f85750601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63bfc51638909184600001600001546040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156144bb57600080fd5b505af41580156144cf573d6000803e3d6000fd5b505050506040513d60208110156144e557600080fd5b8101908080519060200190929190505050155b61454d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b81526020018061b808602b913960400191505060405180910390fd5b60006145f682601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd637577759990918d6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156145ad57600080fd5b505af41580156145c1573d6000803e3d6000fd5b505050506040513d60208110156145d757600080fd5b8101908080519060200190929190505050618f5790919063ffffffff16565b9050601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63239491ba90918b848c8c6040518663ffffffff1660e01b8152600401808681526020018581526020018481526020018381526020018281526020019550505050505060006040518083038186803b15801561466a57600080fd5b505af415801561467e573d6000803e3d6000fd5b5050505060405180604001604052808a8152602001838152508360000160008201518160000155602082015181600101559050508373ffffffffffffffffffffffffffffffffffffffff16897fd19965d25ef670a1e322fbf05475924b7b12d81fd6b96ab718b261782efb3d62846040518082815260200191505060405180910390a360019550505050505b6001548114614781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b509392505050565b60008082148061479a5750600b5482115b156147a857600090506147e8565b6147b18261786e565b156147bf57600190506147e8565b6147e56003600f600085815260200190815260200160002061963f90919063ffffffff16565b90505b919050565b6147f5615e3f565b614867576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61486f61b077565b61487882618c39565b905061488381618c57565b6148d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061b4ef6027913960400191505060405180910390fd5b614904601960020160405180602001604052908160008201548152505082618c7190919063ffffffff16565b15614977576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f426173656c696e652075706461746520666163746f7220756e6368616e67656481525060200191505060405180910390fd5b806019600201600082015181600001559050507f8dedb4d995dd500718c7c5f6a077fba6153a7ee063da961d9fcab90ff528ac1f826040518082815260200191505060405180910390a15050565b60006060600060fa73ffffffffffffffffffffffffffffffffffffffff16858560405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310614a3e5780518252602082019150602081019050602083039250614a1b565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114614a9e576040519150601f19603f3d011682016040523d82523d6000602084013e614aa3565b606091505b50809350819250505080614b02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061b61f6036913960400191505060405180910390fd5b614b0d826000618c86565b9250505092915050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614614bdc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f6d73672e73656e646572206e6f7420617070726f76657200000000000000000081525060200191505060405180910390fd5b614be46134d1565b600080614bf185856190f8565b91509150614bfe82618c9d565b614c0d57600092505050614df6565b614c16826196fc565b15614c89576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f50726f706f73616c20616c726561647920617070726f7665640000000000000081525060200191505060405180910390fd5b60026005811115614c9657fe5b816005811115614ca257fe5b14614d15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f50726f706f73616c206e6f7420696e20617070726f76616c207374616765000081525060200191505060405180910390fd5b60018260070160006101000a81548160ff021916908315150217905550614d3a619544565b73ffffffffffffffffffffffffffffffffffffffff166330a61d596040518163ffffffff1660e01b815260040160206040518083038186803b158015614d7f57600080fd5b505afa158015614d93573d6000803e3d6000fd5b505050506040513d6020811015614da957600080fd5b81019080805190602001909291905050508260080181905550847f28ec9e38ba73636ceb2f6c1574136f83bd46284a3c74734b711bf45e12f8d92960405160405180910390a26001925050505b92915050565b6000806000601060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206003016000858152602001908152602001600020905080600101548160000160009054906101000a900460ff166003811115614e7857fe5b92509250509250929050565b600080601060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000816000016000015490506000808214158015614eeb5750614eea8261786e565b5b90506000600f6000856002015481526020019081526020016000209050600060036005811115614f1757fe5b614f2b60038461963f90919063ffffffff16565b6005811115614f3657fe5b1490508280614f425750805b95505050505050919050565b600d6020528060005260406000206000915090505481565b6000614f706134d1565b600c54341015614fe8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f546f6f20736d616c6c206465706f73697400000000000000000000000000000081525060200191505060405180910390fd5b614ffe6001600b54618f5790919063ffffffff16565b600b819055506000600f6000600b548152602001908152602001600020905080735d3739f939b974ebeb80afd8f69764e8d78d79dc633053123f90918e8e8e8e8e8e8e8e33346040518c63ffffffff1660e01b8152600401808c8152602001806020018060200180602001806020018773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200186815260200185810385528f8f82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810384528d8d82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810383528b8b82818152602001925080828437600081840152601f19601f8201169050808301925050508581038252898982818152602001925060200280828437600081840152601f19601f8201169050808301925050509f5050505050505050505050505050505060006040518083038186803b15801561518357600080fd5b505af4158015615197573d6000803e3d6000fd5b505050506151f284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508261971790919063ffffffff16565b601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63d7a8acc19091600b546040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b15801561524e57600080fd5b505af4158015615262573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff16600b547f1bfe527f3548d9258c2512b6689f0acfccdd0557d80a53845db25fc57e93d8fe8360060180549050344260405180848152602001838152602001828152602001935050505060405180910390a3600b549150509a9950505050505050505050565b6152ea615e3f565b61535c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600081116153d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4475726174696f6e206d757374206265206c6172676572207468616e2030000081525060200191505060405180910390fd5b60036002015481141561544d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4475726174696f6e20756e6368616e676564000000000000000000000000000081525060200191505060405180910390fd5b806003600201819055507f7819c8059302d1d66abc7fe228ecc02214e0bc5c529956c13717aabefce937d8816040518082815260200191505060405180910390a150565b60006060600060f673ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b602083106154e657805182526020820191506020810190506020830392506154c3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b6020831061554d578051825260208201915060208101905060208303925061552a565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146155ad576040519150601f19603f3d011682016040523d82523d6000602084013e6155b2565b606091505b50809350819250505080615611576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602381526020018061b8336023913960400191505060405180910390fd5b61561c826000619067565b92505050919050565b6060601780548060200260200160405190810160405280929190818152602001828054801561567357602002820191906000526020600020905b81548152602001906001019080831161565f575b5050505050905090565b600080600f600084815260200190815260200160002090506156b2816156ad60038461963f90919063ffffffff16565b61978f565b915050919050565b6156c2615e3f565b615734576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60006157fe436184c1565b905090565b60075481565b6000615826600f60008481526020019081526020016000206196fc565b9050919050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61585b615e3f565b6158cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008111615926576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061b6836026913960400191505060405180910390fd5b60075481141561599e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f646571756575654672657175656e637920756e6368616e67656400000000000081525060200191505060405180910390fd5b806007819055507f391e82aae76c653cd640ad1b6028e2ee39ca4f29b30152e3d0a9ddd7e1169c34816040518082815260200191505060405180910390a150565b6000806000905060006159f0615b35565b905060006159fc619449565b905060008090505b82811015615b29576000615a1782612ae1565b905060008373ffffffffffffffffffffffffffffffffffffffff166393c5c487836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015615a9857600080fd5b505afa158015615aac573d6000803e3d6000fd5b505050506040513d6020811015615ac257600080fd5b81019080805190602001909291905050509050615adf8883613cc0565b80615af05750615aef8882613cc0565b5b15615b0c57615b09600187618f5790919063ffffffff16565b95505b5050615b22600182618f5790919063ffffffff16565b9050615a04565b50829350505050919050565b60006060600060f973ffffffffffffffffffffffffffffffffffffffff1643604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b60208310615ba65780518252602082019150602081019050602083039250615b83565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114615c06576040519150601f19603f3d011682016040523d82523d6000602084013e615c0b565b606091505b50809350819250505080615c6a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603581526020018061b5ea6035913960400191505060405180910390fd5b615c75826000618c86565b9250505090565b60006060600060f773ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b60208310615cd15780518252602082019150602081019050602083039250615cae565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310615d385780518252602082019150602081019050602083039250615d15565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114615d98576040519150601f19603f3d011682016040523d82523d6000602084013e615d9d565b606091505b50809350819250505080615dfc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603181526020018061b7d76031913960400191505060405180910390fd5b615e07826000618c86565b92505050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60065481565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16615e81619819565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b615ea5615e3f565b615f17576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008111615f8d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f6d696e4465706f736974206d757374206265206c6172676572207468616e203081525060200191505060405180910390fd5b600c54811415616005576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f4d696e696d756d206465706f73697420756e6368616e6765640000000000000081525060200191505060405180910390fd5b80600c819055507fc50a7f0bdf88c216b2541b0bdea26f22305460e39ffc672ec1a7501732c5ba81816040518082815260200191505060405180910390a150565b600061605a6160558484619821565b619a73565b905092915050565b600061606d8261786e565b6160df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f50726f706f73616c206e6f74207175657565640000000000000000000000000081525060200191505060405180910390fd5b601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63757775999091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561613957600080fd5b505af415801561614d573d6000803e3d6000fd5b505050506040513d602081101561616357600080fd5b81019080805190602001909291905050509050919050565b616183615e3f565b6161f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000811161626b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4475726174696f6e206d757374206265206c6172676572207468616e2030000081525060200191505060405180910390fd5b6003600001548114156162e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4475726174696f6e20756e6368616e676564000000000000000000000000000081525060200191505060405180910390fd5b806003600001819055507fbc44c003a66b841b48c220869efb738b265af305649ac8bafe8efe0c8130e313816040518082815260200191505060405180910390a150565b6000616335436134b7565b905090565b60006060600060f973ffffffffffffffffffffffffffffffffffffffff1684604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b602083106163ab5780518252602082019150602081019050602083039250616388565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461640b576040519150601f19603f3d011682016040523d82523d6000602084013e616410565b606091505b5080935081925050508061646f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018061b38a602e913960400191505060405180910390fd5b61647a826000618c86565b92505050919050565b806011600082815260200190815260200160002060000160009054906101000a900460ff161561651b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f686f7466697820616c726561647920657865637574656400000000000000000081525060200191505060405180910390fd5b6165248261349b565b616579576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061b6ca6029913960400191505060405180910390fd5b600061658361632a565b9050806011600085815260200190815260200160002060010154106165f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061b73c6026913960400191505060405180910390fd5b80601160008581526020019081526020016000206001018190555080837f6f184ec313435b3307a4fe59e2293381f08419a87214464c875a2a247e8af5e060405160405180910390a3505050565b616649615e3f565b6166bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561675e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616e6e6f7420726567697374657220746865206e756c6c206164647265737381525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f27fe5f0c1c3b1ed427cc63d0f05759ffdecf9aec9e18d31ef366fc8a6cb5dc3b60405160405180910390a250565b601881815481106167f257fe5b906000526020600020016000915090505481565b6000600360010154905090565b6017818154811061682057fe5b906000526020600020016000915090505481565b600060018060008282540192505081905550600060015490506168556134d1565b600061685f619449565b73ffffffffffffffffffffffffffffffffffffffff16636642d594336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156168db57600080fd5b505afa1580156168ef573d6000803e3d6000fd5b505050506040513d602081101561690557600080fd5b810190808051906020019092919050505090506000601060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000160000154905060008114156169de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4163636f756e7420686173206e6f20686973746f726963616c207570766f746581525060200191505060405180910390fd5b6169e7816192ef565b50601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63bfc516389091836040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b158015616a4257600080fd5b505af4158015616a56573d6000803e3d6000fd5b505050506040513d6020811015616a6c57600080fd5b810190808051906020019092919050505015616c1057601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63239491ba909183616b4f8660000160010154601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63757775999091896040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b158015616b0657600080fd5b505af4158015616b1a573d6000803e3d6000fd5b505050506040513d6020811015616b3057600080fd5b810190808051906020019092919050505061901d90919063ffffffff16565b8b8b6040518663ffffffff1660e01b8152600401808681526020018581526020018481526020018381526020018281526020019550505050505060006040518083038186803b158015616ba157600080fd5b505af4158015616bb5573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff16817f7dc46237a819c9171a9c037ec98928e563892905c4d23373ca0f3f500f4ed11484600001600101546040518082815260200191505060405180910390a35b6040518060400160405280600081526020016000815250826000016000820151816000015560208201518160010155905050600194505050506001548114616cc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5092915050565b806011600082815260200190815260200160002060000160009054906101000a900460ff1615616d5f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f686f7466697820616c726561647920657865637574656400000000000000000081525060200191505060405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614616e22576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f6d73672e73656e646572206e6f7420617070726f76657200000000000000000081525060200191505060405180910390fd5b60016011600084815260200190815260200160002060000160016101000a81548160ff021916908315150217905550817f36bc158cba244a94dc9b8c08d327e8f7e3c2ab5f1925454c577527466f04851f60405160405180910390a25050565b806011600082815260200190815260200160002060000160009054906101000a900460ff1615616f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f686f7466697820616c726561647920657865637574656400000000000000000081525060200191505060405180910390fd5b60016011600084815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550817ff6d22d0b43a6753880b8f9511b82b86cd0fe349cd580bbe6a25b6dc063ef496f33604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25050565b6000601260000160020154905090565b6000600180600082825401925050819055506000600154905061701f6134d1565b60008061702c87876190f8565b9150915061703982618c9d565b61704857600093505050617693565b6000617052619449565b73ffffffffffffffffffffffffffffffffffffffff16636642d594336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156170ce57600080fd5b505afa1580156170e2573d6000803e3d6000fd5b505050506040513d60208110156170f857600080fd5b810190808051906020019092919050505090506000601060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000617158619544565b73ffffffffffffffffffffffffffffffffffffffff166330ec70f5846040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156171d457600080fd5b505afa1580156171e8573d6000803e3d6000fd5b505050506040513d60208110156171fe57600080fd5b8101908080519060200190929190505050905061721a856196fc565b61728c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f50726f706f73616c206e6f7420617070726f766564000000000000000000000081525060200191505060405180910390fd5b6003600581111561729957fe5b8460058111156172a557fe5b14617318576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e636f72726563742070726f706f73616c207374617465000000000000000081525060200191505060405180910390fd5b6000600381111561732557fe5b88600381111561733157fe5b14156173a5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f566f74652076616c756520756e7365740000000000000000000000000000000081525060200191505060405180910390fd5b6000811161741b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f566f74657220776569676874207a65726f00000000000000000000000000000081525060200191505060405180910390fd5b60008260030160008b8152602001908152602001600020905085735d3739f939b974ebeb80afd8f69764e8d78d79dc63b05cd27f90918360020154858f86600101541461746957600061747c565b8560000160009054906101000a900460ff165b8e6040518663ffffffff1660e01b8152600401808681526020018581526020018481526020018360038111156174ae57fe5b60ff1681526020018260038111156174c257fe5b60ff1681526020019550505050505060006040518083038186803b1580156174e957600080fd5b505af41580156174fd573d6000803e3d6000fd5b50505050617509619544565b73ffffffffffffffffffffffffffffffffffffffff166330a61d596040518163ffffffff1660e01b815260040160206040518083038186803b15801561754e57600080fd5b505afa158015617562573d6000803e3d6000fd5b505050506040513d602081101561757857600080fd5b8101908080519060200190929190505050866008018190555060405180606001604052808a60038111156175a857fe5b81526020018c8152602001838152508360030160008c815260200190815260200160002060008201518160000160006101000a81548160ff021916908360038111156175f057fe5b02179055506020820151816001015560408201518160020155905050826002015486600201541115617626578a83600201819055505b8373ffffffffffffffffffffffffffffffffffffffff168b7ff3709dc32cf1356da6b8a12a5be1401aeb00989556be7b16ae566e65fef7a9df8b600381111561766b57fe5b85604051808381526020018281526020019250505060405180910390a3600197505050505050505b600154811461770a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b509392505050565b60095481565b6000617735600f6000848152602001908152602001600020618ff8565b9050919050565b600060149054906101000a900460ff16156177bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f636f6e747261637420616c726561647920696e697469616c697a65640000000081525060200191505060405180910390fd5b6001600060146101000a81548160ff0219169083151502179055506177e333619a81565b6177ec8d616641565b6177f58c613233565b6177fe8b617a8c565b6178078a615e9d565b6178108961309a565b61781988615853565b6178228761617b565b61782b86617c9a565b617834856152e2565b61783d84613ae8565b61784683612cb6565b61784f826147ed565b6178588161287a565b4260098190555050505050505050505050505050565b6000601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63bfc516389091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156178ca57600080fd5b505af41580156178de573d6000803e3d6000fd5b505050506040513d60208110156178f457600080fd5b81019080805190602001909291905050508015617917575061791582617718565b155b9050919050565b6000806000806060617941600f6000888152602001908152602001600020619bc5565b808054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156179d65780601f106179ab576101008083540402835291602001916179d6565b820191906000526020600020905b8154815290600101906020018083116179b957829003601f168201915b505050505090509450945094509450945091939590929450565b600080600080617a186019600001604051806020016040529081600082015481525050619a73565b617a3a6019600101604051806020016040529081600082015481525050619a73565b617a5c6019600201604051806020016040529081600082015481525050619a73565b617a7e6019600301604051806020016040529081600082015481525050619a73565b935093509350935090919293565b617a94615e3f565b617b06576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008111617b5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061b3df602c913960400191505060405180910390fd5b600a54811415617bd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4e756d626572206f662070726f706f73616c7320756e6368616e67656400000081525060200191505060405180910390fd5b80600a819055507f85399b9b2595eb13c392e1638ca77730156cd8d48d4733df4db068e4aa6b93a6816040518082815260200191505060405180910390a150565b600080617c2361b0b6565b601060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001604051806040016040529081600082015481526020016001820154815250509050806000015181602001519250925050915091565b617ca2615e3f565b617d14576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008111617d8a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4475726174696f6e206d757374206265206c6172676572207468616e2030000081525060200191505060405180910390fd5b600360010154811415617e05576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4475726174696f6e20756e6368616e676564000000000000000000000000000081525060200191505060405180910390fd5b806003600101819055507f90290eb9b27055e686a69fb810bada5381e544d07b8270021da2d355a6c96ed6816040518082815260200191505060405180910390a150565b6000898989898989898989604051602001808060200180602001806020018060200186815260200185810385528e8e82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810384528c8c82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810383528a8a82818152602001925080828437600081840152601f19601f8201169050808301925050508581038252888882818152602001925060200280828437600081840152601f19601f8201169050808301925050509d50505050505050505050505050506040516020818303038152906040528051906020012090506000806000617f5b84612a52565b9250925092508115617fd5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f686f7466697820616c726561647920657865637574656400000000000000000081525060200191505060405180910390fd5b82618048576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f686f74666978206e6f7420617070726f7665640000000000000000000000000081525060200191505060405180910390fd5b61805061632a565b81146180a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061b3436026913960400191505060405180910390fd5b6181c56181c08e8e80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508d8d80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050336000619c1e565b619e47565b60016011600086815260200190815260200160002060000160006101000a81548160ff021916908315150217905550837f708a7934acb657a77a617b1fcd5f6d7d9ad592b72934841bff01acefd10f9b6360405160405180910390a250505050505050505050505050565b6000806060600f6000868152602001908152602001600020735d3739f939b974ebeb80afd8f69764e8d78d79dc63e6a5192f9091866040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b1580156182a057600080fd5b505af41580156182b4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060608110156182de57600080fd5b810190808051906020019092919080519060200190929190805164010000000081111561830a57600080fd5b8281019050602081018481111561832057600080fd5b815185600182028301116401000000008211171561833d57600080fd5b50509291905050509250925092509250925092565b600b5481565b60006060600060f873ffffffffffffffffffffffffffffffffffffffff166040516020016040516020818303038152906040526040518082805190602001908083835b602083106183be578051825260208201915060208101905060208303925061839b565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461841e576040519150601f19603f3d011682016040523d82523d6000602084013e618423565b606091505b50809350819250505080618482576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061b7626025913960400191505060405180910390fd5b61848d826000618c86565b9250505090565b60008060006184b4600f6000868152602001908152602001600020619e57565b9250925092509193909250565b600061850560036184f760026184e960026184db8861633a565b619e8190919063ffffffff16565b618f5790919063ffffffff16565b619f0790919063ffffffff16565b9050919050565b60008060008714158015618521575060008514155b618593576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f612064656e6f6d696e61746f72206973207a65726f000000000000000000000081525060200191505060405180910390fd5b6000806000606060fc73ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c6040516020018087815260200186815260200185815260200184815260200183815260200182815260200196505050505050506040516020818303038152906040526040518082805190602001908083835b6020831061862d578051825260208201915060208101905060208303925061860a565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461868d576040519150601f19603f3d011682016040523d82523d6000602084013e618692565b606091505b508092508193505050816186f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061b7156027913960400191505060405180910390fd5b6186fc816000618c86565b9350618709816020618c86565b925083839550955050505050965096945050505050565b618728615e3f565b61879a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561883d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f44657374696e6174696f6e2063616e6e6f74206265207a65726f00000000000081525060200191505060405180910390fd5b6969e10de76676d080000081118015618865575061886161885c619f51565b619a73565b8111155b6188ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252604881526020018061b4816048913960600191505060405180910390fd5b600060e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415618942576188ee81618c39565b600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001600082015181600001559050506189ea565b61894b81618c39565b600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020600082015181600001559050505b817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168373ffffffffffffffffffffffffffffffffffffffff167f60c5b4756af49d7b071b00dbf0f87af605cce11896ecd3b760d19f0f9d3fbcef836040518082815260200191505060405180910390a3505050565b618a65615e3f565b618ad7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b618ae081619a81565b50565b60006060600060f573ffffffffffffffffffffffffffffffffffffffff1684604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b60208310618b545780518252602082019150602081019050602083039250618b31565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114618bb4576040519150601f19603f3d011682016040523d82523d6000602084013e618bb9565b606091505b50809350819250505080618c18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061b7ab602c913960400191505060405180910390fd5b618c23826000619067565b92505050919050565b6000600360000154905090565b618c4161b077565b6040518060200160405280838152509050919050565b6000618c6a82618c65619f51565b619f77565b9050919050565b60008160000151836000015114905092915050565b6000618c928383619067565b60001c905092915050565b6000808260020154119050919050565b60006017805490508210618d0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b81526020018061b856602b913960400191505060405180910390fd5b618d1584618c9d565b8015618d3757508260178381548110618d2a57fe5b9060005260206000200154145b90509392505050565b6000618d4a61b077565b618da1618d9260196003016040518060200160405290816000820154815250506019600001604051806020016040529081600082015481525050619f8d90919063ffffffff16565b8461a3ec90919063ffffffff16565b905060008090505b8360060180549050811015618f13576000618e7b856006018381548110618dcc57fe5b90600052602060002090600302016002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015618e715780601f10618e4657610100808354040283529160200191618e71565b820191906000526020600020905b815481529060010190602001808311618e5457829003601f168201915b505050505061a4db565b9050618e8561b077565b618ecf866006018481548110618e9757fe5b906000526020600020906003020160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683619821565b9050618ee48185619f7790919063ffffffff16565b15618ef6576000945050505050618f1a565b5050618f0c600182618f5790919063ffffffff16565b9050618da9565b5060019150505b919050565b600080828481618f2b57fe5b0490506000838581618f3957fe5b061415618f495780915050618f51565b600181019150505b92915050565b600080828401905083811015618fd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000818310618fee5781618ff0565b825b905092915050565b60006190136006548360020154618f5790919063ffffffff16565b4210159050919050565b600061905f83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061a638565b905092915050565b600060208201835110156190e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f736c6963696e67206f7574206f662072616e676500000000000000000000000081525060200191505060405180910390fd5b60006020830184015190508091505092915050565b6000806000600f6000868152602001908152602001600020905061911d818686618cad565b61918f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f50726f706f73616c206e6f74206465717565756564000000000000000000000081525060200191505060405180910390fd5b60006191a560038361963f90919063ffffffff16565b90506191b1828261978f565b156191c2576191c18287876191d1565b5b81819350935050509250929050565b6191da836196fc565b80156191ea575060008360080154115b156191f9576191f88361a6f8565b5b60006017828154811061920857fe5b90600052602060002001819055506018819080600181540180825580915050906001820390600052602060002001600090919290919091505550600f6000838152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560018201600090556002820160009055600382016000808201600090556001820160009055600282016000905550506006820160006192bc919061b0d0565b6007820160006101000a81549060ff021916905560088201600090556009820160006192e8919061b0f4565b5050505050565b600080601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63bfc516389091856040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561934c57600080fd5b505af4158015619360573d6000803e3d6000fd5b505050506040513d602081101561937657600080fd5b81019080805190602001909291905050508015619398575061939783617718565b5b9050801561944057601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63eed5f7be9091856040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b1580156193fa57600080fd5b505af415801561940e573d6000803e3d6000fd5b50505050827f88e53c486703527139dfc8d97a1e559d9bd93d3f9d52cda4e06564111e7a264360405160405180910390a25b80915050919050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f4163636f756e74730000000000000000000000000000000000000000000000008152506008019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561950457600080fd5b505afa158015619518573d6000803e3d6000fd5b505050506040513d602081101561952e57600080fd5b8101908080519060200190929190505050905090565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f4c6f636b6564476f6c6400000000000000000000000000000000000000000000815250600a019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156195ff57600080fd5b505afa158015619613573d6000803e3d6000fd5b505050506040513d602081101561962957600080fd5b8101908080519060200190929190505050905090565b600080619689836002015461967b856001015461966d87600001548960020154618f5790919063ffffffff16565b618f5790919063ffffffff16565b618f5790919063ffffffff16565b905080421061969c5760059150506196f6565b6196b383600201548261901d90919063ffffffff16565b90508042106196c65760049150506196f6565b6196dd83600101548261901d90919063ffffffff16565b90508042106196f05760039150506196f6565b60029150505b92915050565b60008160070160009054906101000a900460ff169050919050565b600081511415619772576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061b4316029913960400191505060405180910390fd5b8082600901908051906020019061978a92919061b13c565b505050565b60006004600581111561979e57fe5b8260058111156197aa57fe5b11806197de5750600360058111156197be57fe5b8260058111156197ca57fe5b1180156197dd57506197db83618d40565b155b5b806198115750600260058111156197f157fe5b8260058111156197fd57fe5b118015619810575061980e836196fc565b155b5b905092915050565b600033905090565b61982961b077565b61983161b077565b6198446969e10de76676d0800000618c39565b905060006198f6600e60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020604051806020016040529081600082015481525050619a73565b146199a857600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020016000206040518060200160405290816000820154815250509050619a69565b6000619a09600e60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001604051806020016040529081600082015481525050619a73565b14619a6857600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160405180602001604052908160008201548152505090505b5b8091505092915050565b600081600001519050919050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415619b07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061b40b6026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008060008060008560000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16866001015487600201548860060180549050896009018090509450945094509450945091939590929450565b619c2661b1bc565b85518751148015619c38575083518651145b619caa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4172726179206c656e677468206d69736d61746368000000000000000000000081525060200191505060405180910390fd5b600087519050619cb861b1bc565b84816000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508381602001818152505042816040018181525050600080905082604051908082528060200260200182016040528015619d4357816020015b619d3061b21f565b815260200190600190039081619d285790505b50826080018190525060008090505b83811015619e365760405180606001604052808c8381518110619d7157fe5b602002602001015181526020018b8381518110619d8a57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff168152602001619dd5848b8581518110619dbd57fe5b60200260200101518d61a88e9092919063ffffffff16565b81525083608001518281518110619de857fe5b6020026020010181905250619e19888281518110619e0257fe5b602002602001015183618f5790919063ffffffff16565b9150619e2f600182618f5790919063ffffffff16565b9050619d52565b508193505050509695505050505050565b619e54816080015161a91a565b50565b60008060008360030160000154846003016001015485600301600201549250925092509193909250565b600080831415619e945760009050619f01565b6000828402905082848281619ea557fe5b0414619efc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061b6a96021913960400191505060405180910390fd5b809150505b92915050565b6000619f4983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061aa23565b905092915050565b619f5961b077565b604051806020016040528069d3c21bcecceda1000000815250905090565b6000816000015183600001511115905092915050565b619f9561b077565b600083600001511480619fac575060008260000151145b15619fc85760405180602001604052806000815250905061a3e6565b69d3c21bcecceda100000082600001511415619fe65782905061a3e6565b69d3c21bcecceda10000008360000151141561a0045781905061a3e6565b600069d3c21bcecceda100000061a01a8561aae9565b600001518161a02557fe5b049050600061a0338561ab20565b600001519050600069d3c21bcecceda100000061a04f8661aae9565b600001518161a05a57fe5b049050600061a0688661ab20565b600001519050600082850290506000851461a0fc578285828161a08757fe5b041461a0fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783179312064657465637465640000000000000000000081525060200191505060405180910390fd5b5b600069d3c21bcecceda1000000820290506000821461a19e5769d3c21bcecceda100000082828161a12957fe5b041461a19d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6f766572666c6f772078317931202a206669786564312064657465637465640081525060200191505060405180910390fd5b5b809150600084860290506000861461a22f578486828161a1ba57fe5b041461a22e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783279312064657465637465640000000000000000000081525060200191505060405180910390fd5b5b600084880290506000881461a2bd578488828161a24857fe5b041461a2bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783179322064657465637465640000000000000000000081525060200191505060405180910390fd5b5b61a2c561ab5d565b878161a2cd57fe5b04965061a2d861ab5d565b858161a2e057fe5b049450600085880290506000881461a371578588828161a2fc57fe5b041461a370576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783279322064657465637465640000000000000000000081525060200191505060405180910390fd5b5b61a37961b077565b604051806020016040528087815250905061a3a28160405180602001604052808781525061ab6a565b905061a3bc8160405180602001604052808681525061ab6a565b905061a3d68160405180602001604052808581525061ab6a565b9050809a50505050505050505050505b92915050565b61a3f461b077565b600083600301600001549050600081141561a41b5761a413600061ac13565b91505061a4d5565b600084600301600101549050600061a455866003016002015461a4478486618f5790919063ffffffff16565b618f5790919063ffffffff16565b9050600061a48061a47b61a46c896008015461ac13565b88619f8d90919063ffffffff16565b61ac9d565b90508181111561a4b25761a4af61a4a0838361901d90919063ffffffff16565b84618f5790919063ffffffff16565b92505b61a4ce8461a4c98587618f5790919063ffffffff16565b61acbe565b9450505050505b92915050565b600060188260038151811061a4ec57fe5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c60108360028151811061a54957fe5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c60088460018151811061a5a657fe5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c8460008151811061a60157fe5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161717179050919050565b600083831115829061a6e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561a6aa57808201518184015260208101905061a68f565b50505050905090810190601f16801561a6d75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b61a70061b077565b61a7098261ad00565b905061a71361b077565b61a73f601960020160405180602001604052908160008201548152505083619f8d90919063ffffffff16565b905061a74961b077565b61a7a761a77f601960020160405180602001604052908160008201548152505061a771619f51565b61ad5c90919063ffffffff16565b6019600001604051806020016040529081600082015481525050619f8d90919063ffffffff16565b905061a7bc818361ab6a90919063ffffffff16565b60196000016000820151816000015590505061a8136019600101604051806020016040529081600082015481525050601960000160405180602001604052908160008201548152505061ae0390919063ffffffff16565b1561a8305760196001016019600001600082015481600001559050505b7f51131d2820f04a6b6edd20e22a07d5bf847e265a3906e85256fca7d6043417c561a8736019600001604051806020016040529081600082015481525050619a73565b6040518082815260200191505060405180910390a150505050565b60608183018451101561a8a057600080fd5b606082156000811461a8bd5760405191506020820160405261a90e565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561a8fb578051835260208301925060208101905061a8de565b50868552601f19601f8301166040525050505b50809150509392505050565b60008090505b815181101561aa1f5761a99282828151811061a93857fe5b60200260200101516020015183838151811061a95057fe5b60200260200101516000015184848151811061a96857fe5b6020026020010151604001515185858151811061a98157fe5b60200260200101516040015161ae18565b61aa04576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f50726f706f73616c20657865637574696f6e206661696c65640000000000000081525060200191505060405180910390fd5b61aa18600182618f5790919063ffffffff16565b905061a920565b5050565b6000808311829061aacf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561aa9457808201518184015260208101905061aa79565b50505050905090810190601f16801561aac15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161aadb57fe5b049050809150509392505050565b61aaf161b077565b604051806020016040528069d3c21bcecceda10000008085600001518161ab1457fe5b04028152509050919050565b61ab2861b077565b604051806020016040528069d3c21bcecceda10000008085600001518161ab4b57fe5b04028460000151038152509050919050565b600064e8d4a51000905090565b61ab7261b077565b600082600001518460000151019050836000015181101561abfb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f616464206f766572666c6f77206465746563746564000000000000000000000081525060200191505060405180910390fd5b60405180602001604052808281525091505092915050565b61ac1b61b077565b61ac2361aec4565b82111561ac7b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061b54e6036913960400191505060405180910390fd5b604051806020016040528069d3c21bcecceda100000084028152509050919050565b600069d3c21bcecceda100000082600001518161acb657fe5b049050919050565b61acc661b077565b61acce61b077565b61acd78461ac13565b905061ace161b077565b61acea8461ac13565b905061acf6828261aee3565b9250505092915050565b61ad0861b077565b600061ad44836003016002015461ad3685600301600101548660030160000154618f5790919063ffffffff16565b618f5790919063ffffffff16565b905061ad5481846008015461acbe565b915050919050565b61ad6461b077565b81600001518360000151101561ade2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f737562737472616374696f6e20756e646572666c6f772064657465637465640081525060200191505060405180910390fd5b60405180602001604052808360000151856000015103815250905092915050565b60008160000151836000015110905092915050565b600080600084111561aea05761ae2d8661b02c565b61ae9f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b5b6040516020840160008287838a8c6187965a03f19250505080915050949350505050565b60007601357c299a88ea76a58924d52ce4f26a85af186c2b9e74905090565b61aeeb61b077565b60008260000151141561af66576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f63616e277420646976696465206279203000000000000000000000000000000081525060200191505060405180910390fd5b600069d3c21bcecceda10000008460000151029050836000015169d3c21bcecceda1000000828161af9357fe5b041461b007576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6f766572666c6f7720617420646976696465000000000000000000000000000081525060200191505060405180910390fd5b60405180602001604052808460000151838161b01f57fe5b0481525091505092915050565b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561b06e57506000801b8214155b92505050919050565b6040518060200160405280600081525090565b81548183558181111561b0b15781836000526020600020918201910161b0b0919061b256565b5b505050565b604051806040016040528060008152602001600081525090565b508054600082556003029060005260206000209081019061b0f1919061b27b565b50565b50805460018160011615610100020316600290046000825580601f1061b11a575061b139565b601f01602090049060005260206000209081019061b138919061b256565b5b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061b17d57805160ff191683800117855561b1ab565b8280016001018555821561b1ab579182015b8281111561b1aa57825182559160200191906001019061b18f565b5b50905061b1b8919061b256565b5090565b604051806101400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200161b1fb61b2d9565b81526020016060815260200160001515815260200160008152602001606081525090565b604051806060016040528060008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b61b27891905b8082111561b27457600081600090555060010161b25c565b5090565b90565b61b2d691905b8082111561b2d2576000808201600090556001820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560028201600061b2c9919061b2fa565b5060030161b281565b5090565b90565b60405180606001604052806000815260200160008152602001600081525090565b50805460018160011615610100020316600290046000825580601f1061b320575061b33f565b601f01602090049060005260206000209081019061b33e919061b256565b5b5056fe686f74666978206d75737420626520707265706172656420666f7220746869732065706f63685175657565457870697279206d757374206265206c6172676572207468616e20306572726f722063616c6c696e67206e756d62657256616c696461746f7273496e53657420707265636f6d70696c6550617274696369706174696f6e20626173656c696e652067726561746572207468616e206f6e654e756d626572206f662070726f706f73616c73206d757374206265206c6172676572207468616e207a65726f4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734465736372697074696f6e2075726c206d7573742068617665206e6f6e2d7a65726f206c656e677468426173656c696e652071756f72756d20666163746f722067726561746572207468616e206f6e655468726573686f6c642068617320746f2062652067726561746572207468616e206d616a6f7269747920616e64206e6f742067726561746572207468616e20756e616e696d69747950617274696369706174696f6e20626173656c696e6520666c6f6f7220756e6368616e676564426173656c696e652075706461746520666163746f722067726561746572207468616e206f6e656572726f722063616c6c696e672067657456657269666965645365616c4269746d617046726f6d48656164657220707265636f6d70696c6563616e277420637265617465206669786964697479206e756d626572206c6172676572207468616e206d61784e65774669786564282963616e6e6f74207570766f746520612070726f706f73616c206e6f7420696e207468652071756575656572726f722063616c6c696e672076616c696461746f725369676e65724164647265737346726f6d43757272656e7453657420707265636f6d70696c656572726f722063616c6c696e67206e756d62657256616c696461746f7273496e43757272656e7453657420707265636f6d70696c656572726f722063616c6c696e672076616c696461746f725369676e65724164647265737346726f6d53657420707265636f6d70696c6550726f706f73616c206e6f7420696e20657865637574696f6e207374616765206f72206e6f742070617373696e67646571756575654672657175656e6379206d757374206265206c6172676572207468616e2030536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77686f74666978206e6f742077686974656c69737465642062792032662b312076616c696461746f727363616e6e6f74207570766f746520776974686f7574206c6f636b696e6720676f6c646572726f722063616c6c696e67206672616374696f6e4d756c45787020707265636f6d70696c65686f7466697820616c726561647920707265706172656420666f7220746869732065706f63686572726f722063616c6c696e672067657445706f636853697a6520707265636f6d70696c6550617274696369706174696f6e20666c6f6f722067726561746572207468616e206f6e656572726f722063616c6c696e6720676574506172656e745365616c4269746d617020707265636f6d70696c656572726f722063616c6c696e6720676574426c6f636b4e756d62657246726f6d48656164657220707265636f6d70696c6563616e6e6f74207570766f7465206d6f7265207468616e206f6e65207175657565642070726f706f73616c6572726f722063616c6c696e67206861736848656164657220707265636f6d70696c6550726f766964656420696e6465782067726561746572207468616e2064657175657565206c656e6774682ea165627a7a723058207b7eeaf07f3051263d12b6f049a82d8c38da16b42ee8d96d5dfbf06b9473aa5b0029

Deployed ByteCode

0x6080604052600436106104cb5760003560e01c80637b10399911610276578063b8f770051161014f578063cf48eb94116100c1578063e50e652d11610085578063e50e652d14612517578063ec68307214612566578063ed385274146125ee578063f2fde38b14612672578063fae8db0a146126c3578063ffea74c014612712576104cb565b8063cf48eb94146121dd578063d704f0c51461236c578063da35c66414612464578063df4da4611461248f578063e41db455146124ba576104cb565b8063c73a6d7811610113578063c73a6d7814611f6c578063c7f758a814611fbf578063c805956d146120bb578063c8d8d2b5146120fb578063cd845a7614612136578063cea69e74146121a2576104cb565b8063b8f7700514611d79578063bbb2eab914611da4578063c0aee5f414611e0e578063c134b2fc14611e39578063c1939b2014611e8c576104cb565b80639a6c3d83116101e8578063aa2feb83116101ac578063aa2feb8314611bdd578063ad78c10914611c2c578063add004df14611c57578063af108a0e14611ca6578063b0f9984214611d03578063b15f0f5814611d3e576104cb565b80639a6c3d8314611a9c5780639a7b3be714611ad75780639b2b592f14611b025780639cb02dfc14611b51578063a91ee0dc14611b8c576104cb565b80638da5cb5b1161023a5780638da5cb5b146118d35780638e905ed61461192a5780638f32d59b146119555780638fcc9cfb1461198457806397b9eba6146119bf57806398f4270214611a4d576104cb565b80637b103999146116eb5780638018556e1461174257806381d4728d1461177d57806387ee8a0f146117cc5780638a883626146117f7576104cb565b80633fa5fed0116103a85780635f8dd6491161031a5780636de8a63b116102de5780636de8a63b1461156c5780636f2ab693146115d8578063715018a61461162b5780637385e5da1461164257806377d26a2a1461166d5780637910867b14611698576104cb565b80635f8dd649146111a657806360b4d34d1461120f57806365bbdaa0146112745780636643ac581461145557806367960e9114611490576104cb565b8063573339781161036c5780635733397814610f4f578063582ae53b14610fb65780635c759394146110135780635d180adb1461104e5780635d35a3d9146110d35780635f115a8514611130576104cb565b80633fa5fed014610d1357806341b3d18514610d8657806345a7849914610db15780634b2c2f4414610e165780635601eaea14610ef2576104cb565b806323f0ab65116104415780633156560e116104055780633156560e14610b9f578063344944cf14610bf05780633b1eb4bf14610c435780633bb0ed2b14610c925780633ccfd60b14610ca95780633db9dd9a14610cd8576104cb565b806323f0ab65146108ea5780632762132114610a81578063283aaefb14610ad45780632c05235514610b3957806330a095d014610b74576104cb565b8063123633ea11610493578063123633ea146106fe5780631374b22d14610779578063141a8dd8146107cc578063152b483414610823578063158ef93e146108805780631c65bc61146108af576104cb565b806301fce27e1461054657806304acaec9146105fa5780630e0b78ae146106355780630f717e421461069a5780631201a0fb146106d3575b60008036905014610544576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f756e6b6e6f776e206d6574686f6400000000000000000000000000000000000081525060200191505060405180910390fd5b005b34801561055257600080fd5b5061055b61273d565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156105a2578082015181840152602081019050610587565b50505050905001838103825284818151815260200191508051906020019060200280838360005b838110156105e45780820151818401526020810190506105c9565b5050505090500194505050505060405180910390f35b34801561060657600080fd5b506106336004803603602081101561061d57600080fd5b810190808035906020019092919050505061287a565b005b34801561064157600080fd5b5061066e6004803603602081101561065857600080fd5b8101908080359060200190929190505050612a52565b604051808415151515815260200183151515158152602001828152602001935050505060405180910390f35b3480156106a657600080fd5b506106af612ac3565b60405180848152602001838152602001828152602001935050505060405180910390f35b3480156106df57600080fd5b506106e8612adb565b6040518082815260200191505060405180910390f35b34801561070a57600080fd5b506107376004803603602081101561072157600080fd5b8101908080359060200190929190505050612ae1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561078557600080fd5b506107b26004803603602081101561079c57600080fd5b8101908080359060200190929190505050612c32565b604051808215151515815260200191505060405180910390f35b3480156107d857600080fd5b506107e1612c56565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561082f57600080fd5b506108666004803603604081101561084657600080fd5b810190808035906020019092919080359060200190929190505050612c7c565b604051808215151515815260200191505060405180910390f35b34801561088c57600080fd5b50610895612ca3565b604051808215151515815260200191505060405180910390f35b3480156108bb57600080fd5b506108e8600480360360208110156108d257600080fd5b8101908080359060200190929190505050612cb6565b005b3480156108f657600080fd5b50610a676004803603606081101561090d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561094a57600080fd5b82018360208201111561095c57600080fd5b8035906020019184600183028401116401000000008311171561097e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290803590602001906401000000008111156109e157600080fd5b8201836020820111156109f357600080fd5b80359060200191846001830284011164010000000083111715610a1557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050612e71565b604051808215151515815260200191505060405180910390f35b348015610a8d57600080fd5b50610aba60048036036020811015610aa457600080fd5b810190808035906020019092919050505061302a565b604051808215151515815260200191505060405180910390f35b348015610ae057600080fd5b50610b2360048036036020811015610af757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061304e565b6040518082815260200191505060405180910390f35b348015610b4557600080fd5b50610b7260048036036020811015610b5c57600080fd5b810190808035906020019092919050505061309a565b005b348015610b8057600080fd5b50610b89613226565b6040518082815260200191505060405180910390f35b348015610bab57600080fd5b50610bee60048036036020811015610bc257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613233565b005b348015610bfc57600080fd5b50610c2960048036036020811015610c1357600080fd5b810190808035906020019092919050505061349b565b604051808215151515815260200191505060405180910390f35b348015610c4f57600080fd5b50610c7c60048036036020811015610c6657600080fd5b81019080803590602001909291905050506134b7565b6040518082815260200191505060405180910390f35b348015610c9e57600080fd5b50610ca76134d1565b005b348015610cb557600080fd5b50610cbe61387c565b604051808215151515815260200191505060405180910390f35b348015610ce457600080fd5b50610d1160048036036020811015610cfb57600080fd5b8101908080359060200190929190505050613ae8565b005b348015610d1f57600080fd5b50610d6c60048036036040811015610d3657600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613cc0565b604051808215151515815260200191505060405180910390f35b348015610d9257600080fd5b50610d9b613d2b565b6040518082815260200191505060405180910390f35b348015610dbd57600080fd5b50610dea60048036036020811015610dd457600080fd5b8101908080359060200190929190505050613d31565b604051808415151515815260200183151515158152602001828152602001935050505060405180910390f35b348015610e2257600080fd5b50610edc60048036036020811015610e3957600080fd5b8101908080359060200190640100000000811115610e5657600080fd5b820183602082011115610e6857600080fd5b80359060200191846001830284011164010000000083111715610e8a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050613d75565b6040518082815260200191505060405180910390f35b348015610efe57600080fd5b50610f3560048036036040811015610f1557600080fd5b810190808035906020019092919080359060200190929190505050613f09565b604051808215151515815260200191505060405180910390f35b348015610f5b57600080fd5b50610f9c60048036036060811015610f7257600080fd5b810190808035906020019092919080359060200190929190803590602001909291905050506140f4565b604051808215151515815260200191505060405180910390f35b348015610fc257600080fd5b50610fef60048036036020811015610fd957600080fd5b8101908080359060200190929190505050614789565b60405180826005811115610fff57fe5b60ff16815260200191505060405180910390f35b34801561101f57600080fd5b5061104c6004803603602081101561103657600080fd5b81019080803590602001909291905050506147ed565b005b34801561105a57600080fd5b506110916004803603604081101561107157600080fd5b8101908080359060200190929190803590602001909291905050506149c5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156110df57600080fd5b50611116600480360360408110156110f657600080fd5b810190808035906020019092919080359060200190929190505050614b17565b604051808215151515815260200191505060405180910390f35b34801561113c57600080fd5b506111896004803603604081101561115357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050614dfc565b604051808381526020018281526020019250505060405180910390f35b3480156111b257600080fd5b506111f5600480360360208110156111c957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614e84565b604051808215151515815260200191505060405180910390f35b34801561121b57600080fd5b5061125e6004803603602081101561123257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050614f4e565b6040518082815260200191505060405180910390f35b61143f600480360360a081101561128a57600080fd5b81019080803590602001906401000000008111156112a757600080fd5b8201836020820111156112b957600080fd5b803590602001918460208302840111640100000000831117156112db57600080fd5b9091929391929390803590602001906401000000008111156112fc57600080fd5b82018360208201111561130e57600080fd5b8035906020019184602083028401116401000000008311171561133057600080fd5b90919293919293908035906020019064010000000081111561135157600080fd5b82018360208201111561136357600080fd5b8035906020019184600183028401116401000000008311171561138557600080fd5b9091929391929390803590602001906401000000008111156113a657600080fd5b8201836020820111156113b857600080fd5b803590602001918460208302840111640100000000831117156113da57600080fd5b9091929391929390803590602001906401000000008111156113fb57600080fd5b82018360208201111561140d57600080fd5b8035906020019184600183028401116401000000008311171561142f57600080fd5b9091929391929390505050614f66565b6040518082815260200191505060405180910390f35b34801561146157600080fd5b5061148e6004803603602081101561147857600080fd5b81019080803590602001909291905050506152e2565b005b34801561149c57600080fd5b50611556600480360360208110156114b357600080fd5b81019080803590602001906401000000008111156114d057600080fd5b8201836020820111156114e257600080fd5b8035906020019184600183028401116401000000008311171561150457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050615491565b6040518082815260200191505060405180910390f35b34801561157857600080fd5b50611581615625565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156115c45780820151818401526020810190506115a9565b505050509050019250505060405180910390f35b3480156115e457600080fd5b50611611600480360360208110156115fb57600080fd5b810190808035906020019092919050505061567d565b604051808215151515815260200191505060405180910390f35b34801561163757600080fd5b506116406156ba565b005b34801561164e57600080fd5b506116576157f3565b6040518082815260200191505060405180910390f35b34801561167957600080fd5b50611682615803565b6040518082815260200191505060405180910390f35b3480156116a457600080fd5b506116d1600480360360208110156116bb57600080fd5b8101908080359060200190929190505050615809565b604051808215151515815260200191505060405180910390f35b3480156116f757600080fd5b5061170061582d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561174e57600080fd5b5061177b6004803603602081101561176557600080fd5b8101908080359060200190929190505050615853565b005b34801561178957600080fd5b506117b6600480360360208110156117a057600080fd5b81019080803590602001909291905050506159df565b6040518082815260200191505060405180910390f35b3480156117d857600080fd5b506117e1615b35565b6040518082815260200191505060405180910390f35b34801561180357600080fd5b506118bd6004803603602081101561181a57600080fd5b810190808035906020019064010000000081111561183757600080fd5b82018360208201111561184957600080fd5b8035906020019184600183028401116401000000008311171561186b57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050615c7c565b6040518082815260200191505060405180910390f35b3480156118df57600080fd5b506118e8615e10565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561193657600080fd5b5061193f615e39565b6040518082815260200191505060405180910390f35b34801561196157600080fd5b5061196a615e3f565b604051808215151515815260200191505060405180910390f35b34801561199057600080fd5b506119bd600480360360208110156119a757600080fd5b8101908080359060200190929190505050615e9d565b005b3480156119cb57600080fd5b50611a37600480360360408110156119e257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050616046565b6040518082815260200191505060405180910390f35b348015611a5957600080fd5b50611a8660048036036020811015611a7057600080fd5b8101908080359060200190929190505050616062565b6040518082815260200191505060405180910390f35b348015611aa857600080fd5b50611ad560048036036020811015611abf57600080fd5b810190808035906020019092919050505061617b565b005b348015611ae357600080fd5b50611aec61632a565b6040518082815260200191505060405180910390f35b348015611b0e57600080fd5b50611b3b60048036036020811015611b2557600080fd5b810190808035906020019092919050505061633a565b6040518082815260200191505060405180910390f35b348015611b5d57600080fd5b50611b8a60048036036020811015611b7457600080fd5b8101908080359060200190929190505050616483565b005b348015611b9857600080fd5b50611bdb60048036036020811015611baf57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050616641565b005b348015611be957600080fd5b50611c1660048036036020811015611c0057600080fd5b81019080803590602001909291905050506167e5565b6040518082815260200191505060405180910390f35b348015611c3857600080fd5b50611c41616806565b6040518082815260200191505060405180910390f35b348015611c6357600080fd5b50611c9060048036036020811015611c7a57600080fd5b8101908080359060200190929190505050616813565b6040518082815260200191505060405180910390f35b348015611cb257600080fd5b50611ce960048036036040811015611cc957600080fd5b810190808035906020019092919080359060200190929190505050616834565b604051808215151515815260200191505060405180910390f35b348015611d0f57600080fd5b50611d3c60048036036020811015611d2657600080fd5b8101908080359060200190929190505050616cc7565b005b348015611d4a57600080fd5b50611d7760048036036020811015611d6157600080fd5b8101908080359060200190929190505050616e82565b005b348015611d8557600080fd5b50611d8e616fee565b6040518082815260200191505060405180910390f35b348015611db057600080fd5b50611df460048036036060811015611dc757600080fd5b810190808035906020019092919080359060200190929190803560ff169060200190929190505050616ffe565b604051808215151515815260200191505060405180910390f35b348015611e1a57600080fd5b50611e23617712565b6040518082815260200191505060405180910390f35b348015611e4557600080fd5b50611e7260048036036020811015611e5c57600080fd5b8101908080359060200190929190505050617718565b604051808215151515815260200191505060405180910390f35b348015611e9857600080fd5b50611f6a60048036036101a0811015611eb057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919050505061773c565b005b348015611f7857600080fd5b50611fa560048036036020811015611f8f57600080fd5b810190808035906020019092919050505061786e565b604051808215151515815260200191505060405180910390f35b348015611fcb57600080fd5b50611ff860048036036020811015611fe257600080fd5b810190808035906020019092919050505061791e565b604051808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200185815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561207c578082015181840152602081019050612061565b50505050905090810190601f1680156120a95780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b3480156120c757600080fd5b506120d06179f0565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b34801561210757600080fd5b506121346004803603602081101561211e57600080fd5b8101908080359060200190929190505050617a8c565b005b34801561214257600080fd5b506121856004803603602081101561215957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050617c18565b604051808381526020018281526020019250505060405180910390f35b3480156121ae57600080fd5b506121db600480360360208110156121c557600080fd5b8101908080359060200190929190505050617c9a565b005b3480156121e957600080fd5b5061236a600480360360a081101561220057600080fd5b810190808035906020019064010000000081111561221d57600080fd5b82018360208201111561222f57600080fd5b8035906020019184602083028401116401000000008311171561225157600080fd5b90919293919293908035906020019064010000000081111561227257600080fd5b82018360208201111561228457600080fd5b803590602001918460208302840111640100000000831117156122a657600080fd5b9091929391929390803590602001906401000000008111156122c757600080fd5b8201836020820111156122d957600080fd5b803590602001918460018302840111640100000000831117156122fb57600080fd5b90919293919293908035906020019064010000000081111561231c57600080fd5b82018360208201111561232e57600080fd5b8035906020019184602083028401116401000000008311171561235057600080fd5b909192939192939080359060200190929190505050617e49565b005b34801561237857600080fd5b506123af6004803603604081101561238f57600080fd5b810190808035906020019092919080359060200190929190505050618230565b604051808481526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561242757808201518184015260208101905061240c565b50505050905090810190601f1680156124545780820380516001836020036101000a031916815260200191505b5094505050505060405180910390f35b34801561247057600080fd5b50612479618352565b6040518082815260200191505060405180910390f35b34801561249b57600080fd5b506124a4618358565b6040518082815260200191505060405180910390f35b3480156124c657600080fd5b506124f3600480360360208110156124dd57600080fd5b8101908080359060200190929190505050618494565b60405180848152602001838152602001828152602001935050505060405180910390f35b34801561252357600080fd5b506125506004803603602081101561253a57600080fd5b81019080803590602001909291905050506184c1565b6040518082815260200191505060405180910390f35b34801561257257600080fd5b506125d1600480360360c081101561258957600080fd5b8101908080359060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919050505061850c565b604051808381526020018281526020019250505060405180910390f35b3480156125fa57600080fd5b506126706004803603606081101561261157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919080359060200190929190505050618720565b005b34801561267e57600080fd5b506126c16004803603602081101561269557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050618a5d565b005b3480156126cf57600080fd5b506126fc600480360360208110156126e657600080fd5b8101908080359060200190929190505050618ae3565b6040518082815260200191505060405180910390f35b34801561271e57600080fd5b50612727618c2c565b6040518082815260200191505060405180910390f35b606080601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd6369b317e390916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b15801561279257600080fd5b505af41580156127a6573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060408110156127d057600080fd5b8101908080516401000000008111156127e857600080fd5b828101905060208101848111156127fe57600080fd5b815185602082028301116401000000008211171561281b57600080fd5b5050929190602001805164010000000081111561283757600080fd5b8281019050602081018481111561284d57600080fd5b815185602082028301116401000000008211171561286a57600080fd5b5050929190505050915091509091565b612882615e3f565b6128f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6128fc61b077565b61290582618c39565b905061291081618c57565b612965576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061b45a6027913960400191505060405180910390fd5b612991601960030160405180602001604052908160008201548152505082618c7190919063ffffffff16565b15612a04576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f426173656c696e652071756f72756d20666163746f7220756e6368616e67656481525060200191505060405180910390fd5b806019600301600082015181600001559050507fddfdbe55eaaa70fe2b8bc82a9b0734c25cabe7cb6f1457f9644019f0b5ff91fc826040518082815260200191505060405180910390a15050565b60008060006011600085815260200190815260200160002060000160019054906101000a900460ff166011600086815260200190815260200160002060000160009054906101000a900460ff1660116000878152602001908152602001600020600101549250925092509193909250565b60038060000154908060010154908060020154905083565b600a5481565b60006060600060fa73ffffffffffffffffffffffffffffffffffffffff16844360405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310612b5a5780518252602082019150602081019050602083039250612b37565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114612bba576040519150601f19603f3d011682016040523d82523d6000602084013e612bbf565b606091505b50809350819250505080612c1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603d81526020018061b5ad603d913960400191505060405180910390fd5b612c29826000618c86565b92505050919050565b6000612c4f600f6000848152602001908152602001600020618c9d565b9050919050565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000612c9b600f60008581526020019081526020016000208484618cad565b905092915050565b600060149054906101000a900460ff1681565b612cbe615e3f565b612d30576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b612d3861b077565b612d4182618c39565b9050612d4c81618c57565b612da1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061b7876024913960400191505060405180910390fd5b612dcd601960010160405180602001604052908160008201548152505082618c7190919063ffffffff16565b15612e23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061b4c96026913960400191505060405180910390fd5b806019600101600082015181600001559050507f122a37b609e0f758b6a23c43506cb567017a4d18b21fa91312fb42b44975a5b5826040518082815260200191505060405180910390a15050565b60008060fb73ffffffffffffffffffffffffffffffffffffffff16858585604051602001808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660601b815260140183805190602001908083835b60208310612efa5780518252602082019150602081019050602083039250612ed7565b6001836020036101000a03801982511681845116808217855250505050505090500182805190602001908083835b60208310612f4b5780518252602082019150602081019050602083039250612f28565b6001836020036101000a03801982511681845116808217855250505050505090500193505050506040516020818303038152906040526040518082805190602001908083835b60208310612fb45780518252602082019150602081019050602083039250612f91565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613014576040519150601f19603f3d011682016040523d82523d6000602084013e613019565b606091505b505080915050809150509392505050565b6000613047600f6000848152602001908152602001600020618d40565b9050919050565b6000601060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201549050919050565b6130a2615e3f565b613114576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000811161316d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061b3696021913960400191505060405180910390fd5b6006548114156131e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f517565756545787069727920756e6368616e676564000000000000000000000081525060200191505060405180910390fd5b806006819055507f4ecbf0bb0701615e2d6f9b0a0996056c959fe359ce76aa7ce06c5f1d57dae4d7816040518082815260200191505060405180910390a150565b6000600360020154905090565b61323b615e3f565b6132ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613350576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f417070726f7665722063616e6e6f74206265203000000000000000000000000081525060200191505060405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613414576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f417070726f76657220756e6368616e676564000000000000000000000000000081525060200191505060405180910390fd5b80600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fa03757d836cb0b61c0fbba2147f5d51d6071ff3dd5bf6963beb55563d64878e160405160405180910390a250565b60006134a56157f3565b6134ae836159df565b10159050919050565b60006134ca826134c5618358565b618f1f565b9050919050565b6134e8600754600954618f5790919063ffffffff16565b421061387a576000613504600a54601260000160020154618fdf565b90506060601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd6377b024799091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b15801561356257600080fd5b505af4158015613576573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156135a057600080fd5b8101908080516401000000008111156135b857600080fd5b828101905060208101848111156135ce57600080fd5b81518560208202830111640100000000821117156135eb57600080fd5b5050929190505050905060008090505b8281101561386f57600082828151811061361157fe5b602002602001015190506000600f6000838152602001908152602001600020905061363b81618ff8565b1561367457817f88e53c486703527139dfc8d97a1e559d9bd93d3f9d52cda4e06564111e7a264360405160405180910390a25050613854565b6136ee8160010154600d60008460000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054618f5790919063ffffffff16565b600d60008360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550428160020181905550600060188054905011156137ec576000613787600160188054905061901d90919063ffffffff16565b90508260176018838154811061379957fe5b9060005260206000200154815481106137ae57fe5b9060005260206000200181905550601881815481106137c957fe5b9060005260206000200160009055806018816137e5919061b08a565b5050613819565b60178290806001815401808255809150509060018203906000526020600020016000909192909190915055505b817f3e069fb74dcf5fbc07740b0d40d7f7fc48e9c0ca5dc3d19eb34d2e05d74c5543426040518082815260200191505060405180910390a250505b613868600182618f5790919063ffffffff16565b90506135fb565b504260098190555050505b565b600060018060008282540192505081905550600060015490506000600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000811161394f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f4e6f7468696e6720746f2077697468647261770000000000000000000000000081525060200191505060405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16318111156139dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f496e636f6e73697374656e742062616c616e636500000000000000000000000081525060200191505060405180910390fd5b6000600d60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015613a67573d6000803e3d6000fd5b5060019250506001548114613ae4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5090565b613af0615e3f565b613b62576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b613b6a61b077565b613b7382618c39565b9050613b7e81618c57565b613bd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061b3b86027913960400191505060405180910390fd5b613bff601960000160405180602001604052908160008201548152505082618c7190919063ffffffff16565b15613c72576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f50617274696369706174696f6e20626173656c696e6520756e6368616e67656481525060200191505060405180910390fd5b806019600001600082015181600001559050507f51131d2820f04a6b6edd20e22a07d5bf847e265a3906e85256fca7d6043417c5826040518082815260200191505060405180910390a15050565b60006011600084815260200190815260200160002060020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600c5481565b60116020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900460ff16908060010154905083565b60006060600060f473ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b60208310613dca5780518252602082019150602081019050602083039250613da7565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310613e315780518252602082019150602081019050602083039250613e0e565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114613e91576040519150601f19603f3d011682016040523d82523d6000602084013e613e96565b606091505b50809350819250505080613ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603881526020018061b5166038913960400191505060405180910390fd5b613f00826000619067565b92505050919050565b60006001806000828254019250508190555060006001549050613f2a6134d1565b600080613f3786866190f8565b915091506000613f4683618c9d565b905080156140705760046005811115613f5b57fe5b826005811115613f6757fe5b148015613f795750613f7883618d40565b5b613fce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018061b655602e913960400191505060405180910390fd5b82735d3739f939b974ebeb80afd8f69764e8d78d79dc63c67e7b4b90916040518263ffffffff1660e01b81526004018082815260200191505060006040518083038186803b15801561401f57600080fd5b505af4158015614033573d6000803e3d6000fd5b50505050867f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f60405160405180910390a261406f8388886191d1565b5b80945050505060015481146140ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5092915050565b600060018060008282540192505081905550600060015490506141156134d1565b61411e856192ef565b1561412c576000915061470a565b6000614136619449565b73ffffffffffffffffffffffffffffffffffffffff16636642d594336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156141b257600080fd5b505afa1580156141c6573d6000803e3d6000fd5b505050506040513d60208110156141dc57600080fd5b810190808051906020019092919050505090506000601060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905061424281600001600001546192ef565b50600061424d619544565b73ffffffffffffffffffffffffffffffffffffffff166330ec70f5846040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156142c957600080fd5b505afa1580156142dd573d6000803e3d6000fd5b505050506040513d60208110156142f357600080fd5b810190808051906020019092919050505090506000811161435f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061b6f36022913960400191505060405180910390fd5b601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63bfc5163890918a6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156143b957600080fd5b505af41580156143cd573d6000803e3d6000fd5b505050506040513d60208110156143e357600080fd5b8101908080519060200190929190505050614449576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061b5846029913960400191505060405180910390fd5b6000826000016000015414806144f85750601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63bfc51638909184600001600001546040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156144bb57600080fd5b505af41580156144cf573d6000803e3d6000fd5b505050506040513d60208110156144e557600080fd5b8101908080519060200190929190505050155b61454d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b81526020018061b808602b913960400191505060405180910390fd5b60006145f682601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd637577759990918d6040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156145ad57600080fd5b505af41580156145c1573d6000803e3d6000fd5b505050506040513d60208110156145d757600080fd5b8101908080519060200190929190505050618f5790919063ffffffff16565b9050601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63239491ba90918b848c8c6040518663ffffffff1660e01b8152600401808681526020018581526020018481526020018381526020018281526020019550505050505060006040518083038186803b15801561466a57600080fd5b505af415801561467e573d6000803e3d6000fd5b5050505060405180604001604052808a8152602001838152508360000160008201518160000155602082015181600101559050508373ffffffffffffffffffffffffffffffffffffffff16897fd19965d25ef670a1e322fbf05475924b7b12d81fd6b96ab718b261782efb3d62846040518082815260200191505060405180910390a360019550505050505b6001548114614781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b509392505050565b60008082148061479a5750600b5482115b156147a857600090506147e8565b6147b18261786e565b156147bf57600190506147e8565b6147e56003600f600085815260200190815260200160002061963f90919063ffffffff16565b90505b919050565b6147f5615e3f565b614867576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61486f61b077565b61487882618c39565b905061488381618c57565b6148d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061b4ef6027913960400191505060405180910390fd5b614904601960020160405180602001604052908160008201548152505082618c7190919063ffffffff16565b15614977576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f426173656c696e652075706461746520666163746f7220756e6368616e67656481525060200191505060405180910390fd5b806019600201600082015181600001559050507f8dedb4d995dd500718c7c5f6a077fba6153a7ee063da961d9fcab90ff528ac1f826040518082815260200191505060405180910390a15050565b60006060600060fa73ffffffffffffffffffffffffffffffffffffffff16858560405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310614a3e5780518252602082019150602081019050602083039250614a1b565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114614a9e576040519150601f19603f3d011682016040523d82523d6000602084013e614aa3565b606091505b50809350819250505080614b02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061b61f6036913960400191505060405180910390fd5b614b0d826000618c86565b9250505092915050565b6000600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614614bdc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f6d73672e73656e646572206e6f7420617070726f76657200000000000000000081525060200191505060405180910390fd5b614be46134d1565b600080614bf185856190f8565b91509150614bfe82618c9d565b614c0d57600092505050614df6565b614c16826196fc565b15614c89576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f50726f706f73616c20616c726561647920617070726f7665640000000000000081525060200191505060405180910390fd5b60026005811115614c9657fe5b816005811115614ca257fe5b14614d15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f50726f706f73616c206e6f7420696e20617070726f76616c207374616765000081525060200191505060405180910390fd5b60018260070160006101000a81548160ff021916908315150217905550614d3a619544565b73ffffffffffffffffffffffffffffffffffffffff166330a61d596040518163ffffffff1660e01b815260040160206040518083038186803b158015614d7f57600080fd5b505afa158015614d93573d6000803e3d6000fd5b505050506040513d6020811015614da957600080fd5b81019080805190602001909291905050508260080181905550847f28ec9e38ba73636ceb2f6c1574136f83bd46284a3c74734b711bf45e12f8d92960405160405180910390a26001925050505b92915050565b6000806000601060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206003016000858152602001908152602001600020905080600101548160000160009054906101000a900460ff166003811115614e7857fe5b92509250509250929050565b600080601060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000816000016000015490506000808214158015614eeb5750614eea8261786e565b5b90506000600f6000856002015481526020019081526020016000209050600060036005811115614f1757fe5b614f2b60038461963f90919063ffffffff16565b6005811115614f3657fe5b1490508280614f425750805b95505050505050919050565b600d6020528060005260406000206000915090505481565b6000614f706134d1565b600c54341015614fe8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f546f6f20736d616c6c206465706f73697400000000000000000000000000000081525060200191505060405180910390fd5b614ffe6001600b54618f5790919063ffffffff16565b600b819055506000600f6000600b548152602001908152602001600020905080735d3739f939b974ebeb80afd8f69764e8d78d79dc633053123f90918e8e8e8e8e8e8e8e33346040518c63ffffffff1660e01b8152600401808c8152602001806020018060200180602001806020018773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200186815260200185810385528f8f82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810384528d8d82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810383528b8b82818152602001925080828437600081840152601f19601f8201169050808301925050508581038252898982818152602001925060200280828437600081840152601f19601f8201169050808301925050509f5050505050505050505050505050505060006040518083038186803b15801561518357600080fd5b505af4158015615197573d6000803e3d6000fd5b505050506151f284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508261971790919063ffffffff16565b601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63d7a8acc19091600b546040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b15801561524e57600080fd5b505af4158015615262573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff16600b547f1bfe527f3548d9258c2512b6689f0acfccdd0557d80a53845db25fc57e93d8fe8360060180549050344260405180848152602001838152602001828152602001935050505060405180910390a3600b549150509a9950505050505050505050565b6152ea615e3f565b61535c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600081116153d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4475726174696f6e206d757374206265206c6172676572207468616e2030000081525060200191505060405180910390fd5b60036002015481141561544d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4475726174696f6e20756e6368616e676564000000000000000000000000000081525060200191505060405180910390fd5b806003600201819055507f7819c8059302d1d66abc7fe228ecc02214e0bc5c529956c13717aabefce937d8816040518082815260200191505060405180910390a150565b60006060600060f673ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b602083106154e657805182526020820191506020810190506020830392506154c3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b6020831061554d578051825260208201915060208101905060208303925061552a565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d80600081146155ad576040519150601f19603f3d011682016040523d82523d6000602084013e6155b2565b606091505b50809350819250505080615611576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602381526020018061b8336023913960400191505060405180910390fd5b61561c826000619067565b92505050919050565b6060601780548060200260200160405190810160405280929190818152602001828054801561567357602002820191906000526020600020905b81548152602001906001019080831161565f575b5050505050905090565b600080600f600084815260200190815260200160002090506156b2816156ad60038461963f90919063ffffffff16565b61978f565b915050919050565b6156c2615e3f565b615734576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60006157fe436184c1565b905090565b60075481565b6000615826600f60008481526020019081526020016000206196fc565b9050919050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61585b615e3f565b6158cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008111615926576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061b6836026913960400191505060405180910390fd5b60075481141561599e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f646571756575654672657175656e637920756e6368616e67656400000000000081525060200191505060405180910390fd5b806007819055507f391e82aae76c653cd640ad1b6028e2ee39ca4f29b30152e3d0a9ddd7e1169c34816040518082815260200191505060405180910390a150565b6000806000905060006159f0615b35565b905060006159fc619449565b905060008090505b82811015615b29576000615a1782612ae1565b905060008373ffffffffffffffffffffffffffffffffffffffff166393c5c487836040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015615a9857600080fd5b505afa158015615aac573d6000803e3d6000fd5b505050506040513d6020811015615ac257600080fd5b81019080805190602001909291905050509050615adf8883613cc0565b80615af05750615aef8882613cc0565b5b15615b0c57615b09600187618f5790919063ffffffff16565b95505b5050615b22600182618f5790919063ffffffff16565b9050615a04565b50829350505050919050565b60006060600060f973ffffffffffffffffffffffffffffffffffffffff1643604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b60208310615ba65780518252602082019150602081019050602083039250615b83565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114615c06576040519150601f19603f3d011682016040523d82523d6000602084013e615c0b565b606091505b50809350819250505080615c6a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603581526020018061b5ea6035913960400191505060405180910390fd5b615c75826000618c86565b9250505090565b60006060600060f773ffffffffffffffffffffffffffffffffffffffff16846040516020018082805190602001908083835b60208310615cd15780518252602082019150602081019050602083039250615cae565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040526040518082805190602001908083835b60208310615d385780518252602082019150602081019050602083039250615d15565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114615d98576040519150601f19603f3d011682016040523d82523d6000602084013e615d9d565b606091505b50809350819250505080615dfc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603181526020018061b7d76031913960400191505060405180910390fd5b615e07826000618c86565b92505050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60065481565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16615e81619819565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b615ea5615e3f565b615f17576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008111615f8d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f6d696e4465706f736974206d757374206265206c6172676572207468616e203081525060200191505060405180910390fd5b600c54811415616005576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f4d696e696d756d206465706f73697420756e6368616e6765640000000000000081525060200191505060405180910390fd5b80600c819055507fc50a7f0bdf88c216b2541b0bdea26f22305460e39ffc672ec1a7501732c5ba81816040518082815260200191505060405180910390a150565b600061605a6160558484619821565b619a73565b905092915050565b600061606d8261786e565b6160df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f50726f706f73616c206e6f74207175657565640000000000000000000000000081525060200191505060405180910390fd5b601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63757775999091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561613957600080fd5b505af415801561614d573d6000803e3d6000fd5b505050506040513d602081101561616357600080fd5b81019080805190602001909291905050509050919050565b616183615e3f565b6161f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000811161626b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4475726174696f6e206d757374206265206c6172676572207468616e2030000081525060200191505060405180910390fd5b6003600001548114156162e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4475726174696f6e20756e6368616e676564000000000000000000000000000081525060200191505060405180910390fd5b806003600001819055507fbc44c003a66b841b48c220869efb738b265af305649ac8bafe8efe0c8130e313816040518082815260200191505060405180910390a150565b6000616335436134b7565b905090565b60006060600060f973ffffffffffffffffffffffffffffffffffffffff1684604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b602083106163ab5780518252602082019150602081019050602083039250616388565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461640b576040519150601f19603f3d011682016040523d82523d6000602084013e616410565b606091505b5080935081925050508061646f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602e81526020018061b38a602e913960400191505060405180910390fd5b61647a826000618c86565b92505050919050565b806011600082815260200190815260200160002060000160009054906101000a900460ff161561651b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f686f7466697820616c726561647920657865637574656400000000000000000081525060200191505060405180910390fd5b6165248261349b565b616579576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061b6ca6029913960400191505060405180910390fd5b600061658361632a565b9050806011600085815260200190815260200160002060010154106165f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061b73c6026913960400191505060405180910390fd5b80601160008581526020019081526020016000206001018190555080837f6f184ec313435b3307a4fe59e2293381f08419a87214464c875a2a247e8af5e060405160405180910390a3505050565b616649615e3f565b6166bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561675e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616e6e6f7420726567697374657220746865206e756c6c206164647265737381525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f27fe5f0c1c3b1ed427cc63d0f05759ffdecf9aec9e18d31ef366fc8a6cb5dc3b60405160405180910390a250565b601881815481106167f257fe5b906000526020600020016000915090505481565b6000600360010154905090565b6017818154811061682057fe5b906000526020600020016000915090505481565b600060018060008282540192505081905550600060015490506168556134d1565b600061685f619449565b73ffffffffffffffffffffffffffffffffffffffff16636642d594336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156168db57600080fd5b505afa1580156168ef573d6000803e3d6000fd5b505050506040513d602081101561690557600080fd5b810190808051906020019092919050505090506000601060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000160000154905060008114156169de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4163636f756e7420686173206e6f20686973746f726963616c207570766f746581525060200191505060405180910390fd5b6169e7816192ef565b50601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63bfc516389091836040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b158015616a4257600080fd5b505af4158015616a56573d6000803e3d6000fd5b505050506040513d6020811015616a6c57600080fd5b810190808051906020019092919050505015616c1057601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63239491ba909183616b4f8660000160010154601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63757775999091896040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b158015616b0657600080fd5b505af4158015616b1a573d6000803e3d6000fd5b505050506040513d6020811015616b3057600080fd5b810190808051906020019092919050505061901d90919063ffffffff16565b8b8b6040518663ffffffff1660e01b8152600401808681526020018581526020018481526020018381526020018281526020019550505050505060006040518083038186803b158015616ba157600080fd5b505af4158015616bb5573d6000803e3d6000fd5b505050508273ffffffffffffffffffffffffffffffffffffffff16817f7dc46237a819c9171a9c037ec98928e563892905c4d23373ca0f3f500f4ed11484600001600101546040518082815260200191505060405180910390a35b6040518060400160405280600081526020016000815250826000016000820151816000015560208201518160010155905050600194505050506001548114616cc0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5092915050565b806011600082815260200190815260200160002060000160009054906101000a900460ff1615616d5f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f686f7466697820616c726561647920657865637574656400000000000000000081525060200191505060405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614616e22576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f6d73672e73656e646572206e6f7420617070726f76657200000000000000000081525060200191505060405180910390fd5b60016011600084815260200190815260200160002060000160016101000a81548160ff021916908315150217905550817f36bc158cba244a94dc9b8c08d327e8f7e3c2ab5f1925454c577527466f04851f60405160405180910390a25050565b806011600082815260200190815260200160002060000160009054906101000a900460ff1615616f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f686f7466697820616c726561647920657865637574656400000000000000000081525060200191505060405180910390fd5b60016011600084815260200190815260200160002060020160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550817ff6d22d0b43a6753880b8f9511b82b86cd0fe349cd580bbe6a25b6dc063ef496f33604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25050565b6000601260000160020154905090565b6000600180600082825401925050819055506000600154905061701f6134d1565b60008061702c87876190f8565b9150915061703982618c9d565b61704857600093505050617693565b6000617052619449565b73ffffffffffffffffffffffffffffffffffffffff16636642d594336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156170ce57600080fd5b505afa1580156170e2573d6000803e3d6000fd5b505050506040513d60208110156170f857600080fd5b810190808051906020019092919050505090506000601060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000617158619544565b73ffffffffffffffffffffffffffffffffffffffff166330ec70f5846040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156171d457600080fd5b505afa1580156171e8573d6000803e3d6000fd5b505050506040513d60208110156171fe57600080fd5b8101908080519060200190929190505050905061721a856196fc565b61728c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f50726f706f73616c206e6f7420617070726f766564000000000000000000000081525060200191505060405180910390fd5b6003600581111561729957fe5b8460058111156172a557fe5b14617318576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e636f72726563742070726f706f73616c207374617465000000000000000081525060200191505060405180910390fd5b6000600381111561732557fe5b88600381111561733157fe5b14156173a5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f566f74652076616c756520756e7365740000000000000000000000000000000081525060200191505060405180910390fd5b6000811161741b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f566f74657220776569676874207a65726f00000000000000000000000000000081525060200191505060405180910390fd5b60008260030160008b8152602001908152602001600020905085735d3739f939b974ebeb80afd8f69764e8d78d79dc63b05cd27f90918360020154858f86600101541461746957600061747c565b8560000160009054906101000a900460ff165b8e6040518663ffffffff1660e01b8152600401808681526020018581526020018481526020018360038111156174ae57fe5b60ff1681526020018260038111156174c257fe5b60ff1681526020019550505050505060006040518083038186803b1580156174e957600080fd5b505af41580156174fd573d6000803e3d6000fd5b50505050617509619544565b73ffffffffffffffffffffffffffffffffffffffff166330a61d596040518163ffffffff1660e01b815260040160206040518083038186803b15801561754e57600080fd5b505afa158015617562573d6000803e3d6000fd5b505050506040513d602081101561757857600080fd5b8101908080519060200190929190505050866008018190555060405180606001604052808a60038111156175a857fe5b81526020018c8152602001838152508360030160008c815260200190815260200160002060008201518160000160006101000a81548160ff021916908360038111156175f057fe5b02179055506020820151816001015560408201518160020155905050826002015486600201541115617626578a83600201819055505b8373ffffffffffffffffffffffffffffffffffffffff168b7ff3709dc32cf1356da6b8a12a5be1401aeb00989556be7b16ae566e65fef7a9df8b600381111561766b57fe5b85604051808381526020018281526020019250505060405180910390a3600197505050505050505b600154811461770a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b509392505050565b60095481565b6000617735600f6000848152602001908152602001600020618ff8565b9050919050565b600060149054906101000a900460ff16156177bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f636f6e747261637420616c726561647920696e697469616c697a65640000000081525060200191505060405180910390fd5b6001600060146101000a81548160ff0219169083151502179055506177e333619a81565b6177ec8d616641565b6177f58c613233565b6177fe8b617a8c565b6178078a615e9d565b6178108961309a565b61781988615853565b6178228761617b565b61782b86617c9a565b617834856152e2565b61783d84613ae8565b61784683612cb6565b61784f826147ed565b6178588161287a565b4260098190555050505050505050505050505050565b6000601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63bfc516389091846040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b1580156178ca57600080fd5b505af41580156178de573d6000803e3d6000fd5b505050506040513d60208110156178f457600080fd5b81019080805190602001909291905050508015617917575061791582617718565b155b9050919050565b6000806000806060617941600f6000888152602001908152602001600020619bc5565b808054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156179d65780601f106179ab576101008083540402835291602001916179d6565b820191906000526020600020905b8154815290600101906020018083116179b957829003601f168201915b505050505090509450945094509450945091939590929450565b600080600080617a186019600001604051806020016040529081600082015481525050619a73565b617a3a6019600101604051806020016040529081600082015481525050619a73565b617a5c6019600201604051806020016040529081600082015481525050619a73565b617a7e6019600301604051806020016040529081600082015481525050619a73565b935093509350935090919293565b617a94615e3f565b617b06576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008111617b5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061b3df602c913960400191505060405180910390fd5b600a54811415617bd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4e756d626572206f662070726f706f73616c7320756e6368616e67656400000081525060200191505060405180910390fd5b80600a819055507f85399b9b2595eb13c392e1638ca77730156cd8d48d4733df4db068e4aa6b93a6816040518082815260200191505060405180910390a150565b600080617c2361b0b6565b601060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001604051806040016040529081600082015481526020016001820154815250509050806000015181602001519250925050915091565b617ca2615e3f565b617d14576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60008111617d8a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4475726174696f6e206d757374206265206c6172676572207468616e2030000081525060200191505060405180910390fd5b600360010154811415617e05576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4475726174696f6e20756e6368616e676564000000000000000000000000000081525060200191505060405180910390fd5b806003600101819055507f90290eb9b27055e686a69fb810bada5381e544d07b8270021da2d355a6c96ed6816040518082815260200191505060405180910390a150565b6000898989898989898989604051602001808060200180602001806020018060200186815260200185810385528e8e82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810384528c8c82818152602001925060200280828437600081840152601f19601f82011690508083019250505085810383528a8a82818152602001925080828437600081840152601f19601f8201169050808301925050508581038252888882818152602001925060200280828437600081840152601f19601f8201169050808301925050509d50505050505050505050505050506040516020818303038152906040528051906020012090506000806000617f5b84612a52565b9250925092508115617fd5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f686f7466697820616c726561647920657865637574656400000000000000000081525060200191505060405180910390fd5b82618048576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f686f74666978206e6f7420617070726f7665640000000000000000000000000081525060200191505060405180910390fd5b61805061632a565b81146180a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061b3436026913960400191505060405180910390fd5b6181c56181c08e8e80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508d8d80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050336000619c1e565b619e47565b60016011600086815260200190815260200160002060000160006101000a81548160ff021916908315150217905550837f708a7934acb657a77a617b1fcd5f6d7d9ad592b72934841bff01acefd10f9b6360405160405180910390a250505050505050505050505050565b6000806060600f6000868152602001908152602001600020735d3739f939b974ebeb80afd8f69764e8d78d79dc63e6a5192f9091866040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b1580156182a057600080fd5b505af41580156182b4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060608110156182de57600080fd5b810190808051906020019092919080519060200190929190805164010000000081111561830a57600080fd5b8281019050602081018481111561832057600080fd5b815185600182028301116401000000008211171561833d57600080fd5b50509291905050509250925092509250925092565b600b5481565b60006060600060f873ffffffffffffffffffffffffffffffffffffffff166040516020016040516020818303038152906040526040518082805190602001908083835b602083106183be578051825260208201915060208101905060208303925061839b565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461841e576040519150601f19603f3d011682016040523d82523d6000602084013e618423565b606091505b50809350819250505080618482576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061b7626025913960400191505060405180910390fd5b61848d826000618c86565b9250505090565b60008060006184b4600f6000868152602001908152602001600020619e57565b9250925092509193909250565b600061850560036184f760026184e960026184db8861633a565b619e8190919063ffffffff16565b618f5790919063ffffffff16565b619f0790919063ffffffff16565b9050919050565b60008060008714158015618521575060008514155b618593576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f612064656e6f6d696e61746f72206973207a65726f000000000000000000000081525060200191505060405180910390fd5b6000806000606060fc73ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c6040516020018087815260200186815260200185815260200184815260200183815260200182815260200196505050505050506040516020818303038152906040526040518082805190602001908083835b6020831061862d578051825260208201915060208101905060208303925061860a565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461868d576040519150601f19603f3d011682016040523d82523d6000602084013e618692565b606091505b508092508193505050816186f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061b7156027913960400191505060405180910390fd5b6186fc816000618c86565b9350618709816020618c86565b925083839550955050505050965096945050505050565b618728615e3f565b61879a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561883d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f44657374696e6174696f6e2063616e6e6f74206265207a65726f00000000000081525060200191505060405180910390fd5b6969e10de76676d080000081118015618865575061886161885c619f51565b619a73565b8111155b6188ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252604881526020018061b4816048913960600191505060405180910390fd5b600060e01b827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415618942576188ee81618c39565b600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001600082015181600001559050506189ea565b61894b81618c39565b600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020600082015181600001559050505b817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168373ffffffffffffffffffffffffffffffffffffffff167f60c5b4756af49d7b071b00dbf0f87af605cce11896ecd3b760d19f0f9d3fbcef836040518082815260200191505060405180910390a3505050565b618a65615e3f565b618ad7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b618ae081619a81565b50565b60006060600060f573ffffffffffffffffffffffffffffffffffffffff1684604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b60208310618b545780518252602082019150602081019050602083039250618b31565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d8060008114618bb4576040519150601f19603f3d011682016040523d82523d6000602084013e618bb9565b606091505b50809350819250505080618c18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061b7ab602c913960400191505060405180910390fd5b618c23826000619067565b92505050919050565b6000600360000154905090565b618c4161b077565b6040518060200160405280838152509050919050565b6000618c6a82618c65619f51565b619f77565b9050919050565b60008160000151836000015114905092915050565b6000618c928383619067565b60001c905092915050565b6000808260020154119050919050565b60006017805490508210618d0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b81526020018061b856602b913960400191505060405180910390fd5b618d1584618c9d565b8015618d3757508260178381548110618d2a57fe5b9060005260206000200154145b90509392505050565b6000618d4a61b077565b618da1618d9260196003016040518060200160405290816000820154815250506019600001604051806020016040529081600082015481525050619f8d90919063ffffffff16565b8461a3ec90919063ffffffff16565b905060008090505b8360060180549050811015618f13576000618e7b856006018381548110618dcc57fe5b90600052602060002090600302016002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015618e715780601f10618e4657610100808354040283529160200191618e71565b820191906000526020600020905b815481529060010190602001808311618e5457829003601f168201915b505050505061a4db565b9050618e8561b077565b618ecf866006018481548110618e9757fe5b906000526020600020906003020160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1683619821565b9050618ee48185619f7790919063ffffffff16565b15618ef6576000945050505050618f1a565b5050618f0c600182618f5790919063ffffffff16565b9050618da9565b5060019150505b919050565b600080828481618f2b57fe5b0490506000838581618f3957fe5b061415618f495780915050618f51565b600181019150505b92915050565b600080828401905083811015618fd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000818310618fee5781618ff0565b825b905092915050565b60006190136006548360020154618f5790919063ffffffff16565b4210159050919050565b600061905f83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061a638565b905092915050565b600060208201835110156190e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f736c6963696e67206f7574206f662072616e676500000000000000000000000081525060200191505060405180910390fd5b60006020830184015190508091505092915050565b6000806000600f6000868152602001908152602001600020905061911d818686618cad565b61918f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f50726f706f73616c206e6f74206465717565756564000000000000000000000081525060200191505060405180910390fd5b60006191a560038361963f90919063ffffffff16565b90506191b1828261978f565b156191c2576191c18287876191d1565b5b81819350935050509250929050565b6191da836196fc565b80156191ea575060008360080154115b156191f9576191f88361a6f8565b5b60006017828154811061920857fe5b90600052602060002001819055506018819080600181540180825580915050906001820390600052602060002001600090919290919091505550600f6000838152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560018201600090556002820160009055600382016000808201600090556001820160009055600282016000905550506006820160006192bc919061b0d0565b6007820160006101000a81549060ff021916905560088201600090556009820160006192e8919061b0f4565b5050505050565b600080601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63bfc516389091856040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561934c57600080fd5b505af4158015619360573d6000803e3d6000fd5b505050506040513d602081101561937657600080fd5b81019080805190602001909291905050508015619398575061939783617718565b5b9050801561944057601273deab08ba1b129b1621c4d94ff14267b54e2cc6bd63eed5f7be9091856040518363ffffffff1660e01b8152600401808381526020018281526020019250505060006040518083038186803b1580156193fa57600080fd5b505af415801561940e573d6000803e3d6000fd5b50505050827f88e53c486703527139dfc8d97a1e559d9bd93d3f9d52cda4e06564111e7a264360405160405180910390a25b80915050919050565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f4163636f756e74730000000000000000000000000000000000000000000000008152506008019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561950457600080fd5b505afa158015619518573d6000803e3d6000fd5b505050506040513d602081101561952e57600080fd5b8101908080519060200190929190505050905090565b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f4c6f636b6564476f6c6400000000000000000000000000000000000000000000815250600a019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156195ff57600080fd5b505afa158015619613573d6000803e3d6000fd5b505050506040513d602081101561962957600080fd5b8101908080519060200190929190505050905090565b600080619689836002015461967b856001015461966d87600001548960020154618f5790919063ffffffff16565b618f5790919063ffffffff16565b618f5790919063ffffffff16565b905080421061969c5760059150506196f6565b6196b383600201548261901d90919063ffffffff16565b90508042106196c65760049150506196f6565b6196dd83600101548261901d90919063ffffffff16565b90508042106196f05760039150506196f6565b60029150505b92915050565b60008160070160009054906101000a900460ff169050919050565b600081511415619772576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061b4316029913960400191505060405180910390fd5b8082600901908051906020019061978a92919061b13c565b505050565b60006004600581111561979e57fe5b8260058111156197aa57fe5b11806197de5750600360058111156197be57fe5b8260058111156197ca57fe5b1180156197dd57506197db83618d40565b155b5b806198115750600260058111156197f157fe5b8260058111156197fd57fe5b118015619810575061980e836196fc565b155b5b905092915050565b600033905090565b61982961b077565b61983161b077565b6198446969e10de76676d0800000618c39565b905060006198f6600e60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020604051806020016040529081600082015481525050619a73565b146199a857600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019081526020016000206040518060200160405290816000820154815250509050619a69565b6000619a09600e60008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001604051806020016040529081600082015481525050619a73565b14619a6857600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160405180602001604052908160008201548152505090505b5b8091505092915050565b600081600001519050919050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415619b07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018061b40b6026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008060008060008560000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16866001015487600201548860060180549050896009018090509450945094509450945091939590929450565b619c2661b1bc565b85518751148015619c38575083518651145b619caa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4172726179206c656e677468206d69736d61746368000000000000000000000081525060200191505060405180910390fd5b600087519050619cb861b1bc565b84816000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508381602001818152505042816040018181525050600080905082604051908082528060200260200182016040528015619d4357816020015b619d3061b21f565b815260200190600190039081619d285790505b50826080018190525060008090505b83811015619e365760405180606001604052808c8381518110619d7157fe5b602002602001015181526020018b8381518110619d8a57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff168152602001619dd5848b8581518110619dbd57fe5b60200260200101518d61a88e9092919063ffffffff16565b81525083608001518281518110619de857fe5b6020026020010181905250619e19888281518110619e0257fe5b602002602001015183618f5790919063ffffffff16565b9150619e2f600182618f5790919063ffffffff16565b9050619d52565b508193505050509695505050505050565b619e54816080015161a91a565b50565b60008060008360030160000154846003016001015485600301600201549250925092509193909250565b600080831415619e945760009050619f01565b6000828402905082848281619ea557fe5b0414619efc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061b6a96021913960400191505060405180910390fd5b809150505b92915050565b6000619f4983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061aa23565b905092915050565b619f5961b077565b604051806020016040528069d3c21bcecceda1000000815250905090565b6000816000015183600001511115905092915050565b619f9561b077565b600083600001511480619fac575060008260000151145b15619fc85760405180602001604052806000815250905061a3e6565b69d3c21bcecceda100000082600001511415619fe65782905061a3e6565b69d3c21bcecceda10000008360000151141561a0045781905061a3e6565b600069d3c21bcecceda100000061a01a8561aae9565b600001518161a02557fe5b049050600061a0338561ab20565b600001519050600069d3c21bcecceda100000061a04f8661aae9565b600001518161a05a57fe5b049050600061a0688661ab20565b600001519050600082850290506000851461a0fc578285828161a08757fe5b041461a0fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783179312064657465637465640000000000000000000081525060200191505060405180910390fd5b5b600069d3c21bcecceda1000000820290506000821461a19e5769d3c21bcecceda100000082828161a12957fe5b041461a19d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6f766572666c6f772078317931202a206669786564312064657465637465640081525060200191505060405180910390fd5b5b809150600084860290506000861461a22f578486828161a1ba57fe5b041461a22e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783279312064657465637465640000000000000000000081525060200191505060405180910390fd5b5b600084880290506000881461a2bd578488828161a24857fe5b041461a2bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783179322064657465637465640000000000000000000081525060200191505060405180910390fd5b5b61a2c561ab5d565b878161a2cd57fe5b04965061a2d861ab5d565b858161a2e057fe5b049450600085880290506000881461a371578588828161a2fc57fe5b041461a370576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f6f766572666c6f7720783279322064657465637465640000000000000000000081525060200191505060405180910390fd5b5b61a37961b077565b604051806020016040528087815250905061a3a28160405180602001604052808781525061ab6a565b905061a3bc8160405180602001604052808681525061ab6a565b905061a3d68160405180602001604052808581525061ab6a565b9050809a50505050505050505050505b92915050565b61a3f461b077565b600083600301600001549050600081141561a41b5761a413600061ac13565b91505061a4d5565b600084600301600101549050600061a455866003016002015461a4478486618f5790919063ffffffff16565b618f5790919063ffffffff16565b9050600061a48061a47b61a46c896008015461ac13565b88619f8d90919063ffffffff16565b61ac9d565b90508181111561a4b25761a4af61a4a0838361901d90919063ffffffff16565b84618f5790919063ffffffff16565b92505b61a4ce8461a4c98587618f5790919063ffffffff16565b61acbe565b9450505050505b92915050565b600060188260038151811061a4ec57fe5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c60108360028151811061a54957fe5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c60088460018151811061a5a657fe5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916901c8460008151811061a60157fe5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161717179050919050565b600083831115829061a6e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561a6aa57808201518184015260208101905061a68f565b50505050905090810190601f16801561a6d75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b61a70061b077565b61a7098261ad00565b905061a71361b077565b61a73f601960020160405180602001604052908160008201548152505083619f8d90919063ffffffff16565b905061a74961b077565b61a7a761a77f601960020160405180602001604052908160008201548152505061a771619f51565b61ad5c90919063ffffffff16565b6019600001604051806020016040529081600082015481525050619f8d90919063ffffffff16565b905061a7bc818361ab6a90919063ffffffff16565b60196000016000820151816000015590505061a8136019600101604051806020016040529081600082015481525050601960000160405180602001604052908160008201548152505061ae0390919063ffffffff16565b1561a8305760196001016019600001600082015481600001559050505b7f51131d2820f04a6b6edd20e22a07d5bf847e265a3906e85256fca7d6043417c561a8736019600001604051806020016040529081600082015481525050619a73565b6040518082815260200191505060405180910390a150505050565b60608183018451101561a8a057600080fd5b606082156000811461a8bd5760405191506020820160405261a90e565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561a8fb578051835260208301925060208101905061a8de565b50868552601f19601f8301166040525050505b50809150509392505050565b60008090505b815181101561aa1f5761a99282828151811061a93857fe5b60200260200101516020015183838151811061a95057fe5b60200260200101516000015184848151811061a96857fe5b6020026020010151604001515185858151811061a98157fe5b60200260200101516040015161ae18565b61aa04576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f50726f706f73616c20657865637574696f6e206661696c65640000000000000081525060200191505060405180910390fd5b61aa18600182618f5790919063ffffffff16565b905061a920565b5050565b6000808311829061aacf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561aa9457808201518184015260208101905061aa79565b50505050905090810190601f16801561aac15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161aadb57fe5b049050809150509392505050565b61aaf161b077565b604051806020016040528069d3c21bcecceda10000008085600001518161ab1457fe5b04028152509050919050565b61ab2861b077565b604051806020016040528069d3c21bcecceda10000008085600001518161ab4b57fe5b04028460000151038152509050919050565b600064e8d4a51000905090565b61ab7261b077565b600082600001518460000151019050836000015181101561abfb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f616464206f766572666c6f77206465746563746564000000000000000000000081525060200191505060405180910390fd5b60405180602001604052808281525091505092915050565b61ac1b61b077565b61ac2361aec4565b82111561ac7b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061b54e6036913960400191505060405180910390fd5b604051806020016040528069d3c21bcecceda100000084028152509050919050565b600069d3c21bcecceda100000082600001518161acb657fe5b049050919050565b61acc661b077565b61acce61b077565b61acd78461ac13565b905061ace161b077565b61acea8461ac13565b905061acf6828261aee3565b9250505092915050565b61ad0861b077565b600061ad44836003016002015461ad3685600301600101548660030160000154618f5790919063ffffffff16565b618f5790919063ffffffff16565b905061ad5481846008015461acbe565b915050919050565b61ad6461b077565b81600001518360000151101561ade2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f737562737472616374696f6e20756e646572666c6f772064657465637465640081525060200191505060405180910390fd5b60405180602001604052808360000151856000015103815250905092915050565b60008160000151836000015110905092915050565b600080600084111561aea05761ae2d8661b02c565b61ae9f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b5b6040516020840160008287838a8c6187965a03f19250505080915050949350505050565b60007601357c299a88ea76a58924d52ce4f26a85af186c2b9e74905090565b61aeeb61b077565b60008260000151141561af66576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f63616e277420646976696465206279203000000000000000000000000000000081525060200191505060405180910390fd5b600069d3c21bcecceda10000008460000151029050836000015169d3c21bcecceda1000000828161af9357fe5b041461b007576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f6f766572666c6f7720617420646976696465000000000000000000000000000081525060200191505060405180910390fd5b60405180602001604052808460000151838161b01f57fe5b0481525091505092915050565b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561b06e57506000801b8214155b92505050919050565b6040518060200160405280600081525090565b81548183558181111561b0b15781836000526020600020918201910161b0b0919061b256565b5b505050565b604051806040016040528060008152602001600081525090565b508054600082556003029060005260206000209081019061b0f1919061b27b565b50565b50805460018160011615610100020316600290046000825580601f1061b11a575061b139565b601f01602090049060005260206000209081019061b138919061b256565b5b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061b17d57805160ff191683800117855561b1ab565b8280016001018555821561b1ab579182015b8281111561b1aa57825182559160200191906001019061b18f565b5b50905061b1b8919061b256565b5090565b604051806101400160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200161b1fb61b2d9565b81526020016060815260200160001515815260200160008152602001606081525090565b604051806060016040528060008152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001606081525090565b61b27891905b8082111561b27457600081600090555060010161b25c565b5090565b90565b61b2d691905b8082111561b2d2576000808201600090556001820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560028201600061b2c9919061b2fa565b5060030161b281565b5090565b90565b60405180606001604052806000815260200160008152602001600081525090565b50805460018160011615610100020316600290046000825580601f1061b320575061b33f565b601f01602090049060005260206000209081019061b33e919061b256565b5b5056fe686f74666978206d75737420626520707265706172656420666f7220746869732065706f63685175657565457870697279206d757374206265206c6172676572207468616e20306572726f722063616c6c696e67206e756d62657256616c696461746f7273496e53657420707265636f6d70696c6550617274696369706174696f6e20626173656c696e652067726561746572207468616e206f6e654e756d626572206f662070726f706f73616c73206d757374206265206c6172676572207468616e207a65726f4f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734465736372697074696f6e2075726c206d7573742068617665206e6f6e2d7a65726f206c656e677468426173656c696e652071756f72756d20666163746f722067726561746572207468616e206f6e655468726573686f6c642068617320746f2062652067726561746572207468616e206d616a6f7269747920616e64206e6f742067726561746572207468616e20756e616e696d69747950617274696369706174696f6e20626173656c696e6520666c6f6f7220756e6368616e676564426173656c696e652075706461746520666163746f722067726561746572207468616e206f6e656572726f722063616c6c696e672067657456657269666965645365616c4269746d617046726f6d48656164657220707265636f6d70696c6563616e277420637265617465206669786964697479206e756d626572206c6172676572207468616e206d61784e65774669786564282963616e6e6f74207570766f746520612070726f706f73616c206e6f7420696e207468652071756575656572726f722063616c6c696e672076616c696461746f725369676e65724164647265737346726f6d43757272656e7453657420707265636f6d70696c656572726f722063616c6c696e67206e756d62657256616c696461746f7273496e43757272656e7453657420707265636f6d70696c656572726f722063616c6c696e672076616c696461746f725369676e65724164647265737346726f6d53657420707265636f6d70696c6550726f706f73616c206e6f7420696e20657865637574696f6e207374616765206f72206e6f742070617373696e67646571756575654672657175656e6379206d757374206265206c6172676572207468616e2030536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77686f74666978206e6f742077686974656c69737465642062792032662b312076616c696461746f727363616e6e6f74207570766f746520776974686f7574206c6f636b696e6720676f6c646572726f722063616c6c696e67206672616374696f6e4d756c45787020707265636f6d70696c65686f7466697820616c726561647920707265706172656420666f7220746869732065706f63686572726f722063616c6c696e672067657445706f636853697a6520707265636f6d70696c6550617274696369706174696f6e20666c6f6f722067726561746572207468616e206f6e656572726f722063616c6c696e6720676574506172656e745365616c4269746d617020707265636f6d70696c656572726f722063616c6c696e6720676574426c6f636b4e756d62657246726f6d48656164657220707265636f6d70696c6563616e6e6f74207570766f7465206d6f7265207468616e206f6e65207175657565642070726f706f73616c6572726f722063616c6c696e67206861736848656164657220707265636f6d70696c6550726f766964656420696e6465782067726561746572207468616e2064657175657565206c656e6774682ea165627a7a723058207b7eeaf07f3051263d12b6f049a82d8c38da16b42ee8d96d5dfbf06b9473aa5b0029

External libraries