ETH Price: $3,647.43 (+0.78%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Process118631212021-02-15 18:58:211420 days ago1613415501IN
Nuo Network: Kernel
0 ETH0.2611319132
Process108036022020-09-05 20:28:271583 days ago1599337707IN
Nuo Network: Kernel
0 ETH0.51171652280
Process107943292020-09-04 10:36:251584 days ago1599215785IN
Nuo Network: Kernel
0 ETH0.00843269229
Process107943202020-09-04 10:34:061584 days ago1599215646IN
Nuo Network: Kernel
0 ETH0.00843269229
Process107943202020-09-04 10:34:061584 days ago1599215646IN
Nuo Network: Kernel
0 ETH0.00843269229
Process107903822020-09-03 20:11:211585 days ago1599163881IN
Nuo Network: Kernel
0 ETH0.00773304210
Process107903822020-09-03 20:11:211585 days ago1599163881IN
Nuo Network: Kernel
0 ETH0.00776986211
Process107903822020-09-03 20:11:211585 days ago1599163881IN
Nuo Network: Kernel
0 ETH0.33300674211
Repay106238712020-08-09 5:41:381611 days ago1596951698IN
Nuo Network: Kernel
0 ETH0.0122304449
Repay106236522020-08-09 4:53:371611 days ago1596948817IN
Nuo Network: Kernel
0 ETH0.0145463455
Process105945652020-08-04 17:06:381615 days ago1596560798IN
Nuo Network: Kernel
0 ETH0.0839526756.5
Repay105934292020-08-04 13:02:091615 days ago1596546129IN
Nuo Network: Kernel
0 ETH0.0119269351.5
Repay105934292020-08-04 13:02:091615 days ago1596546129IN
Nuo Network: Kernel
0 ETH0.0119273451.5
Repay105919722020-08-04 7:40:351616 days ago1596526835IN
Nuo Network: Kernel
0 ETH0.0135485458.5
Repay105919722020-08-04 7:40:351616 days ago1596526835IN
Nuo Network: Kernel
0 ETH0.0144248758.5
Create Order105759792020-08-01 20:03:131618 days ago1596312193IN
Nuo Network: Kernel
0 ETH0.0260441151
Create Order105432182020-07-27 18:48:051623 days ago1595875685IN
Nuo Network: Kernel
0 ETH0.0051717680
Create Order105432172020-07-27 18:48:011623 days ago1595875681IN
Nuo Network: Kernel
0 ETH0.0051717680
Create Order105432172020-07-27 18:48:011623 days ago1595875681IN
Nuo Network: Kernel
0 ETH0.0051679280
Create Order105431992020-07-27 18:44:121623 days ago1595875452IN
Nuo Network: Kernel
0 ETH0.0051688880
Create Order105431722020-07-27 18:38:031623 days ago1595875083IN
Nuo Network: Kernel
0 ETH0.0397277680
Repay105374582020-07-26 21:14:391624 days ago1595798079IN
Nuo Network: Kernel
0 ETH0.0100505738.5
Repay105186622020-07-23 23:23:171627 days ago1595546597IN
Nuo Network: Kernel
0 ETH0.0109109742
Create Order105165852020-07-23 15:47:211627 days ago1595519241IN
Nuo Network: Kernel
0 ETH0.043096480
Create Order105107822020-07-22 18:19:431628 days ago1595441983IN
Nuo Network: Kernel
0 ETH0.0279189955
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:
Kernel

Compiler Version
v0.4.24+commit.e67f0147

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2019-04-17
*/

pragma solidity 0.4.24;

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

    // custom : not in original DSMath, putting it here for consistency, copied from SafeMath
    function div(uint x, uint y) internal pure returns (uint z) {
        z = x / y;
    }

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

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

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

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

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

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

    function name() external view returns(string);
    function symbol() external view returns(string);
    function decimals() external view returns(uint8);
    function totalSupply() external view returns (uint);

    function balanceOf(address tokenOwner) external view returns (uint balance);
    function allowance(address tokenOwner, address spender) external view returns (uint remaining);
    function transfer(address to, uint tokens) external returns (bool success);
    function approve(address spender, uint tokens) external returns (bool success);
    function transferFrom(address from, address to, uint tokens) external returns (bool success);

    event Transfer(address indexed from, address indexed to, uint tokens);
    event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
contract Utils {

    modifier addressValid(address _address) {
        require(_address != address(0), "Utils::_ INVALID_ADDRESS");
        _;
    }

}
contract ErrorUtils {

    event LogError(string methodSig, string errMsg);
    event LogErrorWithHintBytes32(bytes32 indexed bytes32Value, string methodSig, string errMsg);
    event LogErrorWithHintAddress(address indexed addressValue, string methodSig, string errMsg);

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

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

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

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

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

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

    modifier auth {
        require(isAuthorized(msg.sender, msg.sig), "DSAuth::_ SENDER_NOT_AUTHORIZED");
        _;
    }

    function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
        if (src == address(this)) {
            return true;
        } else if (src == owner) {
            return true;
        } else if (authority == DSAuthority(0)) {
            return false;
        } else {
            return authority.canCall(src, this, sig);
        }
    }
}
contract DSNote {
    event LogNote(
        bytes4   indexed  sig,
        address  indexed  guy,
        bytes32  indexed  foo,
        bytes32  indexed  bar,
        uint              wad,
        bytes             fax
    ) anonymous;

    modifier note {
        bytes32 foo;
        bytes32 bar;

        assembly {
            foo := calldataload(4)
            bar := calldataload(36)
        }

        emit LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);

        _;
    }
}
contract SelfAuthorized {
    modifier authorized() {
        require(msg.sender == address(this), "Method can only be called from this contract");
        _;
    }
}
contract DateTime {
    /*
        *  Date and Time utilities for ethereum contracts
        *
        */
    struct _DateTime {
        uint16 year;
        uint8 month;
        uint8 day;
        uint8 hour;
        uint8 minute;
        uint8 second;
        uint8 weekday;
    }

    uint constant DAY_IN_SECONDS = 86400;
    uint constant YEAR_IN_SECONDS = 31536000;
    uint constant LEAP_YEAR_IN_SECONDS = 31622400;

    uint constant HOUR_IN_SECONDS = 3600;
    uint constant MINUTE_IN_SECONDS = 60;

    uint16 constant ORIGIN_YEAR = 1970;

    function isLeapYear(uint16 year) public pure returns (bool) {
        if (year % 4 != 0) {
            return false;
        }
        if (year % 100 != 0) {
            return true;
        }
        if (year % 400 != 0) {
            return false;
        }
        return true;
    }

    function leapYearsBefore(uint year) public pure returns (uint) {
        year -= 1;
        return year / 4 - year / 100 + year / 400;
    }

    function getDaysInMonth(uint8 month, uint16 year) public pure returns (uint8) {
        if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
            return 31;
        }
        else if (month == 4 || month == 6 || month == 9 || month == 11) {
            return 30;
        }
        else if (isLeapYear(year)) {
            return 29;
        }
        else {
            return 28;
        }
    }

    function parseTimestamp(uint timestamp) internal pure returns (_DateTime dt) {
        uint secondsAccountedFor = 0;
        uint buf;
        uint8 i;

        // Year
        dt.year = getYear(timestamp);
        buf = leapYearsBefore(dt.year) - leapYearsBefore(ORIGIN_YEAR);

        secondsAccountedFor += LEAP_YEAR_IN_SECONDS * buf;
        secondsAccountedFor += YEAR_IN_SECONDS * (dt.year - ORIGIN_YEAR - buf);

        // Month
        uint secondsInMonth;
        for (i = 1; i <= 12; i++) {
            secondsInMonth = DAY_IN_SECONDS * getDaysInMonth(i, dt.year);
            if (secondsInMonth + secondsAccountedFor > timestamp) {
                dt.month = i;
                break;
            }
            secondsAccountedFor += secondsInMonth;
        }

        // Day
        for (i = 1; i <= getDaysInMonth(dt.month, dt.year); i++) {
            if (DAY_IN_SECONDS + secondsAccountedFor > timestamp) {
                dt.day = i;
                break;
            }
            secondsAccountedFor += DAY_IN_SECONDS;
        }

        // Hour
        dt.hour = getHour(timestamp);

        // Minute
        dt.minute = getMinute(timestamp);

        // Second
        dt.second = getSecond(timestamp);

        // Day of week.
        dt.weekday = getWeekday(timestamp);
    }

    function getYear(uint timestamp) public pure returns (uint16) {
        uint secondsAccountedFor = 0;
        uint16 year;
        uint numLeapYears;

        // Year
        year = uint16(ORIGIN_YEAR + timestamp / YEAR_IN_SECONDS);
        numLeapYears = leapYearsBefore(year) - leapYearsBefore(ORIGIN_YEAR);

        secondsAccountedFor += LEAP_YEAR_IN_SECONDS * numLeapYears;
        secondsAccountedFor += YEAR_IN_SECONDS * (year - ORIGIN_YEAR - numLeapYears);

        while (secondsAccountedFor > timestamp) {
            if (isLeapYear(uint16(year - 1))) {
                secondsAccountedFor -= LEAP_YEAR_IN_SECONDS;
            }
            else {
                secondsAccountedFor -= YEAR_IN_SECONDS;
            }
            year -= 1;
        }
        return year;
    }

    function getMonth(uint timestamp) public pure returns (uint8) {
        return parseTimestamp(timestamp).month;
    }

    function getDay(uint timestamp) public pure returns (uint8) {
        return parseTimestamp(timestamp).day;
    }

    function getHour(uint timestamp) public pure returns (uint8) {
        return uint8((timestamp / 60 / 60) % 24);
    }

    function getMinute(uint timestamp) public pure returns (uint8) {
        return uint8((timestamp / 60) % 60);
    }

    function getSecond(uint timestamp) public pure returns (uint8) {
        return uint8(timestamp % 60);
    }

    function getWeekday(uint timestamp) public pure returns (uint8) {
        return uint8((timestamp / DAY_IN_SECONDS + 4) % 7);
    }

    function toTimestamp(uint16 year, uint8 month, uint8 day) public pure returns (uint timestamp) {
        return toTimestamp(year, month, day, 0, 0, 0);
    }

    function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour) public pure returns (uint timestamp) {
        return toTimestamp(year, month, day, hour, 0, 0);
    }

    function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute) public pure returns (uint timestamp) {
        return toTimestamp(year, month, day, hour, minute, 0);
    }

    function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute, uint8 second) public pure returns (uint timestamp) {
        uint16 i;

        // Year
        for (i = ORIGIN_YEAR; i < year; i++) {
            if (isLeapYear(i)) {
                timestamp += LEAP_YEAR_IN_SECONDS;
            }
            else {
                timestamp += YEAR_IN_SECONDS;
            }
        }

        // Month
        uint8[12] memory monthDayCounts;
        monthDayCounts[0] = 31;
        if (isLeapYear(year)) {
            monthDayCounts[1] = 29;
        }
        else {
            monthDayCounts[1] = 28;
        }
        monthDayCounts[2] = 31;
        monthDayCounts[3] = 30;
        monthDayCounts[4] = 31;
        monthDayCounts[5] = 30;
        monthDayCounts[6] = 31;
        monthDayCounts[7] = 31;
        monthDayCounts[8] = 30;
        monthDayCounts[9] = 31;
        monthDayCounts[10] = 30;
        monthDayCounts[11] = 31;

        for (i = 1; i < month; i++) {
            timestamp += DAY_IN_SECONDS * monthDayCounts[i - 1];
        }

        // Day
        timestamp += DAY_IN_SECONDS * (day - 1);

        // Hour
        timestamp += HOUR_IN_SECONDS * (hour);

        // Minute
        timestamp += MINUTE_IN_SECONDS * (minute);

        // Second
        timestamp += second;

        return timestamp;
    }
}
contract WETH9 {
    string public name     = "Wrapped Ether";
    string public symbol   = "WETH";
    uint8  public decimals = 18;

    event  Approval(address indexed _owner, address indexed _spender, uint _value);
    event  Transfer(address indexed _from, address indexed _to, uint _value);
    event  Deposit(address indexed _owner, uint _value);
    event  Withdrawal(address indexed _owner, uint _value);

    mapping (address => uint)                       public  balanceOf;
    mapping (address => mapping (address => uint))  public  allowance;

    function() public payable {
        deposit();
    }

    function deposit() public payable {
        balanceOf[msg.sender] += msg.value;
        Deposit(msg.sender, msg.value);
    }

    function withdraw(uint wad) public {
        require(balanceOf[msg.sender] >= wad);
        balanceOf[msg.sender] -= wad;
        msg.sender.transfer(wad);
        Withdrawal(msg.sender, wad);
    }

    function totalSupply() public view returns (uint) {
        return this.balance;
    }

    function approve(address guy, uint wad) public returns (bool) {
        allowance[msg.sender][guy] = wad;
        Approval(msg.sender, guy, wad);
        return true;
    }

    function transfer(address dst, uint wad) public returns (bool) {
        return transferFrom(msg.sender, dst, wad);
    }

    function transferFrom(address src, address dst, uint wad)
        public
        returns (bool)
    {
        require(balanceOf[src] >= wad);

        if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) {
            require(allowance[src][msg.sender] >= wad);
            allowance[src][msg.sender] -= wad;
        }

        balanceOf[src] -= wad;
        balanceOf[dst] += wad;

        Transfer(src, dst, wad);

        return true;
    }
}

contract Proxy {

    // masterCopy always needs to be first declared variable, to ensure that it is at the same location in the contracts to which calls are delegated.
    address masterCopy;

    /// @dev Constructor function sets address of master copy contract.
    /// @param _masterCopy Master copy address.
    constructor(address _masterCopy)
        public
    {
        require(_masterCopy != 0, "Invalid master copy address provided");
        masterCopy = _masterCopy;
    }

    /// @dev Fallback function forwards all transactions and returns all received return data.
    function ()
        external
        payable
    {
        // solium-disable-next-line security/no-inline-assembly
        assembly {
            let masterCopy := and(sload(0), 0xffffffffffffffffffffffffffffffffffffffff)
            calldatacopy(0, 0, calldatasize())
            let success := delegatecall(gas, masterCopy, 0, calldatasize(), 0, 0)
            returndatacopy(0, 0, returndatasize())
            if eq(success, 0) { revert(0, returndatasize()) }
            return(0, returndatasize())
        }
    }

    function implementation()
        public
        view
        returns (address)
    {
        return masterCopy;
    }

    function proxyType()
        public
        pure
        returns (uint256)
    {
        return 2;
    }
}

contract DSStop is DSNote, DSAuth {

    bool public stopped = false;

    modifier whenNotStopped {
        require(!stopped, "DSStop::_ FEATURE_STOPPED");
        _;
    }

    modifier whenStopped {
        require(stopped, "DSStop::_ FEATURE_NOT_STOPPED");
        _;
    }

    function stop() public auth note {
        stopped = true;
    }
    function start() public auth note {
        stopped = false;
    }

}
interface KyberNetworkProxy {

    function maxGasPrice() external view returns(uint);
    function getUserCapInWei(address user) external view returns(uint);
    function getUserCapInTokenWei(address user, ERC20 token) external view returns(uint);
    function enabled() external view returns(bool);
    function info(bytes32 id) external view returns(uint);

    function swapTokenToToken(ERC20 src, uint srcAmount, ERC20 dest, uint minConversionRate) external returns(uint);
    function swapEtherToToken(ERC20 token, uint minConversionRate) external payable returns(uint);
    function swapTokenToEther(ERC20 token, uint srcAmount, uint minConversionRate) external returns(uint);

    function getExpectedRate
    (
        ERC20 src,
        ERC20 dest, 
        uint srcQty
    ) 
        external
        view
        returns 
    (
        uint expectedRate,
        uint slippageRate
    );

    function tradeWithHint
    (
        ERC20 src,
        uint srcAmount,
        ERC20 dest,
        address destAddress,
        uint maxDestAmount,
        uint minConversionRate,
        address walletId,
        bytes hint
    )
        external 
        payable 
        returns(uint);
        
}

library ECRecovery {

    function recover(bytes32 _hash, bytes _sig)
        internal
        pure
    returns (address)
    {
        bytes32 r;
        bytes32 s;
        uint8 v;

        if (_sig.length != 65) {
            return (address(0));
        }

        assembly {
            r := mload(add(_sig, 32))
            s := mload(add(_sig, 64))
            v := byte(0, mload(add(_sig, 96)))
        }

        if (v < 27) {
            v += 27;
        }

        if (v != 27 && v != 28) {
            return (address(0));
        } else {
            return ecrecover(_hash, v, r, s);
        }
    }

    function toEthSignedMessageHash(bytes32 _hash)
        internal
        pure
    returns (bytes32)
    {
        return keccak256(
            abi.encodePacked("\x19Ethereum Signed Message:\n32", _hash)
        );
    }
}


