ETH Price: $2,761.59 (+1.14%)

Contract

0x3528C164e3fCA20E2333Cf58Ab4B1c99DeF83347
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Withdraw149177812022-06-07 0:15:41990 days ago1654560941IN
0x3528C164...9DeF83347
0 ETH0.0176101856.61273101
Withdraw To120668862021-03-19 3:56:101435 days ago1616126170IN
0x3528C164...9DeF83347
0 ETH0.04974741116.00000145
Withdraw To120668392021-03-19 3:48:221435 days ago1616125702IN
0x3528C164...9DeF83347
0 ETH0.05103398119
Withdraw To112058912020-11-06 20:18:471567 days ago1604693927IN
0x3528C164...9DeF83347
0 ETH0.006762616
Withdraw To110505532020-10-14 0:25:431591 days ago1602635143IN
0x3528C164...9DeF83347
0 ETH0.0152158636
Withdraw To108920212020-09-19 10:08:481615 days ago1600510128IN
0x3528C164...9DeF83347
0 ETH0.05269947123
Withdraw To108435752020-09-11 23:25:421623 days ago1599866742IN
0x3528C164...9DeF83347
0 ETH0.0354735280
Withdraw To106981752020-08-20 16:34:481645 days ago1597941288IN
0x3528C164...9DeF83347
0 ETH0.0604129135
Withdraw To106547152020-08-13 23:53:261652 days ago1597362806IN
0x3528C164...9DeF83347
0 ETH0.07249856160
Withdraw To105572652020-07-29 22:37:541667 days ago1596062274IN
0x3528C164...9DeF83347
0 ETH0.0203902245
Withdraw To105239192020-07-24 18:49:111672 days ago1595616551IN
0x3528C164...9DeF83347
0 ETH0.0315434872
Withdraw To105160202020-07-23 13:44:431673 days ago1595511883IN
0x3528C164...9DeF83347
0 ETH0.0337358577
Update104739792020-07-17 1:24:131680 days ago1594949053IN
0x3528C164...9DeF83347
0 ETH0.0011223334.1
Withdraw To104712932020-07-16 15:19:031680 days ago1594912743IN
0x3528C164...9DeF83347
0 ETH0.0337349377
Withdraw To104141472020-07-07 19:05:221689 days ago1594148722IN
0x3528C164...9DeF83347
0 ETH0.013346930.8
Withdraw To104141362020-07-07 19:02:531689 days ago1594148573IN
0x3528C164...9DeF83347
0 ETH0.0135815931
Withdraw To103883152020-07-03 19:29:561693 days ago1593804596IN
0x3528C164...9DeF83347
0 ETH0.0139363634
Withdraw To103230752020-06-23 16:15:481703 days ago1592928948IN
0x3528C164...9DeF83347
0 ETH0.0205909847
Withdraw To103041302020-06-20 18:03:431706 days ago1592676223IN
0x3528C164...9DeF83347
0 ETH0.0096380622
Withdraw To103004812020-06-20 4:18:141707 days ago1592626694IN
0x3528C164...9DeF83347
0 ETH0.0096818722.1
Request102969392020-06-19 15:22:161707 days ago1592580136IN
0x3528C164...9DeF83347
0 ETH0.0618107144
Request102897142020-06-18 12:32:521708 days ago1592483572IN
0x3528C164...9DeF83347
0 ETH0.0501325236
Withdraw To102891822020-06-18 10:32:041708 days ago1592476324IN
0x3528C164...9DeF83347
0 ETH0.0172175738
Request102787672020-06-16 19:39:121710 days ago1592336352IN
0x3528C164...9DeF83347
0 ETH0.0384106527
Create102715812020-06-15 17:03:321711 days ago1592240612IN
0x3528C164...9DeF83347
0 ETH0.0213887146
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Funds

Compiler Version
v0.5.10+commit.5a6ea5b1

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-02-24
*/

pragma solidity 0.5.10;


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

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

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

contract ERC20 is Context, IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    
    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }

    
    function transfer(address recipient, uint256 amount) public returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    
    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowances[owner][spender];
    }

    
    function approve(address spender, uint256 amount) public returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    
    function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    
    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    
    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    
    function _transfer(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    
    function _mint(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: mint to the zero address");

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

     
    function _burn(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: burn from the zero address");

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

    
    function _approve(address owner, address spender, uint256 amount) internal {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    
    function _burnFrom(address account, uint256 amount) internal {
        _burn(account, amount);
        _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
    }
}

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), "Slice out of bounds");

        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 conversion out of bounds.");
        address tempAddress;

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

        return tempAddress;
    }

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

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

        return tempUint;
    }

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

    function toBytes32(bytes memory _source) pure internal returns (bytes32 result) {
        bytes memory tempEmptyStringTest = bytes(_source);
        if (tempEmptyStringTest.length == 0) {
            return 0x0;
        }

        assembly {
            result := mload(add(_source, 32))
        }
    }
}

library BTCUtils {
    using BytesLib for bytes;
    using SafeMath for uint256;

    
    uint256 public constant DIFF1_TARGET = 0xffff0000000000000000000000000000000000000000000000000000;

    uint256 public constant RETARGET_PERIOD = 2 * 7 * 24 * 60 * 60;  
    uint256 public constant RETARGET_PERIOD_BLOCKS = 2016;  

    
    
    

    
    
    
    
    function determineVarIntDataLength(bytes memory _flag) internal pure returns (uint8) {
        if (uint8(_flag[0]) == 0xff) {
            return 8;  
        }
        if (uint8(_flag[0]) == 0xfe) {
            return 4;  
        }
        if (uint8(_flag[0]) == 0xfd) {
            return 2;  
        }

        return 0;  
    }

    
    
    
    
    function reverseEndianness(bytes memory _b) internal pure returns (bytes memory) {
        bytes memory _newValue = new bytes(_b.length);

        for (uint i = 0; i < _b.length; i++) {
            _newValue[_b.length - i - 1] = _b[i];
        }

        return _newValue;
    }

    
    
    
    
    function bytesToUint(bytes memory _b) internal pure returns (uint256) {
        uint256 _number;

        for (uint i = 0; i < _b.length; i++) {
            _number = _number + uint8(_b[i]) * (2 ** (8 * (_b.length - (i + 1))));
        }

        return _number;
    }

    
    
    
    
    function lastBytes(bytes memory _b, uint256 _num) internal pure returns (bytes memory) {
        uint256 _start = _b.length.sub(_num);

        return _b.slice(_start, _num);
    }

    
    
    
    
    function hash160(bytes memory _b) internal pure returns (bytes memory) {
        return abi.encodePacked(ripemd160(abi.encodePacked(sha256(_b))));
    }

    
    
    
    
    function hash256(bytes memory _b) internal pure returns (bytes32) {
        return abi.encodePacked(sha256(abi.encodePacked(sha256(_b)))).toBytes32();
    }

    
    
    

    
    
    
    
    
    function extractInputAtIndex(bytes memory _vin, uint8 _index) internal pure returns (bytes memory) {
        uint256 _len;
        bytes memory _remaining;

        uint256 _offset = 1;

        for (uint8 _i = 0; _i < _index; _i ++) {
            _remaining = _vin.slice(_offset, _vin.length - _offset);
            _len = determineInputLength(_remaining);
            _offset = _offset + _len;
        }

        _remaining = _vin.slice(_offset, _vin.length - _offset);
        _len = determineInputLength(_remaining);
        return _vin.slice(_offset, _len);
    }

    
    
    
    
    function isLegacyInput(bytes memory _input) internal pure returns (bool) {
        return keccak256(_input.slice(36, 1)) != keccak256(hex"00");
    }

    
    
    
    
    function determineInputLength(bytes memory _input) internal pure returns (uint256) {
        uint8 _varIntDataLen;
        uint256 _scriptSigLen;
        (_varIntDataLen, _scriptSigLen) = extractScriptSigLen(_input);
        return 36 + 1 + _varIntDataLen + _scriptSigLen + 4;
    }

    
    
    
    
    function extractSequenceLELegacy(bytes memory _input) internal pure returns (bytes memory) {
        uint8 _varIntDataLen;
        uint256 _scriptSigLen;
        (_varIntDataLen, _scriptSigLen) = extractScriptSigLen(_input);
        return _input.slice(36 + 1 + _varIntDataLen + _scriptSigLen, 4);
    }

    
    
    
    
    function extractSequenceLegacy(bytes memory _input) internal pure returns (uint32) {
        bytes memory _leSeqence = extractSequenceLELegacy(_input);
        bytes memory _beSequence = reverseEndianness(_leSeqence);
        return uint32(bytesToUint(_beSequence));
    }
    
    
    
    
    function extractScriptSig(bytes memory _input) internal pure returns (bytes memory) {
        uint8 _varIntDataLen;
        uint256 _scriptSigLen;
        (_varIntDataLen, _scriptSigLen) = extractScriptSigLen(_input);
        return _input.slice(36, 1 + _varIntDataLen + _scriptSigLen);
    }

    
    
    
    
    function extractScriptSigLen(bytes memory _input) internal pure returns (uint8, uint256) {
        bytes memory _varIntTag = _input.slice(36, 1);
        uint8 _varIntDataLen = determineVarIntDataLength(_varIntTag);
        uint256 _len;
        if (_varIntDataLen == 0) {
            _len = uint8(_varIntTag[0]);
        } else {
            _len = bytesToUint(reverseEndianness(_input.slice(36 + 1, _varIntDataLen)));
        }
        return (_varIntDataLen, _len);
    }


    
    
    

    
    
    
    
    function extractSequenceLEWitness(bytes memory _input) internal pure returns (bytes memory) {
        return _input.slice(37, 4);
    }

    
    
    
    
    function extractSequenceWitness(bytes memory _input) internal pure returns (uint32) {
        bytes memory _leSeqence = extractSequenceLEWitness(_input);
        bytes memory _inputeSequence = reverseEndianness(_leSeqence);
        return uint32(bytesToUint(_inputeSequence));
    }

    
    
    
    
    function extractOutpoint(bytes memory _input) internal pure returns (bytes memory) {
        return _input.slice(0, 36);
    }

    
    
    
    
    function extractInputTxIdLE(bytes memory _input) internal pure returns (bytes32) {
        return _input.slice(0, 32).toBytes32();
    }

    
    
    
    
    function extractInputTxId(bytes memory _input) internal pure returns (bytes32) {
        bytes memory _leId = abi.encodePacked(extractInputTxIdLE(_input));
        bytes memory _beId = reverseEndianness(_leId);
        return _beId.toBytes32();
    }

    
    
    
    
    function extractTxIndexLE(bytes memory _input) internal pure returns (bytes memory) {
        return _input.slice(32, 4);
    }

    
    
    
    
    function extractTxIndex(bytes memory _input) internal pure returns (uint32) {
        bytes memory _leIndex = extractTxIndexLE(_input);
        bytes memory _beIndex = reverseEndianness(_leIndex);
        return uint32(bytesToUint(_beIndex));
    }

    
    
    

    
    
    
    
    function determineOutputLength(bytes memory _output) internal pure returns (uint256) {
        uint8 _len = uint8(_output.slice(8, 1)[0]);
        require(_len < 0xfd, "Multi-byte VarInts not supported");

        return _len + 8 + 1; 
    }

    
    
    
    
    
    function extractOutputAtIndex(bytes memory _vout, uint8 _index) internal pure returns (bytes memory) {
        uint256 _len;
        bytes memory _remaining;

        uint256 _offset = 1;

        for (uint8 _i = 0; _i < _index; _i ++) {
            _remaining = _vout.slice(_offset, _vout.length - _offset);
            _len = determineOutputLength(_remaining);
            _offset = _offset + _len;
        }

        _remaining = _vout.slice(_offset, _vout.length - _offset);
        _len = determineOutputLength(_remaining);
        return _vout.slice(_offset, _len);
    }

    
    
    
    
    function extractOutputScriptLen(bytes memory _output) internal pure returns (bytes memory) {
        return _output.slice(8, 1);
    }

    
    
    
    
    function extractValueLE(bytes memory _output) internal pure returns (bytes memory) {
        return _output.slice(0, 8);
    }

    
    
    
    
    function extractValue(bytes memory _output) internal pure returns (uint64) {
        bytes memory _leValue = extractValueLE(_output);
        bytes memory _beValue = reverseEndianness(_leValue);
        return uint64(bytesToUint(_beValue));
    }

    
    
    
    
    function extractOpReturnData(bytes memory _output) internal pure returns (bytes memory) {
        if (keccak256(_output.slice(9, 1)) != keccak256(hex"6a")) {
            return hex"";
        }
        bytes memory _dataLen = _output.slice(10, 1);
        return _output.slice(11, bytesToUint(_dataLen));
    }

    
    
    
    
    function extractHash(bytes memory _output) internal pure returns (bytes memory) {
        if (uint8(_output.slice(9, 1)[0]) == 0) {
            uint256 _len = uint8(extractOutputScriptLen(_output)[0]) - 2;
            
            if (uint8(_output.slice(10, 1)[0]) != uint8(_len)) {
                return hex"";
            }
            return _output.slice(11, _len);
        } else {
            bytes32 _tag = keccak256(_output.slice(8, 3));
            
            if (_tag == keccak256(hex"1976a9")) {
                
                if (uint8(_output.slice(11, 1)[0]) != 0x14 ||
                    keccak256(_output.slice(_output.length - 2, 2)) != keccak256(hex"88ac")) {
                    return hex"";
                }
                return _output.slice(12, 20);
            
            } else if (_tag == keccak256(hex"17a914")) {
                
                if (uint8(_output.slice(_output.length - 1, 1)[0]) != 0x87) {
                    return hex"";
                }
                return _output.slice(11, 20);
            }
        }
        return hex"";  
    }

    
    
    


    
    
    
    
    function validateVin(bytes memory _vin) internal pure returns (bool) {
        uint256 _offset = 1;
        uint8 _nIns = uint8(_vin.slice(0, 1)[0]);

        
        if (_nIns >= 0xfd || _nIns == 0) {
            return false;
        }

        for (uint8 i = 0; i < _nIns; i++) {
            
            
            _offset += determineInputLength(_vin.slice(_offset, _vin.length - _offset));

            
            if (_offset > _vin.length) {
                return false;
            }
        }

        
        return _offset == _vin.length;
    }

    
    
    
    
    function validateVout(bytes memory _vout) internal pure returns (bool) {
        uint256 _offset = 1;
        uint8 _nOuts = uint8(_vout.slice(0, 1)[0]);

        
        if (_nOuts >= 0xfd || _nOuts == 0) {
            return false;
        }

        for (uint8 i = 0; i < _nOuts; i++) {
            
            
            _offset += determineOutputLength(_vout.slice(_offset, _vout.length - _offset));

            
            if (_offset > _vout.length) {
                return false;
            }
        }

        
        return _offset == _vout.length;
    }



    
    
    

    
    
    
    
    function extractMerkleRootLE(bytes memory _header) internal pure returns (bytes memory) {
        return _header.slice(36, 32);
    }

    
    
    
    
    function extractMerkleRootBE(bytes memory _header) internal pure returns (bytes memory) {
        return reverseEndianness(extractMerkleRootLE(_header));
    }

    
    
    
    
    function extractTarget(bytes memory _header) internal pure returns (uint256) {
        bytes memory _m = _header.slice(72, 3);
        uint8 _e = uint8(_header[75]);
        uint256 _mantissa = bytesToUint(reverseEndianness(_m));
        uint _exponent = _e - 3;

        return _mantissa * (256 ** _exponent);
    }

    
    
    
    
    
    function calculateDifficulty(uint256 _target) internal pure returns (uint256) {
        
        return DIFF1_TARGET.div(_target);
    }

    
    
    
    
    function extractPrevBlockLE(bytes memory _header) internal pure returns (bytes memory) {
        return _header.slice(4, 32);
    }

    
    
    
    
    function extractPrevBlockBE(bytes memory _header) internal pure returns (bytes memory) {
        return reverseEndianness(extractPrevBlockLE(_header));
    }

    
    
    
    
    function extractTimestampLE(bytes memory _header) internal pure returns (bytes memory) {
        return _header.slice(68, 4);
    }

    
    
    
    
    function extractTimestamp(bytes memory _header) internal pure returns (uint32) {
        return uint32(bytesToUint(reverseEndianness(extractTimestampLE(_header))));
    }

    
    
    
    
    function extractDifficulty(bytes memory _header) internal pure returns (uint256) {
        return calculateDifficulty(extractTarget(_header));
    }

    
    
    
    
    function _hash256MerkleStep(bytes memory _a, bytes memory _b) internal pure returns (bytes32) {
        return hash256(abi.encodePacked(_a, _b));
    }

    
    
    
    
    
    function verifyHash256Merkle(bytes memory _proof, uint _index) internal pure returns (bool) {
        
        if (_proof.length % 32 != 0) {
            return false;
        }

        
        if (_proof.length == 32) {
            return true;
        }

        
        if (_proof.length == 64) {
            return false;
        }

        uint _idx = _index;
        bytes32 _root = _proof.slice(_proof.length - 32, 32).toBytes32();
        bytes32 _current = _proof.slice(0, 32).toBytes32();

        for (uint i = 1; i < (_proof.length.div(32)) - 1; i++) {
            if (_idx % 2 == 1) {
                _current = _hash256MerkleStep(_proof.slice(i * 32, 32), abi.encodePacked(_current));
            } else {
                _current = _hash256MerkleStep(abi.encodePacked(_current), _proof.slice(i * 32, 32));
            }
            _idx = _idx >> 1;
        }
        return _current == _root;
    }

    
    
    
    
    
    
    
    function retargetAlgorithm(
        uint256 _previousTarget,
        uint256 _firstTimestamp,
        uint256 _secondTimestamp
    ) internal pure returns (uint256) {
        uint256 _elapsedTime = _secondTimestamp.sub(_firstTimestamp);

        
        if (_elapsedTime < RETARGET_PERIOD.div(4)) {
            _elapsedTime = RETARGET_PERIOD.div(4);
        }
        if (_elapsedTime > RETARGET_PERIOD.mul(4)) {
            _elapsedTime = RETARGET_PERIOD.mul(4);
        }

        

        uint256 _adjusted = _previousTarget.div(65536).mul(_elapsedTime);
        return _adjusted.div(RETARGET_PERIOD).mul(65536);
    }
}

interface FundsInterface {
    function lender(bytes32) external view returns (address);
    function custom(bytes32) external view returns (bool);
    function deposit(bytes32, uint256) external;
    function decreaseTotalBorrow(uint256) external;
    function calcGlobalInterest() external;
}

interface SalesInterface {
    function saleIndexByLoan(bytes32, uint256) external returns(bytes32);
    function settlementExpiration(bytes32) external view returns (uint256);
    function accepted(bytes32) external view returns (bool);
    function next(bytes32) external view returns (uint256);
    function create(bytes32, address, address, address, address, bytes32, bytes32, bytes32, bytes32, bytes20) external returns(bytes32);
}

interface CollateralInterface {
    function onDemandSpv() external view returns(address);
    function collateral(bytes32 loan) external view returns (uint256);
    function refundableCollateral(bytes32 loan) external view returns (uint256);
    function seizableCollateral(bytes32 loan) external view returns (uint256);
    function temporaryRefundableCollateral(bytes32 loan) external view returns (uint256);
    function temporarySeizableCollateral(bytes32 loan) external view returns (uint256);
    function setCollateral(bytes32 loan, uint256 refundableCollateral_, uint256 seizableCollateral_) external;
    function requestSpv(bytes32 loan) external;
    function cancelSpv(bytes32 loan) external;
}

