Feature Tip: Add private address tag to any address under My Name Tag !
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 16,124 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Process | 11863121 | 1420 days ago | IN | 0 ETH | 0.2611319 | ||||
Process | 10803602 | 1583 days ago | IN | 0 ETH | 0.51171652 | ||||
Process | 10794329 | 1584 days ago | IN | 0 ETH | 0.00843269 | ||||
Process | 10794320 | 1584 days ago | IN | 0 ETH | 0.00843269 | ||||
Process | 10794320 | 1584 days ago | IN | 0 ETH | 0.00843269 | ||||
Process | 10790382 | 1585 days ago | IN | 0 ETH | 0.00773304 | ||||
Process | 10790382 | 1585 days ago | IN | 0 ETH | 0.00776986 | ||||
Process | 10790382 | 1585 days ago | IN | 0 ETH | 0.33300674 | ||||
Repay | 10623871 | 1611 days ago | IN | 0 ETH | 0.01223044 | ||||
Repay | 10623652 | 1611 days ago | IN | 0 ETH | 0.01454634 | ||||
Process | 10594565 | 1615 days ago | IN | 0 ETH | 0.08395267 | ||||
Repay | 10593429 | 1615 days ago | IN | 0 ETH | 0.01192693 | ||||
Repay | 10593429 | 1615 days ago | IN | 0 ETH | 0.01192734 | ||||
Repay | 10591972 | 1616 days ago | IN | 0 ETH | 0.01354854 | ||||
Repay | 10591972 | 1616 days ago | IN | 0 ETH | 0.01442487 | ||||
Create Order | 10575979 | 1618 days ago | IN | 0 ETH | 0.02604411 | ||||
Create Order | 10543218 | 1623 days ago | IN | 0 ETH | 0.00517176 | ||||
Create Order | 10543217 | 1623 days ago | IN | 0 ETH | 0.00517176 | ||||
Create Order | 10543217 | 1623 days ago | IN | 0 ETH | 0.00516792 | ||||
Create Order | 10543199 | 1623 days ago | IN | 0 ETH | 0.00516888 | ||||
Create Order | 10543172 | 1623 days ago | IN | 0 ETH | 0.03972776 | ||||
Repay | 10537458 | 1624 days ago | IN | 0 ETH | 0.01005057 | ||||
Repay | 10518662 | 1627 days ago | IN | 0 ETH | 0.01091097 | ||||
Create Order | 10516585 | 1627 days ago | IN | 0 ETH | 0.0430964 | ||||
Create Order | 10510782 | 1628 days ago | IN | 0 ETH | 0.02791899 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
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
- No Contract Security Audit Submitted- Submit Audit Here
[{"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"}]
Contract Creation Code
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
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.