contract Utils2 {
    using ECRecovery for bytes32;
    
    function _recoverSigner(bytes32 _hash, bytes _signature) 
        internal
        pure
        returns(address _signer)
    {
        return _hash.toEthSignedMessageHash().recover(_signature);
    }

}


contract DSThing is DSNote, DSAuth, DSMath {

    function S(string s) internal pure returns (bytes4) {
        return bytes4(keccak256(s));
    }

}


contract MasterCopy is SelfAuthorized {
  // masterCopy always needs to be first declared variable, to ensure that it is at the same location as in the Proxy contract.
  // It should also always be ensured that the address is stored alone (uses a full word)
    address masterCopy;

  /// @dev Allows to upgrade the contract. This can only be done via a Safe transaction.
  /// @param _masterCopy New contract address.
    function changeMasterCopy(address _masterCopy)
        public
        authorized
    {
        // Master copy address cannot be null.
        require(_masterCopy != 0, "Invalid master copy address provided");
        masterCopy = _masterCopy;
    }
}


contract Config is DSNote, DSAuth, Utils {

    WETH9 public weth9;
    mapping (address => bool) public isAccountHandler;
    mapping (address => bool) public isAdmin;
    address[] public admins;
    bool public disableAdminControl = false;
    
    event LogAdminAdded(address indexed _admin, address _by);
    event LogAdminRemoved(address indexed _admin, address _by);

    constructor() public {
        admins.push(msg.sender);
        isAdmin[msg.sender] = true;
    }

    modifier onlyAdmin(){
        require(isAdmin[msg.sender], "Config::_ SENDER_NOT_AUTHORIZED");
        _;
    }

    function setWETH9
    (
        address _weth9
    ) 
        public
        auth
        note
        addressValid(_weth9) 
    {
        weth9 = WETH9(_weth9);
    }

    function setAccountHandler
    (
        address _accountHandler,
        bool _isAccountHandler
    )
        public
        auth
        note
        addressValid(_accountHandler)
    {
        isAccountHandler[_accountHandler] = _isAccountHandler;
    }

    function toggleAdminsControl() 
        public
        auth
        note
    {
        disableAdminControl = !disableAdminControl;
    }

    function isAdminValid(address _admin)
        public
        view
        returns (bool)
    {
        if(disableAdminControl) {
            return true;
        } else {
            return isAdmin[_admin];
        }
    }

    function getAllAdmins()
        public
        view
        returns(address[])
    {
        return admins;
    }

    function addAdmin
    (
        address _admin
    )
        external
        note
        onlyAdmin
        addressValid(_admin)
    {   
        require(!isAdmin[_admin], "Config::addAdmin ADMIN_ALREADY_EXISTS");

        admins.push(_admin);
        isAdmin[_admin] = true;

        emit LogAdminAdded(_admin, msg.sender);
    }

    function removeAdmin
    (
        address _admin
    ) 
        external
        note
        onlyAdmin
        addressValid(_admin)
    {   
        require(isAdmin[_admin], "Config::removeAdmin ADMIN_DOES_NOT_EXIST");
        require(msg.sender != _admin, "Config::removeAdmin ADMIN_NOT_AUTHORIZED");

        isAdmin[_admin] = false;

        for (uint i = 0; i < admins.length - 1; i++) {
            if (admins[i] == _admin) {
                admins[i] = admins[admins.length - 1];
                admins.length -= 1;
                break;
            }
        }

        emit LogAdminRemoved(_admin, msg.sender);
    }
}


contract Account is MasterCopy, DSNote, Utils, Utils2, ErrorUtils {

    address[] public users;
    mapping (address => bool) public isUser;
    mapping (bytes32 => bool) public actionCompleted;

    WETH9 public weth9;
    Config public config;
    bool public isInitialized = false;

    event LogTransferBySystem(address indexed token, address indexed to, uint value, address by);
    event LogTransferByUser(address indexed token, address indexed to, uint value, address by);
    event LogUserAdded(address indexed user, address by);
    event LogUserRemoved(address indexed user, address by);
    event LogImplChanged(address indexed newImpl, address indexed oldImpl);

    modifier initialized() {
        require(isInitialized, "Account::_ ACCOUNT_NOT_INITIALIZED");
        _;
    }

    modifier notInitialized() {
        require(!isInitialized, "Account::_ ACCOUNT_ALREADY_INITIALIZED");
        _;
    }

    modifier userExists(address _user) {
        require(isUser[_user], "Account::_ INVALID_USER");
        _;
    }

    modifier userDoesNotExist(address _user) {
        require(!isUser[_user], "Account::_ USER_DOES_NOT_EXISTS");
        _;
    }

    modifier onlyAdmin() {
        require(config.isAdminValid(msg.sender), "Account::_ INVALID_ADMIN_ACCOUNT");
        _;
    }

    modifier onlyHandler(){
        require(config.isAccountHandler(msg.sender), "Account::_ INVALID_ACC_HANDLER");
        _;
    }

    function init(address _user, address _config)
        public 
        notInitialized
    {
        users.push(_user);
        isUser[_user] = true;
        config = Config(_config);
        weth9 = config.weth9();
        isInitialized = true;
    }
    
    function getAllUsers() public view returns (address[]) {
        return users;
    }

    function balanceFor(address _token) public view returns (uint _balance){
        _balance = ERC20(_token).balanceOf(this);
    }
    
    function transferBySystem
    (   
        address _token,
        address _to,
        uint _value
    ) 
        external 
        onlyHandler
        note 
        initialized
    {
        require(ERC20(_token).balanceOf(this) >= _value, "Account::transferBySystem INSUFFICIENT_BALANCE_IN_ACCOUNT");
        ERC20(_token).transfer(_to, _value);

        emit LogTransferBySystem(_token, _to, _value, msg.sender);
    }
    
    function transferByUser
    (   
        address _token,
        address _to,
        uint _value,
        uint _salt,
        bytes _signature
    )
        external
        addressValid(_to)
        note
        initialized
        onlyAdmin
    {
        bytes32 actionHash = _getTransferActionHash(_token, _to, _value, _salt);

        if(actionCompleted[actionHash]) {
            emit LogError("Account::transferByUser", "ACTION_ALREADY_PERFORMED");
            return;
        }

        if(ERC20(_token).balanceOf(this) < _value){
            emit LogError("Account::transferByUser", "INSUFFICIENT_BALANCE_IN_ACCOUNT");
            return;
        }

        address signer = _recoverSigner(actionHash, _signature);

        if(!isUser[signer]) {
            emit LogError("Account::transferByUser", "SIGNER_NOT_AUTHORIZED_WITH_ACCOUNT");
            return;
        }

        actionCompleted[actionHash] = true;
        
        if (_token == address(weth9)) {
            weth9.withdraw(_value);
            _to.transfer(_value);
        } else {
            require(ERC20(_token).transfer(_to, _value), "Account::transferByUser TOKEN_TRANSFER_FAILED");
        }

        emit LogTransferByUser(_token, _to, _value, signer);
    }

    function addUser
    (
        address _user,
        uint _salt,
        bytes _signature
    )
        external 
        note 
        addressValid(_user)
        userDoesNotExist(_user)
        initialized
        onlyAdmin
    {   
        bytes32 actionHash = _getUserActionHash(_user, "ADD_USER", _salt);
        if(actionCompleted[actionHash])
        {
            emit LogError("Account::addUser", "ACTION_ALREADY_PERFORMED");
            return;
        }

        address signer = _recoverSigner(actionHash, _signature);

        if(!isUser[signer]) {
            emit LogError("Account::addUser", "SIGNER_NOT_AUTHORIZED_WITH_ACCOUNT");
            return;
        }

        actionCompleted[actionHash] = true;

        users.push(_user);
        isUser[_user] = true;

        emit LogUserAdded(_user, signer);
    }

    function removeUser
    (
        address _user,
        uint _salt,
        bytes _signature
    ) 
        external
        note
        userExists(_user) 
        initialized
        onlyAdmin
    {   
        bytes32 actionHash = _getUserActionHash(_user, "REMOVE_USER", _salt);

        if(actionCompleted[actionHash]) {
            emit LogError("Account::removeUser", "ACTION_ALREADY_PERFORMED");
            return;
        }

        address signer = _recoverSigner(actionHash, _signature);
        
        if(users.length == 1){
            emit LogError("Account::removeUser",  "ACC_SHOULD_HAVE_ATLEAST_ONE_USER");
            return;
        }
        
        if(!isUser[signer]){
            emit LogError("Account::removeUser", "SIGNER_NOT_AUTHORIZED_WITH_ACCOUNT");
            return;
        }
        
        actionCompleted[actionHash] = true;

        // should delete value from isUser map? delete isUser[_user]?
        isUser[_user] = false;
        for (uint i = 0; i < users.length - 1; i++) {
            if (users[i] == _user) {
                users[i] = users[users.length - 1];
                users.length -= 1;
                break;
            }
        }

        emit LogUserRemoved(_user, signer);
    }

    function _getTransferActionHash
    ( 
        address _token,
        address _to,
        uint _value,
        uint _salt
    ) 
        internal
        view
        returns (bytes32)
    {
        return keccak256(
            abi.encodePacked(
                address(this),
                _token,
                _to,
                _value,
                _salt
            )
        );
    }

    function _getUserActionHash
    ( 
        address _user,
        string _action,
        uint _salt
    ) 
        internal
        view
        returns (bytes32)
    {
        return keccak256(
            abi.encodePacked(
                address(this),
                _user,
                _action,
                _salt
            )
        );
    }

    // to directly send ether to contract
    function() external payable {
        require(msg.data.length == 0 && msg.value > 0, "Account::fallback INVALID_ETHER_TRANSFER");

        if(msg.sender != address(weth9)){
            weth9.deposit.value(msg.value)();
        }
    }

    function changeImpl
    (
        address _to,
        uint _salt,
        bytes _signature
    )
        external 
        note 
        addressValid(_to)
        initialized
        onlyAdmin
    {   
        bytes32 actionHash = _getUserActionHash(_to, "CHANGE_ACCOUNT_IMPLEMENTATION", _salt);
        if(actionCompleted[actionHash])
        {
            emit LogError("Account::changeImpl", "ACTION_ALREADY_PERFORMED");
            return;
        }

        address signer = _recoverSigner(actionHash, _signature);

        if(!isUser[signer]) {
            emit LogError("Account::changeImpl", "SIGNER_NOT_AUTHORIZED_WITH_ACCOUNT");
            return;
        }

        actionCompleted[actionHash] = true;

        address oldImpl = masterCopy;
        this.changeMasterCopy(_to);
        
        emit LogImplChanged(_to, oldImpl);
    }

}


contract AccountFactory is DSStop, Utils {
    Config public config;
    mapping (address => bool) public isAccount;
    mapping (address => address[]) public userToAccounts;
    address[] public accounts;

    address public accountMaster;

    constructor
    (
        Config _config, 
        address _accountMaster
    ) 
    public 
    {
        config = _config;
        accountMaster = _accountMaster;
    }

    event LogAccountCreated(address indexed user, address indexed account, address by);

    modifier onlyAdmin() {
        require(config.isAdminValid(msg.sender), "AccountFactory::_ INVALID_ADMIN_ACCOUNT");
        _;
    }

    function setConfig(Config _config) external note auth addressValid(_config) {
        config = _config;
    }

    function setAccountMaster(address _accountMaster) external note auth addressValid(_accountMaster) {
        accountMaster = _accountMaster;
    }

    function newAccount(address _user)
        public
        note
        onlyAdmin
        addressValid(config)
        addressValid(accountMaster)
        whenNotStopped
        returns 
        (
            Account _account
        ) 
    {
        address proxy = new Proxy(accountMaster);
        _account = Account(proxy);
        _account.init(_user, config);

        accounts.push(_account);
        userToAccounts[_user].push(_account);
        isAccount[_account] = true;

        emit LogAccountCreated(_user, _account, msg.sender);
    }
    
    function batchNewAccount(address[] _users) public note onlyAdmin {
        for (uint i = 0; i < _users.length; i++) {
            newAccount(_users[i]);
        }
    }

    function getAllAccounts() public view returns (address[]) {
        return accounts;
    }

    function getAccountsForUser(address _user) public view returns (address[]) {
        return userToAccounts[_user];
    }

}
contract Escrow is DSNote, DSAuth {

    event LogTransfer(address indexed token, address indexed to, uint value);
    event LogTransferFromAccount(address indexed account, address indexed token, address indexed to, uint value);

    function transfer
    (
        address _token,
        address _to,
        uint _value
    )
        public
        note
        auth
    {
        require(ERC20(_token).transfer(_to, _value), "Escrow::transfer TOKEN_TRANSFER_FAILED");
        emit LogTransfer(_token, _to, _value);
    }

    function transferFromAccount
    (
        address _account,
        address _token,
        address _to,
        uint _value
    )
        public
        note
        auth
    {   
        Account(_account).transferBySystem(_token, _to, _value);
        emit LogTransferFromAccount(_account, _token, _to, _value);
    }

}

// issue with deploying multiple instances of same type in truffle, hence the following two contracts
contract KernelEscrow is Escrow {

}

contract ReserveEscrow is Escrow {
    
}
interface ExchangeConnector {

    function tradeWithInputFixed
    (   
        Escrow _escrow,
        address _srcToken,
        address _destToken,
        uint _srcTokenValue
    )
        external
        returns (uint _destTokenValue, uint _srcTokenValueLeft);

    function tradeWithOutputFixed
    (   
        Escrow _escrow,
        address _srcToken,
        address _destToken,
        uint _srcTokenValue,
        uint _maxDestTokenValue
    )
        external
        returns (uint _destTokenValue, uint _srcTokenValueLeft);
    

    function getExpectedRate(address _srcToken, address _destToken, uint _srcTokenValue) 
        external
        view
        returns(uint _expectedRate, uint _slippageRate);
    
    function isTradeFeasible(address _srcToken, address _destToken, uint _srcTokenValue) 
        external
        view
        returns(bool);

}