contract DSMath {
    function add(uint x, uint y) internal pure returns (uint z) {
        require((z = x + y) >= x);
    }
    function sub(uint x, uint y) internal pure returns (uint z) {
        require((z = x - y) <= x);
    }
    function mul(uint x, uint y) internal pure returns (uint z) {
        require(y == 0 || (z = x * y) / y == x);
    }
    function div(uint a, uint b) internal pure returns (uint c) {
        require(b > 0);
        c = a / b;
    }

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

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

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

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    function rpow(uint x, uint n) internal pure returns (uint z) {
        z = n % 2 != 0 ? x : RAY;

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

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

contract Medianizer {
    function peek() external view returns (bytes32, bool);
    function read() external returns (bytes32);
    function poke() external;
    function poke(bytes32) external;
    function fund (uint256 amount, ERC20 token) external;
}

contract Loans is DSMath {
    FundsInterface funds;
    Medianizer med;
    SalesInterface sales;
    CollateralInterface col;

    uint256 public constant APPROVE_EXP_THRESHOLD = 4 hours;    
    uint256 public constant ACCEPT_EXP_THRESHOLD = 2 days;      
    uint256 public constant LIQUIDATION_EXP_THRESHOLD = 7 days; 
    uint256 public constant SEIZURE_EXP_THRESHOLD = 2 days;     
    uint256 public constant LIQUIDATION_DISCOUNT = 930000000000000000; 
    uint256 public constant MAX_NUM_LIQUIDATIONS = 3; 
    uint256 public constant MAX_UINT_256 = 2**256-1;

    mapping (bytes32 => Loan)                     public loans;
    mapping (bytes32 => PubKeys)                  public pubKeys;             
    mapping (bytes32 => SecretHashes)             public secretHashes;        
    mapping (bytes32 => Bools)                    public bools;               
    mapping (bytes32 => bytes32)                  public fundIndex;           
    mapping (bytes32 => uint256)                  public repayments;          
    mapping (address => bytes32[])                public borrowerLoans;
    mapping (address => bytes32[])                public lenderLoans;
    mapping (address => mapping(uint256 => bool)) public addressToTimestamp;
    uint256                                       public loanIndex;           

    ERC20 public token; 
    uint256 public decimals;

    address deployer;

    
    struct Loan {
        address borrower;
        address lender;
        address arbiter;
        uint256 createdAt;
        uint256 loanExpiration;
        uint256 requestTimestamp;
        uint256 closedTimestamp;
        uint256 principal;
        uint256 interest;
        uint256 penalty;
        uint256 fee;
        uint256 liquidationRatio;
    }

    
    struct PubKeys {
        bytes   borrowerPubKey;
        bytes   lenderPubKey;
        bytes   arbiterPubKey;
    }

    
    struct SecretHashes {
        bytes32    secretHashA1;
        bytes32[3] secretHashAs;
        bytes32    secretHashB1;
        bytes32[3] secretHashBs;
        bytes32    secretHashC1;
        bytes32[3] secretHashCs;
        bytes32    withdrawSecret;
        bytes32    acceptSecret;
        bool       set;
    }

    
    struct Bools {
        bool funded;
        bool approved;
        bool withdrawn;
        bool sale;
        bool paid;
        bool off;
    }

    event Create(bytes32 loan);

    event SetSecretHashes(bytes32 loan);

    event FundLoan(bytes32 loan);

    event Approve(bytes32 loan);

    event Withdraw(bytes32 loan, bytes32 secretA1);

    event Repay(bytes32 loan, uint256 amount);

    event Refund(bytes32 loan);

    event Cancel(bytes32 loan, bytes32 secret);

    event Accept(bytes32 loan, bytes32 secret);

    event Liquidate(bytes32 loan, bytes32 secretHash, bytes20 pubKeyHash);

    
    function borrower(bytes32 loan) external view returns (address) {
        return loans[loan].borrower;
    }

    
    function lender(bytes32 loan) external view returns (address) {
        return loans[loan].lender;
    }

    
    function arbiter(bytes32 loan) external view returns (address) {
        return loans[loan].arbiter;
    }

    
    function approveExpiration(bytes32 loan) public view returns (uint256) { 
        return add(loans[loan].createdAt, APPROVE_EXP_THRESHOLD);
    }

    
    function acceptExpiration(bytes32 loan) public view returns (uint256) { 
        return add(loans[loan].loanExpiration, ACCEPT_EXP_THRESHOLD);
    }

    
    function liquidationExpiration(bytes32 loan) public view returns (uint256) { 
        return add(loans[loan].loanExpiration, LIQUIDATION_EXP_THRESHOLD);
    }

    
    function seizureExpiration(bytes32 loan) public view returns (uint256) {
        return add(liquidationExpiration(loan), SEIZURE_EXP_THRESHOLD);
    }

    
    function principal(bytes32 loan) public view returns (uint256) {
        return loans[loan].principal;
    }

    
    function interest(bytes32 loan) public view returns (uint256) {
        return loans[loan].interest;
    }

    
    function fee(bytes32 loan) public view returns (uint256) {
        return loans[loan].fee;
    }

    
    function penalty(bytes32 loan) public view returns (uint256) {
        return loans[loan].penalty;
    }

    
    function collateral(bytes32 loan) public view returns (uint256) {
        return col.collateral(loan);
    }

    
    function refundableCollateral(bytes32 loan) external view returns (uint256) {
        return col.refundableCollateral(loan);
    }

    
    function seizableCollateral(bytes32 loan) external view returns (uint256) {
        return col.seizableCollateral(loan);
    }

    
    function temporaryRefundableCollateral(bytes32 loan) external view returns (uint256) {
        return col.temporaryRefundableCollateral(loan);
    }

    
    function temporarySeizableCollateral(bytes32 loan) external view returns (uint256) {
        return col.temporarySeizableCollateral(loan);
    }

    
    function repaid(bytes32 loan) public view returns (uint256) { 
        return repayments[loan];
    }

    
    function liquidationRatio(bytes32 loan) public view returns (uint256) {
        return loans[loan].liquidationRatio;
    }

    
    function owedToLender(bytes32 loan) public view returns (uint256) { 
        return add(principal(loan), interest(loan));
    }

    
    function owedForLoan(bytes32 loan) public view returns (uint256) { 
        return add(owedToLender(loan), fee(loan));
    }

    
    function owedForLiquidation(bytes32 loan) external view returns (uint256) { 
        return add(owedForLoan(loan), penalty(loan));
    }

    
    function owing(bytes32 loan) external view returns (uint256) {
        return sub(owedForLoan(loan), repaid(loan));
    }

    
    function funded(bytes32 loan) external view returns (bool) {
        return bools[loan].funded;
    }

    
    function approved(bytes32 loan) external view returns (bool) {
        return bools[loan].approved;
    }

    
    function withdrawn(bytes32 loan) external view returns (bool) {
        return bools[loan].withdrawn;
    }

    
    function sale(bytes32 loan) public view returns (bool) {
        return bools[loan].sale;
    }

    
    function paid(bytes32 loan) external view returns (bool) {
        return bools[loan].paid;
    }

    
    function off(bytes32 loan) public view returns (bool) {
        return bools[loan].off;
    }

    
    function dmul(uint x) public view returns (uint256) {
        return mul(x, (10 ** sub(18, decimals)));
    }

    
    function ddiv(uint x) public view returns (uint256) {
        return div(x, (10 ** sub(18, decimals)));
    }

    
    function borrowerLoanCount(address borrower_) external view returns (uint256) {
        return borrowerLoans[borrower_].length;
    }

    
    function lenderLoanCount(address lender_) external view returns (uint256) {
        return lenderLoans[lender_].length;
    }

    
    function minSeizableCollateral(bytes32 loan) public view returns (uint256) {
        (bytes32 val, bool set) = med.peek();
        require(set, "Loans.minSeizableCollateral: Medianizer must be set");
        uint256 price = uint(val);
        return div(wdiv(dmul(sub(owedForLoan(loan), repaid(loan))), price), div(WAD, COL));
    }

    
    function collateralValue(bytes32 loan) public view returns (uint256) {
        (bytes32 val, bool set) = med.peek();
        require(set, "Loans.collateralValue: Medianizer must be set");
        uint256 price = uint(val);
        return cmul(price, collateral(loan));
    }

    
    function minCollateralValue(bytes32 loan) public view returns (uint256) {
        return rmul(dmul(sub(owedForLoan(loan), repaid(loan))), liquidationRatio(loan));
    }

    
    function discountCollateralValue(bytes32 loan) public view returns (uint256) {
        return wmul(collateralValue(loan), LIQUIDATION_DISCOUNT);
    }

    
    function safe(bytes32 loan) public view returns (bool) {
        return collateralValue(loan) >= minCollateralValue(loan);
    }

    
    constructor (FundsInterface funds_, Medianizer med_, ERC20 token_, uint256 decimals_) public {
        require(address(funds_) != address(0), "Funds address must be non-zero");
        require(address(med_) != address(0), "Medianizer address must be non-zero");
        require(address(token_) != address(0), "Token address must be non-zero");

        deployer = msg.sender;
        funds = funds_;
        med = med_;
        token = token_;
        decimals = decimals_;
        require(token.approve(address(funds), MAX_UINT_256), "Token approve failed");
    }

    
    
    
    
    
    

    
    function setSales(SalesInterface sales_) external {
        require(msg.sender == deployer, "Loans.setSales: Only the deployer can perform this");
        require(address(sales) == address(0), "Loans.setSales: The Sales address has already been set");
        require(address(sales_) != address(0), "Loans.setSales: Sales address must be non-zero");
        sales = sales_;
    }

    
    function setCollateral(CollateralInterface col_) external {
        require(msg.sender == deployer, "Loans.setCollateral: Only the deployer can perform this");
        require(address(col) == address(0), "Loans.setCollateral: The Collateral address has already been set");
        require(address(col_) != address(0), "Loans.setCollateral: Collateral address must be non-zero");
        col = col_;
    }
    

    
    function create(
        uint256             loanExpiration_,
        address[3] calldata usrs_,
        uint256[7] calldata vals_,
        bytes32             fund
    ) external returns (bytes32 loan) {
        if (fund != bytes32(0)) {
            require(funds.lender(fund) == usrs_[1], "Loans.create: Lender of Fund not in args");
        }
        require(!addressToTimestamp[usrs_[0]][vals_[6]], "Loans.create: Duplicate request timestamps are not allowed");
        require(loanExpiration_ > now, "Loans.create: loanExpiration must be greater than `now`");
        require(usrs_[0] != address(0) && usrs_[1] != address(0), "Loans.create: Borrower and Lender address must be non-zero");
        require(vals_[0] != 0 && vals_[4] != 0, "Loans.create: Principal and Collateral must be non-zero");
        require(vals_[5] != 0 && vals_[6] != 0, "Loans.create: Liquidation ratio and Request timestamp must be non-zero");

        loanIndex = add(loanIndex, 1);
        loan = bytes32(loanIndex);
        loans[loan].createdAt = now;
        loans[loan].loanExpiration = loanExpiration_;
        loans[loan].borrower = usrs_[0];
        loans[loan].lender = usrs_[1];
        loans[loan].arbiter = usrs_[2];
        loans[loan].principal = vals_[0];
        loans[loan].interest = vals_[1];
        loans[loan].penalty = vals_[2];
        loans[loan].fee = vals_[3];
        uint256 minSeizableCol = minSeizableCollateral(loan);
        col.setCollateral(loan, sub(vals_[4], minSeizableCol), minSeizableCol);
        loans[loan].liquidationRatio = vals_[5];
        loans[loan].requestTimestamp = vals_[6];
        fundIndex[loan] = fund;
        secretHashes[loan].set = false;
        borrowerLoans[usrs_[0]].push(bytes32(loanIndex));
        lenderLoans[usrs_[1]].push(bytes32(loanIndex));
        addressToTimestamp[usrs_[0]][vals_[6]] = true;

        emit Create(loan);
    }

    
    function setSecretHashes(
        bytes32             loan,
        bytes32[4] calldata borrowerSecretHashes,
        bytes32[4] calldata lenderSecretHashes,
        bytes32[4] calldata arbiterSecretHashes,
        bytes      calldata borrowerPubKey_,
        bytes      calldata lenderPubKey_,
        bytes      calldata arbiterPubKey_
    ) external {
        require(!secretHashes[loan].set, "Loans.setSecretHashes: Secret hashes must not already be set");
        require(
            msg.sender == loans[loan].borrower || msg.sender == loans[loan].lender || msg.sender == address(funds),
            "Loans.setSecretHashes: msg.sender must be Borrower, Lender or Funds Address"
        );
        secretHashes[loan].secretHashA1 = borrowerSecretHashes[0];
        secretHashes[loan].secretHashAs = [ borrowerSecretHashes[1], borrowerSecretHashes[2], borrowerSecretHashes[3] ];
        secretHashes[loan].secretHashB1 = lenderSecretHashes[0];
        secretHashes[loan].secretHashBs = [ lenderSecretHashes[1], lenderSecretHashes[2], lenderSecretHashes[3] ];
        secretHashes[loan].secretHashC1 = arbiterSecretHashes[0];
        secretHashes[loan].secretHashCs = [ arbiterSecretHashes[1], arbiterSecretHashes[2], arbiterSecretHashes[3] ];
        pubKeys[loan].borrowerPubKey = borrowerPubKey_;
        pubKeys[loan].lenderPubKey = lenderPubKey_;
        pubKeys[loan].arbiterPubKey = arbiterPubKey_;
        secretHashes[loan].set = true;
    }

    
    function fund(bytes32 loan) external {
        require(secretHashes[loan].set, "Loans.fund: Secret hashes must be set");
        require(bools[loan].funded == false, "Loans.fund: Loan is already funded");
        bools[loan].funded = true;
        require(token.transferFrom(msg.sender, address(this), principal(loan)), "Loans.fund: Failed to transfer tokens");

        emit FundLoan(loan);
    }

    
    function approve(bytes32 loan) external { 
    	require(bools[loan].funded == true, "Loans.approve: Loan must be funded");
    	require(loans[loan].lender == msg.sender, "Loans.approve: Only the lender can approve the loan");
        require(now <= approveExpiration(loan), "Loans.approve: Loan is past the approve deadline");
    	bools[loan].approved = true;

        emit Approve(loan);
    }

    
    function withdraw(bytes32 loan, bytes32 secretA1) external {
        require(!off(loan), "Loans.withdraw: Loan cannot be inactive");
        require(bools[loan].funded == true, "Loans.withdraw: Loan must be funded");
        require(bools[loan].approved == true, "Loans.withdraw: Loan must be approved");
        require(bools[loan].withdrawn == false, "Loans.withdraw: Loan principal has already been withdrawn");
        require(sha256(abi.encodePacked(secretA1)) == secretHashes[loan].secretHashA1, "Loans.withdraw: Secret does not match");
        bools[loan].withdrawn = true;
        require(token.transfer(loans[loan].borrower, principal(loan)), "Loans.withdraw: Failed to transfer tokens");

        secretHashes[loan].withdrawSecret = secretA1;
        if (address(col.onDemandSpv()) != address(0)) {col.requestSpv(loan);}

        emit Withdraw(loan, secretA1);
    }

    
    function repay(bytes32 loan, uint256 amount) external {
        require(!off(loan), "Loans.repay: Loan cannot be inactive");
        require(!sale(loan), "Loans.repay: Loan cannot be undergoing a liquidation");
        require(bools[loan].withdrawn == true, "Loans.repay: Loan principal must be withdrawn");
        require(now <= loans[loan].loanExpiration, "Loans.repay: Loan cannot have expired");
        require(add(amount, repaid(loan)) <= owedForLoan(loan), "Loans.repay: Cannot repay more than the owed amount");
        require(token.transferFrom(msg.sender, address(this), amount), "Loans.repay: Failed to transfer tokens");
        repayments[loan] = add(amount, repayments[loan]);
        if (repaid(loan) == owedForLoan(loan)) {
            bools[loan].paid = true;
            if (address(col.onDemandSpv()) != address(0)) {col.cancelSpv(loan);}
        }

        emit Repay(loan, amount);
    }

    
    function refund(bytes32 loan) external {
        require(!off(loan), "Loans.refund: Loan cannot be inactive");
        require(!sale(loan), "Loans.refund: Loan cannot be undergoing a liquidation");
        require(now > acceptExpiration(loan), "Loans.refund: Cannot request refund until after acceptExpiration");
        require(bools[loan].paid == true, "Loans.refund: The loan must be repaid");
        require(msg.sender == loans[loan].borrower, "Loans.refund: Only the borrower can request a refund");
        bools[loan].off = true;
        loans[loan].closedTimestamp = now;
        if (funds.custom(fundIndex[loan]) == false) {
            funds.decreaseTotalBorrow(loans[loan].principal);
            funds.calcGlobalInterest();
        }
        require(token.transfer(loans[loan].borrower, owedForLoan(loan)), "Loans.refund: Failed to transfer tokens");

        emit Refund(loan);
    }

    
    function cancel(bytes32 loan, bytes32 secret) external {
        accept(loan, secret);

        emit Cancel(loan, secret);
    }

    
    function cancel(bytes32 loan) external {
        require(!off(loan), "Loans.cancel: Loan must not be inactive");
        require(bools[loan].withdrawn == false, "Loans.cancel: Loan principal must not be withdrawn");
        require(now >= seizureExpiration(loan), "Loans.cancel: Seizure deadline has not been reached");
        require(bools[loan].sale == false, "Loans.cancel: Loan must not be undergoing liquidation");
        close(loan);

        emit Cancel(loan, bytes32(0));
    }

    
    function accept(bytes32 loan, bytes32 secret) public {
        require(!off(loan), "Loans.accept: Loan must not be inactive");
        require(bools[loan].withdrawn == false || bools[loan].paid == true, "Loans.accept: Loan must be either not withdrawn or repaid");
        require(msg.sender == loans[loan].lender || msg.sender == loans[loan].arbiter, "Loans.accept: msg.sender must be lender or arbiter");
        require(now <= acceptExpiration(loan), "Loans.accept: Acceptance deadline has past");
        require(bools[loan].sale == false, "Loans.accept: Loan must not be going under liquidation");
        require(
            sha256(abi.encodePacked(secret)) == secretHashes[loan].secretHashB1 || sha256(abi.encodePacked(secret)) == secretHashes[loan].secretHashC1,
            "Loans.accept: Invalid secret"
        );
        secretHashes[loan].acceptSecret = secret;
        close(loan);

        emit Accept(loan, secret);
    }

    
    function close(bytes32 loan) private {
        bools[loan].off = true;
        loans[loan].closedTimestamp = now;
        
        if (bools[loan].withdrawn == false) {
            if (fundIndex[loan] == bytes32(0)) {
                require(token.transfer(loans[loan].lender, loans[loan].principal), "Loans.close: Failed to transfer principal to Lender");
            } else {
                if (funds.custom(fundIndex[loan]) == false) {
                    funds.decreaseTotalBorrow(loans[loan].principal);
                }
                funds.deposit(fundIndex[loan], loans[loan].principal);
            }
        }
        
        else {
            if (fundIndex[loan] == bytes32(0)) {
                require(token.transfer(loans[loan].lender, owedToLender(loan)), "Loans.close: Failed to transfer owedToLender to Lender");
            } else {
                if (funds.custom(fundIndex[loan]) == false) {
                    funds.decreaseTotalBorrow(loans[loan].principal);
                }
                funds.deposit(fundIndex[loan], owedToLender(loan));
            }
            require(token.transfer(loans[loan].arbiter, fee(loan)), "Loans.close: Failed to transfer fee to Arbiter");
        }
    }

    
    function liquidate(bytes32 loan, bytes32 secretHash, bytes20 pubKeyHash) external returns (bytes32 sale_) {
        require(!off(loan), "Loans.liquidate: Loan must not be inactive");
        require(bools[loan].withdrawn == true, "Loans.liquidate: Loan principal must be withdrawn");
        require(msg.sender != loans[loan].borrower && msg.sender != loans[loan].lender, "Loans.liquidate: Liquidator must be a third-party");
        require(secretHash != bytes32(0) && pubKeyHash != bytes20(0), "Loans.liquidate: secretHash and pubKeyHash must be non-zero");
        
        if (sales.next(loan) == 0) {
            
            if (now > loans[loan].loanExpiration) {
                require(bools[loan].paid == false, "Loans.liquidate: loan must not have already been repaid");
            } else {
                require(!safe(loan), "Loans.liquidate: collateralization must be below min-collateralization ratio");
            }
            
            if (funds.custom(fundIndex[loan]) == false) {
                funds.decreaseTotalBorrow(loans[loan].principal);
                funds.calcGlobalInterest();
            }
        } else {
            
            require(sales.next(loan) < MAX_NUM_LIQUIDATIONS, "Loans.liquidate: Max number of liquidations reached");
            require(!sales.accepted(sales.saleIndexByLoan(loan, sales.next(loan) - 1)), "Loans.liquidate: Previous liquidation already accepted");
            require(
                now > sales.settlementExpiration(sales.saleIndexByLoan(loan, sales.next(loan) - 1)),
                "Loans.liquidate: Previous liquidation settlement expiration hasn't expired"
            );
        }
        require(token.balanceOf(msg.sender) >= ddiv(discountCollateralValue(loan)), "Loans.liquidate: insufficient balance to liquidate");
        require(token.transferFrom(msg.sender, address(sales), ddiv(discountCollateralValue(loan))), "Loans.liquidate: Token transfer failed");
        SecretHashes storage h = secretHashes[loan];
        uint256 i = sales.next(loan);
        
        sale_ = sales.create(
            loan, loans[loan].borrower, loans[loan].lender, loans[loan].arbiter, msg.sender,
            h.secretHashAs[i], h.secretHashBs[i], h.secretHashCs[i], secretHash, pubKeyHash
        );
        if (bools[loan].sale == false) {
            bools[loan].sale = true;
            require(token.transfer(address(sales), repaid(loan)), "Loans.liquidate: Token transfer to Sales contract failed");
        }
        
        if (address(col.onDemandSpv()) != address(0)) {col.cancelSpv(loan);}

        emit Liquidate(loan, secretHash, pubKeyHash);
    }
}

interface CTokenInterface {
    function redeem(uint redeemTokens) external returns (uint);
    function redeemUnderlying(uint redeemAmount) external returns (uint);
    function borrow(uint borrowAmount) external returns (uint);
    function liquidateBorrow(address borrower, uint repayAmount, address cTokenCollateral) external returns (uint);
    function liquidateBorrow(address borrower, address cTokenCollateral) external payable;
    function exchangeRateCurrent() external returns (uint);
    function getCash() external view returns (uint);
    function totalBorrowsCurrent() external returns (uint);
    function borrowRatePerBlock() external view returns (uint);
    function supplyRatePerBlock() external view returns (uint);
    function totalReserves() external view returns (uint);
    function reserveFactorMantissa() external view returns (uint);

    function totalSupply() external view returns (uint256);
    function balanceOf(address owner) external view returns (uint256 balance);
    function allowance(address, address) external view returns (uint);
    function approve(address, uint) external;
    function transfer(address, uint) external returns (bool);
    function transferFrom(address, address, uint) external returns (bool);
}

interface CERC20Interface {
    function mint(uint mintAmount) external returns (uint); 
    function repayBorrow(uint repayAmount) external returns (uint); 
    function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint); 
    function borrowBalanceCurrent(address account) external returns (uint);
}

interface ERC20Interface {
    function allowance(address, address) external view returns (uint);
    function balanceOf(address) external view returns (uint);
    function approve(address, uint) external;
    function transfer(address, uint) external returns (bool);
    function transferFrom(address, address, uint) external returns (bool);
}

interface TrollerInterface {
    function enterMarkets(address[] calldata cTokens) external returns (uint[] memory);
    function exitMarket(address cTokenAddress) external returns (uint);
    function getAssetsIn(address account) external view returns (address[] memory);
    function getAccountLiquidity(address account) external view returns (uint, uint, uint);
}

contract Helpers is DSMath {

    address public comptroller;

    
    function getComptrollerAddress() public view returns (address) {
        
        
        
        return comptroller;
    }

    function enterMarket(address cErc20) internal {
        TrollerInterface troller = TrollerInterface(getComptrollerAddress());
        address[] memory markets = troller.getAssetsIn(address(this));
        bool isEntered = false;
        for (uint i = 0; i < markets.length; i++) {
            if (markets[i] == cErc20) {
                isEntered = true;
            }
        }
        if (!isEntered) {
            address[] memory toEnter = new address[](1);
            toEnter[0] = cErc20;
            troller.enterMarkets(toEnter);
        }
    }

    
    function setApproval(address erc20, uint srcAmt, address to) internal {
        ERC20Interface erc20Contract = ERC20Interface(erc20);
        uint tokenAllowance = erc20Contract.allowance(address(this), to);
        if (srcAmt > tokenAllowance) {
            erc20Contract.approve(to, 2**255);
        }
    }

}

contract ALCompound is Helpers {
    
    function mintCToken(address erc20, address cErc20, uint tokenAmt) internal {
        enterMarket(cErc20);
        ERC20Interface token = ERC20Interface(erc20);
        uint toDeposit = token.balanceOf(address(this));
        if (toDeposit > tokenAmt) {
            toDeposit = tokenAmt;
        }
        CERC20Interface cToken = CERC20Interface(cErc20);
        setApproval(erc20, toDeposit, cErc20);
        assert(cToken.mint(toDeposit) == 0);
    }

    
    function redeemUnderlying(address cErc20, uint tokenAmt) internal {
        CTokenInterface cToken = CTokenInterface(cErc20);
        setApproval(cErc20, 10**50, cErc20);
        uint toBurn = cToken.balanceOf(address(this));
        uint tokenToReturn = wmul(toBurn, cToken.exchangeRateCurrent());
        if (tokenToReturn > tokenAmt) {
            tokenToReturn = tokenAmt;
        }
        require(cToken.redeemUnderlying(tokenToReturn) == 0, "something went wrong");
    }

    
    function redeemCToken(address cErc20, uint cTokenAmt) internal {
        CTokenInterface cToken = CTokenInterface(cErc20);
        uint toBurn = cToken.balanceOf(address(this));
        if (toBurn > cTokenAmt) {
            toBurn = cTokenAmt;
        }
        setApproval(cErc20, toBurn, cErc20);
        require(cToken.redeem(toBurn) == 0, "something went wrong");
    }
}

contract Funds is DSMath, ALCompound {
    Loans loans;

    uint256 public constant DEFAULT_LIQUIDATION_RATIO = 1400000000000000000000000000;   
    uint256 public constant DEFAULT_LIQUIDATION_PENALTY = 1000000000937303470807876289; 
    uint256 public constant DEFAULT_MIN_LOAN_AMT = 25 ether; 
    uint256 public constant DEFAULT_MAX_LOAN_AMT = 2**256-1; 
    uint256 public constant DEFAULT_MIN_LOAN_DUR = 6 hours;  
    uint256 public constant NUM_SECONDS_IN_YEAR = 365 days;
    uint256 public constant MAX_LOAN_LENGTH = 10 * NUM_SECONDS_IN_YEAR;
    uint256 public constant MAX_UINT_256 = 2**256-1;

    mapping (address => bytes32[]) public secretHashes;    
    mapping (address => uint256)   public secretHashIndex; 

    mapping (address => bytes)     public pubKeys;  

    mapping (bytes32 => Fund)      public funds;
    mapping (address => bytes32)   public fundOwner;
    mapping (bytes32 => Bools)     public bools;
    uint256                        public fundIndex;

    uint256 public lastGlobalInterestUpdated;
    uint256 public tokenMarketLiquidity;
    uint256 public cTokenMarketLiquidity;
    uint256 public marketLiquidity;
    uint256 public totalBorrow;
    uint256 public globalInterestRateNumerator;
    uint256 public lastUtilizationRatio;
    uint256 public globalInterestRate;
    uint256 public maxUtilizationDelta;
    uint256 public utilizationInterestDivisor;
    uint256 public maxInterestRateNumerator;
    uint256 public minInterestRateNumerator;
    uint256 public interestUpdateDelay;
    uint256 public defaultArbiterFee;

    ERC20 public token;
    uint256 public decimals;
    CTokenInterface public cToken;
    bool compoundSet;

    address deployer;

    
    struct Fund {
        address  lender;
        uint256  minLoanAmt;
        uint256  maxLoanAmt;
        uint256  minLoanDur;
        uint256  maxLoanDur;
        uint256  fundExpiry;
        uint256  interest;
        uint256  penalty;
        uint256  fee;
        uint256  liquidationRatio;
        address  arbiter;
        uint256  balance;
        uint256  cBalance;
    }

    
    struct Bools {
        bool     custom;
        bool     compoundEnabled;
    }

    event Create(bytes32 fund);

    event Deposit(bytes32 fund, uint256 amount_);

    event Update(bytes32  fund, uint256  maxLoanDur_, uint256  fundExpiry_, address  arbiter_);

    event Request(bytes32 fund, address borrower_, uint256 amount_, uint256 collateral_, uint256 loanDur_, uint256 requestTimestamp_);

    event Withdraw(bytes32 fund, uint256 amount_, address recipient_);

    event EnableCompound(bytes32 fund);

    event DisableCompound(bytes32 fund);

    
    
    constructor(
        ERC20   token_,
        uint256 decimals_
    ) public {
        require(address(token_) != address(0), "Funds.constructor: Token address must be non-zero");
        require(decimals_ != 0, "Funds.constructor: Decimals must be non-zero");

        deployer = msg.sender;
        token = token_;
        decimals = decimals_;
        utilizationInterestDivisor = 10531702972595856680093239305; 
        maxUtilizationDelta = 95310179948351216961192521; 
        globalInterestRateNumerator = 95310179948351216961192521; 
        maxInterestRateNumerator = 182321557320989604265864303; 
        minInterestRateNumerator = 24692612600038629323181834; 
        interestUpdateDelay = 86400; 
        defaultArbiterFee = 1000000000236936036262880196; 
        globalInterestRate = add(RAY, div(globalInterestRateNumerator, NUM_SECONDS_IN_YEAR)); 
    }

    
    
    
    
    
    

    
    function setLoans(Loans loans_) external {
        require(msg.sender == deployer, "Funds.setLoans: Only the deployer can perform this");
        require(address(loans) == address(0), "Funds.setLoans: Loans address has already been set");
        require(address(loans_) != address(0), "Funds.setLoans: Loans address must be non-zero");
        loans = loans_;
        require(token.approve(address(loans_), MAX_UINT_256), "Funds.setLoans: Tokens cannot be approved");
    }

    
    function setCompound(CTokenInterface cToken_, address comptroller_) external {
        require(msg.sender == deployer, "Funds.setCompound: Only the deployer can enable Compound lending");
        require(!compoundSet, "Funds.setCompound: Compound address has already been set");
        require(address(cToken_) != address(0), "Funds.setCompound: cToken address must be non-zero");
        require(comptroller_ != address(0), "Funds.setCompound: comptroller address must be non-zero");
        cToken = cToken_;
        comptroller = comptroller_;
        compoundSet = true;
    }
    

    
    
    
    
    
    
    

    
    function setUtilizationInterestDivisor(uint256 utilizationInterestDivisor_) external {
        require(msg.sender == deployer, "Funds.setUtilizationInterestDivisor: Only the deployer can perform this");
        require(utilizationInterestDivisor_ != 0, "Funds.setUtilizationInterestDivisor: utilizationInterestDivisor is zero");
        utilizationInterestDivisor = utilizationInterestDivisor_;
    }

    
    function setMaxUtilizationDelta(uint256 maxUtilizationDelta_) external {
        require(msg.sender == deployer, "Funds.setMaxUtilizationDelta: Only the deployer can perform this");
        require(maxUtilizationDelta_ != 0, "Funds.setMaxUtilizationDelta: maxUtilizationDelta is zero");
        maxUtilizationDelta = maxUtilizationDelta_;
    }

    
    function setGlobalInterestRateNumerator(uint256 globalInterestRateNumerator_) external {
        require(msg.sender == deployer, "Funds.setGlobalInterestRateNumerator: Only the deployer can perform this");
        require(globalInterestRateNumerator_ != 0, "Funds.setGlobalInterestRateNumerator: globalInterestRateNumerator is zero");
        globalInterestRateNumerator = globalInterestRateNumerator_;
    }

    
    function setGlobalInterestRate(uint256 globalInterestRate_) external {
        require(msg.sender == deployer, "Funds.setGlobalInterestRate: Only the deployer can perform this");
        require(globalInterestRate_ != 0, "Funds.setGlobalInterestRate: globalInterestRate is zero");
        globalInterestRate = globalInterestRate_;
    }

    
    function setMaxInterestRateNumerator(uint256 maxInterestRateNumerator_) external {
        require(msg.sender == deployer, "Funds.setMaxInterestRateNumerator: Only the deployer can perform this");
        require(maxInterestRateNumerator_ != 0, "Funds.setMaxInterestRateNumerator: maxInterestRateNumerator is zero");
        maxInterestRateNumerator = maxInterestRateNumerator_;
    }

    
    function setMinInterestRateNumerator(uint256 minInterestRateNumerator_) external {
        require(msg.sender == deployer, "Funds.setMinInterestRateNumerator: Only the deployer can perform this");
        require(minInterestRateNumerator_ != 0, "Funds.setMinInterestRateNumerator: minInterestRateNumerator is zero");
        minInterestRateNumerator = minInterestRateNumerator_;
    }

    
    function setInterestUpdateDelay(uint256 interestUpdateDelay_) external {
        require(msg.sender == deployer, "Funds.setInterestUpdateDelay: Only the deployer can perform this");
        require(interestUpdateDelay_ != 0, "Funds.setInterestUpdateDelay: interestUpdateDelay is zero");
        interestUpdateDelay = interestUpdateDelay_;
    }

    
    function setDefaultArbiterFee(uint256 defaultArbiterFee_) external {
        require(msg.sender == deployer, "Funds.setDefaultArbiterFee: Only the deployer can perform this");
        require(defaultArbiterFee_ <= 1000000000315522921573372069, "Funds.setDefaultArbiterFee: defaultArbiterFee cannot be less than -1%"); 
        defaultArbiterFee = defaultArbiterFee_;
    }
    

    
    function lender(bytes32 fund) public view returns (address) {
        return funds[fund].lender;
    }

    
    function minLoanAmt(bytes32 fund) public view returns (uint256) {
        if (bools[fund].custom) {return funds[fund].minLoanAmt;}
        else                    {return div(DEFAULT_MIN_LOAN_AMT, (10 ** sub(18, decimals)));}
    }

    
    function maxLoanAmt(bytes32 fund) public view returns (uint256) {
        if (bools[fund].custom) {return funds[fund].maxLoanAmt;}
        else                    {return DEFAULT_MAX_LOAN_AMT;}
    }

    
    function minLoanDur(bytes32 fund) public view returns (uint256) {
        if (bools[fund].custom) {return funds[fund].minLoanDur;}
        else                    {return DEFAULT_MIN_LOAN_DUR;}
    }

    
    function maxLoanDur(bytes32 fund) public view returns (uint256) {
        return funds[fund].maxLoanDur;
    }

    
    function fundExpiry(bytes32 fund) public view returns (uint256) {
        return funds[fund].fundExpiry;
    }

    
    function interest(bytes32 fund) public view returns (uint256) {
        if (bools[fund].custom) {return funds[fund].interest;}
        else                    {return globalInterestRate;}
    }

    
    function penalty(bytes32 fund) public view returns (uint256) {
        if (bools[fund].custom) {return funds[fund].penalty;}
        else                    {return DEFAULT_LIQUIDATION_PENALTY;}
    }

    
    function fee(bytes32 fund) public view returns (uint256) {
        if (bools[fund].custom) {return funds[fund].fee;}
        else                    {return defaultArbiterFee;}
    }

    
    function liquidationRatio(bytes32 fund) public view returns (uint256) {
        if (bools[fund].custom) {return funds[fund].liquidationRatio;}
        else                    {return DEFAULT_LIQUIDATION_RATIO;}
    }

    
    function arbiter(bytes32 fund) public view returns (address) {
        return funds[fund].arbiter;
    }

    
    function balance(bytes32 fund) public returns (uint256) {
        if (bools[fund].compoundEnabled) {
            return wmul(funds[fund].cBalance, cToken.exchangeRateCurrent());
        } else {
            return funds[fund].balance;
        }
    }

    function cTokenExchangeRate() public returns (uint256) {
        if (compoundSet) {
            return cToken.exchangeRateCurrent();
        } else {
            return 0;
        }
    }

    
    function custom(bytes32 fund) public view returns (bool) {
        return bools[fund].custom;
    }

    
    function secretHashesCount(address addr_) public view returns (uint256) {
        return secretHashes[addr_].length;
    }

    
    function create(
        uint256  maxLoanDur_,
        uint256  fundExpiry_,
        address  arbiter_,
        bool     compoundEnabled_,
        uint256  amount_
    ) external returns (bytes32 fund) {
        
        
        
        require(funds[fundOwner[msg.sender]].lender != msg.sender, "Funds.create: Only one loan fund allowed per address"); 
        
        require(
            ensureNotZero(maxLoanDur_, false) < MAX_LOAN_LENGTH && ensureNotZero(fundExpiry_, true) < now + MAX_LOAN_LENGTH,
            "Funds.create: fundExpiry and maxLoanDur cannot exceed 10 years"
        ); 
        if (!compoundSet) {require(compoundEnabled_ == false, "Funds.create: Cannot enable Compound as it has not been configured");}
        fundIndex = add(fundIndex, 1);
        fund = bytes32(fundIndex);
        funds[fund].lender = msg.sender;
        funds[fund].maxLoanDur = ensureNotZero(maxLoanDur_, false);
        funds[fund].fundExpiry = ensureNotZero(fundExpiry_, true);
        funds[fund].arbiter = arbiter_;
        bools[fund].custom = false;
        bools[fund].compoundEnabled = compoundEnabled_;
        fundOwner[msg.sender] = bytes32(fundIndex);
        if (amount_ > 0) {deposit(fund, amount_);}

        emit Create(fund);
    }

    
    function createCustom(
        uint256  minLoanAmt_,
        uint256  maxLoanAmt_,
        uint256  minLoanDur_,
        uint256  maxLoanDur_,
        uint256  fundExpiry_,
        uint256  liquidationRatio_,
        uint256  interest_,
        uint256  penalty_,
        uint256  fee_,
        address  arbiter_,
        bool     compoundEnabled_,
        uint256  amount_
    ) external returns (bytes32 fund) {
        
        
        
        require(funds[fundOwner[msg.sender]].lender != msg.sender, "Funds.create: Only one loan fund allowed per address"); 
        
        require(
            ensureNotZero(maxLoanDur_, false) < MAX_LOAN_LENGTH && ensureNotZero(fundExpiry_, true) < now + MAX_LOAN_LENGTH,
            "Funds.createCustom: fundExpiry and maxLoanDur cannot exceed 10 years"
        ); 
        require(maxLoanAmt_ >= minLoanAmt_, "Funds.createCustom: maxLoanAmt must be greater than or equal to minLoanAmt");
        require(ensureNotZero(maxLoanDur_, false) >= minLoanDur_, "Funds.createCustom: maxLoanDur must be greater than or equal to minLoanDur");

        if (!compoundSet) {require(compoundEnabled_ == false, "Funds.createCustom: Cannot enable Compound as it has not been configured");}
        fundIndex = add(fundIndex, 1);
        fund = bytes32(fundIndex);
        funds[fund].lender = msg.sender;
        funds[fund].minLoanAmt = minLoanAmt_;
        funds[fund].maxLoanAmt = maxLoanAmt_;
        funds[fund].minLoanDur = minLoanDur_;
        funds[fund].maxLoanDur = ensureNotZero(maxLoanDur_, false);
        funds[fund].fundExpiry = ensureNotZero(fundExpiry_, true);
        funds[fund].interest = interest_;
        funds[fund].penalty = penalty_;
        funds[fund].fee = fee_;
        funds[fund].liquidationRatio = liquidationRatio_;
        funds[fund].arbiter = arbiter_;
        bools[fund].custom = true;
        bools[fund].compoundEnabled = compoundEnabled_;
        fundOwner[msg.sender] = bytes32(fundIndex);
        if (amount_ > 0) {deposit(fund, amount_);}

        emit Create(fund);
    }

    
    function deposit(bytes32 fund, uint256 amount_) public {
        require(token.transferFrom(msg.sender, address(this), amount_), "Funds.deposit: Failed to transfer tokens");
        if (bools[fund].compoundEnabled) {
            mintCToken(address(token), address(cToken), amount_);
            uint256 cTokenToAdd = div(mul(amount_, WAD), cToken.exchangeRateCurrent());
            funds[fund].cBalance = add(funds[fund].cBalance, cTokenToAdd);
            if (!custom(fund)) {cTokenMarketLiquidity = add(cTokenMarketLiquidity, cTokenToAdd);}
        } else {
            funds[fund].balance = add(funds[fund].balance, amount_);
            if (!custom(fund)) {tokenMarketLiquidity = add(tokenMarketLiquidity, amount_);}
        }
        if (!custom(fund)) {calcGlobalInterest();}

        emit Deposit(fund, amount_);
    }

    
    function update(
        bytes32  fund,
        uint256  maxLoanDur_,
        uint256  fundExpiry_,
        address  arbiter_
    ) public {
        require(msg.sender == lender(fund), "Funds.update: Only the lender can update the fund");
        require(
            ensureNotZero(maxLoanDur_, false) <= MAX_LOAN_LENGTH && ensureNotZero(fundExpiry_, true) <= now + MAX_LOAN_LENGTH,
            "Funds.update: fundExpiry and maxLoanDur cannot exceed 10 years"
        );  
        funds[fund].maxLoanDur = maxLoanDur_;
        funds[fund].fundExpiry = fundExpiry_;
        funds[fund].arbiter = arbiter_;

        emit Update(fund, maxLoanDur_, fundExpiry_, arbiter_);
    }

    
    function updateCustom(
        bytes32  fund,
        uint256  minLoanAmt_,
        uint256  maxLoanAmt_,
        uint256  minLoanDur_,
        uint256  maxLoanDur_,
        uint256  fundExpiry_,
        uint256  interest_,
        uint256  penalty_,
        uint256  fee_,
        uint256  liquidationRatio_,
        address  arbiter_
    ) external {
        require(bools[fund].custom, "Funds.updateCustom: Fund must be a custom fund");
        require(maxLoanAmt_ >= minLoanAmt_, "Funds.updateCustom: maxLoanAmt must be greater than or equal to minLoanAmt");
        require(ensureNotZero(maxLoanDur_, false) >= minLoanDur_, "Funds.updateCustom: maxLoanDur must be greater than or equal to minLoanDur");
        update(fund, maxLoanDur_, fundExpiry_, arbiter_);
        funds[fund].minLoanAmt = minLoanAmt_;
        funds[fund].maxLoanAmt = maxLoanAmt_;
        funds[fund].minLoanDur = minLoanDur_;
        funds[fund].interest = interest_;
        funds[fund].penalty = penalty_;
        funds[fund].fee = fee_;
        funds[fund].liquidationRatio = liquidationRatio_;
    }

    
    function request(
        bytes32             fund,
        address             borrower_,
        uint256             amount_,
        uint256             collateral_,
        uint256             loanDur_,
        uint256             requestTimestamp_,
        bytes32[8] calldata secretHashes_,
        bytes      calldata pubKeyA_,
        bytes      calldata pubKeyB_
    ) external returns (bytes32 loanIndex) {
        require(msg.sender == lender(fund), "Funds.request: Only the lender can fulfill a loan request");
        require(amount_ <= balance(fund), "Funds.request: Insufficient balance");
        require(amount_ >= minLoanAmt(fund), "Funds.request: Amount requested must be greater than minLoanAmt");
        require(amount_ <= maxLoanAmt(fund), "Funds.request: Amount requested must be less than maxLoanAmt");
        require(loanDur_ >= minLoanDur(fund), "Funds.request: Loan duration must be greater than minLoanDur");
        require(loanDur_ <= sub(fundExpiry(fund), now) && loanDur_ <= maxLoanDur(fund), "Funds.request: Loan duration must be less than maxLoanDur and expiry");
        require(borrower_ != address(0), "Funds.request: Borrower address must be non-zero");
        require(secretHashes_[0] != bytes32(0) && secretHashes_[1] != bytes32(0), "Funds.request: SecretHash1 & SecretHash2 should be non-zero");
        require(secretHashes_[2] != bytes32(0) && secretHashes_[3] != bytes32(0), "Funds.request: SecretHash3 & SecretHash4 should be non-zero");
        require(secretHashes_[4] != bytes32(0) && secretHashes_[5] != bytes32(0), "Funds.request: SecretHash5 & SecretHash6 should be non-zero");
        require(secretHashes_[6] != bytes32(0) && secretHashes_[7] != bytes32(0), "Funds.request: SecretHash7 & SecretHash8 should be non-zero");

        loanIndex = createLoan(fund, borrower_, amount_, collateral_, loanDur_, requestTimestamp_);
        loanSetSecretHashes(fund, loanIndex, secretHashes_, pubKeyA_, pubKeyB_);
        loanUpdateMarketLiquidity(fund, amount_);
        loans.fund(loanIndex);

        emit Request(fund, borrower_, amount_, collateral_, loanDur_, requestTimestamp_);
    }

    
    function withdraw(bytes32 fund, uint256 amount_) external {
        withdrawTo(fund, amount_, msg.sender);
    }

    
    function withdrawTo(bytes32 fund, uint256 amount_, address recipient_) public {
        require(msg.sender == lender(fund), "Funds.withdrawTo: Only the lender can withdraw tokens");
        require(balance(fund) >= amount_, "Funds.withdrawTo: Insufficient balance");
        if (bools[fund].compoundEnabled) {
            uint256 cBalanceBefore = cToken.balanceOf(address(this));
            redeemUnderlying(address(cToken), amount_);
            uint256 cBalanceAfter = cToken.balanceOf(address(this));
            uint256 cTokenToRemove = sub(cBalanceBefore, cBalanceAfter);
            funds[fund].cBalance = sub(funds[fund].cBalance, cTokenToRemove);
            require(token.transfer(recipient_, amount_), "Funds.withdrawTo: Token transfer failed");
            if (!custom(fund)) {cTokenMarketLiquidity = sub(cTokenMarketLiquidity, cTokenToRemove);}
        } else {
            funds[fund].balance = sub(funds[fund].balance, amount_);
            require(token.transfer(recipient_, amount_), "Funds.withdrawTo: Token transfer failed");
            if (!custom(fund)) {tokenMarketLiquidity = sub(tokenMarketLiquidity, amount_);}
        }
        if (!custom(fund)) {calcGlobalInterest();}

        emit Withdraw(fund, amount_, recipient_);
    }

    
    function generate(bytes32[] calldata secretHashes_) external {
        for (uint i = 0; i < secretHashes_.length; i++) {
            secretHashes[msg.sender].push(secretHashes_[i]);
        }
    }

    
    function setPubKey(bytes calldata pubKey_) external { 
        pubKeys[msg.sender] = pubKey_;
    }

    
    function enableCompound(bytes32 fund) external {
        require(compoundSet, "Funds.enableCompound: Cannot enable Compound as it has not been configured");
        require(bools[fund].compoundEnabled == false, "Funds.enableCompound: Compound is already enabled");
        require(msg.sender == lender(fund), "Funds.enableCompound: Only the lender can enable Compound");
        uint256 cBalanceBefore = cToken.balanceOf(address(this));
        mintCToken(address(token), address(cToken), funds[fund].balance);
        uint256 cBalanceAfter = cToken.balanceOf(address(this));
        uint256 cTokenToReturn = sub(cBalanceAfter, cBalanceBefore);
        tokenMarketLiquidity = sub(tokenMarketLiquidity, funds[fund].balance);
        cTokenMarketLiquidity = add(cTokenMarketLiquidity, cTokenToReturn);
        bools[fund].compoundEnabled = true;
        funds[fund].balance = 0;
        funds[fund].cBalance = cTokenToReturn;

        emit EnableCompound(fund);
    }

    
    function disableCompound(bytes32 fund) external {
        require(bools[fund].compoundEnabled, "Funds.disableCompound: Compound is already disabled");
        require(msg.sender == lender(fund), "Funds.disableCompound: Only the lender can disable Compound");
        uint256 balanceBefore = token.balanceOf(address(this));
        redeemCToken(address(cToken), funds[fund].cBalance);
        uint256 balanceAfter = token.balanceOf(address(this));
        uint256 tokenToReturn = sub(balanceAfter, balanceBefore);
        tokenMarketLiquidity = add(tokenMarketLiquidity, tokenToReturn);
        cTokenMarketLiquidity = sub(cTokenMarketLiquidity, funds[fund].cBalance);
        bools[fund].compoundEnabled = false;
        funds[fund].cBalance = 0;
        funds[fund].balance = tokenToReturn;

        emit DisableCompound(fund);
    }

    
    function decreaseTotalBorrow(uint256 amount_) external {
        require(msg.sender == address(loans), "Funds.decreaseTotalBorrow: Only the Loans contract can perform this");
        totalBorrow = sub(totalBorrow, amount_);
    }

    
    function calcGlobalInterest() public {
        marketLiquidity = add(tokenMarketLiquidity, wmul(cTokenMarketLiquidity, cTokenExchangeRate()));

        if (now > (add(lastGlobalInterestUpdated, interestUpdateDelay))) {
            uint256 utilizationRatio;
            if (totalBorrow != 0) {utilizationRatio = rdiv(totalBorrow, add(marketLiquidity, totalBorrow));}

            if (utilizationRatio > lastUtilizationRatio) {
                uint256 changeUtilizationRatio = sub(utilizationRatio, lastUtilizationRatio);
                globalInterestRateNumerator = min(maxInterestRateNumerator, add(globalInterestRateNumerator, rdiv(min(maxUtilizationDelta, changeUtilizationRatio), utilizationInterestDivisor)));
            } else {
                uint256 changeUtilizationRatio = sub(lastUtilizationRatio, utilizationRatio);
                globalInterestRateNumerator = max(minInterestRateNumerator, sub(globalInterestRateNumerator, rdiv(min(maxUtilizationDelta, changeUtilizationRatio), utilizationInterestDivisor)));
            }

            globalInterestRate = add(RAY, div(globalInterestRateNumerator, NUM_SECONDS_IN_YEAR));

            lastGlobalInterestUpdated = now;
            lastUtilizationRatio = utilizationRatio;
        }
    }

    
    function calcInterest(uint256 amount_, uint256 rate_, uint256 loanDur_) public pure returns (uint256) {
        return sub(rmul(amount_, rpow(rate_, loanDur_)), amount_);
    }

    
    function ensureNotZero(uint256 value, bool addNow) public view returns (uint256) {
        if (value == 0) {
            if (addNow) {
                return now + MAX_LOAN_LENGTH;
            }
            return MAX_LOAN_LENGTH;
        }
        return value;
    }

    
    function createLoan(
        bytes32  fund,
        address  borrower_,
        uint256  amount_,
        uint256  collateral_,
        uint256  loanDur_,
        uint256  requestTimestamp_
    ) private returns (bytes32 loanIndex) {
        loanIndex = loans.create(
            now + loanDur_,
            [borrower_, lender(fund), funds[fund].arbiter],
            [
                amount_,
                calcInterest(amount_, interest(fund), loanDur_),
                calcInterest(amount_, penalty(fund), loanDur_),
                calcInterest(amount_, fee(fund), loanDur_),
                collateral_,
                liquidationRatio(fund),
                requestTimestamp_
            ],
            fund
        );
    }

    
    function loanSetSecretHashes(
        bytes32           fund,
        bytes32           loan,
        bytes32[8] memory secretHashes_,
        bytes      memory pubKeyA_,
        bytes      memory pubKeyB_
    ) private {
        loans.setSecretHashes(
            loan,
            [ secretHashes_[0], secretHashes_[1], secretHashes_[2], secretHashes_[3] ],
            [ secretHashes_[4], secretHashes_[5], secretHashes_[6], secretHashes_[7] ],
            getSecretHashesForLoan(arbiter(fund)),
            pubKeyA_,
            pubKeyB_,
            pubKeys[arbiter(fund)]
        );
    }

    
    function loanUpdateMarketLiquidity(bytes32 fund, uint256 amount_) private {
        if (bools[fund].compoundEnabled) {
            uint256 cBalanceBefore = cToken.balanceOf(address(this));
            redeemUnderlying(address(cToken), amount_);
            uint256 cBalanceAfter = cToken.balanceOf(address(this));
            uint256 cTokenToRemove = sub(cBalanceBefore, cBalanceAfter);
            funds[fund].cBalance = sub(funds[fund].cBalance, cTokenToRemove);
            if (!custom(fund)) {cTokenMarketLiquidity = sub(cTokenMarketLiquidity, cTokenToRemove);}
        } else {
            funds[fund].balance = sub(funds[fund].balance, amount_);
            if (!custom(fund)) {tokenMarketLiquidity = sub(tokenMarketLiquidity, amount_);}
        }
        if (!custom(fund)) {
            totalBorrow = add(totalBorrow, amount_);
            calcGlobalInterest();
        }
    }

    
    function getSecretHashesForLoan(address addr_) private returns (bytes32[4] memory) {
        secretHashIndex[addr_] = add(secretHashIndex[addr_], 4);
        require(secretHashesCount(addr_) >= secretHashIndex[addr_], "Funds.getSecretHashesForLoan: Not enough secrets generated");
        return [
            secretHashes[addr_][sub(secretHashIndex[addr_], 4)],
            secretHashes[addr_][sub(secretHashIndex[addr_], 3)],
            secretHashes[addr_][sub(secretHashIndex[addr_], 2)],
            secretHashes[addr_][sub(secretHashIndex[addr_], 1)]
        ];
    }
}

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"secretHashIndex","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxUtilizationDelta","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"fund","type":"bytes32"}],"name":"minLoanAmt","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"fund","type":"bytes32"},{"name":"amount_","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"defaultArbiterFee","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"cTokenMarketLiquidity","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DEFAULT_LIQUIDATION_RATIO","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"defaultArbiterFee_","type":"uint256"}],"name":"setDefaultArbiterFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"globalInterestRateNumerator","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"globalInterestRateNumerator_","type":"uint256"}],"name":"setGlobalInterestRateNumerator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"fund","type":"bytes32"},{"name":"amount_","type":"uint256"}],"name":"deposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"fundOwner","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"fund","type":"bytes32"}],"name":"penalty","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"fund","type":"bytes32"}],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastGlobalInterestUpdated","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"calcGlobalInterest","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"MAX_UINT_256","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"fund","type":"bytes32"}],"name":"maxLoanAmt","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"fund","type":"bytes32"}],"name":"arbiter","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DEFAULT_MIN_LOAN_AMT","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"fund","type":"bytes32"},{"name":"maxLoanDur_","type":"uint256"},{"name":"fundExpiry_","type":"uint256"},{"name":"arbiter_","type":"address"}],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getComptrollerAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"utilizationInterestDivisor","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"fund","type":"bytes32"},{"name":"minLoanAmt_","type":"uint256"},{"name":"maxLoanAmt_","type":"uint256"},{"name":"minLoanDur_","type":"uint256"},{"name":"maxLoanDur_","type":"uint256"},{"name":"fundExpiry_","type":"uint256"},{"name":"interest_","type":"uint256"},{"name":"penalty_","type":"uint256"},{"name":"fee_","type":"uint256"},{"name":"liquidationRatio_","type":"uint256"},{"name":"arbiter_","type":"address"}],"name":"updateCustom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"interestUpdateDelay_","type":"uint256"}],"name":"setInterestUpdateDelay","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"secretHashes","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"globalInterestRate","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"comptroller","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"marketLiquidity","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"MAX_LOAN_LENGTH","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"value","type":"uint256"},{"name":"addNow","type":"bool"}],"name":"ensureNotZero","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"minInterestRateNumerator","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"cToken","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"funds","outputs":[{"name":"lender","type":"address"},{"name":"minLoanAmt","type":"uint256"},{"name":"maxLoanAmt","type":"uint256"},{"name":"minLoanDur","type":"uint256"},{"name":"maxLoanDur","type":"uint256"},{"name":"fundExpiry","type":"uint256"},{"name":"interest","type":"uint256"},{"name":"penalty","type":"uint256"},{"name":"fee","type":"uint256"},{"name":"liquidationRatio","type":"uint256"},{"name":"arbiter","type":"address"},{"name":"balance","type":"uint256"},{"name":"cBalance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"maxLoanDur_","type":"uint256"},{"name":"fundExpiry_","type":"uint256"},{"name":"arbiter_","type":"address"},{"name":"compoundEnabled_","type":"bool"},{"name":"amount_","type":"uint256"}],"name":"create","outputs":[{"name":"fund","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"bools","outputs":[{"name":"custom","type":"bool"},{"name":"compoundEnabled","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"fund","type":"bytes32"}],"name":"maxLoanDur","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"fund","type":"bytes32"}],"name":"liquidationRatio","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"fund","type":"bytes32"}],"name":"disableCompound","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalBorrow","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"fund","type":"bytes32"}],"name":"balance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"globalInterestRate_","type":"uint256"}],"name":"setGlobalInterestRate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"amount_","type":"uint256"},{"name":"rate_","type":"uint256"},{"name":"loanDur_","type":"uint256"}],"name":"calcInterest","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"loans_","type":"address"}],"name":"setLoans","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"fund","type":"bytes32"}],"name":"lender","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"fund","type":"bytes32"}],"name":"custom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"maxUtilizationDelta_","type":"uint256"}],"name":"setMaxUtilizationDelta","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"fundIndex","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"fund","type":"bytes32"}],"name":"enableCompound","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"fund","type":"bytes32"}],"name":"minLoanDur","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DEFAULT_MIN_LOAN_DUR","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"fund","type":"bytes32"}],"name":"fundExpiry","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"utilizationInterestDivisor_","type":"uint256"}],"name":"setUtilizationInterestDivisor","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"DEFAULT_LIQUIDATION_PENALTY","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DEFAULT_MAX_LOAN_AMT","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"pubKeys","outputs":[{"name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"addr_","type":"address"}],"name":"secretHashesCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"minInterestRateNumerator_","type":"uint256"}],"name":"setMinInterestRateNumerator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"secretHashes_","type":"bytes32[]"}],"name":"generate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"cToken_","type":"address"},{"name":"comptroller_","type":"address"}],"name":"setCompound","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"NUM_SECONDS_IN_YEAR","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"interestUpdateDelay","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"fund","type":"bytes32"},{"name":"amount_","type":"uint256"},{"name":"recipient_","type":"address"}],"name":"withdrawTo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"pubKey_","type":"bytes"}],"name":"setPubKey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amount_","type":"uint256"}],"name":"decreaseTotalBorrow","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"fund","type":"bytes32"}],"name":"interest","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxInterestRateNumerator","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastUtilizationRatio","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"cTokenExchangeRate","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"fund","type":"bytes32"},{"name":"borrower_","type":"address"},{"name":"amount_","type":"uint256"},{"name":"collateral_","type":"uint256"},{"name":"loanDur_","type":"uint256"},{"name":"requestTimestamp_","type":"uint256"},{"name":"secretHashes_","type":"bytes32[8]"},{"name":"pubKeyA_","type":"bytes"},{"name":"pubKeyB_","type":"bytes"}],"name":"request","outputs":[{"name":"loanIndex","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"minLoanAmt_","type":"uint256"},{"name":"maxLoanAmt_","type":"uint256"},{"name":"minLoanDur_","type":"uint256"},{"name":"maxLoanDur_","type":"uint256"},{"name":"fundExpiry_","type":"uint256"},{"name":"liquidationRatio_","type":"uint256"},{"name":"interest_","type":"uint256"},{"name":"penalty_","type":"uint256"},{"name":"fee_","type":"uint256"},{"name":"arbiter_","type":"address"},{"name":"compoundEnabled_","type":"bool"},{"name":"amount_","type":"uint256"}],"name":"createCustom","outputs":[{"name":"fund","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"x","type":"uint256"},{"name":"y","type":"uint256"}],"name":"cmul","outputs":[{"name":"z","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"maxInterestRateNumerator_","type":"uint256"}],"name":"setMaxInterestRateNumerator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"token","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenMarketLiquidity","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"token_","type":"address"},{"name":"decimals_","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"fund","type":"bytes32"}],"name":"Create","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"fund","type":"bytes32"},{"indexed":false,"name":"amount_","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"fund","type":"bytes32"},{"indexed":false,"name":"maxLoanDur_","type":"uint256"},{"indexed":false,"name":"fundExpiry_","type":"uint256"},{"indexed":false,"name":"arbiter_","type":"address"}],"name":"Update","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"fund","type":"bytes32"},{"indexed":false,"name":"borrower_","type":"address"},{"indexed":false,"name":"amount_","type":"uint256"},{"indexed":false,"name":"collateral_","type":"uint256"},{"indexed":false,"name":"loanDur_","type":"uint256"},{"indexed":false,"name":"requestTimestamp_","type":"uint256"}],"name":"Request","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"fund","type":"bytes32"},{"indexed":false,"name":"amount_","type":"uint256"},{"indexed":false,"name":"recipient_","type":"address"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"fund","type":"bytes32"}],"name":"EnableCompound","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"fund","type":"bytes32"}],"name":"DisableCompound","type":"event"}]

