More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 51 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Collect | 8866602 | 1941 days ago | IN | 0 ETH | 0.00002346 | ||||
Collect | 8866601 | 1941 days ago | IN | 0 ETH | 0.00008396 | ||||
Collect | 8866599 | 1941 days ago | IN | 0 ETH | 0.00008395 | ||||
Collect | 8866596 | 1941 days ago | IN | 0 ETH | 0.00008395 | ||||
Collect | 8866594 | 1941 days ago | IN | 0 ETH | 0.00008395 | ||||
New Eth Backed L... | 8527786 | 1994 days ago | IN | 10.60738255 ETH | 0.00399898 | ||||
Collect | 8392002 | 2015 days ago | IN | 0 ETH | 0.00009319 | ||||
New Eth Backed L... | 8190579 | 2046 days ago | IN | 69.03038 ETH | 0.00016994 | ||||
Collect | 8117895 | 2058 days ago | IN | 0 ETH | 0.00033573 | ||||
New Eth Backed L... | 8040060 | 2070 days ago | IN | 0.06205 ETH | 0.00199949 | ||||
Collect | 7972229 | 2081 days ago | IN | 0 ETH | 0.00008393 | ||||
New Eth Backed L... | 7912761 | 2090 days ago | IN | 77.90406 ETH | 0.00033989 | ||||
New Eth Backed L... | 7893245 | 2093 days ago | IN | 0.07673 ETH | 0.00259933 | ||||
New Eth Backed L... | 7867813 | 2097 days ago | IN | 0.07183 ETH | 0.00239934 | ||||
New Eth Backed L... | 7840262 | 2101 days ago | IN | 2.98229 ETH | 0.00220933 | ||||
New Eth Backed L... | 7806294 | 2106 days ago | IN | 0.0723 ETH | 0.00067979 | ||||
New Eth Backed L... | 7806162 | 2106 days ago | IN | 0.0724 ETH | 0.00059983 | ||||
New Eth Backed L... | 7771962 | 2112 days ago | IN | 0.2432 ETH | 0.0036989 | ||||
New Eth Backed L... | 7768169 | 2112 days ago | IN | 5.0892 ETH | 0.00135959 | ||||
New Eth Backed L... | 7768012 | 2112 days ago | IN | 4.0368 ETH | 0.00050983 | ||||
Collect | 7763813 | 2113 days ago | IN | 0 ETH | 0.00092323 | ||||
New Eth Backed L... | 7655134 | 2130 days ago | IN | 4 ETH | 0.00050984 | ||||
New Eth Backed L... | 7655088 | 2130 days ago | IN | 5.1 ETH | 0.00056081 | ||||
New Eth Backed L... | 7635630 | 2133 days ago | IN | 0.11701 ETH | 0.00033989 | ||||
New Eth Backed L... | 7635579 | 2133 days ago | IN | 116.90217 ETH | 0.00033989 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
9882065 | 1776 days ago | 31.4 ETH | ||||
9823802 | 1785 days ago | 10 ETH | ||||
9619405 | 1817 days ago | 10.60738255 ETH | ||||
9468546 | 1840 days ago | 100 ETH | ||||
9369903 | 1855 days ago | 95 ETH | ||||
9278758 | 1869 days ago | 69.03038 ETH | ||||
9038815 | 1912 days ago | 77.90406 ETH | ||||
8882809 | 1938 days ago | 2.98229 ETH | ||||
8882766 | 1938 days ago | 4.0368 ETH | ||||
8882721 | 1938 days ago | 5.0892 ETH | ||||
8866601 | 1941 days ago | 6.36005713 ETH | ||||
8866601 | 1941 days ago | 63.60088182 ETH | ||||
8866601 | 1941 days ago | 46.95299104 ETH | ||||
8866599 | 1941 days ago | 6.36067813 ETH | ||||
8866599 | 1941 days ago | 63.60721604 ETH | ||||
8866599 | 1941 days ago | 46.95768581 ETH | ||||
8866596 | 1941 days ago | 6.35943612 ETH | ||||
8866596 | 1941 days ago | 63.59454759 ETH | ||||
8866596 | 1941 days ago | 46.94818627 ETH | ||||
8866594 | 1941 days ago | 0.00633422 ETH | ||||
8866594 | 1941 days ago | 0.06359063 ETH | ||||
8866594 | 1941 days ago | 0.04708514 ETH | ||||
8392002 | 2015 days ago | 0.30013482 ETH | ||||
8392002 | 2015 days ago | 3.00181722 ETH | ||||
8392002 | 2015 days ago | 5.68776795 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
LoanManager
Compiler Version
v0.4.24+commit.e67f0147
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2018-11-14 */ pragma solidity 0.4.24; // File: contracts/generic/Restricted.sol /* Generic contract to authorise calls to certain functions only from a given address. The address authorised must be a contract (multisig or not, depending on the permission), except for local test deployment works as: 1. contract deployer account deploys contracts 2. constructor grants "PermissionGranter" permission to deployer account 3. deployer account executes initial setup (no multiSig) 4. deployer account grants PermissionGranter permission for the MultiSig contract (e.g. StabilityBoardProxy or PreTokenProxy) 5. deployer account revokes its own PermissionGranter permission */ pragma solidity 0.4.24; contract Restricted { // NB: using bytes32 rather than the string type because it's cheaper gas-wise: mapping (address => mapping (bytes32 => bool)) public permissions; event PermissionGranted(address indexed agent, bytes32 grantedPermission); event PermissionRevoked(address indexed agent, bytes32 revokedPermission); modifier restrict(bytes32 requiredPermission) { require(permissions[msg.sender][requiredPermission], "msg.sender must have permission"); _; } constructor(address permissionGranterContract) public { require(permissionGranterContract != address(0), "permissionGranterContract must be set"); permissions[permissionGranterContract]["PermissionGranter"] = true; emit PermissionGranted(permissionGranterContract, "PermissionGranter"); } function grantPermission(address agent, bytes32 requiredPermission) public { require(permissions[msg.sender]["PermissionGranter"], "msg.sender must have PermissionGranter permission"); permissions[agent][requiredPermission] = true; emit PermissionGranted(agent, requiredPermission); } function grantMultiplePermissions(address agent, bytes32[] requiredPermissions) public { require(permissions[msg.sender]["PermissionGranter"], "msg.sender must have PermissionGranter permission"); uint256 length = requiredPermissions.length; for (uint256 i = 0; i < length; i++) { grantPermission(agent, requiredPermissions[i]); } } function revokePermission(address agent, bytes32 requiredPermission) public { require(permissions[msg.sender]["PermissionGranter"], "msg.sender must have PermissionGranter permission"); permissions[agent][requiredPermission] = false; emit PermissionRevoked(agent, requiredPermission); } function revokeMultiplePermissions(address agent, bytes32[] requiredPermissions) public { uint256 length = requiredPermissions.length; for (uint256 i = 0; i < length; i++) { revokePermission(agent, requiredPermissions[i]); } } } // File: contracts/generic/SafeMath.sol /** * @title SafeMath * @dev Math operations with safety checks that throw on error TODO: check against ds-math: https://blog.dapphub.com/ds-math/ TODO: move roundedDiv to a sep lib? (eg. Math.sol) TODO: more unit tests! */ pragma solidity 0.4.24; library SafeMath { function mul(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a * b; require(a == 0 || c / a == b, "mul overflow"); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "div by 0"); // Solidity automatically throws for div by 0 but require to emit reason uint256 c = a / b; // require(a == b * c + a % b); // There is no case in which this doesn't hold return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "sub underflow"); return a - b; } function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "add overflow"); return c; } // Division, round to nearest integer, round half up function roundedDiv(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "div by 0"); // Solidity automatically throws for div by 0 but require to emit reason uint256 halfB = (b % 2 == 0) ? (b / 2) : (b / 2 + 1); return (a % b >= halfB) ? (a / b + 1) : (a / b); } // Division, always rounds up function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "div by 0"); // Solidity automatically throws for div by 0 but require to emit reason return (a % b != 0) ? (a / b + 1) : (a / b); } function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } function max(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? b : a; } } // File: contracts/interfaces/TransferFeeInterface.sol /* * transfer fee calculation interface * */ pragma solidity 0.4.24; interface TransferFeeInterface { function calculateTransferFee(address from, address to, uint amount) external view returns (uint256 fee); } // File: contracts/interfaces/ERC20Interface.sol /* * ERC20 interface * see https://github.com/ethereum/EIPs/issues/20 */ pragma solidity 0.4.24; interface ERC20Interface { event Approval(address indexed _owner, address indexed _spender, uint _value); event Transfer(address indexed from, address indexed to, uint amount); function transfer(address to, uint value) external returns (bool); // solhint-disable-line no-simple-event-func-name function transferFrom(address from, address to, uint value) external returns (bool); function approve(address spender, uint value) external returns (bool); function balanceOf(address who) external view returns (uint); function allowance(address _owner, address _spender) external view returns (uint remaining); } // File: contracts/interfaces/TokenReceiver.sol /* * receiver contract interface * see https://github.com/ethereum/EIPs/issues/677 */ pragma solidity 0.4.24; interface TokenReceiver { function transferNotification(address from, uint256 amount, uint data) external; } // File: contracts/interfaces/AugmintTokenInterface.sol /* Augmint Token interface (abstract contract) TODO: overload transfer() & transferFrom() instead of transferWithNarrative() & transferFromWithNarrative() when this fix available in web3& truffle also uses that web3: https://github.com/ethereum/web3.js/pull/1185 TODO: shall we use bytes for narrative? */ pragma solidity 0.4.24; contract AugmintTokenInterface is Restricted, ERC20Interface { using SafeMath for uint256; string public name; string public symbol; bytes32 public peggedSymbol; uint8 public decimals; uint public totalSupply; mapping(address => uint256) public balances; // Balances for each account mapping(address => mapping (address => uint256)) public allowed; // allowances added with approve() TransferFeeInterface public feeAccount; mapping(bytes32 => bool) public delegatedTxHashesUsed; // record txHashes used by delegatedTransfer event TransferFeesChanged(uint transferFeePt, uint transferFeeMin, uint transferFeeMax); event Transfer(address indexed from, address indexed to, uint amount); event AugmintTransfer(address indexed from, address indexed to, uint amount, string narrative, uint fee); event TokenIssued(uint amount); event TokenBurned(uint amount); event Approval(address indexed _owner, address indexed _spender, uint256 _value); function transfer(address to, uint value) external returns (bool); // solhint-disable-line no-simple-event-func-name function transferFrom(address from, address to, uint value) external returns (bool); function approve(address spender, uint value) external returns (bool); function delegatedTransfer(address from, address to, uint amount, string narrative, uint maxExecutorFeeInToken, /* client provided max fee for executing the tx */ bytes32 nonce, /* random nonce generated by client */ /* ^^^^ end of signed data ^^^^ */ bytes signature, uint requestedExecutorFeeInToken /* the executor can decide to request lower fee */ ) external; function delegatedTransferAndNotify(address from, TokenReceiver target, uint amount, uint data, uint maxExecutorFeeInToken, /* client provided max fee for executing the tx */ bytes32 nonce, /* random nonce generated by client */ /* ^^^^ end of signed data ^^^^ */ bytes signature, uint requestedExecutorFeeInToken /* the executor can decide to request lower fee */ ) external; function increaseApproval(address spender, uint addedValue) external; function decreaseApproval(address spender, uint subtractedValue) external; function issueTo(address to, uint amount) external; // restrict it to "MonetarySupervisor" in impl.; function burn(uint amount) external; function transferAndNotify(TokenReceiver target, uint amount, uint data) external; function transferWithNarrative(address to, uint256 amount, string narrative) external; function transferFromWithNarrative(address from, address to, uint256 amount, string narrative) external; function setName(string _name) external; function setSymbol(string _symbol) external; function allowance(address owner, address spender) external view returns (uint256 remaining); function balanceOf(address who) external view returns (uint); } // File: contracts/generic/ECRecovery.sol /** * @title Eliptic curve signature operations * * @dev Based on https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/ECRecovery.sol * * TODO Remove this library once solidity supports passing a signature to ecrecover. * See https://github.com/ethereum/solidity/issues/864 * */ library ECRecovery { /** * @dev Recover signer address from a message by using their signature * @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address. * @param sig bytes signature, the signature is generated using web3.eth.sign() */ function recover(bytes32 hash, bytes sig) internal pure returns (address) { bytes32 r; bytes32 s; uint8 v; // Check the signature length if (sig.length != 65) { return (address(0)); } // Divide the signature in r, s and v variables // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. // solium-disable-next-line security/no-inline-assembly assembly { r := mload(add(sig, 32)) s := mload(add(sig, 64)) v := byte(0, mload(add(sig, 96))) } // Version of signature should be 27 or 28, but 0 and 1 are also possible versions if (v < 27) { v += 27; } // If the version is correct return the signer address if (v != 27 && v != 28) { return (address(0)); } else { // solium-disable-next-line arg-overflow return ecrecover(hash, v, r, s); } } /** * toEthSignedMessageHash * @dev prefix a bytes32 value with "\x19Ethereum Signed Message:" * @dev and hash the result */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } } // File: contracts/generic/AugmintToken.sol /* Generic Augmint Token implementation (ERC20 token) This contract manages: * Balances of Augmint holders and transactions between them * Issues/burns tokens TODO: - reconsider delegatedTransfer and how to structure it - shall we allow change of txDelegator? - consider generic bytes arg instead of uint for transferAndNotify - consider separate transfer fee params and calculation to separate contract (to feeAccount?) */ pragma solidity 0.4.24; contract AugmintToken is AugmintTokenInterface { event FeeAccountChanged(TransferFeeInterface newFeeAccount); constructor(address permissionGranterContract, string _name, string _symbol, bytes32 _peggedSymbol, uint8 _decimals, TransferFeeInterface _feeAccount) public Restricted(permissionGranterContract) { require(_feeAccount != address(0), "feeAccount must be set"); require(bytes(_name).length > 0, "name must be set"); require(bytes(_symbol).length > 0, "symbol must be set"); name = _name; symbol = _symbol; peggedSymbol = _peggedSymbol; decimals = _decimals; feeAccount = _feeAccount; } function transfer(address to, uint256 amount) external returns (bool) { _transfer(msg.sender, to, amount, ""); return true; } /* Transfers based on an offline signed transfer instruction. */ function delegatedTransfer(address from, address to, uint amount, string narrative, uint maxExecutorFeeInToken, /* client provided max fee for executing the tx */ bytes32 nonce, /* random nonce generated by client */ /* ^^^^ end of signed data ^^^^ */ bytes signature, uint requestedExecutorFeeInToken /* the executor can decide to request lower fee */ ) external { bytes32 txHash = keccak256(abi.encodePacked(this, from, to, amount, narrative, maxExecutorFeeInToken, nonce)); _checkHashAndTransferExecutorFee(txHash, signature, from, maxExecutorFeeInToken, requestedExecutorFeeInToken); _transfer(from, to, amount, narrative); } function approve(address _spender, uint256 amount) external returns (bool) { require(_spender != 0x0, "spender must be set"); allowed[msg.sender][_spender] = amount; emit Approval(msg.sender, _spender, amount); return true; } /** ERC20 transferFrom attack protection: https://github.com/DecentLabs/dcm-poc/issues/57 approve should be called when allowed[_spender] == 0. To increment allowed value is better to use this function to avoid 2 calls (and wait until the first transaction is mined) Based on MonolithDAO Token.sol */ function increaseApproval(address _spender, uint _addedValue) external { require(_spender != 0x0, "spender must be set"); mapping (address => uint256) allowances = allowed[msg.sender]; uint newValue = allowances[_spender].add(_addedValue); allowances[_spender] = newValue; emit Approval(msg.sender, _spender, newValue); } function decreaseApproval(address _spender, uint _subtractedValue) external { require(_spender != 0x0, "spender must be set"); uint oldValue = allowed[msg.sender][_spender]; if (_subtractedValue > oldValue) { allowed[msg.sender][_spender] = 0; } else { allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue); } emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); } function transferFrom(address from, address to, uint256 amount) external returns (bool) { _transferFrom(from, to, amount, ""); return true; } // Issue tokens. See MonetarySupervisor but as a rule of thumb issueTo is only allowed: // - on new loan (by trusted Lender contracts) // - when converting old tokens using MonetarySupervisor // - strictly to reserve by Stability Board (via MonetarySupervisor) function issueTo(address to, uint amount) external restrict("MonetarySupervisor") { balances[to] = balances[to].add(amount); totalSupply = totalSupply.add(amount); emit Transfer(0x0, to, amount); emit AugmintTransfer(0x0, to, amount, "", 0); } // Burn tokens. Anyone can burn from its own account. YOLO. // Used by to burn from Augmint reserve or by Lender contract after loan repayment function burn(uint amount) external { require(balances[msg.sender] >= amount, "balance must be >= amount"); balances[msg.sender] = balances[msg.sender].sub(amount); totalSupply = totalSupply.sub(amount); emit Transfer(msg.sender, 0x0, amount); emit AugmintTransfer(msg.sender, 0x0, amount, "", 0); } /* to upgrade feeAccount (eg. for fee calculation changes) */ function setFeeAccount(TransferFeeInterface newFeeAccount) external restrict("StabilityBoard") { feeAccount = newFeeAccount; emit FeeAccountChanged(newFeeAccount); } /* transferAndNotify can be used by contracts which require tokens to have only 1 tx (instead of approve + call) Eg. repay loan, lock funds, token sell order on exchange Reverts on failue: - transfer fails - if transferNotification fails (callee must revert on failure) - if targetContract is an account or targetContract doesn't have neither transferNotification or fallback fx TODO: make data param generic bytes (see receiver code attempt in Locker.transferNotification) */ function transferAndNotify(TokenReceiver target, uint amount, uint data) external { _transfer(msg.sender, target, amount, ""); target.transferNotification(msg.sender, amount, data); } /* transferAndNotify based on an instruction signed offline */ function delegatedTransferAndNotify(address from, TokenReceiver target, uint amount, uint data, uint maxExecutorFeeInToken, /* client provided max fee for executing the tx */ bytes32 nonce, /* random nonce generated by client */ /* ^^^^ end of signed data ^^^^ */ bytes signature, uint requestedExecutorFeeInToken /* the executor can decide to request lower fee */ ) external { bytes32 txHash = keccak256(abi.encodePacked(this, from, target, amount, data, maxExecutorFeeInToken, nonce)); _checkHashAndTransferExecutorFee(txHash, signature, from, maxExecutorFeeInToken, requestedExecutorFeeInToken); _transfer(from, target, amount, ""); target.transferNotification(from, amount, data); } function transferWithNarrative(address to, uint256 amount, string narrative) external { _transfer(msg.sender, to, amount, narrative); } function transferFromWithNarrative(address from, address to, uint256 amount, string narrative) external { _transferFrom(from, to, amount, narrative); } /* Allow Stability Board to change the name when a new token contract version is deployed and ready for production use. So that older token contracts are identifiable in 3rd party apps. */ function setName(string _name) external restrict("StabilityBoard") { name = _name; } /* Allow Stability Board to change the symbol when a new token contract version is deployed and ready for production use. So that older token contracts are identifiable in 3rd party apps. */ function setSymbol(string _symbol) external restrict("StabilityBoard") { symbol = _symbol; } function balanceOf(address _owner) external view returns (uint256 balance) { return balances[_owner]; } function allowance(address _owner, address _spender) external view returns (uint256 remaining) { return allowed[_owner][_spender]; } function _checkHashAndTransferExecutorFee(bytes32 txHash, bytes signature, address signer, uint maxExecutorFeeInToken, uint requestedExecutorFeeInToken) private { require(requestedExecutorFeeInToken <= maxExecutorFeeInToken, "requestedExecutorFee must be <= maxExecutorFee"); require(!delegatedTxHashesUsed[txHash], "txHash already used"); delegatedTxHashesUsed[txHash] = true; address recovered = ECRecovery.recover(ECRecovery.toEthSignedMessageHash(txHash), signature); require(recovered == signer, "invalid signature"); _transfer(signer, msg.sender, requestedExecutorFeeInToken, "Delegated transfer fee", 0); } function _transferFrom(address from, address to, uint256 amount, string narrative) private { uint fee = feeAccount.calculateTransferFee(from, to, amount); uint amountWithFee = amount.add(fee); /* NB: fee is deducted from owner, so transferFrom could fail if amount + fee is not available on owner balance, or allowance */ require(balances[from] >= amountWithFee, "balance must be >= amount + fee"); require(allowed[from][msg.sender] >= amountWithFee, "allowance must be >= amount + fee"); _transfer(from, to, amount, narrative, fee); allowed[from][msg.sender] = allowed[from][msg.sender].sub(amountWithFee); } function _transfer(address from, address to, uint transferAmount, string narrative) private { uint fee = feeAccount.calculateTransferFee(from, to, transferAmount); _transfer(from, to, transferAmount, narrative, fee); } function _transfer(address from, address to, uint transferAmount, string narrative, uint fee) private { require(to != 0x0, "to must be set"); uint amountWithFee = transferAmount.add(fee); // to emit proper reason instead of failing on from.sub() require(balances[from] >= amountWithFee, "balance must be >= amount + transfer fee"); balances[from] = balances[from].sub(amountWithFee); balances[to] = balances[to].add(transferAmount); emit Transfer(from, to, transferAmount); if (fee > 0) { balances[feeAccount] = balances[feeAccount].add(fee); emit Transfer(from, feeAccount, fee); } emit AugmintTransfer(from, to, transferAmount, narrative, fee); } } // File: contracts/generic/SystemAccount.sol /* Contract to collect fees from system */ pragma solidity 0.4.24; contract SystemAccount is Restricted { event WithdrawFromSystemAccount(address tokenAddress, address to, uint tokenAmount, uint weiAmount, string narrative); constructor(address permissionGranterContract) public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks function withdraw(AugmintToken tokenAddress, address to, uint tokenAmount, uint weiAmount, string narrative) external restrict("StabilityBoard") { tokenAddress.transferWithNarrative(to, tokenAmount, narrative); if (weiAmount > 0) { to.transfer(weiAmount); } emit WithdrawFromSystemAccount(tokenAddress, to, tokenAmount, weiAmount, narrative); } } // File: contracts/AugmintReserves.sol /* Contract to hold Augmint reserves (ETH & Token) - ETH as regular ETH balance of the contract - ERC20 token reserve (stored as regular Token balance under the contract address) NB: reserves are held under the contract address, therefore any transaction on the reserve is limited to the tx-s defined here (i.e. transfer is not allowed even by the contract owner or StabilityBoard or MonetarySupervisor) */ pragma solidity 0.4.24; contract AugmintReserves is Restricted { event ReserveMigration(address to, uint weiAmount); constructor(address permissionGranterContract) public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks function () external payable { // solhint-disable-line no-empty-blocks // to accept ETH sent into reserve (from defaulted loan's collateral ) } function burn(AugmintTokenInterface augmintToken, uint amount) external restrict("MonetarySupervisor") { augmintToken.burn(amount); } function migrate(address to, uint weiAmount) external restrict("StabilityBoard") { if (weiAmount > 0) { to.transfer(weiAmount); } emit ReserveMigration(to, weiAmount); } } // File: contracts/InterestEarnedAccount.sol /* Contract to hold earned interest from loans repaid premiums for locks are being accrued (i.e. transferred) to Locker */ pragma solidity 0.4.24; contract InterestEarnedAccount is SystemAccount { constructor(address permissionGranterContract) public SystemAccount(permissionGranterContract) {} // solhint-disable-line no-empty-blocks function transferInterest(AugmintTokenInterface augmintToken, address locker, uint interestAmount) external restrict("MonetarySupervisor") { augmintToken.transfer(locker, interestAmount); } } // File: contracts/MonetarySupervisor.sol /* MonetarySupervisor - maintains system wide KPIs (eg totalLockAmount, totalLoanAmount) - holds system wide parameters/limits - enforces system wide limits - burns and issues to AugmintReserves - Send funds from reserve to exchange when intervening (not implemented yet) - Converts older versions of AugmintTokens in 1:1 to new */ pragma solidity 0.4.24; contract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-line no-empty-blocks using SafeMath for uint256; uint public constant PERCENT_100 = 1000000; AugmintTokenInterface public augmintToken; InterestEarnedAccount public interestEarnedAccount; AugmintReserves public augmintReserves; uint public issuedByStabilityBoard; // token issued by Stability Board uint public burnedByStabilityBoard; // token burned by Stability Board uint public totalLoanAmount; // total amount of all loans without interest, in token uint public totalLockedAmount; // total amount of all locks without premium, in token /********** Parameters to ensure totalLoanAmount or totalLockedAmount difference is within limits and system also works when total loan or lock amounts are low. for test calculations: https://docs.google.com/spreadsheets/d/1MeWYPYZRIm1n9lzpvbq8kLfQg1hhvk5oJY6NrR401S0 **********/ struct LtdParams { uint lockDifferenceLimit; /* only allow a new lock if Loan To Deposit ratio would stay above (1 - lockDifferenceLimit) with new lock. Stored as parts per million */ uint loanDifferenceLimit; /* only allow a new loan if Loan To Deposit ratio would stay above (1 + loanDifferenceLimit) with new loan. Stored as parts per million */ /* allowedDifferenceAmount param is to ensure the system is not "freezing" when totalLoanAmount or totalLockAmount is low. It allows a new loan or lock (up to an amount to reach this difference) even if LTD will go below / above lockDifferenceLimit / loanDifferenceLimit with the new lock/loan */ uint allowedDifferenceAmount; } LtdParams public ltdParams; /* Previously deployed AugmintTokens which are accepted for conversion (see transferNotification() ) NB: it's not iterable so old version addresses needs to be added for UI manually after each deploy */ mapping(address => bool) public acceptedLegacyAugmintTokens; event LtdParamsChanged(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount); event AcceptedLegacyAugmintTokenChanged(address augmintTokenAddress, bool newAcceptedState); event LegacyTokenConverted(address oldTokenAddress, address account, uint amount); event KPIsAdjusted(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment); event SystemContractsChanged(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves); constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken, AugmintReserves _augmintReserves, InterestEarnedAccount _interestEarnedAccount, uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount) public Restricted(permissionGranterContract) { augmintToken = _augmintToken; augmintReserves = _augmintReserves; interestEarnedAccount = _interestEarnedAccount; ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount); } function issueToReserve(uint amount) external restrict("StabilityBoard") { issuedByStabilityBoard = issuedByStabilityBoard.add(amount); augmintToken.issueTo(augmintReserves, amount); } function burnFromReserve(uint amount) external restrict("StabilityBoard") { burnedByStabilityBoard = burnedByStabilityBoard.add(amount); augmintReserves.burn(augmintToken, amount); } /* Locker requesting interest when locking funds. Enforcing LTD to stay within range allowed by LTD params NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */ function requestInterest(uint amountToLock, uint interestAmount) external { // only whitelisted Locker require(permissions[msg.sender]["Locker"], "msg.sender must have Locker permission"); require(amountToLock <= getMaxLockAmountAllowedByLtd(), "amountToLock must be <= maxLockAmountAllowedByLtd"); totalLockedAmount = totalLockedAmount.add(amountToLock); // next line would revert but require to emit reason: require(augmintToken.balanceOf(address(interestEarnedAccount)) >= interestAmount, "interestEarnedAccount balance must be >= interestAmount"); interestEarnedAccount.transferInterest(augmintToken, msg.sender, interestAmount); // transfer interest to Locker } // Locker notifying when releasing funds to update KPIs function releaseFundsNotification(uint lockedAmount) external { // only whitelisted Locker require(permissions[msg.sender]["Locker"], "msg.sender must have Locker permission"); totalLockedAmount = totalLockedAmount.sub(lockedAmount); } /* Issue loan if LTD stays within range allowed by LTD params NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */ function issueLoan(address borrower, uint loanAmount) external { // only whitelisted LoanManager contracts require(permissions[msg.sender]["LoanManager"], "msg.sender must have LoanManager permission"); require(loanAmount <= getMaxLoanAmountAllowedByLtd(), "loanAmount must be <= maxLoanAmountAllowedByLtd"); totalLoanAmount = totalLoanAmount.add(loanAmount); augmintToken.issueTo(borrower, loanAmount); } function loanRepaymentNotification(uint loanAmount) external { // only whitelisted LoanManager contracts require(permissions[msg.sender]["LoanManager"], "msg.sender must have LoanManager permission"); totalLoanAmount = totalLoanAmount.sub(loanAmount); } // NB: this is called by Lender contract with the sum of all loans collected in batch function loanCollectionNotification(uint totalLoanAmountCollected) external { // only whitelisted LoanManager contracts require(permissions[msg.sender]["LoanManager"], "msg.sender must have LoanManager permission"); totalLoanAmount = totalLoanAmount.sub(totalLoanAmountCollected); } function setAcceptedLegacyAugmintToken(address legacyAugmintTokenAddress, bool newAcceptedState) external restrict("StabilityBoard") { acceptedLegacyAugmintTokens[legacyAugmintTokenAddress] = newAcceptedState; emit AcceptedLegacyAugmintTokenChanged(legacyAugmintTokenAddress, newAcceptedState); } function setLtdParams(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount) external restrict("StabilityBoard") { ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount); emit LtdParamsChanged(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount); } /* function to migrate old totalLoanAmount and totalLockedAmount from old monetarySupervisor contract when it's upgraded. Set new monetarySupervisor contract in all locker and loanManager contracts before executing this */ function adjustKPIs(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment) external restrict("StabilityBoard") { totalLoanAmount = totalLoanAmount.add(totalLoanAmountAdjustment); totalLockedAmount = totalLockedAmount.add(totalLockedAmountAdjustment); emit KPIsAdjusted(totalLoanAmountAdjustment, totalLockedAmountAdjustment); } /* to allow upgrades of InterestEarnedAccount and AugmintReserves contracts. */ function setSystemContracts(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves) external restrict("StabilityBoard") { interestEarnedAccount = newInterestEarnedAccount; augmintReserves = newAugmintReserves; emit SystemContractsChanged(newInterestEarnedAccount, newAugmintReserves); } /* User can request to convert their tokens from older AugmintToken versions in 1:1 transferNotification is called from AugmintToken's transferAndNotify Flow for converting old tokens: 1) user calls old token contract's transferAndNotify with the amount to convert, addressing the new MonetarySupervisor Contract 2) transferAndNotify transfers user's old tokens to the current MonetarySupervisor contract's address 3) transferAndNotify calls MonetarySupervisor.transferNotification 4) MonetarySupervisor checks if old AugmintToken is permitted 5) MonetarySupervisor issues new tokens to user's account in current AugmintToken 6) MonetarySupervisor burns old tokens from own balance */ function transferNotification(address from, uint amount, uint /* data, not used */ ) external { AugmintTokenInterface legacyToken = AugmintTokenInterface(msg.sender); require(acceptedLegacyAugmintTokens[legacyToken], "msg.sender must be allowed in acceptedLegacyAugmintTokens"); legacyToken.burn(amount); augmintToken.issueTo(from, amount); emit LegacyTokenConverted(msg.sender, from, amount); } /* Helper function for UI. Returns max lock amount based on minLockAmount, interestPt, using LTD params & interestEarnedAccount balance */ function getMaxLockAmount(uint minLockAmount, uint interestPt) external view returns (uint maxLock) { uint allowedByEarning = augmintToken.balanceOf(address(interestEarnedAccount)).mul(PERCENT_100).div(interestPt); uint allowedByLtd = getMaxLockAmountAllowedByLtd(); maxLock = allowedByEarning < allowedByLtd ? allowedByEarning : allowedByLtd; maxLock = maxLock < minLockAmount ? 0 : maxLock; } /* Helper function for UI. Returns max loan amount based on minLoanAmont using LTD params */ function getMaxLoanAmount(uint minLoanAmount) external view returns (uint maxLoan) { uint allowedByLtd = getMaxLoanAmountAllowedByLtd(); maxLoan = allowedByLtd < minLoanAmount ? 0 : allowedByLtd; } /* returns maximum lockable token amount allowed by LTD params. */ function getMaxLockAmountAllowedByLtd() public view returns(uint maxLockByLtd) { uint allowedByLtdDifferencePt = totalLoanAmount.mul(PERCENT_100).div(PERCENT_100 .sub(ltdParams.lockDifferenceLimit)); allowedByLtdDifferencePt = totalLockedAmount >= allowedByLtdDifferencePt ? 0 : allowedByLtdDifferencePt.sub(totalLockedAmount); uint allowedByLtdDifferenceAmount = totalLockedAmount >= totalLoanAmount.add(ltdParams.allowedDifferenceAmount) ? 0 : totalLoanAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLockedAmount); maxLockByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ? allowedByLtdDifferencePt : allowedByLtdDifferenceAmount; } /* returns maximum borrowable token amount allowed by LTD params */ function getMaxLoanAmountAllowedByLtd() public view returns(uint maxLoanByLtd) { uint allowedByLtdDifferencePt = totalLockedAmount.mul(ltdParams.loanDifferenceLimit.add(PERCENT_100)) .div(PERCENT_100); allowedByLtdDifferencePt = totalLoanAmount >= allowedByLtdDifferencePt ? 0 : allowedByLtdDifferencePt.sub(totalLoanAmount); uint allowedByLtdDifferenceAmount = totalLoanAmount >= totalLockedAmount.add(ltdParams.allowedDifferenceAmount) ? 0 : totalLockedAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLoanAmount); maxLoanByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ? allowedByLtdDifferencePt : allowedByLtdDifferenceAmount; } } // File: contracts/Rates.sol /* Generic symbol / WEI rates contract. only callable by trusted price oracles. Being regularly called by a price oracle TODO: trustless/decentrilezed price Oracle TODO: shall we use blockNumber instead of now for lastUpdated? TODO: consider if we need storing rates with variable decimals instead of fixed 4 TODO: could we emit 1 RateChanged event from setMultipleRates (symbols and newrates arrays)? */ pragma solidity 0.4.24; contract Rates is Restricted { using SafeMath for uint256; struct RateInfo { uint rate; // how much 1 WEI worth 1 unit , i.e. symbol/ETH rate // 0 rate means no rate info available uint lastUpdated; } // mapping currency symbol => rate. all rates are stored with 2 decimals. i.e. EUR/ETH = 989.12 then rate = 98912 mapping(bytes32 => RateInfo) public rates; event RateChanged(bytes32 symbol, uint newRate); constructor(address permissionGranterContract) public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks function setRate(bytes32 symbol, uint newRate) external restrict("RatesFeeder") { rates[symbol] = RateInfo(newRate, now); emit RateChanged(symbol, newRate); } function setMultipleRates(bytes32[] symbols, uint[] newRates) external restrict("RatesFeeder") { require(symbols.length == newRates.length, "symobls and newRates lengths must be equal"); for (uint256 i = 0; i < symbols.length; i++) { rates[symbols[i]] = RateInfo(newRates[i], now); emit RateChanged(symbols[i], newRates[i]); } } function convertFromWei(bytes32 bSymbol, uint weiValue) external view returns(uint value) { require(rates[bSymbol].rate > 0, "rates[bSymbol] must be > 0"); return weiValue.mul(rates[bSymbol].rate).roundedDiv(1000000000000000000); } function convertToWei(bytes32 bSymbol, uint value) external view returns(uint weiValue) { // next line would revert with div by zero but require to emit reason require(rates[bSymbol].rate > 0, "rates[bSymbol] must be > 0"); /* TODO: can we make this not loosing max scale? */ return value.mul(1000000000000000000).roundedDiv(rates[bSymbol].rate); } } // File: contracts/LoanManager.sol /* Contract to manage Augmint token loan contracts backed by ETH For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/loanFlow.png TODO: - create MonetarySupervisor interface and use it instead? - make data arg generic bytes? - make collect() run as long as gas provided allows */ pragma solidity 0.4.24; contract LoanManager is Restricted, TokenReceiver { using SafeMath for uint256; enum LoanState { Open, Repaid, Defaulted, Collected } // NB: Defaulted state is not stored, only getters calculate struct LoanProduct { uint minDisbursedAmount; // 0: with decimals set in AugmintToken.decimals uint32 term; // 1 uint32 discountRate; // 2: discountRate in parts per million , ie. 10,000 = 1% uint32 collateralRatio; // 3: loan token amount / colleteral pegged ccy value // in parts per million , ie. 10,000 = 1% uint32 defaultingFeePt; // 4: % of collateral in parts per million , ie. 50,000 = 5% bool isActive; // 5 } /* NB: we don't need to store loan parameters because loan products can't be altered (only disabled/enabled) */ struct LoanData { uint collateralAmount; // 0 uint repaymentAmount; // 1 address borrower; // 2 uint32 productId; // 3 LoanState state; // 4 uint40 maturity; // 5 } LoanProduct[] public products; LoanData[] public loans; mapping(address => uint[]) public accountLoans; // owner account address => array of loan Ids Rates public rates; // instance of ETH/pegged currency rate provider contract AugmintTokenInterface public augmintToken; // instance of token contract MonetarySupervisor public monetarySupervisor; event NewLoan(uint32 productId, uint loanId, address indexed borrower, uint collateralAmount, uint loanAmount, uint repaymentAmount, uint40 maturity); event LoanProductActiveStateChanged(uint32 productId, bool newState); event LoanProductAdded(uint32 productId); event LoanRepayed(uint loanId, address borrower); event LoanCollected(uint loanId, address indexed borrower, uint collectedCollateral, uint releasedCollateral, uint defaultingFee); event SystemContractsChanged(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor); constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken, MonetarySupervisor _monetarySupervisor, Rates _rates) public Restricted(permissionGranterContract) { augmintToken = _augmintToken; monetarySupervisor = _monetarySupervisor; rates = _rates; } function addLoanProduct(uint32 term, uint32 discountRate, uint32 collateralRatio, uint minDisbursedAmount, uint32 defaultingFeePt, bool isActive) external restrict("StabilityBoard") { uint _newProductId = products.push( LoanProduct(minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, isActive) ) - 1; uint32 newProductId = uint32(_newProductId); require(newProductId == _newProductId, "productId overflow"); emit LoanProductAdded(newProductId); } function setLoanProductActiveState(uint32 productId, bool newState) external restrict ("StabilityBoard") { require(productId < products.length, "invalid productId"); // next line would revert but require to emit reason products[productId].isActive = newState; emit LoanProductActiveStateChanged(productId, newState); } function newEthBackedLoan(uint32 productId) external payable { require(productId < products.length, "invalid productId"); // next line would revert but require to emit reason LoanProduct storage product = products[productId]; require(product.isActive, "product must be in active state"); // valid product // calculate loan values based on ETH sent in with Tx uint tokenValue = rates.convertFromWei(augmintToken.peggedSymbol(), msg.value); uint repaymentAmount = tokenValue.mul(product.collateralRatio).div(1000000); uint loanAmount; (loanAmount, ) = calculateLoanValues(product, repaymentAmount); require(loanAmount >= product.minDisbursedAmount, "loanAmount must be >= minDisbursedAmount"); uint expiration = now.add(product.term); uint40 maturity = uint40(expiration); require(maturity == expiration, "maturity overflow"); // Create new loan uint loanId = loans.push(LoanData(msg.value, repaymentAmount, msg.sender, productId, LoanState.Open, maturity)) - 1; // Store ref to new loan accountLoans[msg.sender].push(loanId); // Issue tokens and send to borrower monetarySupervisor.issueLoan(msg.sender, loanAmount); emit NewLoan(productId, loanId, msg.sender, msg.value, loanAmount, repaymentAmount, maturity); } /* repay loan, called from AugmintToken's transferAndNotify Flow for repaying loan: 1) user calls token contract's transferAndNotify loanId passed in data arg 2) transferAndNotify transfers tokens to the Lender contract 3) transferAndNotify calls Lender.transferNotification with lockProductId */ // from arg is not used as we allow anyone to repay a loan: function transferNotification(address, uint repaymentAmount, uint loanId) external { require(msg.sender == address(augmintToken), "msg.sender must be augmintToken"); _repayLoan(loanId, repaymentAmount); } function collect(uint[] loanIds) external { /* when there are a lots of loans to be collected then the client need to call it in batches to make sure tx won't exceed block gas limit. Anyone can call it - can't cause harm as it only allows to collect loans which they are defaulted TODO: optimise defaulting fee calculations */ uint totalLoanAmountCollected; uint totalCollateralToCollect; uint totalDefaultingFee; for (uint i = 0; i < loanIds.length; i++) { require(loanIds[i] < loans.length, "invalid loanId"); // next line would revert but require to emit reason LoanData storage loan = loans[loanIds[i]]; require(loan.state == LoanState.Open, "loan state must be Open"); require(now >= loan.maturity, "current time must be later than maturity"); LoanProduct storage product = products[loan.productId]; uint loanAmount; (loanAmount, ) = calculateLoanValues(product, loan.repaymentAmount); totalLoanAmountCollected = totalLoanAmountCollected.add(loanAmount); loan.state = LoanState.Collected; // send ETH collateral to augmintToken reserve uint defaultingFeeInToken = loan.repaymentAmount.mul(product.defaultingFeePt).div(1000000); uint defaultingFee = rates.convertToWei(augmintToken.peggedSymbol(), defaultingFeeInToken); uint targetCollection = rates.convertToWei(augmintToken.peggedSymbol(), loan.repaymentAmount).add(defaultingFee); uint releasedCollateral; if (targetCollection < loan.collateralAmount) { releasedCollateral = loan.collateralAmount.sub(targetCollection); loan.borrower.transfer(releasedCollateral); } uint collateralToCollect = loan.collateralAmount.sub(releasedCollateral); if (defaultingFee >= collateralToCollect) { defaultingFee = collateralToCollect; collateralToCollect = 0; } else { collateralToCollect = collateralToCollect.sub(defaultingFee); } totalDefaultingFee = totalDefaultingFee.add(defaultingFee); totalCollateralToCollect = totalCollateralToCollect.add(collateralToCollect); emit LoanCollected(loanIds[i], loan.borrower, collateralToCollect.add(defaultingFee), releasedCollateral, defaultingFee); } if (totalCollateralToCollect > 0) { address(monetarySupervisor.augmintReserves()).transfer(totalCollateralToCollect); } if (totalDefaultingFee > 0) { address(augmintToken.feeAccount()).transfer(totalDefaultingFee); } monetarySupervisor.loanCollectionNotification(totalLoanAmountCollected);// update KPIs } /* to allow upgrade of Rates and MonetarySupervisor contracts */ function setSystemContracts(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor) external restrict("StabilityBoard") { rates = newRatesContract; monetarySupervisor = newMonetarySupervisor; emit SystemContractsChanged(newRatesContract, newMonetarySupervisor); } function getProductCount() external view returns (uint) { return products.length; } // returns <chunkSize> loan products starting from some <offset>: // [ productId, minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, maxLoanAmount, isActive ] function getProducts(uint offset, uint16 chunkSize) external view returns (uint[8][]) { uint limit = SafeMath.min(offset.add(chunkSize), products.length); uint[8][] memory response = new uint[8][](limit.sub(offset)); for (uint i = offset; i < limit; i++) { LoanProduct storage product = products[i]; response[i - offset] = [i, product.minDisbursedAmount, product.term, product.discountRate, product.collateralRatio, product.defaultingFeePt, monetarySupervisor.getMaxLoanAmount(product.minDisbursedAmount), product.isActive ? 1 : 0 ]; } return response; } function getLoanCount() external view returns (uint) { return loans.length; } /* returns <chunkSize> loans starting from some <offset>. Loans data encoded as: [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime, loanAmount, interestAmount] */ function getLoans(uint offset, uint16 chunkSize) external view returns (uint[10][]) { uint limit = SafeMath.min(offset.add(chunkSize), loans.length); uint[10][] memory response = new uint[10][](limit.sub(offset)); for (uint i = offset; i < limit; i++) { response[i - offset] = getLoanTuple(i); } return response; } function getLoanCountForAddress(address borrower) external view returns (uint) { return accountLoans[borrower].length; } /* returns <chunkSize> loans of a given account, starting from some <offset>. Loans data encoded as: [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime, loanAmount, interestAmount ] */ function getLoansForAddress(address borrower, uint offset, uint16 chunkSize) external view returns (uint[10][]) { uint[] storage loansForAddress = accountLoans[borrower]; uint limit = SafeMath.min(offset.add(chunkSize), loansForAddress.length); uint[10][] memory response = new uint[10][](limit.sub(offset)); for (uint i = offset; i < limit; i++) { response[i - offset] = getLoanTuple(loansForAddress[i]); } return response; } function getLoanTuple(uint loanId) public view returns (uint[10] result) { require(loanId < loans.length, "invalid loanId"); // next line would revert but require to emit reason LoanData storage loan = loans[loanId]; LoanProduct storage product = products[loan.productId]; uint loanAmount; uint interestAmount; (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount); uint disbursementTime = loan.maturity - product.term; LoanState loanState = loan.state == LoanState.Open && now >= loan.maturity ? LoanState.Defaulted : loan.state; result = [loanId, loan.collateralAmount, loan.repaymentAmount, uint(loan.borrower), loan.productId, uint(loanState), loan.maturity, disbursementTime, loanAmount, interestAmount]; } function calculateLoanValues(LoanProduct storage product, uint repaymentAmount) internal view returns (uint loanAmount, uint interestAmount) { // calculate loan values based on repayment amount loanAmount = repaymentAmount.mul(product.discountRate).div(1000000); interestAmount = loanAmount > repaymentAmount ? 0 : repaymentAmount.sub(loanAmount); } /* internal function, assuming repayment amount already transfered */ function _repayLoan(uint loanId, uint repaymentAmount) internal { require(loanId < loans.length, "invalid loanId"); // next line would revert but require to emit reason LoanData storage loan = loans[loanId]; require(loan.state == LoanState.Open, "loan state must be Open"); require(repaymentAmount == loan.repaymentAmount, "repaymentAmount must be equal to tokens sent"); require(now <= loan.maturity, "current time must be earlier than maturity"); LoanProduct storage product = products[loan.productId]; uint loanAmount; uint interestAmount; (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount); loans[loanId].state = LoanState.Repaid; if (interestAmount > 0) { augmintToken.transfer(monetarySupervisor.interestEarnedAccount(), interestAmount); augmintToken.burn(loanAmount); } else { // negative or zero interest (i.e. discountRate >= 0) augmintToken.burn(repaymentAmount); } monetarySupervisor.loanRepaymentNotification(loanAmount); // update KPIs loan.borrower.transfer(loan.collateralAmount); // send back ETH collateral emit LoanRepayed(loanId, loan.borrower); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"constant":false,"inputs":[{"name":"productId","type":"uint32"},{"name":"newState","type":"bool"}],"name":"setLoanProductActiveState","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"monetarySupervisor","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"borrower","type":"address"}],"name":"getLoanCountForAddress","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"rates","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"loanId","type":"uint256"}],"name":"getLoanTuple","outputs":[{"name":"result","type":"uint256[10]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getProductCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newRatesContract","type":"address"},{"name":"newMonetarySupervisor","type":"address"}],"name":"setSystemContracts","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getLoanCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"loanIds","type":"uint256[]"}],"name":"collect","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"bytes32"}],"name":"permissions","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"agent","type":"address"},{"name":"requiredPermission","type":"bytes32"}],"name":"revokePermission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"","type":"address"},{"name":"repaymentAmount","type":"uint256"},{"name":"loanId","type":"uint256"}],"name":"transferNotification","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"accountLoans","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"products","outputs":[{"name":"minDisbursedAmount","type":"uint256"},{"name":"term","type":"uint32"},{"name":"discountRate","type":"uint32"},{"name":"collateralRatio","type":"uint32"},{"name":"defaultingFeePt","type":"uint32"},{"name":"isActive","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"augmintToken","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"agent","type":"address"},{"name":"requiredPermissions","type":"bytes32[]"}],"name":"revokeMultiplePermissions","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"offset","type":"uint256"},{"name":"chunkSize","type":"uint16"}],"name":"getLoans","outputs":[{"name":"","type":"uint256[10][]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"agent","type":"address"},{"name":"requiredPermissions","type":"bytes32[]"}],"name":"grantMultiplePermissions","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"borrower","type":"address"},{"name":"offset","type":"uint256"},{"name":"chunkSize","type":"uint16"}],"name":"getLoansForAddress","outputs":[{"name":"","type":"uint256[10][]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"term","type":"uint32"},{"name":"discountRate","type":"uint32"},{"name":"collateralRatio","type":"uint32"},{"name":"minDisbursedAmount","type":"uint256"},{"name":"defaultingFeePt","type":"uint32"},{"name":"isActive","type":"bool"}],"name":"addLoanProduct","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"offset","type":"uint256"},{"name":"chunkSize","type":"uint16"}],"name":"getProducts","outputs":[{"name":"","type":"uint256[8][]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"productId","type":"uint32"}],"name":"newEthBackedLoan","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"loans","outputs":[{"name":"collateralAmount","type":"uint256"},{"name":"repaymentAmount","type":"uint256"},{"name":"borrower","type":"address"},{"name":"productId","type":"uint32"},{"name":"state","type":"uint8"},{"name":"maturity","type":"uint40"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"agent","type":"address"},{"name":"requiredPermission","type":"bytes32"}],"name":"grantPermission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"permissionGranterContract","type":"address"},{"name":"_augmintToken","type":"address"},{"name":"_monetarySupervisor","type":"address"},{"name":"_rates","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"productId","type":"uint32"},{"indexed":false,"name":"loanId","type":"uint256"},{"indexed":true,"name":"borrower","type":"address"},{"indexed":false,"name":"collateralAmount","type":"uint256"},{"indexed":false,"name":"loanAmount","type":"uint256"},{"indexed":false,"name":"repaymentAmount","type":"uint256"},{"indexed":false,"name":"maturity","type":"uint40"}],"name":"NewLoan","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"productId","type":"uint32"},{"indexed":false,"name":"newState","type":"bool"}],"name":"LoanProductActiveStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"productId","type":"uint32"}],"name":"LoanProductAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"loanId","type":"uint256"},{"indexed":false,"name":"borrower","type":"address"}],"name":"LoanRepayed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"loanId","type":"uint256"},{"indexed":true,"name":"borrower","type":"address"},{"indexed":false,"name":"collectedCollateral","type":"uint256"},{"indexed":false,"name":"releasedCollateral","type":"uint256"},{"indexed":false,"name":"defaultingFee","type":"uint256"}],"name":"LoanCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newRatesContract","type":"address"},{"indexed":false,"name":"newMonetarySupervisor","type":"address"}],"name":"SystemContractsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"agent","type":"address"},{"indexed":false,"name":"grantedPermission","type":"bytes32"}],"name":"PermissionGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"agent","type":"address"},{"indexed":false,"name":"revokedPermission","type":"bytes32"}],"name":"PermissionRevoked","type":"event"}]
Contract Creation Code
608060405234801561001057600080fd5b50604051608080620043028339810180604052810190808051906020019092919080519060200190929190805190602001909291908051906020019092919050505083600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415151561011e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f7065726d697373696f6e4772616e746572436f6e7472616374206d757374206281526020017f652073657400000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60016000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060007f5065726d697373696f6e4772616e74657200000000000000000000000000000060001916815260200190815260200160002060006101000a81548160ff0219169083151502179055508073ffffffffffffffffffffffffffffffffffffffff167fc65937e3dbcb9fb30f646815dd67a3dbd09ba17718cbcb54efbe3635f8e0a6fe60405180807f5065726d697373696f6e4772616e746572000000000000000000000000000000815250602001905060405180910390a25082600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050505061401280620002f06000396000f30060806040526004361061013e576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806315f647fc14610143578063169f66df146101825780632432282d146101d957806343f48fbd14610230578063442d27dc146102875780634a348da9146102f05780634d8e64ee1461031b578063521968121461037e57806357f46cbe146103a95780635b225526146103e45780635fe070131461044d57806364e7e4a41461049e578063761004bd146104f55780637acc0b20146105565780637b9b9c89146105ee5780637ea4699314610645578063987a0c46146106cb5780639ac3317b1461077e578063bfcbc95614610804578063c1c6d4e8146108d7578063cb47f10d14610950578063d4849a8b14610a03578063e1ec3c6814610a29578063f38a826214610ae1575b600080fd5b34801561014f57600080fd5b50610180600480360381019080803563ffffffff169060200190929190803515159060200190929190505050610b32565b005b34801561018e57600080fd5b50610197610d40565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101e557600080fd5b5061021a600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d66565b6040518082815260200191505060405180910390f35b34801561023c57600080fd5b50610245610db2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561029357600080fd5b506102b260048036038101908080359060200190929190505050610dd8565b6040518082600a60200280838360005b838110156102dd5780820151818401526020810190506102c2565b5050505090500191505060405180910390f35b3480156102fc57600080fd5b50610305611058565b6040518082815260200191505060405180910390f35b34801561032757600080fd5b5061037c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611065565b005b34801561038a57600080fd5b5061039361127d565b6040518082815260200191505060405180910390f35b3480156103b557600080fd5b506103e260048036038101908080359060200190820180359060200191909192939192939050505061128a565b005b3480156103f057600080fd5b50610433600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035600019169060200190929190505050611d80565b604051808215151515815260200191505060405180910390f35b34801561045957600080fd5b5061049c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035600019169060200190929190505050611daf565b005b3480156104aa57600080fd5b506104f3600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190505050611f94565b005b34801561050157600080fd5b50610540600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612068565b6040518082815260200191505060405180910390f35b34801561056257600080fd5b5061058160048036038101908080359060200190929190505050612098565b604051808781526020018663ffffffff1663ffffffff1681526020018563ffffffff1663ffffffff1681526020018463ffffffff1663ffffffff1681526020018363ffffffff1663ffffffff16815260200182151515158152602001965050505050505060405180910390f35b3480156105fa57600080fd5b50610603612130565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561065157600080fd5b506106c9600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290505050612156565b005b3480156106d757600080fd5b5061070460048036038101908080359060200190929190803561ffff16906020019092919050505061219e565b60405180806020018281038252838181518152602001915080516000925b8184101561076d57828490602001906020020151600a60200280838360005b8381101561075c578082015181840152602081019050610741565b505050509050019260010192610722565b925050509250505060405180910390f35b34801561078a57600080fd5b50610802600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290505050612267565b005b34801561081057600080fd5b5061085d600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803561ffff1690602001909291905050506123ca565b60405180806020018281038252838181518152602001915080516000925b818410156108c657828490602001906020020151600a60200280838360005b838110156108b557808201518184015260208101905061089a565b50505050905001926001019261087b565b925050509250505060405180910390f35b3480156108e357600080fd5b5061094e600480360381019080803563ffffffff169060200190929190803563ffffffff169060200190929190803563ffffffff16906020019092919080359060200190929190803563ffffffff1690602001909291908035151590602001909291905050506124ee565b005b34801561095c57600080fd5b5061098960048036038101908080359060200190929190803561ffff1690602001909291905050506127fa565b60405180806020018281038252838181518152602001915080516000925b818410156109f257828490602001906020020151600860200280838360005b838110156109e15780820151818401526020810190506109c6565b5050505090500192600101926109a7565b925050509250505060405180910390f35b610a27600480360381019080803563ffffffff169060200190929190505050612a73565b005b348015610a3557600080fd5b50610a5460048036038101908080359060200190929190505050613233565b604051808781526020018681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018463ffffffff1663ffffffff168152602001836003811115610ab457fe5b60ff1681526020018264ffffffffff1664ffffffffff168152602001965050505050505060405180910390f35b348015610aed57600080fd5b50610b30600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080356000191690602001909291905050506132cc565b005b7f53746162696c697479426f6172640000000000000000000000000000000000006000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000826000191660001916815260200190815260200160002060009054906101000a900460ff161515610c2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6d73672e73656e646572206d7573742068617665207065726d697373696f6e0081525060200191505060405180910390fd5b6001805490508363ffffffff16101515610cae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f696e76616c69642070726f64756374496400000000000000000000000000000081525060200191505060405180910390fd5b8160018463ffffffff16815481101515610cc457fe5b906000526020600020906002020160010160106101000a81548160ff0219169083151502179055507ff686833114a6119b006ebfaf64ed31277c71b76a9855945de8d58f849bff68908383604051808363ffffffff1663ffffffff168152602001821515151581526020019250505060405180910390a1505050565b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610de0613f7a565b60008060008060008060028054905088101515610e65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f696e76616c6964206c6f616e496400000000000000000000000000000000000081525060200191505060405180910390fd5b600288815481101515610e7457fe5b9060005260206000209060030201955060018660020160149054906101000a900463ffffffff1663ffffffff16815481101515610ead57fe5b90600052602060002090600202019450610ecb8587600101546134b1565b80945081955050508460010160009054906101000a900463ffffffff1663ffffffff168660020160199054906101000a900464ffffffffff160364ffffffffff16915060006003811115610f1b57fe5b8660020160189054906101000a900460ff166003811115610f3857fe5b148015610f6157508560020160199054906101000a900464ffffffffff1664ffffffffff164210155b610f7c578560020160189054906101000a900460ff16610f7f565b60025b90506101406040519081016040528089815260200187600001548152602001876001015481526020018760020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018760020160149054906101000a900463ffffffff1663ffffffff16815260200182600381111561101457fe5b81526020018760020160199054906101000a900464ffffffffff1664ffffffffff168152602001838152602001858152602001848152509650505050505050919050565b6000600180549050905090565b7f53746162696c697479426f6172640000000000000000000000000000000000006000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000826000191660001916815260200190815260200160002060009054906101000a900460ff16151561115f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6d73672e73656e646572206d7573742068617665207065726d697373696f6e0081525060200191505060405180910390fd5b82600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f68700d71686a6c45f4e450fa2f38d15fcddf5956d2bd054075f77d4636ff0f1a8383604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a1505050565b6000600280549050905090565b600080600080600080600080600080600080600098505b8d8d9050891015611aa5576002805490508e8e8b81811015156112c057fe5b9050602002013510151561133c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f696e76616c6964206c6f616e496400000000000000000000000000000000000081525060200191505060405180910390fd5b60028e8e8b818110151561134c57fe5b9050602002013581548110151561135f57fe5b906000526020600020906003020197506000600381111561137c57fe5b8860020160189054906101000a900460ff16600381111561139957fe5b14151561140e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f6c6f616e207374617465206d757374206265204f70656e00000000000000000081525060200191505060405180910390fd5b8760020160199054906101000a900464ffffffffff1664ffffffffff1642101515156114c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001807f63757272656e742074696d65206d757374206265206c61746572207468616e2081526020017f6d6174757269747900000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60018860020160149054906101000a900463ffffffff1663ffffffff168154811015156114f157fe5b9060005260206000209060020201965061150f8789600101546134b1565b5080965050611527868d61352390919063ffffffff16565b9b5060038860020160186101000a81548160ff0219169083600381111561154a57fe5b0217905550611595620f424061158789600101600c9054906101000a900463ffffffff1663ffffffff168b600101546135ad90919063ffffffff16565b61364c90919063ffffffff16565b9450600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c481d8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166333a263e66040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561165b57600080fd5b505af115801561166f573d6000803e3d6000fd5b505050506040513d602081101561168557600080fd5b8101908080519060200190929190505050876040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180836000191660001916815260200182815260200192505050602060405180830381600087803b1580156116f857600080fd5b505af115801561170c573d6000803e3d6000fd5b505050506040513d602081101561172257600080fd5b810190808051906020019092919050505093506118e784600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c481d8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166333a263e66040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1580156117fd57600080fd5b505af1158015611811573d6000803e3d6000fd5b505050506040513d602081101561182757600080fd5b81019080805190602001909291905050508c600101546040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180836000191660001916815260200182815260200192505050602060405180830381600087803b15801561189e57600080fd5b505af11580156118b2573d6000803e3d6000fd5b505050506040513d60208110156118c857600080fd5b810190808051906020019092919050505061352390919063ffffffff16565b9250876000015483101561197a5761190c8389600001546136df90919063ffffffff16565b91508760020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050158015611978573d6000803e3d6000fd5b505b6119918289600001546136df90919063ffffffff16565b905080841015156119a857809350600090506119be565b6119bb84826136df90919063ffffffff16565b90505b6119d1848b61352390919063ffffffff16565b99506119e6818c61352390919063ffffffff16565b9a508760020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f328dba6669445381058bdb02ebe2ec93eb6f203f283073dee9b206720390f10b8f8f8c8181101515611a5257fe5b90506020020135611a6c878561352390919063ffffffff16565b85886040518085815260200184815260200183815260200182815260200194505050505060405180910390a288806001019950506112a1565b60008b1115611bb657600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fe1ebb046040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015611b3457600080fd5b505af1158015611b48573d6000803e3d6000fd5b505050506040513d6020811015611b5e57600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff166108fc8c9081150290604051600060405180830381858888f19350505050158015611bb4573d6000803e3d6000fd5b505b60008a1115611cc757600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166365e17c9d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015611c4557600080fd5b505af1158015611c59573d6000803e3d6000fd5b505050506040513d6020811015611c6f57600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff166108fc8b9081150290604051600060405180830381858888f19350505050158015611cc5573d6000803e3d6000fd5b505b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166358c316038d6040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b158015611d5857600080fd5b505af1158015611d6c573d6000803e3d6000fd5b505050505050505050505050505050505050565b60006020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060007f5065726d697373696f6e4772616e74657200000000000000000000000000000060001916815260200190815260200160002060009054906101000a900460ff161515611eca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260318152602001807f6d73672e73656e646572206d7573742068617665205065726d697373696f6e4781526020017f72616e746572207065726d697373696f6e00000000000000000000000000000081525060400191505060405180910390fd5b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167f789770131846de4d1f28418f0f957cdf4fcabe5eccf70067083e20ecece69a348260405180826000191660001916815260200191505060405180910390a25050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515612059576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6d73672e73656e646572206d757374206265206175676d696e74546f6b656e0081525060200191505060405180910390fd5b6120638183613764565b505050565b60036020528160005260406000208181548110151561208357fe5b90600052602060002001600091509150505481565b6001818154811015156120a757fe5b90600052602060002090600202016000915090508060000154908060010160009054906101000a900463ffffffff16908060010160049054906101000a900463ffffffff16908060010160089054906101000a900463ffffffff169080600101600c9054906101000a900463ffffffff16908060010160109054906101000a900460ff16905086565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008082519150600090505b818110156121985761218b84848381518110151561217c57fe5b90602001906020020151611daf565b8080600101915050612162565b50505050565b60606000606060006121cb6121c08661ffff168861352390919063ffffffff16565b600280549050613f61565b92506121e086846136df90919063ffffffff16565b60405190808252806020026020018201604052801561221957816020015b612206613f9e565b8152602001906001900390816121fe5790505b5091508590505b8281101561225b5761223181610dd8565b8287830381518110151561224157fe5b906020019060200201819052508080600101915050612220565b81935050505092915050565b6000806000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060007f5065726d697373696f6e4772616e74657200000000000000000000000000000060001916815260200190815260200160002060009054906101000a900460ff161515612385576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260318152602001807f6d73672e73656e646572206d7573742068617665205065726d697373696f6e4781526020017f72616e746572207065726d697373696f6e00000000000000000000000000000081525060400191505060405180910390fd5b82519150600090505b818110156123c4576123b78484838151811015156123a857fe5b906020019060200201516132cc565b808060010191505061238e565b50505050565b606060008060606000600360008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020935061243861242e8761ffff168961352390919063ffffffff16565b8580549050613f61565b925061244d87846136df90919063ffffffff16565b60405190808252806020026020018201604052801561248657816020015b612473613f9e565b81526020019060019003908161246b5790505b5091508690505b828110156124e0576124b684828154811015156124a657fe5b9060005260206000200154610dd8565b828883038151811015156124c657fe5b90602001906020020181905250808060010191505061248d565b819450505050509392505050565b6000807f53746162696c697479426f6172640000000000000000000000000000000000006000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000826000191660001916815260200190815260200160002060009054906101000a900460ff1615156125eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6d73672e73656e646572206d7573742068617665207065726d697373696f6e0081525060200191505060405180910390fd5b60018060c0604051908101604052808981526020018c63ffffffff1681526020018b63ffffffff1681526020018a63ffffffff1681526020018863ffffffff168152602001871515815250908060018154018082558091505090600182039060005260206000209060020201600090919290919091506000820151816000015560208201518160010160006101000a81548163ffffffff021916908363ffffffff16021790555060408201518160010160046101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160086101000a81548163ffffffff021916908363ffffffff160217905550608082015181600101600c6101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160106101000a81548160ff0219169083151502179055505050039250829150828263ffffffff161415156127ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f70726f647563744964206f766572666c6f77000000000000000000000000000081525060200191505060405180910390fd5b7fccadd8a27b8a91830a26f7dd76f3acec14cd6bc7bfb79e91113ec547150d95f082604051808263ffffffff1663ffffffff16815260200191505060405180910390a1505050505050505050565b60606000606060008061282861281d8761ffff168961352390919063ffffffff16565b600180549050613f61565b935061283d87856136df90919063ffffffff16565b60405190808252806020026020018201604052801561287657816020015b612863613fc2565b81526020019060019003908161285b5790505b5092508691505b83821015612a665760018281548110151561289457fe5b9060005260206000209060020201905061010060405190810160405280838152602001826000015481526020018260010160009054906101000a900463ffffffff1663ffffffff1681526020018260010160049054906101000a900463ffffffff1663ffffffff1681526020018260010160089054906101000a900463ffffffff1663ffffffff16815260200182600101600c9054906101000a900463ffffffff1663ffffffff168152602001600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e95f2c7d84600001546040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b1580156129d657600080fd5b505af11580156129ea573d6000803e3d6000fd5b505050506040513d6020811015612a0057600080fd5b810190808051906020019092919050505081526020018260010160109054906101000a900460ff16612a33576000612a36565b60015b60ff1681525083888403815181101515612a4c57fe5b90602001906020020181905250818060010192505061287d565b8294505050505092915050565b60008060008060008060006001805490508863ffffffff16101515612b00576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f696e76616c69642070726f64756374496400000000000000000000000000000081525060200191505060405180910390fd5b60018863ffffffff16815481101515612b1557fe5b906000526020600020906002020196508660010160109054906101000a900460ff161515612bab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f70726f64756374206d75737420626520696e206163746976652073746174650081525060200191505060405180910390fd5b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166382f5e31b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166333a263e66040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015612c6f57600080fd5b505af1158015612c83573d6000803e3d6000fd5b505050506040513d6020811015612c9957600080fd5b8101908080519060200190929190505050346040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180836000191660001916815260200182815260200192505050602060405180830381600087803b158015612d0c57600080fd5b505af1158015612d20573d6000803e3d6000fd5b505050506040513d6020811015612d3657600080fd5b81019080805190602001909291905050509550612d8b620f4240612d7d8960010160089054906101000a900463ffffffff1663ffffffff16896135ad90919063ffffffff16565b61364c90919063ffffffff16565b9450612d9787866134b1565b508094505086600001548410151515612e3e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001807f6c6f616e416d6f756e74206d757374206265203e3d206d696e4469736275727381526020017f6564416d6f756e7400000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b612e6b8760010160009054906101000a900463ffffffff1663ffffffff164261352390919063ffffffff16565b9250829150828264ffffffffff16141515612eee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6d61747572697479206f766572666c6f7700000000000000000000000000000081525060200191505060405180910390fd5b6001600260c0604051908101604052803481526020018881526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018b63ffffffff16815260200160006003811115612f3f57fe5b81526020018564ffffffffff1681525090806001815401808255809150509060018203906000526020600020906003020160009091929091909150600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160146101000a81548163ffffffff021916908363ffffffff16021790555060808201518160020160186101000a81548160ff0219169083600381111561302057fe5b021790555060a08201518160020160196101000a81548164ffffffffff021916908364ffffffffff1602179055505050039050600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819080600181540180825580915050906001820390600052602060002001600090919290919091505550600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631895687d33866040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b15801561318157600080fd5b505af1158015613195573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff167f1f9972ec35a86b6ea1c3884c02fda9d8d0c5c14089a133610fed51c481b7e208898334888a88604051808763ffffffff1663ffffffff1681526020018681526020018581526020018481526020018381526020018264ffffffffff1664ffffffffff168152602001965050505050505060405180910390a25050505050505050565b60028181548110151561324257fe5b90600052602060002090600302016000915090508060000154908060010154908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020160149054906101000a900463ffffffff16908060020160189054906101000a900460ff16908060020160199054906101000a900464ffffffffff16905086565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060007f5065726d697373696f6e4772616e74657200000000000000000000000000000060001916815260200190815260200160002060009054906101000a900460ff1615156133e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260318152602001807f6d73672e73656e646572206d7573742068617665205065726d697373696f6e4781526020017f72616e746572207065726d697373696f6e00000000000000000000000000000081525060400191505060405180910390fd5b60016000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167fc65937e3dbcb9fb30f646815dd67a3dbd09ba17718cbcb54efbe3635f8e0a6fe8260405180826000191660001916815260200191505060405180910390a25050565b6000806134f6620f42406134e88660010160049054906101000a900463ffffffff1663ffffffff16866135ad90919063ffffffff16565b61364c90919063ffffffff16565b91508282116135175761351282846136df90919063ffffffff16565b61351a565b60005b90509250929050565b60008082840190508381101515156135a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f616464206f766572666c6f77000000000000000000000000000000000000000081525060200191505060405180910390fd5b8091505092915050565b600080828402905060008414806135ce57508284828115156135cb57fe5b04145b1515613642576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f6d756c206f766572666c6f77000000000000000000000000000000000000000081525060200191505060405180910390fd5b8091505092915050565b6000806000831115156136c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260088152602001807f646976206279203000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b82848115156136d257fe5b0490508091505092915050565b6000828211151515613759576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f73756220756e646572666c6f770000000000000000000000000000000000000081525060200191505060405180910390fd5b818303905092915050565b600080600080600280549050861015156137e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f696e76616c6964206c6f616e496400000000000000000000000000000000000081525060200191505060405180910390fd5b6002868154811015156137f557fe5b906000526020600020906003020193506000600381111561381257fe5b8460020160189054906101000a900460ff16600381111561382f57fe5b1415156138a4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f6c6f616e207374617465206d757374206265204f70656e00000000000000000081525060200191505060405180910390fd5b836001015485141515613945576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c8152602001807f72657061796d656e74416d6f756e74206d75737420626520657175616c20746f81526020017f20746f6b656e732073656e74000000000000000000000000000000000000000081525060400191505060405180910390fd5b8360020160199054906101000a900464ffffffffff1664ffffffffff1642111515156139ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f63757272656e742074696d65206d757374206265206561726c6965722074686181526020017f6e206d617475726974790000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60018460020160149054906101000a900463ffffffff1663ffffffff16815481101515613a2857fe5b90600052602060002090600202019250613a468385600101546134b1565b80925081935050506001600287815481101515613a5f57fe5b906000526020600020906003020160020160186101000a81548160ff02191690836003811115613a8b57fe5b02179055506000811115613d0857600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635fcf04556040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015613b5d57600080fd5b505af1158015613b71573d6000803e3d6000fd5b505050506040513d6020811015613b8757600080fd5b8101908080519060200190929190505050836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015613c1e57600080fd5b505af1158015613c32573d6000803e3d6000fd5b505050506040513d6020811015613c4857600080fd5b810190808051906020019092919050505050600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342966c68836040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b158015613ceb57600080fd5b505af1158015613cff573d6000803e3d6000fd5b50505050613db2565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342966c68866040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b158015613d9957600080fd5b505af1158015613dad573d6000803e3d6000fd5b505050505b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634cae5f99836040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b158015613e4357600080fd5b505af1158015613e57573d6000803e3d6000fd5b505050508360020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc85600001549081150290604051600060405180830381858888f19350505050158015613ec9573d6000803e3d6000fd5b507f0bc2fda5eb321ed5f7471e814a5c00752523b3ba8fbfeb905e1b8707eefa16c5868560020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a1505050505050565b6000818310613f705781613f72565b825b905092915050565b61014060405190810160405280600a90602082028038833980820191505090505090565b61014060405190810160405280600a90602082028038833980820191505090505090565b610100604051908101604052806008906020820280388339808201915050905050905600a165627a7a7230582042deca639f0687c84e9ebaf8372f77d01c5167d434db4f969863bc69257a9db10029000000000000000000000000de36a8773531406dcbeffdfd3c7b89fced7a9f84000000000000000000000000c994a2deb02543db1f48688438b9903c4b305ce300000000000000000000000027484afe9e6c332fb07f21fac82d442ebe1d22c30000000000000000000000004272db2eb82068e898588c3d6e4b5d55c3848793
Deployed Bytecode
0x60806040526004361061013e576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806315f647fc14610143578063169f66df146101825780632432282d146101d957806343f48fbd14610230578063442d27dc146102875780634a348da9146102f05780634d8e64ee1461031b578063521968121461037e57806357f46cbe146103a95780635b225526146103e45780635fe070131461044d57806364e7e4a41461049e578063761004bd146104f55780637acc0b20146105565780637b9b9c89146105ee5780637ea4699314610645578063987a0c46146106cb5780639ac3317b1461077e578063bfcbc95614610804578063c1c6d4e8146108d7578063cb47f10d14610950578063d4849a8b14610a03578063e1ec3c6814610a29578063f38a826214610ae1575b600080fd5b34801561014f57600080fd5b50610180600480360381019080803563ffffffff169060200190929190803515159060200190929190505050610b32565b005b34801561018e57600080fd5b50610197610d40565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101e557600080fd5b5061021a600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d66565b6040518082815260200191505060405180910390f35b34801561023c57600080fd5b50610245610db2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561029357600080fd5b506102b260048036038101908080359060200190929190505050610dd8565b6040518082600a60200280838360005b838110156102dd5780820151818401526020810190506102c2565b5050505090500191505060405180910390f35b3480156102fc57600080fd5b50610305611058565b6040518082815260200191505060405180910390f35b34801561032757600080fd5b5061037c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611065565b005b34801561038a57600080fd5b5061039361127d565b6040518082815260200191505060405180910390f35b3480156103b557600080fd5b506103e260048036038101908080359060200190820180359060200191909192939192939050505061128a565b005b3480156103f057600080fd5b50610433600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035600019169060200190929190505050611d80565b604051808215151515815260200191505060405180910390f35b34801561045957600080fd5b5061049c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035600019169060200190929190505050611daf565b005b3480156104aa57600080fd5b506104f3600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190505050611f94565b005b34801561050157600080fd5b50610540600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612068565b6040518082815260200191505060405180910390f35b34801561056257600080fd5b5061058160048036038101908080359060200190929190505050612098565b604051808781526020018663ffffffff1663ffffffff1681526020018563ffffffff1663ffffffff1681526020018463ffffffff1663ffffffff1681526020018363ffffffff1663ffffffff16815260200182151515158152602001965050505050505060405180910390f35b3480156105fa57600080fd5b50610603612130565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561065157600080fd5b506106c9600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290505050612156565b005b3480156106d757600080fd5b5061070460048036038101908080359060200190929190803561ffff16906020019092919050505061219e565b60405180806020018281038252838181518152602001915080516000925b8184101561076d57828490602001906020020151600a60200280838360005b8381101561075c578082015181840152602081019050610741565b505050509050019260010192610722565b925050509250505060405180910390f35b34801561078a57600080fd5b50610802600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290505050612267565b005b34801561081057600080fd5b5061085d600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803561ffff1690602001909291905050506123ca565b60405180806020018281038252838181518152602001915080516000925b818410156108c657828490602001906020020151600a60200280838360005b838110156108b557808201518184015260208101905061089a565b50505050905001926001019261087b565b925050509250505060405180910390f35b3480156108e357600080fd5b5061094e600480360381019080803563ffffffff169060200190929190803563ffffffff169060200190929190803563ffffffff16906020019092919080359060200190929190803563ffffffff1690602001909291908035151590602001909291905050506124ee565b005b34801561095c57600080fd5b5061098960048036038101908080359060200190929190803561ffff1690602001909291905050506127fa565b60405180806020018281038252838181518152602001915080516000925b818410156109f257828490602001906020020151600860200280838360005b838110156109e15780820151818401526020810190506109c6565b5050505090500192600101926109a7565b925050509250505060405180910390f35b610a27600480360381019080803563ffffffff169060200190929190505050612a73565b005b348015610a3557600080fd5b50610a5460048036038101908080359060200190929190505050613233565b604051808781526020018681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018463ffffffff1663ffffffff168152602001836003811115610ab457fe5b60ff1681526020018264ffffffffff1664ffffffffff168152602001965050505050505060405180910390f35b348015610aed57600080fd5b50610b30600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080356000191690602001909291905050506132cc565b005b7f53746162696c697479426f6172640000000000000000000000000000000000006000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000826000191660001916815260200190815260200160002060009054906101000a900460ff161515610c2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6d73672e73656e646572206d7573742068617665207065726d697373696f6e0081525060200191505060405180910390fd5b6001805490508363ffffffff16101515610cae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f696e76616c69642070726f64756374496400000000000000000000000000000081525060200191505060405180910390fd5b8160018463ffffffff16815481101515610cc457fe5b906000526020600020906002020160010160106101000a81548160ff0219169083151502179055507ff686833114a6119b006ebfaf64ed31277c71b76a9855945de8d58f849bff68908383604051808363ffffffff1663ffffffff168152602001821515151581526020019250505060405180910390a1505050565b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610de0613f7a565b60008060008060008060028054905088101515610e65576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f696e76616c6964206c6f616e496400000000000000000000000000000000000081525060200191505060405180910390fd5b600288815481101515610e7457fe5b9060005260206000209060030201955060018660020160149054906101000a900463ffffffff1663ffffffff16815481101515610ead57fe5b90600052602060002090600202019450610ecb8587600101546134b1565b80945081955050508460010160009054906101000a900463ffffffff1663ffffffff168660020160199054906101000a900464ffffffffff160364ffffffffff16915060006003811115610f1b57fe5b8660020160189054906101000a900460ff166003811115610f3857fe5b148015610f6157508560020160199054906101000a900464ffffffffff1664ffffffffff164210155b610f7c578560020160189054906101000a900460ff16610f7f565b60025b90506101406040519081016040528089815260200187600001548152602001876001015481526020018760020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018760020160149054906101000a900463ffffffff1663ffffffff16815260200182600381111561101457fe5b81526020018760020160199054906101000a900464ffffffffff1664ffffffffff168152602001838152602001858152602001848152509650505050505050919050565b6000600180549050905090565b7f53746162696c697479426f6172640000000000000000000000000000000000006000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000826000191660001916815260200190815260200160002060009054906101000a900460ff16151561115f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6d73672e73656e646572206d7573742068617665207065726d697373696f6e0081525060200191505060405180910390fd5b82600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f68700d71686a6c45f4e450fa2f38d15fcddf5956d2bd054075f77d4636ff0f1a8383604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a1505050565b6000600280549050905090565b600080600080600080600080600080600080600098505b8d8d9050891015611aa5576002805490508e8e8b81811015156112c057fe5b9050602002013510151561133c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f696e76616c6964206c6f616e496400000000000000000000000000000000000081525060200191505060405180910390fd5b60028e8e8b818110151561134c57fe5b9050602002013581548110151561135f57fe5b906000526020600020906003020197506000600381111561137c57fe5b8860020160189054906101000a900460ff16600381111561139957fe5b14151561140e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f6c6f616e207374617465206d757374206265204f70656e00000000000000000081525060200191505060405180910390fd5b8760020160199054906101000a900464ffffffffff1664ffffffffff1642101515156114c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001807f63757272656e742074696d65206d757374206265206c61746572207468616e2081526020017f6d6174757269747900000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60018860020160149054906101000a900463ffffffff1663ffffffff168154811015156114f157fe5b9060005260206000209060020201965061150f8789600101546134b1565b5080965050611527868d61352390919063ffffffff16565b9b5060038860020160186101000a81548160ff0219169083600381111561154a57fe5b0217905550611595620f424061158789600101600c9054906101000a900463ffffffff1663ffffffff168b600101546135ad90919063ffffffff16565b61364c90919063ffffffff16565b9450600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c481d8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166333a263e66040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b15801561165b57600080fd5b505af115801561166f573d6000803e3d6000fd5b505050506040513d602081101561168557600080fd5b8101908080519060200190929190505050876040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180836000191660001916815260200182815260200192505050602060405180830381600087803b1580156116f857600080fd5b505af115801561170c573d6000803e3d6000fd5b505050506040513d602081101561172257600080fd5b810190808051906020019092919050505093506118e784600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c481d8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166333a263e66040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1580156117fd57600080fd5b505af1158015611811573d6000803e3d6000fd5b505050506040513d602081101561182757600080fd5b81019080805190602001909291905050508c600101546040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180836000191660001916815260200182815260200192505050602060405180830381600087803b15801561189e57600080fd5b505af11580156118b2573d6000803e3d6000fd5b505050506040513d60208110156118c857600080fd5b810190808051906020019092919050505061352390919063ffffffff16565b9250876000015483101561197a5761190c8389600001546136df90919063ffffffff16565b91508760020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050158015611978573d6000803e3d6000fd5b505b6119918289600001546136df90919063ffffffff16565b905080841015156119a857809350600090506119be565b6119bb84826136df90919063ffffffff16565b90505b6119d1848b61352390919063ffffffff16565b99506119e6818c61352390919063ffffffff16565b9a508760020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f328dba6669445381058bdb02ebe2ec93eb6f203f283073dee9b206720390f10b8f8f8c8181101515611a5257fe5b90506020020135611a6c878561352390919063ffffffff16565b85886040518085815260200184815260200183815260200182815260200194505050505060405180910390a288806001019950506112a1565b60008b1115611bb657600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663fe1ebb046040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015611b3457600080fd5b505af1158015611b48573d6000803e3d6000fd5b505050506040513d6020811015611b5e57600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff166108fc8c9081150290604051600060405180830381858888f19350505050158015611bb4573d6000803e3d6000fd5b505b60008a1115611cc757600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166365e17c9d6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015611c4557600080fd5b505af1158015611c59573d6000803e3d6000fd5b505050506040513d6020811015611c6f57600080fd5b810190808051906020019092919050505073ffffffffffffffffffffffffffffffffffffffff166108fc8b9081150290604051600060405180830381858888f19350505050158015611cc5573d6000803e3d6000fd5b505b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166358c316038d6040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b158015611d5857600080fd5b505af1158015611d6c573d6000803e3d6000fd5b505050505050505050505050505050505050565b60006020528160005260406000206020528060005260406000206000915091509054906101000a900460ff1681565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060007f5065726d697373696f6e4772616e74657200000000000000000000000000000060001916815260200190815260200160002060009054906101000a900460ff161515611eca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260318152602001807f6d73672e73656e646572206d7573742068617665205065726d697373696f6e4781526020017f72616e746572207065726d697373696f6e00000000000000000000000000000081525060400191505060405180910390fd5b60008060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167f789770131846de4d1f28418f0f957cdf4fcabe5eccf70067083e20ecece69a348260405180826000191660001916815260200191505060405180910390a25050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515612059576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6d73672e73656e646572206d757374206265206175676d696e74546f6b656e0081525060200191505060405180910390fd5b6120638183613764565b505050565b60036020528160005260406000208181548110151561208357fe5b90600052602060002001600091509150505481565b6001818154811015156120a757fe5b90600052602060002090600202016000915090508060000154908060010160009054906101000a900463ffffffff16908060010160049054906101000a900463ffffffff16908060010160089054906101000a900463ffffffff169080600101600c9054906101000a900463ffffffff16908060010160109054906101000a900460ff16905086565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008082519150600090505b818110156121985761218b84848381518110151561217c57fe5b90602001906020020151611daf565b8080600101915050612162565b50505050565b60606000606060006121cb6121c08661ffff168861352390919063ffffffff16565b600280549050613f61565b92506121e086846136df90919063ffffffff16565b60405190808252806020026020018201604052801561221957816020015b612206613f9e565b8152602001906001900390816121fe5790505b5091508590505b8281101561225b5761223181610dd8565b8287830381518110151561224157fe5b906020019060200201819052508080600101915050612220565b81935050505092915050565b6000806000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060007f5065726d697373696f6e4772616e74657200000000000000000000000000000060001916815260200190815260200160002060009054906101000a900460ff161515612385576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260318152602001807f6d73672e73656e646572206d7573742068617665205065726d697373696f6e4781526020017f72616e746572207065726d697373696f6e00000000000000000000000000000081525060400191505060405180910390fd5b82519150600090505b818110156123c4576123b78484838151811015156123a857fe5b906020019060200201516132cc565b808060010191505061238e565b50505050565b606060008060606000600360008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020935061243861242e8761ffff168961352390919063ffffffff16565b8580549050613f61565b925061244d87846136df90919063ffffffff16565b60405190808252806020026020018201604052801561248657816020015b612473613f9e565b81526020019060019003908161246b5790505b5091508690505b828110156124e0576124b684828154811015156124a657fe5b9060005260206000200154610dd8565b828883038151811015156124c657fe5b90602001906020020181905250808060010191505061248d565b819450505050509392505050565b6000807f53746162696c697479426f6172640000000000000000000000000000000000006000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000826000191660001916815260200190815260200160002060009054906101000a900460ff1615156125eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f6d73672e73656e646572206d7573742068617665207065726d697373696f6e0081525060200191505060405180910390fd5b60018060c0604051908101604052808981526020018c63ffffffff1681526020018b63ffffffff1681526020018a63ffffffff1681526020018863ffffffff168152602001871515815250908060018154018082558091505090600182039060005260206000209060020201600090919290919091506000820151816000015560208201518160010160006101000a81548163ffffffff021916908363ffffffff16021790555060408201518160010160046101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160086101000a81548163ffffffff021916908363ffffffff160217905550608082015181600101600c6101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160010160106101000a81548160ff0219169083151502179055505050039250829150828263ffffffff161415156127ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f70726f647563744964206f766572666c6f77000000000000000000000000000081525060200191505060405180910390fd5b7fccadd8a27b8a91830a26f7dd76f3acec14cd6bc7bfb79e91113ec547150d95f082604051808263ffffffff1663ffffffff16815260200191505060405180910390a1505050505050505050565b60606000606060008061282861281d8761ffff168961352390919063ffffffff16565b600180549050613f61565b935061283d87856136df90919063ffffffff16565b60405190808252806020026020018201604052801561287657816020015b612863613fc2565b81526020019060019003908161285b5790505b5092508691505b83821015612a665760018281548110151561289457fe5b9060005260206000209060020201905061010060405190810160405280838152602001826000015481526020018260010160009054906101000a900463ffffffff1663ffffffff1681526020018260010160049054906101000a900463ffffffff1663ffffffff1681526020018260010160089054906101000a900463ffffffff1663ffffffff16815260200182600101600c9054906101000a900463ffffffff1663ffffffff168152602001600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e95f2c7d84600001546040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b1580156129d657600080fd5b505af11580156129ea573d6000803e3d6000fd5b505050506040513d6020811015612a0057600080fd5b810190808051906020019092919050505081526020018260010160109054906101000a900460ff16612a33576000612a36565b60015b60ff1681525083888403815181101515612a4c57fe5b90602001906020020181905250818060010192505061287d565b8294505050505092915050565b60008060008060008060006001805490508863ffffffff16101515612b00576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f696e76616c69642070726f64756374496400000000000000000000000000000081525060200191505060405180910390fd5b60018863ffffffff16815481101515612b1557fe5b906000526020600020906002020196508660010160109054906101000a900460ff161515612bab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f70726f64756374206d75737420626520696e206163746976652073746174650081525060200191505060405180910390fd5b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166382f5e31b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166333a263e66040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015612c6f57600080fd5b505af1158015612c83573d6000803e3d6000fd5b505050506040513d6020811015612c9957600080fd5b8101908080519060200190929190505050346040518363ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180836000191660001916815260200182815260200192505050602060405180830381600087803b158015612d0c57600080fd5b505af1158015612d20573d6000803e3d6000fd5b505050506040513d6020811015612d3657600080fd5b81019080805190602001909291905050509550612d8b620f4240612d7d8960010160089054906101000a900463ffffffff1663ffffffff16896135ad90919063ffffffff16565b61364c90919063ffffffff16565b9450612d9787866134b1565b508094505086600001548410151515612e3e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001807f6c6f616e416d6f756e74206d757374206265203e3d206d696e4469736275727381526020017f6564416d6f756e7400000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b612e6b8760010160009054906101000a900463ffffffff1663ffffffff164261352390919063ffffffff16565b9250829150828264ffffffffff16141515612eee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6d61747572697479206f766572666c6f7700000000000000000000000000000081525060200191505060405180910390fd5b6001600260c0604051908101604052803481526020018881526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018b63ffffffff16815260200160006003811115612f3f57fe5b81526020018564ffffffffff1681525090806001815401808255809150509060018203906000526020600020906003020160009091929091909150600082015181600001556020820151816001015560408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160146101000a81548163ffffffff021916908363ffffffff16021790555060808201518160020160186101000a81548160ff0219169083600381111561302057fe5b021790555060a08201518160020160196101000a81548164ffffffffff021916908364ffffffffff1602179055505050039050600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819080600181540180825580915050906001820390600052602060002001600090919290919091505550600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631895687d33866040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b15801561318157600080fd5b505af1158015613195573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff167f1f9972ec35a86b6ea1c3884c02fda9d8d0c5c14089a133610fed51c481b7e208898334888a88604051808763ffffffff1663ffffffff1681526020018681526020018581526020018481526020018381526020018264ffffffffff1664ffffffffff168152602001965050505050505060405180910390a25050505050505050565b60028181548110151561324257fe5b90600052602060002090600302016000915090508060000154908060010154908060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060020160149054906101000a900463ffffffff16908060020160189054906101000a900460ff16908060020160199054906101000a900464ffffffffff16905086565b6000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060007f5065726d697373696f6e4772616e74657200000000000000000000000000000060001916815260200190815260200160002060009054906101000a900460ff1615156133e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260318152602001807f6d73672e73656e646572206d7573742068617665205065726d697373696f6e4781526020017f72616e746572207065726d697373696f6e00000000000000000000000000000081525060400191505060405180910390fd5b60016000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000836000191660001916815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff167fc65937e3dbcb9fb30f646815dd67a3dbd09ba17718cbcb54efbe3635f8e0a6fe8260405180826000191660001916815260200191505060405180910390a25050565b6000806134f6620f42406134e88660010160049054906101000a900463ffffffff1663ffffffff16866135ad90919063ffffffff16565b61364c90919063ffffffff16565b91508282116135175761351282846136df90919063ffffffff16565b61351a565b60005b90509250929050565b60008082840190508381101515156135a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f616464206f766572666c6f77000000000000000000000000000000000000000081525060200191505060405180910390fd5b8091505092915050565b600080828402905060008414806135ce57508284828115156135cb57fe5b04145b1515613642576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f6d756c206f766572666c6f77000000000000000000000000000000000000000081525060200191505060405180910390fd5b8091505092915050565b6000806000831115156136c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260088152602001807f646976206279203000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b82848115156136d257fe5b0490508091505092915050565b6000828211151515613759576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f73756220756e646572666c6f770000000000000000000000000000000000000081525060200191505060405180910390fd5b818303905092915050565b600080600080600280549050861015156137e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f696e76616c6964206c6f616e496400000000000000000000000000000000000081525060200191505060405180910390fd5b6002868154811015156137f557fe5b906000526020600020906003020193506000600381111561381257fe5b8460020160189054906101000a900460ff16600381111561382f57fe5b1415156138a4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f6c6f616e207374617465206d757374206265204f70656e00000000000000000081525060200191505060405180910390fd5b836001015485141515613945576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c8152602001807f72657061796d656e74416d6f756e74206d75737420626520657175616c20746f81526020017f20746f6b656e732073656e74000000000000000000000000000000000000000081525060400191505060405180910390fd5b8360020160199054906101000a900464ffffffffff1664ffffffffff1642111515156139ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001807f63757272656e742074696d65206d757374206265206561726c6965722074686181526020017f6e206d617475726974790000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60018460020160149054906101000a900463ffffffff1663ffffffff16815481101515613a2857fe5b90600052602060002090600202019250613a468385600101546134b1565b80925081935050506001600287815481101515613a5f57fe5b906000526020600020906003020160020160186101000a81548160ff02191690836003811115613a8b57fe5b02179055506000811115613d0857600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635fcf04556040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b158015613b5d57600080fd5b505af1158015613b71573d6000803e3d6000fd5b505050506040513d6020811015613b8757600080fd5b8101908080519060200190929190505050836040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b158015613c1e57600080fd5b505af1158015613c32573d6000803e3d6000fd5b505050506040513d6020811015613c4857600080fd5b810190808051906020019092919050505050600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342966c68836040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b158015613ceb57600080fd5b505af1158015613cff573d6000803e3d6000fd5b50505050613db2565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342966c68866040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b158015613d9957600080fd5b505af1158015613dad573d6000803e3d6000fd5b505050505b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634cae5f99836040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050600060405180830381600087803b158015613e4357600080fd5b505af1158015613e57573d6000803e3d6000fd5b505050508360020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc85600001549081150290604051600060405180830381858888f19350505050158015613ec9573d6000803e3d6000fd5b507f0bc2fda5eb321ed5f7471e814a5c00752523b3ba8fbfeb905e1b8707eefa16c5868560020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a1505050505050565b6000818310613f705781613f72565b825b905092915050565b61014060405190810160405280600a90602082028038833980820191505090505090565b61014060405190810160405280600a90602082028038833980820191505090505090565b610100604051908101604052806008906020820280388339808201915050905050905600a165627a7a7230582042deca639f0687c84e9ebaf8372f77d01c5167d434db4f969863bc69257a9db10029
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000de36a8773531406dcbeffdfd3c7b89fced7a9f84000000000000000000000000c994a2deb02543db1f48688438b9903c4b305ce300000000000000000000000027484afe9e6c332fb07f21fac82d442ebe1d22c30000000000000000000000004272db2eb82068e898588c3d6e4b5d55c3848793
-----Decoded View---------------
Arg [0] : permissionGranterContract (address): 0xde36a8773531406dCBefFdfd3C7b89fCed7A9F84
Arg [1] : _augmintToken (address): 0xc994a2dEb02543Db1f48688438b9903c4b305ce3
Arg [2] : _monetarySupervisor (address): 0x27484AFe9e6c332fB07F21Fac82d442EBe1D22c3
Arg [3] : _rates (address): 0x4272dB2EB82068E898588C3D6e4B5D55c3848793
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000de36a8773531406dcbeffdfd3c7b89fced7a9f84
Arg [1] : 000000000000000000000000c994a2deb02543db1f48688438b9903c4b305ce3
Arg [2] : 00000000000000000000000027484afe9e6c332fb07f21fac82d442ebe1d22c3
Arg [3] : 0000000000000000000000004272db2eb82068e898588c3d6e4b5d55c3848793
Swarm Source
bzzr://42deca639f0687c84e9ebaf8372f77d01c5167d434db4f969863bc69257a9db1
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.