contract Reserve is DSStop, DSThing, Utils, Utils2, ErrorUtils {

    Escrow public escrow;
    AccountFactory public accountFactory;
    DateTime public dateTime;
    Config public config;
    uint public deployTimestamp;

    string constant public VERSION = "1.0.0";

    uint public TIME_INTERVAL = 1 days;
    //uint public TIME_INTERVAL = 1 hours;
    
    constructor
    (
        Escrow _escrow,
        AccountFactory _accountFactory,
        DateTime _dateTime,
        Config _config
    ) 
    public 
    {
        escrow = _escrow;
        accountFactory = _accountFactory;
        dateTime = _dateTime;
        config = _config;
        deployTimestamp = now - (4 * TIME_INTERVAL);
    }

    function setEscrow(Escrow _escrow) 
        public 
        note 
        auth
        addressValid(_escrow)
    {
        escrow = _escrow;
    }

    function setAccountFactory(AccountFactory _accountFactory) 
        public 
        note 
        auth
        addressValid(_accountFactory)
    {
        accountFactory = _accountFactory;
    }

    function setDateTime(DateTime _dateTime) 
        public 
        note 
        auth
        addressValid(_dateTime)
    {
        dateTime = _dateTime;
    }

    function setConfig(Config _config) 
        public 
        note 
        auth
        addressValid(_config)
    {
        config = _config;
    }

    struct Order {
        address account;
        address token;
        address byUser;
        uint value;
        uint duration;
        uint expirationTimestamp;
        uint salt;
        uint createdTimestamp;
        bytes32 orderHash;
    }

    bytes32[] public orders;
    mapping (bytes32 => Order) public hashToOrder;
    mapping (bytes32 => bool) public isOrder;
    mapping (address => bytes32[]) public accountToOrders;
    mapping (bytes32 => bool) public cancelledOrders;

    // per day
    mapping (uint => mapping(address => uint)) public deposits;
    mapping (uint => mapping(address => uint)) public withdrawals;
    mapping (uint => mapping(address => uint)) public profits;
    mapping (uint => mapping(address => uint)) public losses;

    mapping (uint => mapping(address => uint)) public reserves;
    mapping (address => uint) public lastReserveRuns;

    mapping (address => mapping(address => uint)) public surplus;

    mapping (bytes32 => CumulativeRun) public orderToCumulative;

    struct CumulativeRun {
        uint timestamp;
        uint value;
    }

    modifier onlyAdmin() {
        require(config.isAdminValid(msg.sender), "Reserve::_ INVALID_ADMIN_ACCOUNT");
        _;
    }

    event LogOrderCreated(
        bytes32 indexed orderHash,
        address indexed account,
        address indexed token,
        address byUser,
        uint value,
        uint expirationTimestamp
    );

    event LogOrderCancelled(
        bytes32 indexed orderHash,
        address indexed by
    );

    event LogReserveValuesUpdated(
        address indexed token, 
        uint indexed updatedTill,
        uint reserve,
        uint profit,
        uint loss
    );

    event LogOrderCumulativeUpdated(
        bytes32 indexed orderHash,
        uint updatedTill,
        uint value
    );

    event LogRelease(
        address indexed token,
        address indexed to,
        uint value,
        address by
    );

    event LogLock(
        address indexed token,
        address indexed from,
        uint value,
        uint profit,
        uint loss,
        address by
    );

    event LogLockSurplus(
        address indexed forToken, 
        address indexed token,
        address from,
        uint value
    );

    event LogTransferSurplus(
        address indexed forToken,
        address indexed token,
        address to, 
        uint value
    );
    
    function createOrder
    (
        address[3] _orderAddresses,
        uint[3] _orderValues,
        bytes _signature
    ) 
        public
        note
        onlyAdmin
        whenNotStopped
    {
        Order memory order = _composeOrder(_orderAddresses, _orderValues);
        address signer = _recoverSigner(order.orderHash, _signature);

        if(signer != order.byUser){
            emit LogErrorWithHintBytes32(order.orderHash, "Reserve::createOrder", "SIGNER_NOT_ORDER_CREATOR");
            return;
        }
        
        if(isOrder[order.orderHash]){
            emit LogErrorWithHintBytes32(order.orderHash, "Reserve::createOrder", "ORDER_ALREADY_EXISTS");
            return;
        }

        if(!accountFactory.isAccount(order.account)){
            emit LogErrorWithHintBytes32(order.orderHash, "Reserve::createOrder", "INVALID_ORDER_ACCOUNT");
            return;
        }

        if(!Account(order.account).isUser(signer)){
            emit LogErrorWithHintBytes32(order.orderHash, "Reserve::createOrder", "SIGNER_NOT_AUTHORIZED_WITH_ACCOUNT");
            return;
        }
                
        if(!_isOrderValid(order)) {
            emit LogErrorWithHintBytes32(order.orderHash, "Reserve::createOrder", "INVALID_ORDER_PARAMETERS");
            return;
        }

        if(ERC20(order.token).balanceOf(order.account) < order.value){
            emit LogErrorWithHintBytes32(order.orderHash, "Reserve::createOrder", "INSUFFICIENT_BALANCE_IN_ACCOUNT");
            return;
        }

        escrow.transferFromAccount(order.account, order.token, address(escrow), order.value);
        
        orders.push(order.orderHash);
        hashToOrder[order.orderHash] = order;
        isOrder[order.orderHash] = true;
        accountToOrders[order.account].push(order.orderHash);

        uint dateTimestamp = _getDateTimestamp(now);

        deposits[dateTimestamp][order.token] = add(deposits[dateTimestamp][order.token], order.value);
        
        orderToCumulative[order.orderHash].timestamp = _getDateTimestamp(order.createdTimestamp);
        orderToCumulative[order.orderHash].value = order.value;

        emit LogOrderCreated(
            order.orderHash,
            order.account,
            order.token,
            order.byUser,
            order.value,
            order.expirationTimestamp
        );
    }

    function cancelOrder
    (
        bytes32 _orderHash,
        bytes _signature
    )
        external
        note
        onlyAdmin
    {   
        if(!isOrder[_orderHash]) {
            emit LogErrorWithHintBytes32(_orderHash,"Reserve::createOrder", "ORDER_DOES_NOT_EXIST");
            return;
        }

        if(cancelledOrders[_orderHash]){
            emit LogErrorWithHintBytes32(_orderHash,"Reserve::createOrder", "ORDER_ALREADY_CANCELLED");
            return;
        }

        Order memory order = hashToOrder[_orderHash];

        bytes32 cancelOrderHash = _generateActionOrderHash(_orderHash, "CANCEL_RESERVE_ORDER");
        address signer = _recoverSigner(cancelOrderHash, _signature);
        
        if(!Account(order.account).isUser(signer)){
            emit LogErrorWithHintBytes32(_orderHash,"Reserve::createOrder", "SIGNER_NOT_AUTHORIZED_WITH_ACCOUNT");
            return;
        }
        
        doCancelOrder(order);
    }
    
    function processOrder
    (
        bytes32 _orderHash
    ) 
        external 
        note
        onlyAdmin
    {
        if(!isOrder[_orderHash]) {
            emit LogErrorWithHintBytes32(_orderHash,"Reserve::processOrder", "ORDER_DOES_NOT_EXIST");
            return;
        }

        if(cancelledOrders[_orderHash]){
            emit LogErrorWithHintBytes32(_orderHash,"Reserve::processOrder", "ORDER_ALREADY_CANCELLED");
            return;
        }

        Order memory order = hashToOrder[_orderHash];

        if(now > _getDateTimestamp(order.expirationTimestamp)) {
            doCancelOrder(order);
        } else {
            emit LogErrorWithHintBytes32(order.orderHash, "Reserve::processOrder", "ORDER_NOT_EXPIRED");
        }
    }

    function doCancelOrder(Order _order) 
        internal
    {   
        uint valueToTransfer = orderToCumulative[_order.orderHash].value;

        if(ERC20(_order.token).balanceOf(escrow) < valueToTransfer){
            emit LogErrorWithHintBytes32(_order.orderHash, "Reserve::doCancel", "INSUFFICIENT_BALANCE_IN_ESCROW");
            return;
        }

        uint nowDateTimestamp = _getDateTimestamp(now);
        cancelledOrders[_order.orderHash] = true;
        withdrawals[nowDateTimestamp][_order.token] = add(withdrawals[nowDateTimestamp][_order.token], valueToTransfer);

        escrow.transfer(_order.token, _order.account, valueToTransfer);
        emit LogOrderCancelled(_order.orderHash, msg.sender);
    }

    function release(address _token, address _to, uint _value) 
        external
        note
        auth
    {   
        require(ERC20(_token).balanceOf(escrow) >= _value, "Reserve::release INSUFFICIENT_BALANCE_IN_ESCROW");
        escrow.transfer(_token, _to, _value);
        emit LogRelease(_token, _to, _value, msg.sender);
    }

    // _value includes profit/loss as well
    function lock(address _token, address _from, uint _value, uint _profit, uint _loss)
        external
        note
        auth
    {   
        require(!(_profit == 0 && _loss == 0), "Reserve::lock INVALID_PROFIT_LOSS_VALUES");
        require(ERC20(_token).balanceOf(_from) >= _value, "Reserve::lock INSUFFICIENT_BALANCE");
            
        if(accountFactory.isAccount(_from)) {
            escrow.transferFromAccount(_from, _token, address(escrow), _value);
        } else {
            Escrow(_from).transfer(_token, address(escrow), _value);
        }
        
        uint dateTimestamp = _getDateTimestamp(now);

        if (_profit > 0){
            profits[dateTimestamp][_token] = add(profits[dateTimestamp][_token], _profit);
        } else if (_loss > 0) {
            losses[dateTimestamp][_token] = add(losses[dateTimestamp][_token], _loss);
        }

        emit LogLock(_token, _from, _value, _profit, _loss, msg.sender);
    }

    // to lock collateral if cannot be liquidated e.g. not enough reserves in kyber
    function lockSurplus(address _from, address _forToken, address _token, uint _value) 
        external
        note
        auth
    {
        require(ERC20(_token).balanceOf(_from) >= _value, "Reserve::lockSurplus INSUFFICIENT_BALANCE_IN_ESCROW");

        Escrow(_from).transfer(_token, address(escrow), _value);
        surplus[_forToken][_token] = add(surplus[_forToken][_token], _value);

        emit LogLockSurplus(_forToken, _token, _from, _value);
    }

    // to transfer surplus collateral out of the system to trade on other platforms and put back in terms of 
    // principal to reserve manually using an account or surplus escrow
    // should work in tandem with lock method when transferring back principal
    function transferSurplus(address _to, address _forToken, address _token, uint _value) 
        external
        note
        auth
    {
        require(ERC20(_token).balanceOf(escrow) >= _value, "Reserve::transferSurplus INSUFFICIENT_BALANCE_IN_ESCROW");
        require(surplus[_forToken][_token] >= _value, "Reserve::transferSurplus INSUFFICIENT_SURPLUS");

        surplus[_forToken][_token] = sub(surplus[_forToken][_token], _value);
        escrow.transfer(_token, _to, _value);

        emit LogTransferSurplus(_forToken, _token, _to, _value);
    }

    function updateReserveValues(address _token, uint _forDays)
        public
        note
        onlyAdmin
    {   
        uint lastReserveRun = lastReserveRuns[_token];

        if (lastReserveRun == 0) {
            lastReserveRun = _getDateTimestamp(deployTimestamp) - TIME_INTERVAL;
        }

        uint nowDateTimestamp = _getDateTimestamp(now);
        uint updatesLeft = ((nowDateTimestamp - TIME_INTERVAL) - lastReserveRun) / TIME_INTERVAL;

        if(updatesLeft == 0) {
            emit LogErrorWithHintAddress(_token, "Reserve::updateReserveValues", "RESERVE_VALUES_UP_TO_DATE");
            return;
        }

        uint counter = updatesLeft;

        if(updatesLeft > _forDays && _forDays > 0) {
            counter = _forDays;
        }

        for (uint i = 0; i < counter; i++) {
            reserves[lastReserveRun + TIME_INTERVAL][_token] = sub(
                sub(
                    add(
                        add(
                            reserves[lastReserveRun][_token],
                            deposits[lastReserveRun + TIME_INTERVAL][_token]
                        ),
                        profits[lastReserveRun + TIME_INTERVAL][_token]
                    ),
                    losses[lastReserveRun + TIME_INTERVAL][_token]
                ),
                withdrawals[lastReserveRun + TIME_INTERVAL][_token]
            );
            lastReserveRuns[_token] = lastReserveRun + TIME_INTERVAL;
            lastReserveRun = lastReserveRuns[_token];
            
            emit LogReserveValuesUpdated(
                _token,
                lastReserveRun,
                reserves[lastReserveRun][_token],
                profits[lastReserveRun][_token],
                losses[lastReserveRun][_token]
            );
            
        }
    }

    function updateOrderCumulativeValueBatch(bytes32[] _orderHashes, uint[] _forDays) 
        public
        note
        onlyAdmin
    {   
        if(_orderHashes.length != _forDays.length) {
            emit LogError("Reserve::updateOrderCumulativeValueBatch", "ARGS_ARRAYLENGTH_MISMATCH");
            return;
        }

        for(uint i = 0; i < _orderHashes.length; i++) {
            updateOrderCumulativeValue(_orderHashes[i], _forDays[i]);
        }
    }

    function updateOrderCumulativeValue
    (
        bytes32 _orderHash, 
        uint _forDays
    ) 
        public
        note
        onlyAdmin 
    {
        if(!isOrder[_orderHash]) {
            emit LogErrorWithHintBytes32(_orderHash, "Reserve::updateOrderCumulativeValue", "ORDER_DOES_NOT_EXIST");
            return;
        }

        if(cancelledOrders[_orderHash]) {
            emit LogErrorWithHintBytes32(_orderHash, "Reserve::updateOrderCumulativeValue", "ORDER_ALREADY_CANCELLED");
            return;
        }
        
        Order memory order = hashToOrder[_orderHash];
        CumulativeRun storage cumulativeRun = orderToCumulative[_orderHash];
        
        uint profitsAccrued = 0;
        uint lossesAccrued = 0;
        uint cumulativeValue = 0;
        uint counter = 0;

        uint lastOrderRun = cumulativeRun.timestamp;
        uint nowDateTimestamp = _getDateTimestamp(now);

        uint updatesLeft = ((nowDateTimestamp - TIME_INTERVAL) - lastOrderRun) / TIME_INTERVAL;

        if(updatesLeft == 0) {
            emit LogErrorWithHintBytes32(_orderHash, "Reserve::updateOrderCumulativeValue", "ORDER_VALUES_UP_TO_DATE");
            return;
        }

        counter = updatesLeft;

        if(updatesLeft > _forDays && _forDays > 0) {
            counter = _forDays;
        }

        for (uint i = 0; i < counter; i++){
            cumulativeValue = cumulativeRun.value;
            lastOrderRun = cumulativeRun.timestamp;

            if(lastReserveRuns[order.token] < lastOrderRun) {
                emit LogErrorWithHintBytes32(_orderHash, "Reserve::updateOrderCumulativeValue", "RESERVE_VALUES_NOT_UPDATED");
                emit LogOrderCumulativeUpdated(_orderHash, cumulativeRun.timestamp, cumulativeRun.value);
                return;
            }

            profitsAccrued = div(
                mul(profits[lastOrderRun + TIME_INTERVAL][order.token], cumulativeValue),
                reserves[lastOrderRun][order.token]
            );
                
            lossesAccrued = div(
                mul(losses[lastOrderRun + TIME_INTERVAL][order.token], cumulativeValue),
                reserves[lastOrderRun][order.token]
            );

            cumulativeValue = sub(add(cumulativeValue, profitsAccrued), lossesAccrued);

            cumulativeRun.timestamp = lastOrderRun + TIME_INTERVAL;
            cumulativeRun.value = cumulativeValue;
        }
        
        emit LogOrderCumulativeUpdated(_orderHash, cumulativeRun.timestamp, cumulativeRun.value);
    }

    function getAllOrders() 
        public
        view 
        returns 
        (
            bytes32[]
        ) 
    {
        return orders;
    }

    function getOrdersForAccount(address _account) 
        public
        view 
        returns 
        (
            bytes32[]
        )
    {
        return accountToOrders[_account];
    }

    function getOrder(bytes32 _orderHash)
        public 
        view 
        returns 
        (
            address _account,
            address _token,
            address _byUser,
            uint _value,
            uint _expirationTimestamp,
            uint _salt,
            uint _createdTimestamp
        )
    {   
        Order memory order = hashToOrder[_orderHash];
        return (
            order.account,
            order.token,
            order.byUser,
            order.value,
            order.expirationTimestamp,
            order.salt,
            order.createdTimestamp
        );
    }

    function _isOrderValid(Order _order)
        internal
        view
        returns (bool)
    {
        if(_order.account == address(0) || _order.byUser == address(0)
         || _order.value <= 0
         || _order.expirationTimestamp <= _order.createdTimestamp || _order.salt <= 0) {
            return false;
        }

        if(isOrder[_order.orderHash]) {
            return false;
        }

        if(cancelledOrders[_order.orderHash]) {
            return false;
        }

        return true;
    }

    function _composeOrder(address[3] _orderAddresses, uint[3] _orderValues)
        internal
        view
        returns (Order _order)
    {
        Order memory order = Order({
            account: _orderAddresses[0],
            token: _orderAddresses[1],
            byUser: _orderAddresses[2],
            value: _orderValues[0],
            createdTimestamp: now,
            duration: _orderValues[1],
            expirationTimestamp: add(now, _orderValues[1]),
            salt: _orderValues[2],
            orderHash: bytes32(0)
        });

        order.orderHash = _generateCreateOrderHash(order);

        return order;
    }

    function _generateCreateOrderHash(Order _order)
        internal
        pure //view
        returns (bytes32 _orderHash)
    {
        return keccak256(
            abi.encodePacked(
 //              address(this),
                _order.account,
                _order.token,
                _order.value,
                _order.duration,
                _order.salt
            )
        );
    }

    function _generateActionOrderHash
    (
        bytes32 _orderHash,
        string _action
    )
        internal
        pure //view
        returns (bytes32 _repayOrderHash)
    {
        return keccak256(
            abi.encodePacked(
//                address(this),
                _orderHash,
                _action
            )
        );
    }

    function _getDateTimestamp(uint _timestamp) 
        internal
        view
        returns (uint)
    {
        // 1 day
        return dateTime.toTimestamp(dateTime.getYear(_timestamp), dateTime.getMonth(_timestamp), dateTime.getDay(_timestamp));
        // 1 hour
        //return dateTime.toTimestamp(dateTime.getYear(_timestamp), dateTime.getMonth(_timestamp), dateTime.getDay(_timestamp), dateTime.getHour(_timestamp));
    } 

}
contract KyberConnector is ExchangeConnector, DSThing, Utils {
    KyberNetworkProxy public kyber;
    address public feeWallet;

    uint constant internal KYBER_MAX_QTY = (10**28);

    constructor(KyberNetworkProxy _kyber, address _feeWallet) public {
        kyber = _kyber;
        feeWallet = _feeWallet;
    }

    function setKyber(KyberNetworkProxy _kyber) 
        public
        auth
        addressValid(_kyber)
    {
        kyber = _kyber;
    }

    function setFeeWallet(address _feeWallet) 
        public 
        note 
        auth
        addressValid(_feeWallet)
    {
        feeWallet = _feeWallet;
    }
    

    event LogTrade
    (
        address indexed _from,
        address indexed _srcToken,
        address indexed _destToken,
        uint _srcTokenValue,
        uint _maxDestTokenValue,
        uint _destTokenValue,
        uint _srcTokenValueLeft,
        uint _exchangeRate
    );

    function tradeWithInputFixed
    (   
        Escrow _escrow,
        address _srcToken,
        address _destToken,
        uint _srcTokenValue
    )
        public    
        note
        auth
        returns (uint _destTokenValue, uint _srcTokenValueLeft)
    {
        return tradeWithOutputFixed(_escrow, _srcToken, _destToken, _srcTokenValue, KYBER_MAX_QTY);
    }

    function tradeWithOutputFixed
    (   
        Escrow _escrow,
        address _srcToken,
        address _destToken,
        uint _srcTokenValue,
        uint _maxDestTokenValue
    )
        public
        note
        auth
        returns (uint _destTokenValue, uint _srcTokenValueLeft)
    {   
        require(_srcToken != _destToken, "KyberConnector::tradeWithOutputFixed TOKEN_ADDRS_SHOULD_NOT_MATCH");

        uint _slippageRate;
        (, _slippageRate) = getExpectedRate(_srcToken, _destToken, _srcTokenValue);

        uint initialSrcTokenBalance = ERC20(_srcToken).balanceOf(this);

        require(ERC20(_srcToken).balanceOf(_escrow) >= _srcTokenValue, "KyberConnector::tradeWithOutputFixed INSUFFICIENT_BALANCE_IN_ESCROW");
        _escrow.transfer(_srcToken, this, _srcTokenValue);

        require(ERC20(_srcToken).approve(kyber, 0), "KyberConnector::tradeWithOutputFixed SRC_APPROVAL_FAILED");
        require(ERC20(_srcToken).approve(kyber, _srcTokenValue), "KyberConnector::tradeWithOutputFixed SRC_APPROVAL_FAILED");
        
        _destTokenValue = kyber.tradeWithHint(
            ERC20(_srcToken),
            _srcTokenValue,
            ERC20(_destToken),
            this,
            _maxDestTokenValue,
            _slippageRate, // no min coversation rate
            feeWallet, 
            new bytes(0)
        );

        _srcTokenValueLeft = sub(ERC20(_srcToken).balanceOf(this), initialSrcTokenBalance);

        require(_transfer(_destToken, _escrow, _destTokenValue), "KyberConnector::tradeWithOutputFixed DEST_TOKEN_TRANSFER_FAILED");
        
        if(_srcTokenValueLeft > 0) {
            require(_transfer(_srcToken, _escrow, _srcTokenValueLeft), "KyberConnector::tradeWithOutputFixed SRC_TOKEN_TRANSFER_FAILED");
        }

        emit LogTrade(_escrow, _srcToken, _destToken, _srcTokenValue, _maxDestTokenValue, _destTokenValue, _srcTokenValueLeft, _slippageRate);
    } 

    function getExpectedRate(address _srcToken, address _destToken, uint _srcTokenValue) 
        public
        view
        returns(uint _expectedRate, uint _slippageRate)
    {
        (_expectedRate, _slippageRate) = kyber.getExpectedRate(ERC20(_srcToken), ERC20(_destToken), _srcTokenValue);
    }

    function isTradeFeasible(address _srcToken, address _destToken, uint _srcTokenValue) 
        public
        view
        returns(bool)
    {
        uint slippageRate; 

        (, slippageRate) = getExpectedRate(
            _srcToken,
            _destToken,
            _srcTokenValue
        );

        return slippageRate != 0;
    }

    function _transfer
    (
        address _token,
        address _to,
        uint _value
    )
        internal
        returns (bool)
    {
        return ERC20(_token).transfer(_to, _value);
    }
}
contract Kernel is DSStop, DSThing, Utils, Utils2, ErrorUtils {

    Escrow public escrow;
    AccountFactory public accountFactory;
    Reserve public reserve;
    address public feeWallet;
    Config public config;
    KyberConnector public kyberConnector;
    
    string constant public VERSION = "1.0.0";

    constructor
    (
        Escrow _escrow,
        AccountFactory _accountFactory,
        Reserve _reserve,
        address _feeWallet,
        Config _config,
        KyberConnector _kyberConnector
    ) 
    public 
    {
        escrow = _escrow;
        accountFactory = _accountFactory;
        reserve = _reserve;
        feeWallet = _feeWallet;
        config = _config;
        kyberConnector = _kyberConnector;
    }

    function setEscrow(Escrow _escrow) 
        public 
        note 
        auth
        addressValid(_escrow)
    {
        escrow = _escrow;
    }

    function setAccountFactory(AccountFactory _accountFactory)
        public 
        note 
        auth
        addressValid(_accountFactory)
    {
        accountFactory = _accountFactory;
    }

    function setReserve(Reserve _reserve)
        public 
        note 
        auth
        addressValid(_reserve)
    {
        reserve = _reserve;
    }

    function setConfig(Config _config)
        public 
        note 
        auth
        addressValid(_config)
    {
        config = _config;
    }

    function setKyberConnector(KyberConnector _kyberConnector)
        public 
        note 
        auth
        addressValid(_kyberConnector)
    {
        kyberConnector = _kyberConnector;
    }

    function setFeeWallet(address _feeWallet) 
        public 
        note 
        auth
        addressValid(_feeWallet)
    {
        feeWallet = _feeWallet;
    }

    event LogOrderCreated(
        bytes32 indexed orderHash,
        address indexed account,
        address indexed principalToken,
        address collateralToken,
        address byUser,
        uint principalAmount,
        uint collateralAmount,
        uint premium, // should be in wad?
        uint expirationTimestamp,
        uint fee
    );

    event LogOrderRepaid(
        bytes32 indexed orderHash,
        uint  valueRepaid
    );

    event LogOrderDefaulted(
        bytes32 indexed orderHash,
        string reason
    );

    struct Order {
        address account;
        address byUser;
        address principalToken; 
        address collateralToken;
        uint principalAmount;
        uint collateralAmount;
        uint premium;
        uint duration;
        uint expirationTimestamp;
        uint salt;
        uint fee;
        uint createdTimestamp;
        bytes32 orderHash;
    }

    bytes32[] public orders;
    mapping (bytes32 => Order) public hashToOrder;
    mapping (bytes32 => bool) public isOrder;
    mapping (address => bytes32[]) public accountToOrders;
    
    mapping (bytes32 => bool) public isRepaid;
    mapping (bytes32 => bool) public isDefaulted;

    modifier onlyAdmin() {
        require(config.isAdminValid(msg.sender), "Kernel::_ INVALID_ADMIN_ACCOUNT");
        _;
    }

    // add price to check collateralisation ratio?
    function createOrder
    (
        address[4] _orderAddresses,
        uint[6] _orderValues,
        bytes _signature
    )    
        external
        note
        onlyAdmin
        whenNotStopped
    {   
        Order memory order = _composeOrder(_orderAddresses, _orderValues);
        address signer = _recoverSigner(order.orderHash, _signature);

        if(signer != order.byUser) {
            emit LogErrorWithHintBytes32(order.orderHash, "Kernel::createOrder","SIGNER_NOT_ORDER_CREATOR");
            return;
        }

        if(isOrder[order.orderHash]){
            emit LogErrorWithHintBytes32(order.orderHash, "Kernel::createOrder","ORDER_ALREADY_EXISTS");
            return;
        }

        if(!accountFactory.isAccount(order.account)){
            emit LogErrorWithHintBytes32(order.orderHash, "Kernel::createOrder","INVALID_ORDER_ACCOUNT");
            return;
        }

        if(!Account(order.account).isUser(signer)) {
            emit LogErrorWithHintBytes32(order.orderHash, "Kernel::createOrder","SIGNER_NOT_AUTHORIZED_WITH_ACCOUNT");
            return;
        }

        if(!_isOrderValid(order)){
            emit LogErrorWithHintBytes32(order.orderHash, "Kernel::createOrder","INVALID_ORDER_PARAMETERS");
            return;
        }

        if(ERC20(order.collateralToken).balanceOf(order.account) < order.collateralAmount){
            emit LogErrorWithHintBytes32(order.orderHash, "Kernel::createOrder","INSUFFICIENT_COLLATERAL_IN_ACCOUNT");
            return;
        }

        if(ERC20(order.principalToken).balanceOf(reserve.escrow()) < order.principalAmount){
            emit LogErrorWithHintBytes32(order.orderHash, "Kernel::createOrder","INSUFFICIENT_FUNDS_IN_RESERVE");
            return;
        }
        
        orders.push(order.orderHash);
        hashToOrder[order.orderHash] = order;
        isOrder[order.orderHash] = true;
        accountToOrders[order.account].push(order.orderHash);

        escrow.transferFromAccount(order.account, order.collateralToken, address(escrow), order.collateralAmount);
        reserve.release(order.principalToken, order.account, order.principalAmount);
    
        emit LogOrderCreated(
            order.orderHash,
            order.account,
            order.principalToken,
            order.collateralToken,
            order.byUser,
            order.principalAmount,
            order.collateralAmount,
            order.premium,
            order.expirationTimestamp,
            order.fee
        );
    }

    function getExpectedRepayValue(bytes32 _orderHash) 
        public
        view
        returns (uint)
    {
        Order memory order = hashToOrder[_orderHash];
        uint profits = sub(div(mul(order.principalAmount, order.premium), WAD), order.fee);
        uint valueToRepay = add(order.principalAmount, profits);

        return valueToRepay;
    }

    function repay
    (
        bytes32 _orderHash,
        uint _value,
        bytes _signature
    ) 
        external
        note
        onlyAdmin
    {   
        if(!isOrder[_orderHash]){
            emit LogErrorWithHintBytes32(_orderHash, "Kernel::repay","ORDER_DOES_NOT_EXIST");
            return;
        }

        if(isRepaid[_orderHash]){
            emit LogErrorWithHintBytes32(_orderHash, "Kernel::repay","ORDER_ALREADY_REPAID");
            return;
        }

        if(isDefaulted[_orderHash]){
            emit LogErrorWithHintBytes32(_orderHash, "Kernel::repay","ORDER_ALREADY_DEFAULTED");
            return;
        }
        
        bytes32 repayOrderHash = _generateRepayOrderHash(_orderHash, _value);
        address signer = _recoverSigner(repayOrderHash, _signature);

        Order memory order = hashToOrder[_orderHash];
        
        if(!Account(order.account).isUser(signer)){
            emit LogErrorWithHintBytes32(_orderHash, "Kernel::repay","SIGNER_NOT_AUTHORIZED_WITH_ACCOUNT");
            return;
        }

        if(ERC20(order.principalToken).balanceOf(order.account) < _value){
            emit LogErrorWithHintBytes32(_orderHash, "Kernel::repay","INSUFFICIENT_BALANCE_IN_ACCOUNT");
            return;
        }

        uint profits = sub(div(mul(order.principalAmount, order.premium), WAD), order.fee);
        uint valueToRepay = add(order.principalAmount, profits);

        if(valueToRepay > _value){
            emit LogErrorWithHintBytes32(_orderHash, "Kernel::repay","INSUFFICIENT_REPAYMENT");
            return;
        }

        if(order.fee > 0) {
            escrow.transferFromAccount(order.account, order.principalToken, feeWallet, order.fee);
        }

        reserve.lock(order.principalToken, order.account, valueToRepay, profits, 0);
        escrow.transfer(order.collateralToken, order.account, order.collateralAmount);

        isRepaid[order.orderHash] = true;

        emit LogOrderRepaid(
            order.orderHash,
            _value
        );
    }

    function process
    (
        bytes32 _orderHash,
        uint _principalPerCollateral // in WAD
    )
        external
        note
        onlyAdmin
    {   
        if(!isOrder[_orderHash]){
            emit LogErrorWithHintBytes32(_orderHash, "Kernel::process","ORDER_DOES_NOT_EXIST");
            return;
        }

        if(isRepaid[_orderHash]){
            emit LogErrorWithHintBytes32(_orderHash, "Kernel::process","ORDER_ALREADY_REPAID");
            return;
        }

        if(isDefaulted[_orderHash]){
            emit LogErrorWithHintBytes32(_orderHash, "Kernel::process","ORDER_ALREADY_DEFAULTED");
            return;
        }

        Order memory order = hashToOrder[_orderHash];

        bool isDefault = false;
        string memory reason = "";

        if(now > order.expirationTimestamp) {
            isDefault = true;
            reason = "DUE_DATE_PASSED";
        } else if (!_isCollateralizationSafe(order, _principalPerCollateral)) {
            isDefault = true;
            reason = "COLLATERAL_UNSAFE";
        }

        isDefaulted[_orderHash] = isDefault;

        if(isDefault) {
            _performLiquidation(order);
            emit LogOrderDefaulted(order.orderHash, reason);
        }

    }

    function _performLiquidation(Order _order) 
        internal
    {
        uint premiumValue = div(mul(_order.principalAmount, _order.premium), WAD);
        uint valueToRepay = add(_order.principalAmount, premiumValue);

        uint principalFromCollateral;
        uint collateralLeft;
        
        (principalFromCollateral, collateralLeft) = kyberConnector.tradeWithOutputFixed(
            escrow,
            ERC20(_order.collateralToken), 
            ERC20(_order.principalToken),
            _order.collateralAmount,
            valueToRepay
        );

        if (principalFromCollateral >= valueToRepay) {
            if(_order.fee > 0) {
                escrow.transfer(_order.principalToken, feeWallet, _order.fee);
            }

            reserve.lock(
                _order.principalToken,
                escrow,
                sub(principalFromCollateral, _order.fee),
                sub(sub(principalFromCollateral,_order.principalAmount), _order.fee),
                0
            );

            escrow.transfer(_order.collateralToken, _order.account, collateralLeft);

        } else if((principalFromCollateral < valueToRepay) && (principalFromCollateral >= _order.principalAmount)) {

            reserve.lock(
                _order.principalToken,
                escrow,
                principalFromCollateral,
                sub(principalFromCollateral, _order.principalAmount),
                0
            );

        } else {

            reserve.lock(
                _order.principalToken,
                escrow,
                principalFromCollateral,
                0,
                sub(_order.principalAmount, principalFromCollateral)
            );

        }
    }

    function _isCollateralizationSafe(Order _order, uint _principalPerCollateral)
        internal 
        pure
        returns (bool)
    {
        uint totalCollateralValueInPrincipal = div(
            mul(_order.collateralAmount, _principalPerCollateral),
            WAD);
        
        uint premiumValue = div(mul(_order.principalAmount, _order.premium), WAD);
        uint premiumValueBuffer = div(mul(premiumValue, 3), 100); // hardcoded -> can be passed through order?
        uint valueToRepay = add(add(_order.principalAmount, premiumValue), premiumValueBuffer);

        if (totalCollateralValueInPrincipal < valueToRepay) {
            return false;
        }

        return true;
    }

    function _generateRepayOrderHash
    (
        bytes32 _orderHash,
        uint _value
    )
        internal
        view
        returns (bytes32 _repayOrderHash)
    {
        return keccak256(
            abi.encodePacked(
                address(this),
                _orderHash,
                _value
            )
        );
    }

    function _isOrderValid(Order _order)
        internal
        pure
        returns (bool)
    {
        if(_order.account == address(0) || _order.byUser == address(0) 
         || _order.principalToken == address(0) || _order.collateralToken == address(0) 
         || (_order.collateralToken == _order.principalToken)
         || _order.principalAmount <= 0 || _order.collateralAmount <= 0
         || _order.premium <= 0
         || _order.expirationTimestamp <= _order.createdTimestamp || _order.salt <= 0) {
            return false;
        }

        return true;
    }

    function _composeOrder
    (
        address[4] _orderAddresses,
        uint[6] _orderValues
    )
        internal
        view
        returns (Order _order)
    {
        Order memory order = Order({
            account: _orderAddresses[0], 
            byUser: _orderAddresses[1],
            principalToken: _orderAddresses[2],
            collateralToken: _orderAddresses[3],
            principalAmount: _orderValues[0],
            collateralAmount: _orderValues[1],
            premium: _orderValues[2],
            duration: _orderValues[3],
            expirationTimestamp: add(now, _orderValues[3]),
            salt: _orderValues[4],
            fee: _orderValues[5],
            createdTimestamp: now,
            orderHash: bytes32(0)
        });

        order.orderHash = _generateOrderHash(order);
    
        return order;
    }

    function _generateOrderHash(Order _order)
        internal
        view
        returns (bytes32 _orderHash)
    {
        return keccak256(
            abi.encodePacked(
                address(this),
                _order.account,
                _order.principalToken,
                _order.collateralToken,
                _order.principalAmount,
                _order.collateralAmount,
                _order.premium,
                _order.duration,
                _order.salt,
                _order.fee
            )
        );
    }

    function getAllOrders()
        public 
        view
        returns 
        (
            bytes32[]
        )
    {
        return orders;
    }

    function getOrder(bytes32 _orderHash)
        public 
        view 
        returns 
        (
            address _account,
            address _byUser,
            address _principalToken,
            address _collateralToken,
            uint _principalAmount,
            uint _collateralAmount,
            uint _premium,
            uint _expirationTimestamp,
            uint _salt,
            uint _fee,
            uint _createdTimestamp
        )
    {   
        Order memory order = hashToOrder[_orderHash];
        return (
            order.account,
            order.byUser,
            order.principalToken,
            order.collateralToken,
            order.principalAmount,
            order.collateralAmount,
            order.premium,
            order.expirationTimestamp,
            order.salt,
            order.fee,
            order.createdTimestamp
        );
    }

    function getOrdersForAccount(address _account) 
        public
        view 
        returns
        (
            bytes32[]
        )
    {
        return accountToOrders[_account];
    }

}