60806040523480156200001157600080fd5b506040516200590638038062005906833981810160405260408110156200003757600080fd5b5080516020909101516001600160a01b038216620000a1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526031815260200180620058a96031913960400191505060405180910390fd5b80620000f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180620058da602c913960400191505060405180910390fd5b601a8054336001600160a01b031991821617909155601780549091166001600160a01b03841617905560188190556b22079eda249d327c677048096012556a4ed6b7353f71d0a0f402496011819055600e8190556a96d0176d4a7d47fc102c6f6013556a146cdd36157a9553e20f0a601455620151806015556b033b2e3ca31a444ebbf023c4601655620001b4906b033b2e3c9fd0803ce800000090620001a5906301e13380620001c0565b6001600160e01b03620001e116565b60105550620001f89050565b6000808211620001cf57600080fd5b818381620001d957fe5b049392505050565b80820182811015620001f257600080fd5b92915050565b6156a180620002086000396000f3fe608060405234801561001057600080fd5b50600436106104545760003560e01c806376a0b16611610241578063d39a2c0c1161013b578063e91d14a4116100c3578063f61d02d311610087578063f61d02d314610de2578063f7837eb714610e51578063fa3bfb1714610e74578063fc0c546a14610e91578063fdd5aab114610e9957610454565b8063e91d14a414610cb9578063eae1c2cf14610cd6578063f05541be14610cde578063f0a422d014610ce6578063f59bf27314610cee57610454565b8063da2c5c5b1161010a578063da2c5c5b14610bec578063db9b376c14610bf4578063e179e77114610bfc578063e32d291314610c2e578063e493325614610c9c57610454565b8063d39a2c0c14610b0d578063d4785d2914610b33578063d73b906214610b50578063d9d0a2d114610bbe57610454565b8063a2c70b6b116101c9578063ba617eef1161018d578063ba617eef14610a30578063bf12f43d14610a4d578063ccb99d5514610a6a578063ce26d44b146105d0578063d1b8b4bf14610a7257610454565b8063a2c70b6b146109c9578063a5a70965146109e6578063a5fa6706146109ee578063a634baf214610a0b578063b2d6107114610a2857610454565b80638c5d5268116102105780638c5d52681461090f578063994871fa1461092c5780639d06bcea146109555780639fc3f02f1461097b578063a18e4a801461099857610454565b806376a0b166146108b05780637e25a221146108cd5780638285ef40146108ea57806389eba421146108f257610454565b806344b6ba95116103525780635fe3b567116102da57806369e527da1161029e57806369e527da1461077a5780636a29a620146107825780636a7bb32c1461081b5780636e1719a61461085b578063712d8e6a1461089357610454565b80635fe3b56714610735578063612ef80b1461073d5780636158153d14610745578063668064da1461074d578063689c76ef1461077257610454565b80634f9bc9d5116103215780634f9bc9d514610676578063513916741461067e578063516dbe24146106e457806354e39f90146107015780635b873ffa1461072d57610454565b806344b6ba95146105f557806347ca77161461062e5780634c9fb84a146106365780634ee9159a1461066e57610454565b80631beec294116103e05780632eb1ad73116103a45780632eb1ad73146105b8578063313ce567146105c057806333549b1b146105c85780633d41a26b146105d057806342febf0c146105d857610454565b80631beec294146105185780631de26e161461053557806321fd933b1461055857806326fc75901461057e57806327cdab061461059b57610454565b806304e9ef031161042757806304e9ef03146104db57806316df840a146104e35780631723cfa5146104eb5780631873fe50146104f35780631bb736971461051057610454565b806301937d0414610459578063031558e51461049157806303b69d1814610499578063040cf020146104b6575b600080fd5b61047f6004803603602081101561046f57600080fd5b50356001600160a01b0316610ea1565b60408051918252519081900360200190f35b61047f610eb3565b61047f600480360360208110156104af57600080fd5b5035610eb9565b6104d9600480360360408110156104cc57600080fd5b5080359060200135610f12565b005b61047f610f21565b61047f610f27565b61047f610f2d565b6104d96004803603602081101561050957600080fd5b5035610f3d565b61047f610fd6565b6104d96004803603602081101561052e57600080fd5b5035610fdc565b6104d96004803603604081101561054b57600080fd5b5080359060200135611066565b61047f6004803603602081101561056e57600080fd5b50356001600160a01b03166112eb565b61047f6004803603602081101561059457600080fd5b50356112fd565b61047f600480360360208110156105b157600080fd5b503561133f565b61047f611377565b61047f61137d565b6104d9611383565b61047f611495565b61047f600480360360208110156105ee57600080fd5b503561149b565b6106126004803603602081101561060b57600080fd5b50356114d3565b604080516001600160a01b039092168252519081900360200190f35b61047f6114f1565b6104d96004803603608081101561064c57600080fd5b50803590602081013590604081013590606001356001600160a01b03166114fe565b610612611648565b61047f611658565b6104d9600480360361016081101561069557600080fd5b5080359060208101359060408101359060608101359060808101359060a08101359060c08101359060e081013590610100810135906101208101359061014001356001600160a01b031661165e565b6104d9600480360360208110156106fa57600080fd5b503561177e565b61047f6004803603604081101561071757600080fd5b506001600160a01b038135169060200135611808565b61047f611836565b61061261183c565b61047f61184b565b61047f611851565b61047f6004803603604081101561076357600080fd5b50803590602001351515611859565b61047f611887565b61061261188d565b61079f6004803603602081101561079857600080fd5b503561189c565b604080516001600160a01b039e8f168152602081019d909d528c81019b909b5260608c019990995260808b019790975260a08a019590955260c089019390935260e08801919091526101008701526101208601529094166101408401526101608301939093526101808201929092529051908190036101a00190f35b61047f600480360360a081101561083157600080fd5b508035906020810135906001600160a01b0360408201351690606081013515159060800135611910565b6108786004803603602081101561087157600080fd5b5035611b30565b60408051921515835290151560208301528051918290030190f35b61047f600480360360208110156108a957600080fd5b5035611b4e565b61047f600480360360208110156108c657600080fd5b5035611b63565b6104d9600480360360208110156108e357600080fd5b5035611ba5565b61047f611e15565b61047f6004803603602081101561090857600080fd5b5035611e1b565b6104d96004803603602081101561092557600080fd5b5035611edc565b61047f6004803603606081101561094257600080fd5b5080359060208101359060400135611f66565b6104d96004803603602081101561096b57600080fd5b50356001600160a01b0316611f8c565b6106126004803603602081101561099157600080fd5b5035612138565b6109b5600480360360208110156109ae57600080fd5b5035612153565b604080519115158252519081900360200190f35b6104d9600480360360208110156109df57600080fd5b5035612168565b61047f6121f2565b6104d960048036036020811015610a0457600080fd5b50356121f8565b61047f60048036036020811015610a2157600080fd5b50356124bd565b61047f6124f5565b61047f60048036036020811015610a4657600080fd5b50356124fb565b6104d960048036036020811015610a6357600080fd5b5035612511565b61047f61259b565b610a9860048036036020811015610a8857600080fd5b50356001600160a01b03166125ab565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610ad2578181015183820152602001610aba565b50505050905090810190601f168015610aff5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61047f60048036036020811015610b2357600080fd5b50356001600160a01b0316612646565b6104d960048036036020811015610b4957600080fd5b5035612661565b6104d960048036036020811015610b6657600080fd5b810190602081018135600160201b811115610b8057600080fd5b820183602082011115610b9257600080fd5b803590602001918460208302840111600160201b83111715610bb357600080fd5b5090925090506126eb565b6104d960048036036040811015610bd457600080fd5b506001600160a01b0381358116916020013516612740565b61047f61289a565b61047f6128a2565b6104d960048036036060811015610c1257600080fd5b50803590602081013590604001356001600160a01b03166128a8565b6104d960048036036020811015610c4457600080fd5b810190602081018135600160201b811115610c5e57600080fd5b820183602082011115610c7057600080fd5b803590602001918460018302840111600160201b83111715610c9157600080fd5b509092509050612cf5565b6104d960048036036020811015610cb257600080fd5b5035612d0f565b61047f60048036036020811015610ccf57600080fd5b5035612d6a565b61047f612da2565b61047f612da8565b61047f612dae565b61047f6004803603610200811015610d0557600080fd5b8135916001600160a01b036020820135169160408201359160608101359160808201359160a08101359160c0820191908101906101e081016101c0820135600160201b811115610d5457600080fd5b820183602082011115610d6657600080fd5b803590602001918460018302840111600160201b83111715610d8757600080fd5b919390929091602081019035600160201b811115610da457600080fd5b820183602082011115610db657600080fd5b803590602001918460018302840111600160201b83111715610dd757600080fd5b509092509050612e4e565b61047f6004803603610180811015610df957600080fd5b5080359060208101359060408101359060608101359060808101359060a08101359060c08101359060e081013590610100810135906001600160a01b0361012082013516906101408101351515906101600135613336565b61047f60048036036040811015610e6757600080fd5b508035906020013561367a565b6104d960048036036020811015610e8a57600080fd5b50356136ab565b610612613735565b61047f613744565b60036020526000908152604090205481565b60115481565b60008181526007602052604081205460ff1615610ee85750600081815260056020526040902060010154610f0d565b610f0a68015af1d78b58c40000610f02601260185461374a565b600a0a61375a565b90505b919050565b610f1d8282336128a8565b5050565b60165481565b600b5481565b6b04860d8812f0b3887800000081565b601a546001600160a01b03163314610f865760405162461bcd60e51b815260040180806020018281038252603e815260200180614fb3603e913960400191505060405180910390fd5b6b033b2e3ca43176a9d2dfd0a5811115610fd15760405162461bcd60e51b81526004018080602001828103825260458152602001806154b06045913960600191505060405180910390fd5b601655565b600e5481565b601a546001600160a01b031633146110255760405162461bcd60e51b8152600401808060200182810382526048815260200180614b506048913960600191505060405180910390fd5b806110615760405162461bcd60e51b81526004018080602001828103825260498152602001806150316049913960600191505060405180910390fd5b600e55565b601754604080516323b872dd60e01b81523360048201523060248201526044810184905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b1580156110c057600080fd5b505af11580156110d4573d6000803e3d6000fd5b505050506040513d60208110156110ea57600080fd5b50516111275760405162461bcd60e51b81526004018080602001828103825260288152602001806150ee6028913960400191505060405180910390fd5b600082815260076020526040902054610100900460ff161561124c57601754601954611160916001600160a01b03908116911683613771565b60006111f861117783670de0b6b3a764000061388b565b601960009054906101000a90046001600160a01b03166001600160a01b031663bd6d894d6040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156111c757600080fd5b505af11580156111db573d6000803e3d6000fd5b505050506040513d60208110156111f157600080fd5b505161375a565b6000848152600560205260409020600c015490915061121790826138af565b6000848152600560205260409020600c015561123283612153565b61124657611242600b54826138af565b600b555b50611297565b6000828152600560205260409020600b015461126890826138af565b6000838152600560205260409020600b015561128382612153565b61129757611293600a54826138af565b600a555b6112a082612153565b6112ac576112ac611383565b604080518381526020810183905281517f98e783c3864bbf744a057ef605a2a61701c3b62b5ed68b3745b99094497daf1f929181900390910190a15050565b60066020526000908152604090205481565b60008181526007602052604081205460ff161561132c5750600081815260056020526040902060070154610f0d565b506b033b2e3cacd278c7503e82c1610f0d565b60008181526007602052604081205460ff161561136e5750600081815260056020526040902060080154610f0d565b50601654610f0d565b60095481565b60185481565b6113a1600a5461139c600b54611397612dae565b6138bf565b6138af565b600c556009546015546113b491906138af565b421115611493576000600d546000146113e3576113e0600d546113db600c54600d546138af565b6138e7565b90505b600f5481111561142e5760006113fb82600f5461374a565b9050611425601354611420600e5461139c6114186011548761390b565b6012546138e7565b61390b565b600e5550611468565b600061143c600f548361374a565b905061146360145461145e600e546114596114186011548761390b565b61374a565b61391e565b600e55505b6114886b033b2e3c9fd0803ce800000061139c600e546301e1338061375a565b60105542600955600f555b565b60001981565b60008181526007602052604081205460ff16156114ca5750600081815260056020526040902060020154610f0d565b50600019610f0d565b6000908152600560205260409020600a01546001600160a01b031690565b68015af1d78b58c4000081565b61150784612138565b6001600160a01b0316336001600160a01b0316146115565760405162461bcd60e51b8152600401808060200182810382526031815260200180614e246031913960400191505060405180910390fd5b6312cc0300611566846000611859565b111580156115845750426312cc030001611581836001611859565b11155b6115bf5760405162461bcd60e51b815260040180806020018281038252603e815260200180614bd4603e913960400191505060405180910390fd5b60008481526005602081815260409283902060048101879055918201859055600a90910180546001600160a01b0385166001600160a01b031990911681179091558251878152918201869052818301859052606082015290517fbc2980147202467df8874a7f933ee11c59b6b1f6273647aca58bd18d349e67ac9181900360800190a150505050565b6000546001600160a01b03165b90565b60125481565b60008b81526007602052604090205460ff166116ab5760405162461bcd60e51b815260040180806020018281038252602e8152602001806154f5602e913960400191505060405180910390fd5b898910156116ea5760405162461bcd60e51b815260040180806020018281038252604a815260200180614c52604a913960600191505060405180910390fd5b876116f6886000611859565b10156117335760405162461bcd60e51b815260040180806020018281038252604a81526020018061534c604a913960600191505060405180910390fd5b61173f8b8888846114fe565b506000998a5260056020526040909920600181019890985560028801969096556003870194909455600686015550506007830155600882015560090155565b601a546001600160a01b031633146117c75760405162461bcd60e51b8152600401808060200182810382526040815260200180614ff16040913960400191505060405180910390fd5b806118035760405162461bcd60e51b8152600401808060200182810382526039815260200180614b176039913960400191505060405180910390fd5b601555565b6002602052816000526040600020818154811061182157fe5b90600052602060002001600091509150505481565b60105481565b6000546001600160a01b031681565b600c5481565b6312cc030081565b60008261187e5781156118735750426312cc030001611881565b506312cc0300611881565b50815b92915050565b60145481565b6019546001600160a01b031681565b600560208190526000918252604090912080546001820154600283015460038401546004850154958501546006860154600787015460088801546009890154600a8a0154600b8b0154600c909b01546001600160a01b039a8b169c999b989a9799989697959694959394929390911691908d565b336000818152600660209081526040808320548352600590915281205490916001600160a01b0390911614156119775760405162461bcd60e51b8152600401808060200182810382526034815260200180614e8e6034913960400191505060405180910390fd5b6312cc0300611987876000611859565b1080156119a35750426312cc0300016119a1866001611859565b105b6119de5760405162461bcd60e51b815260040180806020018281038252603e815260200180614d91603e913960400191505060405180910390fd5b601954600160a01b900460ff16611a2c578215611a2c5760405162461bcd60e51b81526004018080602001828103825260428152602001806151cc6042913960600191505060405180910390fd5b611a3960085460016138af565b6008819055600081815260056020526040812080546001600160a01b03191633179055909150611a6a908790611859565b600082815260056020526040902060040155611a87856001611859565b600082815260056020818152604080842092830194909455600a90910180546001600160a01b0319166001600160a01b03891617905560078152828220805461ffff1916610100881515021790556008543383526006909152919020558115611af457611af48183611066565b6040805182815290517fa7857d7da6974b0157f3bf7dd25a745bd7d81d845bb525ee0b316a87541a5c319181900360200190a195945050505050565b60076020526000908152604090205460ff8082169161010090041682565b60009081526005602052604090206004015490565b60008181526007602052604081205460ff1615611b925750600081815260056020526040902060090154610f0d565b506b04860d8812f0b38878000000610f0d565b600081815260076020526040902054610100900460ff16611bf75760405162461bcd60e51b81526004018080602001828103825260338152602001806149ce6033913960400191505060405180910390fd5b611c0081612138565b6001600160a01b0316336001600160a01b031614611c4f5760405162461bcd60e51b815260040180806020018281038252603b815260200180614d56603b913960400191505060405180910390fd5b601754604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015611c9a57600080fd5b505afa158015611cae573d6000803e3d6000fd5b505050506040513d6020811015611cc457600080fd5b50516019546000848152600560205260409020600c0154919250611cf3916001600160a01b039091169061392e565b601754604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015611d3e57600080fd5b505afa158015611d52573d6000803e3d6000fd5b505050506040513d6020811015611d6857600080fd5b505190506000611d78828461374a565b9050611d86600a54826138af565b600a55600b546000858152600560205260409020600c0154611da8919061374a565b600b9081556000858152600760209081526040808320805461ff001916905560058252808320600c81019390935591909201839055805186815290517ffb6e0a1c4958f3e250db013b5035dc019d1e6426df7b4a40a5d0229a336aad53929181900390910190a150505050565b600d5481565b600081815260076020526040812054610100900460ff1615611ec4576000828152600560209081526040808320600c0154601954825163bd6d894d60e01b81529251610f0a9592946001600160a01b039092169363bd6d894d9360048083019493928390030190829087803b158015611e9357600080fd5b505af1158015611ea7573d6000803e3d6000fd5b505050506040513d6020811015611ebd57600080fd5b50516138bf565b506000818152600560205260409020600b0154610f0d565b601a546001600160a01b03163314611f255760405162461bcd60e51b815260040180806020018281038252603f81526020018061520e603f913960400191505060405180910390fd5b80611f615760405162461bcd60e51b81526004018080602001828103825260378152602001806152976037913960400191505060405180910390fd5b601055565b6000611f84611f7e85611f798686613a7e565b613ad8565b8561374a565b949350505050565b601a546001600160a01b03163314611fd55760405162461bcd60e51b8152600401808060200182810382526032815260200180614df26032913960400191505060405180910390fd5b6001546001600160a01b03161561201d5760405162461bcd60e51b8152600401808060200182810382526032815260200180614c9c6032913960400191505060405180910390fd5b6001600160a01b0381166120625760405162461bcd60e51b815260040180806020018281038252602e815260200180615449602e913960400191505060405180910390fd5b600180546001600160a01b0319166001600160a01b038381169182179092556017546040805163095ea7b360e01b8152600481019390935260001960248401525192169163095ea7b3916044808201926020929091908290030181600087803b1580156120ce57600080fd5b505af11580156120e2573d6000803e3d6000fd5b505050506040513d60208110156120f857600080fd5b50516121355760405162461bcd60e51b815260040180806020018281038252602981526020018061496e6029913960400191505060405180910390fd5b50565b6000908152600560205260409020546001600160a01b031690565b60009081526007602052604090205460ff1690565b601a546001600160a01b031633146121b15760405162461bcd60e51b81526004018080602001828103825260408152602001806155496040913960400191505060405180910390fd5b806121ed5760405162461bcd60e51b8152600401808060200182810382526039815260200180614e556039913960400191505060405180910390fd5b601155565b60085481565b601954600160a01b900460ff166122405760405162461bcd60e51b815260040180806020018281038252604a81526020018061524d604a913960600191505060405180910390fd5b600081815260076020526040902054610100900460ff16156122935760405162461bcd60e51b815260040180806020018281038252603181526020018061493d6031913960400191505060405180910390fd5b61229c81612138565b6001600160a01b0316336001600160a01b0316146122eb5760405162461bcd60e51b81526004018080602001828103825260398152602001806154776039913960400191505060405180910390fd5b601954604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561233657600080fd5b505afa15801561234a573d6000803e3d6000fd5b505050506040513d602081101561236057600080fd5b50516017546019546000858152600560205260409020600b0154929350612396926001600160a01b039283169290911690613771565b601954604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156123e157600080fd5b505afa1580156123f5573d6000803e3d6000fd5b505050506040513d602081101561240b57600080fd5b50519050600061241b828461374a565b600a546000868152600560205260409020600b015491925061243c9161374a565b600a55600b5461244c90826138af565b600b9081556000858152600760209081526040808320805461ff0019166101001790556005825280832093840192909255600c909201839055805186815290517f43c40c3c72eec13a64775a3231f52699c8ba28e57131e7343e4f57734d8a3ce4929181900390910190a150505050565b60008181526007602052604081205460ff16156124ec5750600081815260056020526040902060030154610f0d565b50615460610f0d565b61546081565b6000908152600560208190526040909120015490565b601a546001600160a01b0316331461255a5760405162461bcd60e51b8152600401808060200182810382526047815260200180614a016047913960600191505060405180910390fd5b806125965760405162461bcd60e51b81526004018080602001828103825260478152602001806148f66047913960600191505060405180910390fd5b601255565b6b033b2e3cacd278c7503e82c181565b60046020908152600091825260409182902080548351601f60026000196101006001861615020190931692909204918201849004840281018401909452808452909183018282801561263e5780601f106126135761010080835404028352916020019161263e565b820191906000526020600020905b81548152906001019060200180831161262157829003601f168201915b505050505081565b6001600160a01b031660009081526002602052604090205490565b601a546001600160a01b031633146126aa5760405162461bcd60e51b8152600401808060200182810382526045815260200180614cce6045913960600191505060405180910390fd5b806126e65760405162461bcd60e51b8152600401808060200182810382526043815260200180614a486043913960600191505060405180910390fd5b601455565b60005b8181101561273b5733600090815260026020526040902083838381811061271157fe5b835460018082018655600095865260209586902092909502939093013592019190915550016126ee565b505050565b601a546001600160a01b031633146127895760405162461bcd60e51b8152600401808060200182810382526040815260200180614c126040913960400191505060405180910390fd5b601954600160a01b900460ff16156127d25760405162461bcd60e51b8152600401808060200182810382526038815260200180614f016038913960400191505060405180910390fd5b6001600160a01b0382166128175760405162461bcd60e51b81526004018080602001828103825260328152602001806155896032913960400191505060405180910390fd5b6001600160a01b03811661285c5760405162461bcd60e51b81526004018080602001828103825260378152602001806149976037913960400191505060405180910390fd5b60198054600080546001600160a01b039485166001600160a01b03199182161790915560ff60a01b199390941693169290921716600160a01b179055565b6301e1338081565b60155481565b6128b183612138565b6001600160a01b0316336001600160a01b0316146129005760405162461bcd60e51b81526004018080602001828103825260358152602001806153d16035913960400191505060405180910390fd5b8161290a84611e1b565b10156129475760405162461bcd60e51b81526004018080602001828103825260268152602001806155236026913960400191505060405180910390fd5b600083815260076020526040902054610100900460ff1615612b8b57601954604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156129ae57600080fd5b505afa1580156129c2573d6000803e3d6000fd5b505050506040513d60208110156129d857600080fd5b50516019549091506129f3906001600160a01b031684613b08565b601954604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015612a3e57600080fd5b505afa158015612a52573d6000803e3d6000fd5b505050506040513d6020811015612a6857600080fd5b505190506000612a78838361374a565b6000878152600560205260409020600c0154909150612a97908261374a565b6000878152600560209081526040808320600c0193909355601754835163a9059cbb60e01b81526001600160a01b038981166004830152602482018b90529451949091169363a9059cbb93604480840194938390030190829087803b158015612aff57600080fd5b505af1158015612b13573d6000803e3d6000fd5b505050506040513d6020811015612b2957600080fd5b5051612b665760405162461bcd60e51b81526004018080602001828103825260278152602001806151166027913960400191505060405180910390fd5b612b6f86612153565b612b8357612b7f600b548261374a565b600b555b505050612c93565b6000838152600560205260409020600b0154612ba7908361374a565b6000848152600560209081526040808320600b0193909355601754835163a9059cbb60e01b81526001600160a01b038681166004830152602482018890529451949091169363a9059cbb93604480840194938390030190829087803b158015612c0f57600080fd5b505af1158015612c23573d6000803e3d6000fd5b505050506040513d6020811015612c3957600080fd5b5051612c765760405162461bcd60e51b81526004018080602001828103825260278152602001806151166027913960400191505060405180910390fd5b612c7f83612153565b612c9357612c8f600a548361374a565b600a555b612c9c83612153565b612ca857612ca8611383565b60408051848152602081018490526001600160a01b0383168183015290517f181177e6e9bbf7d7a45604cf4fdb0444641e20905d8d4daf2a7863036e56dc159181900360600190a1505050565b33600090815260046020526040902061273b90838361483f565b6001546001600160a01b03163314612d585760405162461bcd60e51b8152600401808060200182810382526043815260200180614d136043913960600191505060405180910390fd5b612d64600d548261374a565b600d5550565b60008181526007602052604081205460ff1615612d995750600081815260056020526040902060060154610f0d565b50601054610f0d565b60135481565b600f5481565b601954600090600160a01b900460ff1615612e4657601960009054906101000a90046001600160a01b03166001600160a01b031663bd6d894d6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612e1357600080fd5b505af1158015612e27573d6000803e3d6000fd5b505050506040513d6020811015612e3d57600080fd5b50519050611655565b506000611655565b6000612e598c612138565b6001600160a01b0316336001600160a01b031614612ea85760405162461bcd60e51b81526004018080602001828103825260398152602001806150b56039913960400191505060405180910390fd5b612eb18c611e1b565b8a1115612eef5760405162461bcd60e51b8152600401808060200182810382526023815260200180614dcf6023913960400191505060405180910390fd5b612ef88c610eb9565b8a1015612f365760405162461bcd60e51b815260040180806020018281038252603f815260200180614ec2603f913960400191505060405180910390fd5b612f3f8c61149b565b8a1115612f7d5760405162461bcd60e51b815260040180806020018281038252603c815260200180614b98603c913960400191505060405180910390fd5b612f868c6124bd565b881015612fc45760405162461bcd60e51b815260040180806020018281038252603c815260200180615631603c913960400191505060405180910390fd5b612fd6612fd08d6124fb565b4261374a565b8811158015612fed5750612fe98c611b4e565b8811155b6130285760405162461bcd60e51b8152600401808060200182810382526044815260200180614a8b6044913960600191505060405180910390fd5b6001600160a01b038b1661306d5760405162461bcd60e51b8152600401808060200182810382526030815260200180614f396030913960400191505060405180910390fd5b8535158015906130805750602086013515155b6130bb5760405162461bcd60e51b815260040180806020018281038252603b8152602001806155bb603b913960400191505060405180910390fd5b6040860135158015906130d15750606086013515155b61310c5760405162461bcd60e51b815260040180806020018281038252603b8152602001806155f6603b913960400191505060405180910390fd5b608086013515801590613122575060a086013515155b61315d5760405162461bcd60e51b815260040180806020018281038252603b815260200180615396603b913960400191505060405180910390fd5b60c086013515801590613173575060e086013515155b6131ae5760405162461bcd60e51b815260040180806020018281038252603b81526020018061507a603b913960400191505060405180910390fd5b6131bc8c8c8c8c8c8c613cbb565b905061325a8c8288600880602002604051908101604052809291908260086020028082843760009201919091525050604080516020601f8c018190048102820181019092528a815291508a908a908190840183828082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a9150899081908401838280828437600092019190915250613e5092505050565b6132648c8b61412f565b6001546040805163bf14c11960e01b81526004810184905290516001600160a01b039092169163bf14c1199160248082019260009290919082900301818387803b1580156132b157600080fd5b505af11580156132c5573d6000803e3d6000fd5b5050604080518f81526001600160a01b038f1660208201528082018e9052606081018d9052608081018c905260a081018b905290517ff494fa7145682762e6918aefe85748818b2f1092c6f8c0a3284bcb18506416d593509081900360c0019150a19b9a5050505050505050505050565b336000818152600660209081526040808320548352600590915281205490916001600160a01b03909116141561339d5760405162461bcd60e51b8152600401808060200182810382526034815260200180614e8e6034913960400191505060405180910390fd5b6312cc03006133ad8b6000611859565b1080156133c95750426312cc0300016133c78a6001611859565b105b6134045760405162461bcd60e51b81526004018080602001828103825260448152602001806152ce6044913960600191505060405180910390fd5b8c8c10156134435760405162461bcd60e51b815260040180806020018281038252604a815260200180615182604a913960600191505060405180910390fd5b8a61344f8b6000611859565b101561348c5760405162461bcd60e51b815260040180806020018281038252604a815260200180614f69604a913960600191505060405180910390fd5b601954600160a01b900460ff166134da5782156134da5760405162461bcd60e51b8152600401808060200182810382526048815260200180614acf6048913960600191505060405180910390fd5b6134e760085460016138af565b60088190555060085460001b9050336005600083815260200190815260200160002060000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508c60056000838152602001908152602001600020600101819055508b60056000838152602001908152602001600020600201819055508a600560008381526020019081526020016000206003018190555061358c8a6000611859565b6000828152600560205260409020600401556135a9896001611859565b60008281526005602081815260408084209283019490945560068083018c905560078084018c905560088085018c9055600985018f9055600a90940180546001600160a01b0319166001600160a01b038c161790558252848420805460ff191660011761ff0019166101008a1515021790559154338452919052919020558115613637576136378183611066565b6040805182815290517fa7857d7da6974b0157f3bf7dd25a745bd7d81d845bb525ee0b316a87541a5c319181900360200190a19c9b505050505050505050505050565b60006305f5e10061369c61368e858561388b565b60026305f5e1005b046138af565b816136a357fe5b049392505050565b601a546001600160a01b031633146136f45760405162461bcd60e51b815260040180806020018281038252604581526020018061513d6045913960600191505060405180910390fd5b806137305760405162461bcd60e51b81526004018080602001828103825260438152602001806154066043913960600191505060405180910390fd5b601355565b6017546001600160a01b031681565b600a5481565b8082038281111561188157600080fd5b600080821161376857600080fd5b8183816136a357fe5b61377a82614325565b604080516370a0823160e01b8152306004820152905184916000916001600160a01b038416916370a08231916024808301926020929190829003018186803b1580156137c557600080fd5b505afa1580156137d9573d6000803e3d6000fd5b505050506040513d60208110156137ef57600080fd5b50519050828111156137fe5750815b8361380a8683836145a8565b806001600160a01b031663a0712d68836040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b15801561385057600080fd5b505af1158015613864573d6000803e3d6000fd5b505050506040513d602081101561387a57600080fd5b50511561388357fe5b505050505050565b60008115806138a6575050808202828282816138a357fe5b04145b61188157600080fd5b8082018281101561188157600080fd5b6000670de0b6b3a764000061369c6138d7858561388b565b6002670de0b6b3a7640000613696565b60008161369c613903856b033b2e3c9fd0803ce800000061388b565b600285613696565b60008183111561187e57815b9392505050565b60008183101561187e5781613917565b604080516370a0823160e01b8152306004820152905183916000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561397957600080fd5b505afa15801561398d573d6000803e3d6000fd5b505050506040513d60208110156139a357600080fd5b50519050828111156139b25750815b6139bd8482866145a8565b816001600160a01b031663db006a75826040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015613a0357600080fd5b505af1158015613a17573d6000803e3d6000fd5b505050506040513d6020811015613a2d57600080fd5b505115613a78576040805162461bcd60e51b8152602060048201526014602482015273736f6d657468696e672077656e742077726f6e6760601b604482015290519081900360640190fd5b50505050565b600060028206613a9a576b033b2e3c9fd0803ce8000000613a9c565b825b90506002820491505b811561188157613ab58384613ad8565b92506002820615613acd57613aca8184613ad8565b90505b600282049150613aa5565b60006b033b2e3c9fd0803ce800000061369c613af4858561388b565b60026b033b2e3c9fd0803ce8000000613696565b81613b298174446c3b15f9926687d2c40534fdb564000000000000816145a8565b604080516370a0823160e01b815230600482015290516000916001600160a01b038416916370a0823191602480820192602092909190829003018186803b158015613b7357600080fd5b505afa158015613b87573d6000803e3d6000fd5b505050506040513d6020811015613b9d57600080fd5b50516040805163bd6d894d60e01b81529051919250600091613bec9184916001600160a01b0387169163bd6d894d91600480830192602092919082900301818987803b158015611e9357600080fd5b905083811115613bf95750825b826001600160a01b031663852a12e3826040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015613c3f57600080fd5b505af1158015613c53573d6000803e3d6000fd5b505050506040513d6020811015613c6957600080fd5b505115613cb4576040805162461bcd60e51b8152602060048201526014602482015273736f6d657468696e672077656e742077726f6e6760601b604482015290519081900360640190fd5b5050505050565b60015460408051606081019091526001600160a01b03878116825260009216906310375921904286019060208101613cf28c612138565b6001600160a01b03908116825260008d815260056020908152604091829020600a015490921692820192909252815160e081019092528a82528101613d408b613d3a8f612d6a565b8b611f66565b8152602001613d528b613d3a8f6112fd565b8152602001613d648b613d3a8f61133f565b8152602001898152602001613d788d611b63565b81526020018790526040516001600160e01b031960e086901b168152600481018481528d9160240184606080838360005b83811015613dc1578181015183820152602001613da9565b5050505090500183600760200280838360005b83811015613dec578181015183820152602001613dd4565b50505050905001828152602001945050505050602060405180830381600087803b158015613e1957600080fd5b505af1158015613e2d573d6000803e3d6000fd5b505050506040513d6020811015613e4357600080fd5b5051979650505050505050565b600154604080516080808201835286518252602080880151818401528784015183850152606080890151908401528351808301855291880151825260a0880151908201526001600160a01b039093169263ee79b12b928892919081018860066020020151815260200188600760088110613ec657fe5b60200201519052613ede613ed98b6114d3565b614688565b878760046000613eed8f6114d3565b6001600160a01b03166001600160a01b031681526020019081526020016000206040518863ffffffff1660e01b81526004018088815260200187600460200280838360005b83811015613f4a578181015183820152602001613f32565b5050505090500186600460200280838360005b83811015613f75578181015183820152602001613f5d565b5050505090500185600460200280838360005b83811015613fa0578181015183820152602001613f88565b50505050905001806020018060200180602001848103845287818151815260200191508051906020019080838360005b83811015613fe8578181015183820152602001613fd0565b50505050905090810190601f1680156140155780820380516001836020036101000a031916815260200191505b50848103835286518152865160209182019188019080838360005b83811015614048578181015183820152602001614030565b50505050905090810190601f1680156140755780820380516001836020036101000a031916815260200191505b508481038252855460026000196101006001841615020190911604808252602090910190869080156140e85780601f106140bd576101008083540402835291602001916140e8565b820191906000526020600020905b8154815290600101906020018083116140cb57829003601f168201915b50509a5050505050505050505050600060405180830381600087803b15801561411057600080fd5b505af1158015614124573d6000803e3d6000fd5b505050505050505050565b600082815260076020526040902054610100900460ff16156142b657601954604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561419657600080fd5b505afa1580156141aa573d6000803e3d6000fd5b505050506040513d60208110156141c057600080fd5b50516019549091506141db906001600160a01b031683613b08565b601954604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561422657600080fd5b505afa15801561423a573d6000803e3d6000fd5b505050506040513d602081101561425057600080fd5b505190506000614260838361374a565b6000868152600560205260409020600c015490915061427f908261374a565b6000868152600560205260409020600c015561429a85612153565b6142ae576142aa600b548261374a565b600b555b505050614301565b6000828152600560205260409020600b01546142d2908261374a565b6000838152600560205260409020600b01556142ed82612153565b614301576142fd600a548261374a565b600a555b61430a82612153565b610f1d5761431a600d54826138af565b600d55610f1d611383565b600061432f611648565b60408051632aff3bff60e21b815230600482015290519192506060916001600160a01b0384169163abfceffc916024808301926000929190829003018186803b15801561437b57600080fd5b505afa15801561438f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156143b857600080fd5b810190808051600160201b8111156143cf57600080fd5b820160208101848111156143e257600080fd5b81518560208202830111600160201b821117156143fe57600080fd5b509094506000935083925050505b825181101561444f57846001600160a01b031683828151811061442b57fe5b60200260200101516001600160a01b0316141561444757600191505b60010161440c565b5080613a785760408051600180825281830190925260609160208083019080388339019050509050848160008151811061448557fe5b6001600160a01b03928316602091820292909201810191909152604051631853304760e31b8152600481018281528451602483015284519388169363c29982389386938392604490910191858101910280838360005b838110156144f35781810151838201526020016144db565b5050505090500192505050600060405180830381600087803b15801561451857600080fd5b505af115801561452c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561455557600080fd5b810190808051600160201b81111561456c57600080fd5b8201602081018481111561457f57600080fd5b81518560208202830111600160201b8211171561459b57600080fd5b5050505050505050505050565b60408051636eb1769f60e11b81523060048201526001600160a01b038381166024830152915185926000929084169163dd62ed3e91604480820192602092909190829003018186803b1580156145fd57600080fd5b505afa158015614611573d6000803e3d6000fd5b505050506040513d602081101561462757600080fd5b5051905080841115613cb4576040805163095ea7b360e01b81526001600160a01b038581166004830152600160ff1b602483015291519184169163095ea7b39160448082019260009290919082900301818387803b15801561411057600080fd5b6146906148bd565b6001600160a01b0382166000908152600360205260409020546146b49060046138af565b6001600160a01b03831660009081526003602052604090208190556146d883612646565b10156147155760405162461bcd60e51b815260040180806020018281038252603a815260200180615312603a913960400191505060405180910390fd5b604080516080810182526001600160a01b0384166000908152600260209081528382206003909152929020549091829161475090600461374a565b8154811061475a57fe5b600091825260208083209091015483526001600160a01b03861682526002815260408083206003808452919093205493909101926147979161374a565b815481106147a157fe5b600091825260208083209091015483526001600160a01b0386168252600280825260408084206003845293205493909101926147dc9161374a565b815481106147e657fe5b600091825260208083209091015483526001600160a01b03861682526002815260408083206003835292205492019161482090600161374a565b8154811061482a57fe5b90600052602060002001548152509050919050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106148805782800160ff198235161785556148ad565b828001600101855582156148ad579182015b828111156148ad578235825591602001919060010190614892565b506148b99291506148db565b5090565b60405180608001604052806004906020820280388339509192915050565b61165591905b808211156148b957600081556001016148e156fe46756e64732e7365745574696c697a6174696f6e496e74657265737444697669736f723a207574696c697a6174696f6e496e74657265737444697669736f72206973207a65726f46756e64732e656e61626c65436f6d706f756e643a20436f6d706f756e6420697320616c726561647920656e61626c656446756e64732e7365744c6f616e733a20546f6b656e732063616e6e6f7420626520617070726f76656446756e64732e736574436f6d706f756e643a20636f6d7074726f6c6c65722061646472657373206d757374206265206e6f6e2d7a65726f46756e64732e64697361626c65436f6d706f756e643a20436f6d706f756e6420697320616c72656164792064697361626c656446756e64732e7365745574696c697a6174696f6e496e74657265737444697669736f723a204f6e6c7920746865206465706c6f7965722063616e20706572666f726d207468697346756e64732e7365744d696e496e746572657374526174654e756d657261746f723a206d696e496e746572657374526174654e756d657261746f72206973207a65726f46756e64732e726571756573743a204c6f616e206475726174696f6e206d757374206265206c657373207468616e206d61784c6f616e44757220616e642065787069727946756e64732e637265617465437573746f6d3a2043616e6e6f7420656e61626c6520436f6d706f756e6420617320697420686173206e6f74206265656e20636f6e6669677572656446756e64732e736574496e74657265737455706461746544656c61793a20696e74657265737455706461746544656c6179206973207a65726f46756e64732e736574476c6f62616c496e746572657374526174654e756d657261746f723a204f6e6c7920746865206465706c6f7965722063616e20706572666f726d207468697346756e64732e726571756573743a20416d6f756e7420726571756573746564206d757374206265206c657373207468616e206d61784c6f616e416d7446756e64732e7570646174653a2066756e6445787069727920616e64206d61784c6f616e4475722063616e6e6f742065786365656420313020796561727346756e64732e736574436f6d706f756e643a204f6e6c7920746865206465706c6f7965722063616e20656e61626c6520436f6d706f756e64206c656e64696e6746756e64732e757064617465437573746f6d3a206d61784c6f616e416d74206d7573742062652067726561746572207468616e206f7220657175616c20746f206d696e4c6f616e416d7446756e64732e7365744c6f616e733a204c6f616e7320616464726573732068617320616c7265616479206265656e2073657446756e64732e7365744d696e496e746572657374526174654e756d657261746f723a204f6e6c7920746865206465706c6f7965722063616e20706572666f726d207468697346756e64732e6465637265617365546f74616c426f72726f773a204f6e6c7920746865204c6f616e7320636f6e74726163742063616e20706572666f726d207468697346756e64732e64697361626c65436f6d706f756e643a204f6e6c7920746865206c656e6465722063616e2064697361626c6520436f6d706f756e6446756e64732e6372656174653a2066756e6445787069727920616e64206d61784c6f616e4475722063616e6e6f742065786365656420313020796561727346756e64732e726571756573743a20496e73756666696369656e742062616c616e636546756e64732e7365744c6f616e733a204f6e6c7920746865206465706c6f7965722063616e20706572666f726d207468697346756e64732e7570646174653a204f6e6c7920746865206c656e6465722063616e20757064617465207468652066756e6446756e64732e7365744d61785574696c697a6174696f6e44656c74613a206d61785574696c697a6174696f6e44656c7461206973207a65726f46756e64732e6372656174653a204f6e6c79206f6e65206c6f616e2066756e6420616c6c6f77656420706572206164647265737346756e64732e726571756573743a20416d6f756e7420726571756573746564206d7573742062652067726561746572207468616e206d696e4c6f616e416d7446756e64732e736574436f6d706f756e643a20436f6d706f756e6420616464726573732068617320616c7265616479206265656e2073657446756e64732e726571756573743a20426f72726f7765722061646472657373206d757374206265206e6f6e2d7a65726f46756e64732e637265617465437573746f6d3a206d61784c6f616e447572206d7573742062652067726561746572207468616e206f7220657175616c20746f206d696e4c6f616e44757246756e64732e73657444656661756c74417262697465724665653a204f6e6c7920746865206465706c6f7965722063616e20706572666f726d207468697346756e64732e736574496e74657265737455706461746544656c61793a204f6e6c7920746865206465706c6f7965722063616e20706572666f726d207468697346756e64732e736574476c6f62616c496e746572657374526174654e756d657261746f723a20676c6f62616c496e746572657374526174654e756d657261746f72206973207a65726f46756e64732e726571756573743a20536563726574486173683720262053656372657448617368382073686f756c64206265206e6f6e2d7a65726f46756e64732e726571756573743a204f6e6c7920746865206c656e6465722063616e2066756c66696c6c2061206c6f616e207265717565737446756e64732e6465706f7369743a204661696c656420746f207472616e7366657220746f6b656e7346756e64732e7769746864726177546f3a20546f6b656e207472616e73666572206661696c656446756e64732e7365744d6178496e746572657374526174654e756d657261746f723a204f6e6c7920746865206465706c6f7965722063616e20706572666f726d207468697346756e64732e637265617465437573746f6d3a206d61784c6f616e416d74206d7573742062652067726561746572207468616e206f7220657175616c20746f206d696e4c6f616e416d7446756e64732e6372656174653a2043616e6e6f7420656e61626c6520436f6d706f756e6420617320697420686173206e6f74206265656e20636f6e6669677572656446756e64732e736574476c6f62616c496e746572657374526174653a204f6e6c7920746865206465706c6f7965722063616e20706572666f726d207468697346756e64732e656e61626c65436f6d706f756e643a2043616e6e6f7420656e61626c6520436f6d706f756e6420617320697420686173206e6f74206265656e20636f6e6669677572656446756e64732e736574476c6f62616c496e746572657374526174653a20676c6f62616c496e74657265737452617465206973207a65726f46756e64732e637265617465437573746f6d3a2066756e6445787069727920616e64206d61784c6f616e4475722063616e6e6f742065786365656420313020796561727346756e64732e676574536563726574486173686573466f724c6f616e3a204e6f7420656e6f75676820736563726574732067656e65726174656446756e64732e757064617465437573746f6d3a206d61784c6f616e447572206d7573742062652067726561746572207468616e206f7220657175616c20746f206d696e4c6f616e44757246756e64732e726571756573743a20536563726574486173683520262053656372657448617368362073686f756c64206265206e6f6e2d7a65726f46756e64732e7769746864726177546f3a204f6e6c7920746865206c656e6465722063616e20776974686472617720746f6b656e7346756e64732e7365744d6178496e746572657374526174654e756d657261746f723a206d6178496e746572657374526174654e756d657261746f72206973207a65726f46756e64732e7365744c6f616e733a204c6f616e732061646472657373206d757374206265206e6f6e2d7a65726f46756e64732e656e61626c65436f6d706f756e643a204f6e6c7920746865206c656e6465722063616e20656e61626c6520436f6d706f756e6446756e64732e73657444656661756c74417262697465724665653a2064656661756c74417262697465724665652063616e6e6f74206265206c657373207468616e202d312546756e64732e757064617465437573746f6d3a2046756e64206d757374206265206120637573746f6d2066756e6446756e64732e7769746864726177546f3a20496e73756666696369656e742062616c616e636546756e64732e7365744d61785574696c697a6174696f6e44656c74613a204f6e6c7920746865206465706c6f7965722063616e20706572666f726d207468697346756e64732e736574436f6d706f756e643a2063546f6b656e2061646472657373206d757374206265206e6f6e2d7a65726f46756e64732e726571756573743a20536563726574486173683120262053656372657448617368322073686f756c64206265206e6f6e2d7a65726f46756e64732e726571756573743a20536563726574486173683320262053656372657448617368342073686f756c64206265206e6f6e2d7a65726f46756e64732e726571756573743a204c6f616e206475726174696f6e206d7573742062652067726561746572207468616e206d696e4c6f616e447572a265627a7a7230582001ece922c650df050f16dab7220a9a0e1dcfd2986d994476756a09a8d47974bd64736f6c634300050a003246756e64732e636f6e7374727563746f723a20546f6b656e2061646472657373206d757374206265206e6f6e2d7a65726f46756e64732e636f6e7374727563746f723a20446563696d616c73206d757374206265206e6f6e2d7a65726f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000006

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106104545760003560e01c806376a0b16611610241578063d39a2c0c1161013b578063e91d14a4116100c3578063f61d02d311610087578063f61d02d314610de2578063f7837eb714610e51578063fa3bfb1714610e74578063fc0c546a14610e91578063fdd5aab114610e9957610454565b8063e91d14a414610cb9578063eae1c2cf14610cd6578063f05541be14610cde578063f0a422d014610ce6578063f59bf27314610cee57610454565b8063da2c5c5b1161010a578063da2c5c5b14610bec578063db9b376c14610bf4578063e179e77114610bfc578063e32d291314610c2e578063e493325614610c9c57610454565b8063d39a2c0c14610b0d578063d4785d2914610b33578063d73b906214610b50578063d9d0a2d114610bbe57610454565b8063a2c70b6b116101c9578063ba617eef1161018d578063ba617eef14610a30578063bf12f43d14610a4d578063ccb99d5514610a6a578063ce26d44b146105d0578063d1b8b4bf14610a7257610454565b8063a2c70b6b146109c9578063a5a70965146109e6578063a5fa6706146109ee578063a634baf214610a0b578063b2d6107114610a2857610454565b80638c5d5268116102105780638c5d52681461090f578063994871fa1461092c5780639d06bcea146109555780639fc3f02f1461097b578063a18e4a801461099857610454565b806376a0b166146108b05780637e25a221146108cd5780638285ef40146108ea57806389eba421146108f257610454565b806344b6ba95116103525780635fe3b567116102da57806369e527da1161029e57806369e527da1461077a5780636a29a620146107825780636a7bb32c1461081b5780636e1719a61461085b578063712d8e6a1461089357610454565b80635fe3b56714610735578063612ef80b1461073d5780636158153d14610745578063668064da1461074d578063689c76ef1461077257610454565b80634f9bc9d5116103215780634f9bc9d514610676578063513916741461067e578063516dbe24146106e457806354e39f90146107015780635b873ffa1461072d57610454565b806344b6ba95146105f557806347ca77161461062e5780634c9fb84a146106365780634ee9159a1461066e57610454565b80631beec294116103e05780632eb1ad73116103a45780632eb1ad73146105b8578063313ce567146105c057806333549b1b146105c85780633d41a26b146105d057806342febf0c146105d857610454565b80631beec294146105185780631de26e161461053557806321fd933b1461055857806326fc75901461057e57806327cdab061461059b57610454565b806304e9ef031161042757806304e9ef03146104db57806316df840a146104e35780631723cfa5146104eb5780631873fe50146104f35780631bb736971461051057610454565b806301937d0414610459578063031558e51461049157806303b69d1814610499578063040cf020146104b6575b600080fd5b61047f6004803603602081101561046f57600080fd5b50356001600160a01b0316610ea1565b60408051918252519081900360200190f35b61047f610eb3565b61047f600480360360208110156104af57600080fd5b5035610eb9565b6104d9600480360360408110156104cc57600080fd5b5080359060200135610f12565b005b61047f610f21565b61047f610f27565b61047f610f2d565b6104d96004803603602081101561050957600080fd5b5035610f3d565b61047f610fd6565b6104d96004803603602081101561052e57600080fd5b5035610fdc565b6104d96004803603604081101561054b57600080fd5b5080359060200135611066565b61047f6004803603602081101561056e57600080fd5b50356001600160a01b03166112eb565b61047f6004803603602081101561059457600080fd5b50356112fd565b61047f600480360360208110156105b157600080fd5b503561133f565b61047f611377565b61047f61137d565b6104d9611383565b61047f611495565b61047f600480360360208110156105ee57600080fd5b503561149b565b6106126004803603602081101561060b57600080fd5b50356114d3565b604080516001600160a01b039092168252519081900360200190f35b61047f6114f1565b6104d96004803603608081101561064c57600080fd5b50803590602081013590604081013590606001356001600160a01b03166114fe565b610612611648565b61047f611658565b6104d9600480360361016081101561069557600080fd5b5080359060208101359060408101359060608101359060808101359060a08101359060c08101359060e081013590610100810135906101208101359061014001356001600160a01b031661165e565b6104d9600480360360208110156106fa57600080fd5b503561177e565b61047f6004803603604081101561071757600080fd5b506001600160a01b038135169060200135611808565b61047f611836565b61061261183c565b61047f61184b565b61047f611851565b61047f6004803603604081101561076357600080fd5b50803590602001351515611859565b61047f611887565b61061261188d565b61079f6004803603602081101561079857600080fd5b503561189c565b604080516001600160a01b039e8f168152602081019d909d528c81019b909b5260608c019990995260808b019790975260a08a019590955260c089019390935260e08801919091526101008701526101208601529094166101408401526101608301939093526101808201929092529051908190036101a00190f35b61047f600480360360a081101561083157600080fd5b508035906020810135906001600160a01b0360408201351690606081013515159060800135611910565b6108786004803603602081101561087157600080fd5b5035611b30565b60408051921515835290151560208301528051918290030190f35b61047f600480360360208110156108a957600080fd5b5035611b4e565b61047f600480360360208110156108c657600080fd5b5035611b63565b6104d9600480360360208110156108e357600080fd5b5035611ba5565b61047f611e15565b61047f6004803603602081101561090857600080fd5b5035611e1b565b6104d96004803603602081101561092557600080fd5b5035611edc565b61047f6004803603606081101561094257600080fd5b5080359060208101359060400135611f66565b6104d96004803603602081101561096b57600080fd5b50356001600160a01b0316611f8c565b6106126004803603602081101561099157600080fd5b5035612138565b6109b5600480360360208110156109ae57600080fd5b5035612153565b604080519115158252519081900360200190f35b6104d9600480360360208110156109df57600080fd5b5035612168565b61047f6121f2565b6104d960048036036020811015610a0457600080fd5b50356121f8565b61047f60048036036020811015610a2157600080fd5b50356124bd565b61047f6124f5565b61047f60048036036020811015610a4657600080fd5b50356124fb565b6104d960048036036020811015610a6357600080fd5b5035612511565b61047f61259b565b610a9860048036036020811015610a8857600080fd5b50356001600160a01b03166125ab565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610ad2578181015183820152602001610aba565b50505050905090810190601f168015610aff5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61047f60048036036020811015610b2357600080fd5b50356001600160a01b0316612646565b6104d960048036036020811015610b4957600080fd5b5035612661565b6104d960048036036020811015610b6657600080fd5b810190602081018135600160201b811115610b8057600080fd5b820183602082011115610b9257600080fd5b803590602001918460208302840111600160201b83111715610bb357600080fd5b5090925090506126eb565b6104d960048036036040811015610bd457600080fd5b506001600160a01b0381358116916020013516612740565b61047f61289a565b61047f6128a2565b6104d960048036036060811015610c1257600080fd5b50803590602081013590604001356001600160a01b03166128a8565b6104d960048036036020811015610c4457600080fd5b810190602081018135600160201b811115610c5e57600080fd5b820183602082011115610c7057600080fd5b803590602001918460018302840111600160201b83111715610c9157600080fd5b509092509050612cf5565b6104d960048036036020811015610cb257600080fd5b5035612d0f565b61047f60048036036020811015610ccf57600080fd5b5035612d6a565b61047f612da2565b61047f612da8565b61047f612dae565b61047f6004803603610200811015610d0557600080fd5b8135916001600160a01b036020820135169160408201359160608101359160808201359160a08101359160c0820191908101906101e081016101c0820135600160201b811115610d5457600080fd5b820183602082011115610d6657600080fd5b803590602001918460018302840111600160201b83111715610d8757600080fd5b919390929091602081019035600160201b811115610da457600080fd5b820183602082011115610db657600080fd5b803590602001918460018302840111600160201b83111715610dd757600080fd5b509092509050612e4e565b61047f6004803603610180811015610df957600080fd5b5080359060208101359060408101359060608101359060808101359060a08101359060c08101359060e081013590610100810135906001600160a01b0361012082013516906101408101351515906101600135613336565b61047f60048036036040811015610e6757600080fd5b508035906020013561367a565b6104d960048036036020811015610e8a57600080fd5b50356136ab565b610612613735565b61047f613744565b60036020526000908152604090205481565b60115481565b60008181526007602052604081205460ff1615610ee85750600081815260056020526040902060010154610f0d565b610f0a68015af1d78b58c40000610f02601260185461374a565b600a0a61375a565b90505b919050565b610f1d8282336128a8565b5050565b60165481565b600b5481565b6b04860d8812f0b3887800000081565b601a546001600160a01b03163314610f865760405162461bcd60e51b815260040180806020018281038252603e815260200180614fb3603e913960400191505060405180910390fd5b6b033b2e3ca43176a9d2dfd0a5811115610fd15760405162461bcd60e51b81526004018080602001828103825260458152602001806154b06045913960600191505060405180910390fd5b601655565b600e5481565b601a546001600160a01b031633146110255760405162461bcd60e51b8152600401808060200182810382526048815260200180614b506048913960600191505060405180910390fd5b806110615760405162461bcd60e51b81526004018080602001828103825260498152602001806150316049913960600191505060405180910390fd5b600e55565b601754604080516323b872dd60e01b81523360048201523060248201526044810184905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b1580156110c057600080fd5b505af11580156110d4573d6000803e3d6000fd5b505050506040513d60208110156110ea57600080fd5b50516111275760405162461bcd60e51b81526004018080602001828103825260288152602001806150ee6028913960400191505060405180910390fd5b600082815260076020526040902054610100900460ff161561124c57601754601954611160916001600160a01b03908116911683613771565b60006111f861117783670de0b6b3a764000061388b565b601960009054906101000a90046001600160a01b03166001600160a01b031663bd6d894d6040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156111c757600080fd5b505af11580156111db573d6000803e3d6000fd5b505050506040513d60208110156111f157600080fd5b505161375a565b6000848152600560205260409020600c015490915061121790826138af565b6000848152600560205260409020600c015561123283612153565b61124657611242600b54826138af565b600b555b50611297565b6000828152600560205260409020600b015461126890826138af565b6000838152600560205260409020600b015561128382612153565b61129757611293600a54826138af565b600a555b6112a082612153565b6112ac576112ac611383565b604080518381526020810183905281517f98e783c3864bbf744a057ef605a2a61701c3b62b5ed68b3745b99094497daf1f929181900390910190a15050565b60066020526000908152604090205481565b60008181526007602052604081205460ff161561132c5750600081815260056020526040902060070154610f0d565b506b033b2e3cacd278c7503e82c1610f0d565b60008181526007602052604081205460ff161561136e5750600081815260056020526040902060080154610f0d565b50601654610f0d565b60095481565b60185481565b6113a1600a5461139c600b54611397612dae565b6138bf565b6138af565b600c556009546015546113b491906138af565b421115611493576000600d546000146113e3576113e0600d546113db600c54600d546138af565b6138e7565b90505b600f5481111561142e5760006113fb82600f5461374a565b9050611425601354611420600e5461139c6114186011548761390b565b6012546138e7565b61390b565b600e5550611468565b600061143c600f548361374a565b905061146360145461145e600e546114596114186011548761390b565b61374a565b61391e565b600e55505b6114886b033b2e3c9fd0803ce800000061139c600e546301e1338061375a565b60105542600955600f555b565b60001981565b60008181526007602052604081205460ff16156114ca5750600081815260056020526040902060020154610f0d565b50600019610f0d565b6000908152600560205260409020600a01546001600160a01b031690565b68015af1d78b58c4000081565b61150784612138565b6001600160a01b0316336001600160a01b0316146115565760405162461bcd60e51b8152600401808060200182810382526031815260200180614e246031913960400191505060405180910390fd5b6312cc0300611566846000611859565b111580156115845750426312cc030001611581836001611859565b11155b6115bf5760405162461bcd60e51b815260040180806020018281038252603e815260200180614bd4603e913960400191505060405180910390fd5b60008481526005602081815260409283902060048101879055918201859055600a90910180546001600160a01b0385166001600160a01b031990911681179091558251878152918201869052818301859052606082015290517fbc2980147202467df8874a7f933ee11c59b6b1f6273647aca58bd18d349e67ac9181900360800190a150505050565b6000546001600160a01b03165b90565b60125481565b60008b81526007602052604090205460ff166116ab5760405162461bcd60e51b815260040180806020018281038252602e8152602001806154f5602e913960400191505060405180910390fd5b898910156116ea5760405162461bcd60e51b815260040180806020018281038252604a815260200180614c52604a913960600191505060405180910390fd5b876116f6886000611859565b10156117335760405162461bcd60e51b815260040180806020018281038252604a81526020018061534c604a913960600191505060405180910390fd5b61173f8b8888846114fe565b506000998a5260056020526040909920600181019890985560028801969096556003870194909455600686015550506007830155600882015560090155565b601a546001600160a01b031633146117c75760405162461bcd60e51b8152600401808060200182810382526040815260200180614ff16040913960400191505060405180910390fd5b806118035760405162461bcd60e51b8152600401808060200182810382526039815260200180614b176039913960400191505060405180910390fd5b601555565b6002602052816000526040600020818154811061182157fe5b90600052602060002001600091509150505481565b60105481565b6000546001600160a01b031681565b600c5481565b6312cc030081565b60008261187e5781156118735750426312cc030001611881565b506312cc0300611881565b50815b92915050565b60145481565b6019546001600160a01b031681565b600560208190526000918252604090912080546001820154600283015460038401546004850154958501546006860154600787015460088801546009890154600a8a0154600b8b0154600c909b01546001600160a01b039a8b169c999b989a9799989697959694959394929390911691908d565b336000818152600660209081526040808320548352600590915281205490916001600160a01b0390911614156119775760405162461bcd60e51b8152600401808060200182810382526034815260200180614e8e6034913960400191505060405180910390fd5b6312cc0300611987876000611859565b1080156119a35750426312cc0300016119a1866001611859565b105b6119de5760405162461bcd60e51b815260040180806020018281038252603e815260200180614d91603e913960400191505060405180910390fd5b601954600160a01b900460ff16611a2c578215611a2c5760405162461bcd60e51b81526004018080602001828103825260428152602001806151cc6042913960600191505060405180910390fd5b611a3960085460016138af565b6008819055600081815260056020526040812080546001600160a01b03191633179055909150611a6a908790611859565b600082815260056020526040902060040155611a87856001611859565b600082815260056020818152604080842092830194909455600a90910180546001600160a01b0319166001600160a01b03891617905560078152828220805461ffff1916610100881515021790556008543383526006909152919020558115611af457611af48183611066565b6040805182815290517fa7857d7da6974b0157f3bf7dd25a745bd7d81d845bb525ee0b316a87541a5c319181900360200190a195945050505050565b60076020526000908152604090205460ff8082169161010090041682565b60009081526005602052604090206004015490565b60008181526007602052604081205460ff1615611b925750600081815260056020526040902060090154610f0d565b506b04860d8812f0b38878000000610f0d565b600081815260076020526040902054610100900460ff16611bf75760405162461bcd60e51b81526004018080602001828103825260338152602001806149ce6033913960400191505060405180910390fd5b611c0081612138565b6001600160a01b0316336001600160a01b031614611c4f5760405162461bcd60e51b815260040180806020018281038252603b815260200180614d56603b913960400191505060405180910390fd5b601754604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015611c9a57600080fd5b505afa158015611cae573d6000803e3d6000fd5b505050506040513d6020811015611cc457600080fd5b50516019546000848152600560205260409020600c0154919250611cf3916001600160a01b039091169061392e565b601754604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015611d3e57600080fd5b505afa158015611d52573d6000803e3d6000fd5b505050506040513d6020811015611d6857600080fd5b505190506000611d78828461374a565b9050611d86600a54826138af565b600a55600b546000858152600560205260409020600c0154611da8919061374a565b600b9081556000858152600760209081526040808320805461ff001916905560058252808320600c81019390935591909201839055805186815290517ffb6e0a1c4958f3e250db013b5035dc019d1e6426df7b4a40a5d0229a336aad53929181900390910190a150505050565b600d5481565b600081815260076020526040812054610100900460ff1615611ec4576000828152600560209081526040808320600c0154601954825163bd6d894d60e01b81529251610f0a9592946001600160a01b039092169363bd6d894d9360048083019493928390030190829087803b158015611e9357600080fd5b505af1158015611ea7573d6000803e3d6000fd5b505050506040513d6020811015611ebd57600080fd5b50516138bf565b506000818152600560205260409020600b0154610f0d565b601a546001600160a01b03163314611f255760405162461bcd60e51b815260040180806020018281038252603f81526020018061520e603f913960400191505060405180910390fd5b80611f615760405162461bcd60e51b81526004018080602001828103825260378152602001806152976037913960400191505060405180910390fd5b601055565b6000611f84611f7e85611f798686613a7e565b613ad8565b8561374a565b949350505050565b601a546001600160a01b03163314611fd55760405162461bcd60e51b8152600401808060200182810382526032815260200180614df26032913960400191505060405180910390fd5b6001546001600160a01b03161561201d5760405162461bcd60e51b8152600401808060200182810382526032815260200180614c9c6032913960400191505060405180910390fd5b6001600160a01b0381166120625760405162461bcd60e51b815260040180806020018281038252602e815260200180615449602e913960400191505060405180910390fd5b600180546001600160a01b0319166001600160a01b038381169182179092556017546040805163095ea7b360e01b8152600481019390935260001960248401525192169163095ea7b3916044808201926020929091908290030181600087803b1580156120ce57600080fd5b505af11580156120e2573d6000803e3d6000fd5b505050506040513d60208110156120f857600080fd5b50516121355760405162461bcd60e51b815260040180806020018281038252602981526020018061496e6029913960400191505060405180910390fd5b50565b6000908152600560205260409020546001600160a01b031690565b60009081526007602052604090205460ff1690565b601a546001600160a01b031633146121b15760405162461bcd60e51b81526004018080602001828103825260408152602001806155496040913960400191505060405180910390fd5b806121ed5760405162461bcd60e51b8152600401808060200182810382526039815260200180614e556039913960400191505060405180910390fd5b601155565b60085481565b601954600160a01b900460ff166122405760405162461bcd60e51b815260040180806020018281038252604a81526020018061524d604a913960600191505060405180910390fd5b600081815260076020526040902054610100900460ff16156122935760405162461bcd60e51b815260040180806020018281038252603181526020018061493d6031913960400191505060405180910390fd5b61229c81612138565b6001600160a01b0316336001600160a01b0316146122eb5760405162461bcd60e51b81526004018080602001828103825260398152602001806154776039913960400191505060405180910390fd5b601954604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561233657600080fd5b505afa15801561234a573d6000803e3d6000fd5b505050506040513d602081101561236057600080fd5b50516017546019546000858152600560205260409020600b0154929350612396926001600160a01b039283169290911690613771565b601954604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156123e157600080fd5b505afa1580156123f5573d6000803e3d6000fd5b505050506040513d602081101561240b57600080fd5b50519050600061241b828461374a565b600a546000868152600560205260409020600b015491925061243c9161374a565b600a55600b5461244c90826138af565b600b9081556000858152600760209081526040808320805461ff0019166101001790556005825280832093840192909255600c909201839055805186815290517f43c40c3c72eec13a64775a3231f52699c8ba28e57131e7343e4f57734d8a3ce4929181900390910190a150505050565b60008181526007602052604081205460ff16156124ec5750600081815260056020526040902060030154610f0d565b50615460610f0d565b61546081565b6000908152600560208190526040909120015490565b601a546001600160a01b0316331461255a5760405162461bcd60e51b8152600401808060200182810382526047815260200180614a016047913960600191505060405180910390fd5b806125965760405162461bcd60e51b81526004018080602001828103825260478152602001806148f66047913960600191505060405180910390fd5b601255565b6b033b2e3cacd278c7503e82c181565b60046020908152600091825260409182902080548351601f60026000196101006001861615020190931692909204918201849004840281018401909452808452909183018282801561263e5780601f106126135761010080835404028352916020019161263e565b820191906000526020600020905b81548152906001019060200180831161262157829003601f168201915b505050505081565b6001600160a01b031660009081526002602052604090205490565b601a546001600160a01b031633146126aa5760405162461bcd60e51b8152600401808060200182810382526045815260200180614cce6045913960600191505060405180910390fd5b806126e65760405162461bcd60e51b8152600401808060200182810382526043815260200180614a486043913960600191505060405180910390fd5b601455565b60005b8181101561273b5733600090815260026020526040902083838381811061271157fe5b835460018082018655600095865260209586902092909502939093013592019190915550016126ee565b505050565b601a546001600160a01b031633146127895760405162461bcd60e51b8152600401808060200182810382526040815260200180614c126040913960400191505060405180910390fd5b601954600160a01b900460ff16156127d25760405162461bcd60e51b8152600401808060200182810382526038815260200180614f016038913960400191505060405180910390fd5b6001600160a01b0382166128175760405162461bcd60e51b81526004018080602001828103825260328152602001806155896032913960400191505060405180910390fd5b6001600160a01b03811661285c5760405162461bcd60e51b81526004018080602001828103825260378152602001806149976037913960400191505060405180910390fd5b60198054600080546001600160a01b039485166001600160a01b03199182161790915560ff60a01b199390941693169290921716600160a01b179055565b6301e1338081565b60155481565b6128b183612138565b6001600160a01b0316336001600160a01b0316146129005760405162461bcd60e51b81526004018080602001828103825260358152602001806153d16035913960400191505060405180910390fd5b8161290a84611e1b565b10156129475760405162461bcd60e51b81526004018080602001828103825260268152602001806155236026913960400191505060405180910390fd5b600083815260076020526040902054610100900460ff1615612b8b57601954604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156129ae57600080fd5b505afa1580156129c2573d6000803e3d6000fd5b505050506040513d60208110156129d857600080fd5b50516019549091506129f3906001600160a01b031684613b08565b601954604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015612a3e57600080fd5b505afa158015612a52573d6000803e3d6000fd5b505050506040513d6020811015612a6857600080fd5b505190506000612a78838361374a565b6000878152600560205260409020600c0154909150612a97908261374a565b6000878152600560209081526040808320600c0193909355601754835163a9059cbb60e01b81526001600160a01b038981166004830152602482018b90529451949091169363a9059cbb93604480840194938390030190829087803b158015612aff57600080fd5b505af1158015612b13573d6000803e3d6000fd5b505050506040513d6020811015612b2957600080fd5b5051612b665760405162461bcd60e51b81526004018080602001828103825260278152602001806151166027913960400191505060405180910390fd5b612b6f86612153565b612b8357612b7f600b548261374a565b600b555b505050612c93565b6000838152600560205260409020600b0154612ba7908361374a565b6000848152600560209081526040808320600b0193909355601754835163a9059cbb60e01b81526001600160a01b038681166004830152602482018890529451949091169363a9059cbb93604480840194938390030190829087803b158015612c0f57600080fd5b505af1158015612c23573d6000803e3d6000fd5b505050506040513d6020811015612c3957600080fd5b5051612c765760405162461bcd60e51b81526004018080602001828103825260278152602001806151166027913960400191505060405180910390fd5b612c7f83612153565b612c9357612c8f600a548361374a565b600a555b612c9c83612153565b612ca857612ca8611383565b60408051848152602081018490526001600160a01b0383168183015290517f181177e6e9bbf7d7a45604cf4fdb0444641e20905d8d4daf2a7863036e56dc159181900360600190a1505050565b33600090815260046020526040902061273b90838361483f565b6001546001600160a01b03163314612d585760405162461bcd60e51b8152600401808060200182810382526043815260200180614d136043913960600191505060405180910390fd5b612d64600d548261374a565b600d5550565b60008181526007602052604081205460ff1615612d995750600081815260056020526040902060060154610f0d565b50601054610f0d565b60135481565b600f5481565b601954600090600160a01b900460ff1615612e4657601960009054906101000a90046001600160a01b03166001600160a01b031663bd6d894d6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612e1357600080fd5b505af1158015612e27573d6000803e3d6000fd5b505050506040513d6020811015612e3d57600080fd5b50519050611655565b506000611655565b6000612e598c612138565b6001600160a01b0316336001600160a01b031614612ea85760405162461bcd60e51b81526004018080602001828103825260398152602001806150b56039913960400191505060405180910390fd5b612eb18c611e1b565b8a1115612eef5760405162461bcd60e51b8152600401808060200182810382526023815260200180614dcf6023913960400191505060405180910390fd5b612ef88c610eb9565b8a1015612f365760405162461bcd60e51b815260040180806020018281038252603f815260200180614ec2603f913960400191505060405180910390fd5b612f3f8c61149b565b8a1115612f7d5760405162461bcd60e51b815260040180806020018281038252603c815260200180614b98603c913960400191505060405180910390fd5b612f868c6124bd565b881015612fc45760405162461bcd60e51b815260040180806020018281038252603c815260200180615631603c913960400191505060405180910390fd5b612fd6612fd08d6124fb565b4261374a565b8811158015612fed5750612fe98c611b4e565b8811155b6130285760405162461bcd60e51b8152600401808060200182810382526044815260200180614a8b6044913960600191505060405180910390fd5b6001600160a01b038b1661306d5760405162461bcd60e51b8152600401808060200182810382526030815260200180614f396030913960400191505060405180910390fd5b8535158015906130805750602086013515155b6130bb5760405162461bcd60e51b815260040180806020018281038252603b8152602001806155bb603b913960400191505060405180910390fd5b6040860135158015906130d15750606086013515155b61310c5760405162461bcd60e51b815260040180806020018281038252603b8152602001806155f6603b913960400191505060405180910390fd5b608086013515801590613122575060a086013515155b61315d5760405162461bcd60e51b815260040180806020018281038252603b815260200180615396603b913960400191505060405180910390fd5b60c086013515801590613173575060e086013515155b6131ae5760405162461bcd60e51b815260040180806020018281038252603b81526020018061507a603b913960400191505060405180910390fd5b6131bc8c8c8c8c8c8c613cbb565b905061325a8c8288600880602002604051908101604052809291908260086020028082843760009201919091525050604080516020601f8c018190048102820181019092528a815291508a908a908190840183828082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a9150899081908401838280828437600092019190915250613e5092505050565b6132648c8b61412f565b6001546040805163bf14c11960e01b81526004810184905290516001600160a01b039092169163bf14c1199160248082019260009290919082900301818387803b1580156132b157600080fd5b505af11580156132c5573d6000803e3d6000fd5b5050604080518f81526001600160a01b038f1660208201528082018e9052606081018d9052608081018c905260a081018b905290517ff494fa7145682762e6918aefe85748818b2f1092c6f8c0a3284bcb18506416d593509081900360c0019150a19b9a5050505050505050505050565b336000818152600660209081526040808320548352600590915281205490916001600160a01b03909116141561339d5760405162461bcd60e51b8152600401808060200182810382526034815260200180614e8e6034913960400191505060405180910390fd5b6312cc03006133ad8b6000611859565b1080156133c95750426312cc0300016133c78a6001611859565b105b6134045760405162461bcd60e51b81526004018080602001828103825260448152602001806152ce6044913960600191505060405180910390fd5b8c8c10156134435760405162461bcd60e51b815260040180806020018281038252604a815260200180615182604a913960600191505060405180910390fd5b8a61344f8b6000611859565b101561348c5760405162461bcd60e51b815260040180806020018281038252604a815260200180614f69604a913960600191505060405180910390fd5b601954600160a01b900460ff166134da5782156134da5760405162461bcd60e51b8152600401808060200182810382526048815260200180614acf6048913960600191505060405180910390fd5b6134e760085460016138af565b60088190555060085460001b9050336005600083815260200190815260200160002060000160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508c60056000838152602001908152602001600020600101819055508b60056000838152602001908152602001600020600201819055508a600560008381526020019081526020016000206003018190555061358c8a6000611859565b6000828152600560205260409020600401556135a9896001611859565b60008281526005602081815260408084209283019490945560068083018c905560078084018c905560088085018c9055600985018f9055600a90940180546001600160a01b0319166001600160a01b038c161790558252848420805460ff191660011761ff0019166101008a1515021790559154338452919052919020558115613637576136378183611066565b6040805182815290517fa7857d7da6974b0157f3bf7dd25a745bd7d81d845bb525ee0b316a87541a5c319181900360200190a19c9b505050505050505050505050565b60006305f5e10061369c61368e858561388b565b60026305f5e1005b046138af565b816136a357fe5b049392505050565b601a546001600160a01b031633146136f45760405162461bcd60e51b815260040180806020018281038252604581526020018061513d6045913960600191505060405180910390fd5b806137305760405162461bcd60e51b81526004018080602001828103825260438152602001806154066043913960600191505060405180910390fd5b601355565b6017546001600160a01b031681565b600a5481565b8082038281111561188157600080fd5b600080821161376857600080fd5b8183816136a357fe5b61377a82614325565b604080516370a0823160e01b8152306004820152905184916000916001600160a01b038416916370a08231916024808301926020929190829003018186803b1580156137c557600080fd5b505afa1580156137d9573d6000803e3d6000fd5b505050506040513d60208110156137ef57600080fd5b50519050828111156137fe5750815b8361380a8683836145a8565b806001600160a01b031663a0712d68836040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b15801561385057600080fd5b505af1158015613864573d6000803e3d6000fd5b505050506040513d602081101561387a57600080fd5b50511561388357fe5b505050505050565b60008115806138a6575050808202828282816138a357fe5b04145b61188157600080fd5b8082018281101561188157600080fd5b6000670de0b6b3a764000061369c6138d7858561388b565b6002670de0b6b3a7640000613696565b60008161369c613903856b033b2e3c9fd0803ce800000061388b565b600285613696565b60008183111561187e57815b9392505050565b60008183101561187e5781613917565b604080516370a0823160e01b8152306004820152905183916000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561397957600080fd5b505afa15801561398d573d6000803e3d6000fd5b505050506040513d60208110156139a357600080fd5b50519050828111156139b25750815b6139bd8482866145a8565b816001600160a01b031663db006a75826040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015613a0357600080fd5b505af1158015613a17573d6000803e3d6000fd5b505050506040513d6020811015613a2d57600080fd5b505115613a78576040805162461bcd60e51b8152602060048201526014602482015273736f6d657468696e672077656e742077726f6e6760601b604482015290519081900360640190fd5b50505050565b600060028206613a9a576b033b2e3c9fd0803ce8000000613a9c565b825b90506002820491505b811561188157613ab58384613ad8565b92506002820615613acd57613aca8184613ad8565b90505b600282049150613aa5565b60006b033b2e3c9fd0803ce800000061369c613af4858561388b565b60026b033b2e3c9fd0803ce8000000613696565b81613b298174446c3b15f9926687d2c40534fdb564000000000000816145a8565b604080516370a0823160e01b815230600482015290516000916001600160a01b038416916370a0823191602480820192602092909190829003018186803b158015613b7357600080fd5b505afa158015613b87573d6000803e3d6000fd5b505050506040513d6020811015613b9d57600080fd5b50516040805163bd6d894d60e01b81529051919250600091613bec9184916001600160a01b0387169163bd6d894d91600480830192602092919082900301818987803b158015611e9357600080fd5b905083811115613bf95750825b826001600160a01b031663852a12e3826040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015613c3f57600080fd5b505af1158015613c53573d6000803e3d6000fd5b505050506040513d6020811015613c6957600080fd5b505115613cb4576040805162461bcd60e51b8152602060048201526014602482015273736f6d657468696e672077656e742077726f6e6760601b604482015290519081900360640190fd5b5050505050565b60015460408051606081019091526001600160a01b03878116825260009216906310375921904286019060208101613cf28c612138565b6001600160a01b03908116825260008d815260056020908152604091829020600a015490921692820192909252815160e081019092528a82528101613d408b613d3a8f612d6a565b8b611f66565b8152602001613d528b613d3a8f6112fd565b8152602001613d648b613d3a8f61133f565b8152602001898152602001613d788d611b63565b81526020018790526040516001600160e01b031960e086901b168152600481018481528d9160240184606080838360005b83811015613dc1578181015183820152602001613da9565b5050505090500183600760200280838360005b83811015613dec578181015183820152602001613dd4565b50505050905001828152602001945050505050602060405180830381600087803b158015613e1957600080fd5b505af1158015613e2d573d6000803e3d6000fd5b505050506040513d6020811015613e4357600080fd5b5051979650505050505050565b600154604080516080808201835286518252602080880151818401528784015183850152606080890151908401528351808301855291880151825260a0880151908201526001600160a01b039093169263ee79b12b928892919081018860066020020151815260200188600760088110613ec657fe5b60200201519052613ede613ed98b6114d3565b614688565b878760046000613eed8f6114d3565b6001600160a01b03166001600160a01b031681526020019081526020016000206040518863ffffffff1660e01b81526004018088815260200187600460200280838360005b83811015613f4a578181015183820152602001613f32565b5050505090500186600460200280838360005b83811015613f75578181015183820152602001613f5d565b5050505090500185600460200280838360005b83811015613fa0578181015183820152602001613f88565b50505050905001806020018060200180602001848103845287818151815260200191508051906020019080838360005b83811015613fe8578181015183820152602001613fd0565b50505050905090810190601f1680156140155780820380516001836020036101000a031916815260200191505b50848103835286518152865160209182019188019080838360005b83811015614048578181015183820152602001614030565b50505050905090810190601f1680156140755780820380516001836020036101000a031916815260200191505b508481038252855460026000196101006001841615020190911604808252602090910190869080156140e85780601f106140bd576101008083540402835291602001916140e8565b820191906000526020600020905b8154815290600101906020018083116140cb57829003601f168201915b50509a5050505050505050505050600060405180830381600087803b15801561411057600080fd5b505af1158015614124573d6000803e3d6000fd5b505050505050505050565b600082815260076020526040902054610100900460ff16156142b657601954604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561419657600080fd5b505afa1580156141aa573d6000803e3d6000fd5b505050506040513d60208110156141c057600080fd5b50516019549091506141db906001600160a01b031683613b08565b601954604080516370a0823160e01b815230600482015290516000926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561422657600080fd5b505afa15801561423a573d6000803e3d6000fd5b505050506040513d602081101561425057600080fd5b505190506000614260838361374a565b6000868152600560205260409020600c015490915061427f908261374a565b6000868152600560205260409020600c015561429a85612153565b6142ae576142aa600b548261374a565b600b555b505050614301565b6000828152600560205260409020600b01546142d2908261374a565b6000838152600560205260409020600b01556142ed82612153565b614301576142fd600a548261374a565b600a555b61430a82612153565b610f1d5761431a600d54826138af565b600d55610f1d611383565b600061432f611648565b60408051632aff3bff60e21b815230600482015290519192506060916001600160a01b0384169163abfceffc916024808301926000929190829003018186803b15801561437b57600080fd5b505afa15801561438f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156143b857600080fd5b810190808051600160201b8111156143cf57600080fd5b820160208101848111156143e257600080fd5b81518560208202830111600160201b821117156143fe57600080fd5b509094506000935083925050505b825181101561444f57846001600160a01b031683828151811061442b57fe5b60200260200101516001600160a01b0316141561444757600191505b60010161440c565b5080613a785760408051600180825281830190925260609160208083019080388339019050509050848160008151811061448557fe5b6001600160a01b03928316602091820292909201810191909152604051631853304760e31b8152600481018281528451602483015284519388169363c29982389386938392604490910191858101910280838360005b838110156144f35781810151838201526020016144db565b5050505090500192505050600060405180830381600087803b15801561451857600080fd5b505af115801561452c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561455557600080fd5b810190808051600160201b81111561456c57600080fd5b8201602081018481111561457f57600080fd5b81518560208202830111600160201b8211171561459b57600080fd5b5050505050505050505050565b60408051636eb1769f60e11b81523060048201526001600160a01b038381166024830152915185926000929084169163dd62ed3e91604480820192602092909190829003018186803b1580156145fd57600080fd5b505afa158015614611573d6000803e3d6000fd5b505050506040513d602081101561462757600080fd5b5051905080841115613cb4576040805163095ea7b360e01b81526001600160a01b038581166004830152600160ff1b602483015291519184169163095ea7b39160448082019260009290919082900301818387803b15801561411057600080fd5b6146906148bd565b6001600160a01b0382166000908152600360205260409020546146b49060046138af565b6001600160a01b03831660009081526003602052604090208190556146d883612646565b10156147155760405162461bcd60e51b815260040180806020018281038252603a815260200180615312603a913960400191505060405180910390fd5b604080516080810182526001600160a01b0384166000908152600260209081528382206003909152929020549091829161475090600461374a565b8154811061475a57fe5b600091825260208083209091015483526001600160a01b03861682526002815260408083206003808452919093205493909101926147979161374a565b815481106147a157fe5b600091825260208083209091015483526001600160a01b0386168252600280825260408084206003845293205493909101926147dc9161374a565b815481106147e657fe5b600091825260208083209091015483526001600160a01b03861682526002815260408083206003835292205492019161482090600161374a565b8154811061482a57fe5b90600052602060002001548152509050919050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106148805782800160ff198235161785556148ad565b828001600101855582156148ad579182015b828111156148ad578235825591602001919060010190614892565b506148b99291506148db565b5090565b60405180608001604052806004906020820280388339509192915050565b61165591905b808211156148b957600081556001016148e156fe46756e64732e7365745574696c697a6174696f6e496e74657265737444697669736f723a207574696c697a6174696f6e496e74657265737444697669736f72206973207a65726f46756e64732e656e61626c65436f6d706f756e643a20436f6d706f756e6420697320616c726561647920656e61626c656446756e64732e7365744c6f616e733a20546f6b656e732063616e6e6f7420626520617070726f76656446756e64732e736574436f6d706f756e643a20636f6d7074726f6c6c65722061646472657373206d757374206265206e6f6e2d7a65726f46756e64732e64697361626c65436f6d706f756e643a20436f6d706f756e6420697320616c72656164792064697361626c656446756e64732e7365745574696c697a6174696f6e496e74657265737444697669736f723a204f6e6c7920746865206465706c6f7965722063616e20706572666f726d207468697346756e64732e7365744d696e496e746572657374526174654e756d657261746f723a206d696e496e746572657374526174654e756d657261746f72206973207a65726f46756e64732e726571756573743a204c6f616e206475726174696f6e206d757374206265206c657373207468616e206d61784c6f616e44757220616e642065787069727946756e64732e637265617465437573746f6d3a2043616e6e6f7420656e61626c6520436f6d706f756e6420617320697420686173206e6f74206265656e20636f6e6669677572656446756e64732e736574496e74657265737455706461746544656c61793a20696e74657265737455706461746544656c6179206973207a65726f46756e64732e736574476c6f62616c496e746572657374526174654e756d657261746f723a204f6e6c7920746865206465706c6f7965722063616e20706572666f726d207468697346756e64732e726571756573743a20416d6f756e7420726571756573746564206d757374206265206c657373207468616e206d61784c6f616e416d7446756e64732e7570646174653a2066756e6445787069727920616e64206d61784c6f616e4475722063616e6e6f742065786365656420313020796561727346756e64732e736574436f6d706f756e643a204f6e6c7920746865206465706c6f7965722063616e20656e61626c6520436f6d706f756e64206c656e64696e6746756e64732e757064617465437573746f6d3a206d61784c6f616e416d74206d7573742062652067726561746572207468616e206f7220657175616c20746f206d696e4c6f616e416d7446756e64732e7365744c6f616e733a204c6f616e7320616464726573732068617320616c7265616479206265656e2073657446756e64732e7365744d696e496e746572657374526174654e756d657261746f723a204f6e6c7920746865206465706c6f7965722063616e20706572666f726d207468697346756e64732e6465637265617365546f74616c426f72726f773a204f6e6c7920746865204c6f616e7320636f6e74726163742063616e20706572666f726d207468697346756e64732e64697361626c65436f6d706f756e643a204f6e6c7920746865206c656e6465722063616e2064697361626c6520436f6d706f756e6446756e64732e6372656174653a2066756e6445787069727920616e64206d61784c6f616e4475722063616e6e6f742065786365656420313020796561727346756e64732e726571756573743a20496e73756666696369656e742062616c616e636546756e64732e7365744c6f616e733a204f6e6c7920746865206465706c6f7965722063616e20706572666f726d207468697346756e64732e7570646174653a204f6e6c7920746865206c656e6465722063616e20757064617465207468652066756e6446756e64732e7365744d61785574696c697a6174696f6e44656c74613a206d61785574696c697a6174696f6e44656c7461206973207a65726f46756e64732e6372656174653a204f6e6c79206f6e65206c6f616e2066756e6420616c6c6f77656420706572206164647265737346756e64732e726571756573743a20416d6f756e7420726571756573746564206d7573742062652067726561746572207468616e206d696e4c6f616e416d7446756e64732e736574436f6d706f756e643a20436f6d706f756e6420616464726573732068617320616c7265616479206265656e2073657446756e64732e726571756573743a20426f72726f7765722061646472657373206d757374206265206e6f6e2d7a65726f46756e64732e637265617465437573746f6d3a206d61784c6f616e447572206d7573742062652067726561746572207468616e206f7220657175616c20746f206d696e4c6f616e44757246756e64732e73657444656661756c74417262697465724665653a204f6e6c7920746865206465706c6f7965722063616e20706572666f726d207468697346756e64732e736574496e74657265737455706461746544656c61793a204f6e6c7920746865206465706c6f7965722063616e20706572666f726d207468697346756e64732e736574476c6f62616c496e746572657374526174654e756d657261746f723a20676c6f62616c496e746572657374526174654e756d657261746f72206973207a65726f46756e64732e726571756573743a20536563726574486173683720262053656372657448617368382073686f756c64206265206e6f6e2d7a65726f46756e64732e726571756573743a204f6e6c7920746865206c656e6465722063616e2066756c66696c6c2061206c6f616e207265717565737446756e64732e6465706f7369743a204661696c656420746f207472616e7366657220746f6b656e7346756e64732e7769746864726177546f3a20546f6b656e207472616e73666572206661696c656446756e64732e7365744d6178496e746572657374526174654e756d657261746f723a204f6e6c7920746865206465706c6f7965722063616e20706572666f726d207468697346756e64732e637265617465437573746f6d3a206d61784c6f616e416d74206d7573742062652067726561746572207468616e206f7220657175616c20746f206d696e4c6f616e416d7446756e64732e6372656174653a2043616e6e6f7420656e61626c6520436f6d706f756e6420617320697420686173206e6f74206265656e20636f6e6669677572656446756e64732e736574476c6f62616c496e746572657374526174653a204f6e6c7920746865206465706c6f7965722063616e20706572666f726d207468697346756e64732e656e61626c65436f6d706f756e643a2043616e6e6f7420656e61626c6520436f6d706f756e6420617320697420686173206e6f74206265656e20636f6e6669677572656446756e64732e736574476c6f62616c496e746572657374526174653a20676c6f62616c496e74657265737452617465206973207a65726f46756e64732e637265617465437573746f6d3a2066756e6445787069727920616e64206d61784c6f616e4475722063616e6e6f742065786365656420313020796561727346756e64732e676574536563726574486173686573466f724c6f616e3a204e6f7420656e6f75676820736563726574732067656e65726174656446756e64732e757064617465437573746f6d3a206d61784c6f616e447572206d7573742062652067726561746572207468616e206f7220657175616c20746f206d696e4c6f616e44757246756e64732e726571756573743a20536563726574486173683520262053656372657448617368362073686f756c64206265206e6f6e2d7a65726f46756e64732e7769746864726177546f3a204f6e6c7920746865206c656e6465722063616e20776974686472617720746f6b656e7346756e64732e7365744d6178496e746572657374526174654e756d657261746f723a206d6178496e746572657374526174654e756d657261746f72206973207a65726f46756e64732e7365744c6f616e733a204c6f616e732061646472657373206d757374206265206e6f6e2d7a65726f46756e64732e656e61626c65436f6d706f756e643a204f6e6c7920746865206c656e6465722063616e20656e61626c6520436f6d706f756e6446756e64732e73657444656661756c74417262697465724665653a2064656661756c74417262697465724665652063616e6e6f74206265206c657373207468616e202d312546756e64732e757064617465437573746f6d3a2046756e64206d757374206265206120637573746f6d2066756e6446756e64732e7769746864726177546f3a20496e73756666696369656e742062616c616e636546756e64732e7365744d61785574696c697a6174696f6e44656c74613a204f6e6c7920746865206465706c6f7965722063616e20706572666f726d207468697346756e64732e736574436f6d706f756e643a2063546f6b656e2061646472657373206d757374206265206e6f6e2d7a65726f46756e64732e726571756573743a20536563726574486173683120262053656372657448617368322073686f756c64206265206e6f6e2d7a65726f46756e64732e726571756573743a20536563726574486173683320262053656372657448617368342073686f756c64206265206e6f6e2d7a65726f46756e64732e726571756573743a204c6f616e206475726174696f6e206d7573742062652067726561746572207468616e206d696e4c6f616e447572a265627a7a7230582001ece922c650df050f16dab7220a9a0e1dcfd2986d994476756a09a8d47974bd64736f6c634300050a0032

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