Contract Security Audit

Contract ABI

[{"constant":false,"inputs":[],"name":"stop","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_orderHash","type":"bytes32"},{"name":"_value","type":"uint256"},{"name":"_signature","type":"bytes"}],"name":"repay","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"owner_","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_orderHash","type":"bytes32"}],"name":"getExpectedRepayValue","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_config","type":"address"}],"name":"setConfig","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"kyberConnector","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"isDefaulted","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_account","type":"address"}],"name":"getOrdersForAccount","outputs":[{"name":"","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_orderHash","type":"bytes32"}],"name":"getOrder","outputs":[{"name":"_account","type":"address"},{"name":"_byUser","type":"address"},{"name":"_principalToken","type":"address"},{"name":"_collateralToken","type":"address"},{"name":"_principalAmount","type":"uint256"},{"name":"_collateralAmount","type":"uint256"},{"name":"_premium","type":"uint256"},{"name":"_expirationTimestamp","type":"uint256"},{"name":"_salt","type":"uint256"},{"name":"_fee","type":"uint256"},{"name":"_createdTimestamp","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"accountFactory","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_kyberConnector","type":"address"}],"name":"setKyberConnector","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"accountToOrders","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"stopped","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"config","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"authority_","type":"address"}],"name":"setAuthority","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getAllOrders","outputs":[{"name":"","type":"bytes32[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"isRepaid","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"isOrder","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_feeWallet","type":"address"}],"name":"setFeeWallet","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_reserve","type":"address"}],"name":"setReserve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"orders","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_orderHash","type":"bytes32"},{"name":"_principalPerCollateral","type":"uint256"}],"name":"process","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_accountFactory","type":"address"}],"name":"setAccountFactory","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"start","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"authority","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_orderAddresses","type":"address[4]"},{"name":"_orderValues","type":"uint256[6]"},{"name":"_signature","type":"bytes"}],"name":"createOrder","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_escrow","type":"address"}],"name":"setEscrow","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"hashToOrder","outputs":[{"name":"account","type":"address"},{"name":"byUser","type":"address"},{"name":"principalToken","type":"address"},{"name":"collateralToken","type":"address"},{"name":"principalAmount","type":"uint256"},{"name":"collateralAmount","type":"uint256"},{"name":"premium","type":"uint256"},{"name":"duration","type":"uint256"},{"name":"expirationTimestamp","type":"uint256"},{"name":"salt","type":"uint256"},{"name":"fee","type":"uint256"},{"name":"createdTimestamp","type":"uint256"},{"name":"orderHash","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"reserve","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"escrow","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"feeWallet","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"VERSION","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_escrow","type":"address"},{"name":"_accountFactory","type":"address"},{"name":"_reserve","type":"address"},{"name":"_feeWallet","type":"address"},{"name":"_config","type":"address"},{"name":"_kyberConnector","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"orderHash","type":"bytes32"},{"indexed":true,"name":"account","type":"address"},{"indexed":true,"name":"principalToken","type":"address"},{"indexed":false,"name":"collateralToken","type":"address"},{"indexed":false,"name":"byUser","type":"address"},{"indexed":false,"name":"principalAmount","type":"uint256"},{"indexed":false,"name":"collateralAmount","type":"uint256"},{"indexed":false,"name":"premium","type":"uint256"},{"indexed":false,"name":"expirationTimestamp","type":"uint256"},{"indexed":false,"name":"fee","type":"uint256"}],"name":"LogOrderCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"orderHash","type":"bytes32"},{"indexed":false,"name":"valueRepaid","type":"uint256"}],"name":"LogOrderRepaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"orderHash","type":"bytes32"},{"indexed":false,"name":"reason","type":"string"}],"name":"LogOrderDefaulted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"methodSig","type":"string"},{"indexed":false,"name":"errMsg","type":"string"}],"name":"LogError","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"bytes32Value","type":"bytes32"},{"indexed":false,"name":"methodSig","type":"string"},{"indexed":false,"name":"errMsg","type":"string"}],"name":"LogErrorWithHintBytes32","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"addressValue","type":"address"},{"indexed":false,"name":"methodSig","type":"string"},{"indexed":false,"name":"errMsg","type":"string"}],"name":"LogErrorWithHintAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"authority","type":"address"}],"name":"LogSetAuthority","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"}],"name":"LogSetOwner","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event"}]

60806040526001805460a060020a60ff021916905534801561002057600080fd5b5060405160c080613f6183398101604081815282516020840151918401516060850151608086015160a09096015160018054600160a060020a03191633908117909155939694959294919391929091907fce241d7ca1f669fee44b6fc00b8eba2df3bb514eed0f6f668f8f89096e81ed9490600090a260028054600160a060020a0319908116600160a060020a0398891617909155600380548216968816969096179095556004805486169487169490941790935560058054851692861692909217909155600680548416918516919091179055600780549092169216919091179055613e4f806101126000396000f3006080604052600436106101875763ffffffff60e060020a60003504166307da68f5811461018c5780630b7e2e97146101a357806313af4035146101cb57806320cd1649146101ec57806320e3dbd4146102165780632b612988146102375780632fcdb8dd14610268578063359abaed146102945780635778472a14610305578063687cd9c1146103855780636d8a7b9d1461039a5780636dec3260146103bb57806375f12b21146103df57806379502c55146103f45780637a9e5e4b146104095780637bea0d1c1461042a578063817671551461043f5780638723555e146104575780638da5cb5b1461046f57806390d49b9d146104845780639cecc80a146104a5578063a85c38ef146104c6578063acfd6ce6146104de578063addc1a76146104f9578063be9a65551461051a578063bf7e214f1461052f578063c086504214610544578063c10c354614610569578063c559f6861461058a578063cd3293de14610619578063e2fdcc171461062e578063f25f4b5614610643578063ffa1ad7414610658575b600080fd5b34801561019857600080fd5b506101a16106e2565b005b3480156101af57600080fd5b506101a1600480359060248035916044359182019101356107c6565b3480156101d757600080fd5b506101a1600160a060020a03600435166110fd565b3480156101f857600080fd5b506102046004356111a7565b60408051918252519081900360200190f35b34801561022257600080fd5b506101a1600160a060020a03600435166112a0565b34801561024357600080fd5b5061024c6113c0565b60408051600160a060020a039092168252519081900360200190f35b34801561027457600080fd5b506102806004356113cf565b604080519115158252519081900360200190f35b3480156102a057600080fd5b506102b5600160a060020a03600435166113e4565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156102f15781810151838201526020016102d9565b505050509050019250505060405180910390f35b34801561031157600080fd5b5061031d600435611452565b60408051600160a060020a039c8d1681529a8c1660208c0152988b168a8a0152969099166060890152608088019490945260a087019290925260c086015260e08501526101008401526101208301939093526101408201929092529051908190036101600190f35b34801561039157600080fd5b5061024c611614565b3480156103a657600080fd5b506101a1600160a060020a0360043516611623565b3480156103c757600080fd5b50610204600160a060020a0360043516602435611743565b3480156103eb57600080fd5b50610280611773565b34801561040057600080fd5b5061024c611794565b34801561041557600080fd5b506101a1600160a060020a03600435166117a3565b34801561043657600080fd5b506102b5611849565b34801561044b57600080fd5b506102806004356118a2565b34801561046357600080fd5b506102806004356118b7565b34801561047b57600080fd5b5061024c6118cc565b34801561049057600080fd5b506101a1600160a060020a03600435166118db565b3480156104b157600080fd5b506101a1600160a060020a03600435166119fb565b3480156104d257600080fd5b50610204600435611b1b565b3480156104ea57600080fd5b506101a1600435602435611b3a565b34801561050557600080fd5b506101a1600160a060020a036004351661208c565b34801561052657600080fd5b506101a16121ac565b34801561053b57600080fd5b5061024c612279565b34801561055057600080fd5b506101a160046084610144356024810190830135612288565b34801561057557600080fd5b506101a1600160a060020a0360043516612ff5565b34801561059657600080fd5b506105a2600435613115565b60408051600160a060020a039e8f1681529c8e1660208e01529a8d168c8c015298909b1660608b015260808a019690965260a089019490945260c088019290925260e08701526101008601526101208501526101408401526101608301939093526101808201929092529051908190036101a00190f35b34801561062557600080fd5b5061024c61318d565b34801561063a57600080fd5b5061024c61319c565b34801561064f57600080fd5b5061024c6131ab565b34801561066457600080fd5b5061066d6131ba565b6040805160208082528351818301528351919283929083019185019080838360005b838110156106a757818101518382015260200161068f565b50505050905090810190601f1680156106d45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6106f833600035600160e060020a0319166131f1565b151561073c576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b60408051348082526020820183815236938301849052600435936024359384938693339360008035600160e060020a031916949092606082018484808284376040519201829003965090945050505050a450506001805474ff0000000000000000000000000000000000000000191674010000000000000000000000000000000000000000179055565b6000806107d1613cf3565b6040805134808252602082018381523693830184905260009384936004359360243593849386933393600160e060020a03198a35169390928a929091606082018484808284376040519201829003965090945050505050a4600654604080517f9c14ee290000000000000000000000000000000000000000000000000000000081523360048201529051600160a060020a0390921691639c14ee29916024808201926020929091908290030181600087803b15801561088f57600080fd5b505af11580156108a3573d6000803e3d6000fd5b505050506040513d60208110156108b957600080fd5b50511515610911576040805160e560020a62461bcd02815260206004820152601f60248201527f4b65726e656c3a3a5f20494e56414c49445f41444d494e5f4143434f554e5400604482015290519081900360640190fd5b60008b8152600a602052604090205460ff1615156109a15760408051818152600d81830152600080516020613d8483398151915260608201526080602082018190526014908201527f4f524445525f444f45535f4e4f545f455849535400000000000000000000000060a082015290518c91600080516020613dc4833981519152919081900360c00190a26110f0565b60008b8152600c602052604090205460ff1615610a305760408051818152600d81830152600080516020613d8483398151915260608201526080602082018190526014908201527f4f524445525f414c52454144595f52455041494400000000000000000000000060a082015290518c91600080516020613dc4833981519152919081900360c00190a26110f0565b60008b8152600d602052604090205460ff1615610abf5760408051818152600d81830152600080516020613d8483398151915260608201526080602082018190526017908201527f4f524445525f414c52454144595f44454641554c54454400000000000000000060a082015290518c91600080516020613dc4833981519152919081900360c00190a26110f0565b610ac98b8b6132fa565b9650610b05878a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375061339b945050505050565b60008c815260096020818152604080842081516101a0810183528154600160a060020a03908116808352600184015482168387015260028401548216838601526003840154821660608401526004808501546080850152600585015460a0850152600685015460c0850152600785015460e0850152600885015461010085015296840154610120840152600a840154610140840152600b840154610160840152600c9093015461018083015283517f4209fff1000000000000000000000000000000000000000000000000000000008152908816958101959095529151959b5090995093634209fff1936024808501948390030190829087803b158015610c0b57600080fd5b505af1158015610c1f573d6000803e3d6000fd5b505050506040513d6020811015610c3557600080fd5b50511515610cdb5760408051818152600d81830152600080516020613d8483398151915260608201526080602082018190526022908201527f5349474e45525f4e4f545f415554484f52495a45445f574954485f4143434f5560a08201527f4e5400000000000000000000000000000000000000000000000000000000000060c082015290518c91600080516020613dc4833981519152919081900360e00190a26110f0565b898560400151600160a060020a03166370a0823187600001516040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015610d3f57600080fd5b505af1158015610d53573d6000803e3d6000fd5b505050506040513d6020811015610d6957600080fd5b50511015610de95760408051818152600d81830152600080516020613d848339815191526060820152608060208201819052601f908201527f494e53554646494349454e545f42414c414e43455f494e5f4143434f554e540060a082015290518c91600080516020613dc4833981519152919081900360c00190a26110f0565b610e1a610e0f610e0187608001518860c001516133bd565b670de0b6b3a76400006133e5565b8661014001516133fa565b9350610e2a85608001518561340a565b925089831115610eac5760408051818152600d81830152600080516020613d8483398151915260608201526080602082018190526016908201527f494e53554646494349454e545f52455041594d454e540000000000000000000060a082015290518c91600080516020613dc4833981519152919081900360c00190a26110f0565b60008561014001511115610f5e5760025485516040808801516005546101408a015183517f5e61e1c8000000000000000000000000000000000000000000000000000000008152600160a060020a03958616600482015292851660248401529084166044830152606482015290519190921691635e61e1c891608480830192600092919082900301818387803b158015610f4557600080fd5b505af1158015610f59573d6000803e3d6000fd5b505050505b60048054604080880151885182517f106689a5000000000000000000000000000000000000000000000000000000008152600160a060020a0392831695810195909552811660248501526044840187905260648401889052600060848501819052915192169263106689a59260a4808301939282900301818387803b158015610fe657600080fd5b505af1158015610ffa573d6000803e3d6000fd5b50506002546060880151885160a08a0151604080517fbeabacc8000000000000000000000000000000000000000000000000000000008152600160a060020a039485166004820152928416602484015260448301919091525191909216935063beabacc89250606480830192600092919082900301818387803b15801561108057600080fd5b505af1158015611094573d6000803e3d6000fd5b50505050610180850180516000908152600c6020908152604091829020805460ff19166001179055915181518d8152915190927f2d538ae573a2661798539a62b24b14e263cf75f5597027ac2ecfc44ba8ddf9e3928290030190a25b5050505050505050505050565b61111333600035600160e060020a0319166131f1565b1515611157576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b60018054600160a060020a031916600160a060020a0383811691909117918290556040519116907fce241d7ca1f669fee44b6fc00b8eba2df3bb514eed0f6f668f8f89096e81ed9490600090a250565b60006111b1613cf3565b50600082815260096020818152604080842081516101a0810183528154600160a060020a0390811682526001830154811694820194909452600282015484169281019290925260038101549092166060820152600482015460808201819052600583015460a0830152600683015460c08301819052600784015460e0840152600884015461010084015293830154610120830152600a830154610140830152600b830154610160830152600c90920154610180820152929182916112879161127c91610e01916133bd565b8461014001516133fa565b915061129783608001518361340a565b95945050505050565b60408051348082526020820183815236938301849052600435936024359384938693339360008035600160e060020a031916949092606082018484808284376040519201829003965090945050505050a461130733600035600160e060020a0319166131f1565b151561134b576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b82600160a060020a038116151561139a576040805160e560020a62461bcd0281526020600482015260186024820152600080516020613e04833981519152604482015290519081900360640190fd5b505060068054600160a060020a031916600160a060020a03939093169290921790915550565b600754600160a060020a031681565b600d6020526000908152604090205460ff1681565b600160a060020a0381166000908152600b602090815260409182902080548351818402810184019094528084526060939283018282801561144557602002820191906000526020600020905b81548152600190910190602001808311611430575b505050505090505b919050565b600080600080600080600080600080600061146b613cf3565b600960008e600019166000191681526020019081526020016000206101a060405190810160405290816000820160009054906101000a9004600160a060020a0316600160a060020a0316600160a060020a031681526020016001820160009054906101000a9004600160a060020a0316600160a060020a0316600160a060020a031681526020016002820160009054906101000a9004600160a060020a0316600160a060020a0316600160a060020a031681526020016003820160009054906101000a9004600160a060020a0316600160a060020a0316600160a060020a03168152602001600482015481526020016005820154815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201546000191660001916815250509050806000015181602001518260400151836060015184608001518560a001518660c001518761010001518861012001518961014001518a61016001519b509b509b509b509b509b509b509b509b509b509b505091939597999b90929496989a50565b600354600160a060020a031681565b60408051348082526020820183815236938301849052600435936024359384938693339360008035600160e060020a031916949092606082018484808284376040519201829003965090945050505050a461168a33600035600160e060020a0319166131f1565b15156116ce576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b82600160a060020a038116151561171d576040805160e560020a62461bcd0281526020600482015260186024820152600080516020613e04833981519152604482015290519081900360640190fd5b505060078054600160a060020a031916600160a060020a03939093169290921790915550565b600b6020528160005260406000208181548110151561175e57fe5b90600052602060002001600091509150505481565b60015474010000000000000000000000000000000000000000900460ff1681565b600654600160a060020a031681565b6117b933600035600160e060020a0319166131f1565b15156117fd576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b60008054600160a060020a031916600160a060020a03838116919091178083556040519116917f1abebea81bfa2637f28358c371278fb15ede7ea8dd28d2e03b112ff6d936ada491a250565b6060600880548060200260200160405190810160405280929190818152602001828054801561189857602002820191906000526020600020905b81548152600190910190602001808311611883575b5050505050905090565b600c6020526000908152604090205460ff1681565b600a6020526000908152604090205460ff1681565b600154600160a060020a031681565b60408051348082526020820183815236938301849052600435936024359384938693339360008035600160e060020a031916949092606082018484808284376040519201829003965090945050505050a461194233600035600160e060020a0319166131f1565b1515611986576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b82600160a060020a03811615156119d5576040805160e560020a62461bcd0281526020600482015260186024820152600080516020613e04833981519152604482015290519081900360640190fd5b505060058054600160a060020a031916600160a060020a03939093169290921790915550565b60408051348082526020820183815236938301849052600435936024359384938693339360008035600160e060020a031916949092606082018484808284376040519201829003965090945050505050a4611a6233600035600160e060020a0319166131f1565b1515611aa6576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b82600160a060020a0381161515611af5576040805160e560020a62461bcd0281526020600482015260186024820152600080516020613e04833981519152604482015290519081900360640190fd5b505060048054600160a060020a031916600160a060020a03939093169290921790915550565b6008805482908110611b2957fe5b600091825260209091200154905081565b611b42613cf3565b604080513480825260208201838152369383018490526000936060936004359360243593849386933393600160e060020a03198b35169390928b929091818c018484808284376040519201829003965090945050505050a4600654604080517f9c14ee290000000000000000000000000000000000000000000000000000000081523360048201529051600160a060020a0390921691639c14ee29916024808201926020929091908290030181600087803b158015611c0057600080fd5b505af1158015611c14573d6000803e3d6000fd5b505050506040513d6020811015611c2a57600080fd5b50511515611c82576040805160e560020a62461bcd02815260206004820152601f60248201527f4b65726e656c3a3a5f20494e56414c49445f41444d494e5f4143434f554e5400604482015290519081900360640190fd5b6000878152600a602052604090205460ff161515611d245760408051818152600f818301527f4b65726e656c3a3a70726f63657373000000000000000000000000000000000060608201526080602082018190526014908201527f4f524445525f444f45535f4e4f545f455849535400000000000000000000000060a082015290518891600080516020613dc4833981519152919081900360c00190a2612083565b6000878152600c602052604090205460ff1615611dc55760408051818152600f818301527f4b65726e656c3a3a70726f63657373000000000000000000000000000000000060608201526080602082018190526014908201527f4f524445525f414c52454144595f52455041494400000000000000000000000060a082015290518891600080516020613dc4833981519152919081900360c00190a2612083565b6000878152600d602052604090205460ff1615611e665760408051818152600f818301527f4b65726e656c3a3a70726f63657373000000000000000000000000000000000060608201526080602082018190526017908201527f4f524445525f414c52454144595f44454641554c54454400000000000000000060a082015290518891600080516020613dc4833981519152919081900360c00190a2612083565b600087815260096020818152604080842081516101a0810183528154600160a060020a03908116825260018301548116828601526002830154811682850152600383015416606082015260048201546080820152600582015460a0820152600682015460c0820152600782015460e08201526008820154610100820190815294820154610120820152600a820154610140820152600b820154610160820152600c9091015461018082015281519283019091528382529151919750919550909350421115611f6d5760408051808201909152600f81527f4455455f444154455f50415353454400000000000000000000000000000000006020820152600194509250611fb8565b611f77858761341a565b1515611fb85760408051808201909152601181527f434f4c4c41544552414c5f554e5341464500000000000000000000000000000060208201526001945092505b6000878152600d60205260409020805460ff1916851580159190911790915561208357611fe48561349c565b61018085015160408051602080825286518183015286517f98e393d0760ecfe8e3907134d357e8a4fa5b37e364c3baeb0b059a98317638c4938893928392918301919085019080838360005b83811015612048578181015183820152602001612030565b50505050905090810190601f1680156120755780820380516001836020036101000a031916815260200191505b509250505060405180910390a25b50505050505050565b60408051348082526020820183815236938301849052600435936024359384938693339360008035600160e060020a031916949092606082018484808284376040519201829003965090945050505050a46120f333600035600160e060020a0319166131f1565b1515612137576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b82600160a060020a0381161515612186576040805160e560020a62461bcd0281526020600482015260186024820152600080516020613e04833981519152604482015290519081900360640190fd5b505060038054600160a060020a031916600160a060020a03939093169290921790915550565b6121c233600035600160e060020a0319166131f1565b1515612206576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b60408051348082526020820183815236938301849052600435936024359384938693339360008035600160e060020a031916949092606082018484808284376040519201829003965090945050505050a450506001805474ff000000000000000000000000000000000000000019169055565b600054600160a060020a031681565b612290613cf3565b604080513480825260208201838152369383018490526000936004359360243593849386933393600160e060020a03198a351693928a929190606082018484808284376040519201829003965090945050505050a4600654604080517f9c14ee290000000000000000000000000000000000000000000000000000000081523360048201529051600160a060020a0390921691639c14ee29916024808201926020929091908290030181600087803b15801561234b57600080fd5b505af115801561235f573d6000803e3d6000fd5b505050506040513d602081101561237557600080fd5b505115156123cd576040805160e560020a62461bcd02815260206004820152601f60248201527f4b65726e656c3a3a5f20494e56414c49445f41444d494e5f4143434f554e5400604482015290519081900360640190fd5b60015474010000000000000000000000000000000000000000900460ff1615612440576040805160e560020a62461bcd02815260206004820152601960248201527f445353746f703a3a5f20464541545552455f53544f5050454400000000000000604482015290519081900360640190fd5b604080516080818101909252612487918a90600490839083908082843750506040805160c081810190925293508c9250600691508390839080828437506138fe9350505050565b93506124c884610180015187878080601f0160208091040260200160405190810160405280939291908181526020018383808284375061339b945050505050565b92508360200151600160a060020a031683600160a060020a03161415156125645761018084015160408051818152601381830152600080516020613de483398151915260608201526080602082018190526018908201527f5349474e45525f4e4f545f4f524445525f43524541544f52000000000000000060a08201529051600080516020613dc48339815191529181900360c00190a2612feb565b6101808401516000908152600a602052604090205460ff16156125fc5761018084015160408051818152601381830152600080516020613de483398151915260608201526080602082018190526014908201527f4f524445525f414c52454144595f45584953545300000000000000000000000060a08201529051600080516020613dc48339815191529181900360c00190a2612feb565b6003548451604080517f25ca4c9c000000000000000000000000000000000000000000000000000000008152600160a060020a039283166004820152905191909216916325ca4c9c9160248083019260209291908290030181600087803b15801561266657600080fd5b505af115801561267a573d6000803e3d6000fd5b505050506040513d602081101561269057600080fd5b505115156127135761018084015160408051818152601381830152600080516020613de483398151915260608201526080602082018190526015908201527f494e56414c49445f4f524445525f4143434f554e54000000000000000000000060a08201529051600080516020613dc48339815191529181900360c00190a2612feb565b8360000151600160a060020a0316634209fff1846040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b15801561277257600080fd5b505af1158015612786573d6000803e3d6000fd5b505050506040513d602081101561279c57600080fd5b505115156128455761018084015160408051818152601381830152600080516020613de483398151915260608201526080602082018190526022908201527f5349474e45525f4e4f545f415554484f52495a45445f574954485f4143434f5560a08201527f4e5400000000000000000000000000000000000000000000000000000000000060c08201529051600080516020613dc48339815191529181900360e00190a2612feb565b61284e846139b9565b15156128cf5761018084015160408051818152601381830152600080516020613de483398151915260608201526080602082018190526018908201527f494e56414c49445f4f524445525f504152414d4554455253000000000000000060a08201529051600080516020613dc48339815191529181900360c00190a2612feb565b8360a001518460600151600160a060020a03166370a0823186600001516040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b15801561293757600080fd5b505af115801561294b573d6000803e3d6000fd5b505050506040513d602081101561296157600080fd5b50511015612a0a5761018084015160408051818152601381830152600080516020613de483398151915260608201526080602082018190526022908201527f494e53554646494349454e545f434f4c4c41544552414c5f494e5f4143434f5560a08201527f4e5400000000000000000000000000000000000000000000000000000000000060c08201529051600080516020613dc48339815191529181900360e00190a2612feb565b83608001518460400151600160a060020a03166370a08231600460009054906101000a9004600160a060020a0316600160a060020a031663e2fdcc176040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015612a7557600080fd5b505af1158015612a89573d6000803e3d6000fd5b505050506040513d6020811015612a9f57600080fd5b50516040805160e060020a63ffffffff8516028152600160a060020a0390921660048301525160248083019260209291908290030181600087803b158015612ae657600080fd5b505af1158015612afa573d6000803e3d6000fd5b505050506040513d6020811015612b1057600080fd5b50511015612b935761018084015160408051818152601381830152600080516020613de48339815191526060820152608060208201819052601d908201527f494e53554646494349454e545f46554e44535f494e5f5245534552564500000060a08201529051600080516020613dc48339815191529181900360c00190a2612feb565b6008846101800151908060018154018082558091505090600182039060005260206000200160009091929091909150906000191690555083600960008661018001516000191660001916815260200190815260200160002060008201518160000160006101000a815481600160a060020a030219169083600160a060020a0316021790555060208201518160010160006101000a815481600160a060020a030219169083600160a060020a0316021790555060408201518160020160006101000a815481600160a060020a030219169083600160a060020a0316021790555060608201518160030160006101000a815481600160a060020a030219169083600160a060020a031602179055506080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01906000191690559050506001600a60008661018001516000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550600b60008560000151600160a060020a0316600160a060020a031681526020019081526020016000208461018001519080600181540180825580915050906001820390600052602060002001600090919290919091509060001916905550600260009054906101000a9004600160a060020a0316600160a060020a0316635e61e1c885600001518660600151600260009054906101000a9004600160a060020a03168860a001516040518563ffffffff1660e060020a0281526004018085600160a060020a0316600160a060020a0316815260200184600160a060020a0316600160a060020a0316815260200183600160a060020a0316600160a060020a03168152602001828152602001945050505050600060405180830381600087803b158015612e6b57600080fd5b505af1158015612e7f573d6000803e3d6000fd5b505060048054604080890151895160808b015183517f8bfb07c9000000000000000000000000000000000000000000000000000000008152600160a060020a039384169681019690965290821660248601526044850152905191169350638bfb07c99250606480830192600092919082900301818387803b158015612f0357600080fd5b505af1158015612f17573d6000803e3d6000fd5b505050508360400151600160a060020a03168460000151600160a060020a0316856101800151600019167f42436fe8b8c5070e5a6cb3c26e7bc2e889f99c1857c1a1323c54b13fedc655f68760600151886020015189608001518a60a001518b60c001518c61010001518d61014001516040518088600160a060020a0316600160a060020a0316815260200187600160a060020a0316600160a060020a0316815260200186815260200185815260200184815260200183815260200182815260200197505050505050505060405180910390a45b5050505050505050565b60408051348082526020820183815236938301849052600435936024359384938693339360008035600160e060020a031916949092606082018484808284376040519201829003965090945050505050a461305c33600035600160e060020a0319166131f1565b15156130a0576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b82600160a060020a03811615156130ef576040805160e560020a62461bcd0281526020600482015260186024820152600080516020613e04833981519152604482015290519081900360640190fd5b505060028054600160a060020a031916600160a060020a03939093169290921790915550565b600960208190526000918252604090912080546001820154600283015460038401546004850154600586015460068701546007880154600889015499890154600a8a0154600b8b0154600c909b0154600160a060020a039a8b169c998b169b988b169a9097169895979496939592949293919290918d565b600454600160a060020a031681565b600254600160a060020a031681565b600554600160a060020a031681565b60408051808201909152600581527f312e302e30000000000000000000000000000000000000000000000000000000602082015281565b6000600160a060020a03831630141561320c575060016132f4565b600154600160a060020a038481169116141561322a575060016132f4565b600054600160a060020a03161515613244575060006132f4565b60008054604080517fb7009613000000000000000000000000000000000000000000000000000000008152600160a060020a038781166004830152306024830152600160e060020a0319871660448301529151919092169263b700961392606480820193602093909283900390910190829087803b1580156132c557600080fd5b505af11580156132d9573d6000803e3d6000fd5b505050506040513d60208110156132ef57600080fd5b505190505b92915050565b604080516c010000000000000000000000003002602080830191909152603482018590526054808301859052835180840390910181526074909201928390528151600093918291908401908083835b602083106133685780518252601f199092019160209182019101613349565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091209695505050505050565b60006133b6826133aa85613a99565b9063ffffffff613b4316565b9392505050565b60008115806133da5750508082028282828115156133d757fe5b04145b15156132f457600080fd5b600081838115156133f257fe5b049392505050565b808203828111156132f457600080fd5b808201828110156132f457600080fd5b6000806000806000613433610e018860a00151886133bd565b935061344a610e0188608001518960c001516133bd565b925061346161345a8460036133bd565b60646133e5565b915061347a61347488608001518561340a565b8361340a565b90508084101561348d5760009450613492565b600194505b5050505092915050565b6000806000806134b7610e0186608001518760c001516133bd565b93506134c785608001518561340a565b60075460025460608801516040808a015160a08b015182517fc83ec89d000000000000000000000000000000000000000000000000000000008152600160a060020a039586166004820152938516602485015290841660448401526064830152608482018590528051949750919092169263c83ec89d9260a48082019392918290030181600087803b15801561355c57600080fd5b505af1158015613570573d6000803e3d6000fd5b505050506040513d604081101561358657600080fd5b50805160209091015190925090508282106137a057600085610140015111156136425760025460408087015160055461014089015183517fbeabacc8000000000000000000000000000000000000000000000000000000008152600160a060020a03938416600482015291831660248301526044820152915192169163beabacc89160648082019260009290919082900301818387803b15801561362957600080fd5b505af115801561363d573d6000803e3d6000fd5b505050505b6004546040860151600254610140880151600160a060020a039384169363106689a5939216906136739087906133fa565b61368f613684888c608001516133fa565b8b61014001516133fa565b6040805160e060020a63ffffffff8816028152600160a060020a03958616600482015293909416602484015260448301919091526064820152600060848201819052915160a4808301939282900301818387803b1580156136ef57600080fd5b505af1158015613703573d6000803e3d6000fd5b505060025460608801518851604080517fbeabacc8000000000000000000000000000000000000000000000000000000008152600160a060020a0393841660048201529183166024830152604482018790525191909216935063beabacc89250606480830192600092919082900301818387803b15801561378357600080fd5b505af1158015613797573d6000803e3d6000fd5b505050506138f7565b82821080156137b3575084608001518210155b1561384a5760045460408601516002546080880151600160a060020a039384169363106689a59392169086906137ea9082906133fa565b6040805160e060020a63ffffffff8816028152600160a060020a03958616600482015293909416602484015260448301919091526064820152600060848201819052915160a4808301939282900301818387803b15801561378357600080fd5b60045460408601516002546080880151600160a060020a039384169363106689a593921690869060009061387e90836133fa565b6040805160e060020a63ffffffff8916028152600160a060020a039687166004820152949095166024850152604484019290925260648301526084820152905160a480830192600092919082900301818387803b1580156138de57600080fd5b505af11580156138f2573d6000803e3d6000fd5b505050505b5050505050565b613906613cf3565b61390e613cf3565b604080516101a0810182528551600160a060020a03908116825260208088015182168184015287840151821683850152606080890151909216828401528651608084015286015160a08301529185015160c0820152908401805160e08301525161010082019061397f90429061340a565b8152608080860151602083015260a08601516040830152426060830152600091015290506139ac81613c18565b6101808201529392505050565b8051600090600160a060020a031615806139de57506020820151600160a060020a0316155b806139f457506040820151600160a060020a0316155b80613a0a57506060820151600160a060020a0316155b80613a2e57508160400151600160a060020a03168260600151600160a060020a0316145b80613a3e57506000826080015111155b80613a4e575060008260a0015111155b80613a5e575060008260c0015111155b80613a73575081610160015182610100015111155b80613a845750600082610120015111155b15613a915750600061144d565b506001919050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c80830185905283518084039091018152605c909201928390528151600093918291908401908083835b60208310613b115780518252601f199092019160209182019101613af2565b5181516020939093036101000a6000190180199091169216919091179052604051920182900390912095945050505050565b60008060008084516041141515613b5d5760009350613c0f565b50505060208201516040830151606084015160001a601b60ff82161015613b8257601b015b8060ff16601b14158015613b9a57508060ff16601c14155b15613ba85760009350613c0f565b60408051600080825260208083018085528a905260ff8516838501526060830187905260808301869052925160019360a0808501949193601f19840193928390039091019190865af1158015613c02573d6000803e3d6000fd5b5050506020604051035193505b50505092915050565b80516040808301516060840151608085015160a086015160c087015160e08801516101208901516101408a015188516c01000000000000000000000000308102602080840191909152600160a060020a039c8d1682026034840152998c16810260488301529a909716909902605c8701526070860194909452609085019290925260b084015260d083015260f0820152610110808201949094528251808203909401845261013001918290528251600093929182919084019080838360208310613b115780518252601f199092019160209182019101613af2565b6101a0604051908101604052806000600160a060020a031681526020016000600160a060020a031681526020016000600160a060020a031681526020016000600160a060020a03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008019168152509056004b65726e656c3a3a7265706179000000000000000000000000000000000000004453417574683a3a5f2053454e4445525f4e4f545f415554484f52495a454400db0b341562703a7cbd47efa0b024b1ed2e3c68e2d313e46d276db9a46d8a6f804b65726e656c3a3a6372656174654f72646572000000000000000000000000005574696c733a3a5f20494e56414c49445f414444524553530000000000000000a165627a7a7230582081a021c80837ae0518b8c3e2b233a2e8b17c0a3182f3058e9aa43ada0691d9290029000000000000000000000000af38668f4719ecf9452dc0300be3f6c83cbf37210000000000000000000000004e9d7f37eadc6fef64b5f5dccc4deb622466767700000000000000000000000064d14595152b430cf6940da15c6e39545c7c5b7e0000000000000000000000003e990e787a88cd4426fb3af9b90dd1d951e2cb87000000000000000000000000431f429035a1e3059d5c6a9a83208c6d3143d925000000000000000000000000521550e569bc80f1b4957c4f3fd3d677d9ca31f1