000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000006

-----Decoded View---------------
Arg [0] : token_ (address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Arg [1] : decimals_ (uint256): 6

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000006


Deployed Bytecode Sourcemap

62843:27474:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;62843:27474:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63527:53;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;63527:53:0;-1:-1:-1;;;;;63527:53:0;;:::i;:::-;;;;;;;;;;;;;;;;64189:34;;;:::i;70917:234::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;70917:234:0;;:::i;81808:114::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;81808:114:0;;;;;;;:::i;:::-;;64411:32;;;:::i;63945:36::-;;;:::i;62907:80::-;;;:::i;70403:376::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;70403:376:0;;:::i;64058:42::-;;;:::i;68457:412::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;68457:412:0;;:::i;76951:840::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;76951:840:0;;;;;;;:::i;63696:47::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;63696:47:0;-1:-1:-1;;;;;63696:47:0;;:::i;72059:203::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;72059:203:0;;:::i;72276:185::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;72276:185:0;;:::i;63856:40::-;;;:::i;64477:23::-;;;:::i;85655:1272::-;;;:::i;63410:47::-;;;:::i;71165:202::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;71165:202:0;;:::i;72708:106::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;72708:106:0;;:::i;:::-;;;;-1:-1:-1;;;;;72708:106:0;;;;;;;;;;;;;;63087:55;;;:::i;77805:690::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;77805:690:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;77805:690:0;;:::i;60391:130::-;;;:::i;64230:41::-;;;:::i;78509:1105::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;78509:1105:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;78509:1105:0;;:::i;70041:348::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;70041:348:0;;:::i;63466:50::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;63466:50:0;;;;;;;;:::i;64149:33::-;;;:::i;60350:26::-;;;:::i;63988:30::-;;;:::i;63337:66::-;;;:::i;87133:276::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;87133:276:0;;;;;;;;;:::i;64324:39::-;;;:::i;64507:29::-;;;:::i;63646:43::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;63646:43:0;;:::i;:::-;;;;-1:-1:-1;;;;;63646:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;73552:1277;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;73552:1277:0;;;;;;;;-1:-1:-1;;;;;73552:1277:0;;;;;;;;;;;;;;;;;:::i;63750:43::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;63750:43:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;71597:112;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;71597:112:0;;:::i;72475:219::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;72475:219:0;;:::i;84547:848::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;84547:848:0;;:::i;64025:26::-;;;:::i;72828:256::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;72828:256:0;;:::i;68883:340::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;68883:340:0;;:::i;86941:178::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;86941:178:0;;;;;;;;;;;;:::i;66530:480::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;66530:480:0;-1:-1:-1;;;;;66530:480:0;;:::i;70799:104::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;70799:104:0;;:::i;73299:101::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;73299:101:0;;:::i;:::-;;;;;;;;;;;;;;;;;;68095:348;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;68095:348:0;;:::i;63800:47::-;;;:::i;83553:980::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;83553:980:0;;:::i;71381:202::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;71381:202:0;;:::i;63213:54::-;;;:::i;71723:112::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;71723:112:0;;:::i;67677:404::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;67677:404:0;;:::i;62997:82::-;;;:::i;63590:45::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;63590:45:0;-1:-1:-1;;;;;63590:45:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;63590:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;73414:124;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;73414:124:0;-1:-1:-1;;;;;73414:124:0;;:::i;69639:388::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;69639:388:0;;:::i;83223:201::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;83223:201:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;83223:201:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;83223:201:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;83223:201:0;;-1:-1:-1;83223:201:0;-1:-1:-1;83223:201:0;:::i;67024:589::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;67024:589:0;;;;;;;;;;:::i;63276:54::-;;;:::i;64370:34::-;;;:::i;81936:1273::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;81936:1273:0;;;;;;;;;;;-1:-1:-1;;;;;81936:1273:0;;:::i;83438:101::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;83438:101:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;83438:101:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;83438:101:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;83438:101:0;;-1:-1:-1;83438:101:0;-1:-1:-1;83438:101:0;:::i;85409:232::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;85409:232:0;;:::i;71849:196::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;71849:196:0;;:::i;64278:39::-;;;:::i;64107:35::-;;;:::i;73092:193::-;;;:::i;79628:2166::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;79628:2166:0;;;-1:-1:-1;;;;;79628:2166:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;79628:2166:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;79628:2166:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;79628:2166:0;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;79628:2166:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;79628:2166:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;79628:2166:0;;-1:-1:-1;79628:2166:0;-1:-1:-1;79628:2166:0;:::i;74843:2094::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;74843:2094:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;74843:2094:0;;;;;;;;;;;;;;;;;:::i;34196:111::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;34196:111:0;;;;;;;:::i;69237:388::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;69237:388:0;;:::i;64452:18::-;;;:::i;63903:35::-;;;:::i;63527:53::-;;;;;;;;;;;;;:::o;64189:34::-;;;;:::o;70917:234::-;70972:7;70996:11;;;:5;:11;;;;;:18;;;70992:152;;;-1:-1:-1;71024:11:0;;;;:5;:11;;;;;:22;;;71017:29;;70992:152;71090:52;63134:8;71123:17;71127:2;71131:8;;71123:3;:17::i;:::-;71117:2;:23;71090:3;:52::i;:::-;71083:59;;70992:152;70917:234;;;:::o;81808:114::-;81877:37;81888:4;81894:7;81903:10;81877;:37::i;:::-;81808:114;;:::o;64411:32::-;;;;:::o;63945:36::-;;;;:::o;62907:80::-;62959:28;62907:80;:::o;70403:376::-;70503:8;;-1:-1:-1;;;;;70503:8:0;70489:10;:22;70481:97;;;;-1:-1:-1;;;70481:97:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70619:28;70597:18;:50;;70589:132;;;;-1:-1:-1;;;70589:132:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70733:17;:38;70403:376::o;64058:42::-;;;;:::o;68457:412::-;68577:8;;-1:-1:-1;;;;;68577:8:0;68563:10;:22;68555:107;;;;-1:-1:-1;;;68555:107:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68681:33;68673:119;;;;-1:-1:-1;;;68673:119:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68803:27;:58;68457:412::o;76951:840::-;77025:5;;:54;;;-1:-1:-1;;;77025:54:0;;77044:10;77025:54;;;;77064:4;77025:54;;;;;;;;;;;;-1:-1:-1;;;;;77025:5:0;;;;:18;;:54;;;;;;;;;;;;;;;:5;;:54;;;5:2:-1;;;;30:1;27;20:12;5:2;77025:54:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;77025:54:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;77025:54:0;77017:107;;;;-1:-1:-1;;;77017:107:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77139:11;;;;:5;:11;;;;;:27;;;;;;77135:557;;;77202:5;;77218:6;;77183:52;;-1:-1:-1;;;;;77202:5:0;;;;77218:6;77227:7;77183:10;:52::i;:::-;77250:19;77272:52;77276:17;77280:7;34143:8;77276:3;:17::i;:::-;77295:6;;;;;;;;;-1:-1:-1;;;;;77295:6:0;-1:-1:-1;;;;;77295:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;77295:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;77295:28:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;77295:28:0;77272:3;:52::i;:::-;77366:11;;;;:5;:11;;;;;:20;;;77250:74;;-1:-1:-1;77362:38:0;;77250:74;77362:3;:38::i;:::-;77339:11;;;;:5;:11;;;;;:20;;:61;77420:12;77345:4;77420:6;:12::i;:::-;77415:85;;77459:39;77463:21;;77486:11;77459:3;:39::i;:::-;77435:21;:63;77415:85;77135:557;;;;77558:11;;;;:5;:11;;;;;:19;;;77554:33;;77579:7;77554:3;:33::i;:::-;77532:11;;;;:5;:11;;;;;:19;;:55;77607:12;77538:4;77607:6;:12::i;:::-;77602:79;;77645:34;77649:20;;77671:7;77645:3;:34::i;:::-;77622:20;:57;77602:79;77707:12;77714:4;77707:6;:12::i;:::-;77702:42;;77722:20;:18;:20::i;:::-;77761:22;;;;;;;;;;;;;;;;;;;;;;;;;76951:840;;:::o;63696:47::-;;;;;;;;;;;;;:::o;72059:203::-;72111:7;72135:11;;;:5;:11;;;;;:18;;;72131:124;;;-1:-1:-1;72163:11:0;;;;:5;:11;;;;;:19;;;72156:26;;72131:124;-1:-1:-1;63051:28:0;72219:34;;72276:185;72324:7;72348:11;;;:5;:11;;;;;:18;;;72344:110;;;-1:-1:-1;72376:11:0;;;;:5;:11;;;;;:15;;;72369:22;;72344:110;-1:-1:-1;72435:17:0;;72428:24;;63856:40;;;;:::o;64477:23::-;;;;:::o;85655:1272::-;85721:76;85725:20;;85747:49;85752:21;;85775:20;:18;:20::i;:::-;85747:4;:49::i;:::-;85721:3;:76::i;:::-;85703:15;:94;85825:25;;85852:19;;85821:51;;85825:25;85821:3;:51::i;:::-;85814:3;:59;85810:1110;;;85890:24;85933:11;;85948:1;85933:16;85929:96;;85971:52;85976:11;;85989:33;85993:15;;86010:11;;85989:3;:33::i;:::-;85971:4;:52::i;:::-;85952:71;;85929:96;86064:20;;86045:16;:39;86041:665;;;86105:30;86138:43;86142:16;86160:20;;86138:3;:43::i;:::-;86105:76;;86230:147;86234:24;;86260:116;86264:27;;86293:82;86298:48;86302:19;;86323:22;86298:3;:48::i;:::-;86348:26;;86293:4;:82::i;86260:116::-;86230:3;:147::i;:::-;86200:27;:177;-1:-1:-1;86041:665:0;;;86418:30;86451:43;86455:20;;86477:16;86451:3;:43::i;:::-;86418:76;;86543:147;86547:24;;86573:116;86577:27;;86606:82;86611:48;86615:19;;86636:22;86611:3;:48::i;86606:82::-;86573:3;:116::i;:::-;86543:3;:147::i;:::-;86513:27;:177;-1:-1:-1;86041:665:0;86743:63;34179:8;86752:53;86756:27;;63322:8;86752:3;:53::i;86743:63::-;86722:18;:84;86851:3;86823:25;:31;86869:20;:39;85810:1110;85655:1272::o;63410:47::-;-1:-1:-1;;63410:47:0;:::o;71165:202::-;71220:7;71244:11;;;:5;:11;;;;;:18;;;71240:120;;;-1:-1:-1;71272:11:0;;;;:5;:11;;;;;:22;;;71265:29;;71240:120;-1:-1:-1;;;71331:27:0;;72708:106;72760:7;72787:11;;;:5;:11;;;;;:19;;;-1:-1:-1;;;;;72787:19:0;;72708:106::o;63087:55::-;63134:8;63087:55;:::o;77805:690::-;77982:12;77989:4;77982:6;:12::i;:::-;-1:-1:-1;;;;;77968:26:0;:10;-1:-1:-1;;;;;77968:26:0;;77960:88;;;;-1:-1:-1;;;77960:88:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63379:24;78081:33;78095:11;78108:5;78081:13;:33::i;:::-;:52;;:113;;;;-1:-1:-1;78173:3:0;63379:24;78173:21;78137:32;78151:11;78164:4;78137:13;:32::i;:::-;:57;;78081:113;78059:225;;;;-1:-1:-1;;;78059:225:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78297:11;;;;:5;:11;;;;;;;;;:22;;;:36;;;78344:22;;;:36;;;78391:19;;;;:30;;-1:-1:-1;;;;;78391:30:0;;-1:-1:-1;;;;;;78391:30:0;;;;;;;;78439:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77805:690;;;;:::o;60391:130::-;60445:7;60502:11;-1:-1:-1;;;;;60502:11:0;60391:130;;:::o;64230:41::-;;;;:::o;78509:1105::-;78891:11;;;;:5;:11;;;;;:18;;;78883:77;;;;-1:-1:-1;;;78883:77:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78994:11;78979;:26;;78971:113;;;;-1:-1:-1;;;78971:113:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79140:11;79103:33;79117:11;79130:5;79103:13;:33::i;:::-;:48;;79095:135;;;;-1:-1:-1;;;79095:135:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79241:48;79248:4;79254:11;79267;79280:8;79241:6;:48::i;:::-;-1:-1:-1;79300:11:0;;;;:5;:11;;;;;;:22;;;:36;;;;79347:22;;;:36;;;;79394:22;;;:36;;;;79441:20;;;:32;-1:-1:-1;;79484:19:0;;;:30;79525:15;;;:22;79558:28;;:48;78509:1105::o;70041:348::-;70145:8;;-1:-1:-1;;;;;70145:8:0;70131:10;:22;70123:99;;;;-1:-1:-1;;;70123:99:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70241:25;70233:95;;;;-1:-1:-1;;;70233:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70339:19;:42;70041:348::o;63466:50::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;64149:33::-;;;;:::o;60350:26::-;;;-1:-1:-1;;;;;60350:26:0;;:::o;63988:30::-;;;;:::o;63337:66::-;63379:24;63337:66;:::o;87133:276::-;87205:7;87229:10;87225:154;;87260:6;87256:75;;;-1:-1:-1;87294:3:0;63379:24;87294:21;87287:28;;87256:75;-1:-1:-1;63379:24:0;87345:22;;87225:154;-1:-1:-1;87396:5:0;87133:276;;;;;:::o;64324:39::-;;;;:::o;64507:29::-;;;-1:-1:-1;;;;;64507:29:0;;:::o;63646:43::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;63646:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;73552:1277::-;73848:10;73746:12;73815:21;;;:9;:21;;;;;;;;;73809:28;;:5;:28;;;;;:35;73746:12;;-1:-1:-1;;;;;73809:35:0;;;:49;;73801:114;;;;-1:-1:-1;;;73801:114:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63379:24;73959:33;73973:11;73986:5;73959:13;:33::i;:::-;:51;:111;;;;-1:-1:-1;74049:3:0;63379:24;74049:21;74014:32;74028:11;74041:4;74014:13;:32::i;:::-;:56;73959:111;73937:223;;;;-1:-1:-1;;;73937:223:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74177:11;;-1:-1:-1;;;74177:11:0;;;;74172:125;;74199:25;;74191:104;;;;-1:-1:-1;;;74191:104:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74319:17;74323:9;;74334:1;74319:3;:17::i;:::-;74307:9;:29;;;74354:18;74383:11;;;:5;:11;;;;;:31;;-1:-1:-1;;;;;;74383:31:0;74404:10;74383:31;;;74307:29;;-1:-1:-1;74450:33:0;;74464:11;;74450:13;:33::i;:::-;74425:11;;;;:5;:11;;;;;:22;;:58;74519:32;74533:11;74546:4;74519:13;:32::i;:::-;74494:11;;;;:5;:11;;;;;;;;:22;;;:57;;;;74562:19;;;;:30;;-1:-1:-1;;;;;;74562:30:0;-1:-1:-1;;;;;74562:30:0;;;;;74603:5;:11;;;;;:26;;-1:-1:-1;;74640:46:0;74562:30;74640:46;;;;;;;74729:9;;74707:10;74697:21;;:9;:21;;;;;;:42;74754:11;;74750:42;;74768:22;74776:4;74782:7;74768;:22::i;:::-;74809:12;;;;;;;;;;;;;;;;;73552:1277;;;;;;;:::o;63750:43::-;;;;;;;;;;;;;;;;;;;;;;:::o;71597:112::-;71652:7;71679:11;;;:5;:11;;;;;:22;;;;71597:112::o;72475:219::-;72536:7;72560:11;;;:5;:11;;;;;:18;;;72556:131;;;-1:-1:-1;72588:11:0;;;;:5;:11;;;;;:28;;;72581:35;;72556:131;-1:-1:-1;62959:28:0;72653:32;;84547:848;84614:11;;;;:5;:11;;;;;:27;;;;;;84606:91;;;;-1:-1:-1;;;84606:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84730:12;84737:4;84730:6;:12::i;:::-;-1:-1:-1;;;;;84716:26:0;:10;-1:-1:-1;;;;;84716:26:0;;84708:98;;;;-1:-1:-1;;;84708:98:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84841:5;;:30;;;-1:-1:-1;;;84841:30:0;;84865:4;84841:30;;;;;;84817:21;;-1:-1:-1;;;;;84841:5:0;;:15;;:30;;;;;;;;;;;;;;:5;:30;;;5:2:-1;;;;30:1;27;20:12;5:2;84841:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;84841:30:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;84841:30:0;84903:6;;;84912:11;;;:5;84841:30;84912:11;;;;:20;;;84841:30;;-1:-1:-1;84882:51:0;;-1:-1:-1;;;;;84903:6:0;;;;84882:12;:51::i;:::-;84967:5;;:30;;;-1:-1:-1;;;84967:30:0;;84991:4;84967:30;;;;;;84944:20;;-1:-1:-1;;;;;84967:5:0;;:15;;:30;;;;;;;;;;;;;;:5;:30;;;5:2:-1;;;;30:1;27;20:12;5:2;84967:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;84967:30:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;84967:30:0;;-1:-1:-1;85008:21:0;85032:32;84967:30;85050:13;85032:3;:32::i;:::-;85008:56;;85098:40;85102:20;;85124:13;85098:3;:40::i;:::-;85075:20;:63;85177:21;;85200:11;;;;:5;:11;;;;;:20;;;85173:48;;85177:21;85173:3;:48::i;:::-;85149:21;:72;;;85262:5;85232:11;;;:5;:11;;;;;;;;:35;;-1:-1:-1;;85232:35:0;;;85278:5;:11;;;;;:20;;;:24;;;;85313:19;;;;:35;;;85366:21;;;;;;;;;;;;;;;;;;84547:848;;;;:::o;64025:26::-;;;;:::o;72828:256::-;72875:7;72899:11;;;:5;:11;;;;;:27;;;;;;72895:182;;;72955:11;;;;:5;:11;;;;;;;;:20;;;72977:6;;:28;;-1:-1:-1;;;72977:28:0;;;;72950:56;;72955:20;;-1:-1:-1;;;;;72977:6:0;;;;:26;;:28;;;;;72955:11;72977:28;;;;;;;;:6;:28;;;5:2:-1;;;;30:1;27;20:12;5:2;72977:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;72977:28:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;72977:28:0;72950:4;:56::i;72895:182::-;-1:-1:-1;73046:11:0;;;;:5;:11;;;;;:19;;;73039:26;;68883:340;68985:8;;-1:-1:-1;;;;;68985:8:0;68971:10;:22;68963:98;;;;-1:-1:-1;;;68963:98:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69080:24;69072:92;;;;-1:-1:-1;;;69072:92:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69175:18;:40;68883:340::o;86941:178::-;87034:7;87061:50;87065:36;87070:7;87079:21;87084:5;87091:8;87079:4;:21::i;:::-;87065:4;:36::i;:::-;87103:7;87061:3;:50::i;:::-;87054:57;86941:178;-1:-1:-1;;;;86941:178:0:o;66530:480::-;66604:8;;-1:-1:-1;;;;;66604:8:0;66590:10;:22;66582:85;;;;-1:-1:-1;;;66582:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66694:5;;-1:-1:-1;;;;;66694:5:0;66686:28;66678:91;;;;-1:-1:-1;;;66678:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;66788:29:0;;66780:88;;;;-1:-1:-1;;;66780:88:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66879:5;:14;;-1:-1:-1;;;;;;66879:14:0;-1:-1:-1;;;;;66879:14:0;;;;;;;;;66912:5;;:44;;;-1:-1:-1;;;66912:44:0;;;;;;;;;-1:-1:-1;;66912:44:0;;;;;:5;;;:13;;:44;;;;;;;;;;;;;;;-1:-1:-1;66912:5:0;:44;;;5:2:-1;;;;30:1;27;20:12;5:2;66912:44:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;66912:44:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;66912:44:0;66904:98;;;;-1:-1:-1;;;66904:98:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66530:480;:::o;70799:104::-;70850:7;70877:11;;;:5;:11;;;;;:18;-1:-1:-1;;;;;70877:18:0;;70799:104::o;73299:101::-;73350:4;73374:11;;;:5;:11;;;;;:18;;;;73299:101::o;68095:348::-;68199:8;;-1:-1:-1;;;;;68199:8:0;68185:10;:22;68177:99;;;;-1:-1:-1;;;68177:99:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68295:25;68287:95;;;;-1:-1:-1;;;68287:95:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68393:19;:42;68095:348::o;63800:47::-;;;;:::o;83553:980::-;83619:11;;-1:-1:-1;;;83619:11:0;;;;83611:98;;;;-1:-1:-1;;;83611:98:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83728:11;;;;:5;:11;;;;;:27;;;;;;:36;83720:98;;;;-1:-1:-1;;;83720:98:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83851:12;83858:4;83851:6;:12::i;:::-;-1:-1:-1;;;;;83837:26:0;:10;-1:-1:-1;;;;;83837:26:0;;83829:96;;;;-1:-1:-1;;;83829:96:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83961:6;;:31;;;-1:-1:-1;;;83961:31:0;;83986:4;83961:31;;;;;;83936:22;;-1:-1:-1;;;;;83961:6:0;;:16;;:31;;;;;;;;;;;;;;:6;:31;;;5:2:-1;;;;30:1;27;20:12;5:2;83961:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;83961:31:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;83961:31:0;84022:5;;84038:6;;84022:5;84047:11;;;:5;83961:31;84047:11;;;;:19;;;83961:31;;-1:-1:-1;84003:64:0;;-1:-1:-1;;;;;84022:5:0;;;;84038:6;;;;84003:10;:64::i;:::-;84102:6;;:31;;;-1:-1:-1;;;84102:31:0;;84127:4;84102:31;;;;;;84078:21;;-1:-1:-1;;;;;84102:6:0;;:16;;:31;;;;;;;;;;;;;;:6;:31;;;5:2:-1;;;;30:1;27;20:12;5:2;84102:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;84102:31:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;84102:31:0;;-1:-1:-1;84144:22:0;84169:34;84102:31;84188:14;84169:3;:34::i;:::-;84241:20;;84263:11;;;;:5;:11;;;;;:19;;;84144:59;;-1:-1:-1;84237:46:0;;:3;:46::i;:::-;84214:20;:69;84322:21;;84318:42;;84345:14;84318:3;:42::i;:::-;84294:21;:66;;;84371:11;;;;:5;:11;;;;;;;;:34;;-1:-1:-1;;84371:34:0;;;;;84416:5;:11;;;;;:19;;;:23;;;;84450:20;;;;:37;;;84505:20;;;;;;;;;;;;;;;;;;83553:980;;;;:::o;71381:202::-;71436:7;71460:11;;;:5;:11;;;;;:18;;;71456:120;;;-1:-1:-1;71488:11:0;;;;:5;:11;;;;;:22;;;71481:29;;71456:120;-1:-1:-1;63260:7:0;71547:27;;63213:54;63260:7;63213:54;:::o;71723:112::-;71778:7;71805:11;;;:5;:11;;;;;;;;:22;;;71723:112::o;67677:404::-;67795:8;;-1:-1:-1;;;;;67795:8:0;67781:10;:22;67773:106;;;;-1:-1:-1;;;67773:106:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67898:32;67890:116;;;;-1:-1:-1;;;67890:116:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68017:26;:56;67677:404::o;62997:82::-;63051:28;62997:82;:::o;63590:45::-;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;63590:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;73414:124::-;-1:-1:-1;;;;;73504:19:0;73477:7;73504:19;;;:12;:19;;;;;:26;;73414:124::o;69639:388::-;69753:8;;-1:-1:-1;;;;;69753:8:0;69739:10;:22;69731:104;;;;-1:-1:-1;;;69731:104:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69854:30;69846:110;;;;-1:-1:-1;;;69846:110:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69967:24;:52;69639:388::o;83223:201::-;83300:6;83295:122;83312:24;;;83295:122;;;83371:10;83358:24;;;;:12;:24;;;;;83388:13;;83402:1;83388:16;;;;;;;27:10:-1;;39:1;23:18;;;45:23;;-1:-1;83358:47:0;;;83388:16;83358:47;;;;83388:16;;;;;;;;;83358:47;;;;;;-1:-1:-1;83338:3:0;83295:122;;;;83223:201;;:::o;67024:589::-;67134:8;;-1:-1:-1;;;;;67134:8:0;67120:10;:22;67112:99;;;;-1:-1:-1;;;67112:99:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67231:11;;-1:-1:-1;;;67231:11:0;;;;67230:12;67222:81;;;;-1:-1:-1;;;67222:81:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;67322:30:0;;67314:93;;;;-1:-1:-1;;;67314:93:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;67426:26:0;;67418:94;;;;-1:-1:-1;;;67418:94:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67523:6;:16;;:6;67550:26;;-1:-1:-1;;;;;67550:26:0;;;-1:-1:-1;;;;;;67550:26:0;;;;;;;-1:-1:-1;;;;67523:16:0;;;;;;;;;;67587:18;-1:-1:-1;;;67587:18:0;;;67024:589::o;63276:54::-;63322:8;63276:54;:::o;64370:34::-;;;;:::o;81936:1273::-;82047:12;82054:4;82047:6;:12::i;:::-;-1:-1:-1;;;;;82033:26:0;:10;-1:-1:-1;;;;;82033:26:0;;82025:92;;;;-1:-1:-1;;;82025:92:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82153:7;82136:13;82144:4;82136:7;:13::i;:::-;:24;;82128:75;;;;-1:-1:-1;;;82128:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82218:11;;;;:5;:11;;;;;:27;;;;;;82214:883;;;82287:6;;:31;;;-1:-1:-1;;;82287:31:0;;82312:4;82287:31;;;;;;82262:22;;-1:-1:-1;;;;;82287:6:0;;:16;;:31;;;;;;;;;;;;;;:6;:31;;;5:2:-1;;;;30:1;27;20:12;5:2;82287:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;82287:31:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;82287:31:0;82358:6;;82287:31;;-1:-1:-1;82333:42:0;;-1:-1:-1;;;;;82358:6:0;82367:7;82333:16;:42::i;:::-;82414:6;;:31;;;-1:-1:-1;;;82414:31:0;;82439:4;82414:31;;;;;;82390:21;;-1:-1:-1;;;;;82414:6:0;;:16;;:31;;;;;;;;;;;;;;:6;:31;;;5:2:-1;;;;30:1;27;20:12;5:2;82414:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;82414:31:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;82414:31:0;;-1:-1:-1;82460:22:0;82485:34;82489:14;82414:31;82485:3;:34::i;:::-;82561:11;;;;:5;:11;;;;;:20;;;82460:59;;-1:-1:-1;82557:41:0;;82460:59;82557:3;:41::i;:::-;82534:11;;;;:5;:11;;;;;;;;:20;;:64;;;;82621:5;;:35;;-1:-1:-1;;;82621:35:0;;-1:-1:-1;;;;;82621:35:0;;;;;;;;;;;;;;;:5;;;;;:14;;:35;;;;;82534:11;82621:35;;;;;;;:5;:35;;;5:2:-1;;;;30:1;27;20:12;5:2;82621:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;82621:35:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;82621:35:0;82613:87;;;;-1:-1:-1;;;82613:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82720:12;82727:4;82720:6;:12::i;:::-;82715:88;;82759:42;82763:21;;82786:14;82759:3;:42::i;:::-;82735:21;:66;82715:88;82214:883;;;;;;82861:11;;;;:5;:11;;;;;:19;;;82857:33;;82882:7;82857:3;:33::i;:::-;82835:11;;;;:5;:11;;;;;;;;:19;;:55;;;;82913:5;;:35;;-1:-1:-1;;;82913:35:0;;-1:-1:-1;;;;;82913:35:0;;;;;;;;;;;;;;;:5;;;;;:14;;:35;;;;;82835:11;82913:35;;;;;;;:5;:35;;;5:2:-1;;;;30:1;27;20:12;5:2;82913:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;82913:35:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;82913:35:0;82905:87;;;;-1:-1:-1;;;82905:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83012:12;83019:4;83012:6;:12::i;:::-;83007:79;;83050:34;83054:20;;83076:7;83050:3;:34::i;:::-;83027:20;:57;83007:79;83112:12;83119:4;83112:6;:12::i;:::-;83107:42;;83127:20;:18;:20::i;:::-;83166:35;;;;;;;;;;;;-1:-1:-1;;;;;83166:35:0;;;;;;;;;;;;;;;;;81936:1273;;;:::o;83438:101::-;83510:10;83502:19;;;;:7;:19;;;;;:29;;83524:7;;83502:29;:::i;85409:232::-;85505:5;;-1:-1:-1;;;;;85505:5:0;85483:10;:28;85475:108;;;;-1:-1:-1;;;85475:108:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85608:25;85612:11;;85625:7;85608:3;:25::i;:::-;85594:11;:39;-1:-1:-1;85409:232:0:o;71849:196::-;71902:7;71926:11;;;:5;:11;;;;;:18;;;71922:116;;;-1:-1:-1;71954:11:0;;;;:5;:11;;;;;:20;;;71947:27;;71922:116;-1:-1:-1;72018:18:0;;72011:25;;64278:39;;;;:::o;64107:35::-;;;;:::o;73092:193::-;73162:11;;73138:7;;-1:-1:-1;;;73162:11:0;;;;73158:120;;;73197:6;;;;;;;;;-1:-1:-1;;;;;73197:6:0;-1:-1:-1;;;;;73197:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;73197:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;73197:28:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;73197:28:0;;-1:-1:-1;73190:35:0;;73158:120;-1:-1:-1;73265:1:0;73258:8;;79628:2166;80034:17;80086:12;80093:4;80086:6;:12::i;:::-;-1:-1:-1;;;;;80072:26:0;:10;-1:-1:-1;;;;;80072:26:0;;80064:96;;;;-1:-1:-1;;;80064:96:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80190:13;80198:4;80190:7;:13::i;:::-;80179:7;:24;;80171:72;;;;-1:-1:-1;;;80171:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80273:16;80284:4;80273:10;:16::i;:::-;80262:7;:27;;80254:103;;;;-1:-1:-1;;;80254:103:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80387:16;80398:4;80387:10;:16::i;:::-;80376:7;:27;;80368:100;;;;-1:-1:-1;;;80368:100:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80499:16;80510:4;80499:10;:16::i;:::-;80487:8;:28;;80479:101;;;;-1:-1:-1;;;80479:101:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80611:26;80615:16;80626:4;80615:10;:16::i;:::-;80633:3;80611;:26::i;:::-;80599:8;:38;;:70;;;;;80653:16;80664:4;80653:10;:16::i;:::-;80641:8;:28;;80599:70;80591:151;;;;-1:-1:-1;;;80591:151:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;80761:23:0;;80753:84;;;;-1:-1:-1;;;80753:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80856:16;;:30;;;;:64;;-1:-1:-1;80890:16:0;;;;:30;;80856:64;80848:136;;;;-1:-1:-1;;;80848:136:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81003:16;;;;:30;;;;:64;;-1:-1:-1;81037:16:0;;;;:30;;81003:64;80995:136;;;;-1:-1:-1;;;80995:136:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81150:16;;;;:30;;;;:64;;-1:-1:-1;81184:16:0;;;;:30;;81150:64;81142:136;;;;-1:-1:-1;;;81142:136:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81297:16;;;;:30;;;;:64;;-1:-1:-1;81331:16:0;;;;:30;;81297:64;81289:136;;;;-1:-1:-1;;;81289:136:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81450:78;81461:4;81467:9;81478:7;81487:11;81500:8;81510:17;81450:10;:78::i;:::-;81438:90;;81539:71;81559:4;81565:9;81576:13;81539:71;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;;81539:71:0;;;;137:4:-1;81539:71:0;;;;;;;;;;;;;;;;;;-1:-1:-1;81591:8:0;;;;;;81539:71;;81591:8;;;;81539:71;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;;81539:71:0;;;;137:4:-1;81539:71:0;;;;;;;;;;;;;;;;;;-1:-1:-1;81601:8:0;;-1:-1:-1;81601:8:0;;;;81539:71;;81601:8;;;;81539:71;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;81539:19:0;;-1:-1:-1;;;81539:71:0:i;:::-;81621:40;81647:4;81653:7;81621:25;:40::i;:::-;81672:5;;:21;;;-1:-1:-1;;;81672:21:0;;;;;;;;;;-1:-1:-1;;;;;81672:5:0;;;;:10;;:21;;;;;:5;;:21;;;;;;;;:5;;:21;;;5:2:-1;;;;30:1;27;20:12;5:2;81672:21:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;81711:75:0;;;;;;-1:-1:-1;;;;;81711:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;81711:75:0;;;;;;;-1:-1:-1;81711:75:0;79628:2166;;;;;;;;;;;;;:::o;74843:2094::-;75356:10;75254:12;75323:21;;;:9;:21;;;;;;;;;75317:28;;:5;:28;;;;;:35;75254:12;;-1:-1:-1;;;;;75317:35:0;;;:49;;75309:114;;;;-1:-1:-1;;;75309:114:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63379:24;75467:33;75481:11;75494:5;75467:13;:33::i;:::-;:51;:111;;;;-1:-1:-1;75557:3:0;63379:24;75557:21;75522:32;75536:11;75549:4;75522:13;:32::i;:::-;:56;75467:111;75445:229;;;;-1:-1:-1;;;75445:229:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75709:11;75694;:26;;75686:113;;;;-1:-1:-1;;;75686:113:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75855:11;75818:33;75832:11;75845:5;75818:13;:33::i;:::-;:48;;75810:135;;;;-1:-1:-1;;;75810:135:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75963:11;;-1:-1:-1;;;75963:11:0;;;;75958:131;;75985:25;;75977:110;;;;-1:-1:-1;;;75977:110:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;76111:17;76115:9;;76126:1;76111:3;:17::i;:::-;76099:9;:29;;;;76154:9;;76146:18;;76139:25;;76196:10;76175:5;:11;76181:4;76175:11;;;;;;;;;;;:18;;;:31;;;;;-1:-1:-1;;;;;76175:31:0;;;;;-1:-1:-1;;;;;76175:31:0;;;;;;76242:11;76217:5;:11;76223:4;76217:11;;;;;;;;;;;:22;;:36;;;;76289:11;76264:5;:11;76270:4;76264:11;;;;;;;;;;;:22;;:36;;;;76336:11;76311:5;:11;76317:4;76311:11;;;;;;;;;;;:22;;:36;;;;76383:33;76397:11;76410:5;76383:13;:33::i;:::-;76358:11;;;;:5;:11;;;;;:22;;:58;76452:32;76466:11;76479:4;76452:13;:32::i;:::-;76427:11;;;;:5;:11;;;;;;;;:22;;;:57;;;;76495:20;;;;:32;;;76538:19;;;;:30;;;76579:15;;;;:22;;;76612:28;;;:48;;;76671:19;;;;:30;;-1:-1:-1;;;;;;76671:30:0;-1:-1:-1;;;;;76671:30:0;;;;;76712:11;;;;;:25;;-1:-1:-1;;76712:25:0;-1:-1:-1;76712:25:0;-1:-1:-1;;76748:46:0;76671:30;76748:46;;;;;;;76837:9;;76815:10;76805:21;;;;;;;;:42;76862:11;;76858:42;;76876:22;76884:4;76890:7;76876;:22::i;:::-;76917:12;;;;;;;;;;;;;;;;;74843:2094;;;;;;;;;;;;;;:::o;34196:111::-;34247:6;34108:7;34270:23;34274:9;34278:1;34281;34274:3;:9::i;:::-;34291:1;34108:7;34285;;34270:3;:23::i;:::-;:29;;;;;;;34196:111;-1:-1:-1;;;34196:111:0:o;69237:388::-;69351:8;;-1:-1:-1;;;;;69351:8:0;69337:10;:22;69329:104;;;;-1:-1:-1;;;69329:104:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69452:30;69444:110;;;;-1:-1:-1;;;69444:110:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69565:24;:52;69237:388::o;64452:18::-;;;-1:-1:-1;;;;;64452:18:0;;:::o;63903:35::-;;;;:::o;33310:104::-;33394:5;;;33389:16;;;;33381:25;;;;;33544:113;33596:6;33627:1;33623;:5;33615:14;;;;;;33648:1;33644;:5;;;;61478:462;61564:19;61576:6;61564:11;:19::i;:::-;61666:30;;;-1:-1:-1;;;61666:30:0;;61690:4;61666:30;;;;;;61632:5;;61594:20;;-1:-1:-1;;;;;61666:15:0;;;;;:30;;;;;;;;;;;;;;:15;:30;;;5:2:-1;;;;30:1;27;20:12;5:2;61666:30:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;61666:30:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;61666:30:0;;-1:-1:-1;61711:20:0;;;61707:73;;;-1:-1:-1;61760:8:0;61707:73;61831:6;61849:37;61861:5;61868:9;61831:6;61849:11;:37::i;:::-;61904:6;-1:-1:-1;;;;;61904:11:0;;61916:9;61904:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;61904:22:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;61904:22:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;61904:22:0;:27;61897:35;;;;61478:462;;;;;;:::o;33420:118::-;33472:6;33499;;;:30;;-1:-1:-1;;33514:5:0;;;33528:1;33523;33514:5;33523:1;33509:15;;;;;:20;33499:30;33491:39;;;;;33200:104;33284:5;;;33279:16;;;;33271:25;;;;;34313:113;34366:6;34143:8;34389:23;34393:9;34397:1;34400;34393:3;:9::i;:::-;34410:1;34143:8;34404:7;;34785:111;34838:6;34887:1;34861:23;34865:11;34869:1;34179:8;34865:3;:11::i;:::-;34882:1;34878;:5;;33665:100;33717:6;33748:1;33743;:6;;:14;;33756:1;33743:14;33736:21;33665:100;-1:-1:-1;;;33665:100:0:o;33771:::-;33823:6;33854:1;33849;:6;;:14;;33862:1;33849:14;;62455:381;62602:31;;;-1:-1:-1;;;62602:31:0;;62627:4;62602:31;;;;;;62570:6;;62529:22;;-1:-1:-1;;;;;62602:16:0;;;;;:31;;;;;;;;;;;;;;:16;:31;;;5:2:-1;;;;30:1;27;20:12;5:2;62602:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;62602:31:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;62602:31:0;;-1:-1:-1;62648:18:0;;;62644:69;;;-1:-1:-1;62692:9:0;62644:69;62723:35;62735:6;62743;62751;62723:11;:35::i;:::-;62777:6;-1:-1:-1;;;;;62777:13:0;;62791:6;62777:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;62777:21:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;62777:21:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;62777:21:0;:26;62769:59;;;;;-1:-1:-1;;;62769:59:0;;;;;;;;;;;;-1:-1:-1;;;62769:59:0;;;;;;;;;;;;;;;62455:381;;;;:::o;34994:267::-;35047:6;35074:1;35070;:5;:20;;34179:8;35070:20;;;35083:1;35070:20;35066:24;-1:-1:-1;35113:1:0;35108:6;;;;35103:151;35116:6;;35103:151;;35151:10;35156:1;35159;35151:4;:10::i;:::-;35147:14;-1:-1:-1;35186:1:0;35182;:5;:10;35178:65;;35217:10;35222:1;35225;35217:4;:10::i;:::-;35213:14;;35178:65;35129:1;35124:6;;;;35103:151;;34432:113;34485:6;34179:8;34508:23;34512:9;34516:1;34519;34512:3;:9::i;:::-;34529:1;34179:8;34523:7;;61954:487;62072:6;62090:35;62072:6;62110;62072;62090:11;:35::i;:::-;62150:31;;;-1:-1:-1;;;62150:31:0;;62175:4;62150:31;;;;;;62136:11;;-1:-1:-1;;;;;62150:16:0;;;;;:31;;;;;;;;;;;;;;;:16;:31;;;5:2:-1;;;;30:1;27;20:12;5:2;62150:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;62150:31:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;62150:31:0;62226:28;;;-1:-1:-1;;;62226:28:0;;;;62150:31;;-1:-1:-1;62192:18:0;;62213:42;;62150:31;;-1:-1:-1;;;;;62226:26:0;;;;;:28;;;;;62150:31;;62226:28;;;;;;;62192:18;62226:26;:28;;;5:2:-1;;;;30:1;27;20:12;62213:42:0;62192:63;;62286:8;62270:13;:24;62266:81;;;-1:-1:-1;62327:8:0;62266:81;62365:6;-1:-1:-1;;;;;62365:23:0;;62389:13;62365:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;62365:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;62365:38:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;62365:38:0;:43;62357:76;;;;;-1:-1:-1;;;62357:76:0;;;;;;;;;;;;-1:-1:-1;;;62357:76:0;;;;;;;;;;;;;;;61954:487;;;;;:::o;87423:757::-;87685:5;;:487;;;;;;;;;-1:-1:-1;;;;;87685:487:0;;;;;87643:17;;87685:5;;:12;;87712:3;:14;;;87685:487;;;87753:12;87760:4;87753:6;:12::i;:::-;-1:-1:-1;;;;;87685:487:0;;;;;87767:11;;;;:5;87685:487;87767:11;;;;;;;;:19;;;;;;87685:487;;;;;;;;;;;;;;;;;;;;87847:47;87821:7;87869:14;87773:4;87869:8;:14::i;:::-;87885:8;87847:12;:47::i;:::-;87685:487;;;;87913:46;87926:7;87935:13;87943:4;87935:7;:13::i;87913:46::-;87685:487;;;;87978:42;87991:7;88000:9;88004:4;88000:3;:9::i;87978:42::-;87685:487;;;;88039:11;87685:487;;;;88069:22;88086:4;88069:16;:22::i;:::-;87685:487;;;;;;;;;-1:-1:-1;;;;;;87685:487:0;;;;;;;;;;;;;88157:4;;87685:487;;;;;;;-1:-1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;87685:487:0;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;87685:487:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;87685:487:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;87685:487:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;87685:487:0;;87423:757;-1:-1:-1;;;;;;;87423:757:0:o;88194:609::-;88431:5;;:364;;;;;;;;;88488:16;;88431:364;;88488:16;88506;;;;88431:364;;;;88524:16;;;;88431:364;;;;;88542:16;;;;88431:364;;;;;;;;;;;88577:16;;;;88431:364;;88595:16;;;;88431:364;;;;-1:-1:-1;;;;;88431:5:0;;;;:21;;88467:4;;88431:364;;;;88488:16;88627:1;88613:16;;;;88431:364;;;;88631:13;88645:1;88631:16;;;;;;;;;;;88431:364;;88664:37;88687:13;88695:4;88687:7;:13::i;:::-;88664:22;:37::i;:::-;88716:8;88739;88762:7;:22;88770:13;88778:4;88770:7;:13::i;:::-;-1:-1:-1;;;;;88762:22:0;-1:-1:-1;;;;;88762:22:0;;;;;;;;;;;;88431:364;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;88431:364:0;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;88431:364:0;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;88431:364:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;88431:364:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;88431:364:0;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;88431:364:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;88431:364:0;;;;;;;;-1:-1:-1;;88431:364:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;88431:364:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;88431:364:0;;;;88194:609;;;;;:::o;88817:901::-;88906:11;;;;:5;:11;;;;;:27;;;;;;88902:679;;;88975:6;;:31;;;-1:-1:-1;;;88975:31:0;;89000:4;88975:31;;;;;;88950:22;;-1:-1:-1;;;;;88975:6:0;;:16;;:31;;;;;;;;;;;;;;:6;:31;;;5:2:-1;;;;30:1;27;20:12;5:2;88975:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;88975:31:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;88975:31:0;89046:6;;88975:31;;-1:-1:-1;89021:42:0;;-1:-1:-1;;;;;89046:6:0;89055:7;89021:16;:42::i;:::-;89102:6;;:31;;;-1:-1:-1;;;89102:31:0;;89127:4;89102:31;;;;;;89078:21;;-1:-1:-1;;;;;89102:6:0;;:16;;:31;;;;;;;;;;;;;;:6;:31;;;5:2:-1;;;;30:1;27;20:12;5:2;89102:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;89102:31:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;89102:31:0;;-1:-1:-1;89148:22:0;89173:34;89177:14;89102:31;89173:3;:34::i;:::-;89249:11;;;;:5;:11;;;;;:20;;;89148:59;;-1:-1:-1;89245:41:0;;89148:59;89245:3;:41::i;:::-;89222:11;;;;:5;:11;;;;;:20;;:64;89306:12;89228:4;89306:6;:12::i;:::-;89301:88;;89345:42;89349:21;;89372:14;89345:3;:42::i;:::-;89321:21;:66;89301:88;88902:679;;;;;;89447:11;;;;:5;:11;;;;;:19;;;89443:33;;89468:7;89443:3;:33::i;:::-;89421:11;;;;:5;:11;;;;;:19;;:55;89496:12;89427:4;89496:6;:12::i;:::-;89491:79;;89534:34;89538:20;;89560:7;89534:3;:34::i;:::-;89511:20;:57;89491:79;89596:12;89603:4;89596:6;:12::i;:::-;89591:120;;89639:25;89643:11;;89656:7;89639:3;:25::i;:::-;89625:11;:39;89679:20;:18;:20::i;60529:567::-;60586:24;60630:23;:21;:23::i;:::-;60692:34;;;-1:-1:-1;;;60692:34:0;;60720:4;60692:34;;;;;;60586:68;;-1:-1:-1;60665:24:0;;-1:-1:-1;;;;;60692:19:0;;;;;:34;;;;;-1:-1:-1;;60692:34:0;;;;;;;:19;:34;;;5:2:-1;;;;30:1;27;20:12;5:2;60692:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;60692:34:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;60692:34:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;60692:34:0;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;-1:-1;60692:34:0;;-1:-1:-1;60737:14:0;;-1:-1:-1;60737:14:0;;-1:-1:-1;;;60770:145:0;60791:7;:14;60787:1;:18;60770:145;;;60845:6;-1:-1:-1;;;;;60831:20:0;:7;60839:1;60831:10;;;;;;;;;;;;;;-1:-1:-1;;;;;60831:20:0;;60827:77;;;60884:4;60872:16;;60827:77;60807:3;;60770:145;;;;60930:9;60925:164;;60983:16;;;60997:1;60983:16;;;;;;;;;60956:24;;60983:16;;;;;;105:10:-1;60983:16:0;88:34:-1;136:17;;-1:-1;60983:16:0;60956:43;;61027:6;61014:7;61022:1;61014:10;;;;;;;;-1:-1:-1;;;;;61014:19:0;;;:10;;;;;;;;;;:19;;;;61048:29;;-1:-1:-1;;;61048:29:0;;;;;;;;;;;;;;;;:20;;;;;;61069:7;;61048:29;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;61048:29:0;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;61048:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;61048:29:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;61048:29:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;61048:29:0;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;-1:-1;;;;;;;60529:567:0;;;;:::o;61110:315::-;61276:42;;;-1:-1:-1;;;61276:42:0;;61308:4;61276:42;;;;-1:-1:-1;;;;;61276:42:0;;;;;;;;;61237:5;;61191:28;;61276:23;;;;;;:42;;;;;;;;;;;;;;;:23;:42;;;5:2:-1;;;;30:1;27;20:12;5:2;61276:42:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;61276:42:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;61276:42:0;;-1:-1:-1;61333:23:0;;;61329:89;;;61373:33;;;-1:-1:-1;;;61373:33:0;;-1:-1:-1;;;;;61373:33:0;;;;;;;-1:-1:-1;;;61373:33:0;;;;;;:21;;;;;;:33;;;;;-1:-1:-1;;61373:33:0;;;;;;;;-1:-1:-1;61373:21:0;:33;;;5:2:-1;;;;30:1;27;20:12;89732:582:0;89796:17;;:::i;:::-;-1:-1:-1;;;;;89855:22:0;;;;;;:15;:22;;;;;;89851:30;;89879:1;89851:3;:30::i;:::-;-1:-1:-1;;;;;89826:22:0;;;;;;:15;:22;;;;;:55;;;89900:24;89842:5;89900:17;:24::i;:::-;:50;;89892:121;;;;-1:-1:-1;;;89892:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90024:282;;;;;;;;-1:-1:-1;;;;;90046:19:0;;-1:-1:-1;90046:19:0;;;:12;:19;;;;;;;90070:15;:22;;;;;;;90024:282;;;;90066:30;;90094:1;90066:3;:30::i;:::-;90046:51;;;;;;;;;;;;;;;;;;;;90024:282;;-1:-1:-1;;;;;90112:19:0;;;;:12;:19;;;;;;90136:15;:22;;;;;;;;90024:282;;;;;90132:30;;:3;:30::i;:::-;90112:51;;;;;;;;;;;;;;;;;;;;90024:282;;-1:-1:-1;;;;;90178:19:0;;;;:12;:19;;;;;;;90202:15;:22;;;;;90024:282;;;;;90198:30;;:3;:30::i;:::-;90178:51;;;;;;;;;;;;;;;;;;;;90024:282;;-1:-1:-1;;;;;90244:19:0;;;;:12;:19;;;;;;90268:15;:22;;;;;90024:282;;;90264:30;;90292:1;90264:3;:30::i;:::-;90244:51;;;;;;;;;;;;;;;;90024:282;;;;;89732:582;;;:::o;62843:27474::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;62843:27474:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;62843:27474:0;;;-1:-1:-1;62843:27474:0;:::i;:::-;;;:::o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;62843:27474:0;;;-1:-1:-1;;62843:27474:0:o;:::-;;;;;;;;;;;;;;;;;

Swarm Source

bzzr://01ece922c650df050f16dab7220a9a0e1dcfd2986d994476756a09a8d47974bd

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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