Deployed Bytecode

0x6080604052600436106101875763ffffffff60e060020a60003504166307da68f5811461018c5780630b7e2e97146101a357806313af4035146101cb57806320cd1649146101ec57806320e3dbd4146102165780632b612988146102375780632fcdb8dd14610268578063359abaed146102945780635778472a14610305578063687cd9c1146103855780636d8a7b9d1461039a5780636dec3260146103bb57806375f12b21146103df57806379502c55146103f45780637a9e5e4b146104095780637bea0d1c1461042a578063817671551461043f5780638723555e146104575780638da5cb5b1461046f57806390d49b9d146104845780639cecc80a146104a5578063a85c38ef146104c6578063acfd6ce6146104de578063addc1a76146104f9578063be9a65551461051a578063bf7e214f1461052f578063c086504214610544578063c10c354614610569578063c559f6861461058a578063cd3293de14610619578063e2fdcc171461062e578063f25f4b5614610643578063ffa1ad7414610658575b600080fd5b34801561019857600080fd5b506101a16106e2565b005b3480156101af57600080fd5b506101a1600480359060248035916044359182019101356107c6565b3480156101d757600080fd5b506101a1600160a060020a03600435166110fd565b3480156101f857600080fd5b506102046004356111a7565b60408051918252519081900360200190f35b34801561022257600080fd5b506101a1600160a060020a03600435166112a0565b34801561024357600080fd5b5061024c6113c0565b60408051600160a060020a039092168252519081900360200190f35b34801561027457600080fd5b506102806004356113cf565b604080519115158252519081900360200190f35b3480156102a057600080fd5b506102b5600160a060020a03600435166113e4565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156102f15781810151838201526020016102d9565b505050509050019250505060405180910390f35b34801561031157600080fd5b5061031d600435611452565b60408051600160a060020a039c8d1681529a8c1660208c0152988b168a8a0152969099166060890152608088019490945260a087019290925260c086015260e08501526101008401526101208301939093526101408201929092529051908190036101600190f35b34801561039157600080fd5b5061024c611614565b3480156103a657600080fd5b506101a1600160a060020a0360043516611623565b3480156103c757600080fd5b50610204600160a060020a0360043516602435611743565b3480156103eb57600080fd5b50610280611773565b34801561040057600080fd5b5061024c611794565b34801561041557600080fd5b506101a1600160a060020a03600435166117a3565b34801561043657600080fd5b506102b5611849565b34801561044b57600080fd5b506102806004356118a2565b34801561046357600080fd5b506102806004356118b7565b34801561047b57600080fd5b5061024c6118cc565b34801561049057600080fd5b506101a1600160a060020a03600435166118db565b3480156104b157600080fd5b506101a1600160a060020a03600435166119fb565b3480156104d257600080fd5b50610204600435611b1b565b3480156104ea57600080fd5b506101a1600435602435611b3a565b34801561050557600080fd5b506101a1600160a060020a036004351661208c565b34801561052657600080fd5b506101a16121ac565b34801561053b57600080fd5b5061024c612279565b34801561055057600080fd5b506101a160046084610144356024810190830135612288565b34801561057557600080fd5b506101a1600160a060020a0360043516612ff5565b34801561059657600080fd5b506105a2600435613115565b60408051600160a060020a039e8f1681529c8e1660208e01529a8d168c8c015298909b1660608b015260808a019690965260a089019490945260c088019290925260e08701526101008601526101208501526101408401526101608301939093526101808201929092529051908190036101a00190f35b34801561062557600080fd5b5061024c61318d565b34801561063a57600080fd5b5061024c61319c565b34801561064f57600080fd5b5061024c6131ab565b34801561066457600080fd5b5061066d6131ba565b6040805160208082528351818301528351919283929083019185019080838360005b838110156106a757818101518382015260200161068f565b50505050905090810190601f1680156106d45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6106f833600035600160e060020a0319166131f1565b151561073c576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b60408051348082526020820183815236938301849052600435936024359384938693339360008035600160e060020a031916949092606082018484808284376040519201829003965090945050505050a450506001805474ff0000000000000000000000000000000000000000191674010000000000000000000000000000000000000000179055565b6000806107d1613cf3565b6040805134808252602082018381523693830184905260009384936004359360243593849386933393600160e060020a03198a35169390928a929091606082018484808284376040519201829003965090945050505050a4600654604080517f9c14ee290000000000000000000000000000000000000000000000000000000081523360048201529051600160a060020a0390921691639c14ee29916024808201926020929091908290030181600087803b15801561088f57600080fd5b505af11580156108a3573d6000803e3d6000fd5b505050506040513d60208110156108b957600080fd5b50511515610911576040805160e560020a62461bcd02815260206004820152601f60248201527f4b65726e656c3a3a5f20494e56414c49445f41444d494e5f4143434f554e5400604482015290519081900360640190fd5b60008b8152600a602052604090205460ff1615156109a15760408051818152600d81830152600080516020613d8483398151915260608201526080602082018190526014908201527f4f524445525f444f45535f4e4f545f455849535400000000000000000000000060a082015290518c91600080516020613dc4833981519152919081900360c00190a26110f0565b60008b8152600c602052604090205460ff1615610a305760408051818152600d81830152600080516020613d8483398151915260608201526080602082018190526014908201527f4f524445525f414c52454144595f52455041494400000000000000000000000060a082015290518c91600080516020613dc4833981519152919081900360c00190a26110f0565b60008b8152600d602052604090205460ff1615610abf5760408051818152600d81830152600080516020613d8483398151915260608201526080602082018190526017908201527f4f524445525f414c52454144595f44454641554c54454400000000000000000060a082015290518c91600080516020613dc4833981519152919081900360c00190a26110f0565b610ac98b8b6132fa565b9650610b05878a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375061339b945050505050565b60008c815260096020818152604080842081516101a0810183528154600160a060020a03908116808352600184015482168387015260028401548216838601526003840154821660608401526004808501546080850152600585015460a0850152600685015460c0850152600785015460e0850152600885015461010085015296840154610120840152600a840154610140840152600b840154610160840152600c9093015461018083015283517f4209fff1000000000000000000000000000000000000000000000000000000008152908816958101959095529151959b5090995093634209fff1936024808501948390030190829087803b158015610c0b57600080fd5b505af1158015610c1f573d6000803e3d6000fd5b505050506040513d6020811015610c3557600080fd5b50511515610cdb5760408051818152600d81830152600080516020613d8483398151915260608201526080602082018190526022908201527f5349474e45525f4e4f545f415554484f52495a45445f574954485f4143434f5560a08201527f4e5400000000000000000000000000000000000000000000000000000000000060c082015290518c91600080516020613dc4833981519152919081900360e00190a26110f0565b898560400151600160a060020a03166370a0823187600001516040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015610d3f57600080fd5b505af1158015610d53573d6000803e3d6000fd5b505050506040513d6020811015610d6957600080fd5b50511015610de95760408051818152600d81830152600080516020613d848339815191526060820152608060208201819052601f908201527f494e53554646494349454e545f42414c414e43455f494e5f4143434f554e540060a082015290518c91600080516020613dc4833981519152919081900360c00190a26110f0565b610e1a610e0f610e0187608001518860c001516133bd565b670de0b6b3a76400006133e5565b8661014001516133fa565b9350610e2a85608001518561340a565b925089831115610eac5760408051818152600d81830152600080516020613d8483398151915260608201526080602082018190526016908201527f494e53554646494349454e545f52455041594d454e540000000000000000000060a082015290518c91600080516020613dc4833981519152919081900360c00190a26110f0565b60008561014001511115610f5e5760025485516040808801516005546101408a015183517f5e61e1c8000000000000000000000000000000000000000000000000000000008152600160a060020a03958616600482015292851660248401529084166044830152606482015290519190921691635e61e1c891608480830192600092919082900301818387803b158015610f4557600080fd5b505af1158015610f59573d6000803e3d6000fd5b505050505b60048054604080880151885182517f106689a5000000000000000000000000000000000000000000000000000000008152600160a060020a0392831695810195909552811660248501526044840187905260648401889052600060848501819052915192169263106689a59260a4808301939282900301818387803b158015610fe657600080fd5b505af1158015610ffa573d6000803e3d6000fd5b50506002546060880151885160a08a0151604080517fbeabacc8000000000000000000000000000000000000000000000000000000008152600160a060020a039485166004820152928416602484015260448301919091525191909216935063beabacc89250606480830192600092919082900301818387803b15801561108057600080fd5b505af1158015611094573d6000803e3d6000fd5b50505050610180850180516000908152600c6020908152604091829020805460ff19166001179055915181518d8152915190927f2d538ae573a2661798539a62b24b14e263cf75f5597027ac2ecfc44ba8ddf9e3928290030190a25b5050505050505050505050565b61111333600035600160e060020a0319166131f1565b1515611157576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b60018054600160a060020a031916600160a060020a0383811691909117918290556040519116907fce241d7ca1f669fee44b6fc00b8eba2df3bb514eed0f6f668f8f89096e81ed9490600090a250565b60006111b1613cf3565b50600082815260096020818152604080842081516101a0810183528154600160a060020a0390811682526001830154811694820194909452600282015484169281019290925260038101549092166060820152600482015460808201819052600583015460a0830152600683015460c08301819052600784015460e0840152600884015461010084015293830154610120830152600a830154610140830152600b830154610160830152600c90920154610180820152929182916112879161127c91610e01916133bd565b8461014001516133fa565b915061129783608001518361340a565b95945050505050565b60408051348082526020820183815236938301849052600435936024359384938693339360008035600160e060020a031916949092606082018484808284376040519201829003965090945050505050a461130733600035600160e060020a0319166131f1565b151561134b576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b82600160a060020a038116151561139a576040805160e560020a62461bcd0281526020600482015260186024820152600080516020613e04833981519152604482015290519081900360640190fd5b505060068054600160a060020a031916600160a060020a03939093169290921790915550565b600754600160a060020a031681565b600d6020526000908152604090205460ff1681565b600160a060020a0381166000908152600b602090815260409182902080548351818402810184019094528084526060939283018282801561144557602002820191906000526020600020905b81548152600190910190602001808311611430575b505050505090505b919050565b600080600080600080600080600080600061146b613cf3565b600960008e600019166000191681526020019081526020016000206101a060405190810160405290816000820160009054906101000a9004600160a060020a0316600160a060020a0316600160a060020a031681526020016001820160009054906101000a9004600160a060020a0316600160a060020a0316600160a060020a031681526020016002820160009054906101000a9004600160a060020a0316600160a060020a0316600160a060020a031681526020016003820160009054906101000a9004600160a060020a0316600160a060020a0316600160a060020a03168152602001600482015481526020016005820154815260200160068201548152602001600782015481526020016008820154815260200160098201548152602001600a8201548152602001600b8201548152602001600c8201546000191660001916815250509050806000015181602001518260400151836060015184608001518560a001518660c001518761010001518861012001518961014001518a61016001519b509b509b509b509b509b509b509b509b509b509b505091939597999b90929496989a50565b600354600160a060020a031681565b60408051348082526020820183815236938301849052600435936024359384938693339360008035600160e060020a031916949092606082018484808284376040519201829003965090945050505050a461168a33600035600160e060020a0319166131f1565b15156116ce576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b82600160a060020a038116151561171d576040805160e560020a62461bcd0281526020600482015260186024820152600080516020613e04833981519152604482015290519081900360640190fd5b505060078054600160a060020a031916600160a060020a03939093169290921790915550565b600b6020528160005260406000208181548110151561175e57fe5b90600052602060002001600091509150505481565b60015474010000000000000000000000000000000000000000900460ff1681565b600654600160a060020a031681565b6117b933600035600160e060020a0319166131f1565b15156117fd576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b60008054600160a060020a031916600160a060020a03838116919091178083556040519116917f1abebea81bfa2637f28358c371278fb15ede7ea8dd28d2e03b112ff6d936ada491a250565b6060600880548060200260200160405190810160405280929190818152602001828054801561189857602002820191906000526020600020905b81548152600190910190602001808311611883575b5050505050905090565b600c6020526000908152604090205460ff1681565b600a6020526000908152604090205460ff1681565b600154600160a060020a031681565b60408051348082526020820183815236938301849052600435936024359384938693339360008035600160e060020a031916949092606082018484808284376040519201829003965090945050505050a461194233600035600160e060020a0319166131f1565b1515611986576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b82600160a060020a03811615156119d5576040805160e560020a62461bcd0281526020600482015260186024820152600080516020613e04833981519152604482015290519081900360640190fd5b505060058054600160a060020a031916600160a060020a03939093169290921790915550565b60408051348082526020820183815236938301849052600435936024359384938693339360008035600160e060020a031916949092606082018484808284376040519201829003965090945050505050a4611a6233600035600160e060020a0319166131f1565b1515611aa6576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b82600160a060020a0381161515611af5576040805160e560020a62461bcd0281526020600482015260186024820152600080516020613e04833981519152604482015290519081900360640190fd5b505060048054600160a060020a031916600160a060020a03939093169290921790915550565b6008805482908110611b2957fe5b600091825260209091200154905081565b611b42613cf3565b604080513480825260208201838152369383018490526000936060936004359360243593849386933393600160e060020a03198b35169390928b929091818c018484808284376040519201829003965090945050505050a4600654604080517f9c14ee290000000000000000000000000000000000000000000000000000000081523360048201529051600160a060020a0390921691639c14ee29916024808201926020929091908290030181600087803b158015611c0057600080fd5b505af1158015611c14573d6000803e3d6000fd5b505050506040513d6020811015611c2a57600080fd5b50511515611c82576040805160e560020a62461bcd02815260206004820152601f60248201527f4b65726e656c3a3a5f20494e56414c49445f41444d494e5f4143434f554e5400604482015290519081900360640190fd5b6000878152600a602052604090205460ff161515611d245760408051818152600f818301527f4b65726e656c3a3a70726f63657373000000000000000000000000000000000060608201526080602082018190526014908201527f4f524445525f444f45535f4e4f545f455849535400000000000000000000000060a082015290518891600080516020613dc4833981519152919081900360c00190a2612083565b6000878152600c602052604090205460ff1615611dc55760408051818152600f818301527f4b65726e656c3a3a70726f63657373000000000000000000000000000000000060608201526080602082018190526014908201527f4f524445525f414c52454144595f52455041494400000000000000000000000060a082015290518891600080516020613dc4833981519152919081900360c00190a2612083565b6000878152600d602052604090205460ff1615611e665760408051818152600f818301527f4b65726e656c3a3a70726f63657373000000000000000000000000000000000060608201526080602082018190526017908201527f4f524445525f414c52454144595f44454641554c54454400000000000000000060a082015290518891600080516020613dc4833981519152919081900360c00190a2612083565b600087815260096020818152604080842081516101a0810183528154600160a060020a03908116825260018301548116828601526002830154811682850152600383015416606082015260048201546080820152600582015460a0820152600682015460c0820152600782015460e08201526008820154610100820190815294820154610120820152600a820154610140820152600b820154610160820152600c9091015461018082015281519283019091528382529151919750919550909350421115611f6d5760408051808201909152600f81527f4455455f444154455f50415353454400000000000000000000000000000000006020820152600194509250611fb8565b611f77858761341a565b1515611fb85760408051808201909152601181527f434f4c4c41544552414c5f554e5341464500000000000000000000000000000060208201526001945092505b6000878152600d60205260409020805460ff1916851580159190911790915561208357611fe48561349c565b61018085015160408051602080825286518183015286517f98e393d0760ecfe8e3907134d357e8a4fa5b37e364c3baeb0b059a98317638c4938893928392918301919085019080838360005b83811015612048578181015183820152602001612030565b50505050905090810190601f1680156120755780820380516001836020036101000a031916815260200191505b509250505060405180910390a25b50505050505050565b60408051348082526020820183815236938301849052600435936024359384938693339360008035600160e060020a031916949092606082018484808284376040519201829003965090945050505050a46120f333600035600160e060020a0319166131f1565b1515612137576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b82600160a060020a0381161515612186576040805160e560020a62461bcd0281526020600482015260186024820152600080516020613e04833981519152604482015290519081900360640190fd5b505060038054600160a060020a031916600160a060020a03939093169290921790915550565b6121c233600035600160e060020a0319166131f1565b1515612206576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b60408051348082526020820183815236938301849052600435936024359384938693339360008035600160e060020a031916949092606082018484808284376040519201829003965090945050505050a450506001805474ff000000000000000000000000000000000000000019169055565b600054600160a060020a031681565b612290613cf3565b604080513480825260208201838152369383018490526000936004359360243593849386933393600160e060020a03198a351693928a929190606082018484808284376040519201829003965090945050505050a4600654604080517f9c14ee290000000000000000000000000000000000000000000000000000000081523360048201529051600160a060020a0390921691639c14ee29916024808201926020929091908290030181600087803b15801561234b57600080fd5b505af115801561235f573d6000803e3d6000fd5b505050506040513d602081101561237557600080fd5b505115156123cd576040805160e560020a62461bcd02815260206004820152601f60248201527f4b65726e656c3a3a5f20494e56414c49445f41444d494e5f4143434f554e5400604482015290519081900360640190fd5b60015474010000000000000000000000000000000000000000900460ff1615612440576040805160e560020a62461bcd02815260206004820152601960248201527f445353746f703a3a5f20464541545552455f53544f5050454400000000000000604482015290519081900360640190fd5b604080516080818101909252612487918a90600490839083908082843750506040805160c081810190925293508c9250600691508390839080828437506138fe9350505050565b93506124c884610180015187878080601f0160208091040260200160405190810160405280939291908181526020018383808284375061339b945050505050565b92508360200151600160a060020a031683600160a060020a03161415156125645761018084015160408051818152601381830152600080516020613de483398151915260608201526080602082018190526018908201527f5349474e45525f4e4f545f4f524445525f43524541544f52000000000000000060a08201529051600080516020613dc48339815191529181900360c00190a2612feb565b6101808401516000908152600a602052604090205460ff16156125fc5761018084015160408051818152601381830152600080516020613de483398151915260608201526080602082018190526014908201527f4f524445525f414c52454144595f45584953545300000000000000000000000060a08201529051600080516020613dc48339815191529181900360c00190a2612feb565b6003548451604080517f25ca4c9c000000000000000000000000000000000000000000000000000000008152600160a060020a039283166004820152905191909216916325ca4c9c9160248083019260209291908290030181600087803b15801561266657600080fd5b505af115801561267a573d6000803e3d6000fd5b505050506040513d602081101561269057600080fd5b505115156127135761018084015160408051818152601381830152600080516020613de483398151915260608201526080602082018190526015908201527f494e56414c49445f4f524445525f4143434f554e54000000000000000000000060a08201529051600080516020613dc48339815191529181900360c00190a2612feb565b8360000151600160a060020a0316634209fff1846040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b15801561277257600080fd5b505af1158015612786573d6000803e3d6000fd5b505050506040513d602081101561279c57600080fd5b505115156128455761018084015160408051818152601381830152600080516020613de483398151915260608201526080602082018190526022908201527f5349474e45525f4e4f545f415554484f52495a45445f574954485f4143434f5560a08201527f4e5400000000000000000000000000000000000000000000000000000000000060c08201529051600080516020613dc48339815191529181900360e00190a2612feb565b61284e846139b9565b15156128cf5761018084015160408051818152601381830152600080516020613de483398151915260608201526080602082018190526018908201527f494e56414c49445f4f524445525f504152414d4554455253000000000000000060a08201529051600080516020613dc48339815191529181900360c00190a2612feb565b8360a001518460600151600160a060020a03166370a0823186600001516040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b15801561293757600080fd5b505af115801561294b573d6000803e3d6000fd5b505050506040513d602081101561296157600080fd5b50511015612a0a5761018084015160408051818152601381830152600080516020613de483398151915260608201526080602082018190526022908201527f494e53554646494349454e545f434f4c4c41544552414c5f494e5f4143434f5560a08201527f4e5400000000000000000000000000000000000000000000000000000000000060c08201529051600080516020613dc48339815191529181900360e00190a2612feb565b83608001518460400151600160a060020a03166370a08231600460009054906101000a9004600160a060020a0316600160a060020a031663e2fdcc176040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015612a7557600080fd5b505af1158015612a89573d6000803e3d6000fd5b505050506040513d6020811015612a9f57600080fd5b50516040805160e060020a63ffffffff8516028152600160a060020a0390921660048301525160248083019260209291908290030181600087803b158015612ae657600080fd5b505af1158015612afa573d6000803e3d6000fd5b505050506040513d6020811015612b1057600080fd5b50511015612b935761018084015160408051818152601381830152600080516020613de48339815191526060820152608060208201819052601d908201527f494e53554646494349454e545f46554e44535f494e5f5245534552564500000060a08201529051600080516020613dc48339815191529181900360c00190a2612feb565b6008846101800151908060018154018082558091505090600182039060005260206000200160009091929091909150906000191690555083600960008661018001516000191660001916815260200190815260200160002060008201518160000160006101000a815481600160a060020a030219169083600160a060020a0316021790555060208201518160010160006101000a815481600160a060020a030219169083600160a060020a0316021790555060408201518160020160006101000a815481600160a060020a030219169083600160a060020a0316021790555060608201518160030160006101000a815481600160a060020a030219169083600160a060020a031602179055506080820151816004015560a0820151816005015560c0820151816006015560e082015181600701556101008201518160080155610120820151816009015561014082015181600a015561016082015181600b015561018082015181600c01906000191690559050506001600a60008661018001516000191660001916815260200190815260200160002060006101000a81548160ff021916908315150217905550600b60008560000151600160a060020a0316600160a060020a031681526020019081526020016000208461018001519080600181540180825580915050906001820390600052602060002001600090919290919091509060001916905550600260009054906101000a9004600160a060020a0316600160a060020a0316635e61e1c885600001518660600151600260009054906101000a9004600160a060020a03168860a001516040518563ffffffff1660e060020a0281526004018085600160a060020a0316600160a060020a0316815260200184600160a060020a0316600160a060020a0316815260200183600160a060020a0316600160a060020a03168152602001828152602001945050505050600060405180830381600087803b158015612e6b57600080fd5b505af1158015612e7f573d6000803e3d6000fd5b505060048054604080890151895160808b015183517f8bfb07c9000000000000000000000000000000000000000000000000000000008152600160a060020a039384169681019690965290821660248601526044850152905191169350638bfb07c99250606480830192600092919082900301818387803b158015612f0357600080fd5b505af1158015612f17573d6000803e3d6000fd5b505050508360400151600160a060020a03168460000151600160a060020a0316856101800151600019167f42436fe8b8c5070e5a6cb3c26e7bc2e889f99c1857c1a1323c54b13fedc655f68760600151886020015189608001518a60a001518b60c001518c61010001518d61014001516040518088600160a060020a0316600160a060020a0316815260200187600160a060020a0316600160a060020a0316815260200186815260200185815260200184815260200183815260200182815260200197505050505050505060405180910390a45b5050505050505050565b60408051348082526020820183815236938301849052600435936024359384938693339360008035600160e060020a031916949092606082018484808284376040519201829003965090945050505050a461305c33600035600160e060020a0319166131f1565b15156130a0576040805160e560020a62461bcd02815260206004820152601f6024820152600080516020613da4833981519152604482015290519081900360640190fd5b82600160a060020a03811615156130ef576040805160e560020a62461bcd0281526020600482015260186024820152600080516020613e04833981519152604482015290519081900360640190fd5b505060028054600160a060020a031916600160a060020a03939093169290921790915550565b600960208190526000918252604090912080546001820154600283015460038401546004850154600586015460068701546007880154600889015499890154600a8a0154600b8b0154600c909b0154600160a060020a039a8b169c998b169b988b169a9097169895979496939592949293919290918d565b600454600160a060020a031681565b600254600160a060020a031681565b600554600160a060020a031681565b60408051808201909152600581527f312e302e30000000000000000000000000000000000000000000000000000000602082015281565b6000600160a060020a03831630141561320c575060016132f4565b600154600160a060020a038481169116141561322a575060016132f4565b600054600160a060020a03161515613244575060006132f4565b60008054604080517fb7009613000000000000000000000000000000000000000000000000000000008152600160a060020a038781166004830152306024830152600160e060020a0319871660448301529151919092169263b700961392606480820193602093909283900390910190829087803b1580156132c557600080fd5b505af11580156132d9573d6000803e3d6000fd5b505050506040513d60208110156132ef57600080fd5b505190505b92915050565b604080516c010000000000000000000000003002602080830191909152603482018590526054808301859052835180840390910181526074909201928390528151600093918291908401908083835b602083106133685780518252601f199092019160209182019101613349565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091209695505050505050565b60006133b6826133aa85613a99565b9063ffffffff613b4316565b9392505050565b60008115806133da5750508082028282828115156133d757fe5b04145b15156132f457600080fd5b600081838115156133f257fe5b049392505050565b808203828111156132f457600080fd5b808201828110156132f457600080fd5b6000806000806000613433610e018860a00151886133bd565b935061344a610e0188608001518960c001516133bd565b925061346161345a8460036133bd565b60646133e5565b915061347a61347488608001518561340a565b8361340a565b90508084101561348d5760009450613492565b600194505b5050505092915050565b6000806000806134b7610e0186608001518760c001516133bd565b93506134c785608001518561340a565b60075460025460608801516040808a015160a08b015182517fc83ec89d000000000000000000000000000000000000000000000000000000008152600160a060020a039586166004820152938516602485015290841660448401526064830152608482018590528051949750919092169263c83ec89d9260a48082019392918290030181600087803b15801561355c57600080fd5b505af1158015613570573d6000803e3d6000fd5b505050506040513d604081101561358657600080fd5b50805160209091015190925090508282106137a057600085610140015111156136425760025460408087015160055461014089015183517fbeabacc8000000000000000000000000000000000000000000000000000000008152600160a060020a03938416600482015291831660248301526044820152915192169163beabacc89160648082019260009290919082900301818387803b15801561362957600080fd5b505af115801561363d573d6000803e3d6000fd5b505050505b6004546040860151600254610140880151600160a060020a039384169363106689a5939216906136739087906133fa565b61368f613684888c608001516133fa565b8b61014001516133fa565b6040805160e060020a63ffffffff8816028152600160a060020a03958616600482015293909416602484015260448301919091526064820152600060848201819052915160a4808301939282900301818387803b1580156136ef57600080fd5b505af1158015613703573d6000803e3d6000fd5b505060025460608801518851604080517fbeabacc8000000000000000000000000000000000000000000000000000000008152600160a060020a0393841660048201529183166024830152604482018790525191909216935063beabacc89250606480830192600092919082900301818387803b15801561378357600080fd5b505af1158015613797573d6000803e3d6000fd5b505050506138f7565b82821080156137b3575084608001518210155b1561384a5760045460408601516002546080880151600160a060020a039384169363106689a59392169086906137ea9082906133fa565b6040805160e060020a63ffffffff8816028152600160a060020a03958616600482015293909416602484015260448301919091526064820152600060848201819052915160a4808301939282900301818387803b15801561378357600080fd5b60045460408601516002546080880151600160a060020a039384169363106689a593921690869060009061387e90836133fa565b6040805160e060020a63ffffffff8916028152600160a060020a039687166004820152949095166024850152604484019290925260648301526084820152905160a480830192600092919082900301818387803b1580156138de57600080fd5b505af11580156138f2573d6000803e3d6000fd5b505050505b5050505050565b613906613cf3565b61390e613cf3565b604080516101a0810182528551600160a060020a03908116825260208088015182168184015287840151821683850152606080890151909216828401528651608084015286015160a08301529185015160c0820152908401805160e08301525161010082019061397f90429061340a565b8152608080860151602083015260a08601516040830152426060830152600091015290506139ac81613c18565b6101808201529392505050565b8051600090600160a060020a031615806139de57506020820151600160a060020a0316155b806139f457506040820151600160a060020a0316155b80613a0a57506060820151600160a060020a0316155b80613a2e57508160400151600160a060020a03168260600151600160a060020a0316145b80613a3e57506000826080015111155b80613a4e575060008260a0015111155b80613a5e575060008260c0015111155b80613a73575081610160015182610100015111155b80613a845750600082610120015111155b15613a915750600061144d565b506001919050565b604080517f19457468657265756d205369676e6564204d6573736167653a0a333200000000602080830191909152603c80830185905283518084039091018152605c909201928390528151600093918291908401908083835b60208310613b115780518252601f199092019160209182019101613af2565b5181516020939093036101000a6000190180199091169216919091179052604051920182900390912095945050505050565b60008060008084516041141515613b5d5760009350613c0f565b50505060208201516040830151606084015160001a601b60ff82161015613b8257601b015b8060ff16601b14158015613b9a57508060ff16601c14155b15613ba85760009350613c0f565b60408051600080825260208083018085528a905260ff8516838501526060830187905260808301869052925160019360a0808501949193601f19840193928390039091019190865af1158015613c02573d6000803e3d6000fd5b5050506020604051035193505b50505092915050565b80516040808301516060840151608085015160a086015160c087015160e08801516101208901516101408a015188516c01000000000000000000000000308102602080840191909152600160a060020a039c8d1682026034840152998c16810260488301529a909716909902605c8701526070860194909452609085019290925260b084015260d083015260f0820152610110808201949094528251808203909401845261013001918290528251600093929182919084019080838360208310613b115780518252601f199092019160209182019101613af2565b6101a0604051908101604052806000600160a060020a031681526020016000600160a060020a031681526020016000600160a060020a031681526020016000600160a060020a03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008019168152509056004b65726e656c3a3a7265706179000000000000000000000000000000000000004453417574683a3a5f2053454e4445525f4e4f545f415554484f52495a454400db0b341562703a7cbd47efa0b024b1ed2e3c68e2d313e46d276db9a46d8a6f804b65726e656c3a3a6372656174654f72646572000000000000000000000000005574696c733a3a5f20494e56414c49445f414444524553530000000000000000a165627a7a7230582081a021c80837ae0518b8c3e2b233a2e8b17c0a3182f3058e9aa43ada0691d9290029

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

000000000000000000000000af38668f4719ecf9452dc0300be3f6c83cbf37210000000000000000000000004e9d7f37eadc6fef64b5f5dccc4deb622466767700000000000000000000000064d14595152b430cf6940da15c6e39545c7c5b7e0000000000000000000000003e990e787a88cd4426fb3af9b90dd1d951e2cb87000000000000000000000000431f429035a1e3059d5c6a9a83208c6d3143d925000000000000000000000000521550e569bc80f1b4957c4f3fd3d677d9ca31f1

-----Decoded View---------------
Arg [0] : _escrow (address): 0xaf38668F4719Ecf9452DC0300BE3f6c83Cbf3721
Arg [1] : _accountFactory (address): 0x4E9D7f37EADc6fef64B5F5DCcC4deB6224667677
Arg [2] : _reserve (address): 0x64d14595152B430CF6940Da15C6e39545c7c5B7e
Arg [3] : _feeWallet (address): 0x3E990e787a88cD4426fB3AF9B90DD1D951E2cb87
Arg [4] : _config (address): 0x431F429035a1e3059d5c6a9a83208c6D3143D925
Arg [5] : _kyberConnector (address): 0x521550E569bc80F1b4957C4F3Fd3D677d9ca31f1

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000af38668f4719ecf9452dc0300be3f6c83cbf3721
Arg [1] : 0000000000000000000000004e9d7f37eadc6fef64b5f5dccc4deb6224667677
Arg [2] : 00000000000000000000000064d14595152b430cf6940da15c6e39545c7c5b7e
Arg [3] : 0000000000000000000000003e990e787a88cd4426fb3af9b90dd1d951e2cb87
Arg [4] : 000000000000000000000000431f429035a1e3059d5c6a9a83208c6d3143d925
Arg [5] : 000000000000000000000000521550e569bc80f1b4957c4f3fd3d677d9ca31f1


Swarm Source

bzzr://81a021c80837ae0518b8c3e2b233a2e8b17c0a3182f3058e9aa43ada0691d929

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.